modulo-vki 2.1.4__py3-none-any.whl → 2.1.5__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.
@@ -51,9 +51,8 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
51
51
  if verbose:
52
52
  print("Completing Spatial Structures Modes: \n")
53
53
 
54
- for i in tqdm(range(0, R)):
55
- # Normalize the columns of C to get spatial modes
56
- Phi_P[:, i] = PHI_P_SIGMA_P[:, i] / Sigma_P[i]
54
+ Sigma_P[:] = np.linalg.norm(PHI_P_SIGMA_P, axis=0)
55
+ Phi_P = PHI_P_SIGMA_P / Sigma_P
57
56
 
58
57
  else:
59
58
  # We take only the first R modes.
@@ -156,7 +155,7 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
156
155
  R1 = (i - 1) * dim_col
157
156
  R2 = i * dim_col
158
157
 
159
- if (b == tot_blocks_row) and (N_S - dim_row * N_PARTITIONS > 0): # Change here
158
+ if (b == tot_blocks_row) and (N_S - dim_row * N_PARTITIONS > 0):
160
159
  C1 = C2
161
160
  C2 = C1 + (N_S - dim_row * N_PARTITIONS)
162
161
  else:
@@ -169,13 +168,13 @@ def Spatial_basis_POD(D, PSI_P, Sigma_P, MEMORY_SAVING,
169
168
  if rescale:
170
169
  for j in range(R1, R2):
171
170
  jj = j - R1
172
- Sigma_P[jj] = np.linalg.norm(dps[:, jj])
173
- Phi_P = dps[:, jj] / Sigma_P[jj]
171
+ Sigma_P[j] = np.linalg.norm(dps[:, jj])
172
+ Phi_P = dps[:, jj] / Sigma_P[j]
174
173
  np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
175
174
  else:
176
175
  for j in range(R1, R2):
177
176
  jj = j - R1
178
- Phi_P = dps[:, jj] / Sigma_P[j] # Change here
177
+ Phi_P = dps[:, jj] / Sigma_P[j]
179
178
  np.savez(FOLDER_OUT + f"/phi_{j + 1}", phi_p=Phi_P)
180
179
 
181
180
  Phi_P_M = np.zeros((N_S, R))
modulo_vki/modulo.py CHANGED
@@ -660,14 +660,13 @@ class ModuloVKI:
660
660
  Sigma_sP : numpy.ndarray, shape (n_Modes,)
661
661
  Modal energies (eigenvalues of the filtered covariance).
662
662
  """
663
- if self.D is None:
664
- D = np.load(self.FOLDER_OUT + '/MODULO_tmp/data_matrix/database.npz')['D']
665
- else:
666
- D = self.D
667
-
663
+
668
664
  self.K = CorrelationMatrix(self.N_T, self.N_PARTITIONS, self.MEMORY_SAVING,
669
- self.FOLDER_OUT, self.SAVE_K, D=D)
670
-
665
+ self.FOLDER_OUT, self.SAVE_K, D=self.Dstar)
666
+
667
+ if self.MEMORY_SAVING:
668
+ self.K = np.load(self.FOLDER_OUT + '/correlation_matrix/k_matrix.npz')['K']
669
+
671
670
  # additional step: diagonal spectral filter of K
672
671
  K_F = spectral_filter(self.K, N_o=N_O, f_c=f_c)
673
672
 
@@ -675,7 +674,7 @@ class ModuloVKI:
675
674
  Psi_P, Sigma_P = Temporal_basis_POD(K_F, SAVE_SPOD, self.FOLDER_OUT, n_Modes)
676
675
 
677
676
  # but with a normalization aspect to handle the non-orthogonality of the SPOD modes
678
- Phi_P = Spatial_basis_POD(D, N_T=self.K.shape[0],
677
+ Phi_P = Spatial_basis_POD(self.D, N_T=self.K.shape[0],
679
678
  PSI_P=Psi_P, Sigma_P=Sigma_P,
680
679
  MEMORY_SAVING=self.MEMORY_SAVING,
681
680
  FOLDER_OUT=self.FOLDER_OUT,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modulo_vki
3
- Version: 2.1.4
3
+ Version: 2.1.5
4
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']
@@ -48,7 +48,8 @@ While the discontinued MATLAB version of MODULO is accessible in the “Old_Matl
48
48
  it is no longer maintained. The latest decomposition techniques are exclusively available in the current Python version (`Poletti et al. (2024) <https://joss.theoj.org/papers/10.21105/joss.06753>`_).
49
49
 
50
50
  As a part of the MODULO project, we provide a series of lectures on data-driven modal decomposition, and its applications.
51
- These are available at the `MODULO YouTube channel <https://www.youtube.com/@modulompod5682>`_.
51
+ These are available at the `MODULO YouTube channel <https://www.youtube.com/@modulompod5682>`_.
52
+ The full package documentation can be found at: `MODULO ReadTheDocs <https://lorenzoschena.github.io/MODULO/intro.html>`_.
52
53
 
53
54
  .. contents:: Table of contents
54
55
 
@@ -1,5 +1,5 @@
1
1
  modulo_vki/__init__.py,sha256=AOjmeFjHj69m45iZzfTHM6-SLUelgKdGeu3VdSg9hIo,39
2
- modulo_vki/modulo.py,sha256=bpevQHd6fGwd1fIn3VSEHKgBxc9oa1Q8Fpr_qzVeqA0,38517
2
+ modulo_vki/modulo.py,sha256=XbPyzd5sugYHtgKsPZ220BoWT0L3iqi-JDYXlcFTu0g,38478
3
3
  modulo_vki/modulo_old.py,sha256=3r_BBYQfbmZWGDyPukyJTVYVVcAVuEE0CmREEJkzsxU,59413
4
4
  modulo_vki/core/__init__.py,sha256=y9mIqtmSg3o8TXMqFxoiMCoMSle6mK0LBrvNJCVM1Zg,226
5
5
  modulo_vki/core/_dft.py,sha256=W98vC4HR1fivZjYRQXrFKV7RBa-O3RSRwq-nCKoxqjQ,4374
@@ -11,7 +11,7 @@ modulo_vki/core/_pod_space.py,sha256=A3dfv4Nzs9fx3qwOdlJR5HwyyfI-QcVer8P83xqa_C4
11
11
  modulo_vki/core/_pod_time.py,sha256=JtiFGYFV-tBKTWHWHW8zynMoLt2q8bD1bd1LP9pyvjo,2169
12
12
  modulo_vki/core/_spod_s.py,sha256=rxXSsNdSTLv3sjvlUErw3xjHk0eF8H7IkSJr5nMQ8Vo,4149
13
13
  modulo_vki/core/_spod_t.py,sha256=csftCPRSqs-OghQa8l0mRDL7cy5eXXSCnW8O4pnXTCY,3866
14
- modulo_vki/core/spatial_structures.py,sha256=65xh3zD3ekjRYUeRd2KcOYzPurpua7qDf0AysY-X8hE,14712
14
+ modulo_vki/core/spatial_structures.py,sha256=XRdhcZM0TdUW0PRaRKU8BU3u74H36WGEIx1YHLjrPs4,14620
15
15
  modulo_vki/core/temporal_structures.py,sha256=0DQEdE9ssTnnfIC86VZPsNlym6fsjRAboPHHnv-9CI4,10645
16
16
  modulo_vki/core/utils.py,sha256=Ac9Im9knlbZRByP6Qgv-LCDt5zEC8PbyidqXzVdeYtQ,17889
17
17
  modulo_vki/utils/__init__.py,sha256=F5yy5R19dONK9oaBEpKzylorVJNcjT2kiJ5Og-ZX1ek,94
@@ -19,11 +19,8 @@ modulo_vki/utils/_plots.py,sha256=m43t08cVq-TY0BW0YPqT71hN-54hBphIYKZEn8Kw16E,14
19
19
  modulo_vki/utils/_utils.py,sha256=WFD7nwjSzVHpevVwTEvMdjAmcbeqwoXT9M48tIIniJw,14355
20
20
  modulo_vki/utils/others.py,sha256=9yZzD0_rZIOWYjV2Hbi74N5oXEYct7o5h9ZjNkmxHPw,17338
21
21
  modulo_vki/utils/read_db.py,sha256=lJFauxJxS0_mYoxrbn-43UqZjOkr-qb9f6RTUq4IxZU,15149
22
- modulo_vki-2.1.4.dist-info/licenses/LICENSE,sha256=5TivriXFErrYrJgBq3M72kHNHqtSiCft3xESM1zHc0k,1091
23
- modulo_vki_2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- modulo_vki_2/modulo.py,sha256=JhQFHsoyQ3Bp0FZ80M0WOq9hYMVkMV1lMoEnxwf2Vng,7861
25
- modulo_vki_2/utils.py,sha256=9Zwikg7x7MtvIK1Om1JKKnCH1OQd0nf3m76APjOIyas,858
26
- modulo_vki-2.1.4.dist-info/METADATA,sha256=5S4EkRJbdLMriyOTNqb3jjcxPj8SEaglfHGbmXWYNn8,16733
27
- modulo_vki-2.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- modulo_vki-2.1.4.dist-info/top_level.txt,sha256=xP1gbt8FGvhIM5-zQagZXO7ut-yjUI4cXuM2GeypNuw,24
29
- modulo_vki-2.1.4.dist-info/RECORD,,
22
+ modulo_vki-2.1.5.dist-info/licenses/LICENSE,sha256=5TivriXFErrYrJgBq3M72kHNHqtSiCft3xESM1zHc0k,1091
23
+ modulo_vki-2.1.5.dist-info/METADATA,sha256=J0fY2NItK7F6s1XfraHXgbRKjjxa5EIMstXUUoFs7ns,16857
24
+ modulo_vki-2.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
25
+ modulo_vki-2.1.5.dist-info/top_level.txt,sha256=4PA4AmafKU6M7us7gvt_Q976Khx3qjNUEThRRM5zxeA,11
26
+ modulo_vki-2.1.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ modulo_vki
@@ -1,2 +0,0 @@
1
- modulo_vki
2
- modulo_vki_2
modulo_vki_2/__init__.py DELETED
File without changes
modulo_vki_2/modulo.py DELETED
@@ -1,187 +0,0 @@
1
- import numpy as np
2
- import os
3
-
4
-
5
-
6
- class ModuloVKI:
7
- """
8
- MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute
9
- to perform Multiscale Modal Analysis using Multiscale Proper Orthogonal Decomposition (mPOD)
10
- on numerical and experimental data.
11
-
12
- References
13
- ----------
14
- - Theoretical foundation:
15
- https://arxiv.org/abs/1804.09646
16
-
17
- - MODULO framework presentation:
18
- https://arxiv.org/pdf/2004.12123.pdf
19
-
20
- - Hands-on tutorial videos:
21
- https://youtube.com/playlist?list=PLEJZLD0-4PeKW6Ze984q08bNz28GTntkR
22
-
23
- Notes
24
- -----
25
- MODULO operations assume the dataset is uniformly spaced in both space
26
- (Cartesian grid) and time. For non-cartesian grids, the user must
27
- provide a weights vector `[w_1, w_2, ..., w_Ns]` where `w_i = area_cell_i / area_grid`.
28
- """
29
-
30
- def __init__(self,
31
- data: np.ndarray,
32
- N_PARTITIONS: int = 1,
33
- FOLDER_OUT: str = './',
34
- SAVE_K: bool = False,
35
- N_T: int = 100,
36
- N_S: int = 200,
37
- n_Modes: int = 10,
38
- dtype: str = 'float32',
39
- eig_solver: str = 'eigh',
40
- svd_solver: str = 'svd_sklearn_truncated',
41
- weights: np.ndarray = np.array([])):
42
- """
43
- Initialize the MODULO analysis.
44
-
45
- Parameters
46
- ----------
47
- data : np.ndarray
48
- Data matrix of shape (N_S, N_T) to factorize. If not yet formatted, use the `ReadData`
49
- method provided by MODULO. When memory saving mode (N_PARTITIONS > 1) is active,
50
- set this parameter to None and use prepared partitions instead.
51
-
52
- N_PARTITIONS : int, default=1
53
- Number of partitions used for memory-saving computation. If set greater than 1,
54
- data must be partitioned in advance and `data` set to None.
55
-
56
- FOLDER_OUT : str, default='./'
57
- Directory path to store output (Phi, Sigma, Psi matrices) and intermediate
58
- calculation files (e.g., partitions, correlation matrix).
59
-
60
- SAVE_K : bool, default=False
61
- Whether to store the correlation matrix K to disk in
62
- `FOLDER_OUT/correlation_matrix`.
63
-
64
- N_T : int, default=100
65
- Number of temporal snapshots. Mandatory when using partitions (N_PARTITIONS > 1).
66
-
67
- N_S : int, default=200
68
- Number of spatial grid points. Mandatory when using partitions (N_PARTITIONS > 1).
69
-
70
- n_Modes : int, default=10
71
- Number of modes to compute.
72
-
73
- dtype : str, default='float32'
74
- Data type for casting input data.
75
-
76
- eig_solver : str, default='eigh'
77
- Solver for eigenvalue decomposition.
78
-
79
- svd_solver : str, default='svd_sklearn_truncated'
80
- Solver for Singular Value Decomposition (SVD).
81
-
82
- weights : np.ndarray, default=np.array([])
83
- Weights vector `[w_1, w_2, ..., w_Ns]` to account for non-uniform spatial grids.
84
- Defined as `w_i = area_cell_i / area_grid`. Leave empty for uniform grids.
85
- """
86
-
87
- print("MODULO (MODal mULtiscale pOd) is a software developed at the von Karman Institute to perform "
88
- "data driven modal decomposition of numerical and experimental data. \n")
89
-
90
- if not isinstance(data, np.ndarray) and N_PARTITIONS == 1:
91
- raise TypeError(
92
- "Please check that your database is in an numpy array format. If D=None, then you must have memory saving (N_PARTITIONS>1)")
93
-
94
- if N_PARTITIONS > 1:
95
- self.MEMORY_SAVING = True
96
- else:
97
- self.MEMORY_SAVING = False
98
-
99
- # Assign the number of modes
100
- self.n_Modes = n_Modes
101
- # If particular needs, override choice for svd and eigen solve
102
- self.svd_solver = svd_solver.lower()
103
- self.eig_solver = eig_solver.lower()
104
- possible_svds = ['svd_numpy', 'svd_scipy_sparse', 'svd_sklearn_randomized', 'svd_sklearn_truncated']
105
- possible_eigs = ['svd_sklearn_randomized', 'eigsh', 'eigh']
106
-
107
- if self.svd_solver not in possible_svds:
108
- raise NotImplementedError("The requested SVD solver is not implemented. Please pick one of the following:"
109
- "which belongs to: \n {}".format(possible_svds))
110
-
111
- if self.eig_solver not in possible_eigs:
112
- raise NotImplementedError("The requested EIG solver is not implemented. Please pick one of the following: "
113
- " \n {}".format(possible_eigs))
114
-
115
- # if N_PARTITIONS >= self.N_T:
116
- # raise AttributeError("The number of requested partitions is greater of the total columns (N_T). Please,"
117
- # "try again.")
118
-
119
- self.N_PARTITIONS = N_PARTITIONS
120
- self.FOLDER_OUT = FOLDER_OUT
121
- self.SAVE_K = SAVE_K
122
-
123
- if self.MEMORY_SAVING:
124
- os.makedirs(self.FOLDER_OUT, exist_ok=True)
125
-
126
- # Load the data matrix
127
- if isinstance(data, np.ndarray):
128
- # Number of points in time and space
129
- self.N_T = data.shape[1]
130
- self.N_S = data.shape[0]
131
- # Check the data type
132
- self.D = data.astype(dtype)
133
- else:
134
- self.D = None # D is never saved when N_partitions >1
135
- self.N_S = N_S # so N_S and N_t must be given as parameters of modulo
136
- self.N_T = N_T
137
-
138
- '''If the grid is not cartesian, ensure inner product is properly defined using weights.'''
139
-
140
- if weights.size == 0:
141
- print('Modulo assumes you have a uniform grid. If not, please provide weights as parameters.')
142
- else:
143
- if len(weights) == self.N_S:
144
- print("The weights you have input have the size of the columns of D \n"
145
- "MODULO has considered that you have already duplicated the dimensions of the weights "
146
- "to match the dimensions of the D columns \n")
147
- self.weights = weights
148
- elif len(weights) == 2 * self.N_S:
149
- print("Assuming 2D domain. Automatically duplicating the weights to match the dimension of the D columns \n")
150
- self.weights = np.concatenate((weights, weights))
151
- else:
152
- raise AttributeError("Make sure the size of the weight array is twice smaller than the size of D")
153
-
154
- if isinstance(data, np.ndarray):
155
- # Apply the weights only if D exist.
156
- # If not (i.e. N_partitions >1), weights are applied in _k_matrix.py when loading partitions of D
157
- self.Dstar = np.transpose(np.transpose(self.D) * np.sqrt(self.weights))
158
- else:
159
- self.Dstar = None
160
-
161
- def compute(
162
- self,
163
- kind: str,
164
- **engine_kwargs
165
- ) -> tuple:
166
- """
167
- Unified entry point for all decompositions: POD, SPOD, kPOD, DMD, DFT.
168
- Any engine‐specific parameters (e.g. F_S, L_B, gamma…) can be passed here
169
- and will be forwarded to the chosen engine’s constructor.
170
- """
171
- engine_cls = self._engines.get(kind.lower())
172
- if engine_cls is None:
173
- raise ValueError(f"Unknown decomposition '{kind}'")
174
-
175
- # pick the right data array
176
- D_use = self.Dstar # or self.D if you want un-weighted
177
-
178
- engine = engine_cls(
179
- D=D_use,
180
- folder_out=self.FOLDER_OUT,
181
- save_k=self.SAVE_K,
182
- memory_saving=self.MEMORY_SAVING,
183
- n_partitions=self.N_PARTITIONS,
184
- **engine_kwargs
185
- )
186
- return engine.run()
187
-
modulo_vki_2/utils.py DELETED
@@ -1,22 +0,0 @@
1
- import numpy as np
2
-
3
- def apply_weights(D: np.ndarray, weights: np.ndarray) -> np.ndarray:
4
- """
5
- If `weights` is empty, return D unchanged.
6
- If `weights` has length n_s, assume 1D grid and tile automatically.
7
- If `weights` has length 2*n_s, assume 2D grid and use directly.
8
- Returns D_star = D * sqrt(w) applied column-wise.
9
- """
10
- n_s, n_t = D.shape
11
- if weights.size == 0:
12
- return D
13
- w = np.asarray(weights, dtype=D.dtype)
14
- if w.size == n_s:
15
- # 1D grid: automatically broadcast each weight to full time series
16
- w_full = np.repeat(w, n_t//n_s) # or tile as needed for time dims
17
- elif w.size == 2*n_s:
18
- w_full = w
19
- else:
20
- raise ValueError(f"weights must be length {n_s} or {2*n_s}, got {w.size}")
21
- # apply weights: scale each row i by sqrt(w_full[i])
22
- return (D.T * np.sqrt(w_full)).T