wawi 0.0.9__py3-none-any.whl → 0.0.12__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.
Potentially problematic release.
This version of wawi might be problematic. Click here for more details.
- examples/3 Software interfacing/Abaqus model export/bergsoysund-export.py +12 -8
- examples/3 Software interfacing/Abaqus model export/hardanger-export.py +47 -0
- tests/test_IABSE_step11a.py +12 -11
- tests/test_IABSE_step11c.py +9 -9
- tests/test_IABSE_step2a.py +8 -8
- wawi/__init__.py +5 -3
- wawi/io.py +1 -1
- wawi/modal.py +2 -2
- wawi/model/_model.py +35 -2
- wawi/time_domain.py +45 -0
- wawi/wind.py +1 -1
- {wawi-0.0.9.dist-info → wawi-0.0.12.dist-info}/METADATA +10 -2
- {wawi-0.0.9.dist-info → wawi-0.0.12.dist-info}/RECORD +16 -17
- {wawi-0.0.9.dist-info → wawi-0.0.12.dist-info}/WHEEL +1 -1
- examples/3 Software interfacing/Abaqus model export/test.py +0 -67
- wawi/ext/abq_legacy.py +0 -462
- {wawi-0.0.9.dist-info → wawi-0.0.12.dist-info/licenses}/LICENSE +0 -0
- {wawi-0.0.9.dist-info → wawi-0.0.12.dist-info}/top_level.txt +0 -0
@@ -42,25 +42,29 @@ with open('element.json', 'w') as f:
|
|
42
42
|
phi_full_disp = wawi.ext.abq.get_nodal_phi(step_obj, nodes, flatten_components=True, field_outputs=['UT', 'UR'])
|
43
43
|
|
44
44
|
#%% Get pontoon data
|
45
|
-
|
45
|
+
pontoon_sets = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7']
|
46
|
+
pontoon_types = ['p17', 'p26', 'p345', 'p345', 'p345', 'p26', 'p17']
|
47
|
+
rotations = np.array([13.944407004001892, 9.2962713360012632, 4.6481356680006325, 0.0,
|
48
|
+
-4.6481356680006334, -9.2962713360012632, -13.944407004001883])
|
49
|
+
|
50
|
+
node_matrix_pontoons = np.vstack([wawi.ext.abq.get_element_matrices(db.rootAssembly.nodeSets[pset], obj=part) for pset in pontoon_sets])
|
46
51
|
node_labels_pontoons = node_matrix_pontoons[:,0]
|
47
|
-
nodes_pontoons = wawi.ext.abq.create_list_of_nodes(part, node_labels_pontoons)
|
48
|
-
phi_h = wawi.ext.abq.get_nodal_phi(step_obj, nodes_pontoons, flatten_components=True, field_outputs=['UT', 'UR'])
|
49
52
|
|
50
53
|
# Export pontoon.json
|
51
|
-
pontoon_types = ['ptype_1']*7
|
52
|
-
rotations = -np.array([13.944407004001892, 9.2962713360012632, 4.6481356680006325, 0.0,
|
53
|
-
-4.6481356680006334, -9.2962713360012632, -13.944407004001883])
|
54
|
-
|
55
54
|
pontoon_data = OrderedDict()
|
56
55
|
|
57
56
|
for ix, node in enumerate(node_labels_pontoons):
|
58
|
-
key =
|
57
|
+
key = pontoon_sets[ix]
|
59
58
|
pontoon_data[key] = dict(coordinates=node_matrix_pontoons[ix, 1:].tolist(),
|
60
59
|
node=node,
|
61
60
|
rotation=rotations[ix],
|
62
61
|
pontoon_type=pontoon_types[ix])
|
63
62
|
|
63
|
+
|
64
|
+
nodes_pontoons = wawi.ext.abq.create_list_of_nodes(part, node_labels_pontoons)
|
65
|
+
phi_h = wawi.ext.abq.get_nodal_phi(step_obj, nodes_pontoons, flatten_components=True, field_outputs=['UT', 'UR'])
|
66
|
+
|
67
|
+
|
64
68
|
with open('pontoon.json', 'w') as f:
|
65
69
|
json.dump(pontoon_data, f)
|
66
70
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from sys import path
|
2
|
+
from collections import OrderedDict
|
3
|
+
|
4
|
+
path.append('C:/Users/knutankv/git-repos/wawi/') # this is an easy quick fix to enable importing wawi package in Abaqus environment
|
5
|
+
savefolder = 'C:/Temp/'
|
6
|
+
|
7
|
+
# NOTE: Only linear *beam* elements are supported in relevant sets!!
|
8
|
+
|
9
|
+
import wawi.ext.abq
|
10
|
+
import json
|
11
|
+
import numpy as np
|
12
|
+
|
13
|
+
#%% Get database object (ODB)
|
14
|
+
db = wawi.ext.abq.get_db('odb')
|
15
|
+
|
16
|
+
#%% Definitions
|
17
|
+
frequency_step = 'Step-11' # define set name to extract modal properties from
|
18
|
+
part = db.rootAssembly.instances['PART-1-1'] # define part
|
19
|
+
step_obj = db.steps[frequency_step]
|
20
|
+
|
21
|
+
part.ElementSet('ALL', part.elements) # get all elements (for full element and node matrix)
|
22
|
+
|
23
|
+
#%% Grab regions
|
24
|
+
region_full = part.elementSets['ALL']
|
25
|
+
|
26
|
+
#%% Get modal parameters
|
27
|
+
fn, m = wawi.ext.abq.get_modal_parameters(frequency_step)
|
28
|
+
|
29
|
+
#%% Get wind elements and mode shapes
|
30
|
+
node_matrix, element_matrix = wawi.ext.abq.get_element_matrices(region_full, obj=part)
|
31
|
+
node_labels = node_matrix[:,0]
|
32
|
+
nodes = wawi.ext.abq.create_list_of_nodes(part, node_labels)
|
33
|
+
|
34
|
+
# Export element definitions as json
|
35
|
+
el_data = dict(node_matrix=node_matrix.tolist(),
|
36
|
+
element_matrix=element_matrix.tolist())
|
37
|
+
|
38
|
+
with open('element.json', 'w') as f:
|
39
|
+
json.dump(el_data, f)
|
40
|
+
|
41
|
+
phi_full_disp = wawi.ext.abq.get_nodal_phi(step_obj, nodes, flatten_components=True, field_outputs=['U', 'UR'])
|
42
|
+
|
43
|
+
## ------------------- EXPORT MODES ----------------
|
44
|
+
modal_data = dict(omega_n=(fn*2*np.pi).tolist(), m=m.tolist(), phi=dict(full=phi_full_disp.tolist()))
|
45
|
+
|
46
|
+
with open('modal.json', 'w') as f:
|
47
|
+
json.dump(modal_data, f)
|
tests/test_IABSE_step11a.py
CHANGED
@@ -3,10 +3,10 @@ import pytest
|
|
3
3
|
import numpy as np
|
4
4
|
from math import isclose
|
5
5
|
|
6
|
-
# use the local wawi
|
7
|
-
import sys
|
8
|
-
import os
|
9
|
-
sys.path.insert(0,
|
6
|
+
# use the local wawi
|
7
|
+
#import sys
|
8
|
+
#import os
|
9
|
+
#sys.path.insert(0, r'C:\Users\aksef\OneDrive - Multiconsult\project\wawi\wawi_keep')
|
10
10
|
|
11
11
|
# import functions
|
12
12
|
from wawi.io import import_folder
|
@@ -108,7 +108,6 @@ def test_mean_speed_45():
|
|
108
108
|
# PSD response
|
109
109
|
S_exp = np.transpose(np.array( [ [0.0167, -0.007j], [0.007j, 0.00293] ] ))
|
110
110
|
|
111
|
-
|
112
111
|
model = import_folder(model_folder)
|
113
112
|
model.aero.windstate = iabse_11a_windstate(V)
|
114
113
|
|
@@ -121,11 +120,11 @@ def test_mean_speed_45():
|
|
121
120
|
omega = np.array([0.001, f])*np.pi*2
|
122
121
|
HH = eval_3d_fun(model.get_frf_fun(opt = 1), omega)
|
123
122
|
|
124
|
-
model.aero.sections['girder0'].
|
123
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
125
124
|
model.run_freqsim(omega,
|
126
125
|
include_selfexcited=['aero'],
|
127
126
|
include_action=['aero'],
|
128
|
-
print_progress=False
|
127
|
+
print_progress=False)
|
129
128
|
|
130
129
|
global_dof_ix = np.array([2,3])
|
131
130
|
S = model.get_result_psd(key='full',
|
@@ -170,12 +169,14 @@ def test_response_spectra(Vbuff, RS_vert_exp, RS_tors_exp):
|
|
170
169
|
model.aero.windstate = iabse_11a_windstate(Vbuff)
|
171
170
|
model.modal_dry.xi0 = .3e-2
|
172
171
|
model.aero.sections['girder0'].ADs = ADs(**flatplate_ads())
|
173
|
-
model.aero.sections['girder0'].
|
172
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
174
173
|
|
175
174
|
model.run_freqsim(omega_axis,
|
176
175
|
include_selfexcited=['aero'],
|
177
176
|
include_action=['aero'],
|
178
|
-
print_progress=False,
|
177
|
+
print_progress=False,
|
178
|
+
#merge_aero_sections=True
|
179
|
+
)
|
179
180
|
|
180
181
|
global_dof_ix = np.array([2,3])
|
181
182
|
S = model.get_result_psd(key='full',
|
@@ -204,12 +205,12 @@ def test_RMS_response(Vbuff, RMS_vert_exp, RMS_tors_exp):
|
|
204
205
|
model.aero.windstate = iabse_11a_windstate(Vbuff)
|
205
206
|
model.modal_dry.xi0 = .3e-2
|
206
207
|
model.aero.sections['girder0'].ADs = ADs(**flatplate_ads())
|
207
|
-
model.aero.sections['girder0'].
|
208
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
208
209
|
|
209
210
|
model.run_freqsim(omega_axis,
|
210
211
|
include_selfexcited=['aero'],
|
211
212
|
include_action=['aero'],
|
212
|
-
print_progress=False
|
213
|
+
print_progress=False)
|
213
214
|
|
214
215
|
stds = model.get_result_std(key = 'full')
|
215
216
|
|
tests/test_IABSE_step11c.py
CHANGED
@@ -5,9 +5,9 @@ from math import isclose
|
|
5
5
|
import dill
|
6
6
|
|
7
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'))
|
8
|
+
#import sys
|
9
|
+
#import os
|
10
|
+
#sys.path.insert(0, os.path.abspath('C:\\Users\\aksef\\Documents\\GitHub\\wawi'))
|
11
11
|
|
12
12
|
# import functions
|
13
13
|
from wawi.io import import_folder
|
@@ -166,11 +166,11 @@ def test_mean_speed_45():
|
|
166
166
|
omega = np.array([0.001, f])*np.pi*2
|
167
167
|
HH = eval_3d_fun(model.get_frf_fun(opt = 1), omega)
|
168
168
|
|
169
|
-
model.aero.sections['girder0'].
|
169
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
170
170
|
model.run_freqsim(omega,
|
171
171
|
include_selfexcited=['aero'],
|
172
172
|
include_action=['aero'],
|
173
|
-
print_progress=False
|
173
|
+
print_progress=False)
|
174
174
|
|
175
175
|
global_dof_ix = np.array([1,2,3])
|
176
176
|
S = model.get_result_psd(key='full',
|
@@ -225,13 +225,13 @@ def test_response_spectra(Vbuff, RS_horz_exp, RS_vert_exp, RS_tors_exp):
|
|
225
225
|
AD_funs = dill.load(file)
|
226
226
|
AD_s = AD_dict(AD_funs)
|
227
227
|
model.aero.sections['girder0'].ADs = ADs(**AD_s)
|
228
|
-
model.aero.sections['girder0'].
|
228
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
229
229
|
|
230
230
|
# run analysis
|
231
231
|
model.run_freqsim(omega_axis,
|
232
232
|
include_selfexcited=['aero'],
|
233
233
|
include_action=['aero'],
|
234
|
-
print_progress=False
|
234
|
+
print_progress=False)
|
235
235
|
|
236
236
|
# extract PSD
|
237
237
|
global_dof_ix = np.array([1,2,3])
|
@@ -265,13 +265,13 @@ def test_RMS_response(Vbuff, RMS_horz_exp, RMS_vert_exp, RMS_tors_exp):
|
|
265
265
|
AD_funs = dill.load(file)
|
266
266
|
AD_s = AD_dict(AD_funs)
|
267
267
|
model.aero.sections['girder0'].ADs = ADs(**AD_s)
|
268
|
-
model.aero.sections['girder0'].
|
268
|
+
model.aero.sections['girder0'].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
269
269
|
|
270
270
|
# run analysis
|
271
271
|
model.run_freqsim(omega_axis,
|
272
272
|
include_selfexcited=['aero'],
|
273
273
|
include_action=['aero'],
|
274
|
-
print_progress=False
|
274
|
+
print_progress=False)
|
275
275
|
|
276
276
|
# RMS responses
|
277
277
|
stds = model.get_result_std(key = 'full')
|
tests/test_IABSE_step2a.py
CHANGED
@@ -4,9 +4,9 @@ from math import isclose
|
|
4
4
|
import dill
|
5
5
|
|
6
6
|
# use the local wawi (Github folder) instead of the installed version (remove this when using the installed version)
|
7
|
-
import sys
|
8
|
-
import os
|
9
|
-
sys.path.insert(0, os.path.abspath('C:\\Users\\aksef\\Documents\\GitHub\\wawi'))
|
7
|
+
#import sys
|
8
|
+
#import os
|
9
|
+
#sys.path.insert(0, os.path.abspath('C:\\Users\\aksef\\Documents\\GitHub\\wawi'))
|
10
10
|
|
11
11
|
from wawi.io import import_folder
|
12
12
|
from wawi.model import Windstate
|
@@ -184,14 +184,14 @@ def test_RS_spectra():
|
|
184
184
|
model.aero.windstate = iabse_2a_windstate(V)
|
185
185
|
# admittance
|
186
186
|
for key in model.aero.sections:
|
187
|
-
model.aero.sections[key].
|
187
|
+
model.aero.sections[key].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
188
188
|
|
189
189
|
# run analysis
|
190
190
|
model.run_freqsim(omega,
|
191
191
|
include_selfexcited=['aero'],
|
192
192
|
include_action=['aero'],
|
193
|
-
print_progress=False,
|
194
|
-
|
193
|
+
print_progress=False,
|
194
|
+
ensure_at_peaks=False) # keep the given frequency axis
|
195
195
|
|
196
196
|
|
197
197
|
# extract PSD - at the midpsan
|
@@ -237,7 +237,7 @@ def test_RMS_response(Vbuff, RMS_horz_exp1, RMS_vert_exp1, RMS_tors_exp1, RMS_ho
|
|
237
237
|
model.aero.windstate = iabse_2a_windstate(Vbuff)
|
238
238
|
# admittance
|
239
239
|
for key in model.aero.sections:
|
240
|
-
model.aero.sections[key].
|
240
|
+
model.aero.sections[key].admittance = lambda fred: np.full((4, 3), davenport(fred))
|
241
241
|
|
242
242
|
#model.run_eig(w_initial=model.modal_dry.omega_n.tolist(), freq_kind=True, itmax=100) # alters integration
|
243
243
|
|
@@ -245,7 +245,7 @@ def test_RMS_response(Vbuff, RMS_horz_exp1, RMS_vert_exp1, RMS_tors_exp1, RMS_ho
|
|
245
245
|
model.run_freqsim(omega,
|
246
246
|
include_selfexcited=['aero'],
|
247
247
|
include_action=['aero'],
|
248
|
-
print_progress=False
|
248
|
+
print_progress=False)
|
249
249
|
# RMS responses
|
250
250
|
stds = model.get_result_std(key = 'full')
|
251
251
|
# global dofs
|
wawi/__init__.py
CHANGED
wawi/io.py
CHANGED
wawi/modal.py
CHANGED
@@ -192,7 +192,7 @@ def iteig(K, C, M, omega=None, omega_ref=0, input_functions=True, itmax=None, to
|
|
192
192
|
q[:, m] = phi[:,0]
|
193
193
|
|
194
194
|
if print_progress:
|
195
|
-
pp(m+2,2*ndofs, sym='>', postfix=' finished with iterative modal analysis.')
|
195
|
+
pp(m+2,2*ndofs+1, sym='>', postfix=' finished with iterative modal analysis.')
|
196
196
|
|
197
197
|
if print_progress:
|
198
198
|
print(' ')
|
@@ -323,7 +323,7 @@ def iteig_freq(K, C, M, omega=None, itmax=15, reference_omega=0, input_functions
|
|
323
323
|
q[:, m] = qi[:, m]
|
324
324
|
|
325
325
|
if print_progress:
|
326
|
-
pp(m+2,2*ndofs, sym='>', postfix=' finished with iterative modal analysis.')
|
326
|
+
pp(m+2 ,2*ndofs+1, sym='>', postfix=' finished with iterative modal analysis.')
|
327
327
|
|
328
328
|
if print_progress:
|
329
329
|
print(' ')
|
wawi/model/_model.py
CHANGED
@@ -16,6 +16,8 @@ from wawi.structural import freqsim
|
|
16
16
|
from wawi.tools import print_progress as pp
|
17
17
|
from wawi.wave import stochastic_linearize, waveaction_fft, harmonic_linearize
|
18
18
|
from wawi.wind import windaction, windaction_static
|
19
|
+
# from wawi.io import import_folder
|
20
|
+
|
19
21
|
import dill
|
20
22
|
|
21
23
|
|
@@ -266,6 +268,17 @@ class Model:
|
|
266
268
|
|
267
269
|
self.Cquad_lin = 0.0
|
268
270
|
|
271
|
+
# Not used due to circular referencing.
|
272
|
+
# @staticmethod
|
273
|
+
# def from_folder(*args, **kwargs):
|
274
|
+
# '''
|
275
|
+
# Alternative constructor. Passes all inputs to `wawi.io.import_folder`.
|
276
|
+
# '''
|
277
|
+
|
278
|
+
# model = import_folder(*args, **kwargs)
|
279
|
+
|
280
|
+
# return model
|
281
|
+
|
269
282
|
|
270
283
|
@staticmethod #alternative constructor
|
271
284
|
def from_wwi(path):
|
@@ -568,7 +581,7 @@ class Model:
|
|
568
581
|
pl.add_point_labels(np.vstack([wind_origin]), [f'U={self.aero.windstate.U0:.2f} m/s from heading {self.aero.windstate.direction:.1f} deg (CW)'])
|
569
582
|
|
570
583
|
# Plot wave arrow
|
571
|
-
if plot_wave_direction and self.hydro.seastate is not None:
|
584
|
+
if plot_wave_direction and self.hydro is not None and self.hydro.seastate is not None:
|
572
585
|
if self.hydro.seastate.homogeneous:
|
573
586
|
if wave_origin=='center':
|
574
587
|
wave_origin = origin*1
|
@@ -673,6 +686,8 @@ class Model:
|
|
673
686
|
return phi_tot
|
674
687
|
|
675
688
|
def get_result_psd(self, key='hydro', index=None, convert_to=None, modes=None):
|
689
|
+
# index: applied after transformation to requested csys (convert_to)
|
690
|
+
|
676
691
|
ix, ix_3d = self.get_mode_ix(modes)
|
677
692
|
|
678
693
|
if key is not None:
|
@@ -1321,4 +1336,22 @@ class Model:
|
|
1321
1336
|
if opt == 0:
|
1322
1337
|
return frf
|
1323
1338
|
else:
|
1324
|
-
return imp
|
1339
|
+
return imp
|
1340
|
+
|
1341
|
+
def get_node_ix(self, nodelabel):
|
1342
|
+
ix = np.where(self.eldef.get_node_labels()==nodelabel)[0]
|
1343
|
+
if len(ix)>0:
|
1344
|
+
ix = int(ix[0])
|
1345
|
+
else:
|
1346
|
+
ix = None
|
1347
|
+
|
1348
|
+
return ix
|
1349
|
+
|
1350
|
+
def get_node_ixs(self, nodelabels):
|
1351
|
+
return [self.get_node_ix(nodelabel) for nodelabel in nodelabels]
|
1352
|
+
|
1353
|
+
def get_aerosection_phi_and_x(self, key):
|
1354
|
+
ixs = self.aero.phi_ixs[key]
|
1355
|
+
x = np.vstack([node.coordinates for node in self.aero.eldef[key].nodes])
|
1356
|
+
|
1357
|
+
return ixs, x
|
wawi/time_domain.py
CHANGED
@@ -52,6 +52,51 @@ def simulate_mdof(S, omega, fs=None, tmax=None, reg_factor=None, zero_limit=1e-1
|
|
52
52
|
phase_angles=None, return_phase_angles=False, interpolation_kind='linear',
|
53
53
|
component_scaling=None, print_status=False):
|
54
54
|
|
55
|
+
'''
|
56
|
+
Simulate time series from given cross-spectral density matrix.
|
57
|
+
|
58
|
+
Parameters
|
59
|
+
----------------
|
60
|
+
S : float
|
61
|
+
cross-spectral density matrix (Ndofs x Ndofs x Nfreqs) as complex numpy array
|
62
|
+
omega : float
|
63
|
+
numpy array defining frequencies in rad/s
|
64
|
+
fs : float, optional
|
65
|
+
sampling frequency in Hz; if not given, the value is defined as two times the maximum of `omega`
|
66
|
+
tmax : float, optional
|
67
|
+
duration of realization in seconds
|
68
|
+
reg_factor : float, optional
|
69
|
+
to help the Cholesky decomposition to achieve a numerical solution,
|
70
|
+
a diagonal matrix with the norm of all frequency components of the matrix S scaled by the given factor
|
71
|
+
- if no value is given (--> None imposed), no regularization is conducted;
|
72
|
+
used as input to function `spectrum_to_process` which decomposes the spectral density
|
73
|
+
zero_limit : float, optional
|
74
|
+
frequency components where the norm of S is below this limit is set to zero
|
75
|
+
if no value is given (--> None imposed), no zero limit is applied;
|
76
|
+
used as input to function `spectrum_to_process` which decomposes the spectral density
|
77
|
+
phase_angles : float, optional
|
78
|
+
if previously conducted simulations are to be recreated, they can by inputting the phase angles
|
79
|
+
(to get the phase angles from simulation, see `return_phase_angles` input parameter)
|
80
|
+
return_phase_angles : bool, default=False
|
81
|
+
whether or not to return phase angle enabling recreation of the simulation
|
82
|
+
interpolation_kind : optional, default='linear'
|
83
|
+
interpolation type used for interpolation (to ensure that we get defined duration and sampling) prior to ifft
|
84
|
+
component_scaling : float, optional
|
85
|
+
values to use for scaling of components prior to decomposition (and thereafter rescale afterwards);
|
86
|
+
can help if some components are much smaller than others; size should match number of DOFs in S
|
87
|
+
print_status : False, optional
|
88
|
+
whether or not to print status messages
|
89
|
+
|
90
|
+
Returns
|
91
|
+
----------------
|
92
|
+
p : float
|
93
|
+
time history
|
94
|
+
t : float
|
95
|
+
numpy array with time axis values corresponding to `p`
|
96
|
+
alpha : float
|
97
|
+
phase angles, only returned if `return_phase_angles` is True
|
98
|
+
'''
|
99
|
+
|
55
100
|
if omega[0] !=0:
|
56
101
|
omega = np.insert(omega, 0, 0)
|
57
102
|
S = np.dstack([0*S[:,:,0], S])
|
wawi/wind.py
CHANGED
@@ -6,7 +6,7 @@ from scipy.special import jv as besselj, yv as bessely
|
|
6
6
|
from .general import rodrot, blkdiag
|
7
7
|
from .plot import plot_ads
|
8
8
|
|
9
|
-
conv_text='''
|
9
|
+
conv_text = r'''
|
10
10
|
-----------------------------------------------------
|
11
11
|
| |
|
12
12
|
| ~ ~ ~~~ ~ ~~ ~ /^^^^^^^^^^^^\ 88ooo... . . . |
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: wawi
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.12
|
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
|
@@ -43,6 +43,7 @@ Requires-Dist: trame
|
|
43
43
|
Requires-Dist: ipywidgets
|
44
44
|
Requires-Dist: pyvistaqt
|
45
45
|
Requires-Dist: beefpy
|
46
|
+
Dynamic: license-file
|
46
47
|
|
47
48
|

|
48
49
|
=======================
|
@@ -133,6 +134,13 @@ Examples
|
|
133
134
|
=======================
|
134
135
|
Examples are provided as Jupyter Notebooks in the [examples folder](https://github.com/knutankv/wawi/tree/main/examples).
|
135
136
|
|
137
|
+
The examples are structured in the following folders based on their topic:
|
138
|
+
|
139
|
+
* **0 Model generation and setup** - *Describing how a model is defined, either using input files together with the function `wawi.io.import_folder` or using the classes available in the `wawi.model` module directly (in the latter case, the open source Python library BEEF is used to create the required parameters directly in the notebook).*
|
140
|
+
* **1 Modal analysis** - *Describing how to set up iterative (and incremental) modal analyses to represent the contributions from aerodynamics and hydrodynamices. Also, an example showing how to set up a multi-modal flutter analysis is given.*
|
141
|
+
* **2 Response prediction** - *Describing how to conduct response analyses using WAWI. This includes assigning wind states, sea states, and the necessary commands to run a frequency domain analysis. Furthermore, more advanced topics such as wave-current interaction, inhomogeneous waves and stochastic linearization to represent quadratic drag damping are given in separate examples. Three models are considered: (i) a simple curved floating bridge, (ii) a single beam, (iii) a suspension bridge.*
|
142
|
+
* **3 Software interfacing** - *Describing how to export necessary data from other software (limited to Abaqus for now) to construct a WAWI model.*
|
143
|
+
|
136
144
|
References
|
137
145
|
=======================
|
138
146
|
|
@@ -1,28 +1,27 @@
|
|
1
|
-
examples/3 Software interfacing/Abaqus model export/bergsoysund-export.py,sha256
|
2
|
-
examples/3 Software interfacing/Abaqus model export/
|
3
|
-
tests/test_IABSE_step11a.py,sha256=
|
4
|
-
tests/test_IABSE_step11c.py,sha256=
|
5
|
-
tests/test_IABSE_step2a.py,sha256=
|
1
|
+
examples/3 Software interfacing/Abaqus model export/bergsoysund-export.py,sha256=3HSV009z5oqIUgM6B7xucUpGeh2f8SzC9FSiyP0zd7A,2760
|
2
|
+
examples/3 Software interfacing/Abaqus model export/hardanger-export.py,sha256=YiqS-TxnkydwVHE7k-57nP6CDsxqSXgWR3f8UytAubY,1603
|
3
|
+
tests/test_IABSE_step11a.py,sha256=zTWOxR78F0PNhNqiqodEcL65vdJXyMP78nkJumhy-RA,7915
|
4
|
+
tests/test_IABSE_step11c.py,sha256=TfxPlP70dhujKlSYbA-Gj4U-EJmYZ3jt6yjvX9wSXcA,10337
|
5
|
+
tests/test_IABSE_step2a.py,sha256=9pAd1em2IEY4k5N-jAigV3VGup0QsbUxnwSiziuMbUg,10134
|
6
6
|
tests/test_wind.py,sha256=r4rx6f8Tn-u4fn4gGPBMrL_JJQ2SVHGQiQ9sQuMQCPo,1707
|
7
|
-
wawi/__init__.py,sha256=
|
7
|
+
wawi/__init__.py,sha256=7vUvWFZzW67YG3yHPiBO_bsphhLLgEF4N7wdUkJeEq8,183
|
8
8
|
wawi/fe.py,sha256=22QKI1GlfsG7o_TpFXaKJfzmbO2_2zdIMaoJmaIZdmY,4001
|
9
9
|
wawi/general.py,sha256=xHRoDkcchrL6Y7pTUqGsjBHh8YBLvX9dYcNXXCjQap8,13787
|
10
10
|
wawi/identification.py,sha256=bVB6EVRR6J39OO9ckuzNJ6f0FwIo4cLqfYgrsIN89TE,1748
|
11
|
-
wawi/io.py,sha256=
|
12
|
-
wawi/modal.py,sha256=
|
11
|
+
wawi/io.py,sha256=cr8XLF7bwpTCxpZ84YjOyWjc5uuu-JjGv8vY9UKH-HI,25327
|
12
|
+
wawi/modal.py,sha256=L1Rs_YVEADOmsQL-hJ43eb8Nt5VpYuB1VHOjYK2O9X0,20252
|
13
13
|
wawi/plot.py,sha256=jllJcjZxTBqjzBoT4k9jLXVUnie8oqNr8371IJvCd3c,19791
|
14
14
|
wawi/prob.py,sha256=0nCdKdwkNf4M6sHyCZuYlt06gD0NmqRNfl4KesgySWA,215
|
15
15
|
wawi/random.py,sha256=MHPpyTlRJSJFkCmeTAmw4Q5K1BPoFVb0Nxg0jDhkuIM,871
|
16
16
|
wawi/signal.py,sha256=9HJs7VUhXOccuYPo12A0IUVoBIAJ2e_9F3rL-q3JuP4,1179
|
17
17
|
wawi/structural.py,sha256=t25ohH4uBbzUJ7Hqn_kUfYhxcikZkRp8da-9dn7aEbw,8341
|
18
|
-
wawi/time_domain.py,sha256=
|
18
|
+
wawi/time_domain.py,sha256=q8-H2xceP-2BmtOfbRQqYhD1JSb0z7jGq-dL_MzAX40,6122
|
19
19
|
wawi/tools.py,sha256=-hFBvf0qK4AMn2MQRhrOitDMMMKm2QuRkVfbPBefEkQ,332
|
20
20
|
wawi/wave.py,sha256=hhKg3KhKMBhOoCI7g8PFOGUbYgVhDyGmnYdBEdJ8mkY,16064
|
21
|
-
wawi/wind.py,sha256=
|
21
|
+
wawi/wind.py,sha256=VHy07IbrCJxlqR0Z5O5WRc9YE4jb-MqFbULPiXhj0NA,38211
|
22
22
|
wawi/wind_code.py,sha256=8OKLPpqc84obNNKBoYb2NunKjcn6a3i_pAWpIFEwg4Q,223
|
23
23
|
wawi/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
wawi/ext/abq.py,sha256=Wo-Zzb6b3lr_z7cNKTW-NdYJuVeAwZgwzlGhF_5Jym0,8905
|
25
|
-
wawi/ext/abq_legacy.py,sha256=WVhoPjRAru98NxYqpKp9_G8wwfJiLO4X4xFc-CvI0j4,16494
|
26
25
|
wawi/ext/ansys.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
26
|
wawi/ext/orcaflex.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
27
|
wawi/ext/sofistik.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -30,10 +29,10 @@ wawi/model/__init__.py,sha256=u6B-dugP76LBkOUVMs0KAoQ81PeRHwFL0M8MbNeAaJA,218
|
|
30
29
|
wawi/model/_aero.py,sha256=tvWMjMoVi9ZVBc3NZ_s-wSofbEk1cc5jf5s-Swv2RxQ,9337
|
31
30
|
wawi/model/_dry.py,sha256=KpmFlSinoY6DrSyc3Y0M8w1-cCC7VCFep-uzcqZsHz4,3940
|
32
31
|
wawi/model/_hydro.py,sha256=1tUj19OgvEjItNtBxXuPHf0zWtKv_ioTrOcgl9Ov3dg,26960
|
33
|
-
wawi/model/_model.py,sha256=
|
32
|
+
wawi/model/_model.py,sha256=ynZkyoU00crTAlu7sN0CmJsn-J8vwK7BDbMCh0pb-hI,53061
|
34
33
|
wawi/model/_screening.py,sha256=NRYkKq928z2lqMSUTpbQLls04td_9R_4dhkjU3Gv1oQ,3716
|
35
|
-
wawi-0.0.
|
36
|
-
wawi-0.0.
|
37
|
-
wawi-0.0.
|
38
|
-
wawi-0.0.
|
39
|
-
wawi-0.0.
|
34
|
+
wawi-0.0.12.dist-info/licenses/LICENSE,sha256=bH1aWhrNbbPLrYnVFRaoYYzcUr-figHjry-kGB7Tc54,1076
|
35
|
+
wawi-0.0.12.dist-info/METADATA,sha256=lXTUPijzmyd6QOJ2LmCPJaF7H_NWkysiOZkJkhlKqlU,6530
|
36
|
+
wawi-0.0.12.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
37
|
+
wawi-0.0.12.dist-info/top_level.txt,sha256=Nk5G_ZwgZRCb9ZMWZdr1M3QIskX6kCnlqeMl67N3zg8,20
|
38
|
+
wawi-0.0.12.dist-info/RECORD,,
|
@@ -1,67 +0,0 @@
|
|
1
|
-
from sys import path
|
2
|
-
from collections import OrderedDict
|
3
|
-
|
4
|
-
path.append('C:/Users/knutankv/git-repos/wawi/') # this is an easy quick fix to enable importing wawi package in Abaqus environment
|
5
|
-
savefolder = 'C:/Temp/'
|
6
|
-
|
7
|
-
import wawi.ext.abq
|
8
|
-
import json
|
9
|
-
import numpy as np
|
10
|
-
|
11
|
-
#%% Get (O) database object
|
12
|
-
db = wawi.ext.abq.get_db('odb')
|
13
|
-
|
14
|
-
#%% Definitions
|
15
|
-
frequency_step = 'Step-6'
|
16
|
-
part = db.rootAssembly.instances['BRIDGE-1']
|
17
|
-
step_obj = db.steps[frequency_step]
|
18
|
-
|
19
|
-
if 'ALL' not in part.elementSets: #CREATE SET OF ALL ELEMENTS IN PART
|
20
|
-
part.ElementSet('ALL', part.elements)
|
21
|
-
|
22
|
-
#%% Grab regions
|
23
|
-
region_full = part.elementSets['ALL']
|
24
|
-
region_hydro = part.nodeSets['SPRING']
|
25
|
-
|
26
|
-
#%% Get modal parameters
|
27
|
-
fn, m = wawi.ext.abq.get_modal_parameters(frequency_step)
|
28
|
-
|
29
|
-
#%% Get wind elements and mode shapes
|
30
|
-
node_matrix, element_matrix = wawi.ext.abq.get_element_matrices(region_full, obj=part)
|
31
|
-
node_labels = node_matrix[:,0]
|
32
|
-
|
33
|
-
# Export element definitions as json
|
34
|
-
el_data = dict(node_matrix=node_matrix.tolist(), element_matrix=element_matrix.tolist())
|
35
|
-
|
36
|
-
with open('element.json', 'w') as f:
|
37
|
-
json.dump(el_data, f)
|
38
|
-
|
39
|
-
phi_full_disp = wawi.ext.abq.get_nodal_phi(step_obj, node_labels, flatten_components=True)
|
40
|
-
|
41
|
-
#%% Get pontoon data
|
42
|
-
node_matrix_pontoons = wawi.ext.abq.get_element_matrices(region_hydro, obj=part, sort_nodes_fun=None)
|
43
|
-
node_labels = node_matrix_pontoons[:,0]
|
44
|
-
phi_h = wawi.ext.abq.get_nodal_phi(step_obj, node_labels, flatten_components=True)
|
45
|
-
|
46
|
-
# Export pontoon.json
|
47
|
-
pontoon_types = ['ptype_1']*48
|
48
|
-
rotations = np.zeros(48)
|
49
|
-
|
50
|
-
pontoon_data = OrderedDict()
|
51
|
-
|
52
|
-
for ix, node in enumerate(node_labels):
|
53
|
-
key = 'P'+str (ix+1)
|
54
|
-
pontoon_data[key] = dict(coordinates=node_matrix_pontoons[ix, 1:].tolist(),
|
55
|
-
node=node,
|
56
|
-
rotation=rotations[ix],
|
57
|
-
pontoon_type=pontoon_types[ix])
|
58
|
-
|
59
|
-
with open('pontoon.json', 'w') as f:
|
60
|
-
json.dump(pontoon_data, f)
|
61
|
-
|
62
|
-
## ------------------- EXPORT MODES ----------------
|
63
|
-
modal_data = dict(omega_n=(fn*2*np.pi).tolist(), m=m.tolist(), phi=dict(full=phi_full_disp.tolist(),
|
64
|
-
hydro=phi_h.tolist()))
|
65
|
-
|
66
|
-
with open('modal.json', 'w') as f:
|
67
|
-
json.dump(modal_data, f)
|
wawi/ext/abq_legacy.py
DELETED
@@ -1,462 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import pdb
|
3
|
-
|
4
|
-
from abaqus import *
|
5
|
-
from abaqus import session
|
6
|
-
from abaqusConstants import *
|
7
|
-
import __main__
|
8
|
-
import section
|
9
|
-
import regionToolset
|
10
|
-
import displayGroupMdbToolset as dgm
|
11
|
-
import step
|
12
|
-
import part
|
13
|
-
import material
|
14
|
-
import assembly
|
15
|
-
import interaction
|
16
|
-
import load
|
17
|
-
import mesh
|
18
|
-
import optimization
|
19
|
-
import job
|
20
|
-
import sketch
|
21
|
-
import visualization
|
22
|
-
import xyPlot
|
23
|
-
import displayGroupOdbToolset as dgo
|
24
|
-
import connectorBehavior
|
25
|
-
import symbolicConstants
|
26
|
-
import odbAccess
|
27
|
-
import shutil
|
28
|
-
|
29
|
-
import regionToolset
|
30
|
-
|
31
|
-
import csv
|
32
|
-
from copy import deepcopy
|
33
|
-
|
34
|
-
import numpy as np
|
35
|
-
import os
|
36
|
-
|
37
|
-
from wawi.general import merge_tr_phi
|
38
|
-
|
39
|
-
|
40
|
-
def export_wawi(odb_path, path):
|
41
|
-
pass
|
42
|
-
|
43
|
-
def get_modal_parameters(frequency_step):
|
44
|
-
'''
|
45
|
-
Output the modal parameters from frequency step of current output database.
|
46
|
-
|
47
|
-
Parameters
|
48
|
-
-------------
|
49
|
-
frequency_step : str
|
50
|
-
name of step containing the modal results (frequency step)
|
51
|
-
|
52
|
-
Returns
|
53
|
-
--------------
|
54
|
-
f : float
|
55
|
-
numpy array with undamped natural frequencies in Hz of all modes computed
|
56
|
-
m : float
|
57
|
-
numpy array with modal mass for all modes computed
|
58
|
-
'''
|
59
|
-
|
60
|
-
odb = get_db('odb')
|
61
|
-
history_region_key = odb.steps[frequency_step].historyRegions.keys()[0]
|
62
|
-
|
63
|
-
ftemp = odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs['EIGFREQ'].data
|
64
|
-
f = np.array([x[1] for x in ftemp])
|
65
|
-
|
66
|
-
if 'GM' in odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs.keys():
|
67
|
-
mtemp = odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs['GM'].data
|
68
|
-
m = np.array([x[1] for x in mtemp])
|
69
|
-
else:
|
70
|
-
m = np.ones(np.shape(f)) #if no GM field is available, mass normalization is assumed used on eigenvalues
|
71
|
-
return f, m
|
72
|
-
|
73
|
-
def session_is_odb():
|
74
|
-
"""
|
75
|
-
Check if current session is ODB.
|
76
|
-
|
77
|
-
Returns:
|
78
|
-
is_odb: boolean indicating if the session is odb or not
|
79
|
-
"""
|
80
|
-
is_odb =(('session' in locals() or 'session' in globals()) and
|
81
|
-
session.viewports['Viewport: 1'].displayedObject is not None and
|
82
|
-
hasattr(session.viewports['Viewport: 1'].displayedObject, 'jobData'))
|
83
|
-
|
84
|
-
return is_odb
|
85
|
-
|
86
|
-
def get_db(db_type):
|
87
|
-
"""
|
88
|
-
Return the current database (either a model or an odb object).
|
89
|
-
|
90
|
-
If a model db is wanted and no model is active, the model in the mdb is selected regardless,
|
91
|
-
as long as there is only one model open in the mdb. If no database fits the requirements, None is returned.
|
92
|
-
|
93
|
-
Args:
|
94
|
-
db_type: 'odb' or 'model'
|
95
|
-
Returns:
|
96
|
-
db: database
|
97
|
-
|
98
|
-
NTNU / Knut Andreas Kvaale, 2018
|
99
|
-
"""
|
100
|
-
if db_type is 'model' or db_type is 'mdb':
|
101
|
-
if not session_is_odb():
|
102
|
-
db = mdb.models[session.viewports['Viewport: 1'].displayedObject.modelName]
|
103
|
-
elif len(mdb.models.keys()) is 1:
|
104
|
-
db = mdb.models[mdb.models.keys()[0]]
|
105
|
-
elif len(mdb.models.keys()) > 1:
|
106
|
-
raise AttributeError('No model is not active, and more than one model is available in model database. Impossible to select correct.')
|
107
|
-
else:
|
108
|
-
db = None
|
109
|
-
else:
|
110
|
-
if session_is_odb():
|
111
|
-
db = session.viewports[session.currentViewportName].displayedObject
|
112
|
-
else:
|
113
|
-
db = None
|
114
|
-
|
115
|
-
return db
|
116
|
-
|
117
|
-
|
118
|
-
def modeshapes_from_region(regionobjs, frequency_step, field_outputs):
|
119
|
-
"""
|
120
|
-
Get modes (shape, frequency and modal mass) from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
|
121
|
-
|
122
|
-
"""
|
123
|
-
odb = get_db('odb')
|
124
|
-
|
125
|
-
if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
|
126
|
-
raise TypeError('Type of input step is not modal!')
|
127
|
-
|
128
|
-
Nmodes = len(odb.steps[frequency_step].frames)-1
|
129
|
-
phi = [None]*len(field_outputs)
|
130
|
-
|
131
|
-
for iout, field_output in enumerate(field_outputs):
|
132
|
-
Ndofs, point_ranges, dof_ranges = count_region(regionobjs, field_output, odb.steps[frequency_step].frames[0])
|
133
|
-
phio = np.zeros([np.sum(Ndofs), Nmodes])
|
134
|
-
foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
|
135
|
-
|
136
|
-
for ix, regionobj in enumerate(regionobjs):
|
137
|
-
current_dof_range = np.arange(dof_ranges[ix], dof_ranges[ix+1])
|
138
|
-
|
139
|
-
for mode in range(0, Nmodes):
|
140
|
-
foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
|
141
|
-
phio[:, mode] = np.reshape((np.array([v.data for v in foobj.getSubset(region=regionobj).values])), [np.sum(Ndofs)])
|
142
|
-
|
143
|
-
phi[iout] = phio
|
144
|
-
|
145
|
-
return phi
|
146
|
-
|
147
|
-
def str2region(instance_name, setnames, region_type, db_type, *args):
|
148
|
-
"""
|
149
|
-
Construct a region object from a string defining the set name or a region object.
|
150
|
-
|
151
|
-
Args:
|
152
|
-
instance_name: string defining the set name (either node or element set) or a region object
|
153
|
-
setnames: name of set asked for
|
154
|
-
region_type: type of set ('elements' or 'nodes')
|
155
|
-
db_type: 'odb' or 'model'
|
156
|
-
Optional args:
|
157
|
-
db: database object, either mdb.model[...] or session.openOdb(...) - will get from viewport 1 if not given
|
158
|
-
Returns:
|
159
|
-
regionobjs: region objects
|
160
|
-
|
161
|
-
"""
|
162
|
-
|
163
|
-
is_assembly = instance_name is None
|
164
|
-
|
165
|
-
set_type = settype(region_type, db_type)
|
166
|
-
standard_sets = {'nodes': [' ALL NODES'], 'elements': [' ALL ELEMENTS']}
|
167
|
-
|
168
|
-
if setnames is None:
|
169
|
-
setnames = standard_sets[region_type]
|
170
|
-
|
171
|
-
if len(args)==1: # a db has been input
|
172
|
-
db = args[0]
|
173
|
-
isodb = hasattr(db,'jobData') #check if the input db is reffering to result/odb or model
|
174
|
-
|
175
|
-
else:
|
176
|
-
db = get_db(db_type)
|
177
|
-
|
178
|
-
if db is None:
|
179
|
-
raise TypeError('The database is empty. Please input a database object, or input parameters that matches one. Remember that odbs have to be active to get the db automatically!')
|
180
|
-
|
181
|
-
if is_assembly: # Instance name is given
|
182
|
-
regroot = db.rootAssembly
|
183
|
-
else:
|
184
|
-
regroot = db.rootAssembly.instances[instance_name]
|
185
|
-
|
186
|
-
regionobjs = [None] * np.size(setnames)
|
187
|
-
|
188
|
-
for ix,thisname in enumerate(setnames):
|
189
|
-
regionobjs[ix] = getattr(regroot, set_type)[thisname]
|
190
|
-
|
191
|
-
return regionobjs
|
192
|
-
|
193
|
-
|
194
|
-
def settype(region_type, db_type):
|
195
|
-
"""
|
196
|
-
Define the string used to get set based on region type and database type.
|
197
|
-
|
198
|
-
Args:
|
199
|
-
region_type: 'element' or 'node'
|
200
|
-
db_type: 'odb' or 'mdb'
|
201
|
-
Returns:
|
202
|
-
set_string: string used to obtain set data from database object (odb or mdb)
|
203
|
-
|
204
|
-
"""
|
205
|
-
if db_type is 'odb':
|
206
|
-
if 'element' in region_type.lower():
|
207
|
-
set_string = 'elementSets'
|
208
|
-
elif 'node' in region_type.lower():
|
209
|
-
set_string = 'nodeSets'
|
210
|
-
else:
|
211
|
-
raise TypeError('Wrong input!')
|
212
|
-
elif db_type == 'mdb' or db_type == 'model':
|
213
|
-
set_string = 'sets'
|
214
|
-
|
215
|
-
return set_string
|
216
|
-
|
217
|
-
def count_region(regionobjs, field_output, frame):
|
218
|
-
"""
|
219
|
-
Count the number of DOFs and points in the specified region objects for given field output and frame object.
|
220
|
-
|
221
|
-
Args:
|
222
|
-
regionobjs: list of region objects to query
|
223
|
-
field_output: string specifying field output
|
224
|
-
frame: frame object (from where fieldOutputs field is accessible)
|
225
|
-
Returns:
|
226
|
-
Ndofs: number of DOFs for each region (list)
|
227
|
-
point_ranges: point/node ranges for each region (list of lists)
|
228
|
-
dof_ranges: dof ranges for each region (list of lists)
|
229
|
-
"""
|
230
|
-
odb = get_db('odb')
|
231
|
-
|
232
|
-
Npoints = [len(frame.fieldOutputs[field_output].getSubset(region=regionobj).values) for regionobj in regionobjs]
|
233
|
-
Ndofs = np.dot(Npoints, len(frame.fieldOutputs[field_output].componentLabels))
|
234
|
-
|
235
|
-
dof_ranges = np.cumsum(np.append([0], Ndofs))
|
236
|
-
point_ranges = np.cumsum(np.append([0], Npoints))
|
237
|
-
|
238
|
-
return Ndofs, point_ranges, dof_ranges
|
239
|
-
|
240
|
-
|
241
|
-
def wind_set_data(set_strings, frequency_step, instance, db_type, field_outputs, mode_type='nodes', use_node_region_acronym=False):
|
242
|
-
# use_node_region_acronym: if True, a node set with identical name as the element set given in set_strings is picked and the nodes assumed to correspond to the element. If not the case, the element set is used to establish the nodes (and thus phi)
|
243
|
-
wind_element_regions = str2region(instance, set_strings, 'elements', db_type) # index 0 is girder, index 1 is columns
|
244
|
-
|
245
|
-
if use_node_region_acronym:
|
246
|
-
wind_node_regions = str2region(instance, set_strings, 'nodes', db_type)
|
247
|
-
|
248
|
-
element_labels = [None]*len(set_strings)
|
249
|
-
element_node_indices = [None]*len(set_strings)
|
250
|
-
node_labels = [None]*len(set_strings)
|
251
|
-
node_coordinates = [None]*len(set_strings)
|
252
|
-
phi_ae = [None]*len(set_strings)
|
253
|
-
|
254
|
-
for set_ix, set_string in enumerate(set_strings):
|
255
|
-
element_labels[set_ix], element_node_indices[set_ix], nl, nc = region2elnodes_legacy(wind_element_regions[set_ix])
|
256
|
-
if use_node_region_acronym:
|
257
|
-
nl, nc = region2nodes(wind_node_regions[set_ix])
|
258
|
-
|
259
|
-
node_labels[set_ix] = nl
|
260
|
-
node_coordinates[set_ix] = nc
|
261
|
-
|
262
|
-
# Establish modal transformation matrix, phi
|
263
|
-
if mode_type=='nodes':
|
264
|
-
for set_ix, set_string in enumerate(set_strings):
|
265
|
-
phi_ae_temp = modeshapes_from_nodelist(node_labels[set_ix], frequency_step, field_outputs)
|
266
|
-
phi_ae[set_ix] = merge_tr_phi(phi_ae_temp[0][0], phi_ae_temp[0][1])
|
267
|
-
elif mode_type=='elements':
|
268
|
-
for set_ix, set_string in enumerate(set_strings):
|
269
|
-
phi_ae_temp, integration_points = modeshapes_from_elementlist(element_labels[set_ix], frequency_step, field_outputs)
|
270
|
-
phi_ae[set_ix] = merge_tr_phi(phi_ae_temp[0], phi_ae_temp[1])
|
271
|
-
|
272
|
-
return element_labels, element_node_indices, node_labels, node_coordinates, phi_ae
|
273
|
-
|
274
|
-
|
275
|
-
def region2elnodes_legacy(regionobjs, avoid_central_nodes=True):
|
276
|
-
"""
|
277
|
-
Give node labels (indices) for each node in specified element set.
|
278
|
-
|
279
|
-
Args:
|
280
|
-
regionobjs: region objects to query for node labels
|
281
|
-
|
282
|
-
Returns:
|
283
|
-
element_labels: the labels (indices) of the elements in list
|
284
|
-
element_node_indices: the labels (indices) of the ndoes in each element; list of lists
|
285
|
-
node_labels: all the nodes labels (indices) in a flattened list
|
286
|
-
node_coordinates: node coordinates for each element (list of lists)
|
287
|
-
|
288
|
-
"""
|
289
|
-
|
290
|
-
objstr = regionobjs.__repr__()
|
291
|
-
instance_name = objstr.split(".instances['")[1].split("'].")[0]
|
292
|
-
|
293
|
-
if '.odb' in objstr:
|
294
|
-
db = get_db('odb')
|
295
|
-
dbtype = 'odb'
|
296
|
-
else:
|
297
|
-
db = get_db('mdb')
|
298
|
-
dbtype = 'mdb'
|
299
|
-
|
300
|
-
# Get the elements object root
|
301
|
-
if len(np.shape(regionobjs.elements))>1:
|
302
|
-
elements = regionobjs.elements[0]
|
303
|
-
else:
|
304
|
-
elements = regionobjs.elements
|
305
|
-
|
306
|
-
# Get all element labels and corresponding connectivity (node labels)
|
307
|
-
element_labels = np.array([element.label for element in elements])
|
308
|
-
|
309
|
-
# Instance object
|
310
|
-
instance = db.rootAssembly.instances[instance_name]
|
311
|
-
|
312
|
-
# Full arrays labels and coordinates
|
313
|
-
all_node_labels = np.array([node.label for node in instance.nodes]).flatten([-1])
|
314
|
-
all_node_coords = np.array([node.coordinates for node in instance.nodes])
|
315
|
-
|
316
|
-
# Nodes belonging to all the elements
|
317
|
-
if dbtype is 'odb':
|
318
|
-
element_node_labels = [element.connectivity for element in elements]
|
319
|
-
else:
|
320
|
-
element_node_labels = [[all_node_labels[ix] for ix in element.connectivity] for element in elements]
|
321
|
-
|
322
|
-
if avoid_central_nodes:
|
323
|
-
element_node_labels = [[node_lb[0], node_lb[-1]] for node_lb in element_node_labels]
|
324
|
-
|
325
|
-
node_labels = np.unique(np.array(element_node_labels).flatten())
|
326
|
-
|
327
|
-
nodeixs = np.array([np.where(all_node_labels==node)[0] for node in node_labels]).flatten()
|
328
|
-
node_coordinates = all_node_coords[nodeixs, :]
|
329
|
-
element_node_indices = np.array([np.array([np.where(node_labels==node_label) for node_label in node_labels_for_element]).flatten() for node_labels_for_element in element_node_labels])
|
330
|
-
|
331
|
-
return element_labels, element_node_indices, node_labels, node_coordinates
|
332
|
-
|
333
|
-
|
334
|
-
def region2nodes(regionobj, sortfun=None):
|
335
|
-
"""
|
336
|
-
Give node labels (indices) of nodes in specified node set(s).
|
337
|
-
|
338
|
-
Args:
|
339
|
-
regionobj: region object to query for node labels
|
340
|
-
|
341
|
-
Optional args:
|
342
|
-
sortfun: function with three inputs (1: x, 2: y, 3:z) to sort nodes by
|
343
|
-
examples: sortfun = lambda x, y, z: -np.arctan2(y,x)
|
344
|
-
sortfun = lambda x, y, z: x
|
345
|
-
|
346
|
-
Returns:
|
347
|
-
node_labels: list with nodelabels
|
348
|
-
|
349
|
-
NTNU / Knut Andreas Kvaale, 2018
|
350
|
-
"""
|
351
|
-
|
352
|
-
set_name = regionobj.__repr__().split("ets[")[1].split("'")[1]
|
353
|
-
|
354
|
-
if len(np.shape(regionobj.nodes))>1:
|
355
|
-
nodes = regionobj.nodes[0]
|
356
|
-
else:
|
357
|
-
nodes = regionobj.nodes
|
358
|
-
|
359
|
-
node_labels = np.array([node.label for node in nodes])
|
360
|
-
node_coordinates = np.array([node.coordinates for node in nodes])
|
361
|
-
|
362
|
-
if sortfun != None:
|
363
|
-
vals = sortfun(x=node_coordinates[:,0], y=node_coordinates[:,1], z=node_coordinates[:,2])
|
364
|
-
sort_ix = np.argsort(vals)
|
365
|
-
node_labels = node_labels[:, sort_ix]
|
366
|
-
node_coordinates = node_coordinates[sort_ix, :]
|
367
|
-
|
368
|
-
return node_labels, node_coordinates
|
369
|
-
|
370
|
-
def modeshapes_from_nodelist(node_labels, frequency_step, field_outputs):
|
371
|
-
"""
|
372
|
-
Get mode shapes from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
|
373
|
-
|
374
|
-
Args:
|
375
|
-
node_labels:
|
376
|
-
frequency_step:
|
377
|
-
field_outputs:
|
378
|
-
Returns:
|
379
|
-
phi: mode shape transformation matrix, ordered as NumPy matrices in list for each specified outputs
|
380
|
-
|
381
|
-
"""
|
382
|
-
odb = get_db('odb')
|
383
|
-
|
384
|
-
if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
|
385
|
-
raise TypeError('Type of input step is not modal!')
|
386
|
-
|
387
|
-
Nnodes = len(node_labels)
|
388
|
-
Nmodes = len(odb.steps[frequency_step].frames) - 1
|
389
|
-
phi = [None]*len(field_outputs)
|
390
|
-
basedisp = [None]*len(field_outputs)
|
391
|
-
|
392
|
-
for iout, field_output in enumerate(field_outputs):
|
393
|
-
foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
|
394
|
-
|
395
|
-
Ndofs = len(foobj0.values[0].data)
|
396
|
-
phio = np.zeros([Ndofs*Nnodes, Nmodes])
|
397
|
-
|
398
|
-
# Get correct data indices to get correct order (as given in node_labels)
|
399
|
-
all_nodes = [value.nodeLabel for value in foobj0.values]
|
400
|
-
data_indices = [None]*Nnodes
|
401
|
-
|
402
|
-
for ix, node in enumerate(node_labels):
|
403
|
-
data_indices[ix] = all_nodes.index(node)
|
404
|
-
|
405
|
-
basedisp[iout] = np.array([foobj0.values[data_ix].data for data_ix in data_indices]).flatten()
|
406
|
-
|
407
|
-
for mode in range(0, Nmodes):
|
408
|
-
foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
|
409
|
-
phio[:, mode] = np.array([foobj.values[data_ix].data for data_ix in data_indices]).flatten()
|
410
|
-
|
411
|
-
phi[iout] = phio
|
412
|
-
|
413
|
-
return phi, basedisp
|
414
|
-
|
415
|
-
|
416
|
-
def modeshapes_from_elementlist(element_labels, frequency_step, field_outputs):
|
417
|
-
"""
|
418
|
-
Get mode shape from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
|
419
|
-
|
420
|
-
Args:
|
421
|
-
node_labels:
|
422
|
-
frequency_step:
|
423
|
-
field_outputs:
|
424
|
-
Returns:
|
425
|
-
phi: mode shape transformation matrix, ordered as NumPy matrices in list for each specified outputs
|
426
|
-
|
427
|
-
"""
|
428
|
-
odb = get_db('odb')
|
429
|
-
|
430
|
-
if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
|
431
|
-
raise TypeError('Type of input step is not modal!')
|
432
|
-
|
433
|
-
|
434
|
-
Nmodes = len(odb.steps[frequency_step].frames) - 1
|
435
|
-
phi = [None]*len(field_outputs)
|
436
|
-
integration_points = [None]*len(field_outputs)
|
437
|
-
|
438
|
-
for iout, field_output in enumerate(field_outputs):
|
439
|
-
foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
|
440
|
-
Ndofs = len(foobj0.values[0].data)
|
441
|
-
|
442
|
-
# Get correct data indices to get correct order (as given in node_labels)
|
443
|
-
all_elements = [value.elementLabel for value in foobj0.values]
|
444
|
-
all_integration_points = [value.integrationPoint for value in foobj0.values]
|
445
|
-
|
446
|
-
Nintpoints = len(element_labels) # number of integration points (same element label might appear multiple times if multiple integration points in element)
|
447
|
-
phio = np.zeros([Ndofs*Nintpoints, Nmodes])
|
448
|
-
|
449
|
-
data_indices = [None]*Nintpoints
|
450
|
-
|
451
|
-
for ix, element in enumerate(element_labels):
|
452
|
-
data_indices[ix] = all_elements.index(element)
|
453
|
-
|
454
|
-
for mode in range(0, Nmodes):
|
455
|
-
foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
|
456
|
-
phio[:, mode] = np.array([foobj.values[data_ix].data for data_ix in data_indices]).flatten()
|
457
|
-
|
458
|
-
integration_points[iout] = [all_integration_points[ix] for ix in data_indices]
|
459
|
-
phi[iout] = phio
|
460
|
-
|
461
|
-
|
462
|
-
return phi, integration_points
|
File without changes
|
File without changes
|