wawi 0.0.16__py3-none-any.whl → 0.0.17__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.
wawi/modal.py CHANGED
@@ -28,6 +28,44 @@ def maxreal(phi):
28
28
  return phi_max_real
29
29
 
30
30
  def get_mode_sort(lambd, order_fun_dict=None, return_as_dict=True, remove_conjugates=['dynamic'], sort=['dynamic']):
31
+ """
32
+ Sorts and classifies eigenvalues (modes) according to specified criteria.
33
+
34
+ Parameters
35
+ ----------
36
+ lambd : array_like
37
+ Array of eigenvalues to be classified and sorted.
38
+ order_fun_dict : dict or list, optional
39
+ Dictionary mapping mode types (str) to functions that return boolean masks for selecting eigenvalues.
40
+ If a list is provided, only the specified keys from the standard dictionary are used.
41
+ If None (default), a standard set of mode types is used: 'dynamic', 'undamped', 'unstable', 'overdamped'.
42
+ return_as_dict : bool, optional
43
+ If True (default), returns a dictionary mapping mode types to indices of eigenvalues.
44
+ If False, returns a concatenated array of indices.
45
+ remove_conjugates : list or bool, optional
46
+ List of mode types for which to remove every second index (to remove conjugate pairs).
47
+ If True, applies to all mode types. If False or empty list, does not remove conjugates.
48
+ Default is ['dynamic'].
49
+ sort : list or bool, optional
50
+ List of mode types for which to sort indices by the absolute value of eigenvalues.
51
+ If True, applies to all mode types. If False or empty list, does not sort.
52
+ Default is ['dynamic'].
53
+
54
+ Returns
55
+ -------
56
+ ix_dict : dict
57
+ Dictionary mapping mode types to arrays of indices of eigenvalues, if `return_as_dict` is True.
58
+ indices : ndarray
59
+ Concatenated array of indices, if `return_as_dict` is False.
60
+
61
+ Notes
62
+ -----
63
+ This function is useful for modal analysis, where eigenvalues are classified into categories such as
64
+ 'dynamic', 'undamped', 'unstable', and 'overdamped' based on their real and imaginary parts.
65
+
66
+ Docstring is generated using GitHub Copilot.
67
+ """
68
+
31
69
  order_fun_dict_std = {
32
70
  'dynamic': lambda l: np.logical_and(np.imag(l)!=0, np.real(l)<0),
33
71
  'undamped':lambda l: np.real(l)==0,
@@ -61,6 +99,41 @@ def get_mode_sort(lambd, order_fun_dict=None, return_as_dict=True, remove_conjug
61
99
  return np.hstack(list(ix_dict.values()))
62
100
 
63
101
  def sort_modes(lambd, phi=None, order_fun_dict=None, return_as_dict=True, remove_conjugates=['dynamic'], sort=['dynamic']):
102
+ """
103
+ Sorts and organizes modal data (eigenvalues and optionally eigenvectors) according to specified criteria.
104
+
105
+ Parameters
106
+ ----------
107
+ lambd : np.ndarray
108
+ Array of eigenvalues or modal parameters to be sorted.
109
+ phi : np.ndarray, optional
110
+ Array of eigenvectors or mode shapes corresponding to `lambd`. If provided, will be sorted in the same order as `lambd`.
111
+ order_fun_dict : dict, optional
112
+ Dictionary of functions specifying custom sorting orders for the modes.
113
+ return_as_dict : bool, default=True
114
+ If True, returns results as dictionaries keyed by mode type. If False, returns concatenated arrays.
115
+ remove_conjugates : list of str, default=['dynamic']
116
+ List of mode types for which conjugate pairs should be removed.
117
+ sort : list of str, default=['dynamic']
118
+ List of mode types to be sorted.
119
+
120
+ Returns
121
+ -------
122
+ lambd_dict : dict or np.ndarray
123
+ Dictionary of sorted eigenvalues by mode type if `return_as_dict` is True, otherwise a concatenated array of sorted eigenvalues.
124
+ phi_dict : dict or np.ndarray or None
125
+ Dictionary of sorted eigenvectors by mode type if `return_as_dict` is True and `phi` is provided, otherwise a concatenated array of sorted eigenvectors. Returns None if `phi` is not provided.
126
+
127
+ Notes
128
+ -----
129
+ This function relies on `get_mode_sort` to determine the sorting and organization of the modes. Docstring is generated using GitHub Copilot.
130
+
131
+ See also
132
+ --------
133
+ get_mode_sort : Function to classify and sort eigenvalues based on specified criteria.
134
+
135
+ """
136
+
64
137
  ix_dict = get_mode_sort(lambd, order_fun_dict=order_fun_dict, return_as_dict=True, remove_conjugates=['dynamic'], sort=['dynamic'])
65
138
  lambd_dict = dict()
66
139
 
@@ -88,6 +161,34 @@ def sort_modes(lambd, phi=None, order_fun_dict=None, return_as_dict=True, remove
88
161
 
89
162
 
90
163
  def statespace(K, C, M):
164
+ """
165
+ Constructs the state-space matrix A for a second-order system defined by stiffness (K), damping (C), and mass (M) matrices.
166
+
167
+ Parameters
168
+ ----------
169
+ K : ndarray
170
+ Stiffness matrix of shape (n, n).
171
+ C : ndarray
172
+ Damping matrix of shape (n, n).
173
+ M : ndarray
174
+ Mass matrix of shape (n, n).
175
+
176
+ Returns
177
+ -------
178
+ A : ndarray
179
+ State-space matrix of shape (2n, 2n) representing the system in first-order form.
180
+
181
+ Notes
182
+ -----
183
+ The state-space matrix A is constructed for the system:
184
+ M * x'' + C * x' + K * x = 0
185
+ which is converted to first-order form as:
186
+ [x'] = [ 0 I ] [x ]
187
+ [x''] [-M⁻¹K -M⁻¹C] [x']
188
+
189
+ Docstring is generated using GitHub Copilot.
190
+ """
191
+
91
192
  ndofs = np.shape(K)[0]
92
193
  A = np.zeros([2*ndofs, 2*ndofs])
93
194
  A[0:ndofs, ndofs:2*ndofs] = np.eye(ndofs)
@@ -100,7 +201,75 @@ def statespace(K, C, M):
100
201
  def iteig(K, C, M, omega=None, omega_ref=0, input_functions=True, itmax=None, tol=None, keep_full=False,
101
202
  mac_min=0.9, w_initial=None, normalize=False, print_progress=False, print_warnings=True,
102
203
  track_by_psi=True, remove_velocity=True, divergence_protection=True):
204
+ """
205
+ Iterative eigenvalue solver for frequency-dependent state-space systems.
206
+
207
+ Parameters
208
+ ----------
209
+ K : callable or array_like
210
+ Stiffness matrix or function K(omega) returning the stiffness matrix at frequency omega.
211
+ C : callable or array_like
212
+ Damping matrix or function C(omega) returning the damping matrix at frequency omega.
213
+ M : callable or array_like
214
+ Mass matrix or function M(omega) returning the mass matrix at frequency omega.
215
+ omega : array_like or None, optional
216
+ Frequency vector for interpolation if K, C, M are arrays (default is None).
217
+ omega_ref : float, optional
218
+ Reference frequency for initial eigenvalue estimation (default is 0).
219
+ input_functions : bool, optional
220
+ If True, K, C, M are assumed to be functions of omega. If False, they are interpolated from arrays (default is True).
221
+ itmax : int or None, optional
222
+ Maximum number of iterations per mode (default is 15).
223
+ tol : float or None, optional
224
+ Convergence tolerance for frequency (default is 1e-4).
225
+ keep_full : bool, optional
226
+ If True, keep all modes (including velocity DOFs); otherwise, keep only displacement modes (default is False).
227
+ mac_min : float, optional
228
+ Minimum Modal Assurance Criterion (MAC) value for convergence (default is 0.9).
229
+ w_initial : array_like or None, optional
230
+ Initial guess for modal frequencies (default is sorted imaginary parts of reference eigenvalues).
231
+ normalize : bool, optional
232
+ If True, normalize mode shapes to have maximum absolute value of 1 (default is False).
233
+ print_progress : bool, optional
234
+ If True, print progress during iterations (default is False).
235
+ print_warnings : bool, optional
236
+ If True, print warnings for non-convergence or divergence (default is True).
237
+ track_by_psi : bool, optional
238
+ If True, track modes by MAC with reference mode shapes; otherwise, by index (default is True).
239
+ remove_velocity : bool, optional
240
+ If True, remove velocity DOFs from output mode shapes (default is True).
241
+ divergence_protection : bool, optional
242
+ If True, activate divergence protection by averaging frequencies on oscillatory divergence (default is True).
243
+
244
+ Returns
245
+ -------
246
+ lambd : ndarray
247
+ Array of converged eigenvalues (complex).
248
+ q : ndarray
249
+ Array of corresponding eigenvectors (mode shapes).
250
+ not_converged : list of int
251
+ List of mode indices that did not converge within the maximum number of iterations.
252
+
253
+ Notes
254
+ -----
255
+ This function computes the eigenvalues and eigenvectors (modes) of a system with frequency-dependent stiffness (K),
256
+ damping (C), and mass (M) matrices using an iterative approach. It is particularly useful for systems where these matrices
257
+ are functions of frequency (omega)
103
258
 
259
+ - The function assumes that the state-space matrix is constructed by the `statespace` function.
260
+ - The function uses the Modal Assurance Criterion (MAC) to check convergence of mode shapes.
261
+ - If `input_functions` is False, K, C, and M are interpolated using quadratic interpolation.
262
+ - The function can print warnings and progress information if enabled.
263
+
264
+ Docstring is generated using GitHub Copilot.
265
+
266
+ See Also
267
+ --------
268
+ statespace : Function to construct the state-space matrix.
269
+ xmacmat : Function to compute the MAC matrix.
270
+ mac : Function to compute the MAC value between two vectors.
271
+ """
272
+
104
273
  mean_w = False
105
274
 
106
275
  if itmax is None:
@@ -218,6 +387,38 @@ def iteig(K, C, M, omega=None, omega_ref=0, input_functions=True, itmax=None, to
218
387
 
219
388
 
220
389
  def iteig_naive(K, C, M, itmax=None, tol=1e-4):
390
+ """
391
+ Compute eigenvalues and eigenvectors for a parameter-dependent state-space system using an iterative naive approach.
392
+ This function iteratively solves for the eigenvalues and eigenvectors of a system defined by parameter-dependent stiffness (K), damping (C), and mass (M) matrices. The iteration is performed for each mode, updating the frequency parameter until convergence or a maximum number of iterations is reached.
393
+
394
+ Parameters
395
+ ----------
396
+ K : callable
397
+ Function returning the stiffness matrix for a given frequency parameter `w`.
398
+ C : callable
399
+ Function returning the damping matrix for a given frequency parameter `w`.
400
+ M : callable
401
+ Function returning the mass matrix for a given frequency parameter `w`.
402
+ itmax : int, optional
403
+ Maximum number of iterations for convergence (default is 15).
404
+ tol : float, optional
405
+ Convergence tolerance for the frequency parameter (default is 1e-4).
406
+
407
+ Returns
408
+ -------
409
+ lambd : ndarray of complex
410
+ Array of computed eigenvalues of shape (2 * ndofs,).
411
+ q : ndarray of complex
412
+ Array of computed eigenvectors of shape (2 * ndofs, 2 * ndofs).
413
+
414
+ Notes
415
+ -----
416
+ - The function assumes that `K(w)`, `C(w)`, and `M(w)` return square matrices of the same size for any input `w`.
417
+ - The function uses a state-space formulation via the `statespace` function (not defined here).
418
+ - Eigenvalues and eigenvectors are computed for each mode using `numpy.linalg.eig`.
419
+
420
+ Docstring is generated using GitHub Copilot.
421
+ """
221
422
 
222
423
  if itmax is None:
223
424
  itmax = 15
@@ -255,8 +456,67 @@ def iteig_naive(K, C, M, itmax=None, tol=1e-4):
255
456
 
256
457
  def iteig_freq(K, C, M, omega=None, itmax=15, reference_omega=0, input_functions=True,
257
458
  tol=1e-4, keep_full=False, mac_min=0.98, w_initial=None,
258
- normalize=False, print_progress=False, print_warnings=True, divergence_protection=True):
259
-
459
+ normalize=False, print_progress=False, print_warnings=True, divergence_protection=True):
460
+ """
461
+ Iterative eigenvalue analysis for frequency-dependent state-space systems.
462
+
463
+ Parameters
464
+ ----------
465
+ K : callable or ndarray
466
+ Stiffness matrix or function returning the stiffness matrix as a function of frequency.
467
+ C : callable or ndarray
468
+ Damping matrix or function returning the damping matrix as a function of frequency.
469
+ M : callable or ndarray
470
+ Mass matrix or function returning the mass matrix as a function of frequency.
471
+ omega : array_like, optional
472
+ Frequency vector for interpolation if input matrices are not functions. Default is None.
473
+ itmax : int, optional
474
+ Maximum number of iterations per mode. Default is 15.
475
+ reference_omega : float, optional
476
+ Reference frequency for initial guess or interpolation. Default is 0.
477
+ input_functions : bool, optional
478
+ If True, K, C, and M are assumed to be functions of frequency. If False, they are interpolated.
479
+ Default is True.
480
+ tol : float, optional
481
+ Convergence tolerance for frequency and mode shape. Default is 1e-4.
482
+ keep_full : bool, optional
483
+ If True, keep full state-space eigenvectors and eigenvalues. Default is False.
484
+ mac_min : float, optional
485
+ Minimum Modal Assurance Criterion (MAC) for convergence of mode shapes. Default is 0.98.
486
+ w_initial : array_like, optional
487
+ Initial guess for modal frequencies. If None, zeros are used. Default is None.
488
+ normalize : bool, optional
489
+ If True, normalize mode shapes to unit maximum absolute value. Default is False.
490
+ print_progress : bool, optional
491
+ If True, print progress during computation. Default is False.
492
+ print_warnings : bool, optional
493
+ If True, print warnings for non-convergence or divergence. Default is True.
494
+ divergence_protection : bool, optional
495
+ If True, apply protection against oscillatory divergence. Default is True.
496
+
497
+ Returns
498
+ -------
499
+ lambd : ndarray
500
+ Array of converged eigenvalues (complex), sorted by absolute value.
501
+ q : ndarray
502
+ Array of corresponding eigenvectors (modes), sorted to match `lambd`.
503
+ not_converged : list of int
504
+ List of mode indices that did not converge within the maximum number of iterations.
505
+
506
+ Notes
507
+ -----
508
+ This function computes the eigenvalues and eigenvectors (modes) of a system with frequency-dependent
509
+ stiffness (K), damping (C), and mass (M) matrices using an iterative approach. It supports both
510
+ direct matrix input and interpolated functions for frequency-dependent matrices.
511
+
512
+ - The function uses an iterative approach to solve for eigenvalues and eigenvectors of
513
+ frequency-dependent systems, which may not always converge for all modes.
514
+ - If `input_functions` is False, the matrices are interpolated using quadratic interpolation.
515
+ - The Modal Assurance Criterion (MAC) is used to check convergence of mode shapes.
516
+ - Divergence protection can be enabled to handle oscillatory divergence in the iterative process.
517
+
518
+ Docstring is generated using GitHub Copilot.
519
+ """
260
520
  if not input_functions:
261
521
  K = interp1d(omega, K, kind='quadratic', fill_value='extrapolate')
262
522
  C = interp1d(omega, C, kind='quadratic', fill_value='extrapolate')
@@ -397,6 +657,27 @@ def xmacmat(phi1, phi2=None, conjugates=True):
397
657
  return macs
398
658
 
399
659
  def mac(phi1, phi2):
660
+ """
661
+ Calculate the Modal Assurance Criterion (MAC) between two vectors.
662
+
663
+ Parameters
664
+ ----------
665
+ phi1 : array_like
666
+ First mode shape vector.
667
+ phi2 : array_like
668
+ Second mode shape vector.
669
+
670
+ Returns
671
+ -------
672
+ mac_value : float
673
+ The MAC value between `phi1` and `phi2`, ranging from 0 (no correlation) to 1 (perfect correlation).
674
+
675
+ Notes
676
+ -----
677
+ The MAC is a statistical indicator used to quantify the similarity between two mode shapes (vectors).
678
+ It is commonly used in modal analysis to compare experimental and analytical mode shapes. Both `phi1` and `phi2` should be 1-D arrays of the same length.
679
+
680
+ """
400
681
 
401
682
  mac_value = np.real(np.abs(np.dot(phi1.T,phi2))**2 / np.abs((np.dot(phi1.T, phi1) * np.dot(phi2.T, phi2))))
402
683
  return mac_value
@@ -404,6 +685,29 @@ def mac(phi1, phi2):
404
685
 
405
686
 
406
687
  def mcf(phi):
688
+ """
689
+ Calculate the modal complexity factor (MCF) for a set of mode shapes.
690
+
691
+ Parameters
692
+ ----------
693
+ phi : ndarray
694
+ Array of mode shapes. Can be a 1D array of length n (single mode) or a 2D array
695
+ of shape (n, m), where n is the number of degrees of freedom and m is the number
696
+ of modes. Complex values are expected.
697
+
698
+ Returns
699
+ -------
700
+ modal_complexity_factor : ndarray
701
+ 1D array of modal complexity factors, one for each mode.
702
+
703
+ Notes
704
+ -----
705
+ The modal complexity factor is a measure of the coupling between the real and imaginary
706
+ parts of complex mode shapes. It is commonly used in modal analysis to quantify the
707
+ degree of non-proportional damping or mode complexity.
708
+
709
+ Docstring is generated using GitHub Copilot.
710
+ """
407
711
 
408
712
  # Ensure on matrix format
409
713
  if phi.ndim == 1:
@@ -424,10 +728,27 @@ def mcf(phi):
424
728
 
425
729
 
426
730
  def mpc(phi):
427
- # Based on the current paper:
428
- # Pappa, R. S., Elliott, K. B., & Schenk, A. (1993).
429
- # Consistent-mode indicator for the eigensystem realization algorithm.
430
- # Journal of Guidance, Control, and Dynamics, 16(5), 852–858.
731
+ """
732
+ Calculates the Modal Phase Collinearity (MPC) indicator for a set of mode shapes.
733
+
734
+ Parameters
735
+ ----------
736
+ phi : np.ndarray
737
+ Array of mode shapes. Can be a 1D array (single mode) or a 2D array (each column is a mode shape).
738
+
739
+ Returns
740
+ -------
741
+ mpc_val : np.ndarray
742
+ Array of MPC values, one for each mode.
743
+
744
+ Notes
745
+ -----
746
+ The MPC is a measure used to assess the consistency of complex mode shapes, as described in:
747
+ Pappa, R. S., Elliott, K. B., & Schenk, A. (1993). Consistent-mode indicator for the eigensystem realization algorithm.
748
+ Journal of Guidance, Control, and Dynamics, 16(5), 852–858.
749
+
750
+ Docstring is generated using GitHub Copilot.
751
+ """
431
752
 
432
753
  # Ensure on matrix format
433
754
  if phi.ndim == 1:
@@ -454,6 +775,34 @@ def mpc(phi):
454
775
 
455
776
 
456
777
  def scale_phi(phi, scaling):
778
+ """
779
+ Scales each mode (column) of the input matrix `phi` by the corresponding value in `scaling`.
780
+
781
+ Parameters
782
+ ----------
783
+ phi : numpy.ndarray
784
+ A 2D array where each column represents a mode to be scaled.
785
+ scaling : array_like
786
+ A 1D array or list of scaling factors, one for each mode (column) in `phi`.
787
+
788
+ Returns
789
+ -------
790
+ phi_scaled : numpy.ndarray
791
+ A 2D array of the same shape as `phi`, where each column has been multiplied by the corresponding scaling factor.
792
+
793
+ Examples
794
+ --------
795
+ >>> import numpy as np
796
+ >>> phi = np.array([[1, 2], [3, 4]])
797
+ >>> scaling = [10, 0.5]
798
+ >>> scale_phi(phi, scaling)
799
+ array([[10., 1.],
800
+ [30., 2.]])
801
+
802
+ Notes
803
+ -------
804
+ Docstring is generated using GitHub Copilot.
805
+ """
457
806
  phi_scaled = phi*1
458
807
  for mode in range(phi.shape[1]):
459
808
  phi_scaled[:,mode] = phi[:,mode] * scaling[mode]
@@ -461,6 +810,35 @@ def scale_phi(phi, scaling):
461
810
  return phi_scaled
462
811
 
463
812
  def normalize_phi(phi, include_dofs=[0,1,2,3,4,5,6], n_dofs=6):
813
+ """
814
+ Normalizes the columns of the mode shape matrix `phi` based on the maximum absolute value
815
+ of selected degrees of freedom (DOFs).
816
+
817
+ Parameters
818
+ ----------
819
+ phi : np.ndarray
820
+ The mode shape matrix to be normalized. Each column represents a mode.
821
+ include_dofs : list of int, optional
822
+ List of DOF indices to consider when determining the normalization scaling for each mode.
823
+ Default is [0, 1, 2, 3, 4, 5, 6].
824
+ n_dofs : int, optional
825
+ The total number of DOFs per node or element. Default is 6.
826
+
827
+ Returns
828
+ -------
829
+ phi_n : np.ndarray
830
+ The normalized mode shape matrix, with the same shape as `phi`.
831
+ mode_scaling : np.ndarray
832
+ The scaling factors used for normalization, one per mode (column of `phi`).
833
+
834
+ Notes
835
+ -----
836
+ - The normalization is performed such that the maximum absolute value among the selected DOFs
837
+ for each mode is 1, preserving the sign of the maximum value.
838
+ - If the maximum value for a mode is zero, the scaling factor is set to 1 to avoid division by zero.
839
+
840
+ Docstring is generated using GitHub Copilot.
841
+ """
464
842
  phi_n = phi*0
465
843
 
466
844
  phi_for_scaling = np.vstack([phi[dof::n_dofs, :] for dof in include_dofs])
wawi/model/_model.py CHANGED
@@ -14,7 +14,7 @@ from wawi.modal import maxreal, normalize_phi, iteig_freq, iteig
14
14
  from wawi.general import transform_3dmat, eval_3d_fun, fun_const_sum, eval_3d_fun
15
15
  from wawi.structural import freqsim
16
16
  from wawi.tools import print_progress as pp
17
- from wawi.wave import stochastic_linearize, waveaction_fft, harmonic_linearize
17
+ from wawi.wave import stochastic_linearize, harmonic_linearize
18
18
  from wawi.wind import windaction, windaction_static
19
19
  # from wawi.io import import_folder
20
20