modulo-vki 2.0.6__py3-none-any.whl → 2.0.7__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.
@@ -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
@@ -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