Data-driven analysis¶
Dynamic mode decomposition and spectral proper orthogonal decomposition of snapshots, in the inner product of the physics rather than that of the array.
Snapshots are vectors of values on a grid. Every decomposition takes a DataInnerProduct, built
from the quadrature weights of the grid and per-component weights, so that modes are orthogonal in
the energy norm of the flow. The example uses snapshots of the linear Ginzburg–Landau equation.
import numpy as np
import scipy.linalg as sla
from conatus.diagnostics import Chebyshev, Grid
from conatus.expert import DataInnerProduct, Y, linear_ginzburg_landau, state_space
small = linear_ginzburg_landau(nu=2 + 0.4j, gamma=1 - 1j, mu=-0.2 - 0.01 * Y**2 / 2,
bounds=(-20, 20))
ss = state_space(small.discretize(32), infinite_tol=1e-10)
grid = Grid([Chebyshev(-20.0, 20.0, 64)]) # snapshots on 64 Gauss nodes
E = np.polynomial.chebyshev.chebvander(grid.axes[0].nodes() / 20.0, 31) @ ss.to_state
ip = DataInnerProduct.from_grid(grid, components=["q"], weights={"q": 1.0})
Dynamic mode decomposition¶
from conatus.expert import dmd
lam, V = np.linalg.eig(ss.A)
lead = np.argsort(-lam.real)[:4]
q0 = V[:, lead] @ np.array([1.0, 0.5j, 0.3, 0.2 - 0.1j])
Phi = sla.expm(ss.A * 0.5)
X = E @ np.stack([np.linalg.matrix_power(Phi, j) @ q0 for j in range(40)], axis=1)
r = dmd(X, dt=0.5, rank=4, inner_product=ip, amplitudes="optimal")
print(r.explain())
rank and amplitudes are required. On snapshots of a linear system in the span of a few modes,
DMD returns their eigenvalues to rounding. edmd and its dictionaries (monomials, rbf) extend it
to observables of the state.
Spectral POD¶
The Welch segmentation (nfft, noverlap, window), the treatment of the mean and one- or
two-sided spectra are all arguments.
See also: tutorial 13. Where a global mode is born, and what the data say about it (Towne et al. 2018); dmd, spod, pod, DataInnerProduct.