Skip to content

Commit b29e4bb

Browse files
nmankmtezzele
authored andcommitted
working reconstructions with lag parameter
1 parent 0f260f2 commit b29e4bb

File tree

2 files changed

+61
-10
lines changed

2 files changed

+61
-10
lines changed

pydmd/dmdc.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,12 @@ class DMDc(DMDBase):
191191
equal than `svd_rank`. For the possible values please refer to the
192192
`svd_rank` parameter description above.
193193
:type svd_rank_omega: int or float
194+
:param lag: the time lag for the snapshots. Used in fit method to generate
195+
X and Y.
196+
:type lag: int
194197
"""
195198

196-
def __init__(self, svd_rank=0, tlsq_rank=0, opt=False, svd_rank_omega=-1, lag = 1):
199+
def __init__(self, svd_rank=0, tlsq_rank=0, opt=False, svd_rank_omega=-1, lag=1):
197200
# we're going to initialize Atilde when we know if B is known
198201
self._Atilde = None
199202
# remember the arguments for when we'll need them
@@ -203,14 +206,14 @@ def __init__(self, svd_rank=0, tlsq_rank=0, opt=False, svd_rank_omega=-1, lag =
203206
"tlsq_rank": tlsq_rank,
204207
}
205208

206-
self._lag = lag
207209
self._opt = opt
208210
self._exact = False
209211

210212
self._B = None
211213
self._snapshots_holder = None
212214
self._controlin = None
213215
self._basis = None
216+
self._lag = lag
214217

215218
self._modes_activation_bitmask_proxy = None
216219

@@ -256,7 +259,7 @@ def reconstructed_data(self, control_input=None):
256259
else self._controlin
257260
)
258261

259-
if controlin.shape[-1] != self.dynamics.shape[-1] - 1:
262+
if controlin.shape[-1] != self.dynamics.shape[-1] - self._lag:
260263
raise RuntimeError(
261264
"The number of control inputs and the number of snapshots to "
262265
"reconstruct has to be the same"
@@ -269,7 +272,10 @@ def reconstructed_data(self, control_input=None):
269272
[self.modes, np.diag(eigs), np.linalg.pinv(self.modes)]
270273
)
271274

272-
data = [self.snapshots[:, 0]]
275+
data = []
276+
for i in range(self._lag):
277+
data.append(self.snapshots[:, i])
278+
273279
expected_shape = data[0].shape
274280

275281
for i, u in enumerate(controlin.T):
@@ -299,13 +305,18 @@ def fit(self, X, I, B=None):
299305
:type B: numpy.ndarray or iterable
300306
"""
301307
self._reset()
308+
self._controlin = np.atleast_2d(np.asarray(I))
302309

303310
self._snapshots_holder = Snapshots(X)
304-
self._controlin = np.atleast_2d(np.asarray(I))
311+
n_samples = self.snapshots.shape[-1]
305312

313+
if self._lag < 1:
314+
raise ValueError(
315+
f"Time lag must be positive."
316+
)
317+
306318
X = self.snapshots[:, :-self._lag]
307319
Y = self.snapshots[:, self._lag:]
308-
n_samples = X.shape[1]+1
309320

310321
self._set_initial_time_dictionary(
311322
{"t0": 0, "tend": n_samples - 1, "dt": 1}

tests/test_dmdc.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,30 @@ def create_system_with_B():
1212
return {"snapshots": snapshots, "u": u, "B": B}
1313

1414

15-
def create_system_without_B(lag = 1):
15+
def create_system_without_B():
16+
n = 5 # dimension snapshots
17+
m = 15 # number snapshots
18+
A = scipy.linalg.helmert(n, True)
19+
B = np.random.rand(n, n) - 0.5
20+
x0 = np.array([0.25] * n)
21+
u = np.random.rand(n, m - 1) - 0.5
22+
snapshots = [x0]
23+
for i in range(m - 1):
24+
snapshots.append(A.dot(snapshots[i]) + B.dot(u[:, i]))
25+
snapshots = np.array(snapshots).T
26+
return {"snapshots": snapshots, "u": u, "B": B, "A": A}
27+
28+
29+
def create_system_without_B_lag(lag = 1):
1630
n = 5 # dimension snapshots
1731
m = 15 # number snapshots
1832
A = scipy.linalg.helmert(n, True)
1933
B = np.random.rand(n, n) - 0.5
2034
snapshots = []
21-
for i in range(lag):
35+
for _ in range(lag):
2236
snapshots.append(np.array([0.25] * n))
23-
u = np.random.rand(n, m - lag) - 0.5
24-
for i in range(m - lag):
37+
u = np.random.rand(n, m-lag) - 0.5
38+
for i in range(m-lag):
2539
snapshots.append(A.dot(snapshots[i]) + B.dot(u[:, i]))
2640
snapshots = np.array(snapshots).T
2741
return {"snapshots": snapshots, "u": u, "B": B, "A": A}
@@ -42,13 +56,29 @@ def test_eigs_b_unknown():
4256
assert dmdc.eigs.shape[0] == 3
4357

4458

59+
def test_eigs_b_unknown_lag():
60+
lag = 3
61+
system = create_system_without_B_lag(lag=lag)
62+
dmdc = DMDc(svd_rank=3, opt=False, svd_rank_omega=4, lag=lag)
63+
dmdc.fit(system["snapshots"], system["u"])
64+
assert dmdc.eigs.shape[0] == 3
65+
66+
4567
def test_modes_b_unknown():
4668
system = create_system_without_B()
4769
dmdc = DMDc(svd_rank=3, opt=False, svd_rank_omega=4)
4870
dmdc.fit(system["snapshots"], system["u"])
4971
assert dmdc.modes.shape[1] == 3
5072

5173

74+
def test_modes_b_unknown_lag():
75+
lag = 3
76+
system = create_system_without_B_lag(lag=lag)
77+
dmdc = DMDc(svd_rank=3, opt=False, svd_rank_omega=4, lag=lag)
78+
dmdc.fit(system["snapshots"], system["u"])
79+
assert dmdc.modes.shape[1] == 3
80+
81+
5282
def test_reconstruct_b_known():
5383
system = create_system_with_B()
5484
dmdc = DMDc(svd_rank=-1)
@@ -74,6 +104,16 @@ def test_reconstruct_b_unknown():
74104
)
75105

76106

107+
def test_reconstruct_b_unknown_lag():
108+
lag = 3
109+
system = create_system_without_B_lag(lag = lag)
110+
dmdc = DMDc(svd_rank=-1, opt=True, lag=lag)
111+
dmdc.fit(system["snapshots"], system["u"])
112+
np.testing.assert_array_almost_equal(
113+
dmdc.reconstructed_data(), system["snapshots"], decimal=6
114+
)
115+
116+
77117
def test_atilde_b_unknown():
78118
system = create_system_without_B()
79119
dmdc = DMDc(svd_rank=-1, opt=True)

0 commit comments

Comments
 (0)