#pylint disable=C0301
from __future__ import annotations
from struct import Struct, pack
import copy
import warnings
from abc import abstractmethod
import inspect
from typing import Union
import numpy as np
from numpy import zeros, searchsorted, allclose
from pyNastran.utils.numpy_utils import integer_types, float_types
from pyNastran.op2.result_objects.op2_objects import (
BaseElement, get_times_dtype, get_sort_element_sizes, set_as_sort1)
from pyNastran.f06.f06_formatting import (
write_floats_13e, write_floats_13e_long,
write_float_13e, write_float_13e_long, # write_float_12e,
write_floats_12e,
_eigenvalue_header,
)
from pyNastran.op2.op2_interface.write_utils import set_table3_field
from pyNastran.op2.tables.oes_stressStrain.real.oes_objects import (
update_stress_force_time_word,
set_element_case, set_element_node_xxb_case,
set_static_case, set_modal_case, set_transient_case,
set_post_buckling_case)
from pyNastran.op2.writer.utils import fix_table3_types
TABLE_NAME_TO_TABLE_CODE = {
'OEF1' : 4,
'OEF1X' : 4,
}
ELEMENT_NAME_TO_ELEMENT_TYPE = {
'CROD' : 1,
'CBEAM': 2,
'CTUBE' : 3,
'CONROD' : 10,
'CBAR': 34,
'CELAS1' : 11,
'CELAS2' : 12,
'CELAS3' : 13,
'CELAS4' : 14,
'CDAMP1': 20,
'CDAMP2': 21,
'CDAMP3': 22,
'CDAMP4': 23,
'CSHEAR' : 4,
'CVISC': 24,
}
[docs]
def oef_complex_data_code(table_name: str,
element_name: str, num_wide: int,
is_sort1: bool=True, is_random: bool=False,
random_code=0, title='', subtitle='', label='',
is_msc=True):
dtype_code = 1 # complex
data_code = _oef_data_code(table_name,
element_name, num_wide, dtype_code,
is_sort1=is_sort1,
is_random=is_random, random_code=random_code,
title=title, subtitle=subtitle, label=label, is_msc=is_msc)
return data_code
[docs]
def oef_real_data_code(table_name: str,
element_name: str, num_wide: int,
is_sort1: bool=True, is_random: bool=False,
random_code=0, title='', subtitle='', label='',
is_msc=True):
dtype_code = 0 # real
assert isinstance(element_name, str), element_name
data_code = _oef_data_code(table_name, element_name, num_wide, dtype_code,
is_sort1=is_sort1,
is_random=is_random, random_code=random_code,
title=title, subtitle=subtitle, label=label, is_msc=is_msc)
return data_code
def _oef_data_code(table_name: str,
element_name: str, num_wide: int, dtype_code: int,
is_sort1: bool=True, is_random: bool=False,
random_code=0, title='', subtitle='', label='',
is_msc=True):
"""
Parameters
----------
dtype_code : int
0 : real
1 : complex
2 : random
"""
sort1_sort_bit = 0 if is_sort1 else 1
random_sort_bit = 1 if is_random else 0
sort_method = 1 if is_sort1 else 2
#if format_code == 1:
#format_word = "Real"
#elif format_code == 2:
#format_word = "Real/Imaginary"
#elif format_code == 3:
#format_word = "Magnitude/Phase"
#DEVICE_CODE_MAP = {
#1 : "Print",
#2 : "Plot",
#3 : "Print and Plot",
#4 : "Punch",
#5 : "Print and Punch",
#6 : "Plot and Punch",
#7 : "Print, Plot, and Punch",
#}
table_code = TABLE_NAME_TO_TABLE_CODE[table_name]
sort_code = 1 # TODO: what should this be???
#table_code = tCode % 1000
#sort_code = tCode // 1000
tCode = table_code * 1000 + sort_code
device_code = 2 # Plot
#print(f'approach_code={approach_code} analysis_code={analysis_code} device_code={device_code}')
data_code = {
'nonlinear_factor': None,
'sort_bits': [dtype_code, sort1_sort_bit, random_sort_bit], # real, sort1, random
'sort_method' : sort_method,
'is_msc': is_msc,
#'is_nasa95': is_nasa95,
'format_code': 1, # real
'table_code': table_code,
'tCode': tCode,
'table_name': table_name, ## TODO: should this be a string?
'device_code' : device_code,
'random_code' : random_code,
'thermal': 0,
'title' : title,
'subtitle': subtitle,
'label': label,
'num_wide': num_wide,
'element_name': element_name,
#'num_wide' : 8, # displacement-style table
}
return data_code
[docs]
class ForceObject(BaseElement):
def __init__(self, data_code, isubcase, apply_data_code=True):
self.element_type = None
self.element_name = None
self.nonlinear_factor = np.nan
self.element = None
self._times = None
BaseElement.__init__(self, data_code, isubcase, apply_data_code=apply_data_code)
[docs]
def finalize(self) -> None:
"""it's required that the object be in SORT1"""
self.set_as_sort1()
[docs]
def set_as_sort1(self) -> None:
"""the data is in SORT1, but the flags are wrong"""
set_as_sort1(self)
#update_stress_force_time_word(self)
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs]
def get_element_index(self, eids):
# elements are always sorted; nodes are not
itot = searchsorted(eids, self.element) #[0]
return itot
[docs]
def eid_to_element_node_index(self, eids):
#ind = ravel([searchsorted(self.element == eid) for eid in eids])
ind = searchsorted(eids, self.element)
#ind = ind.reshape(ind.size)
#ind.sort()
return ind
def _write_table_3(self, op2_file, op2_ascii, new_result, itable, itime): #itable=-3, itime=0):
import inspect
from struct import pack
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write('%s.write_table_3: %s\n' % (self.__class__.__name__, call_frame[1][3]))
#print('new_result=%s itable=%s' % (new_result, itable))
if new_result and itable != -3:
header = [
4, 146, 4,
]
else:
header = [
4, itable, 4,
4, 1, 4,
4, 0, 4,
4, 146, 4,
]
op2_file.write(pack(b'%ii' % len(header), *header))
op2_ascii.write('table_3_header = %s\n' % header)
approach_code = self.approach_code
table_code = self.table_code
isubcase = self.isubcase
element_type = self.element_type
assert isinstance(self.element_type, int), self.element_type
#[
#'aCode', 'tCode', 'element_type', 'isubcase',
#'???', '???', '???', 'load_set'
#'format_code', 'num_wide', 's_code', '???',
#'???', '???', '???', '???',
#'???', '???', '???', '???',
#'???', '???', '???', '???',
#'???', 'Title', 'subtitle', 'label']
#random_code = self.random_code
format_code = self.format_code
s_code = 0 # self.s_code
num_wide = self.num_wide
acoustic_flag = 0
thermal = self.thermal
title = b'%-128s' % self.title.encode('ascii')
subtitle = b'%-128s' % self.subtitle.encode('ascii')
label = b'%-128s' % self.label.encode('ascii')
ftable3 = b'50i 128s 128s 128s'
#oCode = 0
load_set = 0
#print(self.code_information())
ftable3 = b'i' * 50 + b'128s 128s 128s'
field6 = 0
field7 = 0
if self.analysis_code == 1:
field5 = self.loadIDs[itime]
elif self.analysis_code == 2:
field5 = self.modes[itime]
field6 = self.eigns[itime]
field7 = self.cycles[itime]
assert isinstance(field6, float), type(field6)
assert isinstance(field7, float), type(field7)
ftable3 = set_table3_field(ftable3, 6, b'f') # field 6
ftable3 = set_table3_field(ftable3, 7, b'f') # field 7
elif self.analysis_code == 5:
try:
field5 = self.freqs[itime]
except AttributeError: # pragma: no cover
print(self)
raise
ftable3 = set_table3_field(ftable3, 5, b'f') # field 5
elif self.analysis_code == 6:
if hasattr(self, 'times'):
field5 = self.times[itime]
#elif hasattr(self, 'dts'):
#field5 = self.times[itime]
else: # pragma: no cover
print(self.get_stats())
raise NotImplementedError('cant find times or dts on analysis_code=8')
ftable3 = set_table3_field(ftable3, 5, b'f') # field 5
elif self.analysis_code == 7: # pre-buckling
field5 = self.loadIDs[itime] # load set number
elif self.analysis_code == 8: # post-buckling
if hasattr(self, 'lsdvmns'):
field5 = self.lsdvmns[itime] # load set number
elif hasattr(self, 'loadIDs'):
field5 = self.loadIDs[itime]
else: # pragma: no cover
print(self.get_stats())
raise NotImplementedError('cant find lsdvmns or loadIDs on analysis_code=8')
if hasattr(self, 'eigns'):
field6 = self.eigns[itime]
elif hasattr(self, 'eigrs'):
field6 = self.eigrs[itime]
else: # pragma: no cover
print(self.get_stats())
raise NotImplementedError('cant find eigns or eigrs on analysis_code=8')
assert isinstance(field6, float_types), type(field6)
ftable3 = set_table3_field(ftable3, 6, b'f') # field 6
elif self.analysis_code == 9: # complex eigenvalues
field5 = self.modes[itime]
if hasattr(self, 'eigns'):
field6 = self.eigns[itime]
elif hasattr(self, 'eigrs'):
field6 = self.eigrs[itime]
else: # pragma: no cover
print(self.get_stats())
raise NotImplementedError('cant find eigns or eigrs on analysis_code=8')
ftable3 = set_table3_field(ftable3, 6, b'f') # field 6
field7 = self.eigis[itime]
ftable3 = set_table3_field(ftable3, 7, b'f') # field 7
elif self.analysis_code == 10: # nonlinear statics
field5 = self.load_steps[itime]
ftable3 = set_table3_field(ftable3, 5, b'f') # field 5; load step
elif self.analysis_code == 11: # old geometric nonlinear statics
field5 = self.loadIDs[itime] # load set number
else:
raise NotImplementedError(self.analysis_code)
table3 = [
approach_code, table_code, element_type, isubcase, field5,
field6, field7, load_set, format_code, num_wide,
s_code, acoustic_flag, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, thermal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
title, subtitle, label,
]
assert table3[22] == thermal
table3 = fix_table3_types(table3, size=4)
data = [584] + table3 + [584]
fmt = b'i' + ftable3 + b'i'
#print(fmt)
#print(data)
#f.write(pack(fascii, '%s header 3c' % self.table_name, fmt, data))
op2_ascii.write('%s header 3c = %s\n' % (self.table_name, data))
op2_file.write(pack(fmt, *data))
[docs]
class RealForceObject(ForceObject):
def __init__(self, data_code, isubcase, apply_data_code=True):
ForceObject.__init__(self, data_code, isubcase, apply_data_code=apply_data_code)
@property
def is_real(self) -> bool:
return True
@property
def is_complex(self) -> bool:
return False
@classmethod
def _set_case(cls, table_name, element_name, isubcase,
is_sort1, is_random, is_msc,
random_code, title, subtitle, label):
data_code = oef_data_code(table_name,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code,
title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
data_code['loadIDs'] = [0] # TODO: ???
data_code['data_names'] = []
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name]
data_code['element_name'] = element_name
data_code['element_type'] = element_type
#data_code['load_set'] = 1
return data_code
"""
F A I L U R E I N D I C E S F O R L A Y E R E D C O M P O S I T E E L E M E N T S ( T R I A 3 )
ELEMENT FAILURE PLY FP=FAILURE INDEX FOR PLY FB=FAILURE INDEX FOR BONDING FAILURE INDEX FOR ELEMENT FLAG
ID THEORY ID (DIRECT STRESSES/STRAINS) (INTER-LAMINAR STRESSES) MAX OF FP,FB FOR ALL PLIES
3 STRAIN 1 20345.4805 -2
7.1402
2 0.9025 -12
7.1402
3 20342.2461 -2
20345.4805 ***
4 STRAIN 1 16806.9277 -2
38.8327
2 0.9865 -2
38.8327
3 16804.4199 -2
F A I L U R E I N D I C E S F O R L A Y E R E D C O M P O S I T E E L E M E N T S ( T R I A 6 )
ELEMENT FAILURE PLY FP=FAILURE INDEX FOR PLY FB=FAILURE INDEX FOR BONDING FAILURE INDEX FOR ELEMENT FLAG
ID THEORY ID (DIRECT STRESSES/STRAINS) (INTER-LAMINAR STRESSES) MAX OF FP,FB FOR ALL PLIES
5 STRAIN 1 21850.3184 -2
166984.4219
2 0.7301 -2
166984.4219
3 21847.9902 -2
166984.4219 ***
6 STRAIN 1 18939.8340 -2
130371.3828
2 0.7599 -1
130371.3828
3 18937.7734 -2
F A I L U R E I N D I C E S F O R L A Y E R E D C O M P O S I T E E L E M E N T S ( Q U A D 4 )
ELEMENT FAILURE PLY FP=FAILURE INDEX FOR PLY FB=FAILURE INDEX FOR BONDING FAILURE INDEX FOR ELEMENT FLAG
ID THEORY ID (DIRECT STRESSES/STRAINS) (INTER-LAMINAR STRESSES) MAX OF FP,FB FOR ALL PLIES
1 STRAIN 1 18869.6621 -2
16.2471
2 1.0418 -2
16.2471
3 18866.6074 -2
18869.6621 ***
1 CC227: CANTILEVERED COMPOSITE PLATE 3 LAYER SYMM PLY CC227 DECEMBER 5, 2011 MSC.NASTRAN 6/17/05 PAGE 15
FAILURE CRITERION IS STRAIN, STRESS ALLOWABLES, LIST STRESSES
0
F A I L U R E I N D I C E S F O R L A Y E R E D C O M P O S I T E E L E M E N T S ( Q U A D 8 )
ELEMENT FAILURE PLY FP=FAILURE INDEX FOR PLY FB=FAILURE INDEX FOR BONDING FAILURE INDEX FOR ELEMENT FLAG
ID THEORY ID (DIRECT STRESSES/STRAINS) (INTER-LAMINAR STRESSES) MAX OF FP,FB FOR ALL PLIES
2 STRAIN 1 14123.7451 -2
31.4861
2 1.0430 -2
31.4861
3 14122.1221 -2
"""
[docs]
class FailureIndicesArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.nelements = 0 # result specific
@property
def nnodes_per_element(self):
return 1
[docs]
def build(self):
"""sizes the vectorized attributes of the FailureIndices"""
if self.is_built:
return
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.failure_theory = np.full(self.nelements, '', dtype='U8')
self.element_layer = zeros((self.nelements, 2), dtype=idtype)
#[failure_stress_for_ply, interlaminar_stress, max_value]
self.data = zeros((self.ntimes, self.nelements, 3), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
element_layer = [self.element_layer[:, 0], self.element_layer[:, 1]]
if self.nonlinear_factor not in (None, np.nan):
# Time 0.00 0.05
# ElementID NodeID Item
# 2 1 failure_index_for_ply (direct stress/strain) 0.0 5.431871e-14
# 2 failure_index_for_bonding (interlaminar stresss) 0.0 3.271738e-16
# 3 max_value NaN NaN
# 1 failure_index_for_ply (direct stress/strain) 0.0 5.484873e-30
# 2 failure_index_for_bonding (interlaminar stresss) 0.0 3.271738e-16
# 3 max_value NaN NaN
# 1 failure_index_for_ply (direct stress/strain) 0.0 5.431871e-14
# 2 failure_index_for_bonding (interlaminar stresss) NaN NaN
# 3 max_value 0.0 5.431871e-14
column_names, column_values = self._build_dataframe_transient_header()
names = ['ElementID', 'Layer', 'Item']
data_frame = self._build_pandas_transient_element_node(
column_values, column_names, headers,
element_layer, self.data, names=names,
from_tuples=False, from_array=True)
#column_names, column_values = self._build_dataframe_transient_header()
#data_frame = pd.Panel(self.data, items=column_values,
#major_axis=element_layer, minor_axis=headers).to_frame()
#data_frame.columns.names = column_names
#data_frame.index.names = ['ElementID', 'Layer', 'Item']
else:
#Static failure_index_for_ply (direct stress/strain) failure_index_for_bonding (interlaminar stresss) max_value
#ElementID Layer
#101 1 7.153059e-07 0.0 NaN
# 2 1.276696e-07 0.0 NaN
# 3 7.153059e-07 NaN 7.153059e-07
element_layer = [self.element_layer[:, 0], self.element_layer[:, 1]]
index = pd.MultiIndex.from_arrays(element_layer, names=['ElementID', 'Layer'])
data_frame = pd.DataFrame(self.data[0], columns=headers, index=index)
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def __eq__(self, table):
return True
def add_sort1(self, dt, eid, failure_theory, ply_id, failure_stress_for_ply, flag,
interlaminar_stress, max_value, nine):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element_layer[self.ielement] = [eid, ply_id]
self.failure_theory[self.ielement] = failure_theory
self.data[self.itime, self.ielement, :] = [failure_stress_for_ply, interlaminar_stress, max_value]
self.ielement += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
ntimes = self.data.shape[0]
nelements = self.data.shape[1]
assert self.ntimes == ntimes, 'ntimes=%s expected=%s' % (self.ntimes, ntimes)
assert self.nelements == nelements, 'nelements=%s expected=%s' % (self.nelements, nelements)
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element type: {self.element_name}-{self.element_type}\n')
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
#msg_temp = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
f06_file.write('skipping FailureIndices f06\n')
return page_num
#NotImplementedError(self.code_information())
#asd
#if self.is_sort1:
#page_num = self._write_sort1_as_sort1(header, page_stamp, page_num, f06_file, msg_temp)
#else:
#raise NotImplementedError(self.code_information())
#page_num = self._write_sort2_as_sort2(header, page_stamp, page_num, f06_file, msg_temp)
#' F A I L U R E I N D I C E S F O R L A Y E R E D C O M P O S I T E E L E M E N T S ( T R I A 3 )\n'
#' ELEMENT FAILURE PLY FP=FAILURE INDEX FOR PLY FB=FAILURE INDEX FOR BONDING FAILURE INDEX FOR ELEMENT FLAG\n'
#' ID THEORY ID (DIRECT STRESSES/STRAINS) (INTER-LAMINAR STRESSES) MAX OF FP,FB FOR ALL PLIES\n'
#' 1 HOFFMAN 101 6.987186E-02 \n'
#' 1.687182E-02 \n'
#' 102 9.048269E-02 \n'
#' 1.721401E-02 \n'
#return page_num
[docs]
class RealSpringDamperForceArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.nelements = 0 # result specific
#if not is_sort1:
#raise NotImplementedError('SORT2')
[docs]
@classmethod
def add_static_case(cls, table_name, element_name, element, data, isubcase,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 2
obj = set_static_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data))
obj.is_built = True
return obj
[docs]
@classmethod
def add_modal_case(cls, table_name, element_name, element, data, isubcase,
modes, eigns, freqs,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 2
obj = set_modal_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigns, freqs)
obj.is_built = True
return obj
[docs]
@classmethod
def add_transient_case(cls, table_name, element_name, element, data, isubcase,
times,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 2
obj = set_transient_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), times)
obj.is_built = True
return obj
[docs]
@classmethod
def add_post_buckling_case(cls, table_name, element_name, element, data, isubcase,
modes, eigrs, eigis,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 2
obj = set_post_buckling_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigrs, eigis)
obj.is_built = True
return obj
[docs]
def build(self):
"""sizes the vectorized attributes of the RealSpringDamperForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(
self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self)
self.build_data(ntimes, nelements, dtype, idtype, fdtype)
[docs]
def build_data(self, ntimes, nelements, dtype, idtype, fdtype):
"""actually performs the build step"""
self.ntimes = ntimes
self.nelements = nelements
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[force]
self.data = zeros((ntimes, nelements, 1), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
#Mode 1 2 3
#Freq 1.482246e-10 3.353940e-09 1.482246e-10
#Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
#Radians 9.313226e-10 2.107342e-08 9.313226e-10
#ElementID Item
#30 spring_force 2.388744e-19 -1.268392e-10 -3.341473e-19
#31 spring_force 2.781767e-19 -3.034770e-11 -4.433221e-19
#32 spring_force 0.000000e+00 0.000000e+00 0.000000e+00
#33 spring_force 0.000000e+00 0.000000e+00 0.000000e+00
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
#Static spring_force
#ElementID
#30 0.0
#31 0.0
#32 0.0
#33 0.0
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
is_nan = (
self.nonlinear_factor is not None and
np.isnan(self.nonlinear_factor) and
np.isnan(table.nonlinear_factor)
)
if not is_nan:
assert self.nonlinear_factor == table.nonlinear_factor
assert self.ntotal == table.ntotal
assert self.table_name == table.table_name, 'table_name=%r table.table_name=%r' % (self.table_name, table.table_name)
assert self.approach_code == table.approach_code
if self.nonlinear_factor not in (None, np.nan):
assert np.array_equal(self._times, table._times), 'ename=%s-%s times=%s table.times=%s' % (
self.element_name, self.element_type, self._times, table._times)
if not np.array_equal(self.element, table.element):
assert self.element.shape == table.element.shape, 'shape=%s element.shape=%s' % (self.element.shape, table.element.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\nEid1, Eid2\n' % str(self.code_information())
for eid, eid2 in zip(self.element, table.element):
msg += '%s, %s\n' % (eid, eid2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
ntimes = self.data.shape[0]
i = 0
if self.is_sort1:
for itime in range(ntimes):
for ieid, eid, in enumerate(self.element):
t1 = self.data[itime, ieid, :]
t2 = table.data[itime, ieid, :]
(force1, stress1) = t1
(force2, stress2) = t2
if not allclose(t1, t2):
#if not np.array_equal(t1, t2):
msg += '%s\n (%s, %s)\n (%s, %s)\n' % (
eid,
force1, stress1,
force2, stress2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
else:
raise NotImplementedError(self.is_sort2)
if i > 0:
print(msg)
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, force):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#print('dt=%s eid=%s' % (dt, eid))
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [force]
self.ielement += 1
def add_sort2(self, dt, eid, force):
"""unvectorized method for adding SORT2 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#print('dt=%s eid=%s' % (dt, eid))
itime = self.itotal
self._times[itime] = dt
self.element[self.ielement] = eid
self.data[itime, self.ielement, :] = [force]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
ntimes = self.data.shape[0]
nelements = self.data.shape[1]
assert self.ntimes == ntimes, 'ntimes=%s expected=%s' % (self.ntimes, ntimes)
assert self.nelements == nelements, 'nelements=%s expected=%s' % (self.nelements, nelements)
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (
ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
msg.append(f' element type: {self.element_name}-{self.element_type}\n')
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
"""
Stress Table - CROD/CONROD/CTUBE
--------------------------------
Flag, SubcaseID, iTime, EID, BLANK, BLANK, Sxx, Syy, Szz, Sxy, Syz, Szx
10, 1, 0, 312, 0, 0, 1642.503, 0, 0, 167.541, 0, 0
10, 1, 0, 313, 0, 0, 3937.541, 0, 0, 66.171, 0, 0
"""
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
headers = ['Flag', 'SubcaseID', 'iTime', 'Eid', 'BLANK', 'BLANK', 'Fx', 'BLANK', 'BLANK', 'BLANK', 'BLANK', 'BLANK']
csv_file.write('# ' + ','.join(headers) + '\n')
# stress vs. strain
flag = 12
isubcase = self.isubcase
#times = self._times
# write the f06
ntimes = self.data.shape[0]
zero = ' 0.000000E+00'
eids = self.element
eid_len = '%d' % len(str(eids.max()))
for itime in range(ntimes):
#dt = self._times[itime]
force = self.data[itime, :, 0]
for eid, forcei in zip(eids, force):
if is_exponent_format:
forcei = write_float_13e_long(forcei)
csv_file.write(f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, 0, 0, '
f'{forcei}, {zero}, {zero}, {zero}, {zero}, {zero}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
if self.is_sort1:
page_num = self._write_sort1_as_sort1(header, page_stamp, page_num, f06_file, msg_temp)
else:
raise NotImplementedError(self.code_information())
#page_num = self._write_sort2_as_sort2(header, page_stamp, page_num, f06_file, msg_temp)
return page_num
def _write_sort1_as_sort1(self, header, page_stamp, page_num, f06_file, msg_temp):
ntimes = self.data.shape[0]
eids = self.element
nwrite = len(eids)
nrows = nwrite // 4
nleftover = nwrite - nrows * 4
for itime in range(ntimes):
dt = self._times[itime]
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
stress = self.data[itime, :, 0]
out = []
for eid, stressi in zip(eids, stress):
out.append([eid, write_float_13e(stressi)])
for i in range(0, nrows * 4, 4):
f06_file.write(' %10i %13s %10i %13s %10i %13s %10i %13s\n' % (
tuple(out[i] + out[i + 1] + out[i + 2] + out[i + 3])))
i = nrows * 4
if nleftover == 3:
f06_file.write(' %10i %13s %10i %13s %10i %13s\n' % (
tuple(out[i] + out[i + 1] + out[i + 2])))
elif nleftover == 2:
f06_file.write(' %10i %13s %10i %13s\n' % (
tuple(out[i] + out[i + 1])))
elif nleftover == 1:
f06_file.write(' %10i %13s\n' % tuple(out[i]))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
import inspect
from struct import Struct, pack
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#eids = self.element
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'if')
else:
raise NotImplementedError('SORT2')
op2_ascii.write('%s-nelements=%i\n' % (self.element_name, nelements))
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
force = self.data[itime, :, 0]
for eid, forcei in zip(eids_device, force):
data = [eid, forcei]
op2_ascii.write(' eid=%s force=%s\n' % tuple(data))
op2_file.write(struct1.pack(*data))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealSpringForceArray(RealSpringDamperForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealSpringDamperForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
@property
def nnodes_per_element(self) -> int:
return 1
[docs]
class RealDamperForceArray(RealSpringDamperForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealSpringDamperForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
@property
def nnodes_per_element(self) -> int:
return 1
[docs]
class RealRodForceArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.nelements = 0 # result specific
[docs]
@classmethod
def add_static_case(cls, table_name, element_name, element, data, isubcase,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 3
obj = set_static_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data))
return obj
[docs]
@classmethod
def add_modal_case(cls, table_name, element_name, element, data, isubcase,
modes, eigns, freqs,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 3
obj = set_modal_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigns, freqs)
obj.is_built = True
return obj
[docs]
@classmethod
def add_transient_case(cls, table_name, element_name, element, data, isubcase,
times,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 3
obj = set_transient_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), times)
obj.is_built = True
return obj
[docs]
@classmethod
def add_post_buckling_case(cls, table_name, element_name, element, data, isubcase,
modes, eigrs, eigis,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 3
obj = set_post_buckling_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigrs, eigis)
obj.is_built = True
return obj
@property
def nnodes_per_element(self) -> int:
return 1
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
def _get_msgs(self):
base_msg = [' ELEMENT AXIAL TORSIONAL ELEMENT AXIAL TORSIONAL\n',
' ID. FORCE MOMENT ID. FORCE MOMENT\n']
crod_msg = [' F O R C E S I N R O D E L E M E N T S ( C R O D )\n', ]
conrod_msg = [' F O R C E S I N R O D E L E M E N T S ( C O N R O D )\n', ]
ctube_msg = [' F O R C E S I N R O D E L E M E N T S ( C T U B E )\n', ]
crod_msg += base_msg
conrod_msg += base_msg
ctube_msg += base_msg
return crod_msg, conrod_msg, ctube_msg
[docs]
def build(self):
"""sizes the vectorized attributes of the RealRodForceArray"""
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
ntimes, nelements, ntotal = get_sort_element_sizes(self, debug=False)
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
self.build_data(ntimes, nelements, float_fmt='float32')
[docs]
def build_data(self, ntimes, nelements, float_fmt='float32'):
"""actually performs the build step"""
self.ntimes = ntimes
self.nelements = nelements
#self.ntotal = ntimes * nelements
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[axial_force, torque]
self.data = zeros((ntimes, nelements, 2), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
#Static axial SMa torsion SMt
#ElementID
#14 0.0 1.401298e-45 0.0 1.401298e-45
#15 0.0 1.401298e-45 0.0 1.401298e-45
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def add_sort1(self, dt: Union[int, float], eid: int, axial: float, torque: float) -> None:
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [axial, torque]
self.ielement += 1
if self.ielement == self.nelements:
self.ielement = 0
def add_sort2(self, dt: Union[int, float], eid: int, axial: float, torque: float) -> None:
"""unvectorized method for adding SORT2 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
itime = self.itotal
self._times[itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [axial, torque]
self.itotal += 1
#if self.ielement == self.nelements:
#self.ielement = 0
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (
ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
"""
Force Table - CROD/CONROD/CTUBE
-------------------------------
Flag, SubcaseID, iTime, EID, BLANK, BLANK, Faxial, BLANK, BLANK, Torsion, BLANK, BLANK
10, 1, 0, 312, 0, 0, 1642.503, 0, 0, 167.541, 0, 0
10, 1, 0, 313, 0, 0, 3937.541, 0, 0, 66.171, 0, 0
"""
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
headers = ['Flag', 'SubcaseID', 'iTime', 'Eid', 'BLANK', 'BLANK', 'Faxial', 'BLANK', 'BLANK', 'Torsion', 'BLANK', 'BLANK']
csv_file.write('# ' + ','.join(headers) + '\n')
# stress vs. strain
flag = 12
isubcase = self.isubcase
#times = self._times
# write the f06
ntimes = self.data.shape[0]
eids = self.element
eid_len = '%d' % len(str(eids.max()))
zero = ' 0.000000E+00'
for itime in range(ntimes):
dt = self._times[itime]
#header = _eigenvalue_header(self, header, itime, ntimes, dt)
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
axial = self.data[itime, :, 0]
torsion = self.data[itime, :, 1]
for eid, axiali, torsioni in zip(eids, axial, torsion):
if is_exponent_format:
[axiali, torsioni] = write_floats_13e_long([axiali, torsioni])
csv_file.write(f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, 0, 0, '
f'{axiali}, {zero}, {zero}, {torsioni}, {zero}, {zero}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
(elem_name, msg_temp) = self.get_f06_header(is_mag_phase)
# write the f06
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
is_odd = False
nwrite = len(eids)
if len(eids) % 2 == 1:
nwrite -= 1
is_odd = True
#print('len(eids)=%s nwrite=%s is_odd=%s' % (len(eids), nwrite, is_odd))
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
axial = self.data[itime, :, 0]
torsion = self.data[itime, :, 1]
out = []
for eid, axiali, torsioni in zip(eids, axial, torsion):
[axiali, torsioni] = write_floats_13e([axiali, torsioni])
out.append([eid, axiali, torsioni])
for i in range(0, nwrite, 2):
out_line = ' %8i %-13s %-13s %8i %-13s %s\n' % tuple(out[i] + out[i + 1])
f06_file.write(out_line)
if is_odd:
out_line = ' %8i %-13s %s\n' % tuple(out[-1])
f06_file.write(out_line)
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
is_nan = (
self.nonlinear_factor is not None and
np.isnan(self.nonlinear_factor) and
np.isnan(table.nonlinear_factor)
)
if not is_nan:
assert self.nonlinear_factor == table.nonlinear_factor
assert self.ntotal == table.ntotal
assert self.table_name == table.table_name, 'table_name=%r table.table_name=%r' % (self.table_name, table.table_name)
assert self.approach_code == table.approach_code
if self.nonlinear_factor not in (None, np.nan):
assert np.array_equal(self._times, table._times), 'ename=%s-%s times=%s table.times=%s' % (
self.element_name, self.element_type, self._times, table._times)
if not np.array_equal(self.element, table.element):
assert self.element.shape == table.element.shape, 'element shape=%s table.shape=%s' % (self.element.shape, table.element.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
msg += 'Eid\n'
for eid, eid2 in zip(self.element, table.element):
msg += '%s, %s\n' % (eid, eid2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(axial1, torque1) = t1
(axial2, torque2) = t2
if not np.array_equal(t1, t2):
msg += '(%s) (%s, %s) (%s, %s)\n' % (
eid,
axial1, torque1,
axial2, torque2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
#eids = self.element
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'i2f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write('%s-nelements=%i\n' % (self.element_name, nelements))
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
axial = self.data[itime, :, 0]
torsion = self.data[itime, :, 1]
#print('eids3', eids3)
for eid, axiali, torsioni in zip(eids_device, axial, torsion):
data = [eid, axiali, torsioni]
op2_ascii.write(' eid=%s axial=%s torsion=%s\n' % tuple(data))
op2_file.write(struct1.pack(*data))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealCBeamForceArray(RealForceObject):
"""11 nodes/element"""
def __init__(self, data_code, is_sort1, isubcase, dt):
#ForceObject.__init__(self, data_code, isubcase)
RealForceObject.__init__(self, data_code, isubcase)
self.result_flag = 0
self.itime = 0
self.nelements = 0 # result specific
#if is_sort1:
##sort1
#pass
#else:
#raise NotImplementedError('SORT2')
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCBeamForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s subtitle=%s' % (self.ntimes, self.nelements, self.ntotal, self.subtitle))
if self.is_built:
return
nnodes = 11
#self.names = []
#self.nelements //= nnodes
self.nelements //= self.ntimes
#self.ntotal //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#print('ntotal=%s ntimes=%s nelements=%s' % (self.ntotal, self.ntimes, self.nelements))
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(
self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self, debug=False)
self._times = zeros(ntimes, dtype)
self.element = zeros(ntotal, idtype)
self.element_node = zeros((ntotal, 2), idtype)
# the number is messed up because of the offset for the element's properties
if not (self.nelements * nnodes) == self.ntotal:
msg = 'ntimes=%s nelements=%s nnodes=%s ne*nn=%s ntotal=%s' % (self.ntimes,
self.nelements, nnodes,
self.nelements * nnodes,
self.ntotal)
if self.size == 4:
raise RuntimeError(msg)
else:
warnings.warn(msg)
#[sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq]
self.data = np.full((ntimes, ntotal, 8), np.nan, fdtype)
[docs]
def finalize(self):
sd = self.data[0, :, 0]
i_sd_zero = np.where(np.isfinite(sd) & (sd != 0.0))[0]
i_node_zero = np.where(self.element_node[:, 1] != 0)[0]
assert i_node_zero.max() > 0, "CBEAM element_node hasn't been filled"
i = np.union1d(i_sd_zero, i_node_zero)
#self.nelements = len(self.element) // 11
self.element = self.element[i]
self.element_node = self.element_node[i, :]
self.data = self.data[:, i, :]
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
element_location = [
self.element_node[:, 0],
self.data[0, :, 0],
]
if self.nonlinear_factor not in (None, np.nan):
#Mode 1 2 3
#Freq 1.482246e-10 3.353940e-09 1.482246e-10
#Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
#Radians 9.313226e-10 2.107342e-08 9.313226e-10
#ElementID Location Item
#12 0.0 bending_moment1 1.505494e-13 -2.554764e-07 -5.272747e-13
# bending_moment2 -2.215085e-13 -2.532377e-07 3.462328e-13
# shear1 1.505494e-13 -2.554763e-07 -5.272747e-13
# shear2 -2.215085e-13 -2.532379e-07 3.462328e-13
# axial_force 1.294136e-15 -1.670896e-09 4.759476e-16
# total_torque -4.240346e-16 2.742446e-09 1.522254e-15
# warping_torque 0.000000e+00 0.000000e+00 0.000000e+00
# 1.0 bending_moment1 0.000000e+00 -1.076669e-13 1.009742e-28
# bending_moment2 -5.048710e-29 1.704975e-13 0.000000e+00
# shear1 1.505494e-13 -2.554763e-07 -5.272747e-13
# shear2 -2.215085e-13 -2.532379e-07 3.462328e-13
# axial_force 1.294136e-15 -1.670896e-09 4.759476e-16
# total_torque -4.240346e-16 2.742446e-09 1.522254e-15
# warping_torque 0.000000e+00 0.000000e+00 0.000000e+00
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_element_node(
column_values, column_names,
headers[1:], element_location, self.data[:, :, 1:], from_tuples=False, from_array=True)
data_frame.index.names = ['ElementID', 'Location', 'Item']
else:
df1 = pd.DataFrame(element_location).T
df1.columns = ['ElementID', 'Location']
df2 = pd.DataFrame(self.data[0])
df2.columns = headers
data_frame = df1.join([df2])
#self.data_frame = data_frame.reset_index().replace({'NodeID': {0:'CEN'}}).set_index(['ElementID', 'NodeID'])
self.data_frame = data_frame
[docs]
@classmethod
def add_static_case(cls, table_name, element_name, element_node, xxb, data, isubcase,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 100
obj = set_static_case(cls, is_sort1, isubcase, data_code,
set_element_node_xxb_case, (element_node, xxb, data))
return obj
[docs]
@classmethod
def add_modal_case(cls, table_name, element_name, element_node, xxb, data, isubcase,
modes, eigns, freqs,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 100
obj = set_modal_case(cls, is_sort1, isubcase, data_code,
set_element_node_xxb_case, (element_node, xxb, data),
modes, eigns, freqs)
return obj
[docs]
@classmethod
def add_transient_case(cls, table_name, element_name, element_node, xxb, data, isubcase,
times,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 100
obj = set_transient_case(cls, is_sort1, isubcase, data_code,
set_element_node_xxb_case, (element_node, xxb, data),
times)
return obj
[docs]
@classmethod
def add_post_buckling_case(cls, table_name, element_name, element_node, xxb, data, isubcase,
modes, eigrs, eigis,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 100
obj = set_post_buckling_case(cls, is_sort1, isubcase, data_code,
set_element_node_xxb_case, (element_node, xxb, data),
modes, eigrs, eigis)
return obj
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
ntimes = self.data.shape[0]
i = 0
if self.is_sort1:
for itime in range(ntimes):
for ieid, eid in enumerate(self.element):
t1 = self.data[itime, ieid, :]
t2 = table.data[itime, ieid, :]
#sd = self.data[itime, :, 0]
#bm1 = self.data[itime, :, 1]
#bm2 = self.data[itime, :, 2]
#ts1 = self.data[itime, :, 3]
#ts2 = self.data[itime, :, 4]
#af = self.data[itime, :, 5]
#ttrq = self.data[itime, :, 6]
#wtrq = self.data[itime, :, 7]
(sd1, bm11, bm21, ts11, ts21, af1, ttrq1, wtrq1) = t1
(sd2, bm12, bm22, ts12, ts22, af2, ttrq2, wtrq2) = t2
if not np.allclose(t1, t2):
#if not np.array_equal(t1, t2):
msg += '%s\n (%s, %s, %s, %s, %s, %s, %s, %s)\n (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
sd1, bm11, bm21, ts11, ts21, af1, ttrq1, wtrq1,
sd2, bm12, bm22, ts12, ts22, af2, ttrq2, wtrq2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
else:
raise NotImplementedError(self.is_sort2)
if i > 0:
print(msg)
raise ValueError(msg)
return True
def __pos__(self) -> RealCBeamForceArray:
"""positive; +a"""
return self
def __neg__(self) -> RealCBeamForceArray:
"""
negative; -a
We stick this [:, :, 1:] all over the place because we don't
want to modify the sd field (aka x/xb).
"""
new_table = copy.deepcopy(self)
new_table.data[:, :, 1:] *= -1.0
return new_table
def __add__(self, table: RealCBeamForceArray) -> RealCBeamForceArray:
"""a + b"""
if isinstance(table, RealCBeamForceArray):
self._check_math(table)
new_data = self.data[:, :, 1:] + table.data[:, :, 1:]
#self._fix_min_max(new_data)
elif isinstance(table, (integer_types, float_types)):
new_data = self.data[:, :, 1:] + table
else:
raise TypeError(table)
new_table = copy.deepcopy(self)
new_table.data[:, :, 1:] = new_data
return new_table
# __radd__: reverse order adding (b+a)
def __iadd__(self, table: RealCBeamForceArray) -> RealCBeamForceArray:
"""inplace adding; a += b"""
if isinstance(table, RealCBeamForceArray):
self._check_math(table)
self.data[:, :, 1:] += table.data[:, :, 1:]
#self._fix_min_max(self.data)
elif isinstance(table, (integer_types, float_types)):
self.data[:, :, 1:] -= table
else:
raise TypeError(table)
return self
def __sub__(self, table: RealCBeamForceArray):
"""a - b"""
if isinstance(table, RealCBeamForceArray):
self._check_math(table)
new_data = self.data[:, :, 1:] - table.data[:, :, 1:]
elif isinstance(table, (integer_types, float_types)):
new_data = self.data[:, :, 1:] - table
else:
raise TypeError(table)
new_table = copy.deepcopy(self)
new_table.data[:, :, 1:] = new_data
return new_table
def __mul__(self, table: RealCBeamForceArray):
"""a * b"""
if isinstance(table, RealCBeamForceArray):
self._check_math(table)
new_data = self.data[:, :, 1:] * table.data[:, :, 1:]
elif isinstance(table, (integer_types, float_types)):
new_data = self.data[:, :, 1:] * table
else:
raise TypeError(table)
new_table = copy.deepcopy(self)
new_table.data[:, :, 1:] = new_data
return new_table
def __truediv__(self, table: RealCBeamForceArray):
"""a / b"""
if isinstance(table, RealCBeamForceArray):
self._check_math(table)
new_data = self.data[:, :, 1:] / table.data[:, :, 1:]
elif isinstance(table, (integer_types, float_types)):
new_data = self.data[:, :, 1:] / table
else:
raise TypeError(table)
new_table = copy.deepcopy(self)
new_table.data[:, :, 1:] = new_data
return new_table
def _check_math(self, table: RealCBeamForceArray) -> None:
"""verifies that the shapes are the same"""
assert self.ntimes == table.ntimes, f'ntimes={self.ntimes} table.times={table.ntimes}'
assert self.ntotal == table.ntotal, f'ntotal={self.ntotal} table.ntotal={table.ntotal}'
assert self.element_node.shape == table.element_node.shape, f'element_node.shape={self.element_node.shape} table.element_node.shape={table.element_node.shape}'
assert self.data.shape == table.data.shape, f'data.shape={self.data.shape} table.data.shape={table.data.shape}'
#def _fix_min_max(self, data: np.ndarray) -> None:
# I don't think I need this function...
# NOTE: "sd" is the source of the [:, :, 1:] part above
#sd = self.data[itime, :, 0]
#bm1 = self.data[itime, :, 1]
#bm2 = self.data[itime, :, 2]
#ts1 = self.data[itime, :, 3]
#ts2 = self.data[itime, :, 4]
#af = self.data[itime, :, 5]
#ttrq = self.data[itime, :, 6]
#wtrq = self.data[itime, :, 7]
#return
#sxc = data[:, :, 0]
#sxd = data[:, :, 1]
#sxe = data[:, :, 2]
#sxf = data[:, :, 3]
#max = data[:, :, 4]
#smin = data[:, :, 5]
#shape = sxc.shape
#maxi = np.max(data[:, :, [0, 1, 2, 3]], axis=2)
#mini = np.min(data[:, :, [0, 1, 2, 3]], axis=2)
#assert maxi.shape == sxc.shape
#data[:, :, 4] = maxi
#data[:, :, 5] = mini
# can you fix MS_tension/compression?
[docs]
def filter_by_index(self, icable_element: np.ndarray) -> None:
self.element = self.element[icable_element]
self.element_node = self.element_node[icable_element, :]
self.data = self.data[:, icable_element, :]
def add_sort1(self, dt, eid, nid, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.data[self.itime, self.itotal, :] = [sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq]
self.element[self.itotal] = eid
self.element_node[self.itotal, :] = [eid, nid]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
else:
msg.append(' type=%s nelements=%i; table_name=%r\n' % (
self.__class__.__name__, nelements, self.table_name))
#msg.append(' eType, cid\n')
msg.append(' data: [ntimes, nelements, 8] where 8=[%s]\n' % str(', '.join(self.get_headers())))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
msg.append(f' element_node.shape = {self.element_node.shape}\n')
msg.append(' is_sort1=%s is_sort2=%s\n' % (self.is_sort1, self.is_sort2))
msg.append(' CBEAM\n')
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
#name = self.data_code['name']
#if name == 'freq':
#name = 'FREQUENCY'
#else: # mode
#raise RuntimeError(name)
#if is_sort1:
msg_temp = [
' F O R C E S I N B E A M E L E M E N T S ( C B E A M )\n',
' STAT DIST/ - BENDING MOMENTS - - WEB SHEARS - AXIAL TOTAL WARPING\n',
' ELEMENT-ID GRID LENGTH PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE TORQUE\n']
#else:
#raise NotImplementedError('CBEAM-SORT2')
if self.is_sort1:
#assert self.is_sort1 is True, str(self)
#if is_sort1:
page_num = self._write_sort1_as_sort1(f06_file, page_num, page_stamp, header, msg_temp)
#else:
#self._write_sort1_as_sort2(f06_file, page_num, page_stamp, header, msg_temp)
else:
print(f'skipping {self.__class__.__name__} because its sort2')
#assert self.is_sort1 is True, str(self)
return page_num - 1
def _write_sort1_as_sort1(self, f06_file, page_num, page_stamp, header, msg_temp):
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
long_form = False
if nids.min() == 0:
msg = header + [
' F O R C E S I N B E A M E L E M E N T S ( C B E A M )\n',
' STAT DIST/ - BENDING MOMENTS - - WEB SHEARS - AXIAL TOTAL WARPING\n',
' ELEMENT-ID GRID LENGTH PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE TORQUE\n']
long_form = True
#times = self._times
ntimes = self.data.shape[0]
for itime in range(ntimes):
if self.nonlinear_factor not in (None, np.nan):
dt = self._times[itime]
dt_line = ' %14s = %12.5E\n' % (self.data_code['name'], dt)
header[1] = dt_line
msg = header + msg_temp
f06_file.write(''.join(msg))
#sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq
assert self.is_sort1 is True, str(self)
sd = self.data[itime, :, 0]
bm1 = self.data[itime, :, 1]
bm2 = self.data[itime, :, 2]
ts1 = self.data[itime, :, 3]
ts2 = self.data[itime, :, 4]
af = self.data[itime, :, 5]
ttrq = self.data[itime, :, 6]
wtrq = self.data[itime, :, 7]
for eid, nid, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi in zip(eids, nids, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
vals = (bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi)
vals2 = write_floats_13e(vals)
(sbm1i, sbm2i, sts1i, sts2i, safi, sttrqi, swtrq) = vals2
if long_form:
f06_file.write(' %8i %.3f %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, sdi, sbm1i, sbm2i, sts1i, sts2i, safi, sttrqi, swtrq))
else:
if sdi == 0.:
f06_file.write('0 %8i\n' % eid)
f06_file.write(' %8i %.3f %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
nid, sdi, sbm1i, sbm2i, sts1i, sts2i, safi, sttrqi, swtrq))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
#long_form = False
#if nids.min() == 0:
#long_form = True
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
#xxbs = self.xxb
#print(xxbs)
eids_device = eids * 10 + self.device_code
ueids = np.unique(eids)
#ieid = np.searchsorted(eids, ueids)
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = len(ueids)
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
op2_ascii.write(f' ntimes = {self.ntimes}\n')
if not self.is_sort1:
raise NotImplementedError('SORT2')
struct1 = Struct(endian + b'2i 8f')
struct2 = Struct(endian + b'i 8f')
op2_ascii.write(f'nelements={nelements:d}\n')
struct_13i = Struct('13i')
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(struct_13i.pack(*header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
sd = self.data[itime, :, 0]
bm1 = self.data[itime, :, 1]
bm2 = self.data[itime, :, 2]
ts1 = self.data[itime, :, 3]
ts2 = self.data[itime, :, 4]
af = self.data[itime, :, 5]
ttrq = self.data[itime, :, 6]
wtrq = self.data[itime, :, 7]
icount = 0
nwide = 0
ielement = 0
assert len(eids) == len(sd)
for eid, nid, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi in zip(eids, nids, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
if icount == 0:
eid_device = eids_device[ielement]
nid = nids[ielement]
data = [eid_device, nid, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi] # 10
op2_file.write(struct1.pack(*data))
ielement += 1
icount = 1
elif nid > 0 and icount > 0:
# 11 total nodes, with 1, 11 getting an nid; the other 9 being
# xxb sections
data = [0, 0., 0., 0., 0., 0., 0., 0., 0.]
#print('***adding %s\n' % (10-icount))
for unused_i in range(10 - icount):
op2_file.write(struct2.pack(*data))
nwide += len(data)
eid_device2 = eids_device[ielement]
assert eid_device == eid_device2
nid = nids[ielement]
data = [nid, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi] # 9
op2_file.write(struct2.pack(*data))
ielement += 1
icount = 0
elif nid == 0 and icount > 0:
eid_device2 = eids_device[ielement]
data = [nid, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi] # 9
op2_file.write(struct2.pack(*data))
ielement += 1
#data = [0, xxb, sxc, sxd, sxe, sxf, smax, smin, smt, smc] # 10
#op2_file.write(struct2.pack(*data))
icount += 1
elif nid == 0 and icount > 0: # pragma: no cover
raise RuntimeError('OEF-CBEAM op2 writer')
else:
raise RuntimeError('OEF-CBEAM op2 writer')
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, str(data)))
nwide += len(data)
assert ntotal == nwide, 'ntotal=%s nwide=%s' % (ntotal, nwide)
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealCShearForceArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
#if not is_sort1:
#raise NotImplementedError('SORT2')
@property
def nnodes_per_element(self) -> int:
return 1
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCShearForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self, debug=False)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[force41, force21, force12, force32, force23, force43,
# force34, force14,
# kick_force1, shear12, kick_force2, shear23,
# kick_force3, shear34, kick_force4, shear41]
self.data = zeros((ntimes, ntotal, 16), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
#Mode 1 2 3
#Freq 1.482246e-10 3.353940e-09 1.482246e-10
#Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
#Radians 9.313226e-10 2.107342e-08 9.313226e-10
#ElementID Item
#22 force41 -4.025374e-14 2.935730e-08 1.017620e-13
# force21 -4.025374e-14 2.935730e-08 1.017620e-13
# force12 4.025374e-14 -2.935730e-08 -1.017620e-13
# force32 4.025374e-14 -2.935730e-08 -1.017620e-13
# force23 -4.025374e-14 2.935730e-08 1.017620e-13
# force43 -4.025374e-14 2.935730e-08 1.017620e-13
# force34 4.025374e-14 -2.935730e-08 -1.017620e-13
# force14 4.025374e-14 -2.935730e-08 -1.017620e-13
# kick_force1 -0.000000e+00 0.000000e+00 0.000000e+00
# shear12 -8.050749e-14 5.871460e-08 2.035239e-13
# kick_force2 -0.000000e+00 0.000000e+00 0.000000e+00
# shear23 -8.050749e-14 5.871460e-08 2.035239e-13
# kick_force3 -0.000000e+00 0.000000e+00 0.000000e+00
# shear34 -8.050749e-14 5.871460e-08 2.035239e-13
# kick_force4 -0.000000e+00 0.000000e+00 0.000000e+00
# shear41 -8.050749e-14 5.871460e-08 2.035239e-13
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
#Static axial SMa torsion SMt
#ElementID
#14 0.0 1.401298e-45 0.0 1.401298e-45
#15 0.0 1.401298e-45 0.0 1.401298e-45
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
[docs]
@classmethod
def add_modal_case(cls, table_name, element_name, element, data, isubcase,
modes, eigns, freqs,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
obj = set_modal_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigns, freqs)
obj.is_built = True
return obj
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
is_nan = (
self.nonlinear_factor is not None and
np.isnan(self.nonlinear_factor) and
np.isnan(table.nonlinear_factor)
)
if not is_nan:
assert self.nonlinear_factor == table.nonlinear_factor
assert self.ntotal == table.ntotal
assert self.table_name == table.table_name, 'table_name=%r table.table_name=%r' % (self.table_name, table.table_name)
assert self.approach_code == table.approach_code
if self.nonlinear_factor not in (None, np.nan):
assert np.array_equal(self._times, table._times), 'ename=%s-%s times=%s table.times=%s' % (
self.element_name, self.element_type, self._times, table._times)
if not np.array_equal(self.element, table.element):
assert self.element.shape == table.element.shape, 'element shape=%s table.shape=%s' % (self.element.shape, table.element.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
msg += 'Eid\n'
for eid1, eid2 in zip(self.element, table.element):
msg += '%s, %s\n' % (eid1, eid2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(force41a, force14a, force21a, force12a, force32a, force23a, force43a, force34a, kick_force1a, kick_force2a, kick_force3a, kick_force4a, shear12a, shear23a, shear34a, shear41a) = t1
(force41b, force14b, force21b, force12b, force32b, force23b, force43b, force34b, kick_force1b, kick_force2b, kick_force3b, kick_force4b, shear12b, shear23b, shear34b, shear41b) = t2
if not np.array_equal(t1, t2):
msg += (
'%s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n'
' (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
force41a, force14a, force21a, force12a, force32a, force23a, force43a, force34a, kick_force1a, kick_force2a, kick_force3a, kick_force4a, shear12a, shear23a, shear34a, shear41a,
force41b, force14b, force21b, force12b, force32b, force23b, force43b, force34b, kick_force1b, kick_force2b, kick_force3b, kick_force4b, shear12b, shear23b, shear34b, shear41b
))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
def add_sort1(self, dt, eid,
force41, force14, force21, force12, force32, force23, force43, force34,
kick_force1, kick_force2, kick_force3, kick_force4,
shear12, shear23, shear34, shear41):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [
force41, force14, force21, force12, force32, force23, force43, force34,
kick_force1, kick_force2, kick_force3, kick_force4,
shear12, shear23, shear34, shear41]
self.ielement += 1
def add_sort2(self, dt, eid,
force41, force14, force21, force12, force32, force23, force43, force34,
kick_force1, kick_force2, kick_force3, kick_force4,
shear12, shear23, shear34, shear41):
"""unvectorized method for adding SORT1 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itotal] = dt
self.element[self.ielement] = eid
self.data[self.itotal, self.ielement, :] = [
force41, force14, force21, force12, force32, force23, force43, force34,
kick_force1, kick_force2, kick_force3, kick_force4,
shear12, shear23, shear34, shear41]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
"""
Force Table - CSHEAR
-------------------------------
Flag, SubcaseID, iTime, EID, BLANK, BLANK
"""
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
#headers = ['Flag', 'SubcaseID', 'iTime', 'EID', 'BLANK', 'BLANK',
#'Nxx', 'Nyy', 'Nxy', 'Mxx', 'Myy', 'Mxy', 'Qx', 'Qy']
headers = ['Flag', 'SubcaseID', 'iTime', 'EID', 'BLANK', 'BLANK',
'f14', 'f12', 'f21', 'f23', 'f32', 'f34', 'f43', 'f41',
'kick1', 'tau12', 'kick2', 'tau23', 'kick3', 'tau34', 'kick4', 'tau41']
csv_file.write('# ' + ','.join(headers) + '\n')
flag = 12
isubcase = self.isubcase
#times = self._times
ntimes = self.data.shape[0]
eids = self.element
eid_len = '%d' % len(str(eids.max()))
#zero = ' 0.000000E+00'
for itime in range(ntimes):
f14 = self.data[itime, :, 0]
f12 = self.data[itime, :, 1]
f21 = self.data[itime, :, 2]
f23 = self.data[itime, :, 3]
f32 = self.data[itime, :, 4]
f34 = self.data[itime, :, 5]
f43 = self.data[itime, :, 6]
f41 = self.data[itime, :, 7]
kick1 = self.data[itime, :, 8]
tau12 = self.data[itime, :, 9]
kick2 = self.data[itime, :, 10]
tau23 = self.data[itime, :, 11]
kick3 = self.data[itime, :, 12]
tau34 = self.data[itime, :, 13]
kick4 = self.data[itime, :, 14]
tau41 = self.data[itime, :, 15]
#zip_in = [
#f14, f12, f21, f23, f32, f34, f43, f41,
#kick1, tau12, kick2, tau23, kick3, tau34, kick4, tau41,
#]
for (eid, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i) in zip(
eids, f14, f12, f21, f23, f32, f34, f43, f41,
kick1, tau12, kick2, tau23, kick3, tau34, kick4, tau41):
if is_exponent_format:
vals2 = write_floats_12e([
f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i])
[
f14i, f12i,
f21i, f23i,
f32i, f34i,
f43i, f41i,
kick1i, tau12i, kick2i, tau23i,
kick3i, tau34i, kick4i, tau41i
] = vals2
csv_file.write(
f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, 0, 0, '
f'{f14i}, {f12i}, {f21i}, {f23i}, {f32i}, {f34i}, {f43i}, {f41i}, '
f'{kick1i}, {tau12i}, {kick2i}, {tau23i}, {kick3i}, {tau34i}, {kick4i}, {tau41i}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = [
' F O R C E S A C T I N G O N S H E A R P A N E L E L E M E N T S (CSHEAR)\n'
' \n'
' ====== POINT 1 ====== ====== POINT 2 ====== ====== POINT 3 ====== ====== POINT 4 ======\n'
' ELEMENT F-FROM-4 F-FROM-2 F-FROM-1 F-FROM-3 F-FROM-2 F-FROM-4 F-FROM-3 F-FROM-1\n'
' ID KICK-1 SHEAR-12 KICK-2 SHEAR-23 KICK-3 SHEAR-34 KICK-4 SHEAR-41\n'
]
#(elem_name, msg_temp) = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
f14 = self.data[itime, :, 0]
f12 = self.data[itime, :, 1]
f21 = self.data[itime, :, 2]
f23 = self.data[itime, :, 3]
f32 = self.data[itime, :, 4]
f34 = self.data[itime, :, 5]
f43 = self.data[itime, :, 6]
f41 = self.data[itime, :, 7]
kick1 = self.data[itime, :, 8]
tau12 = self.data[itime, :, 9]
kick2 = self.data[itime, :, 10]
tau23 = self.data[itime, :, 11]
kick3 = self.data[itime, :, 12]
tau34 = self.data[itime, :, 13]
kick4 = self.data[itime, :, 14]
tau41 = self.data[itime, :, 15]
#zip_in = [
#f14, f12, f21, f23, f32, f34, f43, f41,
#kick1, tau12, kick2, tau23, kick3, tau34, kick4, tau41,
#]
for (eid, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i) in zip(
eids, f14, f12, f21, f23, f32, f34, f43, f41,
kick1, tau12, kick2, tau23, kick3, tau34, kick4, tau41):
vals2 = write_floats_12e([
f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i])
[
f14i, f12i,
f21i, f23i,
f32i, f34i,
f43i, f41i,
kick1i, tau12i, kick2i, tau23i,
kick3i, tau34i, kick4i, tau41i
] = vals2
f06_file.write(
'0%13i%-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result, date,
is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
unused_eids = self.element
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids = self.element
eids_device = self.element * 10 + self.device_code
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'i 16f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write(f'nelements={nelements:d}\n')
for itime in range(self.ntimes):
#print('3, %s' % itable)
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
#print('4, %s' % itable)
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
f14 = self.data[itime, :, 0]
f12 = self.data[itime, :, 1]
f21 = self.data[itime, :, 2]
f23 = self.data[itime, :, 3]
f32 = self.data[itime, :, 4]
f34 = self.data[itime, :, 5]
f43 = self.data[itime, :, 6]
f41 = self.data[itime, :, 7]
kick1 = self.data[itime, :, 8]
tau12 = self.data[itime, :, 9]
kick2 = self.data[itime, :, 10]
tau23 = self.data[itime, :, 11]
kick3 = self.data[itime, :, 12]
tau34 = self.data[itime, :, 13]
kick4 = self.data[itime, :, 14]
tau41 = self.data[itime, :, 15]
for (eid, eid_device, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i) in zip(
eids, eids_device, f14, f12, f21, f23, f32, f34, f43, f41,
kick1, tau12, kick2, tau23, kick3, tau34, kick4, tau41):
op2_file.write(struct1.pack(
eid_device, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i))
vals2 = write_floats_12e([
f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i])
[
f14i, f12i,
f21i, f23i,
f32i, f34i,
f43i, f41i,
kick1i, tau12i, kick2i, tau23i,
kick3i, tau34i, kick4i, tau41i
] = vals2
op2_ascii.write(
'0%13i%-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, f14i, f12i, f21i, f23i, f32i, f34i, f43i, f41i,
kick1i, tau12i, kick2i, tau23i, kick3i, tau34i, kick4i, tau41i))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealViscForceArray(RealForceObject): # 24-CVISC
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
#if not is_sort1:
#raise NotImplementedError('SORT2')
@property
def nnodes_per_element(self) -> int:
return 1
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the RealViscForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self, debug=False)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[axial_force, torque]
self.data = zeros((ntimes, ntotal, 2), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
#Mode 1 2 3
#Freq 1.482246e-10 3.353940e-09 1.482246e-10
#Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
#Radians 9.313226e-10 2.107342e-08 9.313226e-10
#ElementID Item
#50 axial -0.0 -0.0 0.0
# torsion 0.0 0.0 -0.0
#51 axial 0.0 -0.0 -0.0
# torsion -0.0 0.0 0.0
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
#Static axial torsion
#ElementID
#14 0.0 0.0
#15 0.0 0.0
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
[docs]
@classmethod
def add_transient_case(cls, table_name, element_name, element, data, isubcase,
times,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
obj = set_transient_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), times)
obj.is_built = True
return obj
def add_sort1(self, dt, eid, axial, torque):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [axial, torque]
self.ielement += 1
def add_sort2(self, dt, eid, axial, torque):
"""unvectorized method for adding SORT1 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itotal] = dt
self.element[self.ielement] = eid
self.data[self.itotal, self.ielement, :] = [axial, torque]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
"""
Force Table - CROD/CONROD/CTUBE
-------------------------------
Flag, SubcaseID, iTime, EID, BLANK, BLANK, Faxial, BLANK, BLANK, Torsion, BLANK, BLANK
10, 1, 0, 312, 0, 0, 1642.503, 0, 0, 167.541, 0, 0
10, 1, 0, 313, 0, 0, 3937.541, 0, 0, 66.171, 0, 0
"""
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
headers = ['Flag', 'SubcaseID', 'iTime', 'Eid', 'BLANK', 'BLANK', 'Faxial', 'BLANK', 'BLANK', 'Torsion', 'BLANK', 'BLANK']
csv_file.write('# ' + ','.join(headers) + '\n')
# stress vs. strain
flag = 12
isubcase = self.isubcase
#times = self._times
# write the f06
ntimes = self.data.shape[0]
eids = self.element
eid_len = '%d' % len(str(eids.max()))
zero = ' 0.000000E+00'
for itime in range(ntimes):
dt = self._times[itime]
#header = _eigenvalue_header(self, header, itime, ntimes, dt)
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
axial = self.data[itime, :, 0]
torsion = self.data[itime, :, 1]
for eid, axiali, torsioni in zip(eids, axial, torsion):
if is_exponent_format:
[axiali, torsioni] = write_floats_13e_long([axiali, torsioni])
csv_file.write(f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, 0, 0, '
f'{axiali}, {zero}, {zero}, {torsioni}, {zero}, {zero}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = self.get_f06_header(is_mag_phase)
# write the f06
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
is_odd = False
nwrite = len(eids)
if len(eids) % 2 == 1:
nwrite -= 1
is_odd = True
#print('len(eids)=%s nwrite=%s is_odd=%s' % (len(eids), nwrite, is_odd))
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
axial = self.data[itime, :, 0]
torsion = self.data[itime, :, 1]
out = []
for eid, axiali, torsioni in zip(eids, axial, torsion):
[axiali, torsioni] = write_floats_13e([axiali, torsioni])
out.append([eid, axiali, torsioni])
for i in range(0, nwrite, 2):
out_line = ' %8i %-13s %-13s %8i %-13s %s\n' % tuple(out[i] + out[i + 1])
f06_file.write(out_line)
if is_odd:
out_line = ' %8i %-13s %s\n' % tuple(out[-1])
f06_file.write(out_line)
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
is_nan = (
self.nonlinear_factor is not None and
np.isnan(self.nonlinear_factor) and
np.isnan(table.nonlinear_factor)
)
if not is_nan:
assert self.nonlinear_factor == table.nonlinear_factor
assert self.ntotal == table.ntotal
assert self.table_name == table.table_name, 'table_name=%r table.table_name=%r' % (self.table_name, table.table_name)
assert self.approach_code == table.approach_code
if not np.array_equal(self.element, table.element):
assert self.element.shape == table.element.shape, 'element shape=%s table.shape=%s' % (self.element.shape, table.element.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
msg += 'Eid\n'
for eid1, eid2 in zip(self.element, table.element):
msg += '%s, %s\n' % (eid1, eid2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(axial1, torque1) = t1
(axial2, torque2) = t2
if not np.array_equal(t1, t2):
msg += '(%s) (%s, %s) (%s, %s)\n' % (
eid,
axial1, torque1,
axial2, torque2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
class RealPlateForceArray(RealForceObject): # 33-CQUAD4, 74-CTRIA3
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.dt = dt
self.nelements = 0
assert self.element_name != 'RBAR', self.data_code
#if is_sort1:
#if dt is not None:
#self.add = self.add_sort1
#else:
#assert dt is not None
#self.add = self.add_sort2
def _get_msgs(self):
raise NotImplementedError()
[docs]
def build(self):
"""sizes the vectorized attributes of the RealPlateForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
#self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = self._get_sort_element_sizes()
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(ntotal, dtype=idtype)
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.data = zeros((ntimes, ntotal, 8), dtype=fdtype)
def _get_sort_element_sizes(self):
if self.is_sort1:
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
#print("SORT1: ntimes=%s nelements=%s ntotal=%s" % (ntimes, nelements, ntotal))
else:
#ntimes=1 nelements=21 ntotal=105
ntimes = self.nelements
nelements = self.ntimes
ntotal = self.ntotal # // ntimes
#raise RuntimeError("SORT2: ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
#print("SORT2: ntimes=%s nelements=%s ntotal=%s" % (ntimes, nelements, ntotal))
return ntimes, nelements, ntotal
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
assert 0 not in self.element
if self.nonlinear_factor not in (None, np.nan):
#Mode 1 2 3
#Freq 1.482246e-10 3.353940e-09 1.482246e-10
#Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
#Radians 9.313226e-10 2.107342e-08 9.313226e-10
#ElementID Item
#8 mx -5.467631e-14 -1.406068e-07 1.351960e-13
# my -8.983144e-14 -3.912936e-07 9.707208e-14
# mxy 2.767353e-13 -4.950616e-08 -5.985472e-13
# bmx 7.616284e-14 -2.809588e-08 -1.051987e-13
# bmy 4.245138e-14 -6.567249e-09 -6.066584e-14
# bmxy -1.233790e-14 3.561397e-09 1.840837e-14
# tx 2.601638e-13 -9.601510e-08 -3.611116e-13
# ty -5.825233e-14 -7.382687e-09 9.038553e-14
#9 mx 5.444685e-15 -1.014145e-07 -4.500100e-14
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
#Static axial SMa torsion SMt
#ElementID
#14 0.0 1.401298e-45 0.0 1.401298e-45
#15 0.0 1.401298e-45 0.0 1.401298e-45
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
self._eq_header(table)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ie, e in enumerate(self.element_node):
(eid, nid) = e
t1 = self.data[itime, ie, :]
t2 = table.data[itime, ie, :]
(fiber_dist1, oxx1, oyy1, txy1, angle1, majorP1, minorP1, ovm1) = t1
(fiber_dist2, oxx2, oyy2, txy2, angle2, majorP2, minorP2, ovm2) = t2
# vm stress can be NaN for some reason...
if not np.array_equal(t1[:-1], t2[:-1]):
msg += '(%s, %s) (%s, %s, %s, %s, %s, %s, %s, %s) (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid, nid,
fiber_dist1, oxx1, oyy1, txy1, angle1, majorP1, minorP1, ovm1,
fiber_dist2, oxx2, oyy2, txy2, angle2, majorP2, minorP2, ovm2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
#def add_new_eid_sort1(self, dt, eid, axial, SMa, torsion, SMt):
#self._times[self.itime] = dt
#self.element[self.ielement] = eid
#self.data[self.itime, self.ielement, :] = [axial, SMa, torsion, SMt]
#self.ielement += 1
def add_sort1(self, dt, eid, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.itotal] = eid
self.data[self.itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
def add_sort2(self, dt, eid, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
assert self.is_sort2, self
itime = self.itotal
self._times[itime] = dt
self.element[self.itotal] = eid
self.data[itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
#raise NotImplementedError('SORT2')
#if dt not in self.mx:
#self.add_new_transient(dt)
#self.data[self.itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
@property
def nnodes_per_element(self):
return 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
msg.append(f' element type: {self.element_name}-{self.element_type}\n')
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
headers = ['Flag', 'SubcaseID', 'iTime', 'EID', 'BLANK', 'BLANK',
'Nxx', 'Nyy', 'Nxy', 'Mxx', 'Myy', 'Mxy', 'Qx', 'Qy']
csv_file.write('# ' + ','.join(headers) + '\n')
# stress vs. strain
flag = 12
isubcase = self.isubcase
#times = self._times
ntimes = self.data.shape[0]
eids = self.element
eid_len = '%d' % len(str(eids.max()))
#zero = ' 0.000000E+00'
for itime in range(ntimes):
#dt = self._times[itime]
#header = _eigenvalue_header(self, header, itime, ntimes, dt)
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
for eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
if is_exponent_format:
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e_long(
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
# cquad4/ctria3
# 8 -7.954568E+01 2.560061E+03 -4.476376E+01 1.925648E+00 1.914048E+00 3.593237E-01 8.491534E+00 5.596094E-01 #
#f06_file.write(' %8i %18s %13s %13s %13s %13s %13s %13s %s\n' % (
#eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
#'Flag', 'SubcaseID', 'iTime', 'EID', 'BLANK', 'BLANK', 'Nxx', 'Nyy', 'Nxy', 'Mxx', 'Myy', 'Mxy', 'Qx', 'Qy'
#' ID GRID-ID FX FY FXY MX MY MXY QX QY\n'
csv_file.write(f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, 0, 0, '
f'{mxi}, {myi}, {mxyi}, {bmxi}, {bmyi}, {bmxyi}, '
f'{txi}, {tyi}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
(elem_name, nnodes, msg_temp) = self.get_f06_header(is_mag_phase)
# write the f06
ntimes = self.data.shape[0]
eids = self.element
cen_word = 'CEN/%i' % nnodes
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
if self.element_type in [74, 83, 227, 228]:
# 74, 83 CTRIA3
# 227 CTRIAR linear
# 228 CQUADR linear
for eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e(
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
# ctria3
# 8 -7.954568E+01 2.560061E+03 -4.476376E+01 1.925648E+00 1.914048E+00 3.593237E-01 8.491534E+00 5.596094E-01 #
f06_file.write(' %8i %18s %13s %13s %13s %13s %13s %13s %s\n' % (
eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
elif self.element_type == 33:
for eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e(
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
# cquad4
#0 6 CEN/4 1.072685E+01 2.504399E+03 -2.455727E+01 -5.017930E+00 -2.081427E+01 -5.902618E-01 -9.126162E+00 4.194400E+01#
#Fmt = '% 8i ' + '%27.20E ' * 8 + '\n'
#f06_file.write(Fmt % (eid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
#
f06_file.write('0 %8i %8s %13s %13s %13s %13s %13s %13s %13s %s\n' % (
eid, cen_word, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
else:
raise NotImplementedError(f'element_name={self.element_name} element_type={self.element_type}')
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if 'CTRIA3' in self.element_name:
#nnodes = 3
#elif 'CQUAD4' in self.element_name:
#nnodes = 4
#elif 'CTRIAR' in self.element_name:
#nnodes = 4 # ???
#elif 'CQUADR' in self.element_name:
#nnodes = 5 # ???
#else: # pragma: no cover
#raise NotImplementedError(self.code_information())
#print("nnodes_all =", nnodes_all)
#cen_word_ascii = 'CEN/%i' % nnodes
#cen_word = b'CEN/%i' % nnodes
eids = self.element
#cen_word = 'CEN/%i' % nnodes
#msg.append(f' element_node.shape = {self.element_node.shape}\n')
#msg.append(f' data.shape={self.data.shape}\n')
eids = self.element
eids_device = eids * 10 + self.device_code
nelements = len(eids)
assert nelements > 0, eids
#print('nelements =', nelements)
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert nnodes > 1, nnodes
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
#[fiber_dist, oxx, oyy, txy, angle, majorP, minorP, ovm]
if self.is_sort1:
structi = Struct(endian + b'i 8f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write(f'nelements={nelements:d}\n')
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
nwide = 0
for eid_device, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids_device, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
data = [eid_device, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi]
#[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e(
# [mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
op2_file.write(structi.pack(*data))
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, str(data[1:])))
nwide += len(data)
assert nwide == ntotal, f'nwide={nwide} ntotal={ntotal}'
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealPlateBilinearForceArray(RealForceObject): # 144-CQUAD4
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.dt = dt
self.nelements = 0
#if is_sort1:
#if dt is not None:
#self.add = self.add_sort1
#else:
#assert dt is not None
#self.add = self.add_sort2
def _get_msgs(self):
raise NotImplementedError()
[docs]
def build(self):
"""sizes the vectorized attributes of the RealPlateBilinearForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
#self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
dtype, idtype, fdtype = get_times_dtype(
self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = self._get_sort_element_sizes(debug=False)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element_node = zeros((ntotal, 2), dtype=idtype)
# -MEMBRANE FORCES- -BENDING MOMENTS- -TRANSVERSE SHEAR FORCES -
# FX FY FXY MX MY MXY QX QY
#[fx, fy, fxy, mx, my, mxy, qx, qy]
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.data = zeros((ntimes, ntotal, 8), dtype=fdtype)
def _get_sort_element_sizes(self, debug: bool=False):
if debug:
print("RAW: ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
if self.is_sort1:
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
if debug:
print("SORT1: ntimes=%s nelements=%s ntotal=%s" % (ntimes, nelements, ntotal))
else:
#ntimes=1 nelements=21 ntotal=105
#ntimes = self.nelements // self.ntimes
ntimes = self.ntotal
nelements = self.ntimes
ntotal = nelements * self.nnodes_per_element
#raise RuntimeError("SORT2: ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
if debug:
print("SORT2: ntimes=%s nelements=%s ntotal=%s" % (ntimes, nelements, ntotal))
return ntimes, nelements, ntotal
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
node = pd.Series(self.element_node[:, 1])
if pd.__version__ > '1.1':
node.replace({0:'CEN'}, inplace=True)
else:
node.replace({'NodeID': {0:'CEN'}}, inplace=True)
element_node = [self.element_node[:, 0], node]
if self.nonlinear_factor not in (None, np.nan):
# Mode 1 2 3
# Freq 1.482246e-10 3.353940e-09 1.482246e-10
# Eigenvalue -8.673617e-19 4.440892e-16 8.673617e-19
# Radians 9.313226e-10 2.107342e-08 9.313226e-10
# ElementID NodeID Item
# 6 0 mx 2.515537e-13 -2.294306e-07 -3.626725e-13
# my 2.916815e-13 -7.220319e-08 -5.030049e-13
# mxy -2.356622e-14 4.391171e-07 -5.960345e-14
# bmx 4.138377e-14 -1.861012e-08 -5.586283e-14
# bmy 5.991298e-15 -2.471926e-09 -5.400710e-15
# bmxy 4.511364e-15 -1.190845e-09 -5.546569e-15
# tx 1.122732e-13 -5.563460e-08 -1.523176e-13
# ty -1.164320e-14 4.813929e-09 1.023404e-14
# 4 mx 3.839208e-13 -4.580973e-07 -4.949736e-13
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_element_node(
column_values, column_names,
headers, element_node, self.data, from_tuples=False, from_array=True)
else:
df1 = pd.DataFrame(element_node).T
df1.columns = ['ElementID', 'NodeID']
df2 = pd.DataFrame(self.data[0])
df2.columns = headers
data_frame = df1.join(df2)
data_frame = data_frame.reset_index().set_index(['ElementID', 'NodeID'])
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ie, e in enumerate(self.element_node):
(eid, nid) = e
t1 = self.data[itime, ie, :]
t2 = table.data[itime, ie, :]
(mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1) = t1
(mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2) = t2
if not np.array_equal(t1, t2):
msg += '(%s, %s) (%s, %s, %s, %s, %s, %s, %s, %s) (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid, nid,
mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1,
mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, term,
inode, nid, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element_node[self.itotal] = [eid, nid]
self.data[self.itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
def add_sort2(self, dt, eid, term,
inode, nid, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
assert self.is_sort2, self
itime = self.itotal
ielement = self.itime
#nelement_node_total = self.element_node.shape[0]
#ndata_total = self.data.shape[1]
jelement = ielement * self.nnodes_per_element + inode
#print(f'RealPlateBilinearForceArray SORT2 '
#f'dt={dt} eid={eid} nid={nid} inode={inode}\n '
##f'self.itime={self.itime} self.ielement={self.ielement} self.itotal={self.itotal}\n '
#f'itime={itime}/{len(self._times)} jelement={jelement}/{nelement_node_total}'
##f'itime={itime}/{len(self._times)} '
##f'ielement={ielement}/{nelement_node_total} itotal={self.itotal}/{ndata_total}'
#)
self._times[itime] = dt
#try:
self.element_node[jelement] = [eid, nid]
self.data[itime, jelement, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
#except:
#pass
self.itotal += 1
@property
def nnodes_per_element(self):
if self.element_type == 144: # CQUAD4
nnodes_element = 5
elif self.element_type == 64: # CQUAD8
nnodes_element = 5
elif self.element_type == 82: # CQUADR
nnodes_element = 5
elif self.element_type == 75: # CTRIA6
nnodes_element = 4
elif self.element_type == 70: # CTRIAR
nnodes_element = 4
else:
raise NotImplementedError('element_type=%s element_name=%s' % (self.element_type, self.element_name))
return nnodes_element
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i ntotal=%i nnodes/element=%i\n'
% (self.__class__.__name__, ntimes, nelements, ntotal, self.nnodes_per_element))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i ntotal=%i nnodes/element=%i\n'
% (self.__class__.__name__, nelements, ntotal, self.nnodes_per_element))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, ntotal, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element_node.shape = {self.element_node.shape}\n')
msg.append(f' element type: {self.element_name}-{self.element_type}\n')
msg += self.get_data_code()
return msg
[docs]
def write_csv(self, csv_file: TextIO,
is_exponent_format: bool=False,
is_mag_phase: bool=False, is_sort1: bool=True,
write_header: bool=True):
name = str(self.__class__.__name__)
if write_header:
csv_file.write('# %s\n' % name)
headers = ['Flag', 'SubcaseID', 'iTime', 'EID', 'NID', 'BLANK',
'Nxx', 'Nyy', 'Nxy', 'Mxx', 'Myy', 'Mxy',
'Qx', 'Qy']
csv_file.write('# ' + ','.join(headers) + '\n')
# stress vs. strain
flag = 12
isubcase = self.isubcase
#times = self._times
# write the f06
ntimes = self.data.shape[0]
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
eid_len = '%d' % len(str(eids.max()))
nid_len = '%d' % len(str(nids.max()))
for itime in range(ntimes):
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
for eid, nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids, nids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
if is_exponent_format:
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e_long(
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
csv_file.write(f'{flag}, {isubcase}, {itime}, {eid:{eid_len}d}, {nid:{nid_len}d}, 0, '
f'{mxi}, {myi}, {mxyi}, {bmxi}, {bmyi}, {bmxyi}, '
f'{txi}, {tyi}\n')
return
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
(elem_name, nnodes, msg_temp) = self.get_f06_header(is_mag_phase)
# write the f06
ntimes = self.data.shape[0]
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
cen_word = 'CEN/%i' % nnodes
if self.element_type in [64, 82, 144]: # CQUAD8, CQUADR, CQUAD4
cyci = [0, 1, 2, 3, 4]
#cyc = cycle([0, 1, 2, 3, 4]) # TODO: this is totally broken...
nnodes_per_eid = 5
elif self.element_type in [70, 75]: # CTRIAR, CTRIA6
cyci = [0, 1, 2, 3]
#cyc = cycle([0, 1, 2, 3]) # TODO: this is totally broken...
nnodes_per_eid = 4
else:
raise NotImplementedError(self.element_type)
# TODO: this shouldn't be necessary
cyc = cyci * (len(eids) // nnodes_per_eid)
assert len(eids) % nnodes_per_eid == 0
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
for i, eid, nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(cyc, eids, nids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e(
[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
# ctria3
# 8 -7.954568E+01 2.560061E+03 -4.476376E+01 1.925648E+00 1.914048E+00 3.593237E-01 8.491534E+00 5.596094E-01 #
if i == 0:
f06_file.write(
'0 %8i %s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, cen_word, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
else:
f06_file.write(
' %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
# else:
# raise NotImplementedError(self.element_type)
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
(unused_elem_name, nnodes, unused_msg_temp) = self.get_f06_header(is_mag_phase)
# write the f06
#ntimes = self.data.shape[0]
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
if self.element_type in [64, 82, 144]: # CQUAD8, CQUADR, CQUAD4
cyci = [0, 1, 2, 3, 4]
#cyc = cycle([0, 1, 2, 3, 4]) # TODO: this is totally broken...
nnodes_per_eid = 5
elif self.element_type in [70, 75]: # CTRIAR, CTRIA6
cyci = [0, 1, 2, 3]
#cyc = cycle([0, 1, 2, 3]) # TODO: this is totally broken...
nnodes_per_eid = 4
else:
raise NotImplementedError(self.element_type)
# TODO: this shouldn't be necessary
cyc = cyci * (len(eids) // nnodes_per_eid)
assert len(eids) % nnodes_per_eid == 0
#print("nnodes_all =", nnodes_all)
#cen_word_ascii = 'CEN/%i' % nnodes
cen_word = b'CEN/'
#msg.append(f' element_node.shape = {self.element_node.shape}\n')
#msg.append(f' data.shape={self.data.shape}\n')
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
eids_device = eids * 10 + self.device_code
nelements = len(np.unique(eids))
#print('nelements =', nelements)
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
assert nnodes > 1, nnodes
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
#[fiber_dist, oxx, oyy, txy, angle, majorP, minorP, ovm]
if self.is_sort1:
struct1 = Struct(endian + b'i4s i 8f')
struct2 = Struct(endian + b'i 8f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write(f'nelements={nelements:d}\n')
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
mx = self.data[itime, :, 0]
my = self.data[itime, :, 1]
mxy = self.data[itime, :, 2]
bmx = self.data[itime, :, 3]
bmy = self.data[itime, :, 4]
bmxy = self.data[itime, :, 5]
tx = self.data[itime, :, 6]
ty = self.data[itime, :, 7]
nwide = 0
for i, eid, eid_device, nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(cyc, eids, eids_device, nids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
#[mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi] = write_floats_13e(
# [mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi])
if i == 0:
data = [eid_device, cen_word, nnodes, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi]
op2_file.write(struct1.pack(*data))
op2_ascii.write(
'0 %8i %s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, cen_word, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
else:
data = [nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi]
op2_file.write(struct2.pack(*data))
op2_ascii.write(
' %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi))
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, str(data)))
nwide += len(data)
assert nwide == ntotal, f'nwide={nwide} ntotal={ntotal}'
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealCBarFastForceArray(RealForceObject):
"""
34-CBAR
118-WELDP (MSC)
119-CFAST
"""
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
@property
def nnodes_per_element(self) -> int:
return 1
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCBarForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
if self.is_sort1: # or self.table_name in ['OEFRMS2']
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
self._build(ntimes, nelements, ntotal, self._times_dtype)
else:
ntimes = self.nelements
nelements = self.ntimes
ntotal = nelements * 2
name = self.analysis_method + 's'
self._build(ntimes, nelements, ntotal, self._times_dtype)
setattr(self, name, self._times)
self.data_code['name'] = self.analysis_method
self.data_names[0] = self.analysis_method
#print(f'data_names -> {self.data_names}')
def _build(self, ntimes, nelements, ntotal, dtype):
self.ntimes = ntimes
self.nelements = nelements
self.ntotal = ntotal
#print(f"*ntimes={ntimes} nelements={nelements} ntotal={ntotal} data_names={self.data_names}")
unused_dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[bending_moment_a1, bending_moment_a2, bending_moment_b1, bending_moment_b2,
# shear1, shear2, axial, torque]
self.data = np.full((ntimes, ntotal, 8), np.nan, dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def add_sort1(self, dt, eid, bending_moment_a1, bending_moment_a2,
bending_moment_b1, bending_moment_b2, shear1, shear2, axial, torque):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#[eid, bending_moment_a1, bending_moment_a2,
#bending_moment_b1, bending_moment_b2, shear1, shear2, axial, torque] = data
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [
bending_moment_a1, bending_moment_a2,
bending_moment_b1, bending_moment_b2,
shear1, shear2, axial, torque]
self.ielement += 1
def add_sort2(self, dt, eid, bending_moment_a1, bending_moment_a2,
bending_moment_b1, bending_moment_b2, shear1, shear2, axial, torque):
"""unvectorized method for adding SORT2 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#[eid, bending_moment_a1, bending_moment_a2,
#bending_moment_b1, bending_moment_b2, shear1, shear2, axial, torque] = data
itime = self.ielement
ielement = self.itime
#print(f'{self.table_name} itime={itime} ielement={ielement} time={dt} eid={eid} axial={axial}')
self._times[itime] = dt
self.element[ielement] = eid
self.data[itime, ielement, :] = [
bending_moment_a1, bending_moment_a2,
bending_moment_b1, bending_moment_b2,
shear1, shear2, axial, torque]
self.ielement += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def eid_to_element_node_index(self, eids):
ind = searchsorted(eids, self.element)
return ind
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
words = self._words()
#msg = []
#header[1] = ' %s = %10.4E\n' % (self.data_code['name'], dt)
eids = self.element
#f06_file.write(''.join(words))
ntimes = self.data.shape[0]
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + words))
bm1a = self.data[itime, :, 0]
bm2a = self.data[itime, :, 1]
bm1b = self.data[itime, :, 2]
bm2b = self.data[itime, :, 3]
ts1 = self.data[itime, :, 4]
ts2 = self.data[itime, :, 5]
af = self.data[itime, :, 6]
trq = self.data[itime, :, 7]
for eid, bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi in zip(
eids, bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq):
[bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi] = write_floats_13e([
bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi])
f06_file.write(' %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi))
f06_file.write(page_stamp % page_num)
return page_num
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(bm1a1, bm2a1, bm1b1, bm2b1, ts11, ts21, af1, trq1) = t1
(bm1a2, bm2a2, bm1b2, bm2b2, ts12, ts22, af2, trq2) = t2
if not np.array_equal(t1, t2):
msg += '(%s) (%s, %s, %s, %s, %s, %s, %s, %s) (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
bm1a1, bm2a1, bm1b1, bm2b1, ts11, ts21, af1, trq1,
bm1a2, bm2a2, bm1b2, bm2b2, ts12, ts22, af2, trq2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
eids = self.element
eids_device = eids * 10 + self.device_code
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
op2_ascii.write(f' ntimes = {self.ntimes}\n')
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'i 8f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write('%s-nelements=%i\n' % (self.element_name, nelements))
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
bm1a = self.data[itime, :, 0]
bm2a = self.data[itime, :, 1]
bm1b = self.data[itime, :, 2]
bm2b = self.data[itime, :, 3]
ts1 = self.data[itime, :, 4]
ts2 = self.data[itime, :, 5]
af = self.data[itime, :, 6]
trq = self.data[itime, :, 7]
for eid_device, bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi in zip(
eids_device, bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq):
data = [eid_device, bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi]
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, str(data)))
op2_file.write(struct1.pack(*data))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
@abstractmethod
def _words(self) -> list[str]:
return []
[docs]
class RealCBarForceArray(RealCBarFastForceArray): # 34-CBAR
"""34-CBAR"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealCBarFastForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
@classmethod
def add_static_case(cls, table_name, element_name, element, data, isubcase,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 9
obj = set_static_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data))
return obj
[docs]
@classmethod
def add_modal_case(cls, table_name, element_name, element, data, isubcase,
modes, eigns, cycles,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 9
obj = set_modal_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigns, cycles)
return obj
[docs]
@classmethod
def add_transient_case(cls, table_name, element_name, element, data, isubcase,
times,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 9
obj = set_transient_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
times)
return obj
[docs]
@classmethod
def add_post_buckling_case(cls, table_name, element_name, element, data, isubcase,
modes, eigrs, eigis,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
data_code = cls._set_case(table_name, element_name,
isubcase, is_sort1,
is_random, is_msc, random_code,
title, subtitle, label)
data_code['num_wide'] = 9
obj = set_post_buckling_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data),
modes, eigrs, eigis)
return obj
def _words(self) -> list[str]:
words = [' F O R C E S I N B A R E L E M E N T S ( C B A R )\n',
'0 ELEMENT BEND-MOMENT END-A BEND-MOMENT END-B - SHEAR - AXIAL\n',
' ID. PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n']
return words
[docs]
class RealCWeldForceArray(RealCBarFastForceArray): # 34-CBAR
"""117-CWELD"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealCBarFastForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class RealCWeldForceArrayMSC(RealCBarFastForceArray): # 118-WELDP
"""118-WELDP"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealCBarFastForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
def _words(self) -> list[str]:
words = [' F O R C E S I N W E L D E L E M E N T S ( C W E L D P )\n',
' \n',
' ELEMENT BEND-MOMENT END-A BEND-MOMENT END-B - SHEAR - AXIAL\n',
' ID PLANE 1 (MZ) PLANE 2 (MY) PLANE 1 (MZ) PLANE 2 (MY) PLANE 1 (FY) PLANE 2 (FZ) FORCE FX TORQUE MX\n',
#' 179 -2.607303E-02 -5.365749E-02 2.622905E-02 5.209560E-02 -5.230208E-02 -1.057531E-01 -2.476445E-02 -1.661023E-03\n',
]
#words = [' F O R C E S I N B A R E L E M E N T S ( C B A R )\n',
#'0 ELEMENT BEND-MOMENT END-A BEND-MOMENT END-B - SHEAR - AXIAL\n',
#' ID. PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n']
return words
[docs]
class RealCFastForceArrayNX(RealCBarFastForceArray): # 34-CBAR
"""119-CFAST"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealCBarFastForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class RealConeAxForceArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
if not is_sort1:
raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the RealConeAxForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
#[hopa, bmu, bmv, tm, su, sv]
self.data = zeros((self.ntimes, self.ntotal, 6), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = pd.Panel(self.data, items=column_values,
major_axis=self.element, minor_axis=headers).to_frame()
self.data_frame.columns.names = column_names
self.data_frame.index.names = ['ElementID', 'Item']
else:
df1 = pd.DataFrame(self.element)
df1.columns = ['ElementID']
df2 = pd.DataFrame(self.data[0])
df2.columns = headers
self.data_frame = df1.join([df2])
#print(self.data_frame)
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ie, e in enumerate(self.element):
eid = e
t1 = self.data[itime, ie, :]
t2 = table.data[itime, ie, :]
(hopa1, bmu1, bmv1, tm1, su1, sv1) = t1
(hopa2, bmu2, bmv2, tm2, su2, sv2) = t2
if not np.array_equal(t1, t2):
msg += (
'%s (%s, %s, %s, %s, %s, %s)\n'
' (%s, %s, %s, %s, %s, %s)\n' % (
eid,
hopa1, bmu1, bmv1, tm1, su1, sv1,
hopa2, bmu2, bmv2, tm2, su2, sv2,
))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, hopa, bmu, bmv, tm, su, sv):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [hopa, bmu, bmv, tm, su, sv]
self.ielement += 1
#def add_sort2(self, dt, eid, hopa, bmu, bmv, tm, su, sv):
#"""unvectorized method for adding SORT2 transient data"""
#assert self.is_sort2, self
#assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#self._times[itime] = dt
#self.element[self.ielement] = eid
#self.data[itime, self.ielement, :] = [hopa, bmu, bmv, tm, su, sv]
#self.ielement += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = [
' F O R C E S I N A X I S - S Y M M E T R I C C O N I C A L S H E L L E L E M E N T S (CCONEAX)\n'
' \n'
' ELEMENT HARMONIC POINT BEND-MOMENT BEND-MOMENT TWIST-MOMENT SHEAR SHEAR\n'
' ID. NUMBER ANGLE V U V U\n'
#' 101 0 5.864739E-09 1.759422E-09 0.0 0.0 0.0'
#' 101 0.0000 5.864739E-09 1.759422E-09 0.0 0.0 0.0'
]
#(elem_name, msg_temp) = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
hopa = self.data[itime, :, 0]
bmu = self.data[itime, :, 1]
bmv = self.data[itime, :, 2]
tm = self.data[itime, :, 3]
su = self.data[itime, :, 4]
sv = self.data[itime, :, 5]
for (eid, hopai, bmui, bmvi, tmi, sui, svi) in zip(
eids, hopa, bmu, bmv, tm, su, sv):
if hopai > 0.1:
raise NotImplementedError(hopai)
vals2 = write_floats_13e([hopai, bmui, bmvi, tmi, sui, svi])
[hopai, bmui, bmvi, tmi, sui, svi] = vals2
# TODO: hopa is probably the wrong type
# hopa # Mu Mv twist Vy Vu
f06_file.write(' %8i %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, 0.0, hopai, bmui, bmvi, tmi, sui, svi))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
class RealCBar100ForceArray(RealForceObject): # 100-CBAR
"""
CBAR-34s are converted to CBAR-100s when you have PLOAD1s
(distributed bar loads). The number of stations by default is 2,
but with a CBARAO, you can change this (max of 8 points; 6 internal
points).
If you use a CBARO without PLOAD1s, you wil turn CBAR-34s into
CBAR-100s as well.
"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
if not is_sort1:
raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCBar100ForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
# [station, bending_moment1, bending_moment2, shear1, shear2, axial, torque]
self.data = zeros((self.ntimes, self.ntotal, 7), dtype=fdtype)
#def finalize(self):
#sd = self.data[0, :, 0]
#i_sd_zero = np.where(sd != 0.0)[0]
#i_node_zero = np.where(self.element_node[:, 1] != 0)[0]
#assert i_node_zero.max() > 0, 'CBAR element_node has not been filled'
#i = np.union1d(i_sd_zero, i_node_zero)
#self.element = self.element[i]
#self.element_node = self.element_node[i, :]
#self.data = self.data[:, i, :]
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
element_location = [
self.element,
self.data[0, :, 0],
]
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = pd.Panel(self.data[:, :, 1:], items=column_values,
major_axis=element_location, minor_axis=headers[1:]).to_frame()
self.data_frame.columns.names = column_names
self.data_frame.index.names = ['ElementID', 'Location', 'Item']
else:
df1 = pd.DataFrame(element_location).T
df1.columns = ['ElementID', 'Location']
df2 = pd.DataFrame(self.data[0])
df2.columns = headers
self.data_frame = df1.join([df2])
#self.data_frame = self.data_frame.reset_index().replace({'NodeID': {0:'CEN'}}).set_index(['ElementID', 'NodeID'])
#print(self.data_frame)
def add_sort1(self, dt, eid, sd, bm1, bm2, ts1, ts2, af, trq):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
# station, bending_moment1, bending_moment2, shear1, shear2, axial, torque
self.data[self.itime, self.ielement, :] = [sd, bm1, bm2, ts1, ts2, af, trq]
self.ielement += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
msg = [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
return msg
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i; table_name=%r\n'
% (self.__class__.__name__, ntimes, nelements, self.table_name))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i; table_name=%r\n'
% (self.__class__.__name__, nelements, self.table_name))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (
ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def eid_to_element_node_index(self, eids):
ind = searchsorted(eids, self.element)
return ind
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
#' F O R C E D I S T R I B U T I O N I N B A R E L E M E N T S ( C B A R )'
#'0 ELEMENT STATION BEND-MOMENT SHEAR FORCE AXIAL'
#' ID. (PCT) PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE'
#' 10 0.000 0.0 -5.982597E+06 0.0 -7.851454E+03 0.0 0.0'
#' 10 1.000 0.0 1.868857E+06 0.0 -7.851454E+03 0.0 0.0'
#' 11 0.000 0.0 1.868857E+06 0.0 -7.851454E+03 0.0 0.0'
#' 11 0.050 0.0 2.261429E+06 0.0 -7.851454E+03 0.0 0.0'
#' 11 0.100 0.0 2.654002E+06 0.0 -7.851454E+03 0.0 0.0'
words = [
' F O R C E D I S T R I B U T I O N I N B A R E L E M E N T S ( C B A R )\n'
'0 ELEMENT STATION BEND-MOMENT SHEAR FORCE AXIAL\n'
' ID. (PCT) PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n']
# ' 15893 0.000 1.998833E+02 9.004551E+01 2.316835E+00 1.461960E+00 -2.662207E+03 9.795244E-02'
#msg = []
#header[1] = ' %s = %10.4E\n' % (self.data_code['name'], dt)
eids = self.element
#f.write(''.join(words))
ntimes = self.data.shape[0]
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + words))
# sd, bm1, bm2, ts1, ts2, af, trq
sd = self.data[itime, :, 0]
bm1 = self.data[itime, :, 1]
bm2 = self.data[itime, :, 2]
ts1 = self.data[itime, :, 3]
ts2 = self.data[itime, :, 4]
af = self.data[itime, :, 5]
trq = self.data[itime, :, 6]
for eid, sdi, bm1i, bm2i, ts1i, ts2i, afi, trqi in zip(eids, sd, bm1, bm2, ts1, ts2, af, trq):
[bm1i, bm2i, ts1i, ts2i, afi, trqi] = write_floats_13e([
bm1i, bm2i, ts1i, ts2i, afi, trqi])
f06_file.write(
' %8i %4.3f %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, sdi, bm1i, bm2i, ts1i, ts2i, afi, trqi))
f06_file.write(page_stamp % page_num)
return page_num
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
eids = self.element
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'i2f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write('%s-nelements=%i\n' % (self.element_name, nelements))
eids = self.element
#f.write(''.join(words))
#ntimes = self.data.shape[0]
struct1 = Struct(endian + b'i7f')
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
# sd, bm1, bm2, ts1, ts2, af, trq
sd = self.data[itime, :, 0]
bm1 = self.data[itime, :, 1]
bm2 = self.data[itime, :, 2]
ts1 = self.data[itime, :, 3]
ts2 = self.data[itime, :, 4]
af = self.data[itime, :, 5]
trq = self.data[itime, :, 6]
for eid, eid_device, sdi, bm1i, bm2i, ts1i, ts2i, afi, trqi in zip(
eids, eids_device, sd, bm1, bm2, ts1, ts2, af, trq):
[sbm1i, sbm2i, sts1i, sts2i, safi, strqi] = write_floats_13e([
bm1i, bm2i, ts1i, ts2i, afi, trqi])
op2_ascii.write(
' %8i %4.3f %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, sdi, sbm1i, sbm2i, sts1i, sts2i, safi, strqi))
data = [eid_device, sdi, bm1i, bm2i, ts1i, ts2i, afi, trqi]
op2_file.write(struct1.pack(*data))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(sd1, bm11, bm21, ts11, ts21, af1, trq1) = t1
(sd2, bm12, bm22, ts12, ts22, af2, trq2) = t2
if not np.array_equal(t1, t2):
msg += '(%s) (%s, %s, %s, %s, %s, %s, %s) (%s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
sd1, bm11, bm21, ts11, ts21, af1, trq1,
sd2, bm12, bm22, ts12, ts22, af2, trq2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
class RealCGapForceArray(RealForceObject): # 38-CGAP
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
if not is_sort1:
raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCGapForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
# [fx, sfy, sfz, u, v, w, sv, sw]
self.data = zeros((self.ntimes, self.ntotal, 8), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
# LoadStep 1.0
# ElementID Item
# 101 fx 33333.332031
# sfy 0.000000
# sfz 0.000000
# u 0.000115
# v 0.000000
# w 0.000000
# sv 0.000000
# sw 0.000000
# 102 fx -0.000002
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
else:
# Static fx sfy sfz u v w sv sw
# ElementID
# 1 1.253610e-10 -0.0 0.0 0.250722 -0.852163 0.0 0.0 0.0
# 21 1.253610e-10 -0.0 0.0 0.250722 -0.852163 0.0 0.0 0.0
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ie, e in enumerate(self.element):
eid = e
t1 = self.data[itime, ie, :]
t2 = table.data[itime, ie, :]
(fx1, sfy1, sfz1, u1, v1, w1, sv1, sw1) = t1
(fx2, sfy2, sfz2, u2, v2, w2, sv2, sw2) = t2
if not np.array_equal(t1, t2):
msg += (
'%s (%s, %s, %s, %s, %s, %s, %s, %s)\n'
' (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
fx1, sfy1, sfz1, u1, v1, w1, sv1, sw1,
fx2, sfy2, sfz2, u2, v2, w2, sv2, sw2,
))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, fx, sfy, sfz, u, v, w, sv, sw):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [fx, sfy, sfz, u, v, w, sv, sw]
self.ielement += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = [
' F O R C E S I N G A P E L E M E N T S ( C G A P )\n'
' ELEMENT - F O R C E S I N E L E M S Y S T E M - - D I S P L A C E M E N T S I N E L E M S Y S T E M -\n'
' ID COMP-X SHEAR-Y SHEAR-Z AXIAL-U TOTAL-V TOTAL-W SLIP-V SLIP-W\n'
#' 101 3.333333E+04 0.0 0.0 1.149425E-04 0.0 0.0 0.0 0.0\n'
]
##(elem_name, msg_temp) = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
#ntimes, ntotal = self.data.shape[:1]
ntimes = self.data.shape[0]
eids = self.element
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
# [fx, sfy, sfz, u, v, w, sv, sw]
fx = self.data[itime, :, 0]
sfy = self.data[itime, :, 1]
sfz = self.data[itime, :, 2]
u = self.data[itime, :, 3]
v = self.data[itime, :, 4]
w = self.data[itime, :, 5]
sv = self.data[itime, :, 6]
sw = self.data[itime, :, 7]
for (eid, fxi, sfyi, sfzi, ui, vi, wi, svi, swi) in zip(eids, fx, sfy, sfz, u, v, w, sv, sw):
vals2 = write_floats_12e([fxi, sfyi, sfzi, ui, vi, wi, svi, swi])
[fxi, sfyi, sfzi, ui, vi, wi, svi, swi] = vals2
f06_file.write('0%13i%-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, fxi, sfyi, sfzi, ui, vi, wi, svi, swi))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
class RealBendForceArray(RealForceObject): # 69-CBEND
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceObject.__init__(self, data_code, isubcase)
self.nelements = 0 # result specific
[docs]
def build(self):
"""sizes the vectorized attributes of the RealBendForceArray"""
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
if self.is_sort1:
self.nelements //= self.ntimes
else:
#2 6 3
#print('SORT2 RealBendForceArray******', self.ntimes, self.nelements, self.ntotal)
#self.ntotal //= self.nelements # ntotal: 0
#self.ntotal //= self.ntimes # ntotal: 1
self.nelements //= self.ntimes # passes, but ntotal is small
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self, debug=False)
self.ntimes = ntimes
self.nelements = nelements
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element_node = zeros((nelements, 3), dtype=idtype)
#[bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a
# bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b]
self.data = zeros((ntimes, ntotal, 12), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
# TODO: add NodeA, NodeB
element = self.element_node[:, 0]
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, element, self.data)
#data_frame = pd.Panel(self.data, items=column_values,
#major_axis=element, minor_axis=headers).to_frame()
#data_frame.columns.names = column_names
#data_frame.index.names = ['ElementID', 'Item']
else:
df1 = pd.DataFrame(self.element_node)
df1.columns = ['ElementID', 'NodeA', 'NodeB']
df2 = pd.DataFrame(self.data[0])
df2.columns = headers
data_frame = df1.join(df2)
self.data_frame = data_frame
def add_sort1(self, dt, eid,
nid_a, bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
nid_b, bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element_node[self.ielement] = [eid, nid_a, nid_b]
self.data[self.itime, self.ielement, :] = [
bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b,
]
self.ielement += 1
if self.ielement == self.nelements:
self.ielement = 0
def add_sort2(self, dt, eid,
nid_a, bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
nid_b, bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b):
"""unvectorized method for adding SORT1 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
itime = self.itotal
jelement = self.itime
ielement = self.itotal // self.ntotal
#print(f'RealBendForceArray SORT2 itime={itime}/{len(self._times)} '
#f'ielement={ielement}/{len(self.element_node)} jelement={jelement}, '
#f'itotal={self.itotal}/{self.data.shape[1]}'
#f' -> dt={dt:g} eid={eid}')
self._times[itime] = dt
self.element_node[jelement, :] = [eid, nid_a, nid_b]
#print('RealBendForceArray', '%g' % dt, eid, nid_a, nid_b)
#self.data[0, ielement, :] = [
#bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
#bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b,
#]
#self.data[itime, 0, :] = [
#bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
#bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b,
#]
warnings.warn('RealBendForceArray add_sort2 skipped')
self.data[itime, ielement, :] = [
bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b,
]
#if self.itotal == self.ntotal:
#self.itotal = 0
#self.ielement += 1
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element_node.shape = {self.element_node.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = [
' F O R C E S I N B E N D E L E M E N T S ( C B E N D )\n'
' - BENDING MOMENTS - - SHEARS - AXIAL\n'
' ELEMENT-ID GRID END PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n'
#'0 6901 6901 A 0.0 0.0 0.0 0.0 0.0 -6.305720E-16'
#' 6902 B -5.000000E-01 5.000000E-01 1.000000E+00 -1.000000E+00 -5.000000E-07 -1.666537E-07'
]
# write the f06
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element_node[:, 0]
nid_a = self.element_node[:, 1]
nid_b = self.element_node[:, 2]
#print('len(eids)=%s nwrite=%s is_odd=%s' % (len(eids), nwrite, is_odd))
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
bending_moment_1a = self.data[itime, :, 0]
bending_moment_2a = self.data[itime, :, 1]
shear_1a = self.data[itime, :, 2]
shear_2a = self.data[itime, :, 3]
axial_a = self.data[itime, :, 4]
torque_a = self.data[itime, :, 5]
bending_moment_1b = self.data[itime, :, 6]
bending_moment_2b = self.data[itime, :, 7]
shear_1b = self.data[itime, :, 8]
shear_2b = self.data[itime, :, 9]
axial_b = self.data[itime, :, 10]
torque_b = self.data[itime, :, 11]
for (eid,
nid_ai, bending_moment_1ai, bending_moment_2ai, shear_1ai, shear_2ai, axial_ai, torque_ai,
nid_bi, bending_moment_1bi, bending_moment_2bi, shear_1bi, shear_2bi, axial_bi, torque_bi) in zip(
eids,
nid_a, bending_moment_1a, bending_moment_2a, shear_1a, shear_2a, axial_a, torque_a,
nid_b, bending_moment_1b, bending_moment_2b, shear_1b, shear_2b, axial_b, torque_b):
[bending_moment_1ai, bending_moment_2ai, shear_1ai, shear_2ai, axial_ai, torque_ai,
bending_moment_1bi, bending_moment_2bi, shear_1bi, shear_2bi, axial_bi, torque_bi] = write_floats_13e(
[bending_moment_1ai, bending_moment_2ai, shear_1ai, shear_2ai, axial_ai, torque_ai,
bending_moment_1bi, bending_moment_2bi, shear_1bi, shear_2bi, axial_bi, torque_bi])
f06_file.write(
'0 %8i%8i A %13s %13s %13s %13s %13s %13s\n'
' %8i B %13s %13s %13s %13s %13s %13s\n' % (
eid, nid_ai, bending_moment_1ai, bending_moment_2ai, shear_1ai, shear_2ai, axial_ai, torque_ai,
nid_bi, bending_moment_1bi, bending_moment_2bi, shear_1bi, shear_2bi, axial_bi, torque_bi
))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.element_node, table.element_node):
assert self.element_node.shape == table.element_node.shape, 'element_node shape=%s table.shape=%s' % (self.element_node.shape, table.element_node.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
msg += 'Eid, Nid_A, Nid_B\n'
for (eid1, nida1, nidb1), (eid2, nida2, nidb2) in zip(self.element_node, table.element_node):
msg += '(%s, %s, %s), (%s, %s, %s)\n' % (eid1, nida1, nidb1, eid2, nida2, nidb2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
eids = self.element_node[:, 0]
for itime in range(self.ntimes):
for ielem, eid in enumerate(eids):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(bending_moment_1a1, bending_moment_2a1, shear_1a1, shear_2a1, axial_a1, torque_a1,
bending_moment_1b1, bending_moment_2b1, shear_1b1, shear_2b1, axial_b1, torque_b1) = t1
(bending_moment_1a2, bending_moment_2a2, shear_1a2, shear_2a2, axial_a2, torque_a2,
bending_moment_1b2, bending_moment_2b2, shear_1b2, shear_2b2, axial_b2, torque_b2) = t2
if not np.array_equal(t1, t2):
msg += '(%s) (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
bending_moment_1a1, bending_moment_2a1, shear_1a1, shear_2a1, axial_a1, torque_a1,
bending_moment_1b1, bending_moment_2b1, shear_1b1, shear_2b1, axial_b1, torque_b1,
bending_moment_1a2, bending_moment_2a2, shear_1a2, shear_2a2, axial_a2, torque_a2,
bending_moment_1b2, bending_moment_2b2, shear_1b2, shear_2b2, axial_b2, torque_b2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
class RealSolidPressureForceArray(RealForceObject): # 77-PENTA_PR,78-TETRA_PR
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
#if not is_sort1:
#raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the RealSolidPressureForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
if self.is_sort1:
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
if self.is_sort1:
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
else:
#print("RealSolidPressureForceArray: ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
ntimes = self.ntotal
ntotal = self.ntimes
nelements = ntotal
#print("-> ntimes=%s nelements=%s ntotal=%s" % (ntimes, nelements, ntotal))
assert nelements == 1
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[ax, ay, az, vx, vy, vz, pressure]
self.data = zeros((ntimes, ntotal, 7), dtype=fdtype)
def __eq__(self, table): # pragma: no cover
self._eq_header(table)
assert self.is_sort1 == table.is_sort1
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(ax1, ay1, az1, vx1, vy1, vz1, pressure1) = t1
(ax2, ay2, az2, vx2, vy2, vz2, pressure2) = t2
if not np.array_equal(t1, t2):
msg += (
'%s (%s, %s, %s, %s, %s, %s, %s)\n'
' (%s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
ax1, ay1, az1, vx1, vy1, vz1, pressure1,
ax2, ay2, az2, vx2, vy2, vz2, pressure2,
))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, etype, ax, ay, az, vx, vy, vz, pressure):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [ax, ay, az, vx, vy, vz, pressure]
self.ielement += 1
def add_sort2(self, dt, eid, etype, ax, ay, az, vx, vy, vz, pressure):
"""unvectorized method for adding SORT2 transient data"""
assert self.sort_method == 2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
itime = self.itotal
itotal = self.itime
ntimes = len(self._times)
ntotal = self.data.shape[1]
print(f'RealSolidPressureForceArray: itime={itime}/{ntimes} itotal={itotal}/{ntotal} -> dt={dt:g} eid={eid}')
self._times[itime] = dt
self.element[itotal] = eid
self.data[itime, itotal, :] = [ax, ay, az, vx, vy, vz, pressure]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nelements, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
#(elem_name, msg_temp) = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
#(ntimes, ntotal, two) = self.data.shape
if self.is_sort1:
page_num = self._write_sort1_as_sort1(header, page_stamp, page_num, f06_file)
else:
raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
return page_num
def _write_sort2_as_sort1(self, header, page_stamp, page_num=1, f=None):
msg_temp = [' P E A K A C C E L E R A T I O N S A N D P R E S S U R E S\n',
' \n',
' TIME EL-TYPE X-ACCELERATION Y-ACCELERATION Z-ACCELERATION PRESSURE (DB)\n']
ntimes = self.data.shape[0]
eids = self.element
etype = self.element_name
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f.write(''.join(header + msg_temp))
vx = self.data[itime, :, 0]
vy = self.data[itime, :, 1]
vz = self.data[itime, :, 2]
ax = self.data[itime, :, 3]
ay = self.data[itime, :, 4]
az = self.data[itime, :, 5]
pressure = self.data[itime, :, 5]
for (eid, vxi, vyi, vzi, axi, ayi, azi, pressurei) in zip(
eids, vx, vy, vz, ax, ay, az, pressure):
vals2 = write_floats_13e([axi, ayi, azi, pressurei])
[sax, say, saz, spressure] = vals2
#etype = 'PENPR'
f.write('0%13s %5s %-13s %-13s %-13s %s\n' % (eid, etype, sax, say, saz, spressure))
f.write(page_stamp % page_num)
page_num += 1
return page_num - 1
def _write_sort1_as_sort1(self, header, page_stamp, page_num=1, f=None):
msg_temp = [' P E A K A C C E L E R A T I O N S A N D P R E S S U R E S\n',
' \n',
' ELEMENT-ID EL-TYPE X-ACCELERATION Y-ACCELERATION Z-ACCELERATION PRESSURE (DB)\n'] # TODO: bad line...
ntimes = self.data.shape[0]
eids = self.element
etype = self.element_name
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f.write(''.join(header + msg_temp))
vx = self.data[itime, :, 0]
vy = self.data[itime, :, 1]
vz = self.data[itime, :, 2]
ax = self.data[itime, :, 3]
ay = self.data[itime, :, 4]
az = self.data[itime, :, 5]
pressure = self.data[itime, :, 5]
for (eid, vxi, vyi, vzi, axi, ayi, azi, pressurei) in zip(
eids, vx, vy, vz, ax, ay, az, pressure):
vals2 = write_floats_13e([axi, ayi, azi, pressurei])
[sax, say, saz, spressure] = vals2
#etype = 'PENPR'
f.write('0%13s %5s %-13s %-13s %-13s %s\n' % (eid, etype, sax, say, saz, spressure))
f.write(page_stamp % page_num)
page_num += 1
return page_num - 1
# VUBEAM
# F:\work\pyNastran\examples\Dropbox\move_tpl\beamp11.op2
[docs]
class RealForceMomentArray(RealForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
RealForceObject.__init__(self, data_code, isubcase)
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.nelements = 0 # result specific
#if not is_sort1:
#raise NotImplementedError('SORT2; code_info=\n%s' % self.code_information())
@property
def nnodes_per_element(self) -> int:
return 1
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs]
def build(self):
"""sizes the vectorized attributes of the RealCBushForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s' % (self.ntimes, self.nelements, self.ntotal))
if self.is_built:
return
assert self.ntimes > 0, 'ntimes=%s' % self.ntimes
assert self.nelements > 0, 'nelements=%s' % self.nelements
assert self.ntotal > 0, 'ntotal=%s' % self.ntotal
#self.names = []
self.nelements //= self.ntimes
self.itime = 0
self.ielement = 0
self.itotal = 0
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
ntimes, nelements, ntotal = get_sort_element_sizes(self)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[fx, fy, fz, mx, my, mz]
self.data = zeros((ntimes, nelements, 6), dtype=fdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
if self.nonlinear_factor not in (None, np.nan):
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
#data_frame = pd.Panel(self.data, items=column_values,
#major_axis=self.element, minor_axis=headers).to_frame()
#data_frame.columns.names = column_names
#data_frame.index.names = ['ElementID', 'Item']
else:
# >=25.0
#Static fx fy fz mx my mz
#ElementID
#1 1000.0 0.0 0.0 0.0 0.0 0.0
#
# <=24.2
#Static 0
#ElementID Item
#1 fx 1000.0
# fy 0.0
# fz 0.0
# mx 0.0
# my 0.0
# mz 0.0
data_frame = pd.DataFrame(self.data[0], columns=headers, index=self.element)
data_frame.index.name = 'ElementID'
data_frame.columns.names = ['Static']
#data_frame = pd.Panel(self.data,
#major_axis=self.element, minor_axis=headers).to_frame()
#data_frame.columns.names = ['Static']
#data_frame.index.names = ['ElementID', 'Item']
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
assert self.is_sort1 == table.is_sort1
is_nan = (
self.nonlinear_factor is not None and
np.isnan(self.nonlinear_factor) and
np.isnan(table.nonlinear_factor)
)
if not is_nan:
assert self.nonlinear_factor == table.nonlinear_factor
assert self.ntotal == table.ntotal
assert self.table_name == table.table_name, 'table_name=%r table.table_name=%r' % (self.table_name, table.table_name)
assert self.approach_code == table.approach_code
if self.nonlinear_factor not in (None, np.nan):
assert np.array_equal(self._times, table._times), 'ename=%s-%s times=%s table.times=%s' % (
self.element_name, self.element_type, self._times, table._times)
if not np.array_equal(self.element, table.element):
assert self.element.shape == table.element.shape, 'shape=%s element.shape=%s' % (self.element.shape, table.element.shape)
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
for eid, eid2 in zip(self.element, table.element):
msg += '%s, %s\n' % (eid, eid2)
print(msg)
raise ValueError(msg)
if not np.array_equal(self.data, table.data):
msg = 'table_name=%r class_name=%s\n' % (self.table_name, self.__class__.__name__)
msg += '%s\n' % str(self.code_information())
ntimes = self.data.shape[0]
i = 0
if self.is_sort1:
for itime in range(ntimes):
for ieid, eid, in enumerate(self.element):
t1 = self.data[itime, ieid, :]
t2 = table.data[itime, ieid, :]
(fx1, fy1, fz1, mx1, my1, mz1) = t1
(fx2, fy2, fz2, mx2, my2, mz2) = t2
if not allclose(t1, t2):
#if not np.array_equal(t1, t2):
msg += '%s\n (%s, %s, %s, %s, %s, %s)\n (%s, %s, %s, %s, %s, %s)\n' % (
eid,
fx1, fy1, fz1, mx1, my1, mz1,
fx2, fy2, fz2, mx2, my2, mz2)
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
else:
raise NotImplementedError(self.is_sort2)
if i > 0:
print(msg)
raise ValueError(msg)
return True
def add_sort1(self, dt, eid, fx, fy, fz, mx, my, mz):
"""unvectorized method for adding SORT1 transient data"""
assert self.sort_method == 1, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
#print('dt=%s eid=%s' % (dt, eid))
#asdf
assert self.sort_method == 1, self
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, :] = [fx, fy, fz, mx, my, mz]
self.ielement += 1
def add_sort2(self, dt, eid, fx, fy, fz, mx, my, mz):
"""unvectorized method for adding SORT2 transient data"""
assert self.is_sort2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
itotal = self.itime
itime = self.itotal
#print(f'itime={self.itime} itotal={self.itotal} dt={dt}')
self._times[itime] = dt
self.element[self.ielement] = eid
self.data[itime, self.ielement, :] = [fx, fy, fz, mx, my, mz]
self.itotal += 1
[docs]
def get_stats(self, short: bool=False) -> list[str]:
if not self.is_built:
return [
f'<{self.__class__.__name__}>; table_name={self.table_name!r}\n',
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i\n'
% (self.__class__.__name__, ntimes, nelements))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i\n'
% (self.__class__.__name__, nelements))
ntimes_word = '1'
headers = self.get_headers()
n = len(headers)
msg.append(' data: [%s, nnodes, %i] where %i=[%s]\n' % (ntimes_word, n, n, str(', '.join(headers))))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(f' element.shape = {self.element.shape}\n')
#msg.append(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
[docs]
def get_element_index(self, eids):
# elements are always sorted; nodes are not
itot = searchsorted(eids, self.element) #[0]
return itot
[docs]
def eid_to_element_node_index(self, eids):
#ind = ravel([searchsorted(self.element == eid) for eid in eids])
ind = searchsorted(eids, self.element)
#ind = ind.reshape(ind.size)
#ind.sort()
return ind
[docs]
def write_f06(self, f06_file, header=None, page_stamp='PAGE %s',
page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
msg_temp = self.get_f06_header()
# write the f06
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
for itime in range(ntimes):
dt = self._times[itime] # TODO: rename this...
header = _eigenvalue_header(self, header, itime, ntimes, dt)
f06_file.write(''.join(header + msg_temp))
#print("self.data.shape=%s itime=%s ieids=%s" % (str(self.data.shape), itime, str(ieids)))
fx = self.data[itime, :, 0]
fy = self.data[itime, :, 1]
fz = self.data[itime, :, 2]
mx = self.data[itime, :, 3]
my = self.data[itime, :, 4]
mz = self.data[itime, :, 5]
for eid, fxi, fyi, fzi, mxi, myi, mzi in zip(eids, fx, fy, fz, mx, my, mz):
[fxi, fyi, fzi, mxi, myi, mzi] = write_floats_13e([fxi, fyi, fzi, mxi, myi, mzi])
f06_file.write(' %8i %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, fxi, fyi, fzi, mxi, myi, mzi))
#'0 599 0.0 2.000000E+00 3.421458E-14 1.367133E-13 -3.752247E-15 1.000000E+00\n']
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
def write_op2(self, op2_file, op2_ascii, itable, new_result,
date, is_mag_phase=False, endian='>'):
"""writes an OP2"""
frame = inspect.currentframe()
call_frame = inspect.getouterframes(frame, 2)
op2_ascii.write(f'{self.__class__.__name__}.write_op2: {call_frame[1][3]}\n')
if itable == -1:
self._write_table_header(op2_file, op2_ascii, date)
itable = -3
#if isinstance(self.nonlinear_factor, float):
#op2_format = '%sif' % (7 * self.ntimes)
#raise NotImplementedError()
#else:
#op2_format = 'i21f'
#s = Struct(op2_format)
#eids = self.element
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = self.data.shape[1]
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'i6f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write('%s-nelements=%i\n' % (self.element_name, nelements))
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
fx = self.data[itime, :, 0]
fy = self.data[itime, :, 1]
fz = self.data[itime, :, 2]
mx = self.data[itime, :, 3]
my = self.data[itime, :, 4]
mz = self.data[itime, :, 5]
for eid, fxi, fyi, fzi, mxi, myi, mzi in zip(eids_device, fx, fy, fz, mx, my, mz):
data = [eid, fxi, fyi, fzi, mxi, myi, mzi]
op2_ascii.write(' eid=%s data=%s\n' % (eid, str(data[1:])))
op2_file.write(struct1.pack(*data))
itable -= 1
header = [4 * ntotal,]
op2_file.write(pack('i', *header))
op2_ascii.write('footer = %s\n' % header)
new_result = False
return itable
[docs]
class RealCBushForceArray(RealForceMomentArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class RealCBearForceArray(RealForceMomentArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class RealCFastForceArrayMSC(RealForceMomentArray):
"""126-CFAST-MSC"""
def __init__(self, data_code, is_sort1, isubcase, dt):
RealForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
def oef_data_code(table_name,
is_sort1=True, is_random=False,
random_code=0, title='', subtitle='', label='', is_msc=True):
sort1_sort_bit = 0 if is_sort1 else 1
random_sort_bit = 1 if is_random else 0
sort_method = 1 if is_sort1 else 2
#if format_code == 1:
#format_word = "Real"
#elif format_code == 2:
#format_word = "Real/Imaginary"
#elif format_code == 3:
#format_word = "Magnitude/Phase"
#DEVICE_CODE_MAP = {
#1 : "Print",
#2 : "Plot",
#3 : "Print and Plot",
#4 : "Punch",
#5 : "Print and Punch",
#6 : "Plot and Punch",
#7 : "Print, Plot, and Punch",
#}
table_code = TABLE_NAME_TO_TABLE_CODE[table_name]
sort_code = 1 # TODO: what should this be???
#table_code = tCode % 1000
#sort_code = tCode // 1000
tCode = table_code * 1000 + sort_code
device_code = 2 # Plot
#print(f'approach_code={approach_code} analysis_code={analysis_code} device_code={device_code}')
data_code = {
'nonlinear_factor': None,
'sort_bits': [0, sort1_sort_bit, random_sort_bit], # real, sort1, random
'sort_method' : sort_method,
'is_msc': is_msc,
#'is_nasa95': is_nasa95,
'format_code': 1, # real
'table_code': table_code,
'tCode': tCode,
'table_name': table_name, ## TODO: should this be a string?
'device_code' : device_code,
'random_code' : random_code,
'thermal': 0,
'title' : title,
'subtitle': subtitle,
'label': label,
#'num_wide' : 8, # displacement-style table
}
return data_code