modulo-vki 2.0.6__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modulo_vki/__init__.py +0 -22
- modulo_vki/core/__init__.py +9 -9
- modulo_vki/core/_dft.py +132 -61
- modulo_vki/core/_dmd_s.py +81 -72
- modulo_vki/core/_k_matrix.py +209 -81
- modulo_vki/core/_mpod_space.py +180 -180
- modulo_vki/core/_mpod_time.py +175 -154
- modulo_vki/core/_pod_space.py +185 -184
- modulo_vki/core/_pod_time.py +49 -48
- modulo_vki/core/_spod_s.py +101 -101
- modulo_vki/core/_spod_t.py +104 -104
- modulo_vki/core/spatial_structures.py +367 -0
- modulo_vki/core/temporal_structures.py +241 -0
- modulo_vki/core/utils.py +474 -0
- modulo_vki/modulo.py +897 -828
- modulo_vki/modulo_old.py +1368 -0
- modulo_vki/utils/__init__.py +4 -4
- modulo_vki/utils/_plots.py +51 -51
- modulo_vki/utils/_utils.py +358 -341
- modulo_vki/utils/others.py +461 -452
- modulo_vki/utils/read_db.py +339 -339
- {modulo_vki-2.0.6.dist-info → modulo_vki-2.1.0.dist-info}/METADATA +397 -304
- modulo_vki-2.1.0.dist-info/RECORD +26 -0
- {modulo_vki-2.0.6.dist-info → modulo_vki-2.1.0.dist-info}/WHEEL +1 -1
- {modulo_vki-2.0.6.dist-info → modulo_vki-2.1.0.dist-info/licenses}/LICENSE +21 -21
- modulo_vki-2.0.6.dist-info/RECORD +0 -22
- {modulo_vki-2.0.6.dist-info → modulo_vki-2.1.0.dist-info}/top_level.txt +0 -0
modulo_vki/__init__.py
CHANGED
|
@@ -1,23 +1 @@
|
|
|
1
|
-
|
|
2
|
-
#from ._version import get_versions
|
|
3
|
-
#__version__ = get_versions()['version']
|
|
4
|
-
#del get_versions
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# from .utils.read_db import *
|
|
8
|
-
# from .utils._utils import *
|
|
9
|
-
# from .utils._plots import *
|
|
10
|
-
# from .utils.others import *
|
|
11
|
-
|
|
12
|
-
# from .core._k_matrix import *
|
|
13
|
-
# from .core._dft import *
|
|
14
|
-
# from .core._dmd_s import *
|
|
15
|
-
# from .core._k_matrix import *
|
|
16
|
-
# from .core._mpod_time import *
|
|
17
|
-
# from .core._mpod_space import *
|
|
18
|
-
# from .core._pod_time import *
|
|
19
|
-
# from .core._pod_space import *
|
|
20
|
-
# from .core._spod_s import *
|
|
21
|
-
# from .core._spod_t import *
|
|
22
|
-
|
|
23
1
|
from modulo_vki.modulo import ModuloVKI
|
modulo_vki/core/__init__.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from ._dft import *
|
|
2
|
-
from ._dmd_s import *
|
|
3
|
-
from ._k_matrix import *
|
|
4
|
-
from ._mpod_space import *
|
|
5
|
-
from ._mpod_time import *
|
|
6
|
-
from ._pod_space import *
|
|
7
|
-
from ._pod_time import *
|
|
8
|
-
from ._spod_s import *
|
|
9
|
-
from ._spod_t import *
|
|
1
|
+
from ._dft import *
|
|
2
|
+
from ._dmd_s import *
|
|
3
|
+
from ._k_matrix import *
|
|
4
|
+
from ._mpod_space import *
|
|
5
|
+
from ._mpod_time import *
|
|
6
|
+
from ._pod_space import *
|
|
7
|
+
from ._pod_time import *
|
|
8
|
+
from ._spod_s import *
|
|
9
|
+
from ._spod_t import *
|
modulo_vki/core/_dft.py
CHANGED
|
@@ -1,61 +1,132 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from tqdm import tqdm
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def dft_fit(N_T, F_S, D, FOLDER_OUT, SAVE_DFT=False):
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from tqdm import tqdm
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def dft_fit(N_T, F_S, D, FOLDER_OUT, SAVE_DFT=False):
|
|
8
|
+
"""
|
|
9
|
+
Computes the Discrete Fourier Transform (DFT) from the provided dataset.
|
|
10
|
+
|
|
11
|
+
Note
|
|
12
|
+
----
|
|
13
|
+
Memory saving feature is currently not supported by this function.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
N_T : int
|
|
18
|
+
Number of temporal snapshots.
|
|
19
|
+
|
|
20
|
+
F_S : float
|
|
21
|
+
Sampling frequency in Hz.
|
|
22
|
+
|
|
23
|
+
D : np.ndarray
|
|
24
|
+
Snapshot matrix.
|
|
25
|
+
|
|
26
|
+
FOLDER_OUT : str
|
|
27
|
+
Directory path where results are saved if `SAVE_DFT` is True.
|
|
28
|
+
|
|
29
|
+
SAVE_DFT : bool, default=False
|
|
30
|
+
If True, computed results are saved to disk and released from memory.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
Sorted_Freqs : np.ndarray
|
|
35
|
+
Frequency bins in Hz, sorted in ascending order.
|
|
36
|
+
|
|
37
|
+
Phi_F : np.ndarray
|
|
38
|
+
Complex spatial structures corresponding to each frequency mode.
|
|
39
|
+
|
|
40
|
+
SIGMA_F : np.ndarray
|
|
41
|
+
Real amplitudes associated with each frequency mode.
|
|
42
|
+
"""
|
|
43
|
+
n_t = int(N_T)
|
|
44
|
+
Freqs = np.fft.fftfreq(n_t) * F_S # Compute the frequency bins
|
|
45
|
+
# PSI_F = np.conj(np.fft.fft(np.eye(n_t)) / np.sqrt(n_t)) # Prepare the Fourier Matrix.
|
|
46
|
+
|
|
47
|
+
# Method 1 (didactic!)
|
|
48
|
+
# PHI_SIGMA = np.dot(D, np.conj(PSI_F)) # This is PHI * SIGMA
|
|
49
|
+
|
|
50
|
+
# Method 2
|
|
51
|
+
PHI_SIGMA = (np.fft.fft(D, n_t, 1)) / (n_t ** 0.5)
|
|
52
|
+
|
|
53
|
+
PHI_F = np.zeros((D.shape[0], n_t), dtype=complex) # Initialize the PHI_F MATRIX
|
|
54
|
+
SIGMA_F = np.zeros(n_t) # Initialize the SIGMA_F MATRIX
|
|
55
|
+
|
|
56
|
+
# Now we proceed with the normalization. This is also intense so we time it
|
|
57
|
+
for r in tqdm(range(0, n_t)): # Loop over the PHI_SIGMA to normalize
|
|
58
|
+
# MEX = 'Proj ' + str(r + 1) + ' /' + str(n_t)
|
|
59
|
+
# print(MEX)
|
|
60
|
+
SIGMA_F[r] = abs(np.vdot(PHI_SIGMA[:, r], PHI_SIGMA[:, r])) ** 0.5
|
|
61
|
+
PHI_F[:, r] = PHI_SIGMA[:, r] / SIGMA_F[r]
|
|
62
|
+
|
|
63
|
+
Indices = np.flipud(np.argsort(SIGMA_F)) # find indices for sorting in decreasing order
|
|
64
|
+
Sorted_Sigmas = SIGMA_F[Indices] # Sort all the sigmas
|
|
65
|
+
Sorted_Freqs = Freqs[Indices] # Sort all the frequencies accordingly.
|
|
66
|
+
Phi_F = PHI_F[:, Indices] # Sorted Spatial Structures Matrix
|
|
67
|
+
SIGMA_F = Sorted_Sigmas # Sorted Amplitude Matrix (vector)
|
|
68
|
+
|
|
69
|
+
if SAVE_DFT:
|
|
70
|
+
os.makedirs(FOLDER_OUT + 'DFT', exist_ok=True)
|
|
71
|
+
np.savez(FOLDER_OUT + 'DFT/dft_fitted', Freqs=Sorted_Freqs, Phis=Phi_F, Sigmas=SIGMA_F)
|
|
72
|
+
|
|
73
|
+
return Sorted_Freqs, Phi_F, SIGMA_F
|
|
74
|
+
|
|
75
|
+
def dft(N_T, F_S, D, FOLDER_OUT, SAVE_DFT=False):
|
|
76
|
+
"""
|
|
77
|
+
Computes the Discrete Fourier Transform (DFT) from the provided dataset.
|
|
78
|
+
|
|
79
|
+
Note
|
|
80
|
+
----
|
|
81
|
+
Memory saving feature is currently not supported by this function.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
N_T : int
|
|
86
|
+
Number of temporal snapshots.
|
|
87
|
+
|
|
88
|
+
F_S : float
|
|
89
|
+
Sampling frequency in Hz.
|
|
90
|
+
|
|
91
|
+
D : np.ndarray
|
|
92
|
+
Snapshot matrix.
|
|
93
|
+
|
|
94
|
+
FOLDER_OUT : str
|
|
95
|
+
Directory path where results are saved if `SAVE_DFT` is True.
|
|
96
|
+
|
|
97
|
+
SAVE_DFT : bool, default=False
|
|
98
|
+
If True, computed results are saved to disk and released from memory.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
Phi_F : np.ndarray
|
|
103
|
+
Complex spatial structures corresponding to each frequency mode.
|
|
104
|
+
|
|
105
|
+
Sorted_Freqs : np.ndarray
|
|
106
|
+
Frequency bins in Hz, sorted in ascending order.
|
|
107
|
+
|
|
108
|
+
SIGMA_F : np.ndarray
|
|
109
|
+
Real amplitudes associated with each frequency mode.
|
|
110
|
+
"""
|
|
111
|
+
n_t = int(N_T)
|
|
112
|
+
Freqs = np.fft.fftfreq(n_t) * F_S # Compute the frequency bins
|
|
113
|
+
|
|
114
|
+
# FFT along the snapshot axis
|
|
115
|
+
PHI_SIGMA = np.fft.fft(D, axis=1) / np.sqrt(n_t)
|
|
116
|
+
sigma_F = np.linalg.norm(PHI_SIGMA, axis=0) # Compute the norm of each column
|
|
117
|
+
|
|
118
|
+
# make phi_F orthonormal
|
|
119
|
+
Phi_F = PHI_SIGMA / sigma_F
|
|
120
|
+
|
|
121
|
+
# Sort
|
|
122
|
+
Indices = np.flipud(np.argsort(sigma_F)) # find indices for sorting in decreasing order
|
|
123
|
+
Sorted_Sigmas = sigma_F[Indices] # Sort all the sigmas
|
|
124
|
+
Sorted_Freqs = Freqs[Indices] # Sort all the frequencies accordingly.
|
|
125
|
+
Phi_F = Phi_F[:, Indices] # Sorted Spatial Structures Matrix
|
|
126
|
+
sigma_F = Sorted_Sigmas # Sorted Amplitude Matrix (vector)
|
|
127
|
+
|
|
128
|
+
if SAVE_DFT:
|
|
129
|
+
os.makedirs(FOLDER_OUT + 'DFT', exist_ok=True)
|
|
130
|
+
np.savez(FOLDER_OUT + 'DFT/dft_fitted', Freqs=Sorted_Freqs, Phis=Phi_F, Sigmas=SIGMA_F)
|
|
131
|
+
|
|
132
|
+
return Phi_F, Sorted_Freqs, sigma_F
|
modulo_vki/core/_dmd_s.py
CHANGED
|
@@ -1,72 +1,81 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import numpy as np
|
|
3
|
-
from numpy import linalg as LA
|
|
4
|
-
from ..utils._utils import switch_svds
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def dmd_s(D_1, D_2, n_Modes, F_S,
|
|
8
|
-
SAVE_T_DMD=False,
|
|
9
|
-
FOLDER_OUT='./',
|
|
10
|
-
svd_solver: str = 'svd_sklearn_truncated'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from numpy import linalg as LA
|
|
4
|
+
from ..utils._utils import switch_svds
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def dmd_s(D_1, D_2, n_Modes, F_S,
|
|
8
|
+
SAVE_T_DMD: bool = False,
|
|
9
|
+
FOLDER_OUT: str = './',
|
|
10
|
+
svd_solver: str = 'svd_sklearn_truncated',
|
|
11
|
+
verbose=True):
|
|
12
|
+
"""
|
|
13
|
+
Compute the Dynamic Mode Decomposition (DMD) using the PIP algorithm.
|
|
14
|
+
|
|
15
|
+
This implementation follows the Penland & Sardeshmukh PIP approach and
|
|
16
|
+
recovers the same modes as the exact DMD of Tu et al. (2014).
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
D_1 : ndarray, shape (n_features, n_time-1)
|
|
21
|
+
First snapshot matrix (columns 0 to n_t-2 of the full data).
|
|
22
|
+
D_2 : ndarray, shape (n_features, n_time-1)
|
|
23
|
+
Second snapshot matrix (columns 1 to n_t-1 of the full data).
|
|
24
|
+
n_Modes : int
|
|
25
|
+
Number of DMD modes to compute.
|
|
26
|
+
F_S : float
|
|
27
|
+
Sampling frequency in Hz.
|
|
28
|
+
SAVE_T_DMD : bool, optional
|
|
29
|
+
If True, save time‐series DMD results to disk. Default is False.
|
|
30
|
+
FOLDER_OUT : str, optional
|
|
31
|
+
Directory in which to save outputs when SAVE_T_DMD is True. Default is './'.
|
|
32
|
+
svd_solver : str, optional
|
|
33
|
+
SVD solver to use for the low‐rank approximation. Default is
|
|
34
|
+
'svd_sklearn_truncated'.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
Phi_D : ndarray, shape (n_features, n_Modes)
|
|
39
|
+
Complex spatial DMD modes.
|
|
40
|
+
Lambda_D : ndarray, shape (n_Modes,)
|
|
41
|
+
Complex eigenvalues of the reduced propagator.
|
|
42
|
+
freqs : ndarray, shape (n_Modes,)
|
|
43
|
+
Frequencies (Hz) associated with each DMD mode.
|
|
44
|
+
a0s : ndarray, shape (n_Modes,)
|
|
45
|
+
Initial amplitudes (coefficients) of the DMD modes.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
Phi_P, Psi_P, Sigma_P = switch_svds(D_1, n_Modes, svd_solver)
|
|
49
|
+
if verbose:
|
|
50
|
+
print('SVD of D1 rdy')
|
|
51
|
+
Sigma_inv = np.diag(1 / Sigma_P)
|
|
52
|
+
dt = 1 / F_S
|
|
53
|
+
# %% Step 3: Compute approximated propagator
|
|
54
|
+
P_A = LA.multi_dot([np.transpose(Phi_P), D_2, Psi_P, Sigma_inv])
|
|
55
|
+
if verbose:
|
|
56
|
+
print('reduced propagator rdy')
|
|
57
|
+
|
|
58
|
+
# %% Step 4: Compute eigenvalues of the system
|
|
59
|
+
Lambda, Q = LA.eig(P_A) # not necessarily symmetric def pos! Avoid eigsh, eigh
|
|
60
|
+
freqs = np.imag(np.log(Lambda)) / (2 * np.pi * dt)
|
|
61
|
+
if verbose:
|
|
62
|
+
print(' lambdas and freqs rdy')
|
|
63
|
+
|
|
64
|
+
# %% Step 5: Spatial structures of the DMD in the PIP style
|
|
65
|
+
Phi_D = LA.multi_dot([D_2, Psi_P, Sigma_inv, Q])
|
|
66
|
+
if verbose:
|
|
67
|
+
print('Phi_D rdy')
|
|
68
|
+
|
|
69
|
+
# %% Step 6: Compute the initial coefficients
|
|
70
|
+
# a0s=LA.lstsq(Phi_D, D_1[:,0],rcond=None)
|
|
71
|
+
a0s = LA.pinv(Phi_D).dot(D_1[:, 0])
|
|
72
|
+
if verbose:
|
|
73
|
+
print('Sigma_D rdy')
|
|
74
|
+
|
|
75
|
+
if SAVE_T_DMD:
|
|
76
|
+
os.makedirs(FOLDER_OUT + "/DMD/", exist_ok=True)
|
|
77
|
+
print("Saving DMD results")
|
|
78
|
+
np.savez(FOLDER_OUT + '/DMD/dmd_decomposition',
|
|
79
|
+
Phi_D=Phi_D, Lambda=Lambda, freqs=freqs, a0s=a0s)
|
|
80
|
+
|
|
81
|
+
return Phi_D, Lambda, freqs, a0s
|