wawi 0.0.3__py3-none-any.whl → 0.0.5__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
wawi/abq.py DELETED
@@ -1,1128 +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 csv
30
- from copy import deepcopy
31
-
32
- import numpy as np
33
- import os
34
-
35
- from .general import merge_tr_phi
36
-
37
- '''
38
- Abaqus interaction module
39
- '''
40
-
41
- ## Functions to retrieve data from ODB
42
-
43
- def modalparameters(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
-
74
- def modeshapes_from_region(regionobjs, frequency_step, field_outputs):
75
- """
76
- Get modes (shape, frequency and modal mass) from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
77
-
78
- Args:
79
- regionobjs: Abaqus region objects in list
80
- frequency_step: name of frequency step
81
- field_outputs: list of strings with field output quantities, e.g., ['U', 'UR']
82
- Returns:
83
- phi: mode shape transformation matrix, ordered as NumPy matrices in list for each specified outputs
84
- f: undamped natural frequencies
85
- m: modal mass
86
- output_dict: dictionary to access correct index in output phi
87
-
88
- AAJ / Knut Andreas Kvaale, 2017
89
- Further developed NTNU / Knut Andreas Kvaale, 2018
90
- """
91
- odb = get_db('odb')
92
-
93
- if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
94
- raise TypeError('Type of input step is not modal!')
95
-
96
- Nmodes = len(odb.steps[frequency_step].frames)-1
97
- phi = [None]*len(field_outputs)
98
-
99
- for iout, field_output in enumerate(field_outputs):
100
- Ndofs, point_ranges, dof_ranges = count_region(regionobjs, field_output, odb.steps[frequency_step].frames[0])
101
- phio = np.zeros([np.sum(Ndofs), Nmodes])
102
- foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
103
-
104
- for ix, regionobj in enumerate(regionobjs):
105
- current_dof_range = np.arange(dof_ranges[ix], dof_ranges[ix+1])
106
-
107
- for mode in range(0, Nmodes):
108
- foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
109
- phio[:, mode] = np.reshape((np.array([v.data for v in foobj.getSubset(region=regionobj).values])), [np.sum(Ndofs)])
110
-
111
- phi[iout] = phio
112
-
113
- return phi
114
-
115
-
116
- def modeshapes_from_nodelist(node_labels, frequency_step, field_outputs):
117
- """
118
- Get mode shapes from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
119
-
120
- Args:
121
- node_labels:
122
- frequency_step:
123
- field_outputs:
124
- Returns:
125
- phi: mode shape transformation matrix, ordered as NumPy matrices in list for each specified outputs
126
-
127
- NTNU / Knut Andreas Kvaale, 2018
128
- """
129
- odb = get_db('odb')
130
-
131
- if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
132
- raise TypeError('Type of input step is not modal!')
133
-
134
- Nnodes = len(node_labels)
135
- Nmodes = len(odb.steps[frequency_step].frames) - 1
136
- phi = [None]*len(field_outputs)
137
- basedisp = [None]*len(field_outputs)
138
-
139
- for iout, field_output in enumerate(field_outputs):
140
- foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
141
-
142
- Ndofs = len(foobj0.values[0].data)
143
- phio = np.zeros([Ndofs*Nnodes, Nmodes])
144
-
145
- # Get correct data indices to get correct order (as given in node_labels)
146
- all_nodes = [value.nodeLabel for value in foobj0.values]
147
- data_indices = [None]*Nnodes
148
-
149
- for ix, node in enumerate(node_labels):
150
- data_indices[ix] = all_nodes.index(node)
151
-
152
- basedisp[iout] = np.array([foobj0.values[data_ix].data for data_ix in data_indices]).flatten()
153
-
154
- for mode in range(0, Nmodes):
155
- foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
156
- phio[:, mode] = np.array([foobj.values[data_ix].data for data_ix in data_indices]).flatten()
157
-
158
- phi[iout] = phio
159
-
160
- return phi, basedisp
161
-
162
-
163
- def modeshapes_from_elementlist(element_labels, frequency_step, field_outputs):
164
- """
165
- Get mode shape from "Frequency step" (eigenvalue analysis) in active Abaqus ODB.
166
-
167
- Args:
168
- node_labels:
169
- frequency_step:
170
- field_outputs:
171
- Returns:
172
- phi: mode shape transformation matrix, ordered as NumPy matrices in list for each specified outputs
173
-
174
- NTNU / Knut Andreas Kvaale, 2018
175
- """
176
- odb = get_db('odb')
177
-
178
- if odb.steps[frequency_step].domain != MODAL: #MODAL is a variable in abaqusConstants
179
- raise TypeError('Type of input step is not modal!')
180
-
181
-
182
- Nmodes = len(odb.steps[frequency_step].frames) - 1
183
- phi = [None]*len(field_outputs)
184
- integration_points = [None]*len(field_outputs)
185
-
186
- for iout, field_output in enumerate(field_outputs):
187
- foobj0 = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
188
- Ndofs = len(foobj0.values[0].data)
189
-
190
- # Get correct data indices to get correct order (as given in node_labels)
191
- all_elements = [value.elementLabel for value in foobj0.values]
192
- all_integration_points = [value.integrationPoint for value in foobj0.values]
193
-
194
- Nintpoints = len(element_labels) # number of integration points (same element label might appear multiple times if multiple integration points in element)
195
- phio = np.zeros([Ndofs*Nintpoints, Nmodes])
196
-
197
- data_indices = [None]*Nintpoints
198
-
199
- for ix, element in enumerate(element_labels):
200
- data_indices[ix] = all_elements.index(element)
201
-
202
- for mode in range(0, Nmodes):
203
- foobj = odb.steps[frequency_step].frames[mode+1].fieldOutputs[field_output]
204
- phio[:, mode] = np.array([foobj.values[data_ix].data for data_ix in data_indices]).flatten()
205
-
206
- integration_points[iout] = [all_integration_points[ix] for ix in data_indices]
207
- phi[iout] = phio
208
-
209
-
210
- return phi, integration_points
211
-
212
-
213
- def modeshapes_from_set_xydata(field_output, components, output_position, instance_name, set_name, region_type):
214
- """
215
- Get mode shapes from "Frequency step" (eigenvalue analysis) in active Abaqus ODB from specified sets.
216
-
217
- Args: NOT FINISHED
218
- field_output:
219
- components:
220
- data_position:
221
- output_position:
222
- set_name:
223
- region_type:
224
- Returns:
225
- phi: mode shape transformation matrix (Numpy array)
226
-
227
- NTNU / Knut Andreas Kvaale, 2018
228
- """
229
-
230
- set_names = [(instance_name + '.' +set_name)]
231
-
232
- odb = get_db('odb')
233
- n_components = len(components)
234
- xy_data = [None]*n_components
235
-
236
- if region_type == 'element':
237
- data_position = INTEGRATION_POINT
238
- elif region_type == 'node':
239
- data_position = NODAL
240
-
241
- if output_position == 'element':
242
- output_position = ELEMENT_NODAL
243
-
244
- for ix, component in enumerate(components):
245
- refinement = [[COMPONENT, component]]
246
- variable = [[field_output, data_position, refinement]]
247
-
248
- if region_type == 'element':
249
- xy_data[ix] = session.xyDataListFromField(odb=odb, outputPosition=output_position, variable=variable, elementSets=set_names)
250
- else:
251
- xy_data[ix] = session.xyDataListFromField(odb=odb, outputPosition=output_position, variable=variable, nodeSets=set_names)
252
-
253
- n_elements = len(xy_data[0])
254
- n_modes = len(xy_data[0][0])
255
-
256
- phi = np.zeros([n_components*n_elements, n_modes])
257
- for compix, component in enumerate(xy_data):
258
- for elix, element in enumerate(component):
259
- for mode in range(0, n_modes):
260
- phi[elix*n_components + compix, mode] = element[mode][1]
261
-
262
-
263
- return phi, xy_data
264
-
265
- ## MODIFY ODB OR MDB
266
- def set_view_variable(var, component):
267
- """
268
- Set a new view variable and component in current odb session.
269
-
270
- Args:
271
- var: variable name
272
- component: component to display
273
-
274
- NTNU / Knut Andreas Kvaale, 2018
275
- """
276
- position = {NODAL}
277
- session.viewports['Viewport: 1'].odbDisplay.setPrimaryVariable(variableLabel=var, outputPosition=NODAL, refinement=(COMPONENT, component),)
278
-
279
-
280
- def get_db(db_type):
281
- """
282
- Return the current database (either a model or an odb object).
283
-
284
- If a model db is wanted and no model is active, the model in the mdb is selected regardless,
285
- as long as there is only one model open in the mdb. If no database fits the requirements, None is returned.
286
-
287
- Args:
288
- db_type: 'odb' or 'model'
289
- Returns:
290
- db: database
291
-
292
- NTNU / Knut Andreas Kvaale, 2018
293
- """
294
- if db_type is 'model' or db_type is 'mdb':
295
- if not session_is_odb():
296
- db = mdb.models[session.viewports['Viewport: 1'].displayedObject.modelName]
297
- elif len(mdb.models.keys()) is 1:
298
- db = mdb.models[mdb.models.keys()[0]]
299
- elif len(mdb.models.keys()) > 1:
300
- raise AttributeError('No model is not active, and more than one model is available in model database. Impossible to select correct.')
301
- else:
302
- db = None
303
- else:
304
- if session_is_odb():
305
- db = session.viewports[session.currentViewportName].displayedObject
306
- else:
307
- db = None
308
-
309
- return db
310
-
311
-
312
-
313
- ## MODIFY ODB
314
- def unlock_odb():
315
- """
316
- Unlock current ODB file.
317
-
318
- Returns:
319
- odb: database (odb) object
320
-
321
- NTNU / Knut Andreas Kvaale, 2018
322
- """
323
- odb = session.viewports[session.currentViewportName].displayedObject
324
-
325
- if odb.isReadOnly:
326
- load_path = odb.path
327
- odb.close()
328
- odb = odbAccess.openOdb(load_path, readOnly=False)
329
- session.viewports['Viewport: 1'].setValues(displayedObject=session.odbs[load_path])
330
-
331
- return odb
332
-
333
-
334
- def copy_and_unlock_odb():
335
- """
336
- Copy and unlock current ODB file.
337
-
338
- Returns:
339
- odb: database (odb) object
340
-
341
- NTNU / Knut Andreas Kvaale, 2018
342
- """
343
- odb = session.viewports[session.currentViewportName].displayedObject
344
- old_file_path = odb.path
345
- new_file_path = odb.path.split('.odb')[0]+'_org.odb'
346
-
347
- shutil.copyfile(old_file_path, new_file_path) #copy the old file
348
-
349
- odb.close()
350
- odb = odbAccess.openOdb(old_file_path, readOnly=False)
351
- session.viewports['Viewport: 1'].setValues(displayedObject=session.odbs[old_file_path])
352
-
353
- return odb
354
-
355
-
356
- def session_is_odb():
357
- """
358
- Check if current session is ODB.
359
-
360
- Returns:
361
- is_odb: boolean indicating if the session is odb or not
362
-
363
- NTNU / Knut Andreas Kvaale, 2018
364
- """
365
- is_odb =(('session' in locals() or 'session' in globals()) and
366
- session.viewports['Viewport: 1'].displayedObject is not None and
367
- hasattr(session.viewports['Viewport: 1'].displayedObject, 'jobData'))
368
-
369
- return is_odb
370
-
371
-
372
- def save_and_reopen_odb():
373
- """
374
- Save and reopen database (odb) as read-only.
375
-
376
- Returns:
377
- odb: odb object
378
-
379
- NTNU / Knut Andreas Kvaale, 2018
380
- """
381
- odb = get_db('odb')
382
- odb.save()
383
- load_path = odb.path
384
- odb.close()
385
-
386
- odb = odbAccess.openOdb(load_path, readOnly=True)
387
-
388
- return odb
389
-
390
-
391
- def add_response_step_from_modal(phi_response, field_outputs, modal_var, frequency_step, step_name, region_strings, region_type, instance_name, description):
392
- """
393
- Add an artificial step in Abaqus ODB for response data.
394
-
395
- Args:
396
- phi_response: phi of the requested response quantities (list with one matrix for each response quantities)
397
- field_outputs: names of field output variables
398
- modal_var: covariance matrix for the generalized (modal) DOFs
399
- frequency_step: name of the new artificial step_name
400
- step_name: node set name or region object that define what nodes / DOFs phi refers to
401
- regionobjs: Abaqus region objects in list
402
- instance_name: name of the instance
403
- description: frame description
404
-
405
- NTNU / Knut Andreas Kvaale, 2018
406
- """
407
-
408
- odb = copy_and_unlock_odb()
409
- regionobjs = str2region(instance_name, region_strings, region_type, 'odb')
410
- instance = odb.rootAssembly.instances[instance_name]
411
-
412
- step_data = odb.Step(name=step_name, description='Response step', domain=TIME, timePeriod=0)
413
- frame = step_data.Frame(incrementNumber=0, description='Response', frameValue=0)
414
-
415
- type_dict = {'SF': [TENSOR_3D_SURFACE, INTEGRATION_POINT, 'Section forces'], 'SM': [TENSOR_3D_SURFACE, INTEGRATION_POINT, 'Section moments'], 'U': [VECTOR, NODAL, 'Spatial displacement'], 'UR': [VECTOR, NODAL, 'Rotational displacement'] }
416
-
417
- for ix, field_output in enumerate(field_outputs):
418
- foobj_ref = odb.steps[frequency_step].frames[0].fieldOutputs[field_output]
419
- phi = phi_response[ix]
420
- region_type = type_dict[field_output][1]
421
- comps = len(odb.steps[frequency_step].frames[0].fieldOutputs[field_output].componentLabels)
422
-
423
- sigma = np.sqrt(np.sum((np.dot(phi, modal_var) * phi), axis=1)) # Calculate sigma (square root of covariance matrix) from modal coordinates
424
- sigma_comp = np.reshape(sigma, [-1, 3]).astype('float')
425
- data = [list(this) for this in sigma_comp]
426
-
427
- foobj = frame.FieldOutput(name=field_output, description=type_dict[field_output][2], type=type_dict[field_output][0], validInvariants=())
428
-
429
- N = len(odb.steps[frequency_step].frames[0].fieldOutputs[field_output].values)
430
- Ndofs, point_ranges, dof_ranges = count_region(regionobjs, field_output, odb.steps[frequency_step].frames[0])
431
-
432
- for regix,regionobj in enumerate(regionobjs):
433
- good_ix, good_entries = good_element_ix(foobj_ref, regionobj)
434
- point_range = range(point_ranges[regix],point_ranges[regix+1])
435
-
436
- foobj.addData(position=region_type, instance=instance, labels=good_entries, data=data)
437
-
438
- step_data.setDefaultField(foobj)
439
-
440
- odb = save_and_reopen_odb()
441
-
442
- return odb
443
-
444
-
445
- def add_std_to_frame(odb, frame, instance_name, modal_var, phi, regionobj, field_output, reference_step):
446
- '''
447
- Under development. Not verified.
448
- '''
449
- if odb.isReadOnly:
450
- raise TypeError('ODB is read only. Unable to add data.')
451
-
452
- type_dict = {'SF': [TENSOR_3D_SURFACE, INTEGRATION_POINT, 'Section forces'], 'SM': [TENSOR_3D_SURFACE, INTEGRATION_POINT, 'Section moments'], 'U': [VECTOR, NODAL, 'Spatial displacement'], 'UR': [VECTOR, NODAL, 'Rotational displacement'] }
453
- foobj_ref = odb.steps[reference_step].frames[0].fieldOutputs[field_output]
454
-
455
- region_type = type_dict[field_output][1]
456
- comps = len(odb.steps[reference_step].frames[0].fieldOutputs[field_output].componentLabels)
457
-
458
- sigma = np.sqrt(np.sum((np.dot(phi, modal_var) * phi), axis=1)) # Calculate sigma (square root of covariance matrix) from modal coordinates
459
- sigma_comp = np.reshape(sigma, [-1, comps]).astype('float')
460
- data = [list(this) for this in sigma_comp]
461
-
462
- # If already exists, don't create new, but assign to that.
463
- if field_output not in frame.fieldOutputs.keys():
464
- foobj = frame.FieldOutput(name=field_output, description=type_dict[field_output][2], type=type_dict[field_output][0], validInvariants=())
465
- else:
466
- foobj = frame.fieldOutputs[field_output]
467
-
468
- N = len(odb.steps[reference_step].frames[0].fieldOutputs[field_output].values)
469
- good_ix, good_entries = good_element_ix(foobj_ref, regionobj)
470
- instance = odb.rootAssembly.instances[instance_name]
471
-
472
- foobj.addData(position=region_type, instance=instance, labels=good_entries, data=data)
473
- step_data.setDefaultField(foobj)
474
-
475
-
476
-
477
- def add_complex_mode_step(phi, eigvals, instance_name, step_name, region):
478
- """
479
- Add an artificial step in Abaqus ODB for complex modes.
480
-
481
- Args:
482
- phi: complex eigenvector matrix
483
- eigvals: complex eigenvalues
484
- instance_name: name of the instance
485
- step_name: name of the new artificial step_name
486
- regionobj: Abaqus region object
487
-
488
- Knut Andreas Kvaale, 2018
489
- """
490
-
491
- odb = unlock_odb()
492
- complex_step = odb.Step(name=step_name, description='Complex modes', domain=MODAL)
493
- frame0 = complex_step.Frame(incrementNumber=0, description='Base state', frameValue=0)
494
- frame_data = frame0.FieldOutput(name='U', description='Spatial displacement', type=VECTOR, validInvariants=(MAGNITUDE,))
495
- instance = odb.rootAssembly.instances[instance_name]
496
-
497
- for m, lambdam in enumerate(eigvals):
498
- phim = np.reshape(phi[:, m], (-1, 3)).astype('float')
499
- xim = -np.real(lambdam)/abs(lambdam)
500
-
501
- freqm_ud_rad = abs(lambdam)
502
- freqm_d_rad = abs(np.imag(lambdam))
503
- freqm_ud_Hz = freqm_ud_rad/(2*np.pi)
504
-
505
- periodm_ud = 2*np.pi/abs(lambdam)
506
-
507
- description_m = 'Mode ' + str(m+1) + ': f = ' + str(freqm_ud_Hz) + 'Hz | om = ' + str(freqm_ud_rad) + 'rad/s | T = ' + str(periodm_ud) + 's | xi = ' + str(xim*100) + '%'
508
-
509
- frame_m = complex_step.Frame(incrementNumber=m+1, description=description_m, frameValue=freqm_ud_Hz)
510
- frame_data = frame_m.FieldOutput(name='U', description='Spatial displacement', type=VECTOR, validInvariants=(MAGNITUDE,))
511
- nodelabels = np.array([node.label for node in regionobj.nodes[0]]).astype('int')
512
-
513
- frame_data.addData(position=NODAL, instance=instance, labels=nodelabels, data=np.real(phim), conjugateData=np.imag(phim))
514
-
515
- odb.save()
516
- load_path = odb.path
517
- odb.close()
518
- odb = odbAccess.openOdb(load_path, readOnly=True)
519
-
520
- ## MODIFY MDB
521
- def mass_and_stiffness_input(stiffness,mass,pontoon_set_names,pont_nodes,trans_mats,filename):
522
- pontoons = len(pontoon_set_names)
523
- if len(pont_nodes) != pontoons or len(trans_mats)!=pontoons:
524
- raise ValueError('Mismatch between dimensions for input variables: pontoon_set_names, pont_nodes and trans_mats')
525
- f = open(filename, 'w')
526
-
527
- for pontoon in range(0,pontoons):
528
- f.write('********************************PONTOON NUMBER {0} ************************************* \n'.format(str(pontoon+1)))
529
- f.write('*USER ELEMENT, LINEAR, NODES=1, UNSYM, TYPE=U{0}00 \n'.format(str(pontoon+1))) # Defines a linear user element
530
- f.write('1, 2, 3, 4, 5, 6 \n') # The element has one node with 6 DOFS
531
-
532
- T = trans_mats[pontoon]
533
-
534
- K = np.dot(np.dot(T.transpose(), stiffness),T)
535
- M = np.dot(np.dot(T.transpose(), mass),T)
536
-
537
- f.write('*MATRIX, TYPE=MASS \n') # Defines the mass matrix in GLOBAL coordinate system
538
- for n in range(0,6):
539
- string1 = ','.join(map(str, M[n, 0:4]))
540
- string2 = ','.join(map(str, M[n, 4:6]))
541
- f.write(string1 + '\n' + string2 +'\n')
542
-
543
- f.write('*MATRIX, TYPE=STIFFNESS \n')
544
- for n in range(0,6):
545
- string1 = ','.join(map(str, K[n, 0:4]))
546
- string2 = ','.join(map(str, K[n, 4:6]))
547
- f.write(string1 + '\n' + string2 +'\n')
548
-
549
- f.write('*ELEMENT, TYPE=U{0}00, ELSET={1} \n'.format(str(pontoon+1),pontoon_set_names[pontoon])) #Introduce one user element into the FE model
550
- f.write('800{0}, {1} \n'.format(str(pontoon+1),pont_nodes[pontoon])) #Numbering elements as 8001,8002,...,8007, followed by first node number forming the element
551
- f.write('*UEL PROPERTY, ELSET={0} \n'.format(pontoon_set_names[pontoon]))
552
-
553
-
554
- def update_input(freq,wadam_file,input_file,pontoon_set_names,pont_nodes,trans_mats):
555
- from .io import import_wadam_mat
556
- static_mass, stiffness, added_mass, damping, frequency = import_wadam_mat(wadam_file)
557
- mass = freq_sysmat(added_mass,frequency,freq)+static_mass
558
- mass_and_stiffness_input(stiffness,mass,pontoon_set_names,pont_nodes,trans_mats,input_file)
559
- print('Input file '+ input_file + ' is modified to correspond to added mass at f = ' + str(freq) + ' Hz.')
560
-
561
-
562
- def imperfection_input(node_labels, displacement_vector, input_file=None, rotations=False):
563
-
564
- d = np.array(displacement_vector)
565
-
566
- if rotations is True:
567
- n_nodes = len(d)/6
568
- d_trans = np.zeros([n_nodes*3])
569
- for node in range(0, n_nodes):
570
- d_trans[node*3:node*3+3] = d[node*6:node*6+3]
571
-
572
- d = d_trans
573
- else:
574
- n_nodes = len(d)/3
575
-
576
- mat = np.hstack([np.array(node_labels)[:, np.newaxis], d.reshape(-1, 3)])
577
-
578
- if input_file != None:
579
- open(input_file, 'w').close()
580
-
581
- with open(input_file, 'a') as f:
582
- f.write('*IMPERFECTION \n')
583
- np.savetxt(f, mat, delimiter=',', fmt='%i,%.8e,%.8e,%.8e')
584
-
585
- return mat
586
-
587
-
588
- def add_input_file(model, input_file_path, pos, target_string=None, relative_pos=0):
589
-
590
- if target_string != None:
591
- pos = model.keywordBlock.sieBlocks.index(target_string)
592
-
593
- model.keywordBlock.insert(pos+relative_pos, '*INCLUDE, INPUT={0}'.format(input_file_path))
594
-
595
-
596
- def add_springs(assem, Kh, region, name):
597
-
598
- ON = symbolicConstants.AbaqusBoolean(1)
599
-
600
- Kpos = (Kh+abs(Kh))/2
601
- Krem = (Kh-abs(Kh))/2
602
-
603
- for dof in range(2, 5):
604
- if Kpos[dof, dof] != 0:
605
- assem.engineeringFeatures.SpringDashpotToGround(name=name+'_K%i%i' % (dof+1, dof+1), region=region, orientation=None, dof=dof+1, springBehavior=ON, springStiffness=Kpos[dof, dof])
606
-
607
- return Krem
608
-
609
-
610
- def add_inertia(assem, M0, region, name, specify_rot=False):
611
- if specify_rot is True:
612
- assem.engineeringFeatures.PointMassInertia(alpha=0.0, composite=0.0, i11=M0[3, 3], i12=M0[3, 4], i13=M0[3, 5], i22=M0[4, 4], i23=M0[4, 5],
613
- i33=M0[5, 5], mass1=M0[0, 0], mass2=M0[1, 1], mass3=M0[2, 2], name=name+'_M0', region=region)
614
- comps = range(0, 6)
615
- elif specify_rot is False:
616
- assem.engineeringFeatures.PointMassInertia(alpha=0.0, composite=0.0, mass1=M0[0, 0], mass2=M0[1, 1], mass3=M0[2, 2], name=name+'_M0', region=region)
617
- comps = range(0, 3)
618
-
619
- Mrem = deepcopy(M0)
620
-
621
- for comp in comps:
622
- Mrem[comp, comp] = 0
623
-
624
- return Mrem
625
-
626
-
627
- #%% USEFUL FUNCTIONS FOR DEALING WITH REGIONS IN DATABASE
628
- def count_region(regionobjs, field_output, frame):
629
- """
630
- Count the number of DOFs and points in the specified region objects for given field output and frame object.
631
-
632
- Args:
633
- regionobjs: list of region objects to query
634
- field_output: string specifying field output
635
- frame: frame object (from where fieldOutputs field is accessible)
636
- Returns:
637
- Ndofs: number of DOFs for each region (list)
638
- point_ranges: point/node ranges for each region (list of lists)
639
- dof_ranges: dof ranges for each region (list of lists)
640
-
641
- NTNU / Knut Andreas Kvaale, 2018
642
- """
643
- odb = get_db('odb')
644
-
645
- Npoints = [len(frame.fieldOutputs[field_output].getSubset(region=regionobj).values) for regionobj in regionobjs]
646
- Ndofs = np.dot(Npoints, len(frame.fieldOutputs[field_output].componentLabels))
647
-
648
- dof_ranges = np.cumsum(np.append([0], Ndofs))
649
- point_ranges = np.cumsum(np.append([0], Npoints))
650
-
651
- return Ndofs, point_ranges, dof_ranges
652
-
653
-
654
- def good_element_ix(foobj, regionobj):
655
- """
656
- Get the indices of the good (??) elements.
657
-
658
- Args:
659
- foobj: field object
660
- regionobj: region object
661
- Returns:
662
- good_ix: ?
663
- good_entries: ?
664
-
665
- NTNU / Knut Andreas Kvaale, 2018
666
- """
667
- foobj_values = foobj.getSubset(region=regionobj).values
668
- region_type = obtain_region_types([regionobj])[0]
669
-
670
- if region_type is 'elements':
671
- rootobj = regionobj.elements
672
- label_string = 'elementLabel'
673
- elif region_type is 'nodes':
674
- rootobj = regionobj.nodes
675
- label_string = 'nodeLabel'
676
-
677
- if type(rootobj) is tuple:
678
- rootobj = rootobj[0]
679
-
680
- good_entries = [getattr(val, label_string) for val in foobj_values]
681
- all_entries = [obj.label for obj in rootobj]
682
-
683
- good_ix = [all_entries.index(this_entry) for this_entry in good_entries]
684
-
685
- return good_ix, good_entries
686
-
687
-
688
- def obtain_region_types(regionobjs):
689
- """
690
- Get the region types of list of region objects.
691
-
692
- Args:
693
- regionobjs: list of region objects
694
- Returns:
695
- region_type: list of region types
696
-
697
- NTNU / Knut Andreas Kvaale, 2018
698
- """
699
- elementsets = [regionobj.nodes is None for regionobj in regionobjs] # true if regionobjects are element sets
700
- settypedict = {False: 'nodes', True: 'elements'}
701
- region_type = [settypedict[elementset] for elementset in elementsets]
702
-
703
- return region_type
704
-
705
-
706
- def str2region(instance_name, setnames, region_type, db_type, *args):
707
- """
708
- Construct a region object from a string defining the set name or a region object.
709
-
710
- Args:
711
- instance_name: string defining the set name (either node or element set) or a region object
712
- setnames: name of set asked for
713
- region_type: type of set ('elements' or 'nodes')
714
- db_type: 'odb' or 'model'
715
- Optional args:
716
- db: database object, either mdb.model[...] or session.openOdb(...) - will get from viewport 1 if not given
717
- Returns:
718
- regionobjs: region objects
719
-
720
- AAJ / Knut Andreas Kvaale, 2017
721
- Further developed NTNU / Knut Andreas Kvaale, 2018
722
- """
723
-
724
- is_assembly = instance_name is None
725
-
726
- set_type = settype(region_type, db_type)
727
- standard_sets = {'nodes': [' ALL NODES'], 'elements': [' ALL ELEMENTS']}
728
-
729
- if setnames is None:
730
- setnames = standard_sets[region_type]
731
-
732
- if len(args)==1: # a db has been input
733
- db = args[0]
734
- isodb = hasattr(db,'jobData') #check if the input db is reffering to result/odb or model
735
-
736
- else:
737
- db = get_db(db_type)
738
-
739
- if db is None:
740
- 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!')
741
-
742
- if is_assembly: # Instance name is given
743
- regroot = db.rootAssembly
744
- else:
745
- regroot = db.rootAssembly.instances[instance_name]
746
-
747
- regionobjs = [None] * np.size(setnames)
748
-
749
- for ix,thisname in enumerate(setnames):
750
- regionobjs[ix] = getattr(regroot, set_type)[thisname]
751
-
752
- return regionobjs
753
-
754
-
755
- def region2nodes(regionobj, sortfun=None):
756
- """
757
- Give node labels (indices) of nodes in specified node set(s).
758
-
759
- Args:
760
- regionobj: region object to query for node labels
761
-
762
- Optional args:
763
- sortfun: function with three inputs (1: x, 2: y, 3:z) to sort nodes by
764
- examples: sortfun = lambda x, y, z: -np.arctan2(y,x)
765
- sortfun = lambda x, y, z: x
766
-
767
- Returns:
768
- node_labels: list with nodelabels
769
-
770
- NTNU / Knut Andreas Kvaale, 2018
771
- """
772
-
773
- set_name = regionobj.__repr__().split("ets[")[1].split("'")[1]
774
-
775
- if len(np.shape(regionobj.nodes))>1:
776
- nodes = regionobj.nodes[0]
777
- else:
778
- nodes = regionobj.nodes
779
-
780
- node_labels = np.array([node.label for node in nodes])
781
- node_coordinates = np.array([node.coordinates for node in nodes])
782
-
783
- if sortfun != None:
784
- vals = sortfun(x=node_coordinates[:,0], y=node_coordinates[:,1], z=node_coordinates[:,2])
785
- sort_ix = np.argsort(vals)
786
- node_labels = node_labels[:, sort_ix]
787
- node_coordinates = node_coordinates[sort_ix, :]
788
-
789
- return node_labels, node_coordinates
790
-
791
- def region2elnodes(regionobj, avoid_central_nodes=True, db_type='odb'):
792
- """
793
- Give node labels (indices) for each node in specified element set.
794
-
795
- Args:
796
- regionobj: region object to query for labels
797
-
798
- Returns:
799
- element_labels: the labels (indices) of the elements in list
800
- element_node_indices: the labels (indices) of the ndoes in each element; list of lists
801
- node_labels: all the nodes labels (indices) in a flattened list
802
- node_coordinates: node coordinates for each element (list of lists)
803
-
804
- NTNU / Knut Andreas Kvaale, 2018
805
- """
806
-
807
- db = get_db(db_type)
808
- objstr = regionobj.__repr__()
809
- if 'instances' in objstr:
810
- instance_name = objstr.split(".instances['")[1].split("'].")[0]
811
- else:
812
- instance_name = None
813
-
814
- if instance_name is None:
815
- instance = db.rootAssembly
816
- else:
817
- instance = db.rootAssembly.instances[instance_name]
818
-
819
- # Get the elements object root
820
- if len(np.shape(regionobj.elements))>1:
821
- elements = regionobj.elements[0]
822
- else:
823
- elements = regionobj.elements
824
-
825
- # Get all element labels and corresponding connectivity (node labels)
826
- element_labels = np.array([element.label for element in elements])
827
- node_labels = [el.connectivity for el in elements]
828
-
829
- if avoid_central_nodes:
830
- node_labels = np.unique([item for sublist in node_labels for item in sublist[:1]+sublist[-1:]])
831
- else:
832
- node_labels = [item for sublist in node_labels for item in sublist]
833
-
834
- element_matrix = None
835
-
836
- return element_labels, node_labels, element_matrix
837
-
838
-
839
- def get_element_matrix(element_labels=None): #if None is specified, full model is exported
840
- pass
841
-
842
- def get_node_matrix(node_labels=None): #if None is specified, full model is exported
843
- pass
844
-
845
- def region2elnodes_legacy(regionobjs, avoid_central_nodes=True):
846
- """
847
- Give node labels (indices) for each node in specified element set.
848
-
849
- Args:
850
- regionobjs: region objects to query for node labels
851
-
852
- Returns:
853
- element_labels: the labels (indices) of the elements in list
854
- element_node_indices: the labels (indices) of the ndoes in each element; list of lists
855
- node_labels: all the nodes labels (indices) in a flattened list
856
- node_coordinates: node coordinates for each element (list of lists)
857
-
858
- NTNU / Knut Andreas Kvaale, 2018
859
- """
860
-
861
- objstr = regionobjs.__repr__()
862
- instance_name = objstr.split(".instances['")[1].split("'].")[0]
863
-
864
- if '.odb' in objstr:
865
- db = get_db('odb')
866
- dbtype = 'odb'
867
- else:
868
- db = get_db('mdb')
869
- dbtype = 'mdb'
870
-
871
- # Get the elements object root
872
- if len(np.shape(regionobjs.elements))>1:
873
- elements = regionobjs.elements[0]
874
- else:
875
- elements = regionobjs.elements
876
-
877
- # Get all element labels and corresponding connectivity (node labels)
878
- element_labels = np.array([element.label for element in elements])
879
-
880
- # Instance object
881
- instance = db.rootAssembly.instances[instance_name]
882
-
883
- # Full arrays labels and coordinates
884
- all_node_labels = np.array([node.label for node in instance.nodes]).flatten([-1])
885
- all_node_coords = np.array([node.coordinates for node in instance.nodes])
886
-
887
- # Nodes belonging to all the elements
888
- if dbtype is 'odb':
889
- element_node_labels = [element.connectivity for element in elements]
890
- else:
891
- element_node_labels = [[all_node_labels[ix] for ix in element.connectivity] for element in elements]
892
-
893
- if avoid_central_nodes:
894
- element_node_labels = [[node_lb[0], node_lb[-1]] for node_lb in element_node_labels]
895
-
896
- node_labels = np.unique(np.array(element_node_labels).flatten())
897
-
898
- nodeixs = np.array([np.where(all_node_labels==node)[0] for node in node_labels]).flatten()
899
- node_coordinates = all_node_coords[nodeixs, :]
900
- 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])
901
-
902
- return element_labels, element_node_indices, node_labels, node_coordinates
903
-
904
-
905
- #%% RETRIEVE THINGS FROM DATABASE
906
- def element_orientations(element_labels, instance_name):
907
- """
908
- Provide transformation matrices describing the three unit vectors of the local CSYS of all elements in element_labels.
909
-
910
- Args:
911
- element_labels: element labels to query
912
- instance_name: name of instance to find beam orientations
913
-
914
- Returns:
915
- element_orientations: array of numpy 2d-arrays with transformation matrices of all elements in element_labels
916
-
917
- NTNU / Knut Andreas Kvaale, 2018
918
- """
919
- db_type = 'odb' # may consider mdb option later
920
- db = get_db(db_type)
921
-
922
- all_elements = db.rootAssembly.elementSets[' ALL ELEMENTS'].elements[0]
923
- all_nodes = db.rootAssembly.nodeSets[' ALL NODES'].nodes[0]
924
- all_element_labels = [value.label for value in all_elements]
925
- all_node_labels = [value.label for value in all_nodes]
926
- element_orientations = [None]*len(element_labels)
927
-
928
- beam_orientations = db.rootAssembly.instances[instance_name].beamOrientations
929
-
930
- for beam_orientation in beam_orientations:
931
- bo_elements = [value.label for value in beam_orientation.region.elements]
932
- for this_element_label in bo_elements:
933
- if this_element_label in element_labels:
934
- n1_temp = np.array(beam_orientation.vector)
935
- node_labels = all_elements[all_element_labels.index(this_element_label)].connectivity
936
-
937
- node_start_coor = all_nodes[all_node_labels.index(node_labels[0])].coordinates
938
- node_end_coor = all_nodes[all_node_labels.index(node_labels[-1])].coordinates
939
- t = (node_end_coor-node_start_coor)
940
- t = t/np.linalg.norm(t)
941
-
942
- n2 = np.cross(t, n1_temp)
943
- n2 = n2/np.linalg.norm(n2)
944
-
945
- n1 = np.cross(n2, t) #does this actually work?
946
-
947
- element_orientations[np.where(element_labels == this_element_label)[0]] = np.array([t,n1,n2])
948
-
949
- return element_orientations
950
-
951
-
952
- def freq_sysmat(mat,freqs,freq):
953
- """
954
- Interpolate frequency dependent matrix, for given frequency value. !! Deprecated - use numpy functions directly instead !!
955
-
956
- Args:
957
- mat: 3D matrix (Numpy array)
958
- freqs: frequency axis (Numpy array)
959
- freq: selected frequency value (scalar)
960
- Returns:
961
- mat_sel: 2D matrix corresponding to queried frequency value (Numpy array)
962
-
963
- NTNU / AAJ / Knut Andreas Kvaale, 2018
964
- """
965
- from .general import interp1z
966
-
967
- if freq == []:
968
- mat_sel = 0
969
- else:
970
- mat_sel = interp1z(freqs[:,0,0],mat,freq)
971
- return mat_sel
972
-
973
-
974
- def wind_set_data(set_strings, frequency_step, instance, db_type, field_outputs, mode_type='nodes', use_node_region_acronym=False):
975
- # 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)
976
- wind_element_regions = str2region(instance, set_strings, 'elements', db_type) # index 0 is girder, index 1 is columns
977
-
978
- if use_node_region_acronym:
979
- wind_node_regions = str2region(instance, set_strings, 'nodes', db_type)
980
-
981
- element_labels = [None]*len(set_strings)
982
- element_node_indices = [None]*len(set_strings)
983
- node_labels = [None]*len(set_strings)
984
- node_coordinates = [None]*len(set_strings)
985
- phi_ae = [None]*len(set_strings)
986
-
987
- for set_ix, set_string in enumerate(set_strings):
988
- element_labels[set_ix], element_node_indices[set_ix], nl, nc = region2elnodes_legacy(wind_element_regions[set_ix])
989
- if use_node_region_acronym:
990
- nl, nc = region2nodes(wind_node_regions[set_ix])
991
-
992
- node_labels[set_ix] = nl
993
- node_coordinates[set_ix] = nc
994
-
995
- # Establish modal transformation matrix, phi
996
- if mode_type=='nodes':
997
- for set_ix, set_string in enumerate(set_strings):
998
- phi_ae_temp = modeshapes_from_nodelist(node_labels[set_ix], frequency_step, field_outputs)
999
- phi_ae[set_ix] = merge_tr_phi(phi_ae_temp[0][0], phi_ae_temp[0][1])
1000
- elif mode_type=='elements':
1001
- for set_ix, set_string in enumerate(set_strings):
1002
- phi_ae_temp, integration_points = modeshapes_from_elementlist(element_labels[set_ix], frequency_step, field_outputs)
1003
- phi_ae[set_ix] = merge_tr_phi(phi_ae_temp[0], phi_ae_temp[1])
1004
-
1005
- return element_labels, element_node_indices, node_labels, node_coordinates, phi_ae
1006
-
1007
-
1008
-
1009
- def settype(region_type, db_type):
1010
- """
1011
- Define the string used to get set based on region type and database type.
1012
-
1013
- Args:
1014
- region_type: 'element' or 'node'
1015
- db_type: 'odb' or 'mdb'
1016
- Returns:
1017
- set_string: string used to obtain set data from database object (odb or mdb)
1018
-
1019
- NTNU / Knut Andreas Kvaale, 2018
1020
- """
1021
- if db_type is 'odb':
1022
- if 'element' in region_type.lower():
1023
- set_string = 'elementSets'
1024
- elif 'node' in region_type.lower():
1025
- set_string = 'nodeSets'
1026
- else:
1027
- raise TypeError('Wrong input!')
1028
- elif db_type == 'mdb' or db_type == 'model':
1029
- set_string = 'sets'
1030
-
1031
- return set_string
1032
-
1033
- #%% EXPORT THINGS
1034
- def save_nodes_and_elements(folder, element_labels, element_node_indices, node_labels, node_coordinates, element_orientations=None, set_strings=None):
1035
- for ix, element_labels_i in enumerate(element_labels):
1036
- element_info = np.column_stack([element_labels[ix], element_node_indices[ix]])
1037
- node_info = np.column_stack([node_labels[ix], node_coordinates[ix]])
1038
- np.savetxt(os.path.join(folder, 'node_info_%i.dat' % (ix)), node_info)
1039
- np.savetxt(os.path.join(folder, 'element_info_%i.dat' % (ix)), element_info)
1040
-
1041
- if element_orientations:
1042
- np.savetxt(os.path.join(folder, 'element_orientations_%i.dat' % (ix)), element_orientations)
1043
-
1044
- if set_strings:
1045
- np.savetxt(os.path.join(folder, 'node_and_element_sets.txt'), set_strings, fmt='%s', delimiter=',')
1046
-
1047
-
1048
- def save_pontoon_info(folder, node_labels, node_coordinates, pontoon_labels=None, pontoon_angles=None):
1049
- if pontoon_labels==None: # standard if no pontoon_labels are provided (integers!)
1050
- pontoon_labels = np.linspace(1, len(node_labels), len(node_labels)).astype(int)
1051
-
1052
- if pontoon_angles==None:
1053
- pontoon_angles = np.zeros(len(node_labels)) #if no angles are given, output zero for all pontoon angles
1054
-
1055
- pontooninfo = np.column_stack([pontoon_labels, node_coordinates, node_labels, pontoon_angles])
1056
- np.savetxt(os.path.join(folder, 'pontoon_info.dat'), pontooninfo)
1057
-
1058
-
1059
- def save_all_modal(folder, phi, suffix='', f=None, m=None, set_strings=None):
1060
-
1061
- if isinstance(phi, list):
1062
- for ix, phi_i in enumerate(phi):
1063
- np.savetxt(os.path.join(folder, 'phi_%s_%i.dat' % (suffix, ix)), phi_i)
1064
-
1065
- if set_strings:
1066
- np.savetxt(os.path.join(folder, 'phi_%s_sets.txt' % (suffix)), set_strings, fmt='%s', delimiter=',')
1067
-
1068
- elif isinstance(phi, np.ndarray):
1069
- np.savetxt(os.path.join(folder, 'phi_%s_%i.dat' % (suffix, 0)), phi)
1070
-
1071
- if f is not None:
1072
- np.savetxt(os.path.join(folder, 'f.dat'), f)
1073
- if m is not None:
1074
- np.savetxt(os.path.join(folder, 'm.dat'), m)
1075
-
1076
-
1077
- #%% ONLY DEBUGGED IN BRIGADE
1078
- def mode2df(model, node_labels, phi, name, instance_name):
1079
- nodes = tuple(np.repeat(node_labels,6).tolist())
1080
- dofs = np.tile(np.arange(1,6+1), len(node_labels))
1081
-
1082
- dofs_and_mags = np.empty([np.shape(dofs)[0],2])
1083
- dofs_and_mags[:, 0::2] = dofs[:, np.newaxis]
1084
- dofs_and_mags[:, 1::2] = phi[:, np.newaxis]
1085
-
1086
- data = ((instance_name, 2, nodes, tuple(dofs_and_mags.flatten().tolist())),)
1087
- df = model.DiscreteField(data=data, dataWidth=2, defaultValues=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0), description='Mode displacement', fieldType=PRESCRIBEDCONDITION_DOF, location=NODES, name=name)
1088
-
1089
- return df
1090
-
1091
-
1092
- def apply_nodal_load(model, node_labels, step_name, loads, instance_name, prefix=''):
1093
- instance = model.rootAssembly.instances[instance_name]
1094
- all_node_labels = [node.label for node in instance.nodes]
1095
- ndof = 6 # assumes 6 DOFs for all nodes - be aware!
1096
- for node_ix, node_label in enumerate(node_labels):
1097
- if all_node_labels.count(node_label) != None: # if in node labels
1098
- global_node_ix = all_node_labels.index(node_label)
1099
- node_set = model.rootAssembly.Set(name='node_%i' % (node_label), nodes=instance.nodes[global_node_ix:global_node_ix+1])
1100
- nodeloads = loads[node_ix*6:node_ix*6+6]
1101
-
1102
- if not np.all(nodeloads[0:3]==0):
1103
- model.ConcentratedForce(cf1=nodeloads[0], cf2=nodeloads[1], cf3=nodeloads[2], createStepName=step_name, distributionType=UNIFORM, field='', localCsys=None, name='%sforces_node_%i' % (prefix, node_label), region=node_set)
1104
-
1105
- if not np.all(nodeloads[3:6]==0):
1106
- model.Moment(cm1=nodeloads[3], cm2=nodeloads[4], cm3=nodeloads[5], createStepName=step_name, distributionType=UNIFORM, field='', localCsys=None, name='%smoments_node_%i' % (prefix, node_label), region=node_set)
1107
-
1108
- else:
1109
- raise ValueError('Node %i does not exist in selected instance.' % (node_label))
1110
-
1111
-
1112
- def assign_modal_constraint_equation(model, instance_name, name, node_labels, displacement):
1113
- ndof = 6 # assumes 6 DOFs for all nodes - be aware!
1114
- instance = model.rootAssembly.instances[instance_name]
1115
- all_node_labels = [node.label for node in instance.nodes]
1116
- terms = []
1117
- for node_ix, node_label in enumerate(node_labels):
1118
- if all_node_labels.count(node_label) != None: # if in node labels
1119
- global_node_ix = all_node_labels.index(node_label)
1120
- node_set_name = 'node_%i' % (node_label)
1121
- node_set = model.rootAssembly.Set(name=node_set_name, nodes=instance.nodes[global_node_ix:global_node_ix+1])
1122
- displacement_of_node = displacement[node_ix*ndof:node_ix*ndof+ndof]
1123
- non_zero = np.where(displacement_of_node !=0 )[0]
1124
- terms.append([(displacement_of_node[ldof], node_set_name, ldof+1) for ldof in non_zero])
1125
-
1126
- terms = tuple([term for sublist in terms for term in sublist])
1127
- model.Equation(name=name, terms=terms)
1128
-