wawi 0.0.3__tar.gz → 0.0.5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. {wawi-0.0.3 → wawi-0.0.5}/PKG-INFO +1 -1
  2. {wawi-0.0.3 → wawi-0.0.5}/wawi/__init__.py +2 -2
  3. {wawi-0.0.3 → wawi-0.0.5}/wawi/general.py +0 -5
  4. {wawi-0.0.3 → wawi-0.0.5}/wawi/io.py +35 -12
  5. {wawi-0.0.3 → wawi-0.0.5}/wawi/wind.py +20 -19
  6. {wawi-0.0.3 → wawi-0.0.5}/wawi.egg-info/PKG-INFO +1 -1
  7. {wawi-0.0.3 → wawi-0.0.5}/wawi.egg-info/SOURCES.txt +0 -2
  8. wawi-0.0.3/tests/test_IABSE_step11a - Copy.py +0 -104
  9. wawi-0.0.3/wawi/abq.py +0 -1128
  10. {wawi-0.0.3 → wawi-0.0.5}/LICENSE +0 -0
  11. {wawi-0.0.3 → wawi-0.0.5}/README.md +0 -0
  12. {wawi-0.0.3 → wawi-0.0.5}/pyproject.toml +0 -0
  13. {wawi-0.0.3 → wawi-0.0.5}/setup.cfg +0 -0
  14. {wawi-0.0.3 → wawi-0.0.5}/tests/test_IABSE_step11a.py +0 -0
  15. {wawi-0.0.3 → wawi-0.0.5}/tests/test_IABSE_step11c.py +0 -0
  16. {wawi-0.0.3 → wawi-0.0.5}/tests/test_IABSE_step2a.py +0 -0
  17. {wawi-0.0.3 → wawi-0.0.5}/tests/test_wind.py +0 -0
  18. {wawi-0.0.3 → wawi-0.0.5}/wawi/fe.py +0 -0
  19. {wawi-0.0.3 → wawi-0.0.5}/wawi/identification.py +0 -0
  20. {wawi-0.0.3 → wawi-0.0.5}/wawi/modal.py +0 -0
  21. {wawi-0.0.3 → wawi-0.0.5}/wawi/plot.py +0 -0
  22. {wawi-0.0.3 → wawi-0.0.5}/wawi/prob.py +0 -0
  23. {wawi-0.0.3 → wawi-0.0.5}/wawi/random.py +0 -0
  24. {wawi-0.0.3 → wawi-0.0.5}/wawi/signal.py +0 -0
  25. {wawi-0.0.3 → wawi-0.0.5}/wawi/structural.py +0 -0
  26. {wawi-0.0.3 → wawi-0.0.5}/wawi/time_domain.py +0 -0
  27. {wawi-0.0.3 → wawi-0.0.5}/wawi/tools.py +0 -0
  28. {wawi-0.0.3 → wawi-0.0.5}/wawi/wave.py +0 -0
  29. {wawi-0.0.3 → wawi-0.0.5}/wawi/wind_code.py +0 -0
  30. {wawi-0.0.3 → wawi-0.0.5}/wawi.egg-info/dependency_links.txt +0 -0
  31. {wawi-0.0.3 → wawi-0.0.5}/wawi.egg-info/requires.txt +0 -0
  32. {wawi-0.0.3 → wawi-0.0.5}/wawi.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: wawi
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: WAve and WInd response prediction
5
5
  Author-email: "Knut A. Kvåle" <knut.a.kvale@ntnu.no>, Ole Øiseth <ole.oiseth@ntnu.no>, Aksel Fenerci <aksel.fenerci@ntnu.no>, Øivind Wiig Petersen <oyvind.w.petersen@ntnu.no>
6
6
  License: MIT License
@@ -1,7 +1,7 @@
1
- __version__ = "0.0.3"
1
+ __version__ = "0.0.5"
2
2
 
3
3
  __pdoc__ = dict()
4
- __pdoc__['module.name'] = False
4
+ __pdoc__['wawi.abq'] = False
5
5
 
6
6
  # Other packages
7
7
  import numpy as np
@@ -162,8 +162,6 @@ def merge_tr_phi(phi_trans, phi_rot, thread_stack=True):
162
162
  thread_stack: specify if the matrices should be thread in or not (if True, 3 translational DOFs and 3 rotational DOFs ...) (default = True)
163
163
  Returns:
164
164
  phi_combined: phi matrix with all DOFs
165
-
166
- AAJ / Knut Andreas Kvaale, 2017
167
165
  """
168
166
 
169
167
  Ndofs = phi_trans.shape[0]*2
@@ -204,7 +202,6 @@ def interp1z(z,mat,znew):
204
202
  Returns:
205
203
  matnew: interpolated 3D matrix (Numpy array)
206
204
 
207
- NTNU / Knut Andreas Kvaale, 2018
208
205
  """
209
206
 
210
207
  matnew = np.zeros([1,len(mat[0]),len(mat[0][0])])
@@ -226,7 +223,6 @@ def interpolate_3d(z, mat, zi):
226
223
  Returns:
227
224
  mati: interpolated matrix
228
225
 
229
- NTNU / Knut Andreas Kvaale, 2017
230
226
  """
231
227
  mat_shape = np.shape(mat)
232
228
  mati = np.zeros([mat_shape[0], mat_shape[1], len(zi)])
@@ -280,7 +276,6 @@ def rodrot(theta, rotaxis=[0, 0, 1], style='row'):
280
276
  Returns:
281
277
  T: transformation matrix in NumPy format
282
278
 
283
- NTNU / Knut Andreas Kvaale, 2017
284
279
  """
285
280
 
286
281
  axis = np.asarray(rotaxis)
@@ -48,7 +48,7 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
48
48
 
49
49
  Notes
50
50
  ---------------
51
- Add info here describing the structure and contents of all files.
51
+ TODO: Add info here describing the structure and contents of all files.
52
52
 
53
53
  See `importing-folder.ipynb` for a full example.
54
54
  '''
@@ -105,7 +105,7 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
105
105
  common_ptype_settings = pontoon_type_settings.pop('*')
106
106
 
107
107
  except:
108
- print('Valid pontoon types file not found. No pontoon_types definitions applied.')
108
+ print('Valid pontoon type settings file not found. No definitions applied.')
109
109
  pontoon_type_settings = {}
110
110
 
111
111
  else:
@@ -152,22 +152,28 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
152
152
 
153
153
  # Modal dry object
154
154
  if 'xi0' in modal:
155
- xi0 = np.array(modal['xi0'])
155
+ xi0 = np.array(modal.pop('xi0'))
156
156
  else:
157
157
  xi0 = 0.0
158
158
 
159
159
  if 'm_min' in modal:
160
- m_min = modal['m_min']
160
+ m_min = modal.pop('m_min')
161
161
  else:
162
162
  m_min = 0.0
163
163
 
164
164
  if 'phi_x' in modal:
165
- phi_x = modal['phi_x']
165
+ phi_x = modal.pop('phi_x')
166
166
  else:
167
167
  phi_x = None
168
-
169
- modal_dry = ModalDry(modal['phi'], m=np.array(modal['m']), k=np.array(modal['k']),
170
- local_phi=modal['local'], xi0=xi0, phi_x=phi_x, m_min=m_min)
168
+
169
+ if 'local' in modal:
170
+ local_phi = modal.pop('local')
171
+ else:
172
+ local_phi = False
173
+
174
+ phi = modal.pop('phi')
175
+
176
+ modal_dry = ModalDry(phi, xi0=xi0, local_phi=local_phi, phi_x=phi_x, m_min=m_min, **modal)
171
177
 
172
178
  # Element definition
173
179
  if element_data != {}:
@@ -184,7 +190,25 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
184
190
  node_matrix = np.array(element_data['node_matrix'])
185
191
  node_matrix[:,0] = node_matrix[:,0].astype(int)
186
192
  element_matrix = np.array(element_data['element_matrix'])
187
-
193
+ element_matrix = element_matrix.astype(int)
194
+
195
+ # Remove elements without valid nodes
196
+ remove_ix = []
197
+ remove_els = []
198
+
199
+ for ix,row in enumerate(element_matrix):
200
+ el,node1,node2 = row
201
+ # print(row)
202
+
203
+ if (node1 not in node_matrix[:,0].astype(int)) or (node2 not in node_matrix[:,0].astype(int)):
204
+ remove_ix.append(ix)
205
+ remove_els.append(el)
206
+
207
+ if len(remove_els)>0:
208
+ print(f'Elements {remove_els} do not have valid nodes - not included in model.')
209
+
210
+ element_matrix = np.delete(element_matrix, remove_ix, axis=0)
211
+
188
212
  eldef = Part(node_matrix, element_matrix, sections=sections,
189
213
  assemble=False, forced_ndofs=6)
190
214
 
@@ -211,7 +235,6 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
211
235
  for el_label in elements:
212
236
  el = eldef.get_element(int(el_label))
213
237
 
214
-
215
238
  el.assign_e2(e2)
216
239
  el.assign_e3(e3)
217
240
 
@@ -219,7 +242,7 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
219
242
  else:
220
243
  eldef = None
221
244
 
222
- # Create model object
245
+ # Create model object (only hydro part)
223
246
  model = Model.from_nodes_and_types(pontoon_nodes, [ptypes[pt] for pt in pontoon_types], modal_dry=modal_dry,
224
247
  rotation=pontoon_rotation, eldef=eldef, labels=pontoon_names)
225
248
 
@@ -249,7 +272,7 @@ def import_folder(model_folder, pontoon_stl='pontoon.stl', aero_sections='aero_s
249
272
  model.assign_drag_elements(data)
250
273
  except:
251
274
  print('Specified drag_elements file found or invalid. No drag elements defined.')
252
-
275
+
253
276
  model.connect_eldef()
254
277
  model.assign_dry_modes()
255
278
 
@@ -610,10 +610,10 @@ def generic_kaimal_matrix(omega, nodes, T_wind, A, sigma, C, Lx, U, options=None
610
610
  return SvSv
611
611
 
612
612
 
613
- def loadmatrix_fe(V, load_coefficients, rho, B, D, Admittance = None):
613
+ def loadmatrix_fe(V, load_coefficients, rho, B, D, admittance=None):
614
614
 
615
- if Admittance is None :
616
- Admittance = lambda omega_k: np.ones( (4,3) )
615
+ if admittance is None :
616
+ admittance = lambda omega_k: np.ones( (4,3) )
617
617
 
618
618
  Cd = load_coefficients['Cd']
619
619
  dCd = load_coefficients['dCd']
@@ -623,7 +623,7 @@ def loadmatrix_fe(V, load_coefficients, rho, B, D, Admittance = None):
623
623
  dCm = load_coefficients['dCm']
624
624
 
625
625
  # Equation 7 from Oiseth, 2010
626
- BqBq = lambda omega_k: 1/2*rho*V*B*Admittance(omega_k*B/V/2/np.pi)*np.array([[0, 0, 0],
626
+ BqBq = lambda omega_k: 1/2*rho*V*B*admittance(omega_k*B/V/2/np.pi)*np.array([[0, 0, 0],
627
627
  [0, 2*D/B*Cd, (D/B*dCd-Cl)],
628
628
  [0, 2*Cl, (dCl+D/B*Cd)],
629
629
  [0, -2*B*Cm, -B*dCm]])
@@ -636,10 +636,10 @@ def loadmatrix_fe_static(V, load_coefficients, rho, B, D ):
636
636
  Cl = load_coefficients['Cl']
637
637
  Cm = load_coefficients['Cm']
638
638
 
639
- BqBq = 1/2*rho*V**2*B*np.array([[ 0, 0 , 0 ],
640
- [ D/B*Cd, 0 , 0 ],
641
- [ 0, 0 , Cl ],
642
- [ 0, B*Cm , 0 ]])
639
+ BqBq = 1/2*rho*V**2*B*np.array([[ 0 ],
640
+ [ D/B*Cd ],
641
+ [ Cl ],
642
+ [ -B*Cm ]])
643
643
  return BqBq
644
644
 
645
645
  def loadvector(T_el, Bq, T_wind, L, static = False):
@@ -660,15 +660,16 @@ def loadvector(T_el, Bq, T_wind, L, static = False):
660
660
 
661
661
  # Transform from wind coordinates to local element coordinates
662
662
 
663
- if static is False:
664
- T = T_el @ T_wind.T
665
- else:
666
- T = T_el @ T_wind.T @ np.ones( [3,1] )
663
+ T = T_el @ T_wind.T
667
664
 
668
665
  T_full = blkdiag(T_el, 4) # Block diagonal - repeated 4 times to transform both trans and rot DOFs at each node (2+2)
669
666
 
670
667
  # T_full.T transforms L-->G
671
- R = T_full.T @ G @ Bq @ T
668
+ if static is False:
669
+ R = T_full.T @ G @ Bq @ T
670
+ else:
671
+ R = T_full.T @ G @ Bq
672
+
672
673
  R1 = R[0:6] # Element node 1
673
674
  R2 = R[6:12] # Element node 2
674
675
 
@@ -678,7 +679,7 @@ def loadvector(T_el, Bq, T_wind, L, static = False):
678
679
 
679
680
  def windaction(omega, S, load_coefficients, elements, T_wind,
680
681
  phi, B, D, U, omega_reduced=None, rho=1.225, print_progress=True,
681
- section_lookup=None, nodes=None, Admittance = None):
682
+ section_lookup=None, nodes=None, admittance=None):
682
683
 
683
684
  if nodes is None:
684
685
  nodes = list(set([a for b in [el.nodes for el in elements] for a in b]))
@@ -704,7 +705,7 @@ def windaction(omega, S, load_coefficients, elements, T_wind,
704
705
  lc_fun = lambda el: load_coefficients
705
706
  B_fun = lambda el: B
706
707
  D_fun = lambda el: D
707
- Admittance_fun = lambda el: Admittance
708
+ admittance_fun = lambda el: admittance
708
709
  else:
709
710
  def get_sec(el):
710
711
  for key in section_lookup:
@@ -715,7 +716,7 @@ def windaction(omega, S, load_coefficients, elements, T_wind,
715
716
  B_fun = lambda el: B[get_sec(el)]
716
717
  D_fun = lambda el: D[get_sec(el)]
717
718
 
718
- if Admittance is None: # omit the frequency loop if ADmittance is not included - faster !
719
+ if admittance is None: # omit the frequency loop if ADmittance is not included - faster !
719
720
  RG = np.zeros([len(nodes)*n_dofs, 3])
720
721
  for el in elements:
721
722
  node1_dofs = el.nodes[0].global_dofs
@@ -724,7 +725,7 @@ def windaction(omega, S, load_coefficients, elements, T_wind,
724
725
  mean_wind = U(el.get_cog())
725
726
  Vn = normal_wind(T_wind, el.T0)*mean_wind # Find the normal wind
726
727
  BqBq = loadmatrix_fe(Vn, lc_fun(el), rho, B_fun(el), D_fun(el))
727
- R1, R2 = loadvector(el.T0, BqBq, T_wind, el.L) # Obtain the load vector for each element
728
+ R1, R2 = loadvector(el.T0, BqBq(1), T_wind, el.L) # Obtain the load vector for each element
728
729
 
729
730
  RG[node1_dofs, :] = RG[node1_dofs, :] + R1 # Add the contribution from the element (end 1) to the system
730
731
  RG[node2_dofs, :] = RG[node2_dofs, :] + R2 # Add the contribution from the element (end 2) to the system
@@ -747,7 +748,7 @@ def windaction(omega, S, load_coefficients, elements, T_wind,
747
748
  genSqSq_reduced[:, :, k] = phiT_RG_block @ S(omega_k) @ phiT_RG_block.T # to modal coordinates
748
749
 
749
750
  else: # admittance is given - triple loop (the old way, slower)
750
- Admittance_fun = lambda el: Admittance[get_sec(el)]
751
+ admittance_fun = lambda el: admittance[get_sec(el)]
751
752
 
752
753
  for k, omega_k in enumerate(omega_reduced):
753
754
  if print_progress:
@@ -763,7 +764,7 @@ def windaction(omega, S, load_coefficients, elements, T_wind,
763
764
 
764
765
  mean_wind = U(el.get_cog())
765
766
  Vn = normal_wind(T_wind, el.T0)*mean_wind # Find the normal wind
766
- BqBq = loadmatrix_fe(Vn, lc_fun(el), rho, B_fun(el), D_fun(el), Admittance = Admittance_fun(el))
767
+ BqBq = loadmatrix_fe(Vn, lc_fun(el), rho, B_fun(el), D_fun(el), admittance=admittance_fun(el))
767
768
  R1, R2 = loadvector(el.T0, BqBq(omega_k), T_wind, el.L) # Obtain the load vector for each element
768
769
 
769
770
  RG[node1_dofs, :] = RG[node1_dofs, :] + R1 # Add the contribution from the element (end 1) to the system
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: wawi
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: WAve and WInd response prediction
5
5
  Author-email: "Knut A. Kvåle" <knut.a.kvale@ntnu.no>, Ole Øiseth <ole.oiseth@ntnu.no>, Aksel Fenerci <aksel.fenerci@ntnu.no>, Øivind Wiig Petersen <oyvind.w.petersen@ntnu.no>
6
6
  License: MIT License
@@ -1,13 +1,11 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- tests/test_IABSE_step11a - Copy.py
5
4
  tests/test_IABSE_step11a.py
6
5
  tests/test_IABSE_step11c.py
7
6
  tests/test_IABSE_step2a.py
8
7
  tests/test_wind.py
9
8
  wawi/__init__.py
10
- wawi/abq.py
11
9
  wawi/fe.py
12
10
  wawi/general.py
13
11
  wawi/identification.py
@@ -1,104 +0,0 @@
1
-
2
- import pytest
3
- import numpy as np
4
- from math import isclose
5
- import dill
6
-
7
- # use the local wawi (Github folder) instead of the installed version (remove this when using the installed version)
8
- import sys
9
- import os
10
- sys.path.insert(0, os.path.abspath('C:\\Users\\aksef\\Documents\\GitHub\\wawi'))
11
-
12
- # import functions
13
- from wawi.io import import_folder
14
- from wawi.model import Windstate
15
- from wawi.wind import ADs, flatplate_ads
16
- from wawi.wind import itflutter_cont_naive
17
- from wawi.general import eval_3d_fun
18
-
19
- model_folder = './tests/models/model_2a'
20
-
21
- def AD_dict(AD_funs):
22
- AD_s = dict(
23
- A1 = lambda v: -AD_funs['a_fun'][0](v), # sign convention
24
- A2 = AD_funs['a_fun'][1],
25
- A3 = AD_funs['a_fun'][2],
26
- A4 = lambda v: -AD_funs['a_fun'][3](v),
27
- A5 = lambda v: -AD_funs['a_fun'][4](v),
28
- A6 = lambda v: -AD_funs['a_fun'][5](v),
29
-
30
- H1 = AD_funs['h_fun'][0],
31
- H2 = lambda v: -AD_funs['h_fun'][1](v),
32
- H3 = lambda v: -AD_funs['h_fun'][2](v),
33
- H4 = AD_funs['h_fun'][3],
34
- H5 = AD_funs['h_fun'][4],
35
- H6 = AD_funs['h_fun'][5],
36
-
37
- P1 = AD_funs['p_fun'][0],
38
- P2 = lambda v: -AD_funs['p_fun'][1](v),
39
- P3 = lambda v: -AD_funs['p_fun'][2](v),
40
- P4 = AD_funs['p_fun'][3],
41
- P5 = AD_funs['p_fun'][4],
42
- P6 = AD_funs['p_fun'][5],
43
- )
44
- return AD_s
45
-
46
- def iabse_2a_windstate(mean_v):
47
- windstate = Windstate(mean_v,
48
- 90,
49
- Iu=0.1,
50
- Iw=0.05,
51
- Au=6.8, Aw=9.4, # not used in von Karman
52
- Cuy=10.0, Cwy=6.5,
53
- Cuz=10.0, Cwz=3.0,
54
- Lux=200.0, Lwx=20.0,
55
- x_ref=[0,0,0], rho=1.22,
56
- options = {
57
- 'spectra_type': 'vonKarman'
58
- }
59
- )
60
-
61
- return windstate
62
-
63
- davenport = lambda fred: 2*(7*fred-1+np.exp(-7*fred))/(7*fred)**2
64
-
65
- omega = np.linspace(0.001, 6, 1000)
66
-
67
- # import the model and assign properties
68
- model = import_folder(model_folder)
69
- model.modal_dry.xi0 = .3e-2
70
-
71
- # assign ADs (BB3 ADs)
72
- with open( model_folder + '/AD_funs_BB3_scanlan.pkl', 'rb') as file:
73
- AD_funs = dill.load(file)
74
- AD_s = AD_dict(AD_funs)
75
- for key in model.aero.sections:
76
- model.aero.sections[key].ADs = ADs(**AD_s)
77
-
78
- V = 30
79
- # assign windstate
80
- model.aero.windstate = iabse_2a_windstate(30)
81
- # admittance
82
- for key in model.aero.sections:
83
- model.aero.sections[key].Admittance = lambda fred: np.full((4, 3), davenport(fred))
84
-
85
- model.run_eig(w_initial=model.modal_dry.omega_n.tolist(), freq_kind=True, itmax=100)
86
-
87
- # run analysis
88
- model.run_freqsim(omega,
89
- include_selfexcited=['aero'],
90
- include_action=['aero'],
91
- print_progress=False, merge_aero_sections=True)
92
- # RMS responses
93
- stds = model.get_result_std(key = 'full')
94
- # global dofs
95
- global_dof_ix1 = model.eldef.node_dof_lookup(36)[1:4]
96
- global_dof_ix2 = model.eldef.node_dof_lookup(26)[1:4]
97
-
98
- assert isclose(stds[global_dof_ix1][0], RMS_horz_exp1, rel_tol = 10e-2) # midspan horizontal
99
- assert isclose(stds[global_dof_ix1][1], RMS_vert_exp1, rel_tol = 10e-2) # midspan vertical
100
- assert isclose(stds[global_dof_ix1][2]*31/2, RMS_tors_exp1, rel_tol = 10e-2) # midspan torsional
101
-
102
- assert isclose(stds[global_dof_ix2][0], RMS_horz_exp2, rel_tol = 15e-2) # q-span horizontal
103
- assert isclose(stds[global_dof_ix2][1], RMS_vert_exp2, rel_tol = 15e-2) # q-span vertical
104
- assert isclose(stds[global_dof_ix2][2]*31/2, RMS_tors_exp2, rel_tol = 20e-2) # q-span torsional