Computing decompositions

MODULO allows for computing POD, SPODs, DFT, DMD and mPOD.

MODULO Initialization

modulo_vki.__init__(*args, **kwargs)

Initialize self. See help(type(self)) for accurate signature.

Then, the key functions for the available decompositions are:

POD via SVD

modulo_vki.modulo.ModuloVKI.compute_POD_svd(self, SAVE_T_POD: bool = False)

This method computes the Proper Orthogonal Decomposition (POD) of a dataset using the SVD decomposition. The svd solver is defined by ‘svd_solver’. Note that in this case, the memory saving option is of no help, since the SVD must be performed over the entire dataset.

https://youtu.be/8fhupzhAR_M

Return Psi_P:

np.array POD Psis

Return Sigma_P:
np.array

POD Sigmas. If needed, Lambdas can be easily computed recalling that: Sigma_P = np.sqrt(Lambda_P)

return Phi_P:

np.array POD Phis

POD via matrix K

modulo_vki.modulo.ModuloVKI.compute_POD_K(self, SAVE_T_POD: bool = False)

This method computes the Proper Orthogonal Decomposition (POD) of a dataset using the snapshot approach, i.e. working on the temporal correlation matrix. The eig solver for K is defined in ‘eig_solver’ The theoretical background of the POD is briefly recalled here:

https://youtu.be/8fhupzhAR_M

Return Psi_P:

np.array POD Psis

Return Sigma_P:

np.array POD Sigmas. If needed, Lambdas can be easily computed recalling that: Sigma_P = np.sqrt(Lambda_P)

Return Phi_P:

np.array POD Phis

DFT

modulo_vki.modulo.ModuloVKI.compute_DFT(self, F_S, SAVE_DFT=False)

This method computes the Discrete Fourier Transform of your data.

Check out this tutorial: https://www.youtube.com/watch?v=8fhupzhAR_M&list=PLEJZLD0-4PeKW6Ze984q08bNz28GTntkR&index=2

Parameters:
  • F_S – float, Sampling Frequency [Hz]

  • SAVE_DFT – bool, If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp

Returns:

Sorted_Freqs: np.array, Sorted Frequencies

Return Phi_F:

np.array, DFT Phis

Return Sigma_F:

np.array, DFT Sigmas

SPOD_s

modulo_vki.modulo.ModuloVKI.compute_SPOD_s(self, F_S, N_O=100, f_c=0.3, n_Modes=10, SAVE_SPOD=True)

This method computes the Spectral POD of your data. This is the one by Sieber et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition/DCD8A6EDEFD56F5A9715DBAD38BD461A)

Parameters:
  • F_S – float, Sampling Frequency [Hz]

  • N_o – float, Semi-Order of the diagonal filter. Note that the filter order will be 2 N_o +1 (to make sure it is odd)

  • f_c – float, cut-off frequency of the diagonal filter

  • n_Modes – float, number of modes to be computed

  • SAVE_SPOD – bool, If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp

Return Psi_P:

np.array SPOD Psis

Return Sigma_P:

np.array SPOD Sigmas.

Return Phi_P:

np.array SPOD Phis

SPOD_t

modulo_vki.modulo.ModuloVKI.compute_SPOD_t(self, F_S, L_B=500, O_B=250, n_Modes=10, SAVE_SPOD=True)

This method computes the Spectral POD of your data. This is the one by Towne et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition-and-its-relationship-to-dynamic-mode-decomposition-and-resolvent-analysis/EC2A6DF76490A0B9EB208CC2CA037717)

Parameters:
  • F_S – float, Sampling Frequency [Hz]

  • L_B – float, lenght of the chunks

  • O_B – float, Overlapping between blocks in the chunk

  • n_Modes – float, number of modes to be computed for each frequency

  • SAVE_SPOD – bool, If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp

Return Psi_P_hat:

np.array Spectra of the SPOD Modes

Return Sigma_P:

np.array Amplitudes of the SPOD Modes.

Return Phi_P:

np.array SPOD Phis

Return freq:

float frequency bins for the Spectral POD

DMD (or PIP)

modulo_vki.modulo.ModuloVKI.compute_DMD_PIP(self, SAVE_T_DMD: bool = True, F_S=1)

This method computes the Dynamic Mode Decomposition of the data using the algorithm in https://arxiv.org/abs/1312.0041, which is basically the same as the PIP algorithm proposed in https://www.sciencedirect.com/science/article/abs/pii/0167278996001248 See v1 of this paper https://arxiv.org/abs/2001.01971 for more details (yes, reviewers did ask to omit this detail in v2).

Return Phi_D:

np.array DMD Phis. As for the DFT, these are complex.

Return Lambda_D:

np.array DMD Eigenvalues (of the reduced propagator). These are complex.

Return freqs:

np.array Frequencies (in Hz, associated to the DMD modes)

Return a0s:

np.array Initial Coefficients of the Modes

mPOD

modulo_vki.modulo.ModuloVKI.compute_mPOD(self, Nf, Ex, F_V, Keep, SAT, boundaries, MODE, dt, SAVE=False)

This function computes the temporal structures of each scale in the mPOD, as in step 4 of the algorithm ref: Multi-Scale Proper Orthogonal Decomposition of Complex Fluid Flows - M. A. Mendez et al.

Parameters:
  • K – np.array Temporal correlation matrix

  • Nf – np.array Order of the FIR filters that are used to isolate each of the scales

  • Ex – int Extension at the boundaries of K to impose the boundary conditions (see boundaries) It must be at least as Nf.

  • F_V – np.array Frequency splitting vector, containing the frequencies of each scale (see article). If the time axis is in seconds, these frequencies are in Hz.

  • Keep – np.array Scale keep

  • boundaries – str -> {‘nearest’, ‘reflect’, ‘wrap’ or ‘extrap’} Define the boundary conditions for the filtering process, in order to avoid edge effects. The available boundary conditions are the classic ones implemented for image processing: nearest’, ‘reflect’, ‘wrap’ or ‘extrap’. See also https://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html

  • MODE – str -> {‘reduced’, ‘complete’, ‘r’, ‘raw’} A QR factorization is used to enforce the orthonormality of the mPOD basis, to compensate for the non-ideal frequency response of the filters. The option MODE from np.linalg.qr carries out this operation.

  • SAT – Maximum number of modes per scale. Only used for mPOD (max number of modes per scale)

  • dt – float temporal step

Return Phi_M:

np.array mPOD Phis (Matrix of spatial structures)

Return Psi_M:

np.array mPOD Psis (Matrix of temporal structures)

Return Sigma_M:

np.array mPOD Sigmas (vector of amplitudes, i.e. the diagonal of Sigma_M

kPOD

modulo_vki.modulo.ModuloVKI.compute_kPOD(self, M_DIST=[1, 10], k_m=0.1, cent=True, n_Modes=10, alpha=1e-06, metric='rbf', K_out=False)

This function implements the kernel PCA as described in the VKI course https://www.vki.ac.be/index.php/events-ls/events/eventdetail/552/-/online-on-site-hands-on-machine-learning-for-fluid-dynamics-2023

The computation of the kernel function is carried out as in https://arxiv.org/pdf/2208.07746.pdf.

Parameters:
  • M_DIST – array, position of the two snapshots that will be considered to estimate the minimal k. They should be the most different ones.

  • k_m – float, minimum value for the kernelized correlation

  • alpha – float regularization for K_zeta

  • cent – bool, if True, the matrix K is centered. Else it is not

  • n_Modes – float, number of modes to be computed

  • metric – string, This identifies the metric for the kernel matrix. It is a wrapper to ‘pairwise_kernels’ from sklearn.metrics.pairwise Note that different metrics would need different set of parameters. For the moment, only rbf was tested; use any other option at your peril !

  • K_out – bool, If true, the matrix K is also exported as a fourth output.

Return Psi_xi:

np.array kPOD’s Psis

Return Sigma_xi:

np.array kPOD’s Sigmas.

Return Phi_xi:

np.array kPOD’s Phis

Return K_zeta:

np.array Kernel Function from which the decomposition is computed. (exported only if K_out=True)