#from itertools import cycle
from abc import abstractmethod
import numpy as np
from numpy import zeros, searchsorted, allclose
from pyNastran.utils.numpy_utils import integer_types, empty_array
from pyNastran.op2.result_objects.op2_objects import (
BaseElement, get_complex_times_dtype, get_sort_element_sizes)
from pyNastran.op2.tables.oef_forces.oef_force_objects import ForceObject, oef_complex_data_code
from pyNastran.op2.tables.oes_stressStrain.real.oes_objects import (
oes_complex_data_code, set_element_case, set_freq_case, set_complex_modes_case)
from pyNastran.f06.f06_formatting import write_imag_floats_13e, write_float_12e # get_key0,
from pyNastran.f06.f06_formatting import _eigenvalue_header
ELEMENT_NAME_TO_ELEMENT_TYPE = {
'CELAS1': 11,
'CELAS2': 12,
'CELAS3': 13,
'CELAS4': 14,
'CDAMP1': 20,
'CDAMP2': 21,
'CDAMP3': 22,
'CDAMP4': 23,
'CROD' : 1,
'CONROD' : 10,
'CTUBE' : 3,
'CSHEAR': 4,
}
[docs]
class ComplexForceObject(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 False
@property
def is_complex(self) -> bool:
return True
@property
def nnodes_per_element(self):
return 1
[docs]
class ComplexRodForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__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 is_sort1:
pass
else:
raise NotImplementedError('SORT2')
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexRodForceArray"""
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
#[axial_force, torque]
self.data = zeros((self.ntimes, self.ntotal, 2), dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
headers = self.get_headers()
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']
self.data_frame = data_frame
[docs]
@classmethod
def add_freq_case(cls, table_name, element, data, isubcase,
freqs,
element_name: str,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
num_wide = 5
data_code = oef_complex_data_code(
table_name,
element_name, num_wide,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code, title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name.upper()]
data_code['element_name'] = element_name.upper()
data_code['element_type'] = element_type
obj = set_freq_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), freqs)
return obj
[docs]
@classmethod
def add_complex_modes_case(cls, table_name, element, data, isubcase,
modes, eigrs, eigis,
element_name: str,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
num_wide = 5
data_code = oef_complex_data_code(
table_name,
element_name, num_wide,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code, title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name.upper()]
data_code['element_name'] = element_name.upper()
data_code['element_type'] = element_type
obj = set_complex_modes_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, 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())
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 allclose(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
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
[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'
msg.append(' eType\n')
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(' 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: str='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)
# 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]
for eid, axiali, torsioni in zip(eids, axial, torsion):
out = write_imag_floats_13e([axiali, torsioni], is_mag_phase)
[raxial, rtorsion, iaxial, itorsion] = out
#ELEMENT AXIAL TORSIONAL
#ID. STRESS STRESS
#14 0.0 / 0.0 0.0 / 0.0
f06_file.write(' %8i %-13s / %-13s %-13s / %s\n' % (eid, raxial, iaxial, rtorsion, itorsion))
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
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
if self.is_sort1:
struct1 = Struct(endian + b'i4f')
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
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]
for eid_device, axiali, torsioni in zip(eids_device, axial, torsion):
data = [eid_device, axiali.real, torsioni.real, axiali.imag, torsioni.imag]
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, 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 ComplexCShearForceArray(BaseElement):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
BaseElement.__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 is_sort1:
#pass
#else:
#raise NotImplementedError('SORT2')
@property
def is_real(self) -> bool:
return False
@property
def is_complex(self) -> bool:
return True
@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 ComplexCShearForceArray"""
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
#[force41, force14, force21, force12, force32, force23, force43, force34,
#kick_force1, kick_force2, kick_force3, kick_force4,
#shear12, shear23, shear34, shear41]
self.data = zeros((self.ntimes, self.ntotal, 16), dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Mode 1 2
#EigenvalueReal -0.0 -0.0
#EigenvalueImag -0.0 -0.0
#Damping 0.0 0.0
#ElementID Item
#22 force41 2.927977e-10+0.000000e+00j 0.000000+0.000000j
# force14 2.927977e-10+5.855954e-10j 0.000000+0.000000j
# force21 -2.927977e-10+0.000000e+00j 0.000000+0.000000j
# force12 -2.927977e-10+5.855954e-10j 0.000000+0.000000j
# force32 2.927977e-10+0.000000e+00j 0.000000+0.000000j
# force23 2.927977e-10+5.855954e-10j 0.000000+0.000000j
# force43 -2.927977e-10+0.000000e+00j 0.000000+0.000000j
# force34 -2.927977e-10+5.855954e-10j 0.000000+0.000000j
# kickForce1 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# kickForce2 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# kickForce3 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# kickForce4 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# shear12 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# shear23 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# shear34 0.000000e+00+0.000000e+00j 0.000000+0.000000j
# shear41 0.000000e+00+0.000000e+00j 0.000000+0.000000j
headers = self.get_headers()
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
[docs]
@classmethod
def add_freq_case(cls, table_name, element, data, isubcase,
freqs,
element_name: str,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
num_wide = 33
data_code = oef_complex_data_code(
table_name,
element_name, num_wide,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code, title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name.upper()]
data_code['element_name'] = element_name.upper()
data_code['element_type'] = element_type
obj = set_freq_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), freqs)
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())
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 allclose(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
[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'
msg.append(' eType\n')
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(' 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 = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
# 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)))
## TODO: I'm sure this ordering is wrong...
force41 = self.data[itime, :, 0]
force14 = self.data[itime, :, 1]
force21 = self.data[itime, :, 2] # TODO: this is wrong...
force12 = self.data[itime, :, 3]
force32 = self.data[itime, :, 4]
force23 = self.data[itime, :, 5]
force43 = self.data[itime, :, 6]
force34 = self.data[itime, :, 7]
kick_force1 = self.data[itime, :, 8]
kick_force2 = self.data[itime, :, 9]
kick_force3 = self.data[itime, :, 10]
kick_force4 = self.data[itime, :, 11]
shear12 = self.data[itime, :, 12]
shear23 = self.data[itime, :, 13]
shear34 = self.data[itime, :, 14]
shear41 = self.data[itime, :, 15]
assert len(force12) > 0, force12
for (eid, iforce41, force14i, iforce21, iforce12, iforce32, iforce23, iforce43, iforce34,
ikick_force1, ikick_force2, ikick_force3, ikick_force4,
ishear12, ishear23, ishear34, ishear41) in zip(
eids, force41, force14, force21, force12, force32, force23, force43, force34,
kick_force1, kick_force2, kick_force3, kick_force4,
shear12, shear23, shear34, shear41):
vals2 = write_imag_floats_13e([
iforce41, force14i, iforce21, iforce12, iforce32, iforce23, iforce43, iforce34,
ikick_force1, ikick_force2, ikick_force3, ikick_force4,
ishear12, ishear23, ishear34, ishear41], is_mag_phase)
[
force41r, force14r, force21i, force12r, force32r, force23r, force43r, force34r,
kick_force1r, kick_force2r, kick_force3r, kick_force4r,
shear12r, shear23r, shear34r, shear41r,
force41i, force14i, force21i, force12i, force32i, force23i, force43i, force34i,
kick_force1i, kick_force2i, kick_force3i, kick_force4i,
shear12i, shear23i, shear34i, shear41i
] = vals2
#complex_cshear_force_f06
#' ====== POINT 1 ====== ====== POINT 2 ====== ====== POINT 3 ====== ====== POINT 4 ======'
#' 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'
#' ID KICK-1 SHEAR-12 KICK-2 SHEAR-23 KICK-3 SHEAR-34 KICK-4 SHEAR-41'
#' 25 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.0 0.0 0.0'
f06_file.write(
' %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'% (
eid,
force41r, force14r, force21i, force12r, force32r, force23r, force43r, force34r,
kick_force1r, kick_force2r, kick_force3r, kick_force4r,
shear12r, shear23r, shear34r, shear41r,
force41i, force14i, force21i, force12i, force32i, force23i, force43i, force34i,
kick_force1i, kick_force2i, kick_force3i, kick_force4i,
shear12i, shear23i, shear34i, shear41i
))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
class ComplexSpringDamperForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__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 is_sort1:
#pass
#else:
#raise NotImplementedError('SORT2')
#def get_headers(self):
#headers = ['axial', 'torque']
#return headers
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexSpringDamperForceArray"""
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
ntimes, nelements, ntotal = get_sort_element_sizes(self)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[axial_force, torque]
self.data = zeros((ntimes, ntotal, 1), dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Mode 1 2
#EigenvalueReal -0.0 -0.0
#EigenvalueImag -0.0 -0.0
#Damping 0.0 0.0
#ElementID Item
#30 spring_force 0.000000+0.000000j 0.000000+0.000000j
#31 spring_force 0.000000+0.000000j 0.000000+0.000000j
#32 spring_force 0.000000+0.000000j 0.000000+0.000000j
#33 spring_force 0.000000+0.000000j 0.000000+0.000000j
headers = self.get_headers()
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
[docs]
@classmethod
def add_freq_case(cls, table_name, element, data, isubcase,
freqs,
element_name: str,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
num_wide = 3
data_code = oef_complex_data_code(
table_name,
element_name, num_wide,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code, title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name.upper()]
data_code['element_name'] = element_name.upper()
data_code['element_type'] = element_type
obj = set_freq_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, data), freqs)
return obj
[docs]
@classmethod
def add_complex_modes_case(cls, table_name, element, data, isubcase,
modes, eigrs, eigis,
element_name: str,
is_sort1=True, is_random=False, is_msc=True,
random_code=0, title='', subtitle='', label=''):
num_wide = 3
data_code = oef_complex_data_code(
table_name,
element_name, num_wide,
is_sort1=is_sort1, is_random=is_random,
random_code=random_code, title=title, subtitle=subtitle, label=label,
is_msc=is_msc)
element_type = ELEMENT_NAME_TO_ELEMENT_TYPE[element_name.upper()]
data_code['element_name'] = element_name.upper()
data_code['element_type'] = element_type
obj = set_complex_modes_case(cls, is_sort1, isubcase, data_code,
set_element_case, (element, 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())
i = 0
for itime in range(self.ntimes):
for ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, 0]
t2 = table.data[itime, ielem, 0]
if not allclose([t1.real, t1.imag], [t2.real, t2.imag], atol=0.0001):
msg += '%s (%s, %s) (%s, %s)\n' % (
eid,
t1.real, t1.imag,
t2.real, t2.imag)
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, 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)
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.data[self.itime, self.ielement, 0] = force
self.ielement += 1
def add_sort2(self, dt, eid, force):
"""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.itime] = dt
#self.element[self.ielement] = eid
#self.data[self.itime, self.ielement, 0] = force
#self.ielement += 1
#itotal = self.itime
itime = self.itotal
#print(f'itime={itime}/{len(self._times)}; itotal={itotal}/{self.ntotal}; self.ielement={self.ielement}/{len(self.element)}')
self._times[itime] = dt
self.element[self.ielement] = eid
self.data[itime, self.ielement, 0] = 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',
]
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'
msg.append(' eType\n')
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(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
#def get_element_index(self, eids):
## elements are always sorted; nodes are not
#itot = searchsorted(eids, self.element) #[0]
#return itot
#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: str='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)
# 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)))
spring_force = self.data[itime, :, 0]
for eid, spring_forcei in zip(eids, spring_force):
[rspring, ispring] = write_imag_floats_13e([spring_forcei], is_mag_phase)
#ELEMENT AXIAL TORSIONAL
#ID. STRESS STRESS
#14 0.0 / 0.0 0.0 / 0.0
f06_file.write(' %8i %-13s / %-13s\n' % (eid, rspring, ispring))
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'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
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.real, forcei.imag]
op2_ascii.write(' eid=%s force=%s\n' % (eid, forcei))
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 ComplexSpringForceArray(ComplexSpringDamperForceArray): # 11-CELAS1,12-CELAS2,13-CELAS3, 14-CELAS4
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexSpringDamperForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class ComplexDamperForceArray(ComplexSpringDamperForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexSpringDamperForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class ComplexViscForceArray(BaseElement):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
BaseElement.__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 is_sort1:
pass
else:
raise NotImplementedError('SORT2')
@property
def is_real(self) -> bool:
return False
@property
def is_complex(self) -> bool:
return True
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
@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 ComplexViscForceArray"""
#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))
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype='int32')
#[axial_force, torque]
self.data = zeros((self.ntimes, self.ntotal, 2), dtype='complex64')
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Mode 1 2 3 4
#EigenvalueReal -0.0 -0.0 -0.0 -0.0
#EigenvalueImag -0.0 -0.0 -0.0 -0.0
#Damping 0.0 0.0 0.0 0.0
#ElementID Item
#50 axial_force (-0+0j) (-0+0j) (-0+0j) (-0+0j)
# torque (-0+0j) (-0+0j) (-0+0j) (-0+0j)
#51 axial_force (-0+0j) (-0+0j) (-0+0j) (-0+0j)
# torque 0j (-0+0j) (-0+0j) (-0+0j)
headers = self.get_headers()
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)
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 ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(axial1, torque1) = t1
(axial2, torque2) = t2
if not allclose(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
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
[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'
msg.append(' eType\n')
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(' 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 = []
(elem_name, msg_temp) = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
# 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]
for eid, axiali, torsioni in zip(eids, axial, torsion):
out = write_imag_floats_13e([axiali, torsioni], is_mag_phase)
[raxial, rtorsion, iaxial, itorsion] = out
#ELEMENT AXIAL TORSIONAL
#ID. STRESS STRESS
#14 0.0 / 0.0 0.0 / 0.0
f06_file.write(' %8i %-13s / %-13s %-13s / %s\n' %
(eid, raxial, iaxial, rtorsion, itorsion))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
class ComplexPlateForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__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 is_sort1:
#pass
#else:
#raise NotImplementedError('SORT2')
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexPlateForceArray"""
#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.itime = 0
self.ielement = 0
self.itotal = 0
if self.is_sort1:
self.nelements //= self.ntimes
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
else:
self.ntimes, self.nelements = self.nelements, self.ntimes
#print(f'ComplexPlateForceArray {self.element_name}-{self.element_type}: ntimes={self.ntimes} nelements={self.nelements} ntotal={self.ntotal}')
ntimes = self.ntimes
nelements = self.nelements
ntimes = self.ntotal
ntotal = ntimes
#print(f'-> ntimes={ntimes} nelements={nelements} ntotal={ntotal}')
self.ntimes = ntimes
#self.ntimes = 0
#self.nelements = 0
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(nelements, dtype=idtype)
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.data = np.full((ntimes, ntotal, 8), np.nan, dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
# Freq 0.00001 10.00000 20.00000 30.00000 40.00000 50.00000 60.00000
# ElementID Item
#8 mx 0j 0j 0j 0j (-361.6303-680.04156j) 0j 0j
# my 0j 0j 0j 0j (-7884.6196-14826.936j) 0j 0j
# mxy 0j 0j 0j 0j (-237.5723-446.7519j) 0j 0j
# bmx 0j 0j 0j 0j (5.514431+10.3698225j) 0j 0j
# bmy 0j 0j 0j 0j (10.107019+19.00613j) 0j 0j
# bmxy 0j 0j 0j 0j (-16.361727-30.768036j) 0j 0j
# tx 0j 0j 0j 0j (18.819313+35.3895j) 0j 0j
# ty 0j 0j 0j 0j (-61.55238-115.74853j) 0j 0j
#9 mx 0j 0j 0j 0j (1086.9078+2043.9175j) 0j 0j
# my 0j 0j 0j 0j (8089.895+15212.953j) 0j 0j
# mxy 0j 0j 0j 0j (-4725.3286-8885.925j) 0j 0j
# bmx 0j 0j 0j 0j (-3.9810739-7.486363j) 0j 0j
# bmy 0j 0j 0j 0j (-10.283798-19.338562j) 0j 0j
# bmxy 0j 0j 0j 0j (-8.663734-16.292051j) 0j 0j
# tx 0j 0j 0j 0j (54.14508+101.81919j) 0j 0j
# ty 0j 0j 0j 0j (-61.92162-116.44288j) 0j 0j
headers = self.get_headers()
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']
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 ielem, eid in enumerate(self.element):
t1 = self.data[itime, ielem, :]
t2 = table.data[itime, ielem, :]
(mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1) = t1
(mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2) = t2
if not allclose(t1, t2):
#if not np.array_equal(t1.real, t2.real):
msg += ('%-8s (%s, %s, %s, %s, %s, %s, %s, %s)\n'
'%-8s (%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
#mx1.real, my1.real, mxy1.real, bmx1.real, bmy1.real,
#bmxy1.real, tx1.real, ty1.real,
mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1,
'',
mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2,
#mx2.real, my2.real, mxy2.real, bmx2.real, bmy2.real,
#bmxy2.real, tx2.real, ty2.real,
))
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: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: 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, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.ielement += 1
self.itotal += 1
def add_sort2(self, dt, eid: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: float) -> None:
"""unvectorized method for adding SORT1 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
ielement = self.itime
ntimes = len(self._times)
nelement = len(self.element)
#print(f'ComplexPlateForceArray: itime={itime}/{ntimes} -> dt={dt}; ielement={ielement}/{nelement}-> eid={eid}')
self._times[itime] = dt
self.element[ielement] = eid
self.data[itime, ielement, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.ielement += 1
self.itotal += 1
#@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; 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'
msg.append(' eType\n')
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(' 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: str='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)
# 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)))
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):
out = write_imag_floats_13e([mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi], is_mag_phase)
[smxr, smyr, smxyr, sbmxr, sbmyr, sbmxyr, stxr, styr,
smxi, smyi, smxyi, sbmxi, sbmyi, sbmxyi, stxi, styi] = out
#"""
#ELEMENT - MEMBRANE FORCES - - BENDING MOMENTS - - TRANSVERSE SHEAR FORCES -
#ID FX FY FXY MX MY MXY QX QY
#0 564 1.543439E+03 7.311177E+02 1.322702E+02 1.080178E+00 1.699104E+00 2.618547E-01 3.877034E+01 4.518554E+00
#358.3129 358.0245 177.5593 177.5292 178.2112 0.0907 358.1465 179.4567
#"""
# fx fy fxy mx my mxy qx qy
f06_file.write(
'0 %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %8s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, smxr, smyr, smxyr, sbmxr, sbmyr, sbmxyr, stxr, styr,
'', smxi, smyi, smxyi, sbmxi, sbmyi, sbmxyi, stxi, styi))
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
#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 16f')
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')
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_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.real, myi.real, mxyi.real, bmxi.real, bmyi.real, bmxyi.real, txi.real, tyi.real,
mxi.imag, myi.imag, mxyi.imag, bmxi.imag, bmyi.imag, bmxyi.imag, txi.imag, tyi.imag]
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
[docs]
class ComplexPlate2ForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__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 is_sort1:
#pass
#else:
#raise NotImplementedError('SORT2')
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexPlate2ForceArray"""
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.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))
#print(self.object_stats())
idtype, cfdtype = get_complex_times_dtype(self.size)
if self.is_sort1:
self.nelements //= self.ntimes
ntimes = self.ntimes
nelements = self.nelements
ntotal = self.ntotal
else:
#ComplexPlate2ForceArray: ntimes=2 nelements=4002 ntotal=10005
# -> ntimes=4002 nelements=2 ntotal=10005
#ntimes_actual = 2001
#nelement_nid_actual = 10
#{(2, 43), (2, 4), (20, 53), (2, 23), (20, 4),
#(20, 52), (20, 32), (2, 22), (2, 44), (20, 31)}
#self.all_times = set()
#self.all_elements = set()
#print(f'ComplexPlateForceArray: {self.element_name}-{self.element_type}: '
#f'ntimes={self.ntimes} nelements={self.nelements} ntotal={self.ntotal}'
#f' nnodes/element={self.nnodes_per_element}')
#ntimes = self.nelements
nelements = self.ntimes # ntotal // ntimes
ntotal = nelements * self.nnodes_per_element
#self.itotal // self.nnodes_per_element
ntimes = self.ntotal // self.nnodes_per_element
#ntotal = self.ntotal
#print('-> ntimes=%s nelements=%s ntotal=%s' % (ntimes, nelements, ntotal))
#asdf
self.ntimes = ntimes
self.nelements = nelements
#self.ntotal = ntotal
self._times = empty_array(ntimes, dtype=self.analysis_fmt)
self.element = np.full(nelements, -1, dtype=idtype)
self.element_node = zeros((ntotal, 2), dtype=idtype)
#[mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.data = np.full((ntimes, ntotal, 8), np.nan, dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
assert 0 not in self.element
#print(self.element_node)
element_node = [self.element_node[:, 0], self.element_node[:, 1]]
assert 0 not in self.element_node[:, 0]
if self.nonlinear_factor not in (None, np.nan):
# Freq 0.00001 10.00000 20.00000 30.00000 40.00000 50.00000 60.00000
# ElementID NodeID Item
# 6 0 mx 0j 0j 0j 0j (-705.7376-1327.1312j) 0j 0j
# my 0j 0j 0j 0j (7404.8853+13924.8j) 0j 0j
# mxy 0j 0j 0j 0j (-101.319756-190.53061j) 0j 0j
# bmx 0j 0j 0j 0j (3.0701134+5.7733126j) 0j 0j
# bmy 0j 0j 0j 0j (98.75731+185.71196j) 0j 0j
# bmxy 0j 0j 0j 0j (0.25202343+0.4739271j) 0j 0j
# tx 0j 0j 0j 0j (14.426779+27.129389j) 0j 0j
# ty 0j 0j 0j 0j (-199.6823-375.5002j) 0j 0j
# 4 mx 0j 0j 0j 0j (-2934.639-5518.5537j) 0j 0j
# my 0j 0j 0j 0j (7516.2485+14134.217j) 0j 0j
# mxy 0j 0j 0j 0j (-101.319756-190.53061j) 0j 0j
# bmx 0j 0j 0j 0j (-19.69526-37.036705j) 0j 0j
# bmy 0j 0j 0j 0j (100.64615+189.2639j) 0j 0j
# bmxy 0j 0j 0j 0j (0.25202343+0.4739271j) 0j 0j
# tx 0j 0j 0j 0j (14.426779+27.129389j) 0j 0j
# ty 0j 0j 0j 0j (-199.6823-375.5002j) 0j 0j
column_names, column_values = self._build_dataframe_transient_header()
data_frame = self._build_pandas_transient_element_node(
column_values, column_names,
headers, self.element_node, self.data)
#data_frame = pd.Panel(self.data, items=column_values,
#major_axis=element_node, minor_axis=headers).to_frame()
#data_frame.columns.names = column_names
#data_frame.index.names = ['ElementID', 'NodeID', 'Item']
else:
data_frame = pd.Panel(self.data,
major_axis=element_node, minor_axis=headers).to_frame()
data_frame.columns.names = ['Static']
data_frame.index.names = ['ElementID', 'NodeID', 'Item']
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 itotal, e in enumerate(self.element_node):
(eid, nid) = e
t1 = self.data[itime, itotal, :]
t2 = table.data[itime, itotal, :]
(mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1) = t1
(mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2) = t2
if not allclose(t1, t2):
base1 = '(%s, %s) ' % (eid, nid)
base2 = ' ' * len(base1)
msg += (
f'itime={itime} itotal={itotal}\n' +
'%s (%s, %s, %s, %s, %s, %s, %s, %s)\n'
'%s(%s, %s, %s, %s, %s, %s, %s, %s)\n' % (
base1,
mx1, my1, mxy1, bmx1, bmy1, bmxy1, tx1, ty1,
base2,
mx2, my2, mxy2, bmx2, bmy2, bmxy2, tx2, ty2))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
if i > 0:
raise ValueError(msg)
return True
[docs]
def add_new_element_sort1(self, dt, eid: int, term: str, nid: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: float) -> None:
self._times[self.itime] = dt
self.element[self.ielement] = eid
self.element_node[self.itotal, :] = [eid, nid]
self.data[self.itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
self.ielement += 1
def add_sort1(self, dt, eid: int, inid: int, nid: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: 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
#assert self.element[self.ielement - 1] == eid, eid
self.element_node[self.itotal, :] = [eid, nid]
self.data[self.itime, self.itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
[docs]
def add_new_element_sort2(self, dt, eid: int, term: str, nid: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: float) -> None:
assert isinstance(nid, int), nid
#print(f'ntimes={self.ntimes} nelement={self.nelements} ntotal={self.ntotal}')
#self.all_times.add(dt)
#self.all_elements.add((eid, nid))
itime = self.itotal // self.nnodes_per_element
ntimes = len(self._times)
#ielement = self.ielement
#ielement = self.itotal // ntimes
ielement = self.itime
nelement = len(self.element)
#itotal = self.itotal
#itotala = self.itotal // self.ntimes
#itotal = ielement *self.nnodes_per_element + self.itotal // ntimes
itotal = ielement * self.nnodes_per_element
ntotal = len(self.element_node)
#print(f'ComplexPlate2ForceArrayA: itime={itime}/{ntimes} -> dt={dt}; ielement={ielement}/{nelement}-> eid={eid}; itotal={itotal}/{ntotal}-> nid={nid}')
self._times[itime] = dt
self.element[ielement] = eid
self.element_node[itotal, :] = [eid, nid]
self.data[itime, itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
#self.ielement += 1
#print(self.element_node)
def add_sort2(self, dt, eid: int, inid: int, nid: int,
mx: float, my: float, mxy: float,
bmx: float, bmy: float, bmxy: float,
tx: float, ty: float) -> None:
"""unvectorized method for adding SORT2 transient data"""
assert isinstance(nid, int), nid
#self.all_times.add(dt)
#self.all_elements.add((eid, nid))
assert self.sort_method == 2, self
assert isinstance(eid, integer_types) and eid > 0, 'dt=%s eid=%s' % (dt, eid)
itime = self.itotal // self.nnodes_per_element
ntimes = len(self._times)
ielement = self.itime
#ielement = self.ielement
nelement = len(self.element)
#itotal = self.itotal // self.ntimes
#itotal = ielement * self.nnodes_per_element + self.itotal // ntimes
itotal = ielement * self.nnodes_per_element + inid + 1
ntotal = len(self.element_node)
#print(self.all_elements)
#print(f'ComplexPlate2ForceArrayB: itime={itime}/{ntimes} -> dt={dt}; ielement={ielement}/{nelement}-> eid={eid}; itotal={itotal}/{ntotal}-> nid={nid}; inid={inid}')
#print(len(self.all_times), len(self.all_elements))
self._times[itime] = dt
#assert self.element[self.ielement] == eid, eid
self.element_node[itotal, :] = [eid, nid]
self.data[itime, itotal, :] = [mx, my, mxy, bmx, bmy, bmxy, tx, ty]
self.itotal += 1
@property
def nnodes_per_element(self) -> int:
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: # pragma: no cover
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; 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'
msg.append(' eType\n')
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(' 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: str='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)
# 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)))
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):
out = write_imag_floats_13e([mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi], is_mag_phase)
[smxr, smyr, smxyr, sbmxr, sbmyr, sbmxyr, stxr, styr,
smxi, smyi, smxyi, sbmxi, sbmyi, sbmxyi, stxi, styi] = out
#"""
#ELEMENT - MEMBRANE FORCES - - BENDING MOMENTS - - TRANSVERSE SHEAR FORCES -
#ID FX FY FXY MX MY MXY QX QY
#0 564 1.543439E+03 7.311177E+02 1.322702E+02 1.080178E+00 1.699104E+00 2.618547E-01 3.877034E+01 4.518554E+00
#358.3129 358.0245 177.5593 177.5292 178.2112 0.0907 358.1465 179.4567
#"""
# fx fy fxy mx my mxy qx qy
f06_file.write(
'0 %8i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %8s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, smxr, smyr, smxyr, sbmxr, sbmyr, sbmxyr, stxr, styr,
'', smxi, smyi, smxyi, sbmxi, sbmyi, sbmxyi, stxi, styi))
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
#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 = self.element * 10 + self.device_code
eids = self.element_node[:, 0]
nids = self.element_node[:, 1]
# table 4 info
#ntimes = self.data.shape[0]
#nnodes = self.data.shape[1]
nelements = len(self.element)
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
ntotali = self.num_wide
if self.element_type in [70, 75]: # CTRIAR,CTRIA6
nnodes = 3
elif self.element_type in [64, 82, 144]: # CQUAD8,CQUADR,CQUAD4-bilinear
nnodes = 4
else:
raise NotImplementedError(self.code_information())
nnodes_all = nnodes + 1
numwide_imag = 2 + nnodes_all * 17
# CTRIA6-75: ntotal=
assert ntotali == numwide_imag, f'nnodes={nnodes_all}\n{self.code_information()}'
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 4s i 16f')
struct2 = Struct(endian + b'i 16f')
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')
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
ielement = -1
for eid, nid, mxi, myi, mxyi, bmxi, bmyi, bmxyi, txi, tyi in zip(eids, nids, mx, my, mxy, bmx, bmy, bmxy, tx, ty):
if nid == 0:
ielement += 1
eid_device = eids_device[ielement]
data = [eid_device, b'CEN/', nid,
mxi.real, myi.real, mxyi.real, bmxi.real, bmyi.real, bmxyi.real, txi.real, tyi.real,
mxi.imag, myi.imag, mxyi.imag, bmxi.imag, bmyi.imag, bmxyi.imag, txi.imag, tyi.imag]
op2_ascii.write(' eid_device=%s data=%s\n' % (eid_device, str(data)))
op2_file.write(struct1.pack(*data))
else:
data = [nid,
mxi.real, myi.real, mxyi.real, bmxi.real, bmyi.real, bmxyi.real, txi.real, tyi.real,
mxi.imag, myi.imag, mxyi.imag, bmxi.imag, bmyi.imag, bmxyi.imag, txi.imag, tyi.imag]
op2_ascii.write(' data=%s\n' % (str(data)))
op2_file.write(struct2.pack(*data))
nwide += len(data)
assert nwide == ntotal, 'nwide=%s ntotal=%s' % (nwide, 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 ComplexCBarWeldForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__init__(self, data_code, isubcase)
self.result_flag = 0
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.itime = 0
self.nelements = 0 # result specific
#self.element_type = 'CBAR'
#self.cid = {} # gridGauss
#if is_sort1:
##sort1
#pass
#else:
#raise NotImplementedError('SORT2')
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexCBarForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s subtitle=%s' % (
#self.ntimes, self.nelements, self.ntotal, self.subtitle))
if self.is_built:
return
#nnodes = 1
#self.names = []
#self.nelements //= nnodes
if self.is_sort1:
self.nelements //= self.ntimes
ntimes = self.ntimes
nelements = self.nelements
ntotal = nelements
else:
#print(f'{self.class_name}: ntimes={self.ntimes} nelements={self.nelements} ntotal={self.ntotal}')
self.ntimes, self.nelements = self.ntotal, self.ntimes
#print(f'-> ntimes={self.ntimes} nelements={self.nelements} ntotal={self.ntotal}')
ntimes = self.ntimes
nelements = self.nelements
ntotal = nelements
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = empty_array(ntimes, dtype=self.analysis_fmt)
self.element = zeros(ntotal, dtype=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)
#raise RuntimeError(msg)
#[bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq]
self.data = np.full((ntimes, ntotal, 8), np.nan, dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
headers = self.get_headers()
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)
#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']
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())
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, :]
(s1a1, s2a1, s3a1, s4a1, axial1, s2a1, s2b1, s2c1, s2d1) = t1
(s1a2, s2a2, s3a2, s4a2, axial2, s2a2, s2b2, s2c2, s2d2) = t2
#d = t1 - t2
if not allclose([s1a1.real, s2a1.real, s3a1.real, s4a1.real, axial1.real, s2a1.real, s2b1.real, s2c1.real, s2d1.real],
[s1a2.real, s2a2.real, s3a2.real, s4a2.real, axial2.real, s2a2.real, s2b2.real, s2c2.real, s2d2.real], atol=0.0001):
#if not np.array_equal(t1, t2):
msg += '%-4s (%s, %s, %s, %s, %s, %s, %s, %s, %s)\n (%s, %s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid,
s1a1.real, s2a1.real, s3a1.real, s4a1.real, axial1.real, s2a1.real, s2b1.real, s2c1.real, s2d1.real,
s1a2.real, s2a2.real, s3a2.real, s4a2.real, axial2.real, s2a2.real, s2b2.real, s2c2.real, s2d2.real,
)
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: int, bm1a: float, bm2a: float, bm1b: float, bm2b: float,
ts1: float, ts2: float, af: float, trq: float):
"""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, :] = [bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq]
self.element[self.itotal] = eid
self.itotal += 1
def add_sort2(self, dt, eid: int, bm1a: float, bm2a: float, bm1b: float, bm2b: float,
ts1: float, ts2: float, af: float, trq: float):
"""unvectorized method for adding SORT1 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
ielement = self.itime
ntimes = len(self._times)
nelement = len(self.element)
#print(f'ComplexCBarForceArray: itime={itime}/{ntimes} -> dt={dt}; ielement={ielement}/{nelement}-> eid={eid}')
itime = self.itotal
ielement = self.itime
self._times[itime] = dt
self.data[itime, ielement, :] = [bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq]
self.element[ielement] = eid
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(' is_sort1=%s is_sort2=%s\n' % (self.is_sort1, self.is_sort2))
msg.append(f' {self.element_name}\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, nnodes = get_f06_header(self, is_mag_phase, is_sort1)
#is_sort1 = False
if is_mag_phase:
mag_phase = ' (MAGNITUDE/PHASE)\n \n'
else:
mag_phase = ' (REAL/IMAGINARY)\n \n'
name = self.data_code['name']
if name == 'freq':
name = 'FREQUENCY'
#else: # mode
#raise RuntimeError(name)
if is_sort1:
line1 = '0 ELEMENT BEND-MOMENT-END-A BEND-MOMENT-END-B SHEAR\n'
line2 = ' ID. PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n'
else:
line1 = ' BEND-MOMENT-END-A BEND-MOMENT-END-B SHEAR\n'
line2 = ' %16s PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n' % name
# force
msg_temp = header + [
' C O M P L E X F O R C E S I N B A R E L E M E N T S ( C B A R )\n',
mag_phase,
' ',
line1,
line2,
]
if self.is_sort1:
assert self.is_sort1 == True, str(self)
if is_sort1:
page_num = self._write_sort1_as_sort1(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
else:
self._write_sort1_as_sort2(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
else:
assert self.is_sort1 == True, str(self)
return page_num - 1
def _write_sort1_as_sort1(self, f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase):
eids = self.element
#times = self._times
ntimes = self.data.shape[0]
for itime in range(ntimes):
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))
#bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq
assert self.is_sort1 == True, str(self)
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):
vals = (bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(bm1air, bm2air, bm1bir, bm2bir, ts1ir, ts2ir, afir, trqir,
bm1aii, bm2aii, bm1bii, bm2bii, ts1ii, ts2ii, afii, trqii) = vals2
f06_file.write('0%16i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %14s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, bm1air, bm2air, bm1bir, bm2bir, ts1ir, ts2ir, afir, trqir,
'', bm1aii, bm2aii, bm1bii, bm2bii, ts1ii, ts2ii, afii, trqii))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num
def _write_sort1_as_sort2(self, f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase):
eids = self.element
times = self._times
#ntimes = self.data.shape[0]
for ieid, eid in enumerate(eids):
eid_line = ' ELEMENT-ID = %s' % (eid)
header[1] = eid_line
msg = header + msg_temp
f06_file.write(''.join(msg))
#bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq
bm1a = self.data[:, ieid, 0]
bm2a = self.data[:, ieid, 1]
bm1b = self.data[:, ieid, 2]
bm2b = self.data[:, ieid, 3]
ts1 = self.data[:, ieid, 4]
ts2 = self.data[:, ieid, 5]
af = self.data[:, ieid, 6]
trq = self.data[:, ieid, 7]
for dt, bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi in zip(times, bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq):
vals = (bm1ai, bm2ai, bm1bi, bm2bi, ts1i, ts2i, afi, trqi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(bm1air, bm2air, bm1bir, bm2bir, ts1ir, ts2ir, afir, trqir,
bm1aii, bm2aii, bm1bii, bm2bii, ts1ii, ts2ii, afii, trqii) = vals2
f06_file.write('0%16s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %15s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
write_float_12e(dt),
bm1air, bm2air, bm1bir, bm2bir, ts1ir, ts2ir, afir, trqir,
'', bm1aii, bm2aii, bm1bii, bm2bii, ts1ii, ts2ii, afii, trqii))
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"""
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
#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 16f')
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, bm2a, bm1b, bm2b, ts1, ts2, af, trq
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]
assert len(eids_device) == len(bm1a.real)
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.real, bm2ai.real, bm1bi.real, bm2bi.real, ts1i.real, ts2i.real, afi.real, trqi.real,
bm1ai.imag, bm2ai.imag, bm1bi.imag, bm2bi.imag, ts1i.imag, ts2i.imag, afi.imag, trqi.imag]
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
[docs]
class ComplexCBarForceArray(ComplexCBarWeldForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexCBarWeldForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class ComplexCWeldForceArray(ComplexCBarWeldForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexCBarWeldForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class ComplexCWeldForceArrayMSC(ComplexCBarWeldForceArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexCBarWeldForceArray.__init__(self, data_code, is_sort1, isubcase, dt)
[docs]
class ComplexCBeamForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__init__(self, data_code, isubcase)
self.result_flag = 0
self.itime = 0
self.nelements = 0 # result specific
#self.element_type = 'CBEAM'
#if is_sort1:
##sort1
#pass
#else:
#raise NotImplementedError('SORT2')
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexCBeamForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s subtitle=%s' % (
#self.ntimes, self.nelements, self.ntotal, self.subtitle))
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(self.ntimes, self.analysis_fmt)
self.element = zeros(self.ntotal, idtype)
self.element_node = zeros((self.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)
#raise RuntimeError(msg)
#[sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq]
self.data = zeros((self.ntimes, self.ntotal, 8), cfdtype)
[docs]
def finalize(self):
sd = self.data[0, :, 0].real
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, 'CBEAM 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"""
# Freq 0.00001 10.00000 ... 50.00000 60.00000
# ElementID Location Item ...
# 12.0 12.0 bending_moment1 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# bending_moment2 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# shear1 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# shear2 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# axial_force 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# total_torque 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# warping_torque 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# 0.0 1.0 bending_moment1 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# bending_moment2 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# shear1 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# shear2 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# axial_force 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# total_torque 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
# warping_torque 0.000000+0.000000j 0.000000+0.000000j ... 0.000000+0.000000j 0.000000+0.000000j
import pandas as pd
headers = self.get_headers()[1:]
column_names, column_values = self._build_dataframe_transient_header()
element_location = [
self.element_node[:, 0],
self.data[0, :, 0].real,
]
is_v25 = pd.__version__ >= '0.25'
if is_v25:
print(f'skipping pandas {self.class_name}')
return
# wrong type for ElementID
#data_frame = self._build_pandas_transient_element_node(
#column_values, column_names,
#headers, element_location, self.data[:, :, 1:])
#data_frame.index.names = ['ElementID', 'Location', 'Item']
#data_frame.index['ElementID', :]# .astype('int32')
#print(data_frame)
data_frame = pd.Panel(self.data[:, :, 1:], items=column_values,
major_axis=element_location, minor_axis=headers).to_frame()
data_frame.columns.names = column_names
data_frame.index.names = ['ElementID', 'Location', 'Item']
#print(data_frame)
self.data_frame = data_frame
def __eq__(self, table): # pragma: no cover
return self.assert_equal(table)
[docs]
def assert_equal(self, table, rtol=1.e-5, atol=1.e-8):
assert self.is_sort1 == table.is_sort1
self._eq_header(table)
if not np.allclose(self.data, table.data, atol=atol):
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, :]
#print(t1)
#'sd', 'bending_moment1', 'bending_moment2', 'shear1', 'shear2',
#'axial_force', 'total_torque', 'warping_torque', ]
(sd1, bm11, bm21, shear11, shear21, axial1, total_torque1, warp_torque1) = t1
(sd2, bm12, bm22, shear12, shear22, axial2, total_torque2, warp_torque2) = t2
d = t1 - t2
if not allclose(t1, t2, atol=atol):
msg += (
'%-4s (%s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj)\n'
' (%s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj)\n'
' dt12=(%s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj, %s, %sj)\n' % (
eid,
bm11.real, bm11.imag,
bm21.real, bm21.imag,
shear11.real, shear11.imag,
shear21.real, shear21.imag,
axial1.real, axial1.imag,
total_torque1.real, total_torque1.imag,
warp_torque1.real, warp_torque1.imag,
bm12.real, bm12.imag,
bm22.real, bm22.imag,
shear12.real, shear12.imag,
shear22.real, shear22.imag,
axial2.real, axial2.imag,
total_torque2.real, total_torque2.imag,
warp_torque2.real, warp_torque2.imag,
d[0].real, d[0].imag,
d[1].real, d[1].imag,
d[2].real, d[2].imag,
d[3].real, d[3].imag,
d[4].real, d[4].imag,
d[5].real, d[5].imag,
d[6].real, d[6].imag,
))
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_new_element_sort1(self, dt, eid, nid, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
#return self.add_sort1(dt, eid, nid, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq)
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 type=%s' % (dt, eid, type(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\n'
% (self.__class__.__name__, ntimes, nelements))
else:
msg.append(' type=%s nelements=%i\n' % (self.__class__.__name__, nelements))
#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(' 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: str='PAGE %s', page_num: int=1, is_mag_phase: bool=False, is_sort1: bool=True):
if header is None:
header = []
# option B
#' C O M P L E X 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 ) '
#' (REAL/IMAGINARY)'
#' STAT DIST/ - BENDING MOMENTS - - WEB SHEARS - AXIAL TOTAL WARPING'
#' ELEMENT-ID GRID LENGTH PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE TORQUE'
#'0 20'
#'0 11 0.000 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.0'
#'0 12 1.000 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.0'
#msg_temp, nnodes = get_f06_header(self, is_mag_phase, is_sort1)
#print('write_f06 not implemented for ComplexCBeamForceArray')
#return page_num
#is_sort1 = False
if is_mag_phase:
mag_phase = ' (MAGNITUDE/PHASE)\n \n'
else:
mag_phase = ' (REAL/IMAGINARY)\n \n'
if is_sort1:
line1 = '0 ELEMENT BEND-MOMENT-END-A BEND-MOMENT-END-B SHEAR\n'
line2 = ' ID. PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n'
else:
name = self.data_code['name']
if name == 'freq':
name = 'FREQUENCY'
else: # mode
raise RuntimeError(name)
line1 = ' BEND-MOMENT-END-A BEND-MOMENT-END-B SHEAR\n'
line2 = ' %16s PLANE 1 PLANE 2 PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE\n' % name
# force
msg_temp = header + [
' C O M P L E X F O R C E S I N B A R E L E M E N T S ( C B E A M )\n',
mag_phase,
' ',
line1,
line2,
]
if self.is_sort1:
assert self.is_sort1 == True, str(self)
#if is_sort1:
page_num = self._write_sort1_as_sort1(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
#else:
#self._write_sort1_as_sort2(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
else:
assert self.is_sort1 == True, str(self)
return page_num - 1
def _write_sort1_as_sort1(self, f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase):
eids = self.element
#times = self._times
ntimes = self.data.shape[0]
for itime in range(ntimes):
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))
#bm1a, bm2a, bm1b, bm2b, ts1, ts2, af, trq
assert self.is_sort1 == True, str(self)
#sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq
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, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi in zip(eids, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
vals = (sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(sdir, bm1ir, bm2ir, ts1ir, ts2ir, afir, ttrqir, wtrqir,
sdii, bm1ii, bm2ii, ts1ii, ts2ii, afii, ttrqii, wtrqii) = vals2
f06_file.write('0%16i %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %14s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, sdir, bm1ir, bm2ir, ts1ir, ts2ir, afir, ttrqir, wtrqir,
'', sdii, bm1ii, bm2ii, ts1ii, ts2ii, afii, ttrqii, wtrqii))
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"""
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_node[:, 0]
nids = self.element_node[:, 1]
#long_form = False
#if nids.min() == 0:
#long_form = True
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')
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
struct1 = Struct(endian + b'2i 15f')
struct2 = Struct(endian + b'i 15f')
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
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 = 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, sdi, bm1i, bm2i, ts1i, ts2i, afi, ttrqi, wtrqi in zip(eids, sd, bm1, bm2, ts1, ts2, af, ttrq, wtrq):
if icount == 0:
eid_device = eids_device[ielement]
nid = nids[ielement]
data = [eid_device, nid, sdi.real,
bm1i.real, bm2i.real, ts1i.real, ts2i.real, afi.real, ttrqi.real, wtrqi.real,
bm1i.imag, bm2i.imag, ts1i.imag, ts2i.imag, afi.imag, ttrqi.imag, wtrqi.imag] # 17
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.,
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]
#print(eids_device)
assert eid_device == eid_device2, 'eid_device=%s eid_device2=%s' % (eid_device, eid_device2)
nid = nids[ielement]
data = [nid, sdi.real,
bm1i.real, bm2i.real, ts1i.real, ts2i.real, afi.real, ttrqi.real, wtrqi.real,
bm1i.imag, bm2i.imag, ts1i.imag, ts2i.imag, afi.imag, ttrqi.imag, wtrqi.imag] # 16
op2_file.write(struct2.pack(*data))
ielement += 1
icount = 0
else:
raise RuntimeError('CBEAM OEF op2 writer')
#data = [0, xxb, sxc, sxd, sxe, sxf, smax, smin, smt, smc] # 10
#op2_file.write(struct2.pack(*data))
#icount += 1
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 ComplexCBendForceArray(BaseElement): # 69-CBEND
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
BaseElement.__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 is_sort1:
#pass
#else:
#raise NotImplementedError('SORT2')
@property
def is_real(self) -> bool:
"""is the result real?"""
return False
@property
def is_complex(self) -> bool:
"""is the result complex?"""
return True
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexCBendForceArray"""
#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))
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element_node = zeros((self.nelements, 3), dtype='int32')
#[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((self.ntimes, self.nelements, 12), dtype='complex64')
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Freq 0.0 2.5
#ElementID Item
#6901 bending_moment_1a 1.066567-0.035549j 1.066996-0.035577j
# bending_moment_2a 1.101375-0.036709j 1.102188-0.036763j
# shear_1a 0.516478-0.017214j 0.516842-0.017239j
# shear_2a 0.859292-0.028640j 0.860111-0.028695j
# axial_a 0.834822-0.027825j 0.834982-0.027835j
# torque_a 0.953420-0.031777j 0.953947-0.031813j
# bending_moment_1b -0.284733+0.009490j -0.284828+0.009497j
# bending_moment_2b 0.094127-0.003137j 0.093836-0.003118j
# shear_1b 0.834822-0.027825j 0.834982-0.027835j
# shear_2b 0.859292-0.028640j 0.860111-0.028695j
# axial_b -0.516478+0.017214j -0.516842+0.017239j
# torque_b -0.242082+0.008069j -0.242077+0.008068j
#6902 bending_moment_1a -0.931214+0.031037j -0.931519+0.031058j
headers = self.get_headers()
column_names, column_values = self._build_dataframe_transient_header()
# element_node is (nelements, 3)
element = self.element_node[:, 0]
self.data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, element, self.data)
def __eq__(self, table): # pragma: no cover
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_nodes.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 allclose(t1, t2):
msg += '(%s) (%s, %s) (%s, %s)\n' % (
eid,
bending_moment_1a1.real,
bending_moment_1b1.real,
bending_moment_1a2.real,
bending_moment_1b2.real, )
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#if not allclose(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
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)
#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._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
[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'
msg.append(' eType\n')
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(' 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 = []
#' C O M P L E X 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 )'
#' (REAL/IMAGINARY)'
#' - BENDING MOMENTS - - SHEARS - AXIAL'
#' ELEMENT-ID GRID END PLANE 1 PLANE 2 PLANE 1 PLANE 2 FORCE TORQUE'
#'0 27 21 A 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 22 B 0.0 0.0 0.0 0.0 0.0 0.0'
#' 0.0 0.0 0.0 0.0 0.0 0.0'
msg_temp = self.get_f06_header(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
# 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]
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_1ari, bending_moment_2ari, shear_1ari, shear_2ari, axial_ari, torque_ari,
bending_moment_1bri, bending_moment_2bri, shear_1bri, shear_2bri, axial_bri, torque_bri,
bending_moment_1aii, bending_moment_2aii, shear_1aii, shear_2aii, axial_aii, torque_aii,
bending_moment_1bii, bending_moment_2bii, shear_1bii, shear_2bii, axial_bii, torque_bii,
] = write_imag_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],
is_mag_phase)
f06_file.write(
'0 %8s%8s A %13s %13s %13s %13s %13s %s\n'
' %13s %13s %13s %13s %13s %s\n'
'0 %8s%8s B %13s %13s %13s %13s %13s %s\n'
' %13s %13s %13s %13s %13s %s\n'
% (
eid, nid_ai,
bending_moment_1ari, bending_moment_2ari, shear_1ari, shear_2ari, axial_ari, torque_ari,
bending_moment_1aii, bending_moment_2aii, shear_1aii, shear_2aii, axial_aii, torque_aii,
'', nid_bi,
bending_moment_1bri, bending_moment_2bri, shear_1bri, shear_2bri, axial_bri, torque_bri,
bending_moment_1bii, bending_moment_2bii, shear_1bii, shear_2bii, axial_bii, torque_bii,))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num - 1
[docs]
class ComplexSolidPressureForceArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
self.element_type = None
self.element_name = None
ComplexForceObject.__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 is_sort1:
pass
else:
raise NotImplementedError('SORT2')
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 ComplexSolidPressureForceArray"""
#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))
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(self.ntimes, dtype=self.analysis_fmt)
self.element = zeros(self.nelements, dtype=idtype)
#[ax, ay, az, vx, vy, vz, pressure]
self.data = zeros((self.ntimes, self.ntotal, 7), dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Mode 1 2
#EigenvalueReal -0.000000 -0.000000
#EigenvalueImag -0.000000 -0.000000
#Damping 0.000000 0.000000
#ElementID Item
#1000 ax -1.887379e-13+2.791559e-13j -1.901257e-13+2.789015e-13j
# ay 3.330669e-14-7.316397e-14j 1.776357e-14-7.368508e-14j
# az -1.360023e-13-9.545406e-14j -1.432188e-13-8.333307e-14j
# vx 0.000000e+00+0.000000e+00j 0.000000e+00+0.000000e+00j
# vy 0.000000e+00+0.000000e+00j 0.000000e+00+0.000000e+00j
# vz 0.000000e+00+0.000000e+00j 0.000000e+00+0.000000e+00j
# pressure 0.000000e+00+0.000000e+00j 0.000000e+00+0.000000e+00j
headers = self.get_headers()
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
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
#rpressure1 = pressure1.real
#rpressure2 = pressure2.real
if not allclose([ax1, ay1, az1, vx1, vy1, vz1],
[ax2, ay2, az2, vx2, vy2, vz2]):
msg += '%s (%s, %s) (%s, %s)\n' % (
eid,
ax1.real, t1.imag,
ax2.real, t2.imag)
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, ename, 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
[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'
msg.append(' eType\n')
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(' element type: %s\n' % self.element_type)
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
return msg
#def get_element_index(self, eids):
## elements are always sorted; nodes are not
#itot = searchsorted(eids, self.element) #[0]
#return itot
#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(is_mag_phase=is_mag_phase, is_sort1=is_sort1)
# write the f06
#(ntimes, ntotal, two) = self.data.shape
ntimes = self.data.shape[0]
eids = self.element
#print('len(eids)=%s nwrite=%s is_odd=%s' % (len(eids), nwrite, is_odd))
etypei = self.element_type
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)))
ax = self.data[itime, :, 0]
ay = self.data[itime, :, 0]
az = self.data[itime, :, 0]
vx = self.data[itime, :, 0]
vy = self.data[itime, :, 0]
vz = self.data[itime, :, 0]
pressure = self.data[itime, :, 0]
for eid, axi, ayi, azi, vxi, vyi, vzi, pressurei in zip(eids, ax, ay, az, vx, vy, vz, pressure):
out = write_imag_floats_13e([axi, ayi, azi, vxi, vyi, vzi, pressurei], is_mag_phase)
[saxr, sayr, sazr, svxr, svyr, svzr, spressurer,
saxi, sayi, sazi, svxi, svyi, svzi, spressurei] = out
#' 1000 HEXPR 1.582050E-08 5.505425E+06 2.598164E-09 -8.884337E-10 -4.806934E+04 1.046571E-10 9.968034E+01'
#' -1.116439E-08 -6.040572E+05 1.315160E-09 -1.258955E-09 -4.381078E+05 -2.067553E-10'
f06_file.write(' %8i %8s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %8s %8s %-13s %-13s %-13s %-13s %-13s %s\n\n'
% (eid, etypei, saxr, sayr, sazr, svxr, svyr, svzr, spressurer,
'', '', saxi, sayi, sazi, svxi, svyi, svzi))
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
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
if self.is_sort1:
struct1 = Struct(endian + b'i 8s13f')
else:
raise NotImplementedError('SORT2')
op2_ascii.write(f'nelements={nelements:d}\n')
etypei = self.element_type
if etypei == 76:
ename = b'HEXPR'
elif etypei == 77:
ename = b'PENPR'
elif etypei == 78:
ename = b'TETPR'
else:
raise NotImplementedError(self)
#etypeb = self.element_type#.encode('ascii')
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')
ax = self.data[itime, :, 0]
ay = self.data[itime, :, 0]
az = self.data[itime, :, 0]
vx = self.data[itime, :, 0]
vy = self.data[itime, :, 0]
vz = self.data[itime, :, 0]
pressure = self.data[itime, :, 0]
for eid, eid_device, axi, ayi, azi, vxi, vyi, vzi, pressurei in zip(
eids, eids_device, ax, ay, az, vx, vy, vz, pressure):
out = write_imag_floats_13e([axi, ayi, azi, vxi, vyi, vzi, pressurei], is_mag_phase)
[saxr, sayr, sazr, svxr, svyr, svzr, spressurer,
saxi, sayi, sazi, svxi, svyi, svzi, spressurei] = out
#' 1000 HEXPR 1.582050E-08 5.505425E+06 2.598164E-09 -8.884337E-10 -4.806934E+04 1.046571E-10 9.968034E+01'
#' -1.116439E-08 -6.040572E+05 1.315160E-09 -1.258955E-09 -4.381078E+05 -2.067553E-10'
data = [
eid_device, ename,
axi.real, ayi.real, azi.real, vxi.real, vyi.real, vzi.real, pressurei.real,
axi.imag, ayi.imag, azi.imag, vxi.imag, vyi.imag, vzi.imag,
]
op2_ascii.write(' %8i %8s %-13s %-13s %-13s %-13s %-13s %-13s %s\n'
' %8s %8s %-13s %-13s %-13s %-13s %-13s %s\n\n'
% (eid, etypei, saxr, sayr, sazr, svxr, svyr, svzr, spressurer,
'', '', saxi, sayi, sazi, svxi, svyi, svzi))
op2_file.write(struct1.pack(*data))
#for eid, eid_device, fxi, fyi, fzi, mxi, myi, mzi in zip(eids, eids_device, fx, fy, fz, mx, my, mz):
#data = [
#eid_device,
#fxi.real, fyi.real, fzi.real, mxi.real, myi.real, mzi.real,
#fxi.imag, fyi.imag, fzi.imag, mxi.imag, myi.imag, mzi.imag,
#]
#vals = (fxi, fyi, fzi, mxi, myi, mzi)
#vals2 = write_imag_floats_13e(vals, is_mag_phase)
#(fxir, fyir, fzir, mxir, myir, mzir,
#fxii, fyii, fzii, mxii, myii, mzii) = vals2
#op2_ascii.write('0%26i %-13s %-13s %-13s %-13s %-13s %s\n'
#' %26s %-13s %-13s %-13s %-13s %-13s %s\n' % (
#eid, fxir, fyir, fzir, mxir, myir, mzir,
#'', fxii, fyii, fzii, mxii, myii, mzii))
#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 ComplexForceMomentArray(ComplexForceObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexForceObject.__init__(self, data_code, isubcase)
self.result_flag = 0
#self.code = [self.format_code, self.sort_code, self.s_code]
#self.ntimes = 0 # or frequency/mode
#self.ntotal = 0
self.itime = 0
self.nelements = 0 # result specific
@property
def is_real(self) -> bool:
return False
@property
def is_complex(self) -> bool:
return True
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs]
def build(self):
"""sizes the vectorized attributes of the ComplexCBushForceArray"""
#print('ntimes=%s nelements=%s ntotal=%s subtitle=%s' % (
#self.ntimes, self.nelements, self.ntotal, self.subtitle))
if self.is_built:
return
nnodes = 1
#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))
if self.is_sort1:
ntimes = self.ntimes
ntotal = self.ntotal
#print(f'CBUSH SORT1: ntimes={ntimes} ntotal={ntotal}')
else:
ntimes = self.ntotal
ntotal = self.ntimes
#print(f'CBUSH SORT2: ntimes={ntimes} ntotal={ntotal}')
idtype, cfdtype = get_complex_times_dtype(self.size)
self._times = zeros(ntimes, dtype=self.analysis_fmt)
self.element = zeros(ntotal, dtype=idtype)
# the number is messed up because of the offset for the element's properties
if 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)
raise RuntimeError(msg)
#[fx, fy, fz, mx, my, mz]
self.data = zeros((ntimes, ntotal, 6), dtype=cfdtype)
[docs]
def build_dataframe(self):
"""creates a pandas dataframe"""
#Freq 10.0
#ElementID Item
#123 fx 10000.000000+0.000021j
# fy 1000.000000+0.000002j
# fz 100.000000+0.000000j
# mx 7000.000000+0.000000j
# my 700.000000+0.000000j
# mz 70.000000+0.000000j
headers = self.get_headers()
column_names, column_values = self._build_dataframe_transient_header()
self.data_frame = self._build_pandas_transient_elements(
column_values, column_names,
headers, self.element, self.data)
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, :]
(tx1, ty1, tz1, rx1, ry1, rz1) = t1
(tx2, ty2, tz2, rx2, ry2, rz2) = t2
d = t1 - t2
if not allclose([tx1.real, tx1.imag, ty1.real, ty1.imag],
[tx2.real, tx2.imag, ty2.real, ty2.imag], atol=0.0001):
#if not np.array_equal(t1, t2):
msg += '%-4s (%s, %sj, %s, %sj)\n (%s, %sj, %s, %sj)\n dt12=(%s, %sj, %s, %sj)\n' % (
eid,
tx1.real, tx1.imag, ty1.real, ty1.imag,
tx2.real, tx2.imag, ty2.real, ty2.imag,
d[0].real, d[0].imag, d[1].real, d[1].imag,)
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)
#[fx, fy, fz, mx, my, mz]
self._times[self.itime] = dt
self.data[self.itime, self.itotal, :] = [fx, fy, fz, mx, my, mz]
self.element[self.itotal] = eid
self.itotal += 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)
#[fx, fy, fz, mx, my, mz]
itime = self.itotal
itotal = self.itime
#print(itime, itotal, dt, eid)
self._times[itime] = dt
self.data[itime, itotal, :] = [fx, fy, fz, mx, my, mz]
self.element[itotal] = eid
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))
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, 6] where 6=[%s]\n' % str(', '.join(self.get_headers())))
msg.append(f' data.shape = {self.data.shape}\n')
# msg.append(' is_sort1=%s is_sort2=%s\n' % (self.is_sort1, self.is_sort2))
msg.append(f' {self.element_name}\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 = []
if is_mag_phase:
mag_phase = ' (MAGNITUDE/PHASE)\n\n'
else:
mag_phase = ' (REAL/IMAGINARY)\n\n'
name = self.data_code['name']
if name == 'freq':
name = 'FREQUENCY'
elif name == 'mode':
name = 'MODE'
else:
raise RuntimeError(name)
# is_sort1 = True
if is_sort1:
line2 = ' ID. FORCE-X FORCE-Y FORCE-Z MOMENT-X MOMENT-Y MOMENT-Z \n'
else:
line2 = ' %26s FORCE-X FORCE-Y FORCE-Z MOMENT-X MOMENT-Y MOMENT-Z \n' % name
# force
words = self._words()
msg_temp = header + [
words,
mag_phase,
' ',
# line1,
line2,
]
if self.is_sort1:
if is_sort1:
page_num = self._write_sort1_as_sort1(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
else:
page_num = self._write_sort1_as_sort2(f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase)
else:
assert self.is_sort1 == True, str(self)
return page_num - 1
def _write_sort1_as_sort1(self, f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase):
ntimes = self.data.shape[0]
eids = self.element
for itime in range(ntimes):
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))
#fx, fy, fz, mx, my, mz
if self.is_sort1:
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]
else:
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):
vals = (fxi, fyi, fzi, mxi, myi, mzi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(fxir, fyir, fzir, mxir, myir, mzir,
fxii, fyii, fzii, mxii, myii, mzii) = vals2
f06_file.write('0%26i %-13s %-13s %-13s %-13s %-13s %s\n'
' %26s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, fxir, fyir, fzir, mxir, myir, mzir,
'', fxii, fyii, fzii, mxii, myii, mzii))
f06_file.write(page_stamp % page_num)
page_num += 1
return page_num
def _write_sort1_as_sort2(self, f06_file, page_num, page_stamp, header, msg_temp, is_mag_phase):
eids = self.element
times = self._times
for ieid, eid in enumerate(eids):
eid_line = ' ELEMENT-ID = %s' % (eid)
header[1] = eid_line
msg = header + msg_temp
f06_file.write(''.join(msg))
if self.is_sort1:
fx = self.data[:, ieid, 0]
fy = self.data[:, ieid, 1]
fz = self.data[:, ieid, 2]
mx = self.data[:, ieid, 3]
my = self.data[:, ieid, 4]
mz = self.data[:, ieid, 5]
else:
raise RuntimeError()
for dt, fxi, fyi, fzi, mxi, myi, mzi in zip(times, fx, fy, fz, mx, my, mz):
vals = (fxi, fyi, fzi, mxi, myi, mzi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(fxir, fyir, fzir, mxir, myir, mzir,
fxii, fyii, fzii, mxii, myii, mzii) = vals2
f06_file.write('0%26s %-13s %-13s %-13s %-13s %-13s %s\n'
' %26s %-13s %-13s %-13s %-13s %-13s %s\n' % (
write_float_12e(dt),
fxir, fyir, fzir, mxir, myir, mzir,
'', fxii, fyii, fzii, mxii, myii, mzii))
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"""
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
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
eids_device = self.element * 10 + self.device_code
if self.is_sort1:
struct1 = Struct(endian + b'i 12f')
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
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, eid_device, fxi, fyi, fzi, mxi, myi, mzi in zip(eids, eids_device, fx, fy, fz, mx, my, mz):
data = [
eid_device,
fxi.real, fyi.real, fzi.real, mxi.real, myi.real, mzi.real,
fxi.imag, fyi.imag, fzi.imag, mxi.imag, myi.imag, mzi.imag,
]
vals = (fxi, fyi, fzi, mxi, myi, mzi)
vals2 = write_imag_floats_13e(vals, is_mag_phase)
(fxir, fyir, fzir, mxir, myir, mzir,
fxii, fyii, fzii, mxii, myii, mzii) = vals2
op2_ascii.write('0%26i %-13s %-13s %-13s %-13s %-13s %s\n'
' %26s %-13s %-13s %-13s %-13s %-13s %s\n' % (
eid, fxir, fyir, fzir, mxir, myir, mzir,
'', fxii, fyii, fzii, mxii, myii, mzii))
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) -> str:
return ''
[docs]
class ComplexCBushForceArray(ComplexForceMomentArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
#self.element_type = 'CBUSH'
def _words(self) -> str:
words = ' C O M P L E X F O R C E S I N B U S H E L E M E N T S ( C B U S H ) \n'
return words
[docs]
class ComplexCFastForceArrayMSC(ComplexForceMomentArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
#self.element_type = 'CFAST'
#def _words(self) -> str:
#words = ' C O M P L E X F O R C E S I N B U S H E L E M E N T S ( C B U S H ) \n'
#return words
[docs]
class ComplexCBearForceArray(ComplexForceMomentArray):
def __init__(self, data_code, is_sort1, isubcase, dt):
ComplexForceMomentArray.__init__(self, data_code, is_sort1, isubcase, dt)
#self.element_type = 'CBEAR'
#def _words(self) -> str:
#words = ' C O M P L E X F O R C E S I N B U S H E L E M E N T S ( C B E A R ) \n'
#return words