modulo-vki 2.0.5__py3-none-any.whl → 2.0.6__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 +22 -22
- modulo_vki/core/__init__.py +9 -9
- modulo_vki/core/_dft.py +61 -61
- modulo_vki/core/_dmd_s.py +72 -72
- modulo_vki/core/_k_matrix.py +81 -81
- modulo_vki/core/_mpod_space.py +180 -180
- modulo_vki/core/_mpod_time.py +154 -154
- modulo_vki/core/_pod_space.py +184 -184
- modulo_vki/core/_pod_time.py +48 -48
- modulo_vki/core/_spod_s.py +101 -101
- modulo_vki/core/_spod_t.py +104 -104
- modulo_vki/modulo.py +828 -828
- modulo_vki/utils/__init__.py +4 -4
- modulo_vki/utils/_plots.py +51 -51
- modulo_vki/utils/_utils.py +341 -339
- modulo_vki/utils/others.py +452 -449
- modulo_vki/utils/read_db.py +339 -339
- {modulo_vki-2.0.5.dist-info → modulo_vki-2.0.6.dist-info}/LICENSE +21 -21
- modulo_vki-2.0.6.dist-info/METADATA +304 -0
- modulo_vki-2.0.6.dist-info/RECORD +22 -0
- {modulo_vki-2.0.5.dist-info → modulo_vki-2.0.6.dist-info}/WHEEL +1 -1
- modulo_vki-2.0.5.dist-info/METADATA +0 -96
- modulo_vki-2.0.5.dist-info/RECORD +0 -22
- {modulo_vki-2.0.5.dist-info → modulo_vki-2.0.6.dist-info}/top_level.txt +0 -0
modulo_vki/core/_spod_s.py
CHANGED
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from scipy import signal
|
|
3
|
-
from scipy.signal import firwin
|
|
4
|
-
from ._pod_time import Temporal_basis_POD
|
|
5
|
-
from ._pod_space import Spatial_basis_POD
|
|
6
|
-
|
|
7
|
-
def compute_SPOD_s(D, K, F_S, n_s, n_t,N_o=100, f_c=0.3,n_Modes=10, SAVE_SPOD=True,
|
|
8
|
-
FOLDER_OUT='./', MEMORY_SAVING=False, N_PARTITIONS=1):
|
|
9
|
-
"""
|
|
10
|
-
This method computes the Spectral POD of your data.
|
|
11
|
-
This is the one by Sieber
|
|
12
|
-
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition/DCD8A6EDEFD56F5A9715DBAD38BD461A)
|
|
13
|
-
|
|
14
|
-
:param F_S: float,
|
|
15
|
-
Sampling Frequency [Hz]
|
|
16
|
-
:param N_o: float,
|
|
17
|
-
Semi-Order of the diagonal filter.
|
|
18
|
-
Note that the filter order will be 2 N_o +1 (to make sure it is odd)
|
|
19
|
-
:param f_c: float,
|
|
20
|
-
cut-off frequency of the diagonal filter
|
|
21
|
-
:param n_Modes: float,
|
|
22
|
-
number of modes to be computed
|
|
23
|
-
:param SAVE_SPOD: bool,
|
|
24
|
-
If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp
|
|
25
|
-
:param FOLDER_OUT: string
|
|
26
|
-
Define where the out will be stored (ignored if SAVE_POD=False)
|
|
27
|
-
:param MEMORY SAVING: bool
|
|
28
|
-
Define if memory saving is active or not (reduntant; to be improved)
|
|
29
|
-
Currently left for compatibility with the rest of MODULO.
|
|
30
|
-
:param N_PARTITIONS: int
|
|
31
|
-
number of partitions (if memory saving = False, it should be 1).
|
|
32
|
-
(reduntant; to be improved)
|
|
33
|
-
Currently left for compatibility with the rest of MODULO.
|
|
34
|
-
:return Psi_P: np.array
|
|
35
|
-
SPOD Psis
|
|
36
|
-
:return Sigma_P: np.array
|
|
37
|
-
SPOD Sigmas.
|
|
38
|
-
:return Phi_P: np.array
|
|
39
|
-
SPOD Phis
|
|
40
|
-
"""
|
|
41
|
-
# if self.D is None:
|
|
42
|
-
# D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
43
|
-
# SAVE_SPOD = True
|
|
44
|
-
# # TODO : Lorenzo check this stuff
|
|
45
|
-
# else:
|
|
46
|
-
# D = self.D
|
|
47
|
-
#
|
|
48
|
-
# n_s = self.N_S # Repeat variable for debugging compatibility
|
|
49
|
-
# n_t = self.N_T
|
|
50
|
-
#
|
|
51
|
-
# print('Computing Correlation Matrix \n')
|
|
52
|
-
|
|
53
|
-
# The first step is the same as the POD: we compute the correlation matrix
|
|
54
|
-
# K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
|
|
55
|
-
# self.FOLDER_OUT, D=self.D)
|
|
56
|
-
|
|
57
|
-
# 1. Initialize the extended
|
|
58
|
-
K_e = np.zeros((n_t + 2 * N_o, n_t + 2 * N_o))
|
|
59
|
-
# From which we clearly know that:
|
|
60
|
-
K_e[N_o:n_t + N_o, N_o:n_t + N_o] = K
|
|
61
|
-
|
|
62
|
-
# 2. We fill the edges ( a bit of repetition but ok.. )
|
|
63
|
-
|
|
64
|
-
# Row-wise, Upper part
|
|
65
|
-
for i in range(0, N_o):
|
|
66
|
-
K_e[i, i:i + n_t] = K[0, :]
|
|
67
|
-
|
|
68
|
-
# Row-wise, bottom part
|
|
69
|
-
for i in range(N_o + n_t, n_t + 2 * N_o):
|
|
70
|
-
K_e[i, i - n_t + 1:i + 1] = K[-1, :]
|
|
71
|
-
|
|
72
|
-
# Column-wise, left part
|
|
73
|
-
for j in range(0, N_o):
|
|
74
|
-
K_e[j:j + n_t, j] = K[:, 0]
|
|
75
|
-
|
|
76
|
-
# Column-wise, right part
|
|
77
|
-
for j in range(N_o + n_t, 2 * N_o + n_t):
|
|
78
|
-
K_e[j - n_t + 1:j + 1, j] = K[:, -1]
|
|
79
|
-
|
|
80
|
-
# Now you create the diagonal kernel in 2D
|
|
81
|
-
h_f = firwin(N_o, f_c) # Kernel in 1D
|
|
82
|
-
# This is also something that must be put in a separate file:
|
|
83
|
-
# To cancel the phase lag we make this non-causal with a symmetric
|
|
84
|
-
# shift, hence with zero padding as equal as possible on both sides
|
|
85
|
-
n_padd_l = round((n_t - N_o) / 2);
|
|
86
|
-
n_padd_r = n_t - N_o - n_padd_l
|
|
87
|
-
|
|
88
|
-
h_f_pad = np.pad(h_f, (n_padd_l, n_padd_r)) # symmetrically padded kernel in 1D
|
|
89
|
-
h_f_2 = np.diag(h_f_pad)
|
|
90
|
-
|
|
91
|
-
# Finally the filtered K is just
|
|
92
|
-
K_F = signal.fftconvolve(K_e, h_f_2, mode='same')[N_o:n_t + N_o, N_o:n_t + N_o]
|
|
93
|
-
# plt.plot(np.diag(K),'b--'); plt.plot(np.diag(K_F_e),'r')
|
|
94
|
-
|
|
95
|
-
# From now on it's just POD:
|
|
96
|
-
Psi_P, Sigma_P = Temporal_basis_POD(K_F, SAVE_SPOD, FOLDER_OUT, n_Modes)
|
|
97
|
-
# but with a normalization aspect to be careful about!
|
|
98
|
-
Phi_P = Spatial_basis_POD(D, N_T=n_t, PSI_P=Psi_P, Sigma_P=Sigma_P,
|
|
99
|
-
MEMORY_SAVING=MEMORY_SAVING, FOLDER_OUT=FOLDER_OUT,
|
|
100
|
-
N_PARTITIONS=N_PARTITIONS,rescale=True)
|
|
101
|
-
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy import signal
|
|
3
|
+
from scipy.signal import firwin
|
|
4
|
+
from ._pod_time import Temporal_basis_POD
|
|
5
|
+
from ._pod_space import Spatial_basis_POD
|
|
6
|
+
|
|
7
|
+
def compute_SPOD_s(D, K, F_S, n_s, n_t,N_o=100, f_c=0.3,n_Modes=10, SAVE_SPOD=True,
|
|
8
|
+
FOLDER_OUT='./', MEMORY_SAVING=False, N_PARTITIONS=1):
|
|
9
|
+
"""
|
|
10
|
+
This method computes the Spectral POD of your data.
|
|
11
|
+
This is the one by Sieber
|
|
12
|
+
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition/DCD8A6EDEFD56F5A9715DBAD38BD461A)
|
|
13
|
+
|
|
14
|
+
:param F_S: float,
|
|
15
|
+
Sampling Frequency [Hz]
|
|
16
|
+
:param N_o: float,
|
|
17
|
+
Semi-Order of the diagonal filter.
|
|
18
|
+
Note that the filter order will be 2 N_o +1 (to make sure it is odd)
|
|
19
|
+
:param f_c: float,
|
|
20
|
+
cut-off frequency of the diagonal filter
|
|
21
|
+
:param n_Modes: float,
|
|
22
|
+
number of modes to be computed
|
|
23
|
+
:param SAVE_SPOD: bool,
|
|
24
|
+
If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp
|
|
25
|
+
:param FOLDER_OUT: string
|
|
26
|
+
Define where the out will be stored (ignored if SAVE_POD=False)
|
|
27
|
+
:param MEMORY SAVING: bool
|
|
28
|
+
Define if memory saving is active or not (reduntant; to be improved)
|
|
29
|
+
Currently left for compatibility with the rest of MODULO.
|
|
30
|
+
:param N_PARTITIONS: int
|
|
31
|
+
number of partitions (if memory saving = False, it should be 1).
|
|
32
|
+
(reduntant; to be improved)
|
|
33
|
+
Currently left for compatibility with the rest of MODULO.
|
|
34
|
+
:return Psi_P: np.array
|
|
35
|
+
SPOD Psis
|
|
36
|
+
:return Sigma_P: np.array
|
|
37
|
+
SPOD Sigmas.
|
|
38
|
+
:return Phi_P: np.array
|
|
39
|
+
SPOD Phis
|
|
40
|
+
"""
|
|
41
|
+
# if self.D is None:
|
|
42
|
+
# D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
43
|
+
# SAVE_SPOD = True
|
|
44
|
+
# # TODO : Lorenzo check this stuff
|
|
45
|
+
# else:
|
|
46
|
+
# D = self.D
|
|
47
|
+
#
|
|
48
|
+
# n_s = self.N_S # Repeat variable for debugging compatibility
|
|
49
|
+
# n_t = self.N_T
|
|
50
|
+
#
|
|
51
|
+
# print('Computing Correlation Matrix \n')
|
|
52
|
+
|
|
53
|
+
# The first step is the same as the POD: we compute the correlation matrix
|
|
54
|
+
# K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
|
|
55
|
+
# self.FOLDER_OUT, D=self.D)
|
|
56
|
+
|
|
57
|
+
# 1. Initialize the extended
|
|
58
|
+
K_e = np.zeros((n_t + 2 * N_o, n_t + 2 * N_o))
|
|
59
|
+
# From which we clearly know that:
|
|
60
|
+
K_e[N_o:n_t + N_o, N_o:n_t + N_o] = K
|
|
61
|
+
|
|
62
|
+
# 2. We fill the edges ( a bit of repetition but ok.. )
|
|
63
|
+
|
|
64
|
+
# Row-wise, Upper part
|
|
65
|
+
for i in range(0, N_o):
|
|
66
|
+
K_e[i, i:i + n_t] = K[0, :]
|
|
67
|
+
|
|
68
|
+
# Row-wise, bottom part
|
|
69
|
+
for i in range(N_o + n_t, n_t + 2 * N_o):
|
|
70
|
+
K_e[i, i - n_t + 1:i + 1] = K[-1, :]
|
|
71
|
+
|
|
72
|
+
# Column-wise, left part
|
|
73
|
+
for j in range(0, N_o):
|
|
74
|
+
K_e[j:j + n_t, j] = K[:, 0]
|
|
75
|
+
|
|
76
|
+
# Column-wise, right part
|
|
77
|
+
for j in range(N_o + n_t, 2 * N_o + n_t):
|
|
78
|
+
K_e[j - n_t + 1:j + 1, j] = K[:, -1]
|
|
79
|
+
|
|
80
|
+
# Now you create the diagonal kernel in 2D
|
|
81
|
+
h_f = firwin(N_o, f_c) # Kernel in 1D
|
|
82
|
+
# This is also something that must be put in a separate file:
|
|
83
|
+
# To cancel the phase lag we make this non-causal with a symmetric
|
|
84
|
+
# shift, hence with zero padding as equal as possible on both sides
|
|
85
|
+
n_padd_l = round((n_t - N_o) / 2);
|
|
86
|
+
n_padd_r = n_t - N_o - n_padd_l
|
|
87
|
+
|
|
88
|
+
h_f_pad = np.pad(h_f, (n_padd_l, n_padd_r)) # symmetrically padded kernel in 1D
|
|
89
|
+
h_f_2 = np.diag(h_f_pad)
|
|
90
|
+
|
|
91
|
+
# Finally the filtered K is just
|
|
92
|
+
K_F = signal.fftconvolve(K_e, h_f_2, mode='same')[N_o:n_t + N_o, N_o:n_t + N_o]
|
|
93
|
+
# plt.plot(np.diag(K),'b--'); plt.plot(np.diag(K_F_e),'r')
|
|
94
|
+
|
|
95
|
+
# From now on it's just POD:
|
|
96
|
+
Psi_P, Sigma_P = Temporal_basis_POD(K_F, SAVE_SPOD, FOLDER_OUT, n_Modes)
|
|
97
|
+
# but with a normalization aspect to be careful about!
|
|
98
|
+
Phi_P = Spatial_basis_POD(D, N_T=n_t, PSI_P=Psi_P, Sigma_P=Sigma_P,
|
|
99
|
+
MEMORY_SAVING=MEMORY_SAVING, FOLDER_OUT=FOLDER_OUT,
|
|
100
|
+
N_PARTITIONS=N_PARTITIONS,rescale=True)
|
|
101
|
+
|
|
102
102
|
return Phi_P, Psi_P, Sigma_P
|
modulo_vki/core/_spod_t.py
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from modulo_vki.utils._utils import overlap
|
|
3
|
-
from tqdm import tqdm
|
|
4
|
-
import os
|
|
5
|
-
|
|
6
|
-
from modulo_vki.utils._utils import switch_svds
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def compute_SPOD_t(D, F_S, L_B=500, O_B=250,n_Modes=10, SAVE_SPOD=True, FOLDER_OUT='/',
|
|
11
|
-
possible_svds='svd_sklearn_truncated'):
|
|
12
|
-
"""
|
|
13
|
-
This method computes the Spectral POD of your data.
|
|
14
|
-
This is the one by Town
|
|
15
|
-
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/spectral-proper-orthogonal-decomposition-and-its-relationship-to-dynamic-mode-decomposition-and-resolvent-analysis/EC2A6DF76490A0B9EB208CC2CA037717)
|
|
16
|
-
|
|
17
|
-
:param D: array.
|
|
18
|
-
snapshot matrix to decompose, of size N_S,N_T
|
|
19
|
-
:param F_S: float,
|
|
20
|
-
Sampling Frequency [Hz]
|
|
21
|
-
:param L_B: float,
|
|
22
|
-
Lenght of the chunks
|
|
23
|
-
:param O_B: float,
|
|
24
|
-
Overlapping between blocks in the chunk
|
|
25
|
-
:param n_Modes: float,
|
|
26
|
-
Number of modes to be computed FOR EACH FREQUENCY
|
|
27
|
-
:param SAVE_SPOD: bool,
|
|
28
|
-
If True, MODULO will save the output in FOLDER OUT/MODULO_tmp
|
|
29
|
-
:param possible_svds: str,
|
|
30
|
-
Svd solver to be used throughout the computation
|
|
31
|
-
|
|
32
|
-
:return Psi_P_hat: np.array
|
|
33
|
-
Spectra of the SPOD Modes
|
|
34
|
-
:return Sigma_P: np.array
|
|
35
|
-
Amplitudes of the SPOD Modes.
|
|
36
|
-
:return Phi_P: np.array
|
|
37
|
-
SPOD Phis
|
|
38
|
-
:return freq: float
|
|
39
|
-
Frequency bins for the Spectral POD
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
# if D is None:
|
|
43
|
-
# D = np.load(FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
44
|
-
# SAVE_SPOD = True
|
|
45
|
-
# else:
|
|
46
|
-
# D = D
|
|
47
|
-
#
|
|
48
|
-
# n_s = N_S # Repeat variable for debugging compatibility
|
|
49
|
-
# n_t = N_T
|
|
50
|
-
#
|
|
51
|
-
# # First comput the PS in each point (this is very time consuming and should be parallelized)
|
|
52
|
-
# # Note: this can be improved a lot...! ok for the moment
|
|
53
|
-
print('Computing PSD at all points\n')
|
|
54
|
-
N_S,N_T=np.shape(D)
|
|
55
|
-
|
|
56
|
-
# Step 1 : Partition the data into blocks ( potentially overlapping)
|
|
57
|
-
Ind = np.arange(N_T)
|
|
58
|
-
Indices = overlap(Ind, len_chunk=L_B, len_sep=O_B)
|
|
59
|
-
|
|
60
|
-
N_B = np.shape(Indices)[1]
|
|
61
|
-
N_P = np.shape(Indices)[0]
|
|
62
|
-
print('Partitioned into blocks of length n_B=' + str(N_B))
|
|
63
|
-
print('Number of partitions retained is n_P=' + str(N_P))
|
|
64
|
-
|
|
65
|
-
# The frequency bins are thus defined:
|
|
66
|
-
Freqs = np.fft.fftfreq(N_B) * F_S # Compute the frequency bins
|
|
67
|
-
Keep_IND = np.where(Freqs >= 0)
|
|
68
|
-
N_B2 = len(Keep_IND[0]) # indexes for positive frequencies
|
|
69
|
-
Freqs_Pos = Freqs[Keep_IND] # positive frequencies
|
|
70
|
-
|
|
71
|
-
# Step 2 : Construct the D_hats in each partition
|
|
72
|
-
D_P_hat_Tens = np.zeros((N_S, N_B, N_P))
|
|
73
|
-
print('Computing DFTs in each partition')
|
|
74
|
-
for k in tqdm(range(0, N_P)): # Loop over the partitions
|
|
75
|
-
D_p = D[:, Indices[k]] # Take the portion of data
|
|
76
|
-
D_P_hat_Tens[:, :, k] = np.fft.fft(D_p, N_B, 1)
|
|
77
|
-
|
|
78
|
-
# This would be the mean over the frequencies
|
|
79
|
-
# D_hat_Mean=np.mean(D_P_hat_Tens,axis=1)
|
|
80
|
-
|
|
81
|
-
# Initialize the outputs
|
|
82
|
-
Sigma_SP = np.zeros((n_Modes, N_B2))
|
|
83
|
-
Phi_SP = np.zeros((N_S, n_Modes, N_B2))
|
|
84
|
-
|
|
85
|
-
# Step 3: Loop over frequencies to build the modes.
|
|
86
|
-
# Note: you only care about half of these frequencies.
|
|
87
|
-
# This is why you loop over N_B2, not N_B
|
|
88
|
-
print('Computing POD for each frequency')
|
|
89
|
-
for j in tqdm(range(0, N_B2)):
|
|
90
|
-
# Get D_hat of the chunk
|
|
91
|
-
D_hat_f = D_P_hat_Tens[:, j, :]
|
|
92
|
-
# Go for the SVD
|
|
93
|
-
|
|
94
|
-
U,V,Sigma=switch_svds(D_hat_f,n_Modes,svd_solver=possible_svds)
|
|
95
|
-
|
|
96
|
-
Phi_SP[:, :, j] = U
|
|
97
|
-
Sigma_SP[:, j] = Sigma / (N_S * N_B)
|
|
98
|
-
|
|
99
|
-
if SAVE_SPOD:
|
|
100
|
-
folder_dir = FOLDER_OUT + '/SPOD_T'
|
|
101
|
-
os.makedirs(folder_dir, exist_ok=True)
|
|
102
|
-
np.savez(folder_dir + '/spod_t.npz', Phi=Phi_SP, Sigma=Sigma_SP, Freqs=Freqs_Pos)
|
|
103
|
-
|
|
104
|
-
return Phi_SP, Sigma_SP, Freqs_Pos
|
|
1
|
+
import numpy as np
|
|
2
|
+
from modulo_vki.utils._utils import overlap
|
|
3
|
+
from tqdm import tqdm
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from modulo_vki.utils._utils import switch_svds
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def compute_SPOD_t(D, F_S, L_B=500, O_B=250,n_Modes=10, SAVE_SPOD=True, FOLDER_OUT='/',
|
|
11
|
+
possible_svds='svd_sklearn_truncated'):
|
|
12
|
+
"""
|
|
13
|
+
This method computes the Spectral POD of your data.
|
|
14
|
+
This is the one by Town
|
|
15
|
+
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/spectral-proper-orthogonal-decomposition-and-its-relationship-to-dynamic-mode-decomposition-and-resolvent-analysis/EC2A6DF76490A0B9EB208CC2CA037717)
|
|
16
|
+
|
|
17
|
+
:param D: array.
|
|
18
|
+
snapshot matrix to decompose, of size N_S,N_T
|
|
19
|
+
:param F_S: float,
|
|
20
|
+
Sampling Frequency [Hz]
|
|
21
|
+
:param L_B: float,
|
|
22
|
+
Lenght of the chunks
|
|
23
|
+
:param O_B: float,
|
|
24
|
+
Overlapping between blocks in the chunk
|
|
25
|
+
:param n_Modes: float,
|
|
26
|
+
Number of modes to be computed FOR EACH FREQUENCY
|
|
27
|
+
:param SAVE_SPOD: bool,
|
|
28
|
+
If True, MODULO will save the output in FOLDER OUT/MODULO_tmp
|
|
29
|
+
:param possible_svds: str,
|
|
30
|
+
Svd solver to be used throughout the computation
|
|
31
|
+
|
|
32
|
+
:return Psi_P_hat: np.array
|
|
33
|
+
Spectra of the SPOD Modes
|
|
34
|
+
:return Sigma_P: np.array
|
|
35
|
+
Amplitudes of the SPOD Modes.
|
|
36
|
+
:return Phi_P: np.array
|
|
37
|
+
SPOD Phis
|
|
38
|
+
:return freq: float
|
|
39
|
+
Frequency bins for the Spectral POD
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
# if D is None:
|
|
43
|
+
# D = np.load(FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
44
|
+
# SAVE_SPOD = True
|
|
45
|
+
# else:
|
|
46
|
+
# D = D
|
|
47
|
+
#
|
|
48
|
+
# n_s = N_S # Repeat variable for debugging compatibility
|
|
49
|
+
# n_t = N_T
|
|
50
|
+
#
|
|
51
|
+
# # First comput the PS in each point (this is very time consuming and should be parallelized)
|
|
52
|
+
# # Note: this can be improved a lot...! ok for the moment
|
|
53
|
+
print('Computing PSD at all points\n')
|
|
54
|
+
N_S,N_T=np.shape(D)
|
|
55
|
+
|
|
56
|
+
# Step 1 : Partition the data into blocks ( potentially overlapping)
|
|
57
|
+
Ind = np.arange(N_T)
|
|
58
|
+
Indices = overlap(Ind, len_chunk=L_B, len_sep=O_B)
|
|
59
|
+
|
|
60
|
+
N_B = np.shape(Indices)[1]
|
|
61
|
+
N_P = np.shape(Indices)[0]
|
|
62
|
+
print('Partitioned into blocks of length n_B=' + str(N_B))
|
|
63
|
+
print('Number of partitions retained is n_P=' + str(N_P))
|
|
64
|
+
|
|
65
|
+
# The frequency bins are thus defined:
|
|
66
|
+
Freqs = np.fft.fftfreq(N_B) * F_S # Compute the frequency bins
|
|
67
|
+
Keep_IND = np.where(Freqs >= 0)
|
|
68
|
+
N_B2 = len(Keep_IND[0]) # indexes for positive frequencies
|
|
69
|
+
Freqs_Pos = Freqs[Keep_IND] # positive frequencies
|
|
70
|
+
|
|
71
|
+
# Step 2 : Construct the D_hats in each partition
|
|
72
|
+
D_P_hat_Tens = np.zeros((N_S, N_B, N_P))
|
|
73
|
+
print('Computing DFTs in each partition')
|
|
74
|
+
for k in tqdm(range(0, N_P)): # Loop over the partitions
|
|
75
|
+
D_p = D[:, Indices[k]] # Take the portion of data
|
|
76
|
+
D_P_hat_Tens[:, :, k] = np.fft.fft(D_p, N_B, 1)
|
|
77
|
+
|
|
78
|
+
# This would be the mean over the frequencies
|
|
79
|
+
# D_hat_Mean=np.mean(D_P_hat_Tens,axis=1)
|
|
80
|
+
|
|
81
|
+
# Initialize the outputs
|
|
82
|
+
Sigma_SP = np.zeros((n_Modes, N_B2))
|
|
83
|
+
Phi_SP = np.zeros((N_S, n_Modes, N_B2))
|
|
84
|
+
|
|
85
|
+
# Step 3: Loop over frequencies to build the modes.
|
|
86
|
+
# Note: you only care about half of these frequencies.
|
|
87
|
+
# This is why you loop over N_B2, not N_B
|
|
88
|
+
print('Computing POD for each frequency')
|
|
89
|
+
for j in tqdm(range(0, N_B2)):
|
|
90
|
+
# Get D_hat of the chunk
|
|
91
|
+
D_hat_f = D_P_hat_Tens[:, j, :]
|
|
92
|
+
# Go for the SVD
|
|
93
|
+
|
|
94
|
+
U,V,Sigma=switch_svds(D_hat_f,n_Modes,svd_solver=possible_svds)
|
|
95
|
+
|
|
96
|
+
Phi_SP[:, :, j] = U
|
|
97
|
+
Sigma_SP[:, j] = Sigma / (N_S * N_B)
|
|
98
|
+
|
|
99
|
+
if SAVE_SPOD:
|
|
100
|
+
folder_dir = FOLDER_OUT + '/SPOD_T'
|
|
101
|
+
os.makedirs(folder_dir, exist_ok=True)
|
|
102
|
+
np.savez(folder_dir + '/spod_t.npz', Phi=Phi_SP, Sigma=Sigma_SP, Freqs=Freqs_Pos)
|
|
103
|
+
|
|
104
|
+
return Phi_SP, Sigma_SP, Freqs_Pos
|