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.
@@ -1,180 +1,180 @@
1
- import numpy as np
2
- import os
3
- from tqdm import tqdm
4
- import math
5
-
6
-
7
- def spatial_basis_mPOD(D, PSI_M, N_T, N_PARTITIONS, N_S, MEMORY_SAVING, FOLDER_OUT, SAVE: bool = False,weights: np.array = np.array([])):
8
- """
9
- Given the temporal basis of the mPOD now the spatial ones are computed
10
-
11
- :param D:
12
- Snapshot matrix D: if memory savig is active, this is ignored.
13
- :param PSI_M: np.array.:
14
- The mPOD temporal basis Psi tentatively assembled from all scales
15
- :param N_T: int.
16
- Number of snapshots
17
- :param N_PARTITIONS: int.
18
- Number of partitions in the memory saving
19
- :param N_S: int.
20
- Number of grid points in space
21
- :param MEMORY_SAVING: bool.
22
- Inherited from main class, if True turns on the MEMORY_SAVING feature, loading the partitions and starting the proper algorithm
23
- :param FOLDER_OUT: str.
24
- Folder in which the results are saved if SAVE_SPATIAL_POD = True
25
- :param SAVE_SPATIAL_POD: bool.
26
- If True, results are saved on disk and released from memory
27
- :param weights: np.array
28
- weight vector [w_i,....,w_{N_s}] where w_i = area_cell_i/area_grid. Only needed if grid is non-uniform & MEMORY_SAVING== True
29
- :return: Phi_M, Psi_M, Sigma_M: np.arrays. The final (sorted) mPOD decomposition
30
- """
31
-
32
- R1 = 0; R2 = 0
33
- if MEMORY_SAVING:
34
- SAVE = True
35
- os.makedirs(FOLDER_OUT + '/mPOD/', exist_ok=True)
36
- dim_col = math.floor(N_T / N_PARTITIONS)
37
- dim_row = math.floor(N_S / N_PARTITIONS)
38
- dr = np.zeros((dim_row, N_T))
39
-
40
- # 1 --- Converting partitions dC to dR
41
- if N_S % N_PARTITIONS != 0:
42
- tot_blocks_row = N_PARTITIONS + 1
43
- else:
44
- tot_blocks_row = N_PARTITIONS
45
-
46
- if N_T % N_PARTITIONS != 0:
47
- tot_blocks_col = N_PARTITIONS + 1
48
- else:
49
- tot_blocks_col = N_PARTITIONS
50
-
51
- fixed = 0
52
-
53
- for i in range(1, tot_blocks_row + 1):
54
- # --- Check if dim_row has to be fixed:
55
- if i == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0):
56
- dim_row_fix = N_S - dim_row * N_PARTITIONS
57
- dr = np.zeros((dim_row_fix, N_T))
58
-
59
- for cont in range(1, tot_blocks_col + 1):
60
- di = np.load(FOLDER_OUT + f"/data_partitions/di_{cont}.npz")['di']
61
-
62
- if i == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0) and fixed == 0:
63
- R1 = R2
64
- R2 = R1 + (N_S - dim_row * N_PARTITIONS)
65
- fixed = 1
66
- elif fixed == 0:
67
- R1 = (i - 1) * dim_row
68
- R2 = i * dim_row
69
-
70
- # Same as before, but we don't need the variable fixed because if
71
- # % the code runs this loop, it will be the last time
72
-
73
- if cont == tot_blocks_col and (N_T - dim_col * N_PARTITIONS > 0):
74
- C1 = C2
75
- C2 = C1 + (N_T - dim_col * N_PARTITIONS)
76
- else:
77
- C1 = (cont - 1) * dim_col
78
- C2 = cont * dim_col
79
-
80
- dr[:, C1:C2] = di[R1:R2, :]
81
-
82
- # 2 --- Computing partitions R of PHI_SIGMA
83
- PHI_SIGMA_BLOCK = dr @ PSI_M
84
- np.savez(FOLDER_OUT + f'/mPOD/phi_sigma_{i}', PHI_SIGMA_BLOCK)
85
-
86
- # 3 --- Convert partitions R to partitions C and get SIGMA
87
- R = PSI_M.shape[1]
88
- dim_col = math.floor(R / N_PARTITIONS)
89
- dim_row = math.floor(N_S / N_PARTITIONS)
90
- dps = np.zeros((N_S, dim_col))
91
- SIGMA_M = []
92
- PHI_M = []
93
-
94
- if R % N_PARTITIONS != 0:
95
- tot_blocks_col = N_PARTITIONS + 1
96
- else:
97
- tot_blocks_col = N_PARTITIONS
98
-
99
- fixed = 0
100
-
101
- # Here we apply the same logic of the loop before
102
-
103
- for j in range(1, tot_blocks_col + 1):
104
-
105
- if j == tot_blocks_col and (R - dim_col * N_PARTITIONS > 0):
106
- dim_col_fix = R - dim_col * N_PARTITIONS
107
- dps = np.zeros((N_S, dim_col_fix))
108
-
109
- for k in range(1, tot_blocks_row + 1):
110
- PHI_SIGMA_BLOCK = np.load(FOLDER_OUT + f"/mPOD/phi_sigma_{k}.npz")['arr_0']
111
-
112
- if j == tot_blocks_col and (R - dim_col * N_PARTITIONS > 0) and fixed == 0:
113
- R1 = R2
114
- R2 = R1 + (R - dim_col * N_PARTITIONS)
115
- fixed = 1
116
- elif fixed == 0:
117
- R1 = (j - 1) * dim_col
118
- R2 = j * dim_col
119
-
120
- if k == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0):
121
- C1 = C2
122
- C2 = C1 + (N_S - dim_row * N_PARTITIONS)
123
- else:
124
- C1 = (k - 1) * dim_row
125
- C2 = k * dim_row
126
-
127
- dps[C1:C2, :] = PHI_SIGMA_BLOCK[:, R1:R2]
128
-
129
- # Getting sigmas and phis
130
- for z in range(R1, R2):
131
- zz = z - R1
132
- if weights.size == 0:
133
- SIGMA_M.append(np.linalg.norm(dps[:, zz]))
134
- else:
135
- SIGMA_M.append(np.linalg.norm(dps[:, zz]*np.sqrt(weights)))
136
- tmp = dps[:, zz] / SIGMA_M[z]
137
- #print(f'Shape tmp = {np.shape(tmp)}')
138
- PHI_M.append(tmp)
139
- np.savez(FOLDER_OUT + f'/mPOD/phi_{z + 1}', tmp)
140
-
141
- Indices = np.argsort(SIGMA_M)[::-1] # find indices for sorting in decreasing order
142
- SIGMA_M = np.asarray(SIGMA_M)
143
- PHI_M = np.asarray(PHI_M).T
144
- PSI_M = np.asarray(PSI_M)
145
- Sorted_Sigmas = SIGMA_M[Indices] # Sort all the sigmas
146
- Phi_M = PHI_M[:, Indices] # Sorted Spatial Structures Matrix
147
- Psi_M = PSI_M[:, Indices] # Sorted Temporal Structures Matrix
148
- Sigma_M = Sorted_Sigmas # Sorted Amplitude Matrix
149
-
150
- else:
151
- R = PSI_M.shape[1]
152
- PHI_M_SIGMA_M = np.dot(D, (PSI_M))
153
- # Initialize the output
154
- PHI_M = np.zeros((N_S, R))
155
- SIGMA_M = np.zeros((R))
156
-
157
- for i in tqdm(range(0, R)):
158
- # print('Completing mPOD Mode ' + str(i))
159
- # Assign the norm as amplitude
160
- if weights.size == 0:
161
- SIGMA_M[i] = np.linalg.norm(PHI_M_SIGMA_M[:, i])
162
- else:
163
- SIGMA_M[i] = np.linalg.norm(PHI_M_SIGMA_M[:, i]*np.sqrt(weights))
164
- # Normalize the columns of C to get spatial modes
165
- PHI_M[:, i] = PHI_M_SIGMA_M[:, i] / SIGMA_M[i]
166
-
167
- Indices = np.flipud(np.argsort(SIGMA_M)) # find indices for sorting in decreasing order
168
- Sorted_Sigmas = SIGMA_M[Indices] # Sort all the sigmas
169
- Phi_M = PHI_M[:, Indices] # Sorted Spatial Structures Matrix
170
- Psi_M = PSI_M[:, Indices] # Sorted Temporal Structures Matrix
171
- Sigma_M = Sorted_Sigmas # Sorted Amplitude Matrix
172
-
173
- if SAVE:
174
- '''Saving results in MODULO tmp proper folder'''
175
- os.makedirs(FOLDER_OUT + '/mPOD/', exist_ok=True)
176
- np.savez(FOLDER_OUT + "/mPOD/sorted_phis", Phi_M)
177
- np.savez(FOLDER_OUT + "/mPOD/sorted_psis", Psi_M)
178
- np.savez(FOLDER_OUT + "/mPOD/sorted_sigma", Sorted_Sigmas)
179
-
180
- return Phi_M, Psi_M, Sigma_M
1
+ import numpy as np
2
+ import os
3
+ from tqdm import tqdm
4
+ import math
5
+
6
+
7
+ def spatial_basis_mPOD(D, PSI_M, N_T, N_PARTITIONS, N_S, MEMORY_SAVING, FOLDER_OUT, SAVE: bool = False,weights: np.array = np.array([])):
8
+ """
9
+ Given the temporal basis of the mPOD now the spatial ones are computed
10
+
11
+ :param D:
12
+ Snapshot matrix D: if memory savig is active, this is ignored.
13
+ :param PSI_M: np.array.:
14
+ The mPOD temporal basis Psi tentatively assembled from all scales
15
+ :param N_T: int.
16
+ Number of snapshots
17
+ :param N_PARTITIONS: int.
18
+ Number of partitions in the memory saving
19
+ :param N_S: int.
20
+ Number of grid points in space
21
+ :param MEMORY_SAVING: bool.
22
+ Inherited from main class, if True turns on the MEMORY_SAVING feature, loading the partitions and starting the proper algorithm
23
+ :param FOLDER_OUT: str.
24
+ Folder in which the results are saved if SAVE_SPATIAL_POD = True
25
+ :param SAVE_SPATIAL_POD: bool.
26
+ If True, results are saved on disk and released from memory
27
+ :param weights: np.array
28
+ weight vector [w_i,....,w_{N_s}] where w_i = area_cell_i/area_grid. Only needed if grid is non-uniform & MEMORY_SAVING== True
29
+ :return: Phi_M, Psi_M, Sigma_M: np.arrays. The final (sorted) mPOD decomposition
30
+ """
31
+
32
+ R1 = 0; R2 = 0
33
+ if MEMORY_SAVING:
34
+ SAVE = True
35
+ os.makedirs(FOLDER_OUT + '/mPOD/', exist_ok=True)
36
+ dim_col = math.floor(N_T / N_PARTITIONS)
37
+ dim_row = math.floor(N_S / N_PARTITIONS)
38
+ dr = np.zeros((dim_row, N_T))
39
+
40
+ # 1 --- Converting partitions dC to dR
41
+ if N_S % N_PARTITIONS != 0:
42
+ tot_blocks_row = N_PARTITIONS + 1
43
+ else:
44
+ tot_blocks_row = N_PARTITIONS
45
+
46
+ if N_T % N_PARTITIONS != 0:
47
+ tot_blocks_col = N_PARTITIONS + 1
48
+ else:
49
+ tot_blocks_col = N_PARTITIONS
50
+
51
+ fixed = 0
52
+
53
+ for i in range(1, tot_blocks_row + 1):
54
+ # --- Check if dim_row has to be fixed:
55
+ if i == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0):
56
+ dim_row_fix = N_S - dim_row * N_PARTITIONS
57
+ dr = np.zeros((dim_row_fix, N_T))
58
+
59
+ for cont in range(1, tot_blocks_col + 1):
60
+ di = np.load(FOLDER_OUT + f"/data_partitions/di_{cont}.npz")['di']
61
+
62
+ if i == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0) and fixed == 0:
63
+ R1 = R2
64
+ R2 = R1 + (N_S - dim_row * N_PARTITIONS)
65
+ fixed = 1
66
+ elif fixed == 0:
67
+ R1 = (i - 1) * dim_row
68
+ R2 = i * dim_row
69
+
70
+ # Same as before, but we don't need the variable fixed because if
71
+ # % the code runs this loop, it will be the last time
72
+
73
+ if cont == tot_blocks_col and (N_T - dim_col * N_PARTITIONS > 0):
74
+ C1 = C2
75
+ C2 = C1 + (N_T - dim_col * N_PARTITIONS)
76
+ else:
77
+ C1 = (cont - 1) * dim_col
78
+ C2 = cont * dim_col
79
+
80
+ dr[:, C1:C2] = di[R1:R2, :]
81
+
82
+ # 2 --- Computing partitions R of PHI_SIGMA
83
+ PHI_SIGMA_BLOCK = dr @ PSI_M
84
+ np.savez(FOLDER_OUT + f'/mPOD/phi_sigma_{i}', PHI_SIGMA_BLOCK)
85
+
86
+ # 3 --- Convert partitions R to partitions C and get SIGMA
87
+ R = PSI_M.shape[1]
88
+ dim_col = math.floor(R / N_PARTITIONS)
89
+ dim_row = math.floor(N_S / N_PARTITIONS)
90
+ dps = np.zeros((N_S, dim_col))
91
+ SIGMA_M = []
92
+ PHI_M = []
93
+
94
+ if R % N_PARTITIONS != 0:
95
+ tot_blocks_col = N_PARTITIONS + 1
96
+ else:
97
+ tot_blocks_col = N_PARTITIONS
98
+
99
+ fixed = 0
100
+
101
+ # Here we apply the same logic of the loop before
102
+
103
+ for j in range(1, tot_blocks_col + 1):
104
+
105
+ if j == tot_blocks_col and (R - dim_col * N_PARTITIONS > 0):
106
+ dim_col_fix = R - dim_col * N_PARTITIONS
107
+ dps = np.zeros((N_S, dim_col_fix))
108
+
109
+ for k in range(1, tot_blocks_row + 1):
110
+ PHI_SIGMA_BLOCK = np.load(FOLDER_OUT + f"/mPOD/phi_sigma_{k}.npz")['arr_0']
111
+
112
+ if j == tot_blocks_col and (R - dim_col * N_PARTITIONS > 0) and fixed == 0:
113
+ R1 = R2
114
+ R2 = R1 + (R - dim_col * N_PARTITIONS)
115
+ fixed = 1
116
+ elif fixed == 0:
117
+ R1 = (j - 1) * dim_col
118
+ R2 = j * dim_col
119
+
120
+ if k == tot_blocks_row and (N_S - dim_row * N_PARTITIONS > 0):
121
+ C1 = C2
122
+ C2 = C1 + (N_S - dim_row * N_PARTITIONS)
123
+ else:
124
+ C1 = (k - 1) * dim_row
125
+ C2 = k * dim_row
126
+
127
+ dps[C1:C2, :] = PHI_SIGMA_BLOCK[:, R1:R2]
128
+
129
+ # Getting sigmas and phis
130
+ for z in range(R1, R2):
131
+ zz = z - R1
132
+ if weights.size == 0:
133
+ SIGMA_M.append(np.linalg.norm(dps[:, zz]))
134
+ else:
135
+ SIGMA_M.append(np.linalg.norm(dps[:, zz]*np.sqrt(weights)))
136
+ tmp = dps[:, zz] / SIGMA_M[z]
137
+ #print(f'Shape tmp = {np.shape(tmp)}')
138
+ PHI_M.append(tmp)
139
+ np.savez(FOLDER_OUT + f'/mPOD/phi_{z + 1}', tmp)
140
+
141
+ Indices = np.argsort(SIGMA_M)[::-1] # find indices for sorting in decreasing order
142
+ SIGMA_M = np.asarray(SIGMA_M)
143
+ PHI_M = np.asarray(PHI_M).T
144
+ PSI_M = np.asarray(PSI_M)
145
+ Sorted_Sigmas = SIGMA_M[Indices] # Sort all the sigmas
146
+ Phi_M = PHI_M[:, Indices] # Sorted Spatial Structures Matrix
147
+ Psi_M = PSI_M[:, Indices] # Sorted Temporal Structures Matrix
148
+ Sigma_M = Sorted_Sigmas # Sorted Amplitude Matrix
149
+
150
+ else:
151
+ R = PSI_M.shape[1]
152
+ PHI_M_SIGMA_M = np.dot(D, (PSI_M))
153
+ # Initialize the output
154
+ PHI_M = np.zeros((N_S, R))
155
+ SIGMA_M = np.zeros((R))
156
+
157
+ for i in tqdm(range(0, R)):
158
+ # print('Completing mPOD Mode ' + str(i))
159
+ # Assign the norm as amplitude
160
+ if weights.size == 0:
161
+ SIGMA_M[i] = np.linalg.norm(PHI_M_SIGMA_M[:, i])
162
+ else:
163
+ SIGMA_M[i] = np.linalg.norm(PHI_M_SIGMA_M[:, i]*np.sqrt(weights))
164
+ # Normalize the columns of C to get spatial modes
165
+ PHI_M[:, i] = PHI_M_SIGMA_M[:, i] / SIGMA_M[i]
166
+
167
+ Indices = np.flipud(np.argsort(SIGMA_M)) # find indices for sorting in decreasing order
168
+ Sorted_Sigmas = SIGMA_M[Indices] # Sort all the sigmas
169
+ Phi_M = PHI_M[:, Indices] # Sorted Spatial Structures Matrix
170
+ Psi_M = PSI_M[:, Indices] # Sorted Temporal Structures Matrix
171
+ Sigma_M = Sorted_Sigmas # Sorted Amplitude Matrix
172
+
173
+ if SAVE:
174
+ '''Saving results in MODULO tmp proper folder'''
175
+ os.makedirs(FOLDER_OUT + '/mPOD/', exist_ok=True)
176
+ np.savez(FOLDER_OUT + "/mPOD/sorted_phis", Phi_M)
177
+ np.savez(FOLDER_OUT + "/mPOD/sorted_psis", Psi_M)
178
+ np.savez(FOLDER_OUT + "/mPOD/sorted_sigma", Sorted_Sigmas)
179
+
180
+ return Phi_M, Psi_M, Sigma_M