wawi 0.0.16__py3-none-any.whl → 0.0.18__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/wind.py CHANGED
@@ -32,12 +32,43 @@ beaufort_dict = {
32
32
  }
33
33
 
34
34
  def get_beaufort(U0):
35
+ """Get the Beaufort scale for a given wind speed U0."""
36
+
35
37
  return [key for key in beaufort_dict if inrange(U0, beaufort_dict[key])][0]
36
38
 
37
39
  def inrange(num, rng):
40
+ """Check if a number is in a given range."""
38
41
  return num<=np.max(rng) and num>=np.min(rng)
39
42
 
40
43
  class LoadCoefficients:
44
+ """
45
+ Class to hold the load coefficients for a aerodynamic section
46
+
47
+ Attributes
48
+ ----------
49
+ Cd : float
50
+ Drag coefficient
51
+ dCd : float
52
+ Derivative of drag coefficient with respect to reduced velocity
53
+ Cl : float
54
+ Lift coefficient
55
+ dCl : float
56
+ Derivative of lift coefficient with respect to reduced velocity
57
+ Cm : float
58
+ Moment coefficient
59
+ dCm : float
60
+ Derivative of moment coefficient with respect to reduced velocity
61
+ fill_empty : bool
62
+ If True, fill empty attributes with zeros
63
+
64
+ Methods
65
+ -------
66
+ fill_empty_with_zeros : None
67
+ Fills empty attributes with zeros
68
+ to_dict : dict
69
+ Converts the LoadCoefficients object to a dictionary
70
+
71
+ """
41
72
  keys = ['Cd', 'Cm', 'Cl', 'dCd', 'dCm', 'dCl']
42
73
 
43
74
  def __repr__(self):
@@ -58,14 +89,54 @@ class LoadCoefficients:
58
89
  self.fill_empty_with_zeros()
59
90
 
60
91
  def fill_empty_with_zeros(self):
92
+ """
93
+ Fills empty attributes with zeros.
94
+ """
95
+ # Fill empty attributes with zeros
61
96
  for key in self.keys:
62
97
  if getattr(self, key) is None:
63
98
  setattr(self, key, 0)
64
99
 
65
100
  def to_dict(self):
101
+ """
102
+ Converts the LoadCoefficients object to a dictionary.
103
+
104
+ Returns
105
+ -------
106
+ dict
107
+ A dictionary with the keys and values of the LoadCoefficients object.
108
+ """
109
+
66
110
  return {key: getattr(self, key) for key in self.keys}
67
111
 
68
112
  class ADs:
113
+ """
114
+ Class to hold the aerodynamic derivatives (ADs) for a given aerodynamic section.
115
+
116
+ Attributes
117
+ ----------
118
+ type : str
119
+ Type of the aerodynamic section
120
+ P1, P2, P3, P4, P5, P6 : function
121
+ Functions representing the aerodynamic derivatives for the section, related to horizontal motion of the section.
122
+ H1, H2, H3, H4, H5, H6 : function
123
+ Functions representing the aerodynamic derivatives for the section, related to vertical motion of the section.
124
+ A1, A2, A3, A4, A5, A6 : function
125
+ Functions representing the aerodynamic derivatives for the section, related to twisting motion of the section.
126
+
127
+ Methods
128
+ -------
129
+ plot : None
130
+ Plots the aerodynamic derivatives for the section
131
+ to_dict : dict
132
+ Converts the ADs object to a dictionary
133
+ evaluate_all : dict
134
+ Evaluates all aerodynamic derivatives for a given reduced velocity
135
+ evaluate : dict
136
+ Evaluates a specific aerodynamic derivative for a given reduced velocity
137
+
138
+ """
139
+
69
140
  ad_keys = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6',
70
141
  'H1', 'H2', 'H3', 'H4', 'H5', 'H6',
71
142
  'A1', 'A2', 'A3', 'A4', 'A5', 'A6']
@@ -103,13 +174,47 @@ class ADs:
103
174
  self.A6 = A6
104
175
 
105
176
  def plot(self, v=np.arange(0,5,0.01), **kwargs):
177
+ """
178
+ Plots the aerodynamic derivatives for the section.
179
+
180
+ Parameters
181
+ ----------
182
+ v : array-like
183
+ Reduced velocity values for which to plot the aerodynamic derivatives.
184
+ **kwargs : keyword arguments
185
+ Additional keyword arguments to pass to the `plot_ads` function.
186
+ """
187
+
106
188
  return plot_ads(self.to_dict(), v, **kwargs)
107
189
 
108
190
 
109
191
  def to_dict(self):
192
+ """
193
+ Converts the ADs object to a dictionary.
194
+
195
+ Returns
196
+ -------
197
+ dict
198
+ A dictionary with the keys and values of the ADs object.
199
+ """
200
+
110
201
  return {key: getattr(self, key) for key in self.ad_keys}
111
202
 
112
203
  def evaluate_all(self, v):
204
+ """
205
+ Evaluates all aerodynamic derivatives for a given reduced velocity.
206
+
207
+ Parameters
208
+ ----------
209
+ v : float
210
+ Reduced velocity for which to evaluate the aerodynamic derivatives.
211
+
212
+ Returns
213
+ -------
214
+ dict
215
+ A dictionary with the evaluated aerodynamic derivatives.
216
+ """
217
+
113
218
  AD_evaluated = dict()
114
219
  for key in self.ad_keys:
115
220
  AD_evaluated[key] = getattr(self, key)(v)
@@ -118,12 +223,36 @@ class ADs:
118
223
 
119
224
 
120
225
  def evaluate(self, key, v):
226
+ """
227
+ Evaluates a specific aerodynamic derivative for a given reduced velocity.
228
+
229
+ Parameters
230
+ ----------
231
+ key : str
232
+
233
+ The key of the aerodynamic derivative to evaluate.
234
+ v : float
235
+ Reduced velocity for which to evaluate the aerodynamic derivative.
236
+
237
+ Returns
238
+ -------
239
+ float
240
+ The evaluated aerodynamic derivative.
241
+ """
242
+
121
243
  AD_evaluated = getattr(self, key)(v)
122
244
 
123
245
  return AD_evaluated
124
246
 
125
247
  def flatplate_ads():
126
-
248
+ """Flat plate aerodynamic derivatives.
249
+
250
+ Returns
251
+ -------
252
+ dict
253
+ A dictionary with the aerodynamic derivatives for a flat plate.
254
+
255
+ """
127
256
  ad_dict = dict()
128
257
 
129
258
  def F(v):
@@ -175,8 +304,29 @@ def flatplate_ads():
175
304
 
176
305
 
177
306
  def quasisteady_ads(D, B, load_coefficients):
178
- # Assuming load coeffs are normalized wrt. both D (Cd) and B (Cl and Cm) and ADs are
179
- # normalized using B only.
307
+ """Quasi-steady aerodynamic derivatives.
308
+
309
+ Parameters
310
+ ----------
311
+ D : float
312
+ Diameter of the section
313
+ B : float
314
+ Width of the section
315
+ load_coefficients : LoadCoefficients or dict
316
+ Load coefficients for the section. If a dictionary is provided, it should contain
317
+ the keys 'Cd', 'dCd', 'Cl', 'dCl', 'Cm', and 'dCm' with corresponding values.
318
+ If a LoadCoefficients object is provided, it should have the same attributes.
319
+ Returns
320
+ -------
321
+ dict
322
+ A dictionary with the aerodynamic derivatives for the section.
323
+
324
+ Notes
325
+ -----
326
+ The aerodynamic derivatives are calculated based on the load coefficients provided.
327
+ The load coefficients should be normalized with respect to both D (Cd) and B (Cl and Cm).
328
+ ADs are normalized using B only.
329
+ """
180
330
 
181
331
  if type(load_coefficients)==dict:
182
332
  Cd = load_coefficients['Cd']
@@ -205,6 +355,36 @@ def quasisteady_ads(D, B, load_coefficients):
205
355
 
206
356
  def compute_aero_matrices(U, AD, B, elements, T_wind, phi,
207
357
  omega_reduced=None, print_progress=False, rho=1.225):
358
+ """Compute the aerodynamic matrices for a given set of elements.
359
+
360
+ Parameters
361
+ ----------
362
+ U : float or function
363
+ Wind speed or function to calculate wind speed at a given point.
364
+ AD : ADs
365
+ Aerodynamic derivatives for the section.
366
+ B : float
367
+ Width of the section.
368
+ elements : list
369
+ List of elements for which to compute the aerodynamic matrices.
370
+ T_wind : np.ndarray
371
+ Transformation matrix from global to wind coordinates.
372
+ phi : np.ndarray
373
+ Mode shapes for the elements.
374
+ omega_reduced : np.ndarray, optional
375
+ Reduced frequencies for which to compute the aerodynamic matrices.
376
+ print_progress : bool, optional
377
+ If True, print progress of the computation.
378
+ rho : float, optional
379
+ Air density, default is 1.225 kg/m^3.
380
+
381
+ Returns
382
+ -------
383
+ Kae : np.ndarray
384
+ Aerodynamic stiffness matrix.
385
+ Cae : np.ndarray
386
+ Aerodynamic damping matrix.
387
+ """
208
388
 
209
389
  if omega_reduced is None:
210
390
  omega_reduced = np.linspace(0.015, 2.0, 75)
@@ -248,6 +428,37 @@ def compute_aero_matrices(U, AD, B, elements, T_wind, phi,
248
428
  def compute_aero_matrices_sets(U, AD, B, elements, T_wind, phi_dict,
249
429
  omega_reduced=None, omega=None, print_progress=False, sets=None):
250
430
 
431
+ """Compute the aerodynamic matrices for a given set of elements.
432
+
433
+ Parameters
434
+ ----------
435
+ U : float or function
436
+ Wind speed or function to calculate wind speed at a given point.
437
+ AD : dict
438
+ Dictionary of aerodynamic derivatives for the section.
439
+ B : float
440
+ Width of the section.
441
+ elements : dict
442
+ Dictionary of elements (BEEF elements) for which to compute the aerodynamic matrices.
443
+ T_wind : np.ndarray
444
+ Transformation matrix from global to wind coordinates.
445
+ phi : np.ndarray
446
+ Mode shapes for the elements.
447
+ omega_reduced : np.ndarray, optional
448
+ Reduced frequencies for which to compute the aerodynamic matrices.
449
+ print_progress : bool, optional
450
+ If True, print progress of the computation.
451
+ sets : list, optional
452
+ List of sets of elements for which to compute the aerodynamic matrices.
453
+
454
+ Returns
455
+ -------
456
+ Kae : np.ndarray
457
+ Aerodynamic stiffness matrix.
458
+ Cae : np.ndarray
459
+ Aerodynamic damping matrix.
460
+ """
461
+
251
462
  if sets is None:
252
463
  sets = elements.keys()
253
464
 
@@ -306,32 +517,6 @@ def compute_aero_matrices_sets(U, AD, B, elements, T_wind, phi_dict,
306
517
 
307
518
  return Kae, Cae
308
519
 
309
- def mvregress_ads(beta):
310
- ad_dict = dict()
311
- ad_keys = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6',
312
- 'H1', 'H2', 'H3', 'H4', 'H5', 'H6',
313
- 'A1', 'A2', 'A3', 'A4', 'A5', 'A6']
314
-
315
- for key in ad_keys:
316
- ad_dict[key] = lambda v, key=key: 0
317
-
318
- #TODO: FINALIZE, NOT FINISHED
319
-
320
- return ad_dict
321
-
322
-
323
- def f_rf_fun_legacy(a, d, v):
324
- N = len(a)
325
- f = 0j
326
- for l in range(0, 3):
327
- f = f + a[l] * (1j/v)**l
328
-
329
- for l in range(0, N-3):
330
- f = f + a[l+2]*(1j/v) / ((1j/v + d[l]))
331
-
332
- f = f*v**2
333
- return f
334
-
335
520
 
336
521
  def f_rf_fun(a, d, v):
337
522
  N = len(a)
@@ -349,6 +534,29 @@ def f_rf_fun(a, d, v):
349
534
 
350
535
 
351
536
  def rf_ads(a, d):
537
+ """
538
+ Function to compute the aerodynamic derivatives for a given set of reduced frequencies using rational functions.
539
+
540
+ Parameters
541
+ ----------
542
+ a : list
543
+ List of coefficients for the rational function, assumed in the order of
544
+ P1, P2, P3, P4, P5, P6, H1, H2, H3, H4, H5, H6, A1, A2, A3, A4, A5, A6.
545
+ d : list
546
+ List of poles for the rational function, assumed in the order of
547
+ P1, P2, P3, P4, P5, P6, H1, H2, H3, H4, H5, H6, A1, A2, A3, A4, A5, A6.
548
+
549
+ Returns
550
+ -------
551
+ dict
552
+ A dictionary with the aerodynamic derivatives for the section.
553
+
554
+ Notes
555
+ -----
556
+ The aerodynamic derivatives are calculated based on the coefficients and poles provided.
557
+ The coefficients should be normalized with respect to both D (Cd) and B (Cl and Cm).
558
+
559
+ """
352
560
  # B assumed to be implicitly included in RF factors
353
561
  ad_dict = dict()
354
562
  ad_keys = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6',
@@ -375,6 +583,30 @@ def rf_ads(a, d):
375
583
 
376
584
 
377
585
  def distribute_to_dict(prefix, array, count_start=1):
586
+ """
587
+ Distributes a list of arrays to a dictionary with keys based on the prefix and index.
588
+
589
+ Parameters
590
+ ----------
591
+ prefix : str
592
+ Prefix for the keys in the dictionary.
593
+ array : list
594
+ List of arrays to be distributed.
595
+ count_start : int, optional
596
+ Starting index for the keys in the dictionary. Default is 1.
597
+
598
+ Returns
599
+ -------
600
+ dict
601
+ A dictionary with keys based on the prefix and index, and values from the input array.
602
+
603
+ Notes
604
+ -----
605
+ The keys in the dictionary are formed by concatenating the prefix with the index of the array.
606
+
607
+ Docstring is generated by GitHub Copilot.
608
+
609
+ """
378
610
  array_dict = dict()
379
611
  for ix,array_i in enumerate(array):
380
612
  key = prefix + str(ix+count_start)
@@ -384,6 +616,25 @@ def distribute_to_dict(prefix, array, count_start=1):
384
616
 
385
617
 
386
618
  def distribute_multi_to_dict(prefixes, arrays):
619
+ """
620
+ Distributes a list of arrays to a dictionary with keys based on the prefix and index.
621
+
622
+ Parameters
623
+ ----------
624
+ prefixes : list
625
+ List of prefixes for the keys in the dictionary.
626
+ arrays : list
627
+ List of arrays to be distributed.
628
+
629
+ Returns
630
+ -------
631
+ dict
632
+ A dictionary with keys based on the prefix and index, and values from the input array.
633
+
634
+ Notes
635
+ -----
636
+ The keys in the dictionary are formed by concatenating the prefix with the index of the array.
637
+ Docstring is generated by GitHub Copilot."""
387
638
  array_dict = dict()
388
639
 
389
640
  for prefix_ix, prefix in enumerate(prefixes):
@@ -395,6 +646,24 @@ def distribute_multi_to_dict(prefixes, arrays):
395
646
 
396
647
 
397
648
  def unwrap_rf_parameters(parameters):
649
+ """
650
+ Unwraps the parameters from a dictionary into two lists: one for the coefficients and one for the poles.
651
+
652
+ Parameters
653
+ ----------
654
+ parameters : dict
655
+ Dictionary containing the parameters with keys starting with 'a' for coefficients and 'd' for poles.
656
+
657
+ Returns
658
+ -------
659
+ tuple
660
+ tuple containing two lists: one for the coefficients and one for the poles.
661
+
662
+ Notes
663
+ -----
664
+ Docstring is generated by GitHub Copilot.
665
+ """
666
+
398
667
  keys = list(parameters.keys())
399
668
  a_ixs = np.where([word.startswith('a') for word in keys])[0]
400
669
  d_ixs = np.where([word.startswith('d') for word in keys])[0]
@@ -415,6 +684,24 @@ def unwrap_rf_parameters(parameters):
415
684
 
416
685
 
417
686
  def normal_wind(T_g2wi, T_g2el, U=1.0):
687
+ """
688
+ Computes the wind speed in the local coordinates of the element.
689
+
690
+ Parameters
691
+ ----------
692
+ T_g2wi : np.ndarray
693
+ Transformation matrix from global to wind coordinates.
694
+ T_g2el : np.ndarray
695
+ Transformation matrix from global to element coordinates.
696
+ U : float, optional
697
+ Wind speed in the global coordinates. Default is 1.0.
698
+
699
+ Returns
700
+ -------
701
+ np.ndarray
702
+ Wind speed in the local coordinates of the element.
703
+ """
704
+
418
705
  T_wi2el = T_g2el @ T_g2wi.T
419
706
  e_wind_local = (T_wi2el @ np.array([1, 0, 0])[np.newaxis,:].T).flatten()
420
707
 
@@ -520,6 +807,28 @@ def element_aero_mats(B, omega, ad_dict, L, T=None, phi=None, rho=1.225):
520
807
 
521
808
  # Spectra
522
809
  def kaimal_auto(omega, Lx, A, sigma, V):
810
+ """
811
+ Kaimal auto-spectral density function (either single-component or three components).
812
+
813
+ Parameters
814
+ ----------
815
+ omega : float
816
+ Angular frequency.
817
+ Lx : float or np.ndarray
818
+ Integral length scale(s).
819
+ A : float or np.ndarray
820
+ Spectral shape parameter(s).
821
+ sigma : float or np.ndarray
822
+ Standard deviation(s) of the turbulence.
823
+ V : float
824
+ Mean wind speed.
825
+
826
+ Returns
827
+ -------
828
+ S : float
829
+ Auto-spectral density function value.
830
+ """
831
+
523
832
  f = omega/(2*np.pi)
524
833
  fhat = f*Lx/V
525
834
  S = (sigma**2*(A*fhat)/(1+(1.5*A*fhat))**(5/3))/f
@@ -527,6 +836,24 @@ def kaimal_auto(omega, Lx, A, sigma, V):
527
836
  return S/(2*np.pi)
528
837
 
529
838
  def von_karman_auto(omega, Lx, sigma, V):
839
+ """
840
+ Von Karman auto-spectral density function (either single-component or three components).
841
+
842
+ Parameters
843
+ ----------
844
+ omega : float
845
+ Angular frequency.
846
+ Lx : float or np.ndarray
847
+ Integral length scale(s).
848
+ sigma : float or np.ndarray
849
+ Standard deviation(s) of the turbulence.
850
+ V : float
851
+ Mean wind speed.
852
+ Returns
853
+ -------
854
+ S : float
855
+ Auto-spectral density function value.
856
+ """
530
857
 
531
858
  A1 = [
532
859
  0.0,
@@ -553,6 +880,33 @@ def von_karman_auto(omega, Lx, sigma, V):
553
880
  return S/(2*np.pi)
554
881
 
555
882
  def generic_kaimal_matrix(omega, nodes, T_wind, A, sigma, C, Lx, U, spectrum_type='kaimal'):
883
+ """
884
+ Computes the cross-spectral density matrix for a given set of nodes.
885
+
886
+ Parameters
887
+ ----------
888
+ omega : float
889
+
890
+ Angular frequency.
891
+ nodes : list
892
+ List of BEEF nodes for which to compute the cross-spectral density matrix.
893
+ T_wind : np.ndarray
894
+ Transformation matrix from global to wind coordinates.
895
+ A : float or np.ndarray
896
+ Parameter(s) A in Kaimal auto-spectral density.
897
+ sigma : float or np.ndarray
898
+ Standard deviation of the turbulence (either single or all components).
899
+ C : float or np.ndarray
900
+ Coefficient(s) for the cross-spectral density matrix.
901
+ LX : float or np.ndarray
902
+ Length scale(s) for the cross-spectral density matrix.
903
+ U : function
904
+ Function (of x, y and z) to calculate mean wind speed at a given point.
905
+ spectrum_type : str, optional
906
+ Type of spectrum to use. Default is 'kaimal'. Other options are 'vonKarman' or 'Karman'.
907
+
908
+ """
909
+
556
910
  # Adopted from MATLAB version. `nodes` is list with beef-nodes.
557
911
  V = np.zeros(len(nodes)) # Initialize vector with mean wind in all nodes
558
912
  Su = np.zeros([len(nodes), len(nodes)]) # One-point spectra for u component in all nodes
@@ -605,6 +959,29 @@ def generic_kaimal_matrix(omega, nodes, T_wind, A, sigma, C, Lx, U, spectrum_typ
605
959
 
606
960
 
607
961
  def loadmatrix_fe(V, load_coefficients, rho, B, D, admittance=None):
962
+ """
963
+ Computes the aerodynamic load matrix for a given set of parameters.
964
+
965
+ Parameters
966
+ ----------
967
+ V : float
968
+ Wind speed.
969
+ load_coefficients : dict
970
+ Dictionary containing the aerodynamic coefficients.
971
+ rho : float
972
+ Air density.
973
+ B : float
974
+ Width of the section.
975
+ D : float
976
+ Height of the section.
977
+ admittance : function, optional
978
+ Function to compute the admittance function. Default is None.
979
+
980
+ Returns
981
+ -------
982
+ BqBq : function
983
+ Function to compute the aerodynamic load matrix for a given frequency.
984
+ """
608
985
 
609
986
  if admittance is None :
610
987
  admittance = lambda omega_k: np.ones( (4,3) )
@@ -625,6 +1002,27 @@ def loadmatrix_fe(V, load_coefficients, rho, B, D, admittance=None):
625
1002
  return BqBq
626
1003
 
627
1004
  def loadmatrix_fe_static(V, load_coefficients, rho, B, D ):
1005
+ """
1006
+ Computes the aerodynamic load matrix for a given set of parameters in static conditions.
1007
+
1008
+ Parameters
1009
+ ----------
1010
+ V : float
1011
+ Wind speed.
1012
+ load_coefficients : dict
1013
+ Dictionary containing the aerodynamic coefficients.
1014
+ rho : float
1015
+ Air density.
1016
+ B : float
1017
+ Width of the section.
1018
+ D : float
1019
+ Height of the section.
1020
+
1021
+ Returns
1022
+ -------
1023
+ BqBq : np.ndarray
1024
+ Aerodynamic load matrix.
1025
+ """
628
1026
 
629
1027
  Cd = load_coefficients['Cd']
630
1028
  Cl = load_coefficients['Cl']
@@ -637,6 +1035,30 @@ def loadmatrix_fe_static(V, load_coefficients, rho, B, D ):
637
1035
  return BqBq
638
1036
 
639
1037
  def loadvector(T_el, Bq, T_wind, L, static = False):
1038
+ """
1039
+ Computes load vectors for a given set of parameters.
1040
+
1041
+ Parameters
1042
+ ----------
1043
+ T_el : np.ndarray
1044
+ Transformation matrix from global to element coordinates.
1045
+ Bq : np.ndarray
1046
+ Aerodynamic load matrix.
1047
+ T_wind : np.ndarray
1048
+ Transformation matrix from global to wind coordinates.
1049
+ L : float
1050
+ Length of the element.
1051
+ static : bool, optional
1052
+ If True, compute the load vector for static conditions. Default is False.
1053
+
1054
+ Returns
1055
+ -------
1056
+ R1 : np.ndarray
1057
+ Load vector for element node 1.
1058
+ R2 : np.ndarray
1059
+ Load vector for element node 2.
1060
+
1061
+ """
640
1062
 
641
1063
  G = np.zeros([12,4])
642
1064
  G[0,0] = L/2
@@ -674,6 +1096,48 @@ def loadvector(T_el, Bq, T_wind, L, static = False):
674
1096
  def windaction(omega, S, load_coefficients, elements, T_wind,
675
1097
  phi, B, D, U, omega_reduced=None, rho=1.225, print_progress=True,
676
1098
  section_lookup=None, nodes=None, admittance=None):
1099
+ """
1100
+ Computes the wind cross-spectral density matrix on a set of elements using the specified parameters.
1101
+
1102
+ Parameters
1103
+ ----------
1104
+ omega : np.ndarray
1105
+ Angular frequency.
1106
+ S : function
1107
+ Function to compute the cross-spectral density matrix.
1108
+ load_coefficients : dict
1109
+ Dictionary containing the aerodynamic coefficients.
1110
+ elements : list
1111
+ List of elements for which to compute the wind cross-spectral density matrix.
1112
+ T_wind : np.ndarray
1113
+ Transformation matrix from global to wind coordinates.
1114
+ phi : np.ndarray
1115
+ Transformation matrix from global to element coordinates.
1116
+ B : float
1117
+ Width of the section.
1118
+ D : float
1119
+ Height of the section.
1120
+ U : function
1121
+ Function to calculate mean wind speed at a given point.
1122
+ omega_reduced : np.ndarray, optional
1123
+ Reduced angular frequency. Default is None.
1124
+ rho : float, optional
1125
+ Air density. Default is 1.225.
1126
+ print_progress : bool, optional
1127
+ If True, print progress. Default is True.
1128
+ section_lookup : dict, optional
1129
+ Dictionary to look up sections for each element. Default is None.
1130
+ nodes : list, optional
1131
+ List of BEEF nodes for which to compute the wind cross-spectral density matrix. Default is None.
1132
+ admittance : function, optional
1133
+ Function to compute the admittance function. Default is None.
1134
+
1135
+ Returns
1136
+ -------
1137
+ genSqSq_reduced : np.ndarray
1138
+ Cross-spectral density matrix for the wind action.
1139
+
1140
+ """
677
1141
 
678
1142
  if nodes is None:
679
1143
  nodes = list(set([a for b in [el.nodes for el in elements] for a in b]))
@@ -787,6 +1251,40 @@ def windaction_static(load_coefficients, elements, T_wind,
787
1251
  phi, B, D, U, rho=1.225, print_progress=True,
788
1252
  section_lookup=None, nodes=None):
789
1253
 
1254
+ """
1255
+ Computes the wind load vector for a set of elements using the specified parameters.
1256
+
1257
+ Parameters
1258
+ ----------
1259
+ load_coefficients : dict
1260
+ Dictionary containing the aerodynamic coefficients.
1261
+ elements : list
1262
+ List of BEEF elements for which to compute the wind load vector.
1263
+ T_wind : np.ndarray
1264
+ Transformation matrix from global to wind coordinates.
1265
+ phi : np.ndarray
1266
+ Transformation matrix from global to element coordinates.
1267
+ B : float
1268
+ Width of the section.
1269
+ D : float
1270
+ Height of the section.
1271
+ U : function
1272
+ Function to calculate mean wind speed at a given point.
1273
+ rho : float, optional
1274
+ Air density. Default is 1.225.
1275
+ print_progress : bool, optional
1276
+ If True, print progress. Default is True.
1277
+ section_lookup : dict, optional
1278
+ Dictionary to look up sections for each element. Default is None.
1279
+ nodes : list, optional
1280
+ List of BEEF nodes for which to compute the wind load vector. Default is None.
1281
+
1282
+ Returns
1283
+ -------
1284
+ genF : np.ndarray
1285
+ Wind load vector for the specified elements.
1286
+ """
1287
+
790
1288
  if nodes is None:
791
1289
  nodes = list(set([a for b in [el.nodes for el in elements] for a in b]))
792
1290
 
@@ -834,6 +1332,35 @@ def windaction_static(load_coefficients, elements, T_wind,
834
1332
  return genF
835
1333
 
836
1334
  def K_from_ad(ad, V, w, B, rho):
1335
+ """
1336
+ Compute the aerodynamic stiffness matrix K from aerodynamic derivatives.
1337
+
1338
+ Parameters
1339
+ ----------
1340
+ ad : dict
1341
+ Dictionary containing aerodynamic derivative functions. Expected keys are:
1342
+ 'P4', 'P6', 'P3', 'H6', 'H4', 'H3', 'A6', 'A4', 'A3'. Each value should be a callable
1343
+ that takes a single argument (the reduced velocity `v`).
1344
+ V : float
1345
+ Wind velocity.
1346
+ w : float
1347
+ Circular frequency (rad/s). If zero, returns a zero matrix.
1348
+ B : float
1349
+ Reference length (e.g., bridge deck width).
1350
+ rho : float
1351
+ Air density.
1352
+
1353
+ Returns
1354
+ -------
1355
+ k : ndarray of shape (3, 3)
1356
+ Aerodynamic stiffness matrix.
1357
+
1358
+ Notes
1359
+ -----
1360
+ If `w` is zero, the function returns a 3x3 zero matrix.
1361
+ Otherwise, the matrix is computed using the provided aerodynamic derivatives evaluated at the reduced velocity.
1362
+ """
1363
+
837
1364
  if w==0:
838
1365
  k = np.zeros([3,3])
839
1366
  else:
@@ -849,6 +1376,34 @@ def K_from_ad(ad, V, w, B, rho):
849
1376
 
850
1377
 
851
1378
  def C_from_ad(ad, V, w, B, rho):
1379
+ """
1380
+ Compute the aerodynamic damping matrix K from aerodynamic derivatives.
1381
+
1382
+ Parameters
1383
+ ----------
1384
+ ad : dict
1385
+ Dictionary containing aerodynamic derivative functions. Expected keys are:
1386
+ 'P1', 'P5', 'P2', 'H5', 'H1', 'H2', 'A5', 'A1', 'A2'. Each value should be a callable
1387
+ that takes a single argument (the reduced velocity `v`).
1388
+ V : float
1389
+ Wind velocity.
1390
+ w : float
1391
+ Circular frequency (rad/s). If zero, returns a zero matrix.
1392
+ B : float
1393
+ Reference length (e.g., bridge deck width).
1394
+ rho : float
1395
+ Air density.
1396
+
1397
+ Returns
1398
+ -------
1399
+ k : ndarray of shape (3, 3)
1400
+ Aerodynamic stiffness matrix.
1401
+
1402
+ Notes
1403
+ -----
1404
+ If `w` is zero, the function returns a 3x3 zero matrix.
1405
+ Otherwise, the matrix is computed using the provided aerodynamic derivatives evaluated at the reduced velocity.
1406
+ """
852
1407
  if w==0:
853
1408
  c = np.zeros([3,3])
854
1409
  else:
@@ -863,6 +1418,24 @@ def C_from_ad(ad, V, w, B, rho):
863
1418
 
864
1419
 
865
1420
  def phi_aero_sum(mat, phi, x):
1421
+ """
1422
+ Computes the aerodynamic matrix (damping or stiffness) in modal coordinates.
1423
+
1424
+ Parameters
1425
+ ----------
1426
+ mat : ndarray
1427
+ Aerodynamic matrix in global coordinates.
1428
+ phi : ndarray
1429
+ Transformation matrix from global to modal coordinates.
1430
+ x : ndarray
1431
+ Vector of x-coordinates for integration.
1432
+
1433
+ Returns
1434
+ -------
1435
+ mat : ndarray
1436
+ Aerodynamic matrix in modal coordinates.
1437
+ """
1438
+
866
1439
  n_modes = phi.shape[1]
867
1440
  n_points = len(x)
868
1441
 
@@ -878,6 +1451,24 @@ def phi_aero_sum(mat, phi, x):
878
1451
 
879
1452
 
880
1453
  def function_sum(fun, const, fun_factor=1):
1454
+ """
1455
+ Function to sum a function and a constant. The function is multiplied by a factor.
1456
+
1457
+ Parameters
1458
+ ----------
1459
+ fun : callable
1460
+ Function to be summed with the constant.
1461
+ const : float
1462
+ Constant to be summed with the function.
1463
+ fun_factor : float, optional
1464
+ Factor to multiply the function. Default is 1.
1465
+
1466
+ Returns
1467
+ -------
1468
+ fsum : callable
1469
+ Function that computes the sum of the function and the constant.
1470
+
1471
+ """
881
1472
  def fsum(x):
882
1473
  if fun is None:
883
1474
  return const
@@ -888,6 +1479,33 @@ def function_sum(fun, const, fun_factor=1):
888
1479
 
889
1480
 
890
1481
  def get_aero_cont_adfun(ad_dict_fun, V, B, rho, phi, x):
1482
+ """
1483
+ Computes the aerodynamic matrices in modal coordinates.
1484
+
1485
+ Parameters
1486
+ ----------
1487
+ ad_dict_fun : callable
1488
+ Function that returns the aerodynamic derivatives for a given reduced velocity.
1489
+ V : float
1490
+ Wind velocity.
1491
+ B : float
1492
+ Reference length (e.g., bridge deck width).
1493
+ rho : float
1494
+ Air density.
1495
+ phi : ndarray
1496
+ Transformation matrix from global to modal coordinates.
1497
+ x : ndarray
1498
+ Vector of x-coordinates for integration.
1499
+
1500
+ Returns
1501
+ -------
1502
+ K : callable
1503
+ Function that computes the aerodynamic stiffness matrix in modal coordinates.
1504
+ C : callable
1505
+ Function that computes the aerodynamic damping matrix in modal coordinates.
1506
+
1507
+
1508
+ """
891
1509
  def K(w):
892
1510
  n_modes = phi.shape[1]
893
1511
  n_points = len(x)
@@ -920,6 +1538,35 @@ def get_aero_cont_adfun(ad_dict_fun, V, B, rho, phi, x):
920
1538
 
921
1539
 
922
1540
  def get_aero_cont_addict(ad_dict, V, B, rho, phi, x):
1541
+ """
1542
+ Computes the aerodynamic matrices in modal coordinates.
1543
+
1544
+ Parameters
1545
+ ----------
1546
+ ad_dict : dict
1547
+ Dictionary containing aerodynamic derivative functions. Expected keys are:
1548
+ 'P4', 'P6', 'P3', 'H6', 'H4', 'H3', 'A6', 'A4', 'A3'. Each value should be a callable
1549
+ that takes a single argument (the reduced velocity `v`).
1550
+ V : float
1551
+ Wind velocity.
1552
+ B : float
1553
+ Reference length (e.g., bridge deck width).
1554
+ rho : float
1555
+ Air density.
1556
+ phi : ndarray
1557
+ Transformation matrix from global to modal coordinates.
1558
+ x : ndarray
1559
+ Vector of x-coordinates for integration.
1560
+
1561
+ Returns
1562
+ -------
1563
+ K : callable
1564
+ Function that computes the aerodynamic stiffness matrix in modal coordinates.
1565
+ C : callable
1566
+ Function that computes the aerodynamic damping matrix in modal coordinates.
1567
+
1568
+
1569
+ """
923
1570
  def K(w):
924
1571
  kae = K_from_ad(ad_dict, V, w, B, rho)
925
1572
  return phi_aero_sum(kae, phi, x)
@@ -935,6 +1582,58 @@ def itflutter_cont(Ms, Cs, Ks, phi, x, ad_dict, B, V=0.0, rho=1.225, dV=1,
935
1582
  overshoot_factor=0.5, itmax={}, omega_ref=None,
936
1583
  tol={}, print_progress=True, keep_all=False, track_by_psi=True):
937
1584
 
1585
+ """
1586
+ Iterative flutter analysis for continuous systems using the iterative eigensolver.
1587
+
1588
+ Parameters
1589
+ ----------
1590
+ Ms : ndarray
1591
+ Mass matrix for in-vacuum and dry sub-structure.
1592
+ Cs : ndarray
1593
+ Damping matrix for in-vacuum and dry sub-structure.
1594
+ Ks : ndarray
1595
+ Stiffness matrix for in-vacuum and dry sub-structure.
1596
+ phi : ndarray
1597
+ Transformation matrix from global to modal coordinates.
1598
+ x : ndarray
1599
+ Vector of x-coordinates for integration.
1600
+ ad_dict : dict or callable
1601
+ Dictionary containing aerodynamic derivative functions or a function that returns the aerodynamic derivatives.
1602
+ If a dictionary, it should contain the following keys: 'P4', 'P6', 'P3', 'H6', 'H4', 'H3', 'A6', 'A4', 'A3'.
1603
+ Each value should be a callable that takes a single argument (the reduced velocity `v`).
1604
+ B : float
1605
+ Reference length (e.g., bridge deck width).
1606
+ V : float, optional
1607
+ Initial wind velocity. Default is 0.0.
1608
+ rho : float, optional
1609
+ Air density. Default is 1.225.
1610
+ dV : float, optional
1611
+ Increment for wind velocity. Default is 1.
1612
+ overshoot_factor : float, optional
1613
+ Factor to reduce the increment for wind velocity in case of overshooting. Default is 0.5.
1614
+ itmax : dict, optional
1615
+ Dictionary containing maximum iterations for velocity and frequency. Default is {'V': 50, 'f': 15}.
1616
+ omega_ref : float, optional
1617
+ Reference angular frequency. If None, it is computed from the eigenvalues of the system.
1618
+ tol : dict, optional
1619
+ Dictionary containing tolerance for velocity and frequency. Default is {'V': 1e-3, 'f': 1e-4}.
1620
+ print_progress : bool, optional
1621
+ If True, print progress. Default is True.
1622
+ keep_all : bool, optional
1623
+ If True, keep all results. Default is False.
1624
+ track_by_psi : bool, optional
1625
+ If True, track the eigenvectors by their similarity. Default is True.
1626
+
1627
+ Returns
1628
+ -------
1629
+ res : dict
1630
+ Dictionary containing the results of the flutter analysis. The keys are:
1631
+ 'V' : list of wind velocities at which flutter was detected.
1632
+ 'lambd' : list of eigenvalues at which flutter was detected.
1633
+ 'critical_mode' : list of indices of the critical mode at each velocity.
1634
+ 'critical_psi' : list of eigenvectors corresponding to the critical mode at each velocity.
1635
+ """
1636
+
938
1637
  if callable(ad_dict):
939
1638
  get_aero = get_aero_cont_adfun
940
1639
  else:
@@ -1028,7 +1727,52 @@ def itflutter_cont(Ms, Cs, Ks, phi, x, ad_dict, B, V=0.0, rho=1.225, dV=1,
1028
1727
 
1029
1728
  def itflutter_cont_naive(Ms, Cs, Ks, phi, x, ad_dict, B, V=0.0, rho=1.225, dV=1,
1030
1729
  overshoot_factor=0.5, itmax={}, tol={}, print_progress=True):
1031
-
1730
+ """
1731
+ Iterative flutter analysis for continuous systems using a naive iteration.
1732
+
1733
+ Parameters
1734
+ ----------
1735
+ Ms : ndarray
1736
+ Mass matrix for in-vacuum and dry sub-structure.
1737
+ Cs : ndarray
1738
+ Damping matrix for in-vacuum and dry sub-structure.
1739
+ Ks : ndarray
1740
+ Stiffness matrix for in-vacuum and dry sub-structure.
1741
+ phi : ndarray
1742
+ Transformation matrix from global to modal coordinates.
1743
+ x : ndarray
1744
+ Vector of x-coordinates for integration.
1745
+ ad_dict : dict or callable
1746
+ Dictionary containing aerodynamic derivative functions or a function that returns the aerodynamic derivatives.
1747
+ If a dictionary, it should contain the following keys: 'P4', 'P6', 'P3', 'H6', 'H4', 'H3', 'A6', 'A4', 'A3'.
1748
+ Each value should be a callable that takes a single argument (the reduced velocity `v`).
1749
+ B : float
1750
+ Reference length (e.g., bridge deck width).
1751
+ V : float, optional
1752
+ Initial wind velocity. Default is 0.0.
1753
+ rho : float, optional
1754
+ Air density. Default is 1.225.
1755
+ dV : float, optional
1756
+ Increment for wind velocity. Default is 1.
1757
+ overshoot_factor : float, optional
1758
+ Factor to reduce the increment for wind velocity in case of overshooting. Default is 0.5.
1759
+ itmax : dict, optional
1760
+ Dictionary containing maximum iterations for velocity and frequency. Default is {'V': 50, 'f': 15}.
1761
+ tol : dict, optional
1762
+ Dictionary containing tolerance for velocity and frequency. Default is {'V': 1e-3, 'f': 1e-4}.
1763
+ print_progress : bool, optional
1764
+ If True, print progress. Default is True.
1765
+
1766
+ Returns
1767
+ -------
1768
+ res : dict
1769
+ Dictionary containing the results of the flutter analysis. The keys are:
1770
+ 'V' : list of wind velocities at which flutter was detected.
1771
+ 'lambd' : list of eigenvalues at which flutter was detected.
1772
+ 'critical_mode' : list of indices of the critical mode at each velocity.
1773
+ 'critical_psi' : list of eigenvectors corresponding to the critical mode at each velocity.
1774
+
1775
+ """
1032
1776
 
1033
1777
  if callable(ad_dict):
1034
1778
  get_aero = get_aero_cont_adfun
@@ -1098,5 +1842,4 @@ def itflutter_cont_naive(Ms, Cs, Ks, phi, x, ad_dict, B, V=0.0, rho=1.225, dV=1,
1098
1842
 
1099
1843
  res = {key: np.array(res[key]) for key in ['critical_mode', 'critical_psi', 'V', 'lambd']}
1100
1844
 
1101
- return res
1102
-
1845
+ return res