Skip to content

Commit 763573b

Browse files
committed
Fixed conjugate_pair code
1 parent 90b1b55 commit 763573b

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

pydmd/bopdmd.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -290,23 +290,29 @@ def _push_eigenvalues(self, eigenvalues):
290290
if "conjugate_pairs" in self._eig_constraints:
291291
num_eigs = len(eigenvalues)
292292
new_eigs = np.empty(num_eigs, dtype="complex")
293+
unassigned_inds = set(np.arange(num_eigs))
293294
# If given an odd number of eigenvalues, find the eigenvalue with
294295
# the smallest imaginary part and take it to be a real eigenvalue.
295296
if num_eigs % 2 == 1:
296-
ind_single = np.argmin(np.abs(eigenvalues.imag))
297-
new_eigs[ind_single] = eigenvalues[ind_single].real
298-
eig_pair_inds = np.delete(np.arange(num_eigs), ind_single)[::2]
299-
else:
300-
eig_pair_inds = np.arange(0, num_eigs, 2)
301-
# Note: a consequence of the OptDMD variable projection process is
302-
# that complex conjugate pairs naturally appear together in the
303-
# computed eigenvalue vectors. We thus take advantage of this...
304-
for i in eig_pair_inds:
305-
eig_pair = eigenvalues[i : i + 2]
306-
real_comp = np.mean(eig_pair.real)
307-
imag_comp = np.mean(np.abs(eig_pair.imag))
308-
new_eigs[i] = real_comp + 1j * imag_comp
309-
new_eigs[i + 1] = real_comp - 1j * imag_comp
297+
ind_0 = np.argmin(np.abs(eigenvalues.imag))
298+
new_eigs[ind_0] = eigenvalues[ind_0].real
299+
unassigned_inds.remove(ind_0)
300+
# Assign complex conjugate pairs until all eigenvalues are paired.
301+
while len(unassigned_inds) != 0:
302+
# Randomly grab the next unassigned eigenvalue.
303+
ind_1 = unassigned_inds.pop()
304+
eig_1 = eigenvalues[ind_1]
305+
# Get the index of the eigenvalue that's closest to being the
306+
# complex conjugate of the randomly selected eigenvalue.
307+
ind_2 = np.argmin(np.abs(eigenvalues - np.conj(eig_1)))
308+
eig_2 = eigenvalues[ind_2]
309+
unassigned_inds.remove(ind_2)
310+
# Average their real and imaginary components together.
311+
a = 0.5 * (eig_1.real + eig_2.real)
312+
b = 0.5 * (abs(eig_1.imag) + abs(eig_2.imag))
313+
new_eigs[ind_1] = a + 1j * (b * np.sign(eig_1.imag))
314+
new_eigs[ind_2] = a + 1j * (b * np.sign(eig_2.imag))
315+
# ind_1 and ind_2 have now been paired.
310316

311317
eigenvalues = np.copy(new_eigs)
312318

0 commit comments

Comments
 (0)