Static & Transient DataFrames in PyNastran
==========================================
The Jupyter notebook for this demo can be found in: -
docs/quick_start/demo/op2_pandas_multi_case.ipynb -
https://github.com/SteveDoyle2/pyNastran/tree/master/docs/quick_start/demo/op2_pandas_multi_case.ipynb
.. code:: ipython3
import os
import pandas as pd
import pyNastran
from pyNastran.op2.op2 import read_op2
pkg_path = pyNastran.__path__[0]
model_path = os.path.join(pkg_path, '..', 'models')
Solid Bending
-------------
Let’s show off ``combine=True/False``. We’ll talk about the keys soon.
.. code:: ipython3
solid_bending_op2 = os.path.join(model_path, 'solid_bending', 'solid_bending.op2')
solid_bending = read_op2(solid_bending_op2, combine=False, debug=False)
print(solid_bending.displacements.keys())
.. raw:: html
INFO: op2_scalar.py:1588 op2_filename = 'c:\\nasa\\m4\\formats\\git\\pynastran\\pyNastran\\..\\models\\solid_bending\\solid_bending.op2'
.. parsed-literal::
dict_keys([(1, 1, 1, 0, 0, '', '')])
.. code:: ipython3
solid_bending_op2 = os.path.join(model_path, 'solid_bending', 'solid_bending.op2')
solid_bending2 = read_op2(solid_bending_op2, combine=True, debug=False)
print(solid_bending2.displacements.keys())
.. raw:: html
INFO: op2_scalar.py:1588 op2_filename = 'c:\\nasa\\m4\\formats\\git\\pynastran\\pyNastran\\..\\models\\solid_bending\\solid_bending.op2'
.. parsed-literal::
dict_keys([1])
Single Subcase Buckling Example
-------------------------------
The keys cannot be “combined” despite us telling the program that it was
OK. We’ll get the following values that we need to handle. ####
isubcase, analysis_code, sort_method, count, subtitle \* isubcase -> the
same key that you’re used to accessing \* sort_method -> 1 (SORT1), 2
(SORT2) \* count -> the optimization count \* subtitle -> the analysis
subtitle (changes for superlements) \* analysis code -> the “type” of
solution
### Partial code for calculating analysis code:
::
if trans_word == 'LOAD STEP': # nonlinear statics
analysis_code = 10
elif trans_word in ['TIME', 'TIME STEP']: # TODO check name
analysis_code = 6
elif trans_word == 'EIGENVALUE': # normal modes
analysis_code = 2
elif trans_word == 'FREQ': # TODO check name
analysis_code = 5
elif trans_word == 'FREQUENCY':
analysis_code = 5
elif trans_word == 'COMPLEX EIGENVALUE':
analysis_code = 9
else:
raise NotImplementedError('transient_word=%r is not supported...' % trans_word)
Let’s look at an odd case:
~~~~~~~~~~~~~~~~~~~~~~~~~~
You can do buckling as one subcase or two subcases (makes parsing it a
lot easier!).
However, you **have** to do this once you start messing around with
superelements or multi-step optimization.
For optimization, sometimes Nastran will downselect elements and do an
optimization on that and print out a subset of the elements. At the end,
it will rerun an analysis to double check the constraints are satisfied.
It does not always do multi-step optimization.
.. code:: ipython3
op2_filename = os.path.join(model_path, 'sol_101_elements', 'buckling_solid_shell_bar.op2')
model = read_op2(op2_filename, combine=True, debug=False, build_dataframe=True)
.. raw:: html
INFO: op2_scalar.py:1588 op2_filename = 'c:\\nasa\\m4\\formats\\git\\pynastran\\pyNastran\\..\\models\\sol_101_elements\\buckling_solid_shell_bar.op2'
.. code:: ipython3
stress_keys = model.cquad4_stress.keys()
print (stress_keys)
# subcase, analysis_code, sort_method, count, isuperelmemnt_adaptivity_index, pval_step
key0 = (1, 1, 1, 0, 0, '', '')
key1 = (1, 8, 1, 0, 0, '', '')
.. parsed-literal::
dict_keys([(1, 1, 1, 0, 0, '', ''), (1, 8, 1, 0, 0, '', '')])
Keys: \* key0 is the “static” key \* key1 is the “buckling” key
Similarly: \* Transient solutions can have preload \* Frequency
solutions can have loadsets (???)
Moving onto the data frames
---------------------------
- The static case is the initial deflection state
- The buckling case is “transient”, where the modes (called load steps
or lsdvmn here) represent the “times”
pyNastran reads these tables differently and handles them differently
internally. They look very similar though.
.. code:: ipython3
stress_static = model.cquad4_stress[key0].data_frame
stress_transient = model.cquad4_stress[key1].data_frame
# The final calculated factor:
# Is it a None or not?
# This defines if it's static or transient
print('stress_static.nonlinear_factor = %s' % model.cquad4_stress[key0].nonlinear_factor)
print('stress_transient.nonlinear_factor = %s' % model.cquad4_stress[key1].nonlinear_factor)
print('data_names = %s' % model.cquad4_stress[key1].data_names)
print('loadsteps = %s' % model.cquad4_stress[key1].lsdvmns)
print('eigenvalues = %s' % model.cquad4_stress[key1].eigrs)
.. parsed-literal::
stress_static.nonlinear_factor = nan
stress_transient.nonlinear_factor = 4
data_names = ['lsdvmn', 'eigr']
loadsteps = [1, 2, 3, 4]
eigenvalues = [-49357660160.0, -58001940480.0, -379750744064.0, -428462538752.0]
Static Table
------------
.. code:: ipython3
# Sets default precision of real numbers for pandas output\n"
pd.set_option('precision', 2)
stress_static.head(20)
.. raw:: html
|
|
|
index |
fiber_distance |
oxx |
oyy |
txy |
angle |
omax |
omin |
von_mises |
| ElementID |
NodeID |
Location |
|
|
|
|
|
|
|
|
|
| 6 |
CEN |
Top |
0 |
-0.12 |
5.85e-07 |
9.73e-06 |
-1.36e-07 |
-89.15 |
9.73e-06 |
5.83e-07 |
9.46e-06 |
| Bottom |
1 |
0.12 |
4.71e-07 |
9.44e-06 |
-1.61e-07 |
-88.97 |
9.44e-06 |
4.69e-07 |
9.21e-06 |
| 4 |
Top |
2 |
-0.12 |
-6.50e-07 |
9.48e-06 |
-1.36e-07 |
-89.23 |
9.48e-06 |
-6.52e-07 |
9.82e-06 |
| Bottom |
3 |
0.12 |
-8.37e-07 |
9.11e-06 |
-1.61e-07 |
-89.08 |
9.12e-06 |
-8.39e-07 |
9.56e-06 |
| 1 |
Top |
4 |
-0.12 |
-6.50e-07 |
9.98e-06 |
-1.36e-07 |
-89.27 |
9.99e-06 |
-6.51e-07 |
1.03e-05 |
| Bottom |
5 |
0.12 |
-8.37e-07 |
9.76e-06 |
-1.61e-07 |
-89.13 |
9.76e-06 |
-8.39e-07 |
1.02e-05 |
| 14 |
Top |
6 |
-0.12 |
1.82e-06 |
9.98e-06 |
-1.36e-07 |
-89.05 |
9.99e-06 |
1.82e-06 |
9.21e-06 |
| Bottom |
7 |
0.12 |
1.78e-06 |
9.76e-06 |
-1.61e-07 |
-88.85 |
9.76e-06 |
1.78e-06 |
9.01e-06 |
| 15 |
Top |
8 |
-0.12 |
1.82e-06 |
9.48e-06 |
-1.36e-07 |
-88.98 |
9.48e-06 |
1.82e-06 |
8.72e-06 |
| Bottom |
9 |
0.12 |
1.78e-06 |
9.11e-06 |
-1.61e-07 |
-88.75 |
9.12e-06 |
1.78e-06 |
8.37e-06 |
| 7 |
CEN |
Top |
10 |
-0.12 |
7.16e-07 |
1.02e-05 |
1.22e-07 |
89.26 |
1.02e-05 |
7.14e-07 |
9.82e-06 |
| Bottom |
11 |
0.12 |
7.31e-07 |
1.04e-05 |
1.53e-07 |
89.10 |
1.04e-05 |
7.29e-07 |
1.01e-05 |
| 3 |
Top |
12 |
-0.12 |
-7.30e-07 |
1.04e-05 |
1.22e-07 |
89.37 |
1.04e-05 |
-7.31e-07 |
1.08e-05 |
| Bottom |
13 |
0.12 |
-8.05e-07 |
1.07e-05 |
1.53e-07 |
89.24 |
1.07e-05 |
-8.07e-07 |
1.12e-05 |
| 2 |
Top |
14 |
-0.12 |
-7.30e-07 |
9.90e-06 |
1.22e-07 |
89.34 |
9.90e-06 |
-7.31e-07 |
1.03e-05 |
| Bottom |
15 |
0.12 |
-8.05e-07 |
1.01e-05 |
1.53e-07 |
89.20 |
1.01e-05 |
-8.07e-07 |
1.05e-05 |
| 17 |
Top |
16 |
-0.12 |
2.16e-06 |
9.90e-06 |
1.22e-07 |
89.10 |
9.90e-06 |
2.16e-06 |
9.02e-06 |
| Bottom |
17 |
0.12 |
2.27e-06 |
1.01e-05 |
1.53e-07 |
88.88 |
1.01e-05 |
2.26e-06 |
9.18e-06 |
| 16 |
Top |
18 |
-0.12 |
2.16e-06 |
1.04e-05 |
1.22e-07 |
89.15 |
1.04e-05 |
2.16e-06 |
9.52e-06 |
| Bottom |
19 |
0.12 |
2.27e-06 |
1.07e-05 |
1.53e-07 |
88.96 |
1.07e-05 |
2.26e-06 |
9.79e-06 |
Transient Table
---------------
.. code:: ipython3
# Sets default precision of real numbers for pandas output\n"
pd.set_option('precision', 3)
#import numpy as np
#np.set_printoptions(formatter={'all':lambda x: '%g'})
stress_transient.head(20)
.. raw:: html
|
|
|
LoadStep |
1 |
2 |
3 |
4 |
|
|
|
EigenvalueReal |
-4.936e+10 |
-5.800e+10 |
-3.798e+11 |
-4.285e+11 |
| ElementID |
NodeID |
Location |
Item |
|
|
|
|
| 6 |
CEN |
Top |
fiber_distance |
-1.250e-01 |
-1.250e-01 |
-1.250e-01 |
-1.250e-01 |
| Bottom |
oxx |
-3.657e+04 |
-1.587e+05 |
-1.497e+05 |
1.069e+06 |
| 4 |
Top |
oyy |
2.064e+05 |
1.084e+06 |
4.032e+05 |
6.158e+06 |
| Bottom |
txy |
2.296e+02 |
-1.267e+04 |
4.394e+06 |
-3.572e+05 |
| 1 |
Top |
angle |
8.995e+01 |
-8.942e+01 |
4.680e+01 |
-8.601e+01 |
| Bottom |
omax |
2.064e+05 |
1.084e+06 |
4.530e+06 |
6.183e+06 |
| 14 |
Top |
omin |
-3.657e+04 |
-1.588e+05 |
-4.276e+06 |
1.044e+06 |
| Bottom |
von_mises |
2.269e+05 |
1.171e+06 |
7.627e+06 |
5.733e+06 |
| 15 |
Top |
fiber_distance |
1.250e-01 |
1.250e-01 |
1.250e-01 |
1.250e-01 |
| Bottom |
oxx |
-2.816e+04 |
-9.555e+04 |
-1.942e+05 |
-4.882e+05 |
| 7 |
CEN |
Top |
oyy |
1.402e+05 |
7.325e+05 |
7.017e+03 |
-2.785e+05 |
| Bottom |
txy |
7.409e+04 |
-3.522e+04 |
4.535e+06 |
-3.533e+05 |
| 3 |
Top |
angle |
6.933e+01 |
-8.757e+01 |
4.564e+01 |
-5.326e+01 |
| Bottom |
omax |
1.682e+05 |
7.340e+05 |
4.442e+06 |
-1.480e+04 |
| 2 |
Top |
omin |
-5.611e+04 |
-9.705e+04 |
-4.630e+06 |
-7.519e+05 |
| Bottom |
von_mises |
2.022e+05 |
7.870e+05 |
7.857e+06 |
7.446e+05 |
| 17 |
Top |
fiber_distance |
-1.250e-01 |
-1.250e-01 |
-1.250e-01 |
-1.250e-01 |
| Bottom |
oxx |
-9.976e+04 |
-5.802e+05 |
-2.925e+05 |
7.936e+05 |
| 16 |
Top |
oyy |
-1.102e+06 |
1.461e+06 |
-3.138e+06 |
6.441e+06 |
| Bottom |
txy |
2.296e+02 |
-1.267e+04 |
4.394e+06 |
-3.572e+05 |