modulo-vki 2.0.3__tar.gz → 2.0.5__tar.gz
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-2.0.3 → modulo_vki-2.0.5}/PKG-INFO +2 -4
- modulo_vki-2.0.5/modulo_vki/__init__.py +23 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_k_matrix.py +1 -1
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_mpod_time.py +1 -1
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_pod_space.py +5 -5
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_spod_t.py +2 -2
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/modulo.py +111 -134
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/modulo_vki.egg-info/PKG-INFO +3 -5
- modulo_vki-2.0.5/modulo_vki.egg-info/SOURCES.txt +25 -0
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/modulo_vki.egg-info/requires.txt +0 -2
- modulo_vki-2.0.5/modulo_vki.egg-info/top_level.txt +1 -0
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/setup.py +8 -5
- modulo_vki-2.0.3/modulo/__init__.py +0 -23
- modulo_vki-2.0.3/modulo_vki.egg-info/SOURCES.txt +0 -25
- modulo_vki-2.0.3/modulo_vki.egg-info/top_level.txt +0 -1
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/LICENSE +0 -0
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/README.md +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/__init__.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_dft.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_dmd_s.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_mpod_space.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_pod_time.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/core/_spod_s.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/utils/__init__.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/utils/_plots.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/utils/_utils.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/utils/others.py +0 -0
- {modulo_vki-2.0.3/modulo → modulo_vki-2.0.5/modulo_vki}/utils/read_db.py +0 -0
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/modulo_vki.egg-info/dependency_links.txt +0 -0
- {modulo_vki-2.0.3 → modulo_vki-2.0.5}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: modulo_vki
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary: MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale Modal Analysis of numerical and experimental data
|
|
3
|
+
Version: 2.0.5
|
|
4
|
+
Summary: MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale Modal Analysis of numerical and experimental data.
|
|
5
5
|
Home-page: https://github.com/mendezVKI/MODULO/tree/master/modulo_python_package/
|
|
6
6
|
Author: ['R. Poletti', 'L. Schena', 'D. Ninni', 'M. A. Mendez']
|
|
7
7
|
Author-email: mendez@vki.ac.be
|
|
@@ -21,8 +21,6 @@ Requires-Dist: ipython
|
|
|
21
21
|
Requires-Dist: ipython-genutils
|
|
22
22
|
Requires-Dist: ipywidgets
|
|
23
23
|
Requires-Dist: matplotlib
|
|
24
|
-
Requires-Dist: pyvista
|
|
25
|
-
Requires-Dist: imageio
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
from modulo_vki.modulo import ModuloVKI
|
|
@@ -4,7 +4,7 @@ import numpy as np
|
|
|
4
4
|
import math
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def CorrelationMatrix(N_T, N_PARTITIONS=1, MEMORY_SAVING=False, FOLDER_OUT='./', SAVE_K=
|
|
7
|
+
def CorrelationMatrix(N_T, N_PARTITIONS=1, MEMORY_SAVING=False, FOLDER_OUT='./', SAVE_K=False, D=None,weights = np.array([])):
|
|
8
8
|
"""
|
|
9
9
|
This method computes the temporal correlation matrix, given a data matrix as input. It's possible to use memory saving
|
|
10
10
|
then splitting the computing in different tranches if computationally heavy. If D has been computed using MODULO
|
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
from scipy.signal import firwin # To create FIR kernels
|
|
4
4
|
from tqdm import tqdm
|
|
5
|
-
from
|
|
5
|
+
from modulo_vki.utils._utils import conv_m, switch_eigs
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def temporal_basis_mPOD(K, Nf, Ex, F_V, Keep, boundaries, MODE='reduced', dt=1,FOLDER_OUT: str = "./", MEMORY_SAVING: bool = False,SAT: int = 100,n_Modes=10, eig_solver: str = 'svd_sklearn_randomized'):
|
|
@@ -120,7 +120,7 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING, N_T, FOLDER_OUT='./', N_
|
|
|
120
120
|
np.copyto(dr[:, C1:C2], di[R1:R2, :])
|
|
121
121
|
|
|
122
122
|
PHI_SIGMA_BLOCK = np.dot(dr, PSI_P)
|
|
123
|
-
np.savez(FOLDER_OUT + f"/
|
|
123
|
+
np.savez(FOLDER_OUT + f"/PHI_SIGMA_{i}",
|
|
124
124
|
phi_sigma=PHI_SIGMA_BLOCK)
|
|
125
125
|
|
|
126
126
|
# 3 - Converting partitions R to partitions C and get Sigmas
|
|
@@ -144,7 +144,7 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING, N_T, FOLDER_OUT='./', N_
|
|
|
144
144
|
|
|
145
145
|
for b in range(1, tot_blocks_row + 1):
|
|
146
146
|
|
|
147
|
-
PHI_SIGMA_BLOCK = np.load(FOLDER_OUT + f"/
|
|
147
|
+
PHI_SIGMA_BLOCK = np.load(FOLDER_OUT + f"/PHI_SIGMA_{b}.npz")['phi_sigma']
|
|
148
148
|
|
|
149
149
|
if (i == tot_blocks_col) and (R - dim_col * N_PARTITIONS > 0) and fixed == 0:
|
|
150
150
|
R1 = R2
|
|
@@ -169,16 +169,16 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING, N_T, FOLDER_OUT='./', N_
|
|
|
169
169
|
jj = j - R1
|
|
170
170
|
Sigma_P[jj] = np.linalg.norm(dps[:, jj])
|
|
171
171
|
Phi_P = dps[:, jj] / Sigma_P[jj]
|
|
172
|
-
np.savez(FOLDER_OUT + f"/
|
|
172
|
+
np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
|
|
173
173
|
else:
|
|
174
174
|
for j in range(R1, R2):
|
|
175
175
|
jj = j - R1
|
|
176
176
|
Phi_P = dps[:, jj] / Sigma_P[jj]
|
|
177
|
-
np.savez(FOLDER_OUT + f"/
|
|
177
|
+
np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
|
|
178
178
|
|
|
179
179
|
Phi_P_M = np.zeros((N_S, R))
|
|
180
180
|
for j in range(R):
|
|
181
|
-
Phi_P_V = np.load(FOLDER_OUT + f"/
|
|
181
|
+
Phi_P_V = np.load(FOLDER_OUT + f"/phi_{j + 1}.npz")['phi_p']
|
|
182
182
|
Phi_P_M[:, j] = Phi_P_V
|
|
183
183
|
|
|
184
184
|
return Phi_P_M
|
|
@@ -7,21 +7,20 @@ from sklearn.metrics.pairwise import pairwise_kernels
|
|
|
7
7
|
from tqdm import tqdm
|
|
8
8
|
|
|
9
9
|
# All the functions from the modulo package
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
|
|
21
|
-
from
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class MODULO:
|
|
10
|
+
from modulo_vki.core._dft import dft_fit
|
|
11
|
+
from modulo_vki.core._dmd_s import dmd_s
|
|
12
|
+
from modulo_vki.core._k_matrix import CorrelationMatrix
|
|
13
|
+
from modulo_vki.core._mpod_space import spatial_basis_mPOD
|
|
14
|
+
from modulo_vki.core._mpod_time import temporal_basis_mPOD
|
|
15
|
+
from modulo_vki.core._pod_space import Spatial_basis_POD
|
|
16
|
+
from modulo_vki.core._pod_time import Temporal_basis_POD
|
|
17
|
+
from modulo_vki.core._spod_s import compute_SPOD_s
|
|
18
|
+
from modulo_vki.core._spod_t import compute_SPOD_t
|
|
19
|
+
from modulo_vki.utils._utils import switch_svds
|
|
20
|
+
|
|
21
|
+
from modulo_vki.utils.read_db import ReadData
|
|
22
|
+
|
|
23
|
+
class ModuloVKI:
|
|
25
24
|
"""
|
|
26
25
|
MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale
|
|
27
26
|
Modal Analysis of numerical and experimental data using the Multiscale Proper Orthogonal Decomposition (mPOD).
|
|
@@ -44,6 +43,7 @@ class MODULO:
|
|
|
44
43
|
def __init__(self, data: np.array,
|
|
45
44
|
N_PARTITIONS: int = 1,
|
|
46
45
|
FOLDER_OUT='./',
|
|
46
|
+
SAVE_K: bool = False,
|
|
47
47
|
N_T: int = 100,
|
|
48
48
|
N_S: int = 200,
|
|
49
49
|
n_Modes: int = 10,
|
|
@@ -55,34 +55,37 @@ class MODULO:
|
|
|
55
55
|
This function initializes the main parameters needed by MODULO.
|
|
56
56
|
|
|
57
57
|
Attributes:
|
|
58
|
-
|
|
59
|
-
:param data: This is the data matrix to factorize. It is a np.array with
|
|
58
|
+
|
|
59
|
+
:param data: This is the data matrix to factorize. It is a np.array with
|
|
60
60
|
shape ((N_S, N_T)). If the data has not yet been prepared in the form of a np.array,
|
|
61
|
-
the method ReadData in MODULO can be used (see ReadData). If the memory saving is active (N_PARTITIONS >1), the folder with partitions should be prepared.
|
|
61
|
+
the method ReadData in MODULO can be used (see ReadData). If the memory saving is active (N_PARTITIONS >1), the folder with partitions should be prepared.
|
|
62
62
|
If the memory saving is active, this entry = None. The data matrix is assumed to big to be saved and the
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
:param N_PARTITIONS: If memory saving feature is active, this parameter sets the number of partitions
|
|
65
65
|
that will be used to store the data matrices during the computations.
|
|
66
|
-
|
|
67
|
-
:param FOLDER_OUT: Folder in which the output will be stored.The output includes the matrices Phi, Sigma and Psi (optional) and temporary files
|
|
66
|
+
|
|
67
|
+
:param FOLDER_OUT: Folder in which the output will be stored.The output includes the matrices Phi, Sigma and Psi (optional) and temporary files
|
|
68
68
|
used for some of the calculations (e.g.: for memory saving).
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
:param SAVE_K: A flag deciding if the matrix will be stored in the disk (in FOLDER_OUT/correlation_matrix) or not.
|
|
71
|
+
Default option is 'False'.
|
|
72
|
+
|
|
70
73
|
:param N_T: Number of time steps, must be given when N_PARTITIONS >1
|
|
71
|
-
|
|
74
|
+
|
|
72
75
|
:param N_S: Number of grid points, must be given when N_PARTITIONS >1
|
|
73
|
-
|
|
74
|
-
:param n_Modes: Number of Modes to be computed
|
|
75
|
-
|
|
76
|
+
|
|
77
|
+
:param n_Modes: Number of Modes to be computed
|
|
78
|
+
|
|
76
79
|
:param dtype: Cast "data" with type dtype
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
:param eig_solver: Numerical solver to compute the eigen values
|
|
79
|
-
|
|
82
|
+
|
|
80
83
|
:param svd_solver: Numerical solver to compute the Single Value Decomposition
|
|
81
|
-
|
|
84
|
+
|
|
82
85
|
:param weights: weight vector [w_i,....,w_{N_s}] where w_i = area_cell_i/area_grid
|
|
83
86
|
Only needed if grid is non-uniform.
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
|
|
88
|
+
|
|
86
89
|
"""
|
|
87
90
|
|
|
88
91
|
print("MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform "
|
|
@@ -160,40 +163,15 @@ class MODULO:
|
|
|
160
163
|
|
|
161
164
|
self.FOLDER_OUT = FOLDER_OUT
|
|
162
165
|
|
|
163
|
-
if self.MEMORY_SAVING:
|
|
164
|
-
os.makedirs(self.FOLDER_OUT, exist_ok=True)
|
|
165
|
-
|
|
166
|
-
def _correlation_matrix(self,
|
|
167
|
-
SAVE_K: bool = True):
|
|
168
|
-
"""
|
|
169
|
-
This method computes the time correlation matrix. Here the memory saving is
|
|
170
|
-
beneficial for large datasets. Since the matrix could be potentially heavy, it is automatically stored on disk to
|
|
171
|
-
minimize the usage of the RAM. This feature can be deactivated by setting SAVE_K = False.
|
|
172
|
-
In this case, the correlation matrix is returned to the main class.
|
|
173
|
-
|
|
174
|
-
:param SAVE_K: bool
|
|
175
|
-
A flag deciding if the matrix will be stored in the disk (in FOLDER_OUT/MODULO_tmp) or not.
|
|
176
|
-
Default option is 'True'. This attribute is passed to the class
|
|
177
|
-
in order to decide if it has to be loaded from disk or not.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
:return K: np.array
|
|
181
|
-
The correlation matrix D^T D (as class attribute) if Memory saving is not active.
|
|
182
|
-
Otherwise, it returns None and the matrix is automatically saved on disk.
|
|
183
|
-
|
|
184
|
-
"""
|
|
185
|
-
|
|
186
166
|
self.SAVE_K = SAVE_K
|
|
187
167
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return
|
|
168
|
+
if self.MEMORY_SAVING:
|
|
169
|
+
os.makedirs(self.FOLDER_OUT, exist_ok=True)
|
|
192
170
|
|
|
193
171
|
def _temporal_basis_POD(self,
|
|
194
|
-
SAVE_T_POD: bool =
|
|
172
|
+
SAVE_T_POD: bool = False):
|
|
195
173
|
"""
|
|
196
|
-
This method computes the temporal structure for the Proper Orthogonal Decomposition (POD) computation.
|
|
174
|
+
This method computes the temporal structure for the Proper Orthogonal Decomposition (POD) computation.
|
|
197
175
|
The theoretical background of the POD is briefly recalled here:
|
|
198
176
|
|
|
199
177
|
https://youtu.be/8fhupzhAR_M
|
|
@@ -214,10 +192,10 @@ class MODULO:
|
|
|
214
192
|
https://docs.microsoft.com/en-us/windows/wsl/install-win10
|
|
215
193
|
|
|
216
194
|
:param SAVE_T_POD: bool
|
|
217
|
-
Flag deciding if the results will be stored on the disk.
|
|
195
|
+
Flag deciding if the results will be stored on the disk.
|
|
218
196
|
Default value is True, to limit the RAM's usage.
|
|
219
197
|
Note that this might cause a minor slowdown for the loading,
|
|
220
|
-
but the tradeoff seems worthy.
|
|
198
|
+
but the tradeoff seems worthy.
|
|
221
199
|
This attribute is passed to the MODULO class.
|
|
222
200
|
|
|
223
201
|
|
|
@@ -245,25 +223,25 @@ class MODULO:
|
|
|
245
223
|
def _spatial_basis_POD(self, Psi_P, Sigma_P,
|
|
246
224
|
SAVE_SPATIAL_POD: bool = True):
|
|
247
225
|
"""
|
|
248
|
-
This method computes the spatial structure for the Proper Orthogonal Decomposition (POD) computation.
|
|
226
|
+
This method computes the spatial structure for the Proper Orthogonal Decomposition (POD) computation.
|
|
249
227
|
The theoretical background of the POD is briefly recalled here:
|
|
250
228
|
|
|
251
229
|
https://youtu.be/8fhupzhAR_M
|
|
252
|
-
|
|
230
|
+
|
|
253
231
|
:param Psi_P: np.array
|
|
254
232
|
POD temporal basis
|
|
255
233
|
:param Sigma_P: np.array
|
|
256
234
|
POD Sigmas
|
|
257
235
|
:param SAVE_SPATIAL_POD: bool
|
|
258
|
-
Flag deciding if the results will be stored on the disk.
|
|
236
|
+
Flag deciding if the results will be stored on the disk.
|
|
259
237
|
Default value is True, to limit the RAM's usage.
|
|
260
238
|
Note that this might cause a minor slowdown for the loading,
|
|
261
|
-
but the tradeoff seems worthy.
|
|
239
|
+
but the tradeoff seems worthy.
|
|
262
240
|
This attribute is passed to the MODULO class.
|
|
263
241
|
|
|
264
242
|
:return Phi_P: np.array
|
|
265
243
|
POD Phis
|
|
266
|
-
|
|
244
|
+
|
|
267
245
|
"""
|
|
268
246
|
|
|
269
247
|
self.SAVE_SPATIAL_POD = SAVE_SPATIAL_POD
|
|
@@ -299,10 +277,10 @@ class MODULO:
|
|
|
299
277
|
:param boundaries: str -> {'nearest', 'reflect', 'wrap' or 'extrap'}
|
|
300
278
|
Define the boundary conditions for the filtering process, in order to avoid edge effects.
|
|
301
279
|
The available boundary conditions are the classic ones implemented for image processing:
|
|
302
|
-
nearest', 'reflect', 'wrap' or 'extrap'. See also https://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html
|
|
280
|
+
nearest', 'reflect', 'wrap' or 'extrap'. See also https://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html
|
|
303
281
|
:param MODE: str -> {‘reduced’, ‘complete’, ‘r’, ‘raw’}
|
|
304
282
|
A QR factorization is used to enforce the orthonormality of the mPOD basis, to compensate
|
|
305
|
-
for the non-ideal frequency response of the filters.
|
|
283
|
+
for the non-ideal frequency response of the filters.
|
|
306
284
|
The option MODE from np.linalg.qr carries out this operation.
|
|
307
285
|
|
|
308
286
|
:return PSI_M: np.array
|
|
@@ -322,7 +300,7 @@ class MODULO:
|
|
|
322
300
|
|
|
323
301
|
def _spatial_basis_mPOD(self, D, PSI_M, SAVE):
|
|
324
302
|
"""
|
|
325
|
-
This function implements the last step of the mPOD algorithm:
|
|
303
|
+
This function implements the last step of the mPOD algorithm:
|
|
326
304
|
completing the decomposition. Here we project from psis, to get phis and sigmas
|
|
327
305
|
|
|
328
306
|
:param D: np.array
|
|
@@ -380,10 +358,10 @@ class MODULO:
|
|
|
380
358
|
A QR factorization is used to enforce the orthonormality of the mPOD basis, to compensate
|
|
381
359
|
for the non-ideal frequency response of the filters.
|
|
382
360
|
The option MODE from np.linalg.qr carries out this operation.
|
|
383
|
-
|
|
361
|
+
|
|
384
362
|
:param SAT: Maximum number of modes per scale.
|
|
385
363
|
Only used for mPOD (max number of modes per scale)
|
|
386
|
-
|
|
364
|
+
|
|
387
365
|
:param dt: float
|
|
388
366
|
temporal step
|
|
389
367
|
|
|
@@ -399,7 +377,7 @@ class MODULO:
|
|
|
399
377
|
print('Computing correlation matrix D matrix...')
|
|
400
378
|
self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS,
|
|
401
379
|
self.MEMORY_SAVING,
|
|
402
|
-
self.FOLDER_OUT, D=self.Dstar)
|
|
380
|
+
self.FOLDER_OUT, self.SAVE_K, D=self.Dstar)
|
|
403
381
|
|
|
404
382
|
if self.MEMORY_SAVING:
|
|
405
383
|
self.K = np.load(self.FOLDER_OUT + '/correlation_matrix/k_matrix.npz')['K']
|
|
@@ -432,7 +410,7 @@ class MODULO:
|
|
|
432
410
|
|
|
433
411
|
return Phi_M, Psi_M, Sigma_M
|
|
434
412
|
|
|
435
|
-
def compute_POD_K(self, SAVE_T_POD: bool =
|
|
413
|
+
def compute_POD_K(self, SAVE_T_POD: bool = False):
|
|
436
414
|
"""
|
|
437
415
|
This method computes the Proper Orthogonal Decomposition (POD) of a dataset
|
|
438
416
|
using the snapshot approach, i.e. working on the temporal correlation matrix.
|
|
@@ -440,7 +418,7 @@ class MODULO:
|
|
|
440
418
|
The theoretical background of the POD is briefly recalled here:
|
|
441
419
|
|
|
442
420
|
https://youtu.be/8fhupzhAR_M
|
|
443
|
-
|
|
421
|
+
|
|
444
422
|
:return Psi_P: np.array
|
|
445
423
|
POD Psis
|
|
446
424
|
|
|
@@ -451,10 +429,10 @@ class MODULO:
|
|
|
451
429
|
POD Phis
|
|
452
430
|
"""
|
|
453
431
|
|
|
454
|
-
print('Computing correlation matrix
|
|
432
|
+
print('Computing correlation matrix...')
|
|
455
433
|
self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS,
|
|
456
434
|
self.MEMORY_SAVING,
|
|
457
|
-
self.FOLDER_OUT, D=self.Dstar, weights=self.weights)
|
|
435
|
+
self.FOLDER_OUT, self.SAVE_K, D=self.Dstar, weights=self.weights)
|
|
458
436
|
|
|
459
437
|
if self.MEMORY_SAVING:
|
|
460
438
|
self.K = np.load(self.FOLDER_OUT + '/correlation_matrix/k_matrix.npz')['K']
|
|
@@ -465,29 +443,28 @@ class MODULO:
|
|
|
465
443
|
print("Done.")
|
|
466
444
|
print("Computing Spatial Basis...")
|
|
467
445
|
|
|
468
|
-
if
|
|
469
|
-
print('Computing Phi from D...')
|
|
470
|
-
Phi_P = Spatial_basis_POD(self.D, N_T=self.N_T,
|
|
471
|
-
PSI_P=Psi_P,
|
|
472
|
-
Sigma_P=Sigma_P,
|
|
473
|
-
MEMORY_SAVING=self.MEMORY_SAVING,
|
|
474
|
-
FOLDER_OUT=self.FOLDER_OUT,
|
|
475
|
-
N_PARTITIONS=self.N_PARTITIONS)
|
|
476
|
-
|
|
477
|
-
else: # if not, the memory saving is on and D will not be used. We pass a dummy D
|
|
446
|
+
if self.MEMORY_SAVING: # if self.D is available:
|
|
478
447
|
print('Computing Phi from partitions...')
|
|
479
448
|
Phi_P = Spatial_basis_POD(np.array([1]), N_T=self.N_T,
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
449
|
+
PSI_P=Psi_P,
|
|
450
|
+
Sigma_P=Sigma_P,
|
|
451
|
+
MEMORY_SAVING=self.MEMORY_SAVING,
|
|
452
|
+
FOLDER_OUT=self.FOLDER_OUT,
|
|
453
|
+
N_PARTITIONS=self.N_PARTITIONS)
|
|
485
454
|
|
|
455
|
+
else: # if not, the memory saving is on and D will not be used. We pass a dummy D
|
|
456
|
+
print('Computing Phi from D...')
|
|
457
|
+
Phi_P = Spatial_basis_POD(self.D, N_T=self.N_T,
|
|
458
|
+
PSI_P=Psi_P,
|
|
459
|
+
Sigma_P=Sigma_P,
|
|
460
|
+
MEMORY_SAVING=self.MEMORY_SAVING,
|
|
461
|
+
FOLDER_OUT=self.FOLDER_OUT,
|
|
462
|
+
N_PARTITIONS=self.N_PARTITIONS)
|
|
486
463
|
print("Done.")
|
|
487
464
|
|
|
488
465
|
return Phi_P, Psi_P, Sigma_P
|
|
489
466
|
|
|
490
|
-
def compute_POD_svd(self, SAVE_T_POD: bool =
|
|
467
|
+
def compute_POD_svd(self, SAVE_T_POD: bool = False):
|
|
491
468
|
"""
|
|
492
469
|
This method computes the Proper Orthogonal Decomposition (POD) of a dataset
|
|
493
470
|
using the SVD decomposition. The svd solver is defined by 'svd_solver'.
|
|
@@ -495,7 +472,7 @@ class MODULO:
|
|
|
495
472
|
the SVD must be performed over the entire dataset.
|
|
496
473
|
|
|
497
474
|
https://youtu.be/8fhupzhAR_M
|
|
498
|
-
|
|
475
|
+
|
|
499
476
|
:return Psi_P: np.array
|
|
500
477
|
POD Psis
|
|
501
478
|
|
|
@@ -537,25 +514,25 @@ class MODULO:
|
|
|
537
514
|
def compute_DMD_PIP(self, SAVE_T_DMD: bool = True, F_S=1):
|
|
538
515
|
"""
|
|
539
516
|
This method computes the Dynamic Mode Decomposition of the data
|
|
540
|
-
using the algorithm in https://arxiv.org/abs/1312.0041, which is basically the same as
|
|
541
|
-
the PIP algorithm proposed in https://www.sciencedirect.com/science/article/abs/pii/0167278996001248
|
|
517
|
+
using the algorithm in https://arxiv.org/abs/1312.0041, which is basically the same as
|
|
518
|
+
the PIP algorithm proposed in https://www.sciencedirect.com/science/article/abs/pii/0167278996001248
|
|
542
519
|
See v1 of this paper https://arxiv.org/abs/2001.01971 for more details (yes, reviewers did ask to omit this detail in v2).
|
|
543
|
-
|
|
520
|
+
|
|
544
521
|
:return Phi_D: np.array
|
|
545
522
|
DMD Phis. As for the DFT, these are complex.
|
|
546
523
|
|
|
547
524
|
:return Lambda_D: np.array
|
|
548
525
|
DMD Eigenvalues (of the reduced propagator). These are complex.
|
|
549
|
-
|
|
526
|
+
|
|
550
527
|
:return freqs: np.array
|
|
551
528
|
Frequencies (in Hz, associated to the DMD modes)
|
|
552
|
-
|
|
529
|
+
|
|
553
530
|
:return a0s: np.array
|
|
554
|
-
Initial Coefficients of the Modes
|
|
555
|
-
|
|
531
|
+
Initial Coefficients of the Modes
|
|
532
|
+
|
|
556
533
|
"""
|
|
557
534
|
|
|
558
|
-
# If Memory saving is active, we must load back the data
|
|
535
|
+
# If Memory saving is active, we must load back the data
|
|
559
536
|
if self.MEMORY_SAVING:
|
|
560
537
|
if self.N_T % self.N_PARTITIONS != 0:
|
|
561
538
|
tot_blocks_col = self.N_PARTITIONS + 1
|
|
@@ -622,7 +599,7 @@ class MODULO:
|
|
|
622
599
|
:param L_B: float,
|
|
623
600
|
lenght of the chunks
|
|
624
601
|
:param O_B: float,
|
|
625
|
-
Overlapping between blocks in the chunk
|
|
602
|
+
Overlapping between blocks in the chunk
|
|
626
603
|
:param n_Modes: float,
|
|
627
604
|
number of modes to be computed for each frequency
|
|
628
605
|
:param SAVE_SPOD: bool,
|
|
@@ -630,13 +607,13 @@ class MODULO:
|
|
|
630
607
|
:return Psi_P_hat: np.array
|
|
631
608
|
Spectra of the SPOD Modes
|
|
632
609
|
:return Sigma_P: np.array
|
|
633
|
-
Amplitudes of the SPOD Modes.
|
|
610
|
+
Amplitudes of the SPOD Modes.
|
|
634
611
|
:return Phi_P: np.array
|
|
635
|
-
SPOD Phis
|
|
612
|
+
SPOD Phis
|
|
636
613
|
:return freq: float
|
|
637
|
-
frequency bins for the Spectral POD
|
|
638
|
-
|
|
639
|
-
|
|
614
|
+
frequency bins for the Spectral POD
|
|
615
|
+
|
|
616
|
+
|
|
640
617
|
"""
|
|
641
618
|
if self.D is None:
|
|
642
619
|
D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
@@ -655,8 +632,8 @@ class MODULO:
|
|
|
655
632
|
def compute_SPOD_s(self, F_S, N_O=100, f_c=0.3, n_Modes=10, SAVE_SPOD=True):
|
|
656
633
|
"""
|
|
657
634
|
This method computes the Spectral POD of your data.
|
|
658
|
-
This is the one by Sieber
|
|
659
|
-
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition/DCD8A6EDEFD56F5A9715DBAD38BD461A)
|
|
635
|
+
This is the one by Sieber
|
|
636
|
+
et al (https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/abs/spectral-proper-orthogonal-decomposition/DCD8A6EDEFD56F5A9715DBAD38BD461A)
|
|
660
637
|
|
|
661
638
|
:param F_S: float,
|
|
662
639
|
Sampling Frequency [Hz]
|
|
@@ -664,15 +641,15 @@ class MODULO:
|
|
|
664
641
|
Semi-Order of the diagonal filter.
|
|
665
642
|
Note that the filter order will be 2 N_o +1 (to make sure it is odd)
|
|
666
643
|
:param f_c: float,
|
|
667
|
-
cut-off frequency of the diagonal filter
|
|
644
|
+
cut-off frequency of the diagonal filter
|
|
668
645
|
:param n_Modes: float,
|
|
669
|
-
number of modes to be computed
|
|
646
|
+
number of modes to be computed
|
|
670
647
|
:param SAVE_SPOD: bool,
|
|
671
648
|
If True, MODULO will save the output in self.FOLDER OUT/MODULO_tmp
|
|
672
649
|
:return Psi_P: np.array
|
|
673
650
|
SPOD Psis
|
|
674
651
|
:return Sigma_P: np.array
|
|
675
|
-
SPOD Sigmas.
|
|
652
|
+
SPOD Sigmas.
|
|
676
653
|
:return Phi_P: np.array
|
|
677
654
|
SPOD Phis
|
|
678
655
|
"""
|
|
@@ -681,7 +658,7 @@ class MODULO:
|
|
|
681
658
|
D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
682
659
|
|
|
683
660
|
self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
|
|
684
|
-
self.FOLDER_OUT, D=D)
|
|
661
|
+
self.FOLDER_OUT, self.SAVE_K, D=D)
|
|
685
662
|
|
|
686
663
|
Phi_sP, Psi_sP, Sigma_sP = compute_SPOD_s(D, self.K, F_S, self.N_S, self.N_T, N_O, f_c,
|
|
687
664
|
n_Modes, SAVE_SPOD, self.FOLDER_OUT, self.MEMORY_SAVING,
|
|
@@ -689,7 +666,7 @@ class MODULO:
|
|
|
689
666
|
|
|
690
667
|
else:
|
|
691
668
|
self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
|
|
692
|
-
self.FOLDER_OUT, D=self.D)
|
|
669
|
+
self.FOLDER_OUT, self.SAVE_K, D=self.D)
|
|
693
670
|
|
|
694
671
|
Phi_sP, Psi_sP, Sigma_sP = compute_SPOD_s(self.D, self.K, F_S, self.N_S, self.N_T, N_O, f_c,
|
|
695
672
|
n_Modes, SAVE_SPOD, self.FOLDER_OUT, self.MEMORY_SAVING,
|
|
@@ -759,25 +736,25 @@ class MODULO:
|
|
|
759
736
|
|
|
760
737
|
return Phi_sP, Psi_sP, Sigma_sP
|
|
761
738
|
|
|
762
|
-
def compute_kPOD(self, M_DIST=[1,10],k_m=0.1, cent=True,
|
|
763
|
-
n_Modes=10,alpha=1e-6,metric='rbf',K_out=False):
|
|
739
|
+
def compute_kPOD(self, M_DIST=[1, 10], k_m=0.1, cent=True,
|
|
740
|
+
n_Modes=10, alpha=1e-6, metric='rbf', K_out=False):
|
|
764
741
|
"""
|
|
765
742
|
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
|
|
766
743
|
|
|
767
744
|
The computation of the kernel function is carried out as in https://arxiv.org/pdf/2208.07746.pdf.
|
|
768
745
|
|
|
769
|
-
|
|
746
|
+
|
|
770
747
|
:param M_DIST: array,
|
|
771
748
|
position of the two snapshots that will be considered to
|
|
772
749
|
estimate the minimal k. They should be the most different ones.
|
|
773
750
|
:param k_m: float,
|
|
774
751
|
minimum value for the kernelized correlation
|
|
775
752
|
:param alpha: float
|
|
776
|
-
regularization for K_zeta
|
|
753
|
+
regularization for K_zeta
|
|
777
754
|
:param cent: bool,
|
|
778
755
|
if True, the matrix K is centered. Else it is not
|
|
779
756
|
:param n_Modes: float,
|
|
780
|
-
number of modes to be computed
|
|
757
|
+
number of modes to be computed
|
|
781
758
|
:param metric: string,
|
|
782
759
|
This identifies the metric for the kernel matrix. It is a wrapper to 'pairwise_kernels' from sklearn.metrics.pairwise
|
|
783
760
|
Note that different metrics would need different set of parameters. For the moment, only rbf was tested; use any other option at your peril !
|
|
@@ -786,14 +763,14 @@ class MODULO:
|
|
|
786
763
|
:return Psi_xi: np.array
|
|
787
764
|
kPOD's Psis
|
|
788
765
|
:return Sigma_xi: np.array
|
|
789
|
-
kPOD's Sigmas.
|
|
766
|
+
kPOD's Sigmas.
|
|
790
767
|
:return Phi_xi: np.array
|
|
791
|
-
kPOD's Phis
|
|
768
|
+
kPOD's Phis
|
|
792
769
|
:return K_zeta: np.array
|
|
793
|
-
Kernel Function from which the decomposition is computed.
|
|
770
|
+
Kernel Function from which the decomposition is computed.
|
|
794
771
|
(exported only if K_out=True)
|
|
795
|
-
|
|
796
|
-
|
|
772
|
+
|
|
773
|
+
|
|
797
774
|
"""
|
|
798
775
|
if self.D is None:
|
|
799
776
|
D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
|
|
@@ -811,19 +788,19 @@ class MODULO:
|
|
|
811
788
|
print('Kernel K ready')
|
|
812
789
|
|
|
813
790
|
# Compute the Kernel Matrix
|
|
814
|
-
n_t=np.shape(D)[1]
|
|
791
|
+
n_t = np.shape(D)[1]
|
|
815
792
|
# Center the Kernel Matrix (if cent is True):
|
|
816
|
-
if cent
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
793
|
+
if cent:
|
|
794
|
+
H = np.eye(n_t) - 1 / n_t * np.ones_like(K_zeta)
|
|
795
|
+
K_zeta = H @ K_zeta @ H.T
|
|
796
|
+
print('K_zeta centered')
|
|
820
797
|
# Diagonalize and Sort
|
|
821
798
|
lambdas, Psi_xi = linalg.eigh(K_zeta + alpha * np.eye(n_t), subset_by_index=[n_t - n_Modes, n_t - 1])
|
|
822
799
|
lambdas, Psi_xi = lambdas[::-1], Psi_xi[:, ::-1];
|
|
823
800
|
Sigma_xi = np.sqrt(lambdas);
|
|
824
801
|
print('K_zeta diagonalized')
|
|
825
802
|
# Encode
|
|
826
|
-
# Z_xi=np.diag(Sigma_xi)@Psi_xi.T
|
|
803
|
+
# Z_xi=np.diag(Sigma_xi)@Psi_xi.T
|
|
827
804
|
# We compute the spatial structures as projections of the data
|
|
828
805
|
# onto the Psi_xi!
|
|
829
806
|
R = Psi_xi.shape[1]
|
|
@@ -846,6 +823,6 @@ class MODULO:
|
|
|
846
823
|
print('Phi_xi computed')
|
|
847
824
|
|
|
848
825
|
if K_out:
|
|
849
|
-
|
|
850
|
-
else:
|
|
851
|
-
|
|
826
|
+
return Phi_xi, Psi_xi, Sigma_xi, K_zeta
|
|
827
|
+
else:
|
|
828
|
+
return Phi_xi, Psi_xi, Sigma_xi
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary: MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale Modal Analysis of numerical and experimental data
|
|
2
|
+
Name: modulo_vki
|
|
3
|
+
Version: 2.0.5
|
|
4
|
+
Summary: MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform Multiscale Modal Analysis of numerical and experimental data.
|
|
5
5
|
Home-page: https://github.com/mendezVKI/MODULO/tree/master/modulo_python_package/
|
|
6
6
|
Author: ['R. Poletti', 'L. Schena', 'D. Ninni', 'M. A. Mendez']
|
|
7
7
|
Author-email: mendez@vki.ac.be
|
|
@@ -21,8 +21,6 @@ Requires-Dist: ipython
|
|
|
21
21
|
Requires-Dist: ipython-genutils
|
|
22
22
|
Requires-Dist: ipywidgets
|
|
23
23
|
Requires-Dist: matplotlib
|
|
24
|
-
Requires-Dist: pyvista
|
|
25
|
-
Requires-Dist: imageio
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
modulo_vki/__init__.py
|
|
5
|
+
modulo_vki/modulo.py
|
|
6
|
+
modulo_vki.egg-info/PKG-INFO
|
|
7
|
+
modulo_vki.egg-info/SOURCES.txt
|
|
8
|
+
modulo_vki.egg-info/dependency_links.txt
|
|
9
|
+
modulo_vki.egg-info/requires.txt
|
|
10
|
+
modulo_vki.egg-info/top_level.txt
|
|
11
|
+
modulo_vki/core/__init__.py
|
|
12
|
+
modulo_vki/core/_dft.py
|
|
13
|
+
modulo_vki/core/_dmd_s.py
|
|
14
|
+
modulo_vki/core/_k_matrix.py
|
|
15
|
+
modulo_vki/core/_mpod_space.py
|
|
16
|
+
modulo_vki/core/_mpod_time.py
|
|
17
|
+
modulo_vki/core/_pod_space.py
|
|
18
|
+
modulo_vki/core/_pod_time.py
|
|
19
|
+
modulo_vki/core/_spod_s.py
|
|
20
|
+
modulo_vki/core/_spod_t.py
|
|
21
|
+
modulo_vki/utils/__init__.py
|
|
22
|
+
modulo_vki/utils/_plots.py
|
|
23
|
+
modulo_vki/utils/_utils.py
|
|
24
|
+
modulo_vki/utils/others.py
|
|
25
|
+
modulo_vki/utils/read_db.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
modulo_vki
|
|
@@ -33,10 +33,9 @@ with open(path.join(here, 'README.md'), encoding='utf-8') as readme_file:
|
|
|
33
33
|
|
|
34
34
|
setup(
|
|
35
35
|
name='modulo_vki',
|
|
36
|
-
version='2.0.
|
|
36
|
+
version='2.0.5',
|
|
37
37
|
description="MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform "
|
|
38
|
-
"Multiscale Modal Analysis of numerical and experimental data
|
|
39
|
-
"Orthogonal Decomposition (mPOD).",
|
|
38
|
+
"Multiscale Modal Analysis of numerical and experimental data.",
|
|
40
39
|
long_description=readme,
|
|
41
40
|
long_description_content_type='text/markdown',
|
|
42
41
|
author=["R. Poletti","L. Schena", "D. Ninni", "M. A. Mendez"],
|
|
@@ -67,9 +66,13 @@ setup(
|
|
|
67
66
|
"ipython-genutils",
|
|
68
67
|
"ipywidgets",
|
|
69
68
|
"matplotlib",
|
|
70
|
-
"pyvista",
|
|
71
|
-
"imageio", #to be moved to optional, tutorial only
|
|
72
69
|
],
|
|
70
|
+
extra_requires={
|
|
71
|
+
'tutorials': [
|
|
72
|
+
"pyvista",
|
|
73
|
+
"imageio",
|
|
74
|
+
]
|
|
75
|
+
},
|
|
73
76
|
license='BSD (3-clause)',
|
|
74
77
|
classifiers=[
|
|
75
78
|
'Development Status :: 4 - Beta',
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
from modulo.modulo import MODULO
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
setup.py
|
|
4
|
-
modulo/__init__.py
|
|
5
|
-
modulo/modulo.py
|
|
6
|
-
modulo/core/__init__.py
|
|
7
|
-
modulo/core/_dft.py
|
|
8
|
-
modulo/core/_dmd_s.py
|
|
9
|
-
modulo/core/_k_matrix.py
|
|
10
|
-
modulo/core/_mpod_space.py
|
|
11
|
-
modulo/core/_mpod_time.py
|
|
12
|
-
modulo/core/_pod_space.py
|
|
13
|
-
modulo/core/_pod_time.py
|
|
14
|
-
modulo/core/_spod_s.py
|
|
15
|
-
modulo/core/_spod_t.py
|
|
16
|
-
modulo/utils/__init__.py
|
|
17
|
-
modulo/utils/_plots.py
|
|
18
|
-
modulo/utils/_utils.py
|
|
19
|
-
modulo/utils/others.py
|
|
20
|
-
modulo/utils/read_db.py
|
|
21
|
-
modulo_vki.egg-info/PKG-INFO
|
|
22
|
-
modulo_vki.egg-info/SOURCES.txt
|
|
23
|
-
modulo_vki.egg-info/dependency_links.txt
|
|
24
|
-
modulo_vki.egg-info/requires.txt
|
|
25
|
-
modulo_vki.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
modulo
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|