Static & Transient DataFrames in PyNastran

The iPython notebook for this demo can be found in: - docs:raw-latex:quick_start:raw-latex:demo:raw-latex:`op`2_pandas_multi_case.ipynb - https://github.com/SteveDoyle2/pyNastran/tree/master/docs/quick_start/demo/op2_pandas_multi_case.ipynb

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.

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())
INFO:      fname=op2_scalar.py             lineNo=1176   op2_filename = 'f:\work\pynastran\pynastran\master3\pyNastran\..\models\solid_bending\solid_bending.op2'
[(1, 1, 1, 0, u'DEFAULT')]
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())
INFO:      fname=op2_scalar.py             lineNo=1176   op2_filename = 'f:\work\pynastran\pynastran\master3\pyNastran\..\models\solid_bending\solid_bending.op2'
[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.

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)
INFO:      fname=op2_scalar.py             lineNo=1176   op2_filename = 'f:\work\pynastran\pynastran\master3\pyNastran\..\models\sol_101_elements\buckling_solid_shell_bar.op2'
stress_keys = model.cquad4_stress.keys()
print (stress_keys)

# isubcase, analysis_code, sort_method, count, subtitle
key0 = (1, 1, 1, 0, 'DEFAULT1')
key1 = (1, 8, 1, 0, 'DEFAULT1')
[(1, 1, 1, 0, u'DEFAULT1'), (1, 8, 1, 0, u'DEFAULT1')]

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.

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)
stress_static.nonlinear_factor = None
stress_transient.nonlinear_factor = 4
data_names  = [u'lsdvmn', u'eigr']
loadsteps   = [1, 2, 3, 4]
eigenvalues = [-49357660160.0, -58001940480.0, -379750744064.0, -428462538752.0]

Static Table

# Sets default precision of real numbers for pandas output\n"
pd.set_option('precision', 2)

stress_static.head(20)
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

# 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)
LoadStep Item 1 2 3 4
EigenvalueReal -49357660160.0 -58001940480.0 -3.79750744064e+11 -4.28462538752e+11
Freq 35358.7915137 38330.227181 98077.5138317 104178.13059
Radians 222165.839318 240835.920244 616239.193872 654570.499451
ElementID NodeID Location
6 CEN Top fiber_distance -0.125 -0.125 -0.125 -0.125
Top oxx -36570.457 -158687.391 -149706.203 1068952.125
Top oyy 206374.969 1083602.750 403245.969 6158211.500
Top txy 229.650 -12673.086 4394314.500 -357167.656
Top angle 89.946 -89.416 46.800 -86.005
Top omax 206375.188 1083732.125 4529773.000 6183155.500
Top omin -36570.672 -158816.656 -4276233.500 1044008.062
Top von_mises 226881.938 1171244.000 7627279.000 5732896.500
Bottom fiber_distance 0.125 0.125 0.125 0.125
Bottom oxx -28156.799 -95551.906 -194234.062 -488197.969
Bottom oyy 140208.719 732509.188 7016.848 -278514.844
Bottom txy 74085.039 -35219.672 4534850.000 -353332.000
Bottom angle 69.325 -87.569 45.636 -53.263
Bottom omax 168165.734 734004.500 4442357.500 -14798.063
Bottom omin -56113.816 -97047.195 -4629575.000 -751914.750
Bottom von_mises 202150.672 787028.500 7857081.500 744626.000
4 Top fiber_distance -0.125 -0.125 -0.125 -0.125
Top oxx -99755.844 -580174.062 -292532.719 793623.688
Top oyy -1101563.000 1460770.000 -3137639.000 6441436.000
Top txy 229.650 -12673.086 4394314.500 -357167.656