wawi 0.0.8__tar.gz → 0.0.11__tar.gz
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-0.0.8/wawi.egg-info → wawi-0.0.11}/PKG-INFO +10 -2
- {wawi-0.0.8 → wawi-0.0.11}/README.md +7 -0
- wawi-0.0.11/examples/3 Software interfacing/Abaqus model export/bergsoysund-export.py +72 -0
- wawi-0.0.11/examples/3 Software interfacing/Abaqus model export/test.py +67 -0
- {wawi-0.0.8 → wawi-0.0.11}/pyproject.toml +3 -3
- wawi-0.0.11/wawi/__init__.py +12 -0
- wawi-0.0.11/wawi/ext/__init__.py +0 -0
- wawi-0.0.11/wawi/ext/abq.py +259 -0
- wawi-0.0.11/wawi/ext/ansys.py +0 -0
- wawi-0.0.11/wawi/ext/orcaflex.py +0 -0
- wawi-0.0.11/wawi/ext/sofistik.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/io.py +1 -1
- wawi-0.0.11/wawi/model/__init__.py +11 -0
- wawi-0.0.11/wawi/model/_aero.py +363 -0
- wawi-0.0.11/wawi/model/_dry.py +141 -0
- wawi-0.0.11/wawi/model/_hydro.py +882 -0
- wawi-0.0.11/wawi/model/_model.py +1338 -0
- wawi-0.0.11/wawi/model/_screening.py +124 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/time_domain.py +45 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/wind.py +1 -1
- {wawi-0.0.8 → wawi-0.0.11/wawi.egg-info}/PKG-INFO +10 -2
- {wawi-0.0.8 → wawi-0.0.11}/wawi.egg-info/SOURCES.txt +14 -1
- wawi-0.0.11/wawi.egg-info/top_level.txt +5 -0
- wawi-0.0.8/wawi/__init__.py +0 -10
- wawi-0.0.8/wawi.egg-info/top_level.txt +0 -1
- {wawi-0.0.8 → wawi-0.0.11}/LICENSE +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/setup.cfg +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/tests/test_IABSE_step11a.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/tests/test_IABSE_step11c.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/tests/test_IABSE_step2a.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/tests/test_wind.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/fe.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/general.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/identification.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/modal.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/plot.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/prob.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/random.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/signal.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/structural.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/tools.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/wave.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi/wind_code.py +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi.egg-info/dependency_links.txt +0 -0
- {wawi-0.0.8 → wawi-0.0.11}/wawi.egg-info/requires.txt +0 -0
@@ -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.11
|
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
|
|
@@ -87,6 +87,13 @@ Examples
|
|
87
87
|
=======================
|
88
88
|
Examples are provided as Jupyter Notebooks in the [examples folder](https://github.com/knutankv/wawi/tree/main/examples).
|
89
89
|
|
90
|
+
The examples are structured in the following folders based on their topic:
|
91
|
+
|
92
|
+
* **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).*
|
93
|
+
* **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.*
|
94
|
+
* **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.*
|
95
|
+
* **3 Software interfacing** - *Describing how to export necessary data from other software (limited to Abaqus for now) to construct a WAWI model.*
|
96
|
+
|
90
97
|
References
|
91
98
|
=======================
|
92
99
|
|
@@ -0,0 +1,72 @@
|
|
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 (O) database object
|
14
|
+
db = wawi.ext.abq.get_db('odb')
|
15
|
+
|
16
|
+
#%% Definitions
|
17
|
+
frequency_step = 'Step-1'
|
18
|
+
part = db.rootAssembly.instances['TRUSSPART']
|
19
|
+
step_obj = db.steps[frequency_step]
|
20
|
+
|
21
|
+
if 'ALL' not in part.elementSets: #CREATE SET OF ALL ELEMENTS IN PART
|
22
|
+
part.ElementSet('ALL', part.elements)
|
23
|
+
|
24
|
+
#%% Grab regions
|
25
|
+
region_full = part.elementSets['ALL']
|
26
|
+
region_hydro = db.rootAssembly.nodeSets['PALL']
|
27
|
+
|
28
|
+
#%% Get modal parameters
|
29
|
+
fn, m = wawi.ext.abq.get_modal_parameters(frequency_step)
|
30
|
+
|
31
|
+
#%% Get wind elements and mode shapes
|
32
|
+
node_matrix, element_matrix = wawi.ext.abq.get_element_matrices(region_full, obj=part)
|
33
|
+
node_labels = node_matrix[:,0]
|
34
|
+
nodes = wawi.ext.abq.create_list_of_nodes(part, node_labels)
|
35
|
+
|
36
|
+
# Export element definitions as json
|
37
|
+
el_data = dict(node_matrix=node_matrix.tolist(), element_matrix=element_matrix.tolist())
|
38
|
+
|
39
|
+
with open('element.json', 'w') as f:
|
40
|
+
json.dump(el_data, f)
|
41
|
+
|
42
|
+
phi_full_disp = wawi.ext.abq.get_nodal_phi(step_obj, nodes, flatten_components=True, field_outputs=['UT', 'UR'])
|
43
|
+
|
44
|
+
#%% Get pontoon data
|
45
|
+
node_matrix_pontoons = wawi.ext.abq.get_element_matrices(region_hydro, obj=part)
|
46
|
+
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
|
+
|
50
|
+
# 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
|
+
pontoon_data = OrderedDict()
|
56
|
+
|
57
|
+
for ix, node in enumerate(node_labels_pontoons):
|
58
|
+
key = 'P'+str (ix+1)
|
59
|
+
pontoon_data[key] = dict(coordinates=node_matrix_pontoons[ix, 1:].tolist(),
|
60
|
+
node=node,
|
61
|
+
rotation=rotations[ix],
|
62
|
+
pontoon_type=pontoon_types[ix])
|
63
|
+
|
64
|
+
with open('pontoon.json', 'w') as f:
|
65
|
+
json.dump(pontoon_data, f)
|
66
|
+
|
67
|
+
## ------------------- EXPORT MODES ----------------
|
68
|
+
modal_data = dict(omega_n=(fn*2*np.pi).tolist(), m=m.tolist(), phi=dict(full=phi_full_disp.tolist(),
|
69
|
+
hydro=phi_h.tolist()))
|
70
|
+
|
71
|
+
with open('modal.json', 'w') as f:
|
72
|
+
json.dump(modal_data, f)
|
@@ -0,0 +1,67 @@
|
|
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)
|
@@ -27,12 +27,12 @@ dependencies = ["plotly", "pandas", "numpy", "pyvista[jupyter]>=0.38.1",
|
|
27
27
|
"beefpy"]
|
28
28
|
|
29
29
|
|
30
|
-
[tool.setuptools]
|
31
|
-
packages = ["wawi"]
|
32
|
-
|
33
30
|
[tool.setuptools.dynamic]
|
34
31
|
version = {attr = "wawi.__version__"}
|
35
32
|
|
33
|
+
[tool.setuptools.packages]
|
34
|
+
find = {}
|
35
|
+
|
36
36
|
[project.urls]
|
37
37
|
repository = "https://github.com/knutankv/wawi"
|
38
38
|
documentation = "https://knutankv.github.io/wawi/"
|
File without changes
|
@@ -0,0 +1,259 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import numpy as np
|
3
|
+
import pdb
|
4
|
+
|
5
|
+
from abaqus import *
|
6
|
+
from abaqus import session
|
7
|
+
from abaqusConstants import *
|
8
|
+
import __main__
|
9
|
+
import section
|
10
|
+
import regionToolset
|
11
|
+
import displayGroupMdbToolset as dgm
|
12
|
+
import step
|
13
|
+
import part
|
14
|
+
import material
|
15
|
+
import assembly
|
16
|
+
import interaction
|
17
|
+
import load
|
18
|
+
import mesh
|
19
|
+
import optimization
|
20
|
+
import job
|
21
|
+
import sketch
|
22
|
+
import visualization
|
23
|
+
import xyPlot
|
24
|
+
import displayGroupOdbToolset as dgo
|
25
|
+
import connectorBehavior
|
26
|
+
import symbolicConstants
|
27
|
+
import odbAccess
|
28
|
+
import shutil
|
29
|
+
|
30
|
+
import regionToolset
|
31
|
+
|
32
|
+
import csv
|
33
|
+
from copy import deepcopy
|
34
|
+
|
35
|
+
|
36
|
+
def get_db(db_type):
|
37
|
+
"""
|
38
|
+
Return the current database (either a model or an odb object).
|
39
|
+
|
40
|
+
If a model db is wanted and no model is active, the model in the mdb is selected regardless,
|
41
|
+
as long as there is only one model open in the mdb. If no database fits the requirements, None is returned.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
db_type: 'odb' or 'model'
|
45
|
+
Returns:
|
46
|
+
db: database
|
47
|
+
|
48
|
+
NTNU / Knut Andreas Kvaale, 2018
|
49
|
+
"""
|
50
|
+
if db_type is 'model' or db_type is 'mdb':
|
51
|
+
if not session_is_odb():
|
52
|
+
db = mdb.models[session.viewports['Viewport: 1'].displayedObject.modelName]
|
53
|
+
elif len(mdb.models.keys()) is 1:
|
54
|
+
db = mdb.models[mdb.models.keys()[0]]
|
55
|
+
elif len(mdb.models.keys()) > 1:
|
56
|
+
raise AttributeError('No model is not active, and more than one model is available in model database. Impossible to select correct.')
|
57
|
+
else:
|
58
|
+
db = None
|
59
|
+
else:
|
60
|
+
if session_is_odb():
|
61
|
+
db = session.viewports[session.currentViewportName].displayedObject
|
62
|
+
else:
|
63
|
+
db = None
|
64
|
+
|
65
|
+
return db
|
66
|
+
|
67
|
+
def session_is_odb():
|
68
|
+
"""
|
69
|
+
Check if current session is ODB.
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
is_odb: boolean indicating if the session is odb or not
|
73
|
+
"""
|
74
|
+
is_odb =(('session' in locals() or 'session' in globals()) and
|
75
|
+
session.viewports['Viewport: 1'].displayedObject is not None and
|
76
|
+
hasattr(session.viewports['Viewport: 1'].displayedObject, 'jobData'))
|
77
|
+
|
78
|
+
return is_odb
|
79
|
+
|
80
|
+
def sort_nodes(nodes, sort_nodes_fun=lambda node: node.label):
|
81
|
+
if sort_nodes_fun is not None:
|
82
|
+
sort_val = [sort_nodes_fun(node) for node in nodes]
|
83
|
+
sort_ix = np.argsort(sort_val)
|
84
|
+
nodes_new = [None] * len(nodes)
|
85
|
+
for node,ix in zip(nodes,sort_ix):
|
86
|
+
nodes_new[ix] = node
|
87
|
+
|
88
|
+
return nodes_new
|
89
|
+
else:
|
90
|
+
return nodes
|
91
|
+
|
92
|
+
def get_element_matrices(region, obj=None, sort_nodes_fun=lambda node: node.label):
|
93
|
+
|
94
|
+
if region.nodes is None: #element region
|
95
|
+
if obj is None:
|
96
|
+
raise ValueError('If region is of element type, `obj` must be given as input. This is either an `instance` object or a `rootAssembly`')
|
97
|
+
|
98
|
+
elements = region.elements
|
99
|
+
element_labels = [el.label for el in elements]
|
100
|
+
element_matrix = np.zeros([len(element_labels), 3])
|
101
|
+
|
102
|
+
node_labels = []
|
103
|
+
for ix,el in enumerate(elements):
|
104
|
+
element_matrix[ix,0] = el.label
|
105
|
+
nodes = list(el.connectivity)
|
106
|
+
if len(nodes)==3:
|
107
|
+
__ = nodes.pop(1) #remove middle node
|
108
|
+
element_matrix[ix, 1:] = nodes
|
109
|
+
|
110
|
+
for node in nodes:
|
111
|
+
if node not in node_labels:
|
112
|
+
node_labels.append(node)
|
113
|
+
|
114
|
+
nodes = [obj.getNodeFromLabel(node) for node in node_labels]
|
115
|
+
nodes = sort_nodes(nodes, sort_nodes_fun=sort_nodes_fun)
|
116
|
+
node_matrix = create_node_matrix(nodes)
|
117
|
+
return node_matrix, element_matrix
|
118
|
+
|
119
|
+
else: # node region
|
120
|
+
if type(region.nodes) is tuple:
|
121
|
+
nodes = region.nodes[0]
|
122
|
+
else:
|
123
|
+
nodes = region.nodes
|
124
|
+
nodes = sort_nodes(nodes, sort_nodes_fun=sort_nodes_fun)
|
125
|
+
node_matrix = create_node_matrix(nodes)
|
126
|
+
|
127
|
+
return node_matrix
|
128
|
+
|
129
|
+
|
130
|
+
def create_list_of_nodes(region, node_labels):
|
131
|
+
return [region.getNodeFromLabel(int(label)) for label in node_labels]
|
132
|
+
|
133
|
+
def create_list_of_elements(region, element_labels):
|
134
|
+
return [region.getElementFromLabel(int(label)) for label in element_labels]
|
135
|
+
|
136
|
+
def create_node_matrix(nodes):
|
137
|
+
labels = np.hstack([node.label for node in nodes])[:,np.newaxis]
|
138
|
+
coordinates = np.vstack([node.coordinates for node in nodes])
|
139
|
+
node_matrix = np.hstack([labels, coordinates])
|
140
|
+
|
141
|
+
return node_matrix
|
142
|
+
|
143
|
+
def get_nodal_phi(step_obj, nodes, field_outputs=['U', 'UR'], flatten_components=True, return_base_disp=False):
|
144
|
+
|
145
|
+
if step_obj.domain != MODAL: #MODAL is a variable in abaqusConstants
|
146
|
+
raise TypeError('Type of input step is not modal!')
|
147
|
+
|
148
|
+
n_nodes = len(nodes)
|
149
|
+
n_modes = len(step_obj.frames) - 1
|
150
|
+
|
151
|
+
phi = dict()
|
152
|
+
basedisp = dict()
|
153
|
+
n_dofs = dict()
|
154
|
+
|
155
|
+
for iout, field_output in enumerate(field_outputs):
|
156
|
+
foobj0 = step_obj.frames[0].fieldOutputs[field_output]
|
157
|
+
|
158
|
+
n_dofs[field_output] = len(foobj0.values[0].data)
|
159
|
+
phio = np.zeros([n_dofs[field_output]*n_nodes, n_modes])
|
160
|
+
|
161
|
+
# Get correct data indices to get correct order (as given in node_labels)
|
162
|
+
basedisp[field_output] = np.array([foobj0.getSubset(region=node).values[0].data for node in nodes]).flatten()
|
163
|
+
|
164
|
+
for mode in range(0, n_modes):
|
165
|
+
foobj = step_obj.frames[mode+1].fieldOutputs[field_output]
|
166
|
+
phio[:, mode] = np.array([foobj.getSubset(region=node).values[0].data for node in nodes]).flatten()
|
167
|
+
|
168
|
+
phi[field_output] = phio*1
|
169
|
+
|
170
|
+
if flatten_components:
|
171
|
+
phi_merged = [None]*n_modes
|
172
|
+
|
173
|
+
for mode in range(n_modes):
|
174
|
+
phi_merged[mode] = np.hstack([np.array(phi[key][:, mode]).reshape([-1,n_dofs[key]]) for key in field_outputs]).flatten()
|
175
|
+
|
176
|
+
basedisp = np.hstack([np.array(basedisp[key]).reshape([-1,n_dofs[key]]) for key in field_outputs]).flatten()
|
177
|
+
phi = np.vstack(phi_merged).T
|
178
|
+
|
179
|
+
if return_base_disp:
|
180
|
+
return phi, basedisp
|
181
|
+
else:
|
182
|
+
return phi
|
183
|
+
|
184
|
+
|
185
|
+
def get_element_phi(step_obj, elements, field_outputs=['SF', 'SM'], flatten_components=True, return_integration_points=False):
|
186
|
+
if step_obj.domain != MODAL: #MODAL is a variable in abaqusConstants
|
187
|
+
raise TypeError('Type of input step is not modal!')
|
188
|
+
|
189
|
+
n_modes = len(step_obj.frames) - 1
|
190
|
+
n_dofs = dict()
|
191
|
+
phi = dict()
|
192
|
+
integration_points = dict()
|
193
|
+
|
194
|
+
for iout, field_output in enumerate(field_outputs):
|
195
|
+
foobj0 = step_obj.frames[0].fieldOutputs[field_output]
|
196
|
+
n_dofs[field_output] = len(foobj0.values[0].data)
|
197
|
+
|
198
|
+
# Get correct data indices to get correct order (as given in node_labels)
|
199
|
+
all_integration_points = [value.integrationPoint for value in foobj0.values]
|
200
|
+
|
201
|
+
n_int = len(elements) # number of integration points (same element label might appear multiple times if multiple integration points in element)
|
202
|
+
phio = np.zeros([n_dofs[field_output]*n_int, n_modes])
|
203
|
+
|
204
|
+
data_indices = [None]*n_int
|
205
|
+
|
206
|
+
for mode in range(0, n_modes):
|
207
|
+
foobj = step_obj.frames[mode+1].fieldOutputs[field_output]
|
208
|
+
phio[:, mode] = np.array([foobj.getSubset(region=el)[0].data for el in elements]).flatten()
|
209
|
+
|
210
|
+
integration_points[field_output] = [all_integration_points[ix] for ix in data_indices]
|
211
|
+
phi[field_output] = phio*1
|
212
|
+
|
213
|
+
if flatten_components:
|
214
|
+
phi_merged = [None]*n_modes
|
215
|
+
|
216
|
+
for mode in range(n_modes):
|
217
|
+
phi_merged[mode] = np.hstack([np.array(phi[key][:, mode]).reshape([-1,n_dofs[key]]) for key in field_outputs]).flatten()
|
218
|
+
|
219
|
+
integration_points = np.hstack([np.array(integration_points[key]).reshape([-1,n_dofs[key]]) for key in field_outputs]).flatten()
|
220
|
+
phi = np.vstack(phi_merged).T
|
221
|
+
|
222
|
+
|
223
|
+
if return_integration_points:
|
224
|
+
return phi, integration_points
|
225
|
+
else:
|
226
|
+
return phi
|
227
|
+
|
228
|
+
return phi, integration_points
|
229
|
+
|
230
|
+
|
231
|
+
def get_modal_parameters(frequency_step):
|
232
|
+
'''
|
233
|
+
Output the modal parameters from frequency step of current output database.
|
234
|
+
|
235
|
+
Parameters
|
236
|
+
-------------
|
237
|
+
frequency_step : str
|
238
|
+
name of step containing the modal results (frequency step)
|
239
|
+
|
240
|
+
Returns
|
241
|
+
--------------
|
242
|
+
f : float
|
243
|
+
numpy array with undamped natural frequencies in Hz of all modes computed
|
244
|
+
m : float
|
245
|
+
numpy array with modal mass for all modes computed
|
246
|
+
'''
|
247
|
+
|
248
|
+
odb = get_db('odb')
|
249
|
+
history_region_key = odb.steps[frequency_step].historyRegions.keys()[0]
|
250
|
+
|
251
|
+
ftemp = odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs['EIGFREQ'].data
|
252
|
+
f = np.array([x[1] for x in ftemp])
|
253
|
+
|
254
|
+
if 'GM' in odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs.keys():
|
255
|
+
mtemp = odb.steps[frequency_step].historyRegions[history_region_key].historyOutputs['GM'].data
|
256
|
+
m = np.array([x[1] for x in mtemp])
|
257
|
+
else:
|
258
|
+
m = np.ones(np.shape(f)) #if no GM field is available, mass normalization is assumed used on eigenvalues
|
259
|
+
return f, m
|
File without changes
|
File without changes
|
File without changes
|