# pylint: disable=C0301,C0103,R0913,R0914,R0904,C0111,R0201,R0902
from itertools import count
from struct import Struct, pack
from typing import Tuple, List, Any
import numpy as np
from numpy import zeros, where, searchsorted
from numpy.linalg import eigh # type: ignore
from pyNastran.utils.numpy_utils import integer_types, float_types
from pyNastran.f06.f06_formatting import write_floats_13e, _eigenvalue_header
from pyNastran.op2.result_objects.op2_objects import get_times_dtype
from pyNastran.op2.tables.oes_stressStrain.real.oes_objects import StressObject, StrainObject, OES_Object
from pyNastran.op2.op2_interface.write_utils import to_column_bytes
[docs]class RealSolidArray(OES_Object):
def __init__(self, data_code, is_sort1, isubcase, dt):
OES_Object.__init__(self, data_code, isubcase, apply_data_code=False)
#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:
##sort1
#self.add_node = self.add_node_sort1
#self.add_eid = self.add_eid_sort1
#else:
#raise NotImplementedError('SORT2')
@property
def is_real(self) -> bool:
return True
@property
def is_complex(self) -> bool:
return False
def _reset_indices(self) -> None:
self.itotal = 0
self.ielement = 0
[docs] def update_data_components(self):
# vm
oxx = self.data[:, :, 0]
oyy = self.data[:, :, 1]
ozz = self.data[:, :, 2]
txy = self.data[:, :, 3]
tyz = self.data[:, :, 4]
txz = self.data[:, :, 5]
#I1 = oxx + oyy + ozz
#txyz = txy**2 + tyz**2 + txz ** 2
#I2 = oxx * oyy + oyy * ozz + ozz * oxx - txyz
#I3 = oxx * oyy * ozz + 2 * txy * tyz * txz + oxx * tyz**2 - oyy * txz**2 - ozz * txy
# (n_subarrays, nrows, ncols)
ovm = np.sqrt((oxx - oyy)**2 + (oyy - ozz)**2 + (oxx - ozz)**2 +
3. * (txy**2 + tyz**2 + txz ** 2))
self.data[:, :, 9] = ovm
#A = [[doxx, dtxy, dtxz],
#[dtxy, doyy, dtyz],
#[dtxz, dtyz, dozz]]
#(_lambda, v) = eigh(A) # a hermitian matrix is a symmetric-real matrix
def __iadd__(self, factor):
"""[A] += b"""
#[oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, ovmShear]
if isinstance(factor, float_types):
self.data[:, :, :6] += factor
else:
# TODO: should support arrays
raise TypeError('factor=%s and must be a float' % (factor))
self.update_data_components()
def __isub__(self, factor):
"""[A] -= b"""
if isinstance(factor, float_types):
self.data[:, :, :6] -= factor
else:
# TODO: should support arrays
raise TypeError('factor=%s and must be a float' % (factor))
self.update_data_components()
def __imul__(self, factor):
"""[A] *= b"""
assert isinstance(factor, float_types), 'factor=%s and must be a float' % (factor)
self.data[:, :, :6] *= factor
self.update_data_components()
def __idiv__(self, factor):
"""[A] *= b"""
assert isinstance(factor, float_types), 'factor=%s and must be a float' % (factor)
self.data[:, :, :6] *= 1. / factor
self.update_data_components()
[docs] def build(self):
"""sizes the vectorized attributes of the RealSolidArray"""
#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
self.is_built = True
#print("ntimes=%s nelements=%s ntotal=%s" % (self.ntimes, self.nelements, self.ntotal))
dtype, idtype, fdtype = get_times_dtype(self.nonlinear_factor, self.size, self.analysis_fmt)
_times = zeros(self.ntimes, dtype=dtype)
# TODO: could be more efficient by using nelements for cid
element_node = zeros((self.ntotal, 2), dtype=idtype)
element_cid = zeros((self.nelements, 2), dtype=idtype)
#if self.element_name == 'CTETRA':
#nnodes = 4
#elif self.element_name == 'CPENTA':
#nnodes = 6
#elif self.element_name == 'CHEXA':
#nnodes = 8
#self.element_node = zeros((self.ntotal, nnodes, 2), 'int32')
#[oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, ovmShear]
data = zeros((self.ntimes, self.ntotal, 10), fdtype)
self.nnodes = element_node.shape[0] // self.nelements
#self.data = zeros((self.ntimes, self.nelements, nnodes+1, 10), 'float32')
if self.load_as_h5:
#for key, value in sorted(self.data_code.items()):
#print(key, value)
group = self._get_result_group()
self._times = group.create_dataset('_times', data=_times)
self.element_node = group.create_dataset('element_node', data=element_node)
self.element_cid = group.create_dataset('element_cid', data=element_cid)
self.data = group.create_dataset('data', data=data)
else:
self._times = _times
self.element_node = element_node
self.element_cid = element_cid
self.data = data
[docs] def build_dataframe(self):
"""creates a pandas dataframe"""
import pandas as pd
headers = self.get_headers()
# TODO: cid?
#element_node = [self.element_node[:, 0], self.element_node[:, 1]]
if self.nonlinear_factor not in (None, np.nan):
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)
#self.data_frame = pd.Panel(self.data, items=column_values, major_axis=element_node, minor_axis=headers).to_frame()
#self.data_frame.columns.names = column_names
#self.data_frame.index.names = ['ElementID', 'NodeID', 'Item']
else:
# Static sxc sxd sxe sxf smax smin MS_tension MS_compression
# ElementID NodeID
# 12 22 0.0 0.0 0.0 0.0 0.0 0.0 1.401298e-45 1.401298e-45
# 26 0.0 0.0 0.0 0.0 0.0 0.0 1.401298e-45 1.401298e-45
index = pd.MultiIndex.from_arrays(self.element_node.T, names=['ElementID', 'NodeID'])
data_frame = pd.DataFrame(self.data[0], columns=headers, index=index)
data_frame.columns.names = ['Static']
self.data_frame = data_frame
[docs] def add_eid_sort1(self, unused_etype, cid, dt, eid, unused_node_id,
oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3,
unused_acos, unused_bcos, unused_ccos, unused_pressure, ovm):
# See the CHEXA, CPENTA, or CTETRA entry for the definition of the element coordinate systems.
# The material coordinate system (CORDM) may be the basic system (0 or blank), any defined system
# (Integer > 0), or the standard internal coordinate system of the element designated as:
# -1: element coordinate system (-1)
# -2: element system based on eigenvalue techniques to insure non bias in the element formulation(-2).
# C:\MSC.Software\msc_nastran_runs\ecs-2-rg.op2
assert cid >= -2, cid
assert eid >= 0, eid
#print "dt=%s eid=%s eType=%s" %(dt,eid,eType)
self._times[self.itime] = dt
self.element_node[self.itotal, :] = [eid, 0] # 0 is center
omax_mid_min = [o1, o2, o3]
omin = min(omax_mid_min)
omax_mid_min.remove(omin)
omax = max(omax_mid_min)
omax_mid_min.remove(omax)
omid = omax_mid_min[0]
self.data[self.itime, self.itotal, :] = [oxx, oyy, ozz, txy, tyz, txz, omax, omid, omin, ovm]
#self.data[self.itime, self.ielement, 0, :] = [oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, ovm]
#print('element_cid[%i, :] = [%s, %s]' % (self.ielement, eid, cid))
if self.ielement == self.nelements:
self.ielement = 0
self.element_cid[self.ielement, :] = [eid, cid]
self.itotal += 1
self.ielement += 1
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 ieid, eid_nid in enumerate(self.element_node):
(eid, nid) = eid_nid
t1 = self.data[itime, ieid, :]
t2 = table.data[itime, ieid, :]
(oxx1, oyy1, ozz1, txy1, tyz1, txz1, o11, o21, o31, ovm1) = t1
(oxx2, oyy2, ozz2, txy2, tyz2, txz2, o12, o22, o32, ovm2) = t2
if not np.array_equal(t1, t2):
msg += (
'(%s, %s) (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n'
'%s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n' % (
eid, nid,
oxx1, oyy1, ozz1, txy1, tyz1, txz1, o11, o21, o31, ovm1,
' ' * (len(str(eid)) + len(str(nid)) + 2),
oxx2, oyy2, ozz2, txy2, tyz2, txz2, o12, o22, o32, ovm2))
i += 1
if i > 10:
print(msg)
raise ValueError(msg)
#print(msg)
if i > 0:
raise ValueError(msg)
return True
[docs] def add_node_sort1(self, dt, eid, unused_inode, node_id,
oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3,
unused_acos, unused_bcos, unused_ccos, unused_pressure, ovm):
# skipping aCos, bCos, cCos, pressure
omax_mid_min = [o1, o2, o3]
omin = min(omax_mid_min)
omax_mid_min.remove(omin)
omax = max(omax_mid_min)
omax_mid_min.remove(omax)
omid = omax_mid_min[0]
self.data[self.itime, self.itotal, :] = [oxx, oyy, ozz, txy, tyz, txz, omax, omid, omin, ovm]
#print('data[%s, %s, :] = %s' % (self.itime, self.itotal, str(self.data[self.itime, self.itotal, :])))
#self.data[self.itime, self.ielement-1, self.inode, :] = [oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, ovm]
#print('eid=%i node_id=%i exx=%s' % (eid, node_id, str(oxx)))
self.element_node[self.itotal, :] = [eid, node_id]
#self.element_node[self.ielement-1, self.inode-1, :] = [eid, node_id]
self.itotal += 1
@property
def nnodes_per_element(self) -> int:
return self.nnodes_per_element_no_centroid + 1
@property
def nnodes_per_element_no_centroid(self) -> int:
if self.element_type == 39: # CTETRA
nnodes = 4
elif self.element_type == 67: # CHEXA
nnodes = 8
elif self.element_type == 68: # CPENTA
nnodes = 6
elif self.element_type == 255: # CPYRAM
nnodes = 5
else:
raise NotImplementedError(f'element_name={self.element_name} self.element_type={self.element_type}')
return nnodes
[docs] def get_stats(self, short: bool=False) -> List[str]:
if not self.is_built:
return [
'<%s>\n' % self.__class__.__name__,
f' ntimes: {self.ntimes:d}\n',
f' ntotal: {self.ntotal:d}\n',
]
nelements = self.nelements
ntimes = self.ntimes
#ntotal = self.ntotal
try:
nnodes_per_element = self.element_node.shape[0] // nelements
except ZeroDivisionError:
nnodes_per_element = '???'
nnodes = self.element_node.shape[0]
msg = []
if self.nonlinear_factor not in (None, np.nan): # transient
msg.append(' type=%s ntimes=%i nelements=%i nnodes=%i\n nnodes_per_element=%s (including centroid)\n'
% (self.__class__.__name__, ntimes, nelements, nnodes, nnodes_per_element))
ntimes_word = 'ntimes'
else:
msg.append(' type=%s nelements=%i nnodes=%i\n nodes_per_element=%i (including centroid)\n'
% (self.__class__.__name__, nelements, nnodes, nnodes_per_element))
ntimes_word = '1'
msg.append(' eType, cid\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(' element_node.shape = %s\n' % str(self.element_node.shape).replace('L', ''))
msg.append(' element_cid.shape = %s\n' % str(self.element_cid.shape).replace('L', ''))
msg.append(f' data.shape = {self.data.shape}\n')
msg.append(' element name: %s\n' % self.element_name)
msg += self.get_data_code()
#print(''.join(msg))
return msg
[docs] def get_element_index(self, eids):
# elements are always sorted; nodes are not
itot = searchsorted(eids, self.element_node[:, 0]) #[0]
return itot
[docs] def eid_to_element_node_index(self, eids):
#ind = ravel([searchsorted(self.element_node[:, 0] == eid) for eid in eids])
ind = searchsorted(eids, self.element_node[:, 0])
#ind = ind.reshape(ind.size)
#ind.sort()
return ind
[docs] def write_f06(self, f06_file, header=None, page_stamp='PAGE %s', page_num=1, is_mag_phase=False, is_sort1=True):
if header is None:
header = []
nnodes, msg_temp = _get_f06_header_nnodes(self, is_mag_phase)
# write the f06
ntimes = self.data.shape[0]
eids2 = self.element_node[:, 0]
nodes = self.element_node[:, 1]
eids3 = self.element_cid[:, 0]
cids3 = self.element_cid[:, 1]
for itime in range(ntimes):
dt = self._times[itime]
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)))
oxx = self.data[itime, :, 0]
oyy = self.data[itime, :, 1]
ozz = self.data[itime, :, 2]
txy = self.data[itime, :, 3]
tyz = self.data[itime, :, 4]
txz = self.data[itime, :, 5]
o1 = self.data[itime, :, 6]
o2 = self.data[itime, :, 7]
o3 = self.data[itime, :, 8]
ovm = self.data[itime, :, 9]
p = (o1 + o2 + o3) / -3.
cnnodes = nnodes + 1
for i, deid, node_id, doxx, doyy, dozz, dtxy, dtyz, dtxz, do1, do2, do3, dp, dovm in zip(
count(), eids2, nodes, oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, p, ovm):
j = where(eids3 == deid)[0][0]
cid = cids3[j]
A = [[doxx, dtxy, dtxz],
[dtxy, doyy, dtyz],
[dtxz, dtyz, dozz]]
(_lambda, v) = eigh(A) # a hermitian matrix is a symmetric-real matrix
# o1-max
# o2-mid
# o3-min
assert do1 >= do2 >= do3, 'o1 >= o2 >= o3; eid=%s o1=%e o2=%e o3=%e' % (deid, do1, do2, do3)
[oxxi, oyyi, ozzi, txyi, tyzi, txzi, o1i, o2i, o3i, pi, ovmi] = write_floats_13e(
[doxx, doyy, dozz, dtxy, dtyz, dtxz, do1, do2, do3, dp, dovm])
if i % cnnodes == 0:
f06_file.write('0 %8s %8iGRID CS %i GP\n' % (deid, cid, nnodes))
f06_file.write(
'0 %8s X %-13s XY %-13s A %-13s LX%5.2f%5.2f%5.2f %-13s %s\n'
' %8s Y %-13s YZ %-13s B %-13s LY%5.2f%5.2f%5.2f\n'
' %8s Z %-13s ZX %-13s C %-13s LZ%5.2f%5.2f%5.2f\n'
% ('CENTER', oxxi, txyi, o1i, v[0, 1], v[0, 2], v[0, 0], pi, ovmi,
'', oyyi, tyzi, o2i, v[1, 1], v[1, 2], v[1, 0],
'', ozzi, txzi, o3i, v[2, 1], v[2, 2], v[2, 0]))
else:
f06_file.write(
'0 %8s X %-13s XY %-13s A %-13s LX%5.2f%5.2f%5.2f %-13s %s\n'
' %8s Y %-13s YZ %-13s B %-13s LY%5.2f%5.2f%5.2f\n'
' %8s Z %-13s ZX %-13s C %-13s LZ%5.2f%5.2f%5.2f\n'
% (node_id, oxxi, txyi, o1i, v[0, 1], v[0, 2], v[0, 0], pi, ovmi,
'', oyyi, tyzi, o2i, v[1, 1], v[1, 2], v[1, 0],
'', ozzi, txzi, o3i, v[2, 1], v[2, 2], v[2, 0]))
i += 1
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
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:
#print('***************', itable)
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)
nnodes_expected = self.nnodes
eids2 = self.element_node[:, 0]
nodes = self.element_node[:, 1]
nelements_nodes = len(nodes)
eids3 = self.element_cid[:, 0]
cids3 = self.element_cid[:, 1]
element_device = eids3 * 10 + self.device_code
# table 4 info
#ntimes = self.data.shape[0]
nnodes = self.data.shape[1]
nelements = len(np.unique(eids2))
#if len(ueids2) == 1 and len(eids3) != 1:
#raise RuntimeError(f'SORT2: ueids2={ueids2}')
# 21 = 1 node, 3 principal, 6 components, 9 vectors, 2 p/ovm
#ntotal = ((nnodes * 21) + 1) + (nelements * 4)
nnodes_expected = self.nnodes_per_element_no_centroid
ntotali = 4 + 21 * nnodes_expected
ntotali = self.num_wide
ntotal = ntotali * nelements
#print('shape = %s' % str(self.data.shape))
assert nnodes > 1, nnodes
#assert self.ntimes == 1, self.ntimes
#device_code = self.device_code
op2_ascii.write(f' ntimes = {self.ntimes}\n')
#fmt = '%2i %6f'
#print('ntotal=%s' % (ntotal))
#assert ntotal == 193, ntotal
if self.is_sort1:
#op2_format = endian + b'2i6f'
struct1 = Struct(endian + b'ii4si')
struct2 = Struct(endian + b'i20f')
else:
raise NotImplementedError('SORT2')
cen = b'GRID'
op2_ascii.write(f'nelements={nelements:d}\n')
for itime in range(self.ntimes):
self._write_table_3(op2_file, op2_ascii, new_result, itable, itime)
# record 4
#print('stress itable = %s' % itable)
itable -= 1
header = [4, itable, 4,
4, 1, 4,
4, 0, 4,
4, ntotal, 4,
4 * ntotal]
op2_file.write(pack('%ii' % len(header), *header))
op2_ascii.write('r4 [4, 0, 4]\n')
op2_ascii.write(f'r4 [4, {itable:d}, 4]\n')
op2_ascii.write(f'r4 [4, {4 * ntotal:d}, 4]\n')
oxx = self.data[itime, :, 0]
oyy = self.data[itime, :, 1]
ozz = self.data[itime, :, 2]
txy = self.data[itime, :, 3]
tyz = self.data[itime, :, 4]
txz = self.data[itime, :, 5]
o1 = self.data[itime, :, 6]
o2 = self.data[itime, :, 7]
o3 = self.data[itime, :, 8]
ovm = self.data[itime, :, 9]
p = (o1 + o2 + o3) / -3.
#print('eids3', eids3)
cnnodes = nnodes_expected + 1
for i, deid, node_id, doxx, doyy, dozz, dtxy, dtyz, dtxz, do1, do2, do3, dp, dovm in zip(
count(), eids2, nodes, oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, p, ovm):
#print(' eid =', deid, node_id)
j = where(eids3 == deid)[0]
assert len(j) > 0, j
cid = cids3[j][0]
A = [[doxx, dtxy, dtxz],
[dtxy, doyy, dtyz],
[dtxz, dtyz, dozz]]
(_lambda, v) = eigh(A) # a hermitian matrix is a symmetric-real matrix
#node_id, oxxi, txyi, o1i, v[0, 1], v[0, 2], v[0, 0], pi, ovmi,
#'', oyyi, tyzi, o2i, v[1, 1], v[1, 2], v[1, 0],
#'', ozzi, txzi, o3i, v[2, 1], v[2, 2], v[2, 0]
#(grid_device, sxx, sxy, s1, a1, a2, a3, pressure, svm,
#syy, syz, s2, b1, b2, b3,
#szz, sxz, s3, c1, c2, c3)
if i % cnnodes == 0:
data = [deid * 10 + self.device_code, cid, cen, nnodes_expected]
op2_ascii.write(' eid=%s cid=%s cen=%s nnodes = %s\n' % tuple(data))
op2_file.write(
struct1.pack(*data)
#pack(b'2i 4s i', *data)
)
#else:
op2_ascii.write(' nid=%i\n' % node_id)
data = [node_id,
doxx, dtxy, do1, v[0, 1], v[0, 2], v[0, 0], dp, dovm,
doyy, dtyz, do2, v[1, 1], v[1, 2], v[1, 0],
dozz, dtxz, do3, v[2, 1], v[2, 2], v[2, 0], ]
op2_ascii.write(' oxx, txy, o1, v01, v02, v00, p, ovm = %s\n' % data[1:8])
op2_ascii.write(' oyy, tyz, o2, v11, v12, v10 = %s\n' % data[8:14])
op2_ascii.write(' ozz, txz, o3, v21, v22, v20 = %s\n' % data[14:])
op2_file.write(struct2.pack(*data))
i += 1
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 RealSolidStressArray(RealSolidArray, StressObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealSolidArray.__init__(self, data_code, is_sort1, isubcase, dt)
StressObject.__init__(self, data_code, isubcase)
[docs]class RealSolidStrainArray(RealSolidArray, StrainObject):
def __init__(self, data_code, is_sort1, isubcase, dt):
RealSolidArray.__init__(self, data_code, is_sort1, isubcase, dt)
StrainObject.__init__(self, data_code, isubcase)
def _get_solid_msgs(self: RealSolidArray):
if self.is_von_mises:
von_mises = 'VON MISES'
else:
von_mises = 'MAX SHEAR'
if self.is_stress:
base_msg = [
'0 CORNER ------CENTER AND CORNER POINT STRESSES--------- DIR. COSINES MEAN \n',
' ELEMENT-ID GRID-ID NORMAL SHEAR PRINCIPAL -A- -B- -C- PRESSURE %s \n' % von_mises]
tetra_msg = [' S T R E S S E S I N T E T R A H E D R O N S O L I D E L E M E N T S ( C T E T R A )\n', ]
penta_msg = [' S T R E S S E S I N P E N T A H E D R O N S O L I D E L E M E N T S ( P E N T A )\n', ]
hexa_msg = [' S T R E S S E S I N H E X A H E D R O N S O L I D E L E M E N T S ( H E X A )\n', ]
pyram_msg = [' S T R E S S E S I N P Y R A M I D S O L I D E L E M E N T S ( P Y R A M )\n', ]
else:
base_msg = [
'0 CORNER ------CENTER AND CORNER POINT STRAINS--------- DIR. COSINES MEAN \n',
' ELEMENT-ID GRID-ID NORMAL SHEAR PRINCIPAL -A- -B- -C- PRESSURE %s \n' % von_mises]
tetra_msg = [' S T R A I N S I N T E T R A H E D R O N S O L I D E L E M E N T S ( C T E T R A )\n', ]
penta_msg = [' S T R A I N S I N P E N T A H E D R O N S O L I D E L E M E N T S ( P E N T A )\n', ]
hexa_msg = [' S T R A I N S I N H E X A H E D R O N S O L I D E L E M E N T S ( H E X A )\n', ]
pyram_msg = [' S T R A I N S I N P Y R A M I D S O L I D E L E M E N T S ( P Y R A M )\n', ]
tetra_msg += base_msg
penta_msg += base_msg
hexa_msg += base_msg
return tetra_msg, penta_msg, hexa_msg, pyram_msg
def _get_f06_header_nnodes(self: RealSolidArray, is_mag_phase=True):
tetra_msg, penta_msg, hexa_msg, pyram_msg = _get_solid_msgs(self)
if self.element_type == 39: # CTETRA
msg = tetra_msg
nnodes = 4
elif self.element_type == 67: # CHEXA
msg = hexa_msg
nnodes = 8
elif self.element_type == 68: # CPENTA
msg = penta_msg
nnodes = 6
elif self.element_type == 255: # CPYRAM
msg = pyram_msg
nnodes = 5
else: # pragma: no cover
msg = f'element_name={self.element_name} self.element_type={self.element_type}'
raise NotImplementedError(msg)
return nnodes, msg