Source code for pyNastran.op2.tables.geom.ept

"""
defines readers for BDF objects in the OP2 EPT/EPTS table
"""
#pylint: disable=C0103,R0914
from __future__ import annotations
from struct import unpack, Struct
from functools import partial
from typing import TYPE_CHECKING

import numpy as np

#from pyNastran import is_release
from pyNastran.bdf.errors import UnsupportedCard
from pyNastran.bdf.cards.properties.mass import PMASS, NSM, NSML
from pyNastran.bdf.cards.properties.bars import PBAR, PBARL, PBEND, PBEAM3
from pyNastran.bdf.cards.properties.beam import PBEAM, PBEAML, PBCOMP
from pyNastran.bdf.cards.properties.bush import PBUSH, PBUSHT
from pyNastran.bdf.cards.properties.damper import PDAMP, PVISC
from pyNastran.bdf.cards.properties.properties import PFAST, PGAP
from pyNastran.bdf.cards.properties.rods import PROD, PTUBE
from pyNastran.bdf.cards.properties.shell import PSHEAR, PSHELL, PCOMP
from pyNastran.bdf.cards.properties.solid import PSOLID
from pyNastran.bdf.cards.properties.springs import PELAS, PELAST

from pyNastran.bdf.cards.thermal.thermal import PCONV, PHBDY, PCONVM
# PCOMPG, PBUSH1D, PBEAML, PBEAM3
from pyNastran.op2.op2_interface.op2_reader import (
    mapfmt, reshape_bytes_block_size) # reshape_bytes_block,
from .utils import get_minus1_start_end
from .geom2 import DoubleCardError
if TYPE_CHECKING:  # pragma: no cover
    from pyNastran.op2.op2_geom import OP2Geom


[docs] class EPT: """defines methods for reading op2 properties""" @property def size(self) -> int: return self.op2.size @property def factor(self) -> int: return self.op2.factor def _read_fake(self, data: bytes, n: int) -> int: return self.op2._read_fake(data, n)
[docs] def read_stop(self, data: bytes, n: int) -> int: return self.op2.reader_geom1.read_stop(data, n)
[docs] def read_ept_4(self, data: bytes, ndata: int): return self.op2._read_geom_4(self.ept_map, data, ndata)
def __init__(self, op2: OP2Geom): self.op2 = op2 self.ept_map = { (3201, 32, 55): ['NSM', self.read_nsm], # record 2 (52, 20, 181): ['PBAR', self.read_pbar], # record 11 - buggy (9102, 91, 52): ['PBARL', self.read_pbarl], # record 12 - almost there... (2706, 27, 287): ['PCOMP', self.read_pcomp], # record 22 - buggy (302, 3, 46): ['PELAS', self.read_pelas], # record 39 (2102, 21, 121): ['PGAP', self.read_pgap], # record 42 (902, 9, 29): ['PROD', self.read_prod], # record 49 (1002, 10, 42): ['PSHEAR', self.read_pshear], # record 50 (2402, 24, 281): ['PSOLID', self.read_psolid], # record 51 (15202, 152, 709): ['PCOMPLS', self.read_pcompls], (2302, 23, 283): ['PSHELL', self.read_pshell], # record 52 (1602, 16, 30): ['PTUBE', self.read_ptube], # record 56 (5402, 54, 262): ['PBEAM', self.read_pbeam], # record 14 - not done (9202, 92, 53): ['PBEAML', self.read_pbeaml], # record 15 (2502, 25, 248): ['PBEND', self.read_pbend], # record 16 - not done (1402, 14, 37): ['PBUSH', self.read_pbush], # record 19 - not done (3101, 31, 219): ['PBUSH1D', self.read_pbush1d], # record 20 - not done (152, 19, 147): ['PCONEAX', self.read_pconeax], # record 24 - not done (11001, 110, 411): ['PCONV', self.read_pconv], # record 25 - not done # record 26 (202, 2, 45): ['PDAMP', self.read_pdamp], # record 27 - not done (2802, 28, 236): ['PHBDY', self.read_phbdy], # record 43 - not done (402, 4, 44): ['PMASS', self.read_pmass], # record 48 (1802, 18, 31): ['PVISC', self.read_pvisc], # record 59 (10201, 102, 400): ['PVAL', self.read_pval], # record 58 - not done (2606, 26, 289): ['VIEW', self.read_view], # record 62 - not done (3201, 32, 991) : ['NSM', self.read_nsm_2], # record (3301, 33, 992) : ['NSM1', self.read_nsm1], # record (3701, 37, 995) : ['NSML1', self.read_nsml1_nx], # record (3601, 36, 62): ['NSML1', self.read_nsml1_msc], # record 7 (15006, 150, 604): ['PCOMPG', self.read_pcompg], # record (702, 7, 38): ['PBUSHT', self.read_pbusht], # record 1 (3301, 33, 56): ['NSM1', self._read_fake], # record 3 (3401, 34, 57) : ['NSMADD', self._read_fake], # record 5 (3501, 35, 58): ['NSML', self._read_fake], # record 6 (3501, 35, 994) : ['NSML', self.read_nsml], (1502, 15, 36): ['PAABSF', self.read_paabaf], # record 8 (8300, 83, 382): ['PACABS', self._read_fake], # record 9 (8500, 85, 384): ['PACBAR', self._read_fake], # record 10 (5403, 55, 349): ['PBCOMP', self.read_pbcomp], # record 13 (13301, 133, 509): ['PBMSECT', self._read_fake], # record 17 (2902, 29, 420): ['PCONVM', self.read_pconvm], # record 26 (1202, 12, 33): ['PDAMPT', self.read_pdampt], # record 28 (8702, 87, 412): ['PDAMP5', self.read_pdamp5], # record 29 (6802, 68, 164): ['PDUM8', self._read_fake], # record 37 (6902, 69, 165): ['PDUM9', self._read_fake], # record 38 (1302, 13, 34): ['PELAST', self.read_pelast], # record 41 (12001, 120, 480): ['PINTC', self._read_fake], # record 44 (12101, 121, 484): ['PINTS', self._read_fake], # record 45 (4606, 46, 375): ['PLPLANE', self.read_plplane], # record 46 (4706, 47, 376): ['PLSOLID', self.read_plsolid], # record 47 (10301, 103, 399): ['PSET', self.read_pset], # record 57 (3002, 30, 415): ['VIEW3D', self.read_view3d], # record 63 (13501, 135, 510) : ['PFAST', self.read_pfast_msc], # MSC-specific (3601, 36, 55) : ['PFAST', self.read_pfast_nx], # NX-specific (3801, 38, 979) : ['PPLANE', self.read_pplane], (11801, 118, 560) : ['PWELD', self._read_fake], (3401, 34, 993) : ['NSMADD', self.read_nsmadd], (9300, 93, 684) : ['ELAR', self._read_fake], (9400, 94, 685) : ['ELAR2', self._read_fake], (16006, 160, 903) : ['PCOMPS', self.read_pcomps], # MSC-specific (14602, 146, 692): ['PSLDN1', self._read_fake], (16502, 165, 916): ['PAXSYMH', self.read_paxsymh], (13201, 132, 513): ['PBRSECT', self._read_fake], (13701, 137, 638): ['PWSEAM', self._read_fake], (7001, 70, 632): ['PMIC', self.read_pmic], (15106, 151, 953): ['PCOMPG1', self.read_pcompg1], (3901, 39, 969): ['PSHL3D', self._read_fake], (17006, 170, 901): ['MATCID', self.read_matcid], (9601, 96, 691): ['PJOINT', self._read_fake], (8901, 89, 905): ['PSOLCZ', self.read_psolcz], (9701, 97, 692): ['PJOINT2', self._read_fake], (9801, 98, 698): ['DESC', self.read_desc], (12901, 129, 989): ['PDISTB', self._read_fake], (13401, 134, 611): ['PBEAM3', self.read_pbeam3], (17302, 173, 971): ['PCOMPFQ', self._read_fake], (14101, 141, 668): ['PSEAM', self._read_fake], (14402, 144, 690): ['PSHLN1', self._read_fake], (16902, 169, 955): ['???', self._read_fake], (17502, 175, 973): ['PFASTT', self._read_fake], #(9701, 97, 692): ['???', self._read_fake], (13601, 136, 636): ['PBUSH2D', self.read_pbush2d], } def _add_op2_property(self, prop): """helper method for op2""" op2: OP2Geom = self.op2 #if prop.pid > 100000000: #raise RuntimeError('bad parsing; pid > 100000000...%s' % str(prop)) #print(str(prop)[:-1]) ntables = op2.table_names.count(b'EPT') + op2.table_names.count(b'EPTS') pid = prop.pid allow_overwrites = ( ntables > 1 and pid in op2.properties and op2.properties[pid].type == prop.type) op2._add_methods._add_property_object(prop, allow_overwrites=allow_overwrites) def _add_op2_property_mass(self, prop): """helper method for op2""" op2: OP2Geom = self.op2 #if prop.pid > 100000000: #raise RuntimeError('bad parsing; pid > 100000000...%s' % str(prop)) #print(str(prop)[:-1]) ntables = op2.table_names.count(b'EPT') + op2.table_names.count(b'EPTS') pid = prop.pid allow_overwrites = ( ntables > 1 and pid in op2.properties_mass and op2.properties_mass[pid].type == prop.type) op2._add_methods._add_property_mass_object(prop, allow_overwrites=allow_overwrites) def _add_pconv(self, prop: PCONV) -> None: if prop.pconid > 100000000: raise RuntimeError('bad parsing pconid > 100000000...%s' % str(prop)) self.op2._add_methods._add_convection_property_object(prop) # HGSUPPR
[docs] def read_matcid(self, data: bytes, n: int) -> None: """ MATCID(17006,170,901) Defines material coordinate system for solid elements. Word Name Type Description 1 CID I Material coordinate system identification number 2 SPECOPT I Specification option SPECOPT=1 Select individual element identification numbers 3 EID I Element identification number Word 3 repeats until -1 occurs SPECOPT=2 Select all element identification numbers 3 ALL(2) CHAR4 Keyword for selecting ALL option Words 3 repeats until -1 occurs SPECOPT=3 Select element identification numbers using a THRU range without the BY option 3 EID I Element identification number 4 THRU(2) CHAR4 Keyword for selecting THRU option 6 EID I Element identification number Words 3 through 5 repeat until -1 occurs SPECOPT=4 Select element identification numbers using a THRU range with the BY option 3 EID I Element identification number 4 THRU(2) CHAR4 Keyword for selecting THRU option 6 EID I Element identification number 7 BY(2) CHAR4 Keyword for selecting BY option 9 N I Element selection increment Words 3 through 9 repeat until -1 occurs """ self.op2.log.warning('geom skipping MATCID in EPT') return len(data)
[docs] def read_psolcz(self, data: bytes, n: int) -> None: """ PSOLCZ(8901,89,905) Word Name Type Description 1 PID I Property identification number 2 MID I Material identification number 3 CORDM I Material coordinate system identification number 4 THICK RS Thickness of cohesive element 5 UNDEF(4) """ op2: OP2Geom = self.op2 size = self.size ntotal = 8 * size struct1 = Struct(mapfmt(op2._endian + b'3if 4i', size)) ndatai = len(data) - n nentries = ndatai // ntotal assert ndatai % ntotal == 0 for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) pid, mid, cordm, thick, undef1, undef2, undef3, undef4 = out assert (undef1, undef2, undef3, undef4) == (0, 0, 0, 0) #op2.add_solcz n += ntotal self.op2.log.warning('geom skipping PSOLCZ in EPT') op2.card_count['PSOLCZ'] = nentries return n
[docs] def read_pcompg1(self, data: bytes, n: int) -> None: """ PCOMPG1(15106,151,953) Word Name Type Description 1 PID I Property identification number 2 Z0 RS Distance from the reference plane to the bottom surface 3 NSM RS Nonstructural mass per unit area 4 SB RS Allowable shear stress of the bonding material 5 UNDEF None 6 TREF RS Reference temperature 7 GE RS Damping coefficient 8 UNDEF None 9 GPLYIDi I Global ply identification number 10 MID I Material identification number 11 T RS Thicknesses of the ply 12 THETA RS Orientation angle of the longitudinal direction of the ply 13 FT I Failure theory 14 SOUT I Stress or strain output request of the ply 15 UNDEF None Words 9 through 15 repeat until (-1,-1,-1,-1,-1,-1,-1) occurs PCOMPG1 PID Z0 NSM SB N/A TREF GE GPLYIDi MIDi TRi THETAi FTi N/A SOUTi PCOMPG1 1 0.0 20.0 0.0 + + 1 1 0.4 0.0 STRN YES + """ op2: OP2Geom = self.op2 size = self.size #op2.to_nx(' because PCOMP-64 was found') nproperties = 0 s1 = Struct(mapfmt(op2._endian + b'i7f', size)) ntotal1 = 8 * size s2 = Struct(mapfmt(op2._endian + b'2i2f2i i', size)) seven_minus1 = Struct(mapfmt(op2._endian + b'7i', size)) ndata = len(data) ntotal2 = 7 * size #props = [] while n < (ndata - ntotal1): out = s1.unpack(data[n:n+ntotal1]) (pid, z0, nsm, sb, undef1, tref, ge, undef2) = out assert (undef1, undef2) == (0, 0) assert pid > 0 #if op2.binary_debug: #op2.binary_debug.write(f'PCOMP pid={pid} nlayers={nlayers} ' #f'sb={sb} Tref={tref} ge={ge}') print(f'PCOMP pid={pid} z0={z0} nsm={nsm} ' f'sb={sb} tref={tref} ge={ge}') n += ntotal1 global_ply_ids = [] mids = [] thicknesses = [] thetas = [] souts = [] failure_theories = [] #op2.show_data(data[n:], types='dqs') edata2 = data[n:n+ntotal2] #idata = seven_minus1.unpack(edata2) idata = (2, ) while idata != (-1, -1, -1, -1, -1, -1, -1): out = s2.unpack(edata2) (global_ply_id, mid, t, theta, ft_int, sout_int, junk) = out #print(out) #HILL for the Hill failure theory. #HOFF for the Hoffman failure theory. #TSAI for the Tsai-Wu failure theory. #4-STRN for the Maximum Strain failure theory. if ft_int == 0: ft = None elif ft_int == 4: ft = 'STRN' else: # pragma: no cover raise NotImplementedError(ft_int) if sout_int == 0: sout = 'NO' elif sout_int == 1: sout = 'YES' else: # pragma: no cover raise NotImplementedError(sout_int) global_ply_ids.append(global_ply_id) mids.append(mid) thicknesses.append(t) thetas.append(theta) souts.append(sout) failure_theories.append(ft) if op2.is_debug_file: op2.binary_debug.write(f' mid={mid} t={t} theta={theta} sout={sout}\n') n += ntotal2 #print(f' mid={mid} t={t} theta={theta} sout={sout}') if n == ndata: op2.log.warning(' no (-1, -1, -1, -1, -1, -1, -1) flag was found to close the PCOMPG1s') break # NX #C:\MSC.Software\simcenter_nastran_2019.2\tpl_post2\c402cmpg8lgm.op2 n += 8 # TODO: random 0 flag??? edata2 = data[n:n+ntotal2] idata = seven_minus1.unpack(edata2) #print(idata) nlayers = len(mids) assert nlayers > 0, nlayers #if size == 4: #assert 0 < nlayers < 400, 'pid=%s nlayers=%s sb=%s ft=%s Tref=%s ge=%s' % ( #pid, nlayers, sb, ft, tref, ge) #else: #assert nlayers == 0, nlayers #nlayers = len(mids) #prop = PCOMP.add_op2_data(data_in) #op2.add_pcompg1 nproperties += 1 n += ntotal2 #props.append(prop) op2.card_count['PCOMPG1'] = nproperties return n
[docs] def read_pcomps(self, data: bytes, n: int) -> None: """ PCOMPS(16006,160,903) Defines the properties of an n-ply composite material laminate for solid elements. Word Name Type Description 1 PID I Property identification number 2 CORDM I Material coordinate system identification number 3 PSDIR I Stack and ply directions in the material coordinate system 4 SB RS Allowable shear stress of the bonding material 5 NB RS Allowable normal stress of the bonding material 6 TREF RS Reference temperature 7 GE RS Damping coefficient 8 UNDEF None 9 GPLYIDi I Global ply identification number 10 MID I Material identification number 11 TR RS Thicknesses of the ply 12 THETA RS Orientation angle of the longitudinal direction of the ply 13 FT I Failure theory 14 ILFT I Inter-laminar failure theory 15 SOUT I Stress or strain output request of the ply 16 TFLAG I Flag of ABS or REL Words 9 through 16 repeat until (-1,-1,-1,-1,-1,-1,-1,-1) occurs """ op2: OP2Geom = self.op2 size = self.size #op2.to_nx(' because PCOMP-64 was found') nproperties = 0 s1 = Struct(mapfmt(op2._endian + b'3i 4fi', size)) ntotal1 = 8 * size s2 = Struct(mapfmt(op2._endian + b'2i 2f 4i', size)) eight_minus1 = Struct(mapfmt(op2._endian + b'8i', size)) ndata = len(data) ntotal2 = 8 * self.size #props = [] while n < (ndata - ntotal1): out = s1.unpack(data[n:n+ntotal1]) (pid, cordm, psdir, sb, nb, tref, ge, undef) = out assert pid > 0 #if op2.binary_debug: #op2.binary_debug.write(f'PCOMP pid={pid} nlayers={nlayers} ' #f'sb={sb} Tref={tref} ge={ge}') #print(f'PCOMP pid={pid} nlayers={nlayers} z0={z0} nsm={nsm} ' #f'sb={sb} ft={ft} Tref={tref} ge={ge}') n += ntotal1 global_ply_ids = [] mids = [] thicknesses = [] thetas = [] souts = [] failure_theories = [] interlaminar_failure_theories = [] tflags = [] edata2 = data[n:n+ntotal2] idata = eight_minus1.unpack(edata2) while idata != (-1, -1, -1, -1, -1, -1, -1, -1): (global_ply_id, mid, t, theta, fti, lam_fti, souti, tflagi) = s2.unpack(edata2) #1-HILL for the Hill failure theory. #2-HOFF for the Hoffman failure theory. #3-TSAI for the Tsai-Wu failure theory. #4-STRN for the Maximum Strain failure theory. #5-STRS for the Maximum Stress failure theory. #6-TS for the Maximum Transverse Shear Stress failure theory. # # #9-PFA for progressive ply failure. See Remark 6. #0-(Character; Default = No failure theory). Not supported if fti == 0: ft = None elif fti == 1: ft = 'HILL' elif fti == 2: ft = 'HOFF' elif fti == 3: ft = 'TSAI' elif fti == 4: ft = 'STRN' elif fti == 5: ft = 'STRS' elif fti == 6: ft = 'TS' elif fti == 9: ft = 'PFA' else: # pragma: no cover self.log.error(f'PCOMPS pid={pid} global_ply_id={global_ply_id} mid={mid} t={t:g} ' f'theta={theta} fti={fti} lam_ft={lam_fti} sout={souti} tflag={tflagi}') raise NotImplementedError(fti) #SB for transverse shear stress failure index. #NB for normal stress failure index. #(Character; Default = No failure index) if lam_fti == 0: lam_ft = None elif lam_fti == 7: lam_ft = 'SB' elif lam_fti == 8: lam_ft = 'NB' else: # pragma: no cover raise NotImplementedError(lam_fti) if souti == 0: sout = 'NO' elif souti == 1: sout = 'YES' else: # pragma: no cover raise NotImplementedError(sout) if tflagi == 0: tflag = 'ABS' else: # pragma: no cover raise NotImplementedError(tflagi) #print(f'global_ply_id={global_ply_id} mid={mid} t={t:g} theta={theta} fti={ft} lam_ft={lam_ft} sout={sout} tflag={tflag}') global_ply_ids.append(global_ply_id) mids.append(mid) thicknesses.append(t) thetas.append(theta) souts.append(sout) failure_theories.append(ft) interlaminar_failure_theories.append(lam_ft) tflags.append(tflag) # flag of ABS/REL if op2.is_debug_file: op2.binary_debug.write(f' mid={mid} t={t} theta={theta} sout={sout}\n') n += ntotal2 #print(f' mid={mid} t={t} theta={theta} sout={sout}') edata2 = data[n:n+ntotal2] if n == ndata: op2.log.warning(' no (-1, -1, -1, -1, -1, -1, -1, -1) flag was found to close the PCOMPSs') break idata = eight_minus1.unpack(edata2) nlayers = len(mids) #if size == 4: #assert 0 < nlayers < 400, 'pid=%s nlayers=%s sb=%s ft=%s Tref=%s ge=%s' % ( #pid, nlayers, sb, ft, tref, ge) #else: #assert nlayers == 0, nlayers #nlayers = len(mids) #prop = PCOMP.add_op2_data(data_in) assert psdir in [12, 13, 21, 23, 31, 32], psdir del tflags op2.add_pcomps(pid, global_ply_ids, mids, thicknesses, thetas, cordm=cordm, psdir=psdir, sb=sb, nb=nb, tref=tref, ge=ge, failure_theories=failure_theories, interlaminar_failure_theories=interlaminar_failure_theories, souts=souts, comment='') nproperties += 1 n += ntotal2 #props.append(prop) op2.card_count['PCOMPS'] = nproperties return n
[docs] def read_paabaf(self, data: bytes, n: int) -> None: """ PAABSF(1502,15,36) Defines the properties of a frequency-dependent acoustic absorber Word Name Type Description 1 PID I Property identification number 2 TZREID I TABLEDi entry identification number for resistance 3 TZMID I TABLEDi entry identification number for reactance 4 S RS Impedance scale factor 5 A RS Area factor when only 1 or 2 grid points are specified 6 B RS Equivalent structural damping 7 K RS Equivalent stiffness 8 RHOC RS Constant used for absorption coefficient """ op2: OP2Geom = self.op2 size = self.size #op2.log.info(f'geom skipping PAABSF in {op2.table_name}; ndata={len(data)-12}') #op2.show_data(data[n:], types='ifs') ntotal = 8 * size # 8*4 struct1 = Struct(mapfmt(op2._endian + b'3i 5f', size)) nentries = (len(data) - n) // ntotal for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) pid, tzreid, tzimid, s, a, b, k, rhoc = out op2.add_paabsf(pid, tzreid=tzreid, tzimid=tzimid, s=s, a=a, b=b, k=k, rhoc=rhoc) n += ntotal op2.card_count['PAABSF'] = nentries return n
[docs] def read_paxsymh(self, data: bytes, n: int) -> None: op2: OP2Geom = self.op2 op2.log.info(f'geom skipping PAXSYMH in {op2.table_name}; ndata={len(data)-12}') #op2.show_data(data[n:], types='ifs') return len(data)
[docs] def read_desc(self, data: bytes, n: int) -> int: """ RECORD – DESC(9801,98,698) Word Name Type Description 1 DID I Description identification number 2 NWORDS I Number of words for the description string 3 DESC CHAR4 Description Words 3 repeats NWORDS times data = (1, 14, 'FACE CONTACT(1) ') """ op2: OP2Geom = self.op2 assert self.size == 4, 'DESC size={self.size} is not supported' #op2.show_data(data[n:], types='ifs') struct_2i = Struct(op2._endian + b'2i') while n < len(data): datai = data[n:n+8] desc_id, nwords = struct_2i.unpack(datai) ndatai = 8 + nwords * 4 word_bytes = data[n+8:n+ndatai] word = word_bytes.decode('ascii').rstrip() assert len(word_bytes) == nwords * 4 #print('word_bytes =', word_bytes) op2.log.warning(f'geom skipping DESC={desc_id}: {word!r}') n += ndatai assert n == len(data), n return n
[docs] def read_nsml(self, data: bytes, n: int) -> int: """ NX 2019.2 RECORD – NSML(3501, 35, 994) Defines a set of lumped nonstructural mass by ID. Word Name Type Description 1 SID I Set identification number 2 PROP(2) CHAR4 Set of properties or elements 4 ID I Property of element identification number 5 VALUE RS Lumped nonstructural mass value Words 4 and 5 repeat until -1 occurs ints = (3, ELEMENT, 0, 200, 0.7, -1, 4, PSHELL, 0, 6401, 4.2, -1) floats = (3, ELEMENT, 0.0, 200, 0.7, -1, 4, PSHELL, 0.0, 6401, 4.2, -1) """ op2: OP2Geom = self.op2 n0 = n #op2.show_data(data[n:]) ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() istart, iend = get_minus1_start_end(ints) ncards = 0 size = self.size for (i0, i1) in zip(istart, iend): #data = (4, ELEMENT, 2.1, 1, 3301, -1, -2) assert ints[i1] == -1, ints[i1] sid = ints[i0] prop_bytes = data[n0+(i0+1)*size:n0+(i0+3)*size] #print(sid, prop_bytes) ids = ints[i0+4:i1:2].tolist() values = floats[i0+5:i1:2].tolist() #print(ids, values) assert len(ids) == len(values) nsm_type = prop_bytes.decode('latin1').rstrip() nsml = op2.add_nsml(sid, nsm_type, ids, values) #print(nsml) str(nsml) n += (i1 - i0 + 1) * size ncards += 1 op2.card_count['NSML'] = ncards return n
[docs] def read_nsmadd(self, data: bytes, n: int) -> int: """ NX 2019.2 (3401, 34, 993) RECORD – NSMADD(3401,34,993) Combines the nonstructural mass inputs. Word Name Type Description 1 SID I Set identification number 2 ID I Set of properties or elements Word 2 repeats until End of Record (1, 2, 3, 4, -1) """ op2: OP2Geom = self.op2 ints = np.frombuffer(data[n:], op2.idtype8).copy() istart, iend = get_minus1_start_end(ints) ncards = 0 istart = [0] + list(iend + 1) size = self.size for (i0, i1) in zip(istart, iend): assert ints[i1] == -1, ints[i1] sid, *nsms = ints[i0:i1] nsmadd = op2.add_nsmadd(sid, nsms) #print(nsmadd) str(nsmadd) n += (i1 - i0 + 1) * size ncards += 1 op2.card_count['NSMADD'] = ncards return n
[docs] def read_nsml1_nx(self, data: bytes, n: int) -> int: """ NSML1(3701, 37, 995) Alternate form of NSML entry. Defines lumped nonstructural mass entries by VALUE, ID list. Word Name Type Description 1 SID I Set identification number 2 PROP CHAR4 Set of properties 3 TYPE CHAR4 Set of elements 4 VALUE RS Lumped nonstructural mass value 5 SPECOPT I Specification option SPECOPT=1 By IDs 6 ID I Property of element identification number Word 6 repeats until -1 occurs SPECOPT=2 All 6 ALL(2) CHAR4 Keyword ALL Words 6 and 7 repeat until -1 occurs SPECOPT=3 Thru range 6 ID1 I Starting identification number 7 THRU(2) CHAR4 Keyword THRU 9 ID2 I Ending identification number Words 6 through 9 repeat until -1 occurs SPECOPT=4 Thru range with by 6 ID1 I Starting identification number 7 THRU(2) CHAR4 Keyword THRU 9 ID2 I Ending identification number 10 BY(2) CHAR4 Keyword BY 12 N I Increment Words 6 through 12 repeat until -1 occurs data = ( 3701, 37, 995, 1, ELEMENT, 466.2, 3, 249311, THRU, 250189, -1, 3, 250656, THRU, 251905, -1, 3, 270705, THRU, 275998, -1, 3, 332687, THRU, 334734, -1, -2, 2, ELEMENT, 77.7, 3, 225740, THRU 227065, -1, 3, 227602, THRU, 228898, -1, 3, 229435, THRU, 230743, -1, 3, 231280, THRU, 233789, -1, 3, 233922, THRU, 235132, -1, 3, 235265, THRU, 236463, -1, 3, 338071, THRU, 341134, -1, -2) """ #ints = (1, ELEMENT, 466.2, # 3, 249311, THRU, 250189, -1, # 3, 250656, THRU, 251905, -1, # 3, 270705, THRU, 275998, -1, # 3, 332687, THRU, 334734, -1, # -2, # # 2, ELEMENT, 77.7, # 3, 225740, THRU 227065, -1, # 3, 227602, THRU, 228898, -1, # 3, 229435, THRU, 230743, -1, # 3, 231280, THRU, 233789, -1, # 3, 233922, THRU, 235132, -1, # 3, 235265, THRU, 236463, -1, # 3, 338071, THRU, 341134, -1, -2) op2: OP2Geom = self.op2 n0 = n #op2.show_data(data[n:]) ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() iminus2 = np.where(ints == -2)[0] istart = [0] + list(iminus2[:-1] + 1) iend = iminus2 #print(istart, iend) assert len(data[n:]) > 12, data[n:] #op2.show_data(data[n:], types='ifs') ncards = 0 istart = [0] + list(iend + 1) size = self.size for (i0, i1) in zip(istart, iend): #data = (4, ELEMENT, 2.1, 1, 3301, -1, -2) assert ints[i1] == -2, ints[i1] sid = ints[i0] nsm_type = data[n0+(i0+1)*size:n0+(i0+2)*size].decode('latin1').rstrip() value = float(floats[i0+3]) #print(f'sid={sid} nsm_type={nsm_type} value={value}') iminus1 = i0 + np.where(ints[i0:i1] == -1)[0] #print('-1', iminus1) #print('-2', iminus2) istart2 = [i0 + 4] + list(iminus1[:-1] + 1) iend2 = iminus1 #print(istart2, iend2) for istarti, iendi in zip(istart2, iend2): #print(istarti, iendi) spec_opt = ints[istarti] # 4 #print(f'ints[{istarti}] = spec_opt = {spec_opt}') if spec_opt == 1: # 6 ID I Property of element identification number ivalues = list(range(istarti, iendi)) #print('ivalues =', ivalues) pid_eids = ints[ivalues].tolist() #print('pid_eids =', pid_eids) elif spec_opt == 3: # datai = (3, 249311, 'THRU ', 250189) #print(f'i0={i0}') #datai = data[n0+(i0+6)*size:n0+i1*size] #op2.show_data(datai) ids = ints[istarti:iendi] istart = ids[1] iend = ids[-1] pid_eids = list(range(istart, iend+1)) else: raise NotImplementedError(spec_opt) if nsm_type == 'ELEM': nsm_type = 'ELEMENT' #for pid_eid in pid_eids: #nsml = op2.add_nsml1(sid, nsm_type, pid_eids, [value]) assert len(pid_eids) > 0, pid_eids nsml1 = op2.add_nsml1(sid, nsm_type, value, pid_eids) #print(nsml1) str(nsml1) n += (i1 - i0 + 1) * size ncards += 1 op2.card_count['NSML'] = ncards return n
[docs] def read_nsml1_msc(self, data: bytes, n: int) -> int: r""" NSML1(3601, 36, 62) Word Name Type Description 1 SID I Set identification number 2 PROP CHAR4 Set of property or elements 3 VALUE RS Lumped nonstructural mass value 4 SPECOPT I Specification option SPECOPT=1 By IDs 5 IDs , =FLG1LIST in ixidlst.prm 6 ID I Property or element ID Word 6 repeats until End of Record SPECOPT=2 means ALL, =FLG1ALL in ixidlst.prm 5 ALL(2) CHAR4 Keyword ALL Words 5 through 6 repeat until End of Record SPECOPT=3 means THRU range, =FLG1THRU in ixidlst.prm 5 ID1 I Starting ID 6 THRU(2) CHAR4 Keyword THRU 8 ID2 I Ending ID Words 5 through 8 repeat until End of Record SPECOPT=4 means THRU range with BY, =FLG1THBY in ixidlst.prm 5 ID1 I Starting ID 6 THRU(2) CHAR4 Keyword THRU 8 ID2 I Ending ID 9 BY(2) CHAR4 Keyword BY 11 N I Increment Words 5 through 11 repeat until End of Record End SPECOPT Words 4 through max repeat until End of Record C:\MSC.Software\simcenter_nastran_2019.2\tpl_post2\elsum15.op2 data = (4, ELEMENT, 2.1, 1, 3301, -1, -2) """ op2: OP2Geom = self.op2 op2.log.info(f'geom skipping NSML1 in {op2.table_name}; ndata={len(data)-12}') #op2.show_data(data[n:], types='ifs') #bbb return len(data)
[docs] def read_nsm1(self, data: bytes, n: int) -> int: """ NSM1(3301, 33, 992) Defines the properties of a nonstructural mass. Word Name Type Description 1 SID I Set identification number 2 PROP CHAR4 Set of properties 3 TYPE CHAR4 Set of elements 4 ORIGIN I Entry origin 5 VALUE RS Nonstructural mass value 6 SPECOPT I Specification option SPECOPT=1 By IDs 7 ID I Word 7 repeats until -1 occurs SPECOPT=2 All 7 ALL(2) CHAR4 Words 7 and 8 repeat until -1 occurs SPECOPT=3 Thru range 7 ID I 8 THRU(2) CHAR4 10 ID I Words 7 through 10 repeat until -1 occurs SPECOPT=4 Thru range with by 7 ID I 8 THRU(2) CHAR4 10 ID I 11 BY(2) CHAR4 13 N I Words 7 through 13 repeat until -1 occurs data = (3, PCOMP, 0, 0.37, 2, ALL, -1, 4, ELEMENT, 2, 2.1, 1, 3301, -1) """ op2: OP2Geom = self.op2 #op2.show_data(data[n:], types='ifs') n0 = n #op2.show_data(data[n:]) ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() istart, iend = get_minus1_start_end(ints) ncards = 0 size = self.size for (i0, i1) in zip(istart, iend): assert ints[i1] == -1, ints[i1] # 1 SID I Set identification number sid = ints[i0] # 2 PROP CHAR4 Set of properties # 3 TYPE CHAR4 Set of elements # 4 ORIGIN I Entry origin # 5 VALUE RS Nonstructural mass value # 6 SPECOPT I Specification option nsm_type = data[n0+(i0+1)*size:n0+(i0+3)*size].decode('latin1').rstrip() zero_two = ints[i0+3] value = float(floats[i0+4]) spec_opt = ints[i0+5] assert zero_two in [0, 2], zero_two #nii = 6 #print(ints[i0+nii:i1]) #print(floats[i0+nii:i1]) #print(sid, nsm_type, value, spec_opt) iminus1 = i0 + np.where(ints[i0:i1] == -1)[0] #print('-1', iminus1) #print('-2', iminus2) istart2 = [i0 + 5] + list(iminus1[:-1] + 1) iend2 = iminus1 #print(istart2, iend2) if spec_opt == 1: # 7 ID I ids = ints[i0+6:i1] elif spec_opt == 2: word = data[n0+(i0+6)*size:n0+i1*size] ids = word elif spec_opt == 3: # thru # datai = (249311, 'THRU ', 250189) #datai = data[n0+(i0+6)*size:n0+i1*size] ids = ints[i0+6:i1] istart = ids[0] iend = ids[-1] ids = list(range(istart, iend+1)) else: raise NotImplementedError(spec_opt) #print(sid, nsm_type, zero_two, value, ids) #if nsm_type == 'ELEM': #nsm_type = 'ELEMENT' #for pid_eid in pid_eids: #nsml = self.add_nsml1(sid, nsm_type, pid_eids, [value]) nsm1 = op2.add_nsm1(sid, nsm_type, value, ids) #print(nsm1) str(nsm1) n += (i1 - i0 + 1) * size ncards += 1 op2.card_count['NSM1'] = ncards return n
[docs] def read_nsm(self, data: bytes, n: int) -> int: """NSM""" op2: OP2Geom = self.op2 n = op2.reader_geom2._read_dual_card( data, n, self._read_nsm_nx, self._read_nsm_msc, 'NSM', op2._add_methods._add_nsm_object) return n
[docs] def read_nsm_2(self, data: bytes, n: int) -> int: """ NX 2019.2 NSM(3201, 32, 991) RECORD – NSM(3201,32,991) Defines the properties of a nonstructural mass. Word Name Type Description 1 SID I Set identification number 2 PROP CHAR4 Set of properties 3 TYPE CHAR4 Set of elements <---- not right...it's an integer and not used... 4 ID I Property or element identification number 5 VALUE RS Nonstructural mass value Words 5 through 6 repeat until End of Record NSM,2,conrod,1007,0.3 data = (2, CONROD, 0, 1007, 0.3, -1, 2, ELEMENT, 0, 200, 0.20, -1, 3, PSHELL, 0, 3301, 0.20, -1, 3, ELEMENT, 2, 200, 1.0, -1, 4, PSHELL, 2, 6401, 4.2, -1) """ op2: OP2Geom = self.op2 n0 = n ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() istart, iend = get_minus1_start_end(ints) ncards = 0 size = self.size for (i0, i1) in zip(istart, iend): #data = (4, ELEMENT, 2.1, 1, 3301, -1, -2) assert ints[i1] == -1, ints[i1] sid = ints[i0] prop_type = data[n0+(i0+1)*size:n0+(i0+3)*size] elem_type = data[n0+(i0+3)*size:n0+(i0+4)*size] nsm_type = prop_type.decode('latin1').rstrip() dunno_int = ints[i0+3] #print(ints[i0+4:i1]) #print(floats[i0+4:i1]) ids = ints[i0+4:i1:2].tolist() values = floats[i0+5:i1:2].tolist() assert len(ids) == len(values) assert dunno_int in [0, 2], (sid, prop_type, (ints[i0+3], floats[i0+4]), ids, values) #print(sid, prop_type, (ints[i0+3], floats[i0+4]), ids, values) nsm = op2.add_nsm(sid, nsm_type, ids, values) #print(nsm[0]) str(nsm) n += (i1 - i0 + 1) * size ncards += 1 op2.card_count['NSM'] = ncards return n
def _read_nsm_msc(self, data: bytes, n: int) -> int: """ NSM(3201,32,55) - the marker for Record 2 MSC 1 SID I Set identification number 2 PROP CHAR4 Set of property or elements 3 ID I Property or element identification number 4 VALUE RS Nonstructural mass value ORIGIN=0 NSM Bulk Data entry 5 ID I Property or element ID 6 VALUE RS Nonstructural mass value Words 5 through 6 repeat until End of Record ORIGIN=2 NSML Bulk Data entry 5 ID I Property or element ID 6 VALUE RS Nonstructural mass value Words 5 through 6 repeat until End of Record Words 3 through 4 repeat until End of Record """ op2: OP2Geom = self.op2 properties = [] struct1 = Struct(op2._endian + b'i 4s if') ndelta = 16 i = 0 ints = np.frombuffer(data[n:], op2.idtype).copy() floats = np.frombuffer(data[n:], op2.fdtype).copy() while n < len(data): edata = data[n:n+ndelta] out = struct1.unpack(edata) (sid, prop_set, pid, value) = out # 538976312 assert pid < 100000000 i += 4 n += ndelta prop_set = prop_set.decode('utf8').rstrip(' ') # \x00 values = [value] #print('ints[i:]=', ints[i:]) while ints[i] != -1: value2 = floats[i] values.append(value2) n += 4 i += 1 op2.log.info("MSC: NSM-sid=%s prop_set=%s pid=%s values=%s" % ( sid, prop_set, pid, values)) prop = NSM.add_op2_data([sid, prop_set, pid, value]) #op2._add_methods._add_nsm_object(prop) properties.append(prop) # handle the trailing -1 i += 1 n += 4 return n, properties def _read_nsm_nx(self, data: bytes, n: int) -> int: """ NSM(3201,32,55) - the marker for Record 2 1 SID I Set identification number 2 PROP(2) CHAR4 Set of properties or elements 4 ORIGIN I Entry origin 5 ID I Property or element identification number 6 VALUE RS Nonstructural mass value Words 5 through 6 repeat until End of Record """ op2: OP2Geom = self.op2 properties = [] #NX: C:\Users\sdoyle\Dropbox\move_tpl\nsmlcr2s.op2 struct1 = Struct(op2._endian + b'i 8s ii f') ndelta = 24 #op2.show_data(data[12:], 'ifs') i = 0 ints = np.frombuffer(data[n:], op2.idtype).copy() floats = np.frombuffer(data[n:], op2.fdtype).copy() unused_packs = break_by_minus1(ints) #for pack in packs: #print(pack) #ipack = 0 while n < len(data): #print('ints[i:]=', ints[i:].tolist()) #i1, i2 = packs[ipack] #print('idata=%s' % idata[i1:i2]) #print('fdata=%s' % fdata[i1:i2]) #print(idata[i1:i2]) edata = data[n:n+ndelta] out = struct1.unpack(edata) (sid, prop_set, origin, pid, value) = out # 538976312 assert pid < 100000000 i += 6 n += ndelta prop_set = prop_set.decode('utf8').rstrip(' ') # \x00 pids = [pid] values = [value] #print('ints[i:]=', ints[i:].tolist()) while ints[i] != -1: pid = ints[i] value2 = floats[i+1] assert pid != -1 pids.append(pid) values.append(value2) n += 8 i += 2 for pid, value in zip(pids, values): if origin == 0: #op2.log.info("NX: NSM-sid=%s prop_set=%s pid=%s values=%s" % ( #sid, prop_set, pid, values)) prop = NSM.add_op2_data([sid, prop_set, pid, value]) elif origin == 2: #op2.log.info("NX: NSML-sid=%s prop_set=%s pid=%s values=%s" % ( #sid, prop_set, pid, values)) prop = NSML.add_op2_data([sid, prop_set, pid, value]) #print(prop.rstrip(), pid, value) #op2._add_methods._add_nsm_object(prop) properties.append(prop) #print('----') # handle the trailing -1 i += 1 n += 4 #ipack += 1 return n, properties # NSM1 # NSML1 # NSMADD # NSML # NSML1 # PAABSF # PACABS # PACBAR
[docs] def read_pbar(self, data: bytes, n: int) -> int: """ PBAR(52,20,181) - the marker for Record 11 .. warning:: this makes a funny property... MSC 2016/NX10 Word Name Type Description 1 PID I Property identification number 2 MID I Material identification number 3 A RS Area 4 I1 RS Area moment of inertia in plane 1 5 I2 RS Area moment of inertia in plane 2 6 J RS Torsional constant 7 NSM RS Nonstructural mass per unit length 8 FE RS 9 C1 RS Stress recovery location at point C in element y-axis 10 C2 RS Stress recovery location at point C in element z-axis 11 D1 RS Stress recovery location at point D in element y-axis 12 D2 RS Stress recovery location at point D in element z-axis 13 E1 RS Stress recovery location at point E in element y-axis 14 E2 RS Stress recovery location at point E in element z-axis 15 F1 RS Stress recovery location at point F in element y-axis 16 F2 RS Stress recovery location at point F in element z-axis 17 K1 RS Area factor for shear in plane 1 18 K2 RS Area factor for shear in plane 2 19 I12 RS Area product of inertia for plane 1 and 2 """ op2: OP2Geom = self.op2 ntotal = 76 * self.factor # 19*4 struct1 = Struct(mapfmt(op2._endian + b'2i17f', self.size)) nentries = (len(data) - n) // ntotal for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) #(pid, mid, a, I1, I2, J, nsm, fe, c1, c2, d1, d2, #e1, e2, f1, f2, k1, k2, I12) = out prop = PBAR.add_op2_data(out) self._add_op2_property(prop) n += ntotal op2.card_count['PBAR'] = nentries return n
[docs] def read_pbarl(self, data: bytes, n: int) -> int: """ PBARL(9102,91,52) - the marker for Record 12 TODO: buggy It's possible to have a PBARL and a PBAR at the same time. NSM is at the end of the element. """ op2: OP2Geom = self.op2 valid_types = { 'ROD': 1, 'TUBE': 2, 'TUBE2': 2, 'I': 6, 'CHAN': 4, 'T': 4, 'BOX': 4, 'BAR': 2, 'CROSS': 4, 'H': 4, 'T1': 4, 'I1': 4, 'CHAN1': 4, 'Z': 4, 'CHAN2': 4, "T2": 4, 'BOX1': 6, 'HEXA': 3, 'HAT': 4, 'HAT1': 5, 'DBOX': 10, # was 12 #'MLO TUBE' : 2, } # for GROUP="MSCBML0" size = self.size ntotal = 28 * self.factor # 7*4 - ROD - shortest entry...could be buggy... # TODO fix this if size == 4: struct1 = Struct(op2._endian + b'2i 8s 8s f') else: struct1 = Struct(op2._endian + b'2q 16s 16s d') #nentries = (len(data) - n) // ntotal #print(self.show_ndata(80)) ndata = len(data) while ndata - n > ntotal: edata = data[n:n+ntotal] n += ntotal out = struct1.unpack(edata) (pid, mid, group, bar_type_bytes, value) = out if pid > 100000000 or pid < 1: op2.log.debug(" pid=%s mid=%s group=%r bar_type=%r value=%s" % ( pid, mid, group, bar_type_bytes, value)) raise RuntimeError('bad parsing...') bar_type = reshape_bytes_block_size(bar_type_bytes, size=size) group = reshape_bytes_block_size(group, size=size) data_in = [pid, mid, group, bar_type, value] expected_length = valid_types[bar_type] iformat = op2._endian + b'%if' % expected_length ndelta = expected_length * 4 dims_nsm = list(unpack(iformat, data[n:n+ndelta])) data_in += dims_nsm #print(" pid=%s mid=%s group=%r bar_type=%r value=%s dims_nsm=%s" % ( #pid, mid, group, bar_type, value, dims_nsm)) # TODO why do i need the +4??? # is that for the nsm? #min_len = expected_length * 4 + 4 #if len(data) #data = data[n + expected_length * 4 + 4:] n += ndelta #prin( "len(out) = ",len(out))) #print("PBARL = %s" % data_in) prop = PBARL.add_op2_data(data_in) # last value is nsm pid = prop.pid if pid in op2.properties: #op2.log.debug("removing:\n%s" % op2.properties[pid]) op2._type_to_id_map['PBAR'].remove(pid) del op2.properties[pid] self._add_op2_property(prop) #op2.properties[pid] = prop #print(prop.get_stats()) #print(op2.show_data(data[n-8:-100])) # the PBARL ends with a -1 flag #value, = unpack(op2._endian + b'i', data[n:n+4]) n += 4 * self.factor if len(op2._type_to_id_map['PBAR']) == 0 and 'PBAR' in op2.card_count: del op2._type_to_id_map['PBAR'] del op2.card_count['PBAR'] op2.increase_card_count('PBARL') #assert len(data) == n if self.size == 8: n += 16 #n += 8 # same for 32/64 bit - not 100% that it's always active return n
[docs] def read_pbcomp(self, data: bytes, n: int) -> int: """ PBCOMP(5403, 55, 349) pid mid A I1 I2 I12 J NSM PBCOMP 3 2 2.00E-4 6.67E-9 1.67E-9 0.0 4.58E-9 0.0 + pid mid floats = (3, 2, 0.0002, 6.67e-09, 1.67e-09, 0.0, 4.58e-09, 0.0, 1.0, 1.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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) ints = (3, 2, 0.0002, 6.67E-9, 1.67E-9, 0, 4.58E-9, 0, 1.0, 1.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) """ op2: OP2Geom = self.op2 struct1 = Struct(mapfmt(op2._endian + b'2i 12f i', self.size)) struct2 = Struct(mapfmt(op2._endian + b'3f 2i', self.size)) nproperties = 0 ntotal1 = 60 * self.factor # 4*15 ntotal2 = 20 * self.factor ndata = len(data) #print(ntotal1, ntotal2) if self.factor == 2: op2.show_data(data[12*self.factor:], types='qd') #print(len(data[12*self.factor:])) while n < ndata: #op2.log.debug(f"n={n} ndata={ndata}") edata = data[n:n+ntotal1] #if len(edata) == ntotal1: data1 = struct1.unpack(edata) #else: #op2.show_data(edata, types='qdi') #n += ntotal2 #continue nsections = data1[-1] if op2.is_debug_file: (pid, mid, a, i1, i2, i12, j, nsm, k1, k2, m1, m2, n1, n2, unused_nsections) = data1 op2.log.info(f'PBCOMP pid={pid} mid={mid} nsections={nsections} ' f'k1={k1} k2={k2} m=({m1},{m2}) n=({n1},{n2})\n') #if pid > 0 and nsections == 0: #print('n1') #n += ntotal1 #continue #if pid == 0 and nsections == 0: #print('n2') #n += ntotal2 #continue data2 = [] n += ntotal1 if nsections in [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]: # 16 Y RS Lumped area location along element's y-axis # 17 Z RS Lumped area location along element's z-axis # 18 C RS Fraction of the total area for the lumped area # 19 MID I Material identification number # 20 UNDEF None # Words 16 through 20 repeat NSECT times for unused_i in range(nsections): datai = data[n:n+ntotal2] xi, yi, ci, mid, unused_null = struct2.unpack(datai) data2.append((xi, yi, ci, mid)) n += ntotal2 else: op2.log.error(f'PBCOMP={data1[0]} has no sections; check your bdf') return n #raise NotImplementedError('PBCOMP nsections=%r' % nsections) if op2.is_debug_file: op2.binary_debug.write(' PBCOMP: %s\n' % str([data1, data2])) msg = ( ' i=%-2s so=%s xxb=%.1f a=%g i1=%g i2=%g i12=%g j=%g nsm=%g ' 'c=[%s,%s] d=[%s,%s] e=[%s,%s] f=[%s,%s]' % ( nsections, None, -9999., a, i1, i2, i12, j, nsm, None, None, None, None, None, None, None, None,) ) op2.log.debug(msg) #op2.log.debug(data1) #op2.log.debug(data2) data_in = [data1, data2] prop = PBCOMP.add_op2_data(data_in) pid = data1[0] if pid in op2.properties: op2._type_to_id_map['PBEAM'].remove(pid) del op2.properties[pid] self._add_op2_property(prop) nproperties += 1 #print(f"n={n} ndata={ndata}") assert nproperties > 0, 'PBCOMP nproperties=%s' % (nproperties) if len(op2._type_to_id_map['PBEAM']) == 0 and 'PBEAM' in op2.card_count: del op2._type_to_id_map['PBEAM'] del op2.card_count['PBEAM'] op2.card_count['PBCOMP'] = nproperties return n
[docs] def read_pbeam(self, data: bytes, n: int) -> int: """ PBEAM(5402,54,262) - the marker for Record 14 .. todo:: add object """ op2: OP2Geom = self.op2 cross_section_type_map = { 0 : 'variable', 1 : 'constant', 2 : '???', } struct1 = Struct(mapfmt(op2._endian + b'4if', self.size)) struct2 = Struct(mapfmt(op2._endian + b'16f', self.size)) struct3 = Struct(mapfmt(op2._endian + b'16f', self.size)) unused_ntotal = 768 # 4*(5+16*12) #nproperties = (len(data) - n) // ntotal #assert nproperties > 0, 'ndata-n=%s n=%s datai\n%s' % (len(data)-n, n, op2.show_data(data[n:100+n])) ndata = len(data) #op2.show_data(data[12:], 'if') #assert ndata % ntotal == 0, 'ndata-n=%s n=%s ndata%%ntotal=%s' % (len(data)-n, n, ndata % ntotal) nproperties = 0 ntotal1 = 20 * self.factor ntotal2 = 64 * self.factor while n < ndata: #while 1: #for i in range(nproperties): edata = data[n:n+ntotal1] n += ntotal1 data_in = list(struct1.unpack(edata)) #if op2.is_debug_file: #op2.log.info('PBEAM pid=%s mid=%s nsegments=%s ccf=%s x=%s\n' % tuple(data_in)) (pid, unused_mid, unused_nsegments, ccf, unused_x) = data_in #op2.log.info('PBEAM pid=%s mid=%s nsegments=%s ccf=%s x=%s' % tuple(data_in)) # Constant cross-section flag: 1=yes and 0=no # what is 2? if ccf not in [0, 1, 2]: msg = (' PBEAM pid=%s mid=%s nsegments=%s ccf=%s x=%s; ' 'ccf must be in [0, 1, 2]\n' % tuple(data_in)) raise ValueError(msg) cross_section_type = cross_section_type_map[ccf] #print('cross_section_type = %s' % cross_section_type) is_pbcomp = False is_bad_so = False so = [] xxb = [] for i in range(11): edata = data[n:n+ntotal2] if len(edata) != ntotal2: endpack = [] raise RuntimeError(f'PBEAM unexpected length i={i:d}...') n += ntotal2 pack = struct2.unpack(edata) (soi, xxbi, a, i1, i2, i12, j, nsm, c1, c2, d1, d2, e1, e2, f1, f2) = pack xxb.append(xxbi) so.append(soi) if soi == 0.0: so_str = 'NO' elif soi == 1.0: so_str = 'YES' else: so_str = str(soi) is_bad_so = True #msg = 'PBEAM pid=%s i=%s x/xb=%s soi=%s; soi not in 0.0 or 1.0' % ( #pid, i, xxb, soi) #raise NotImplementedError(msg) #if xxb != 0.0: #msg = 'PBEAM pid=%s i=%s x/xb=%s soi=%s; xxb not in 0.0 or 1.0' % ( #pid, i, xxb, soi) #raise NotImplementedError(msg) pack2 = (so_str, xxbi, a, i1, i2, i12, j, nsm, c1, c2, d1, d2, e1, e2, f1, f2) data_in.append(pack2) if op2.is_debug_file: op2.binary_debug.write(f' {pack}\n') msg = ( ' i=%-2s' % i + ' so=%s xxb=%.1f a=%g i1=%g i2=%g i12=%g j=%g nsm=%g ' 'c=[%s,%s] d=[%s,%s] e=[%s,%s] f=[%s,%s]' % (tuple(pack2)) ) op2.binary_debug.write(msg) #msg = ( #' i=%-2s' % i + ' so=%s xxb=%.1f a=%g i1=%g i2=%g i12=%g j=%g nsm=%g ' #'c=[%s,%s] d=[%s,%s] e=[%s,%s] f=[%s,%s]' % (tuple(pack2)) #) #print(msg) edata = data[n:n+ntotal2] if len(edata) != ntotal2: endpack = [] raise RuntimeError('PBEAM unexpected length 2...') endpack = struct3.unpack(edata) n += ntotal2 assert len(endpack) == 16, endpack #(k1, k2, s1, s2, nsia, nsib, cwa, cwb, # 8 #m1a, m2a, m1b, m2b, n1a, n2a, n1b, n2b) = endpack # 8 -> 16 if op2.is_debug_file: op2.binary_debug.write(' k=[%s,%s] s=[%s,%s] nsi=[%s,%s] cw=[%s,%s] ' 'ma=[%s,%s] mb=[%s,%s] na=[%s,%s] nb=[%s,%s]' % ( tuple(endpack))) data_in.append(endpack) if is_bad_so: #if soi < 0.: xxb_str = ', '.join(['%g' % xxbi for xxbi in xxb]) so_str = ', '.join(['%g' % soi for soi in so]) msg = (f'PBEAM pid={pid} i={i} soi=[{so_str}]; ' 'soi not 0.0 or 1.0; assuming PBCOMP & dropping') op2.log.error(msg) is_pbcomp = True if min(xxb) < 0.0 or max(xxb) > 1.0: xxb_str = ', '.join(['%g' % xxbi for xxbi in xxb]) msg = (f'PBEAM pid={pid} i={i} x/xb=[{xxb_str}]; ' 'x/xb must be between 0.0 and 1.0; assuming PBCOMP & dropping') op2.log.error(msg) is_pbcomp = True if is_pbcomp: continue if pid in op2.properties: if op2.properties[pid].type == 'PBCOMP': continue prop = PBEAM.add_op2_data(data_in) nproperties += 1 self._add_op2_property(prop) if nproperties: op2.card_count['PBEAM'] = nproperties return n
[docs] def read_pbeaml(self, data: bytes, n: int) -> int: """ PBEAML(9202,92,53) Word Name Type Description 1 PID I Property identification number 2 MID I Material identification number 3 GROUP(2) CHAR4 Cross-section group name 5 TYPE(2) CHAR4 Cross section type 7 VALUE RS Cross section values for XXB, SO, NSM, and dimensions Word 7 repeats until (-1) occurs """ op2: OP2Geom = self.op2 #strs = numpy.core.defchararray.reshapesplit(data, sep=",") #ints = np.frombuffer(data[n:], self._uendian + 'i').copy() #floats = np.frombuffer(data[n:], self._uendian + 'f').copy() ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() istart, iend = get_minus1_start_end(ints) size = self.size nproperties = len(istart) if size == 4: struct1 = Struct(op2._endian + b'2i 8s 8s') else: struct1 = Struct(op2._endian + b'2q 16s 16s') for unused_i, (istarti, iendi) in enumerate(zip(istart, iend)): idata = data[n+istarti*size : n+(istarti+6)*size] pid, mid, group, beam_type = struct1.unpack(idata) group = group.decode('latin1').strip() beam_type = beam_type.decode('latin1').strip() fvalues = floats[istarti+6: iendi] if op2.is_debug_file: op2.binary_debug.write(' %s\n' % str(fvalues)) op2.log.debug(f'pid={pid:d} mid={mid:d} group={group} beam_type={beam_type}') op2.log.debug(fvalues) #op2.log.debug(f'pid={pid:d} mid={mid:d} group={group} beam_type={beam_type}') data_in = [pid, mid, group, beam_type, fvalues] prop = PBEAML.add_op2_data(data_in) if pid in op2.properties: # this is a fake PSHELL propi = op2.properties[pid] assert propi.type in ['PBEAM'], propi.get_stats() nproperties -= 1 continue self._add_op2_property(prop) if nproperties: op2.card_count['PBEAML'] = nproperties return len(data)
[docs] def read_pbend(self, data: bytes, n: int) -> int: """PBEND""" op2: OP2Geom = self.op2 n = op2.reader_geom2._read_dual_card( data, n, self._read_pbend_nx, self._read_pbend_msc, 'PBEND', op2._add_methods._add_property_object) return n
def _read_pbend_msc(self, data: bytes, n: int) -> int: """ PBEND 1 PID I Property identification number 2 MID I Material identification number 3 A RS Area 4 I1 RS Area moment of inertia in plane 1 5 I2 RS Area moment of inertia in plane 2 6 J RS Torsional constant 7 FSI I flexibility and stress intensification factors 8 RM RS Mean cross-sectional radius of the curved pipe 9 T RS Wall thickness of the curved pipe 10 P RS Internal pressure 11 RB RS Bend radius of the line of centroids 12 THETAB RS Arc angle of element 13 C1 RS Stress recovery location at point C in element y-axis 14 C2 RS Stress recovery location at point C in element z-axis 15 D1 RS Stress recovery location at point D in element y-axis 16 D2 RS Stress recovery location at point D in element z-axis 17 E1 RS Stress recovery location at point E in element y-axis 18 E2 RS Stress recovery location at point E in element z-axis 19 F1 RS Stress recovery location at point F in element y-axis 20 F2 RS Stress recovery location at point F in element z-axis 21 K1 RS Area factor for shear in plane 1 22 K2 RS Area factor for shear in plane 2 23 NSM RS Nonstructural mass per unit length 24 RC RS Radial offset of the geometric centroid 25 ZC RS Offset of the geometric centroid 26 DELTAN I Radial offset of the neutral axis from the geometric centroid """ op2: OP2Geom = self.op2 ntotal = 104 # 26*4 struct1 = Struct(op2._endian + b'2i 4f i 18f f') # delta_n is a float, not an integer nproperties = (len(data) - n) // ntotal assert (len(data) - n) % ntotal == 0 assert nproperties > 0, 'table=%r len=%s' % (op2.table_name, len(data) - n) properties = [] for unused_i in range(nproperties): edata = data[n:n+104] out = struct1.unpack(edata) (pid, mid, area, i1, i2, j, fsi, rm, t, p, rb, theta_b, c1, c2, d1, d2, e1, e2, f1, f2, k1, k2, nsm, rc, zc, delta_n) = out beam_type = fsi if (area, rm, t, p) == (0., 0., 0., 0.): area = None rm = None t = None p = None delta_n = None beam_type = 2 if delta_n == 0: #: Radial offset of the neutral axis from the geometric #: centroid, positive is toward the center of curvature delta_n = None pbend = PBEND(pid, mid, beam_type, area, i1, i2, j, c1, c2, d1, d2, e1, e2, f1, f2, k1, k2, nsm, rc, zc, delta_n, fsi, rm, t, p, rb, theta_b) #print(pbend) pbend.validate() properties.append(pbend) n += ntotal return n, properties def _read_pbend_nx(self, data: bytes, n: int) -> int: """ PBEND 1 PID I Property identification number 2 MID I Material identification number 3 A RS Area 4 I1 RS Area moment of inertia in plane 1 5 I2 RS Area moment of inertia in plane 2 6 J RS Torsional constant 7 FSI I Flexibility and stress intensification factors 8 RM RS Mean cross-sectional radius of the curved pipe 9 T RS Wall thickness of the curved pipe 10 P RS Internal pressure 11 RB RS Bend radius of the line of centroids 12 THETAB RS Arc angle of element 13 C1 RS Stress recovery location at point C in element y-axis 14 C2 RS Stress recovery location at point C in element z-axis 15 D1 RS Stress recovery location at point D in element y-axis 16 D2 RS Stress recovery location at point D in element z-axis 17 E1 RS Stress recovery location at point E in element y-axis 18 E2 RS Stress recovery location at point E in element z-axis 19 F1 RS Stress recovery location at point F in element y-axis 20 F2 RS Stress recovery location at point F in element z-axis 21 K1 RS Area factor for shear in plane 1 22 K2 RS Area factor for shear in plane 2 23 NSM RS Nonstructural mass per unit length 24 RC RS Radial offset of the geometric centroid 25 ZC RS Offset of the geometric centroid 26 DELTAN RS Radial offset of the neutral axis from the geometric centroid 27 SACL RS Miter spacing at center line. 28 ALPHA RS One-half angle between the adjacent miter axis (Degrees). 29 FLANGE I For FSI=5, defines the number of flanges attached. 30 KX RS For FSI=6, the user defined flexibility factor for the torsional moment. 31 KY RS For FSI=6, the user defined flexibility factor for the out-of-plane bending moment. 32 KZ RS For FSI=6, the user defined flexbility factor for the in-plane bending moment. 33 Not used """ op2: OP2Geom = self.op2 #op2.log.info('geom skipping PBEND in EPT') #return len(data) ntotal = 132 # 33*4 struct1 = Struct(op2._endian + b'2i 4f i 21f i 4f') nproperties = (len(data) - n) // ntotal assert (len(data) - n) % ntotal == 0 assert nproperties > 0, 'table=%r len=%s' % (op2.table_name, len(data) - n) properties = [] for unused_i in range(nproperties): edata = data[n:n+132] out = struct1.unpack(edata) (pid, mid, area, i1, i2, j, fsi, rm, t, p, rb, theta_b, c1, c2, d1, d2, e1, e2, f1, f2, k1, k2, nsm, rc, zc, delta_n, unused_sacl, unused_alpha, unused_flange, unused_kx, unused_ky, unused_kz, unused_junk,) = out beam_type = fsi pbend = PBEND(pid, mid, beam_type, area, i1, i2, j, c1, c2, d1, d2, e1, e2, f1, f2, k1, k2, nsm, rc, zc, delta_n, fsi, rm, t, p, rb, theta_b) pbend.validate() properties.append(pbend) n += ntotal return n, properties # PBMSECT # PBRSECT
[docs] def read_pbush(self, data: bytes, n: int) -> int: """ The PBUSH card is different between MSC and NX Nastran. DMAP NX 11 ---------- NX has 23 fields in NX 11-NX 2019.2 (same as MSC 2005) NX has 18 fields in the pre-2001 format DMAP MSC 2005 ------------- MSC has 23 fields in 2005 MSC has 18 fields in the pre-2001 format DMAP MSC 2016 ------------- MSC has 24 fields in 2016.1 MSC has 18 fields in the pre-2001 format DMAP MSC 2021 ------------- MSC has 27 fields in 2021 """ op2: OP2Geom = self.op2 card_name = 'PBUSH' card_obj = PBUSH methods = { 72 : self._read_pbush_nx_72, # 72=4*18 92 : self._read_pbush_msc_92, # 92=4*23 96 : self._read_pbush_msc_96, # 96=4*24 108 : self._read_pbush_msc_108, # 108=4*27 } try: n = op2.reader_geom2._read_double_card( card_name, card_obj, self._add_op2_property, methods, data, n) except DoubleCardError: nx_method = partial(self._read_pbush_nx_72, card_obj) msc_method = partial(self._read_pbush_msc_92, card_obj) n = op2.reader_geom2._read_dual_card( data, n, nx_method, msc_method, card_name, self._add_op2_property) # we're listing nx twice because NX/MSC used to be consistent # the new form for MSC is not supported #n = self._read_dual_card(data, n, self._read_pbush_nx, self._read_pbush_msc, #'PBUSH', self._add_op2_property) return n
def _read_pbush_nx_72(self, card_obj: PBUSH, data: bytes, n: int) -> tuple[int, list[PBUSH]]: """ PBUSH(1402,14,37) - 18 fields legacy MSC/NX format """ op2: OP2Geom = self.op2 ntotal = 72 * self.factor # 18*4 struct1 = Struct(mapfmt(op2._endian + b'i17f', self.size)) ndata = len(data) - n nentries = ndata // ntotal assert nentries > 0, f'table={op2.table_name} len={ndata}' assert ndata % ntotal == 0, f'table={op2.table_name} leftover = {ndata} % {ntotal} = {ndata % ntotal}' props = [] for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) (pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, g1, sa, st, ea, et) = out #op2.log.debug(out) assert pid > 0, pid g2 = g3 = g4 = g5 = g6 = g1 data_in = (pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, g1, g2, g3, g4, g5, g6, sa, st, ea, et) prop = PBUSH.add_op2_data(data_in) props.append(prop) n += ntotal return n, props def _read_pbush_msc_92(self, card_obj: PBUSH, data: bytes, n: int) -> tuple[int, list[PBUSH]]: """PBUSH(1402,14,37) - 23 fields MSC 2005r2 to <MSC 2016 """ op2: OP2Geom = self.op2 ntotal = 92 * self.factor # 23*4 struct1 = Struct(mapfmt(op2._endian + b'i22f', self.size)) ndata = len(data) - n nentries = ndata // ntotal assert nentries > 0, f'table={op2.table_name} len={ndata}' assert ndata % ntotal == 0, f'table={op2.table_name} leftover = {ndata} % {ntotal} = {ndata % ntotal}' props = [] for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) #(pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, #g1, g2, g3, g4, g5, g6, sa, st, ea, et) = out pid = out[0] assert pid > 0, pid prop = PBUSH.add_op2_data(out) props.append(prop) n += ntotal return n, props def _read_pbush_msc_96(self, card_obj: PBUSH, data: bytes, n: int) -> tuple[int, list[PBUSH]]: """PBUSH(1402,14,37) - 24 fields MSC 2016.1? to 2020 """ op2: OP2Geom = self.op2 ntotal = 96 * self.factor # 24*4 struct1 = Struct(mapfmt(op2._endian + b'i22f f', self.size)) ndata = len(data) - n nentries = ndata // ntotal assert nentries > 0, f'table={op2.table_name} len={ndata}' assert ndata % ntotal == 0, f'table={op2.table_name} leftover = {ndata} % {ntotal} = {ndata % ntotal}' props = [] for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) #(pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, #g1, g2, g3, g4, g5, g6, sa, st, ea, et, mass) = out pid = out[0] assert pid > 0, pid prop = PBUSH.add_op2_data(out) props.append(prop) n += ntotal return n, props def _read_pbush_msc_108(self, card_obj: PBUSH, data: bytes, n: int) -> tuple[int, list[PBUSH]]: """ PBUSH(1402,14,37) - 27 fields MSC 2021 to current ints = (1402, 14, 37, 2, 100000.0, 200000.0, 300000.0, 0.15, 0.25, 0.35, 1000.0, 2000.0, 3000.0, 0.0015, 0.0025, 0.0035, 0, -1577048263, -1577048263, -1577048263, -1577048263, -1577048263, 1065353216, 1065353216, 1065353216, 1065353216, 0, 0, 0, 0) floats = (1402, 14, 37, 2, 100000.0, 200000.0, 300000.0, 0.15, 0.25, 0.35, 1000.0, 2000.0, 3000.0, 0.0015, 0.0025, 0.0035, 0.0, -1.7367999061094683e-18, -1.7367999061094683e-18, -1.7367999061094683e-18, -1.7367999061094683e-18, -1.7367999061094683e-18, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0) """ op2: OP2Geom = self.op2 ntotal = 108 * self.factor # 27*4 struct1 = Struct(mapfmt(op2._endian + b'i22f 4f', self.size)) #op2.show_data(data, types='ifs') ndata = len(data) - n nentries = ndata // ntotal assert nentries > 0, f'table={op2.table_name} len={ndata}' assert ndata % ntotal == 0, f'table={op2.table_name} leftover = {ndata} % {ntotal} = {ndata % ntotal}' props = [] for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) #(pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, #g1, g2, g3, g4, g5, g6, sa, st, ea, et) = out pid = out[0] assert pid > 0, pid prop = PBUSH.add_op2_data(out) str(prop) props.append(prop) n += ntotal return n, props
[docs] def read_pbush1d(self, data: bytes, n: int) -> int: """ Record 18 -- PBUSH1D(3101,31,219) 1 PID I Property identification number 2 K RS Stiffness 3 C RS Viscous Damping 4 M RS Mass 5 ALPHA RS Temperature coefficient 6 SA RS Stress recovery coefficient 7 EA/SE RS Strain recovery coefficient 8 TYPEA I Shock data type:0=Null, 1=Table, 2=Equation 9 CVT RS Coefficient of translation velocity tension 10 CVC RS Coefficient of translation velocity compression 11 EXPVT RS Exponent of velocity tension 12 EXPVC RS Exponent of velocity compression 13 IDTSU I TABLEDi or DEQATN entry identification number for scale factor vs displacement 14 IDTCU I DEQATN entry identification number for scale factor vs displacement 15 IDTSUD I DEQATN entry identification number for derivative tension 16 IDCSUD I DEQATN entry identification number for derivative compression 17 TYPES I Spring data type: 0=Null, 1=Table, 2=Equation 18 IDTS I TABLEDi or DEQATN entry identification number for tension compression 19 IDCS I DEQATN entry identification number for compression 20 IDTDU I DEQATN entry identification number for scale factor vs displacement 21 IDCDU I DEQATN entry identification number for force vs displacement 22 TYPED I Damper data type: 0=Null, 1=Table, 2=Equation 23 IDTD I TABLEDi or DEQATN entry identification number for tension compression 24 IDCD I DEQATN entry identification number for compression 25 IDTDV I DEQATN entry identification number for scale factor versus velocity 26 IDCDV I DEQATN entry identification number for force versus velocity 27 TYPEG I General data type: 0=Null, 1=Table, 2=Equation 28 IDTG I TABLEDi or DEQATN entry identification number for tension compression 29 IDCG I DEQATN entry identification number for compression 30 IDTDU I DEQATN entry identification number for scale factor versus displacement 31 IDCDU I DEQATN entry identification number for force versus displacement 32 IDTDV I DEQATN entry identification number for scale factor versus velocity 33 IDCDV I DEQATN entry identification number for force vs velocity 34 TYPEF I Fuse data type: 0=Null, 1=Table 35 IDTF I TABLEDi entry identification number for tension 36 IDCF I TABLEDi entry identification number for compression 37 UT RS Ultimate tension 38 UC RS Ultimate compression """ op2: OP2Geom = self.op2 type_map = { 0 : None, # NULL 1 : 'TABLE', 2 : 'EQUAT', } ntotal = 152 * self.factor # 38*4 struct1 = Struct(mapfmt(op2._endian + b'i 6f i 4f 24i 2f', self.size)) nentries = (len(data) - n) // ntotal for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) (pid, k, c, m, unused_alpha, sa, se, typea, cvt, cvc, expvt, expvc, idtsu, idtcu, idtsud, idcsud, types, idts, idcs, idtdus, idcdus, typed, idtd, idcd, idtdvd, idcdvd, typeg, idtg, idcg, idtdug, idcdug, idtdvg, idcdvg, typef, idtf, idcf, unused_ut, unused_uc) = out # test_op2_other_05 #pbush1d, 204, 1.e+5, 1000., , , , , , +pb1 #+pb1, spring, table, 205, , , , , , +pb2 #+pb2, damper, table, 206 #pid=204 k=100000.0 c=1000.0 m=0.0 sa=nan se=nan msg = f'PBUSH1D pid={pid} k={k} c={c} m={m} sa={sa} se={se}' optional_vars = {} typea_str = type_map[typea] types_str = type_map[types] typed_str = type_map[typed] unused_typeg_str = type_map[typeg] unused_typef_str = type_map[typef] if min([typea, types, typed, typeg, typef]) < 0: raise RuntimeError(f'typea={typea} types={types} typed={typed} typeg={typeg} typef={typef}') if typea in [1, 2]: # SHOCKA? #pbush1d, 204, 1.e+5, 1000., , , , , , +pb4 #+pb4, shocka, table, 1000., , 1., , 214, , +pb41 #+pb41, spring, table, 205 idts = idtsu # if typea_str == 'TABLE' else 0 idets = idtsu # if typea_str == 'EQUAT' else 0 optional_vars['SHOCKA'] = [typea_str, cvt, cvc, expvt, expvc, idts, idets, idtcu, idtsud, idcsud] #(shock_type, shock_cvt, shock_cvc, shock_exp_vt, shock_exp_vc, #shock_idts, shock_idets, shock_idecs, shock_idetsd, shock_idecsd #) #print('shock_idts, shock_idets', typea_str, idtsu, idtsu) msg += ( f' SHOCKA type={typea} cvt={cvt} cvc={cvc} expvt={expvt} expvc={expvc}\n' f' idtsu={idtsu} (idts={idts} idets={idets}) idtcu={idtcu} idtsud={idtsud} idcsud={idcsud}') if types in [1, 2]: # SPRING: Spring data type: 0=Null, 1=Table, 2=Equation #(spring_type, spring_idt, spring_idc, spring_idtdu, spring_idcdu) = values # SPRING, TYPE IDT IDC IDTDU IDCDU optional_vars['SPRING'] = [types_str, idts, idcs, idtdus, idcdus] msg += f' SPRING type={types} idt={idts} idc={idcs} idtdu={idtdus} idcdu={idcdus}' if typed in [1, 2]: # Damper data type: 0=Null, 1=Table, 2=Equation optional_vars['DAMPER'] = [typed_str, idtd, idcd, idtdvd, idcdvd] msg += f' DAMPER type={typed} idt={idtd} idc={idtd} idtdv={idtdvd} idcdv={idcdvd}' if typeg in [1, 2]: # general, GENER?: 0=Null, 1=Table 2=Equation # C:\NASA\m4\formats\git\examples\move_tpl\ar29scbt.bdf #pbush1d, 206, 1.e+3, 10., , , , , , +pb6 #+pb6, gener, equat, 315, , 3015, , 3016 msg += f' GENER type={typeg} idt={idtg} idc={idcg} idtdu={idtdug} idcdu={idcdug} idtdv={idtdvg} idcdv={idcdvg}' optional_vars['GENER'] = [idtg, idcg, idtdug, idcdug, idtdvg, idcdvg] if typef in [1, 2]: # Fuse data type: 0=Null, 1=Table raise NotImplementedError(f'typef={typef} idtf={idtf} idcf={idcf}') if op2.is_debug_file: op2.binary_debug.write(msg) pbush1d = op2.add_pbush1d(pid, k=k, c=c, m=m, sa=sa, se=se, optional_vars=optional_vars,) str(pbush1d) n += ntotal op2.card_count['PBUSH1D'] = nentries return n
#def _read_pbusht(self, data: bytes, n: int) -> int: #"""reads the PBUSHT(702, 7, 38)""" #n, props = self._read_pbusht_nx(data, n) #for prop in props: ##print(prop) #op2._add_pbusht_object(prop) #return n
[docs] def read_pbush2d(self, data: bytes, n: int) -> int: """ Word Name Type Description 1 PID I Property identification number 2 K1 RS Nominal Stiffness for T1 3 K2 RS Nominal Stiffness for T2 4 B1 RS Nominal Viscous Damping for T1 5 B2 RS Nominal Viscous Damping for T2 6 M1 RS Nominal Mass for T1 7 M2 RS Nominal Mass for T2 8 DEFINED I DEFINED =1 9 FTBEQ I TABLE or EQUATN; see NOTEs after EOR 10 TIDF1 I TABLE/DEQATN ID for P in T1 vs. disp/velo/acce/rotorsp 11 TIDF2 I TABLE/DEQATN ID for P in T2 vs. disp/velo/acce/rotorsp 12 UNDEF(17) none DEFINED=2 defined via SQUEEZE 9 BDIA RS Inner journal diameter, required 10 BLEN RS Damper length, required 11 BCLR RS Damper radial clearance, required 12 SOLN I Solution option: 1=LONG or 2=SHORT bearing 13 VISCO RS Lubricant viscosity, required 14 PVAPCO RS Lubricant vapor pressure, required 15 NPORT I Number of lubrication ports: 1 or 2 16 PRES1 RS Boundary pressure for port 1, required if NPORT=1 or 2 17 THETA1 RS Angular position for port 1, required if NPORT=1 or 2 18 PRES2 RS Boundary pressure for port 2, required if NPORT=2 19 THETA2 RS Angular position for port 2, required if NPORT=2 20 OFFSET1 RS Offset in the SFD direction 1 21 OFFSET2 RS Offset in the SFD direction 2 22 UNDEF(7) none DEFINED=3 defined via CROSS 9 K12 RS Stiffness in T1 due to disp in T2 10 K21 RS Stiffness in T2 due to disp in T1 11 B12 RS Damping in T1 due to velo in T2 12 B21 RS Damping in T2 due to velo in T1 13 M12 RS Acce depend force in T1 due to acce in T2 14 M21 RS Acce depend force in T2 due to acce in T1 15 UNDEF(14) none DEFINED=4 defined via SPRING/DAMPER/MASS 9 OPTTYP(C) I Option type OPTTYP=1 for SPRING 10 STBEQ I TABLE or EQUATN; see NOTEs after EOR 11 TEIDK11 I TABLED5/DEQATN ID for K in T1 due to motion in T1 12 TEIDK22 I TABLED5/DEQATN ID for K in T2 due to motion in T2 13 TEIDK12 I TABLED5/DEQATN ID for K in T1 due to motion in T2 14 TEIDK21 I TABLED5/DEQATN ID for K in T2 due to motion in T1 OPTTYP=2 for DAMPER 10 DTBEQ I TABLE or EQUATN; see NOTEs after EOR 11 TEIDB11 I TABLED5/DEQATN ID for B in T1 due to motion in T1 12 TEIDB22 I TABLED5/DEQATN ID for B in T2 due to motion in T2 13 TEIDB12 I TABLED5/DEQATN ID for B in T1 due to motion in T2 14 TEIDB21 I TABLED5/DEQATN ID for B in T2 due to motion in T1 OPTTYP=3 for MASS 10 MTBEQ I TABLE or EQUATN; see NOTEs after EOR 11 TEIDM11 I TABLED5/DEQATN ID for M in T1 due to motion in T1 12 TEIDM22 I TABLED5/DEQATN ID for M in T2 due to motion in T2 13 TEIDM12 I TABLED5/DEQATN ID for M in T1 due to motion in T2 14 TEIDM21 I TABLED5/DEQATN ID for M in T2 due to motion in T1 End OPTTYP Words 9 through max repeat until End of Record 15 N(C) I Count for UNDEF 16 UNDEF none Word 16 repeats N times DEFINED=5 defined via RGAP 9 TABK I Table ID for GAP K vs. rela disp 10 TABB I Table ID for GAP K vs. rela disp(>0) or velo( 11 TABG I Table ID for GAP clearance vs. time 12 TABU I Table ID for friciton coef vs. time 13 RADIUS RS Shaft radius >=0.0 14 UNDEF(15) none DEFINED=0 No continuation 9 UNDEF(20) none End DEFINED VIA """ #1 PID I Property identification number #2 K1 RS Nominal Stiffness for T1 #3 K2 RS Nominal Stiffness for T2 #4 B1 RS Nominal Viscous Damping for T1 #5 B2 RS Nominal Viscous Damping for T2 #6 M1 RS Nominal Mass for T1 #7 M2 RS Nominal Mass for T2 #8 DEFINED I op2: OP2Geom = self.op2 ints = np.frombuffer(data[n:], op2.idtype8).copy() floats = np.frombuffer(data[n:], op2.fdtype8).copy() i = 0 nfields = len(ints) while i < nfields: pid = ints[i] k1, k2, b1, b2, m1, m2 = floats[i+1:i+7] flag = ints[i+7] if flag == 1: #9 FTBEQ I TABLE or EQUATN; see NOTEs after EOR #10 TIDF1 I TABLE/DEQATN ID for P in T1 vs. disp/velo/acce/rotorsp #11 TIDF2 I TABLE/DEQATN ID for P in T2 vs. disp/velo/acce/rotorsp #12 UNDEF(17) none ftbeq_flag, tid_f1, tid_f2 = ints[i+8:i+10] i += 10 asdf elif flag == 3: #9 K12 RS Stiffness in T1 due to disp in T2 #10 K21 RS Stiffness in T2 due to disp in T1 #11 B12 RS Damping in T1 due to velo in T2 #12 B21 RS Damping in T2 due to velo in T1 #13 M12 RS Acce depend force in T1 due to acce in T2 #14 M21 RS Acce depend force in T2 due to acce in T1 #15 UNDEF(14) none k12, k21, b12, b21, m12, m21 = floats[i+8:i+14] undef = floats[i+14:i+28] assert np.abs(undef).sum() == 0, undef i += 28 op2.add_pbush2d_cross(pid, k1, k2, b1, b2, m1, m2, k12, k21, b12, b21, m12, m21) else: # pragma: no cover raise NotImplementedError(flag) #op2.log.warning('geom skipping PBUSH2D in EPT') #op2.add_pbush2d_squeeze() #""" #| PBUSH2D | PID | K11 | K22 | B11 | B22 | M11 | M22 | #| | SQUEEZE | BDIA | BLEN | BCLR | SOLN | VISCO | PVAPCO | #| | NPORT | PRES1 | THETA1 | PRES2 | THETA2 | OFFSET1 | OFFSET2 | #""" return len(data)
[docs] def read_pbusht(self, data: bytes, n: int) -> int: """ NX 12 / MSC 2005 Word Name Type Description 1 PID I Property identification number 2 TKID(6) I TABLEDi entry identification numbers for stiffness 8 TBID(6) I TABLEDi entry identification numbers for viscous damping 14 TGEID(6) I TABLEDi entry identification number for structural damping 20 TKNID(6) I TABLEDi entry identification numbers for force versus deflection old style Word Name Type Description 1 PID I Property identification number 2 TKID(6) I TABLEDi entry identification numbers for stiffness 8 TBID(6) I TABLEDi entry identification numbers for viscous damping 14 TGEID I TABLEDi entry identification number for structural damping 15 TKNID(6) I TABLEDi entry IDs for force versus deflection """ op2: OP2Geom = self.op2 card_name = 'PBUSHT' card_obj = PBUSHT methods = { 80 : self._read_pbusht_80, 100 : self._read_pbusht_100, 136 : self._read_pbusht_136, } try: n = op2.reader_geom2._read_double_card( card_name, card_obj, op2._add_methods._add_pbusht_object, methods, data, n) except DoubleCardError: raise op2.log.warning(f'try-except {card_name}') #n = self._read_split_card(data, n, #self._read_cquad8_current, self._read_cquad8_v2001, #card_name, self.add_op2_element) #nelements = op2.card_count['CQUAD8'] #op2.log.debug(f'nCQUAD8 = {nelements}') #n = self._read_dual_card(data, n, self._read_ctriax_8, self._read_ctriax_9, #'CTRIAX', self.add_op2_element) return n
[docs] def read_pbusht_nx_old(self, data: bytes, n: int) -> int: op2: OP2Geom = self.op2 #op2.show_data(data[12:]) ndata = (len(data) - n) // self.factor if ndata % 100 == 0 and ndata % 80 == 0: op2.log.warning(f"skipping PBUSHT in EPT because nfields={ndata//4}, which is " 'nproperties*25 or nproperties*20') return len(data), [] if ndata % 100 == 0: n, props = self._read_pbusht_100(data, n) elif ndata % 80 == 0: n, props = self._read_pbusht_80(data, n) else: # C:\MSC.Software\msc_nastran_runs\mbsh14.op2 # ints = (1, # 51, 51, 0, 0, 0, 0, # 61, 61, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, # 0, '', '', 0, 0, '', '', 0, 0, 925353388, 0, 0, 0, 0, 0, # 7, # 51, 51, 0, 0, 0, 0, # 61, 61, 0, 0, 0, 0, # 0, 0, 0, 0, 0, 0, # 0, '', '', 0, 0, '', '', 0, 0, 925353388, 0, 0, 0, 0, 0) # strings = (b"1 51 51 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\xac\xc5'7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x003\x00\x00\x003\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\xac\xc5'7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",) # ints = (1, 51, 51, 0, 0, 0, 0, 61, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', 0, 0, ' ', ' ', 0, 0, 1e-5, 0, 0, 0, 0 , 0, # # 7, 51, 51, 0, 0, 0, 0, 61, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', 0, 0, ' ', ' ', 0, 0, 1e-5, 0, 0, 0, 0, 0) #op2.show_data(data[n:], types='is') raise NotImplementedError('You have blank lines in your PBUSHT') return n, props
def _read_pbusht_80(self, card_obj, data: bytes, n: int) -> int: """ Word Name Type Description 1 PID I Property identification number 2 TKID(6) I TABLEDi entry identification numbers for stiffness 8 TBID(6) I TABLEDi entry identification numbers for viscous damping 14 TGEID I TABLEDi entry identification number for structural damping 15 TKNID(6) I TABLEDi entry identification numbers for force versus deflection 16,17,18,19,20 ??? """ op2: OP2Geom = self.op2 ntotal = 80 * self.factor struct1 = Struct(op2._endian + b'20i') nentries = (len(data) - n) // ntotal assert nentries > 0, 'table=%r len=%s' % (op2.table_name, len(data) - n) props = [] for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) #(pid, #k1, k2, k3, k4, k5, k6, #b1, b2, b3, b4, b5, b6, #g1, sa, st, ea, et) = out (pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, g1, n1, n2, n3, n4, n5, n6) = out g2 = g3 = g4 = g5 = g6 = g1 k_tables = [k1, k2, k3, k4, k5, k6] b_tables = [b1, b2, b3, b4, b5, b6] ge_tables = [g1, g2, g3, g4, g5, g6] kn_tables = [n1, n2, n3, n4, n5, n6] prop = PBUSHT(pid, k_tables, b_tables, ge_tables, kn_tables) props.append(prop) n += ntotal return n, props def _read_pbusht_100(self, card_obj, data: bytes, n: int) -> int: op2: OP2Geom = self.op2 props = [] ntotal = 100 * self.factor struct1 = Struct(mapfmt(op2._endian + b'25i', self.size)) nentries = (len(data) - n) // ntotal assert nentries > 0, 'table=%r len=%s' % (op2.table_name, len(data) - n) for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) (pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, g1, g2, g3, g4, g5, g6, n1, n2, n3, n4, n5, n6) = out k_tables = [k1, k2, k3, k4, k5, k6] b_tables = [b1, b2, b3, b4, b5, b6] ge_tables = [g1, g2, g3, g4, g5, g6] kn_tables = [n1, n2, n3, n4, n5, n6] prop = PBUSHT(pid, k_tables, b_tables, ge_tables, kn_tables) props.append(prop) n += ntotal return n, props def _read_pbusht_136(self, card_obj, data: bytes, n: int) -> int: r"""not 100% 1 PID I Property identification number 2 TKID(6) I TABLEDi entry identification numbers for stiffness 8 TBID(6) I TABLEDi entry identification numbers for viscous damping 14 TGEID(6) I TABLEDi entry identification number for structural damping 20 TKNID(6) I TABLEDi entry IDs for force vs. deflection 26 FDC(2) CHAR4 Force deflection curve rule 28 FUSE I Failure level 29 DIR I Fuse direction 30 OPTION(2) CHAR4 Failure mode 32 LOWER RS Lower failure bound 33 UPPER RS Upper failure bound 34 FRATE RS FACTOR of scales the stiffness 35 LRGR I Controls large rotation 36 UNDEF(4) none # C:\MSC.Software\msc_nastran_runs\mbsh14.op2 PBUSHT 1 K 51 51 B 61 61 PBUSHT 7 K 51 51 B 61 61 538976288 = ' ' ints = ( 702, 7, 38, 1, (51, 51, 0, 0, 0, 0), (61, 61, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0), 0, 538976288, 538976288, 0, 0, 538976288, 538976288, 0, 0, 925353388, 0, 0, 0, 0, 0, 7, (51, 51, 0, 0, 0, 0), (61, 61, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0), 0, 538976288, 538976288, 0, 0, 538976288, 538976288, 0, 0, 925353388, 0, 0, 0, 0, 0) floats = ( 702, 7, 38, 1, 51, 51, 0.0, 0.0, 0.0, 0.0, 61, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 538976288, 538976288, 0.0, 0.0, 538976288, 538976288, 0.0, 0.0, 1.e-7, 0.0, 0.0, 0.0, 0.0, 0.0, 7, 51, 51, 0.0, 0.0, 0.0, 0.0, 61, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 538976288, 538976288, 0.0, 0.0, 538976288, 538976288, 0.0, 0.0, 1.e-7, 0.0, 0.0, 0.0, 0.0, 0.0) """ op2: OP2Geom = self.op2 props = [] ntotal = 136 * self.factor # k b g n fdc struct1 = Struct(mapfmt(op2._endian + b'i 6i 6i 6i 6i 4s 2i i 5i', self.size)) nentries = (len(data) - n) // ntotal assert nentries > 0, 'table=%r len=%s' % (op2.table_name, len(data) - n) for unused_i in range(nentries): edata = data[n:n+ntotal] out = struct1.unpack(edata) (pid, k1, k2, k3, k4, k5, k6, b1, b2, b3, b4, b5, b6, g1, g2, g3, g4, g5, g6, n1, n2, n3, n4, n5, n6, word1, a, word2, c, *other) = out k_tables = [ki if ki != 538976288 else 0 for ki in [k1, k2, k3, k4, k5, k6]] b_tables = [bi if bi != 538976288 else 0 for bi in [b1, b2, b3, b4, b5, b6]] ge_tables = [gei if gei != 538976288 else 0 for gei in [g1, g2, g3, g4, g5, g6]] kn_tables = [kni if kni != 538976288 else 0 for kni in [n1, n2, n3, n4, n5, n6]] op2.log.warning( f'PBUSHT: pid={pid} ' f'k={k_tables} ' f'b={b_tables} ' f'ge={ge_tables} ' f'n={kn_tables} ' + 'words=' + str([word1, a, word2, c]) + f' other={other}') assert sum(other) == 0, other prop = PBUSHT(pid, k_tables, b_tables, ge_tables, kn_tables) props.append(prop) n += ntotal return n, props
[docs] def read_pcomp(self, data: bytes, n: int) -> int: r""" PCOMP(2706,27,287) - the marker for Record 22 standard: EPTS; 64-bit: C:\MSC.Software\simcenter_nastran_2019.2\tpl_post1\cqrdbxdra3lg.op2 optistruct: ints = (2706, 27, 287, 5, 3, -2.75, 0, 0, 1, 0, 0, 2, 0.25, 0, 2, # why is sout=2? 3, 5.0, 0, 3, # why is sout=3? 2, 0.25, 0, 2, # why is sout=2? 6, 5, -3.0, 0, 0, 1, 0, 0, 2, 0.25, 0, 2, 2, 0.25, 0, 2, 3, 5.0, 0, 3, 2, 0.25, 0, 2, 2, 0.25, 0, 2, 7, 7, -1068498944, 0, 0, 1, 0, 0, 2, 0.25, 0, 2, 2, 0.25, 0, 2, 2, 0.25, 0, 2, 3, 5.0, 0, 3, 2, 0.25, 0, 2, 2, 0.25, 0, 2, 2, 0.25, 0, 2) floats = (2706, 27, 287, 5, 3, -2.75, 0.0, 0.0, 1, 0.0, 0.0, 2, 0.25, 0.0, 2, 3, 5.0, 0.0, 3, 2, 0.25, 0.0, 2, 6, 5, -3.0, 0.0, 0.0, 1, 0.0, 0.0, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2, 3, 5.0, 0.0, 3, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2, 9.80908925027372e-45, 9.80908925027372e-45, -3.25, 0.0, 0.0, 1, 0.0, 0.0, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2, 3, 5.0, 0.0, 3, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2, 2, 0.25, 0.0, 2) """ op2: OP2Geom = self.op2 if self.size == 4: n2, props = self._read_pcomp_32_bit(data, n) nproperties = len(props) for prop in props: self._add_op2_property(prop) op2.card_count['PCOMP'] = nproperties else: n2 = op2.reader_geom2._read_dual_card( data, n, self._read_pcomp_32_bit, self._read_pcomp_64_bit, 'PCOMP', self._add_op2_property) return n2
def _read_pcomp_64_bit(self, data: bytes, n: int) -> tuple[int, list[PCOMP]]: r""" PCOMP(2706,27,287) - the marker for Record 22 1 PID I Property identification number 2 N(C) I Number of plies 3 Z0 RS Distance from the reference plane to the bottom surface 4 NSM RS Nonstructural mass per unit area 5 SB RS Allowable shear stress of the bonding material 6 FT I Failure theory 7 TREF RS Reference temperature 8 GE RS Damping coefficient 9 MID I Material identification number 10 T RS Thicknesses of the ply 11 THETA RS Orientation angle of the longitudinal direction of the ply 12 SOUT I Stress or strain output request of the ply Words 9 through 12 repeat N times TODO: 64-bit bug: why is the number of plies 0??? doubles (float64) = ( 1, 0.0, 1.7368e-18, 0.0, 1.0, 1.5e-323, 0.0, 0.0, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, -1, -1, -1, -1, 21, 0.0, 1.7368e-18, 0.0, 1.0, 1.5e-323, 0.0, 0.0, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, -1, -1, -1, -1) long long (int64) = ( 1, 0, 1.7368e-18, 0, 1.0, 3, 0, 0, 1, 4592590756007337001, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, -1, -1, -1, -1, 21, 0, 4341475431749739292, 0, 4607182418800017408, 3, 0, 0, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, 1, 0.11, 0, 1, -1, -1, -1, -1) doubles (float64) = (5e-324, 0.0, -0.005, 0.0, 0.0, 0.0, 0.0, 0.0, 4e-323, 0.005, 0.0, 5e-324, 4e-323, 0.005, 0.0, 5e-324, nan, nan, nan, nan) long long (int64) = (1, 0, -4650957407178058629, 0, 0, 0, 0, 0, 8, 4572414629676717179, 0, 1, 8, 4572414629676717179, 0, 1, -1, -1, -1, -1) C:\MSC.Software\simcenter_nastran_2019.2\tpl_post2\dbxdr12lg.op2 data = (3321, 2, -0.5, 0.0, 1.0, 4, 0.0, 0.0, 3, 0.5, 0, 1, 3, 0.5, 0, 1) """ op2: OP2Geom = self.op2 op2.to_nx(' because PCOMP-64 was found') nproperties = 0 s1 = Struct(mapfmt(op2._endian + b'2i3fi2f', self.size)) ntotal1 = 32 * self.factor s2 = Struct(mapfmt(op2._endian + b'i2fi', self.size)) four_minus1 = Struct(mapfmt(op2._endian + b'4i', self.size)) ndata = len(data) ntotal2 = 16 * self.factor props = [] while n < (ndata - ntotal1): out = s1.unpack(data[n:n+ntotal1]) (pid, nlayers, z0, nsm, sb, ft, tref, ge) = out assert pid > 0 if op2.binary_debug: op2.binary_debug.write(f'PCOMP pid={pid} nlayers={nlayers} z0={z0} nsm={nsm} ' f'sb={sb} ft={ft} Tref={tref} ge={ge}') assert isinstance(nlayers, int), out #print(f'PCOMP pid={pid} nlayers={nlayers} z0={z0} nsm={nsm} ' #f'sb={sb} ft={ft} Tref={tref} ge={ge}') n += ntotal1 # None, 'SYM', 'MEM', 'BEND', 'SMEAR', 'SMCORE', 'NO' is_symmetrical = 'NO' #if nlayers < 0: #is_symmetrical = 'SYM' #nlayers = abs(nlayers) mids = [] T = [] thetas = [] souts = [] edata2 = data[n:n+ntotal2] idata = four_minus1.unpack(edata2) while idata != (-1, -1, -1, -1): (mid, t, theta, sout) = s2.unpack(edata2) mids.append(mid) T.append(t) thetas.append(theta) souts.append(sout) if op2.is_debug_file: op2.binary_debug.write(f' mid={mid} t={t} theta={theta} sout={sout}\n') n += ntotal2 #print(f' mid={mid} t={t} theta={theta} sout={sout}') edata2 = data[n:n+ntotal2] if n == ndata: op2.log.warning(' no (-1, -1, -1, -1) flag was found to close the PCOMPs') break idata = four_minus1.unpack(edata2) if self.size == 4: assert 0 < nlayers < 400, 'pid=%s nlayers=%s z0=%s nms=%s sb=%s ft=%s Tref=%s ge=%s' % ( pid, nlayers, z0, nsm, sb, ft, tref, ge) else: assert nlayers == 0, nlayers nlayers = len(mids) data_in = [ pid, z0, nsm, sb, ft, tref, ge, is_symmetrical, mids, T, thetas, souts] prop = PCOMP.add_op2_data(data_in) nproperties += 1 n += ntotal2 props.append(prop) return n, props def _read_pcomp_32_bit(self, data: bytes, n: int) -> tuple[int, list[PCOMP]]: # pragma: no cover """PCOMP(2706,27,287) - the marker for Record 22""" op2: OP2Geom = self.op2 nproperties = 0 s1 = Struct(mapfmt(op2._endian + b'2i3fi2f', self.size)) ntotal1 = 32 * self.factor s2 = Struct(mapfmt(op2._endian + b'i2fi', self.size)) ndata = len(data) ntotal2 = 16 * self.factor props = [] while n < (ndata - ntotal1): out = s1.unpack(data[n:n+ntotal1]) (pid, nlayers, z0, nsm, sb, ft, tref, ge) = out assert pid > 0 if op2.binary_debug: op2.binary_debug.write(f'PCOMP pid={pid} nlayers={nlayers} z0={z0} nsm={nsm} ' f'sb={sb} ft={ft} Tref={tref} ge={ge}') assert isinstance(nlayers, int), out #print(f'PCOMP pid={pid} nlayers={nlayers} z0={z0} nsm={nsm} ' #f'sb={sb} ft={ft} Tref={tref} ge={ge}') n += ntotal1 mids = [] T = [] thetas = [] souts = [] # None, 'SYM', 'MEM', 'BEND', 'SMEAR', 'SMCORE', 'NO' is_symmetrical = 'NO' if nlayers < 0: is_symmetrical = 'SYM' nlayers = abs(nlayers) assert nlayers > 0, out assert 0 < nlayers < 400, 'pid=%s nlayers=%s z0=%s nsm=%s sb=%s ft=%s Tref=%s ge=%s' % ( pid, nlayers, z0, nsm, sb, ft, tref, ge) if op2.is_debug_file: op2.binary_debug.write(' pid=%s nlayers=%s z0=%s nsm=%s sb=%s ft=%s Tref=%s ge=%s\n' % ( pid, nlayers, z0, nsm, sb, ft, tref, ge)) #if op2._nastran_format == 'optistruct': #print(' pid=%s nlayers=%s z0=%s nsm=%s sb=%s ft=%s Tref=%s ge=%s' % ( #pid, nlayers, z0, nsm, sb, ft, tref, ge)) for unused_ilayer in range(nlayers): (mid, t, theta, sout) = s2.unpack(data[n:n+ntotal2]) if op2._nastran_format == 'optistruct': #print(f' mid={mid} t={t} theta={theta} sout={sout}') if sout in [2, 3]: # TODO: Why is this 2/3? sout = 1 # YES mids.append(mid) assert mid > 0 T.append(t) thetas.append(theta) souts.append(sout) if op2.is_debug_file: op2.binary_debug.write(f' mid={mid} t={t} theta={theta} sout={sout}\n') n += ntotal2 data_in = [ pid, z0, nsm, sb, ft, tref, ge, is_symmetrical, mids, T, thetas, souts] prop = PCOMP.add_op2_data(data_in) #print(prop) props.append(prop) nproperties += 1 return n, props
[docs] def read_pcompg(self, data: bytes, n: int) -> int: """ PCOMP(2706,27,287) 1 PID I Property identification number 2 LAMOPT I Laminate option 3 Z0 RS Distance from the reference plane to the bottom surface 4 NSM RS Nonstructural mass per unit area 5 SB RS Allowable shear stress of the bonding material 6 FT I Failure theory 7 TREF RS Reference temperature 8 GE RS Damping coefficient 9 GPLYIDi I Global ply IDs. 10 MID I Material identification number 11 T RS Thicknesses of the ply 12 THETA RS Orientation angle of the longitudinal direction of the ply 13 SOUT I Stress or strain output request of the ply Words 9 through 13 repeat N times (until -1, -1, -1, -1, -1 as Nplies doesn't exist...) float = (15006, 150, 604, 5, 0.0, 1.7368e-18, 0.0, 0.0, 0.0, 20.0, 0.0, 5e-324, 5e-324, 2.0, 0.0, 0.0, 1e-323, 1e-323, 3.0, 0.0, 0.0, 1.5e-323, 1e-323, 3.0, 0.0, 0.0, 2e-323, 5e-324, 2.0, 0.0, 0.0, nan, nan, nan, nan, nan) int = (15006, 150, 604, 5, 0, 1.7368e-18, 0, 0, 0, 20.0, 0, 1, 1, 4611686018427387904, 0, 0, 2, 2, 4613937818241073152, 0, 0, 3, 2, 4613937818241073152, 0, 0, 4, 1, 4611686018427387904, 0, 0, -1, -1, -1, -1, -1) """ op2: OP2Geom = self.op2 nproperties = 0 s1 = Struct(mapfmt(op2._endian + b'2i 3f i 2f', self.size)) s2 = Struct(mapfmt(op2._endian + b'2i 2f i', self.size)) struct_i5 = Struct(mapfmt(op2._endian + b'5i', self.size)) # lam - SYM, MEM, BEND, SMEAR, SMCORE, None lam_map = { 0 : None, # MEM # BEND # SMEAR # SMCORE } # ft - HILL, HOFF, TSAI, STRN, None ft_map = { 0 : None, # HILL # HOFF 3 : 'TSAI', # STRN } # sout - YES, NO sout_map = { 0 : 'NO', 1 : 'YES', } ndata = len(data) #op2.show_data(data, types='qd') ntotal1 = 32 * self.factor ntotal2 = 20 * self.factor while n < (ndata - ntotal1): out = s1.unpack(data[n:n+ntotal1]) (pid, lam_int, z0, nsm, sb, ft_int, tref, ge) = out if op2.binary_debug: op2.binary_debug.write(f'PCOMPG pid={pid} lam_int={lam_int} z0={z0} nsm={nsm} ' f'sb={sb} ft_int={ft_int} tref={tref} ge={ge}') #print(f'PCOMPG pid={pid} lam_int={lam_int} z0={z0} nsm={nsm} sb={sb} ' #f'ft_int={ft_int} tref={tref} ge={ge}') assert isinstance(lam_int, int), out assert pid > -1, out n += ntotal1 mids = [] thicknesses = [] thetas = [] souts = [] global_ply_ids = [] # None, 'SYM', 'MEM', 'BEND', 'SMEAR', 'SMCORE', 'NO' #is_symmetrical = 'NO' #if nlayers < 0: #is_symmetrical = 'SYM' #nlayers = abs(nlayers) #assert nlayers > 0, out #assert 0 < nlayers < 400, 'pid=%s nlayers=%s z0=%s nms=%s sb=%s ft=%s tref=%s ge=%s' % ( #pid, nlayers, z0, nsm, sb, ft, tref, ge) #if op2.is_debug_file: #op2.binary_debug.write(' pid=%s nlayers=%s z0=%s nms=%s sb=%s ft=%s tref=%s ge=%s\n' % ( #pid, nlayers, z0, nsm, sb, ft, tref, ge)) ilayer = 0 while ilayer < 1000: ints5 = struct_i5.unpack(data[n:n+ntotal2]) if ints5 == (-1, -1, -1, -1, -1): if op2.is_debug_file: op2.binary_debug.write(' global_ply=%-1 mid=%-1 t=%-1 theta=%-1 sout=-1\n') break (global_ply, mid, t, theta, sout_int) = s2.unpack(data[n:n+ntotal2]) #print(' ', (global_ply, mid, t, theta, sout_int)) try: sout = sout_map[sout_int] except KeyError: op2.log.error('cant parse global_ply=%s sout=%s; assuming 0=NO' % ( global_ply, sout_int)) sout = 'NO' global_ply_ids.append(global_ply) mids.append(mid) thicknesses.append(t) thetas.append(theta) souts.append(sout) if op2.is_debug_file: op2.binary_debug.write(' global_ply=%s mid=%s t=%s theta=%s sout_int=%s sout=%r\n' % ( global_ply, mid, t, theta, sout_int, sout)) n += ntotal2 ilayer += 1 n += ntotal2 try: ft = ft_map[ft_int] except KeyError: op2.log.error('pid=%s cant parse ft=%s; should be HILL, HOFF, TSAI, STRN' '...skipping' % (pid, ft_int)) continue try: lam = lam_map[lam_int] except KeyError: op2.log.error('pid=%s cant parse lam=%s; should be HILL, HOFF, TSAI, STRN' '...skipping' % (pid, lam_int)) continue # apparently Nastran makes duplicate property ids... if pid in op2.properties and op2.properties[pid].type == 'PCOMP': del op2.properties[pid] op2.add_pcompg(pid, global_ply_ids, mids, thicknesses, thetas=thetas, souts=souts, nsm=nsm, sb=sb, ft=ft, tref=tref, ge=ge, lam=lam, z0=z0, comment='') nproperties += 1 op2.card_count['PCOMPG'] = nproperties return n
# PCOMPA
[docs] def read_pconeax(self, data: bytes, n: int) -> int: """ (152,19,147) - Record 24 """ self.op2.log.info('geom skipping PCONEAX in EPT') return len(data)
[docs] def read_pconv(self, data: bytes, n: int) -> int: """common method for reading PCONVs""" op2: OP2Geom = self.op2 #n = self._read_dual_card(data, n, self._read_pconv_nx, self._read_pconv_msc, #'PCONV', self._add_pconv) card_name = 'PCONV' card_obj = PCONV methods = { 16 : self._read_pconv_nx_16, # 16=4*4 56 : self._read_pconv_msc_56, # 56=4*14 } try: n, elements = op2.reader_geom2._read_double_card_load( card_name, card_obj, methods, data, n) except DoubleCardError: nx_method = partial(self._read_pconv_nx_16, card_obj) msc_method = partial(self._read_pconv_msc_56, card_obj) n, elements = op2._read_dual_card_load( data, n, nx_method, msc_method, card_name, self._add_op2_property) nelements = len(elements) for prop in elements: key = prop.pconid if key in op2.convection_properties: prop_old = op2.convection_properties[key] if prop != prop_old: op2.log.warning(prop.raw_fields()) op2.log.warning(prop_old.raw_fields()) op2.log.warning(f'PCONV pconid={key}; old, new\n{prop_old}{prop}') # this will fail due to a duplicate id self._add_pconv(prop) #else: # already exists else: self._add_pconv(prop) op2.card_count['PCONV'] = nelements return n
def _read_pconv_nx_16(self, card_obj: PCONV, data: bytes, n: int) -> int: """ (11001,110,411)- NX version """ op2: OP2Geom = self.op2 ntotal = 16 # 4*4 nentries = (len(data) - n) // ntotal assert (len(data) - n) % ntotal == 0 props = [] struct_3if = Struct(op2._endian + b'3if') for unused_i in range(nentries): out = struct_3if.unpack(data[n:n+ntotal]) (pconid, mid, form, expf) = out ftype = tid = chlen = gidin = ce = e1 = e2 = e3 = None data_in = (pconid, mid, form, expf, ftype, tid, chlen, gidin, ce, e1, e2, e3) prop = PCONV.add_op2_data(data_in) props.append(prop) n += ntotal return n, props def _read_pconv_msc_56(self, card_obj: PCONV, data: bytes, n: int) -> int: """ (11001,110,411)- MSC version - Record 25 """ op2: OP2Geom = self.op2 ntotal = 56 # 14*4 s = Struct(op2._endian + b'3if 4i fii 3f') nentries = (len(data) - n) // ntotal assert (len(data) - n) % ntotal == 0 props = [] for unused_i in range(nentries): out = s.unpack(data[n:n+ntotal]) (pconid, mid, form, expf, ftype, tid, unused_undef1, unused_undef2, chlen, gidin, ce, e1, e2, e3) = out data_in = (pconid, mid, form, expf, ftype, tid, chlen, gidin, ce, e1, e2, e3) prop = PCONV.add_op2_data(data_in) props.append(prop) n += ntotal return n, props
[docs] def read_pconvm(self, data: bytes, n: int) -> int: """Record 24 -- PCONVM(2902,29,420) 1 PID I Property identification number 2 MID I Material identification number 3 FORM I Type of formula used for free convection 4 FLAG I Flag for mass flow convection 5 COEF RS Constant coefficient used for forced convection 6 EXPR RS Reynolds number convection exponent 7 EXPPI RS Prandtl number convection exponent into the working fluid 8 EXPPO RS Prandtl number convection exponent out of the working fluid """ op2: OP2Geom = self.op2 ntotal = 32 # 8*4 structi = Struct(op2._endian + b'4i 4f') nentries = (len(data) - n) // ntotal for unused_i in range(nentries): out = structi.unpack(data[n:n+ntotal]) if out != (0, 0, 0, 0, 0., 0., 0., 0.): (pconid, mid, form, flag, coeff, expr, expri, exppo) = out #print(out) prop = PCONVM(pconid, mid, coeff, form=form, flag=flag, expr=expr, exppi=expri, exppo=exppo, comment='') op2._add_methods._add_convection_property_object(prop) n += ntotal op2.card_count['PCONVM'] = nentries return n
[docs] def read_pdamp(self, data: bytes, n: int) -> int: """ PDAMP(202,2,45) - the marker for Record ??? """ op2: OP2Geom = self.op2 ntotal = 8 * self.factor # 2*4 struct_if = Struct(mapfmt(op2._endian + b'if', self.size)) nentries = (len(data) - n) // ntotal for unused_i in range(nentries): out = struct_if.unpack(data[n:n+ntotal]) #(pid, b) = out prop = PDAMP.add_op2_data(out) self._add_op2_property(prop) n += ntotal op2.card_count['PDAMP'] = nentries return n
[docs] def read_pdampt(self, data: bytes, n: int) -> int: # 26 self.op2.log.info('geom skipping PDAMPT in EPT') return len(data)
[docs] def read_pdamp5(self, data: bytes, n: int) -> int: # 26 """ Word Name Type Description 1 PID I Property identification number 2 MID I Material identification number 3 B RS Damping multiplier """ op2: OP2Geom = self.op2 ntotal = 3 * self.size struct_if = Struct(mapfmt(op2._endian + b'2if', self.size)) ndatai = len(data) - n nentries = ndatai // ntotal assert ndatai % ntotal == 0 for unused_i in range(nentries): pid, mid, b = struct_if.unpack(data[n:n+ntotal]) #(pid, b) = out prop = op2.add_pdamp5(pid, mid, b) self._add_op2_property(prop) n += ntotal op2.card_count['PDAMP5'] = nentries return len(data)
# PDUM1 # PDUM2 # PDUM3 # PDUM4 # PDUM5 # PDUM6 # PDUM7 # PDUM8 # PDUM9
[docs] def read_pelas(self, data: bytes, n: int) -> int: """PELAS(302,3,46) - the marker for Record 39""" op2: OP2Geom = self.op2 ntotal = 16 * self.factor # 4*4 nproperties = (len(data) - n) // ntotal struct_i3f = Struct(mapfmt(op2._endian + b'i3f', self.size)) for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_i3f.unpack(edata) #(pid, k, ge, s) = out if op2.is_debug_file: op2.binary_debug.write(' PELAS=%s\n' % str(out)) prop = PELAS.add_op2_data(out) self._add_op2_property(prop) n += ntotal op2.card_count['PELAS'] = nproperties return n
[docs] def read_pfast_msc(self, data: bytes, n: int) -> int: r""" Word Name Type Description 1 PID I Property identification number 2 MID I Material property identification number 3 D RS Diameter of the fastener 4 CONNBEH I Connection behavior (0=FF/F, 1=FR, 10=RF/R, 11=RR) 5 CONNTYPE I Connection type (0=clamp, 1=hinge, 2=bolt) 6 EXTCON I External constraint flag (0=off, 1=on) 7 CONDTYPE I Condition type (0=rigid, 1=equivalent) 8 WELDTYPE I Weld type (0=spot weld, 1=but seam, 2=T-seam) 9 MINLEN RS Minimum length of spot weld 10 MAXLEN RS Maximum length of spot weld 11 GMCHK I Perform geometry check 12 SPCGS I SPC the master grid GS 13 CMASS RS Concentrated mass 14 GE RS Structureal Damping 15 UNDEF(3) none Not used 18 MCID I Element stiffness coordinate system 19 MFLAG I Defined the coordinate system type 20 KT(3) RS Stiffness values in direction 1 23 KR(3) RS Rotation stiffness values in direction 1 C:\MSC.Software\msc_nastran_runs\cfmass.op2 pid mid D con con ext cond weld min max chk spc cmass ge und und und mcid mfag kt1 kt2 kt3 kr1 kr2 kr3 ints = (99, 0, 0.1, 0, 0, 0, 0, -1, 0.2, 5.0, 0, 0, 7.9, 0, 0, 0, 0, -1, 0, 471200.0, 181200.0, 181200.0, 226.6, 45610.0, 45610.0) floats = (99, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, -1, 0.2, 5.0, 0.0, 0.0, 7.9, 0.0, 0.0, 0.0, 0.0, -1, 0.0, 471200.0, 181200.0, 181200.0, 226.6, 45610.0, 45610.0) """ op2: OP2Geom = self.op2 #op2.show_data(data[n:], types='ifs') #ntotal = 92 * self.factor # 26*4 #struct1 = Struct(op2._endian + b'ifii 3f') ntotal = 100 * self.factor # 25*4 ndatai = len(data) - n nproperties = ndatai // ntotal delta = ndatai % ntotal assert delta == 0, 'len(data)-n=%s n=%s' % (ndatai, ndatai / 100.) struct1 = Struct(op2._endian + b'2if 5i 2f2i2f 3i 2i 6f') for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct1.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PFAST=%s\n' % str(out)) (pid, mid, d, unused_connbeh, unused_conntype, unused_extcon, unused_condtype, unused_weldtype, unused_minlen, unused_maxlen, unused_gmcheck, unused_spcgs, mass, ge, unused_aa, unused_bb, unused_cc, mcid, mflag, kt1, kt2, kt3, kr1, kr2, kr3) = out #(pid, d, mcid, mflag, kt1, kt2, kt3, #kr1, kr2, kr3, mass, ge) = data data_in = (pid, d, mcid, mflag, kt1, kt2, kt3, kr1, kr2, kr3, mass, ge) assert isinstance(d, float), d prop = PFAST.add_op2_data(data_in) str(prop) #print(prop) self._add_op2_property(prop) n += ntotal op2.card_count['PFAST'] = nproperties return n
[docs] def read_pfast_nx(self, data: bytes, n: int) -> int: """ PFAST(3601,36,55) NX only Word Name Type Description 1 PID I Property identification number 2 D RS Diameter of the spot weld 3 MCID I Element stiffness coordinate system 4 MFLAG I Defines MCID as absolute or relative 5-7 KT(3) RS Translational stiffness 8-10 KR(3) RS Rotational stiffness """ op2: OP2Geom = self.op2 ntotal = 48 * self.factor nproperties = (len(data) - n) // ntotal delta = (len(data) - n) % ntotal assert delta == 0, 'len(data)-n=%s n=%s' % (len(data) - n, (len(data) - n) / 48.) struct1 = Struct(op2._endian + b'ifii 8f') for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct1.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PFAST=%s\n' % str(out)) (pid, d, mcid, mflag, kt1, kt2, kt3, kr1, kr2, kr3, mass, ge) = out data_in = (pid, d, mcid, mflag, kt1, kt2, kt3, kr1, kr2, kr3, mass, ge) assert isinstance(d, float), d prop = PFAST.add_op2_data(data_in) self._add_op2_property(prop) n += ntotal op2.card_count['PFAST'] = nproperties op2.to_nx(' because PFAST-NX was found') return n
[docs] def read_pelast(self, data: bytes, n: int) -> int: """ Record 41 -- PELAST(1302,13,34) 1 PID I Property identification number 2 TKID I TABLEDi entry identification number for stiffness 3 TGEID I TABLEDi entry identification number for structural damping 4 TKNID I TABLEDi entry """ op2: OP2Geom = self.op2 ntotal = 16 * self.factor struct_4i = Struct(mapfmt(op2._endian + b'4i', self.size)) nproperties = (len(data) - n) // ntotal for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_4i.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PELAST=%s\n' % str(out)) #(pid, tkid, tgeid, tknid) = out prop = PELAST.add_op2_data(out) op2._add_methods._add_pelast_object(prop) n += ntotal op2.card_count['PELAST'] = nproperties return n
[docs] def read_pgap(self, data: bytes, n: int) -> int: """ PGAP(2102,21,121) - the marker for Record 42 """ op2: OP2Geom = self.op2 ntotal = 44 * self.factor struct_i10f = Struct(mapfmt(op2._endian + b'i10f', self.size)) nproperties = (len(data) - n) // ntotal for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_i10f.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PGAP=%s\n' % str(out)) #(pid,u0,f0,ka,kb,kt,mu1,mu2,tmax,mar,trmin) = out prop = PGAP.add_op2_data(out) self._add_op2_property(prop) n += ntotal op2.card_count['PGAP'] = nproperties return n
[docs] def read_phbdy(self, data: bytes, n: int) -> int: """ PHBDY(2802,28,236) - the marker for Record 43 """ op2: OP2Geom = self.op2 nproperties = (len(data) - n) // 16 struct_i3f = Struct(op2._endian + b'ifff') for unused_i in range(nproperties): edata = data[n:n+16] out = struct_i3f.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PHBDY=%s\n' % str(out)) #(pid, af, d1, d2) = out prop = PHBDY.add_op2_data(out) op2._add_methods._add_phbdy_object(prop) n += 16 op2.card_count['PHBDY'] = nproperties return n
[docs] def read_pintc(self, data: bytes, n: int) -> int: # pragma: no cover raise UnsupportedCard('PINTC') self.op2.log.info('geom skipping PINTC in EPT') return len(data)
[docs] def read_pints(self, data: bytes, n: int) -> int: # pragma: no cover raise UnsupportedCard('PINTS') self.op2.log.info('geom skipping PINTS in EPT') return len(data)
[docs] def read_pbeam3(self, data: bytes, n: int) -> int: op2: OP2Geom = self.op2 card_name = 'PBUSHT' card_obj = PBUSHT methods = { 264 : self._read_pbeam3_264, 456 : self._read_pbeam3_456, } try: n = op2.reader_geom2._read_double_card( card_name, card_obj, self._add_op2_property, methods, data, n) except DoubleCardError: raise op2.log.warning(f'try-except {card_name}') return n
def _read_pbeam3_456(self, card_obj, data: bytes, n: int) -> int: r""" # per C:\MSC.Software\msc_nastran_runs\b3plod3.op2 ints = (2201, 1, 1.0, 0.1833, 0.0833, 0, -1.0, 0, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 2, 1.0, 0.1833, 0.0833, 0, -1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1.0, 0.1833, 0.0833, 0, -1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.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, 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, 0, 0, 0, 2901, 2, 0.1, 0.1, 0.1, 0, 0.2, 0, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5, 2, 0.1, 0.1, 0.1, 0, 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0.1, 0.1, 0.1, 0, 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.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, 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, 0, 0, 0) floats = (2201, 1, 1.0, 0.1833, 0.0833, 0.0, -1.0, 0.0, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 2, 1.0, 0.1833, 0.0833, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2, 1.0, 0.1833, 0.0833, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.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.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.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.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.0, 0.0, 0.0, 2901, 2, 0.1, 0.1, 0.1, 0.0, 0.2, 0.0, 0.5, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, -0.5, 2, 0.1, 0.1, 0.1, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2, 0.1, 0.1, 0.1, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.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.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.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.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.0, 0.0, 0.0) """ op2: OP2Geom = self.op2 #op2.show_data(data[n:]) ntotal = 456 * self.factor # 114*4 # struct1 = Struct(mapfmt(op2._endian + b'2i' # pid, mid b'3f' # A, Iy, Iz b'5f' # # a, b, c, d, e b'5f fi 14f i' #fj ki 14f i b'2i3f' #aa-ee - good b'5f' #ff-jj b'5f' #kk-oo b'5f' #pp-tt b'6f' #uu-zz b'5f' #aaa-eee b'4i' #fff-iii # jjj-ooo b'2f iii f' # ppp-ttt b'5f' # uuu-zzz b'6f' b'30f', self.size)) ndatai = len(data) - n nentries = ndatai // ntotal assert ndatai % ntotal == 0 props = [] for unused_i in range(nentries): #print(n, ntotal) datai = data[n:n+ntotal] #op2.show_data(datai, types='ifqd') n += ntotal (pid, mid, A, iz, iy, a, b, c, d, e, f, g, h, i, j, k, inta, l, m, ni, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, cc, dd, ee, ff, gg, hh, ii, jj, kk, ll, mm, nn, oo, pp, qq, rr, ss, tt, uu, vv, ww, xx, yy, zz, aaa, bbb, ccc, ddd, eee, fff, ggg, hhh, iii, jjj, kkk, lll, mmm, nnn, ooo, ppp, qqq, rrr, sss, ttt, uuu, vvv, www, xxx, yyy, zzz, *other) = struct1.unpack(datai) #print(pid, mid, A, iz, iy) #print('a-e', (a, b, c, d, e)) #print('f-j', (f, g, h, i, j)) #print(k, inta, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) #print('aa-ee', (aa, bb, cc, dd, ee)) #print('ff-jj', (ff, gg, hh, ii, jj)) #print('kk-oo', (kk, ll, mm, nn, oo)) #print('pp-tt', (pp, qq, rr, ss, tt)) #print('uu-zz', (uu, vv, ww, xx, yy, zz)) #print('aaa-eee', (aaa, bbb, ccc, ddd, eee)) #print('fff-jjj', (fff, ggg, hhh, iii)) #print('jjj-ooo', (jjj, kkk, lll, mmm, nnn, ooo)) #print('ppp-ttt', (ppp, qqq, rrr, sss, ttt)) #print('uuu-zzz', (uuu, vvv, www, xxx, yyy, zzz)) if mid == 0: continue #assert sum(other) < 100, other prop = PBEAM3( pid, mid, A, iz, iy, iyz=None, j=None, nsm=0., so=None, cy=None, cz=None, dy=None, dz=None, ey=None, ez=None, fy=None, fz=None, ky=1., kz=1., ny=None, nz=None, my=None, mz=None, nsiy=None, nsiz=None, nsiyz=None, cw=None, stress='GRID', w=None, wy=None, wz=None, comment='') assert pid > 0, prop.get_stats() assert mid > 0, prop.get_stats() str(prop) props.append(prop) #self._add_op2_property(prop) #op2.card_count['PBEAM3'] = nentries return n, props def _read_pbeam3_264(self, card_obj, data: bytes, n: int) -> int: """ TODO: partial # per test_cbeam_cbeam3??? ints = (2901, 2, 0.1, 0.1, 0.1, 0, 0.02, 0, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5, 2, 0.1, 0.1, 0.1, 0, 0.02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0.1, 0.1, 0.1, 0, 0.02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0) floats = (2901, 2, 0.1, 0.1, 0.1, 0.0, 0.02, 0.0, 0.5, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0, -0.5, 2, 0.1, 0.1, 0.1, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2, 0.1, 0.1, 0.1, 0.0, 0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.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, nan, 0.0, 0.0) """ op2: OP2Geom = self.op2 ntotal = 264 * self.factor # 66*4 # p/m ayz ae fj ki 14f i struct1 = Struct(mapfmt(op2._endian + b'2i 3f 5f 5f fi 14f i 30f 4i', self.size)) ndatai = len(data) - n nentries = ndatai // ntotal assert ndatai % ntotal == 0 props = [] for unused_i in range(nentries): pid, mid, A, iz, iy, a, b, c, d, e, f, g, h, i, j, k, inta, *other = struct1.unpack(data[n:n+ntotal]) #print(pid, mid, A, iz, iy) #print((a, b, c, d, e)) #print((f, g, h, i, j)) #print(k, inta) assert sum(other) < 100, other prop = PBEAM3( pid, mid, A, iz, iy, iyz=None, j=None, nsm=0., so=None, cy=None, cz=None, dy=None, dz=None, ey=None, ez=None, fy=None, fz=None, ky=1., kz=1., ny=None, nz=None, my=None, mz=None, nsiy=None, nsiz=None, nsiyz=None, cw=None, stress='GRID', w=None, wy=None, wz=None, comment='') assert pid > 0, prop.get_stats() assert mid > 0, prop.get_stats() str(prop) props.append(prop) n += ntotal return n, props def _read_fake_16502(self, data: bytes, n: int) -> int: """(16502, 165, 916)""" op2: OP2Geom = self.op2 op2.show_data(data) asdf
[docs] def read_pmic(self, data: bytes, n: int) -> int: r""" (7001, 70, 632) What is the type???? Pid ??? should be NX, but also checked MSC...need an example related to acoustics not AEPARM C:\MSC.Software\simcenter_nastran_2019.2\tpl_post2\atv005mat.op2 it's a PMIC C:\MSC.Software\simcenter_nastran_2019.2\tpl_post1\acssn100_2.op2 """ op2: OP2Geom = self.op2 ints = np.frombuffer(data[n:], dtype=op2.idtype8) for val in ints: op2.add_pmic(val) nentries = len(ints) op2.card_count['PMIC'] = nentries return len(data)
[docs] def read_pplane(self, data: bytes, n: int) -> int: """ RECORD – PPLANE(3801,38,979) Word Name Type Description 1 PID I Property identification number 2 MID I Material identification number 3 T RS Default membrane thickness for Ti on the connection entry 4 NSM RS Nonstructural mass per unit area 5 FOROPT I Formulation option number 6 CSOPT I Reserved for coordinate system definition of plane 7 UNDEF(2) None ints = (1, 1, 1.0, 0, 0, 0, 0, 0, 2, 2, 1.0, 0, 0, 0, 0, 0) floats = (1, 1, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2, 2, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0) """ op2: OP2Geom = self.op2 ntotal = 32 * self.factor # 8*4 struct1 = Struct(mapfmt(op2._endian + b'2i 2f 4i', self.size)) ndatai = len(data) - n nentries = ndatai // ntotal assert ndatai % ntotal == 0 for unused_i in range(nentries): out = struct1.unpack(data[n:n+ntotal]) pid, mid, t, nsm, foropt, csopt = out[:6] #print(out) assert csopt == 0, csopt pplane = op2.add_pplane(pid, mid, t=t, nsm=nsm, formulation_option=foropt) pplane.validate() #print(pplane) str(pplane) n += ntotal op2.card_count['PLPLANE'] = nentries return n
[docs] def read_plplane(self, data: bytes, n: int) -> int: """ PLPLANE(4606,46,375) NX 10 1 PID I Property identification number 2 MID I Material identification number 3 CID I Coordinate system identification number 4 STR CHAR4 Location of stress and strain output 5 T RS Default membrane thickness for Ti on the connection entry 6 CSOPT I Reserved for coordinate system definition of plane 7 UNDEF(5) None MSC 2016 PID I Property identification number 2 MID I Material identification number 3 CID I Coordinate system identification number 4 STR CHAR4 Location of stress and strain output 5 UNDEF(7 ) none Not used .. warning:: CSOPT ad T are not supported """ op2: OP2Geom = self.op2 ntotal = 44 * self.factor # 4*11 if self.size == 4: s = Struct(op2._endian + b'3i 4s f 6i') else: s = Struct(op2._endian + b'3q 8s d 6q') nentries = (len(data) - n) // ntotal for unused_i in range(nentries): out = s.unpack(data[n:n+ntotal]) pid, mid, cid, location, unused_t, unused_csopt = out[:6] location = location.decode('latin1') #op2.show_data(data[n:n+ntotal], 'ifs') op2.add_plplane(pid, mid, cid=cid, stress_strain_output_location=location) n += ntotal op2.card_count['PLPLANE'] = nentries return n
[docs] def read_plsolid(self, data: bytes, n: int) -> int: """ MSC 2016 1 PID I Property identification number 2 MID I Material identification number 3 STR CHAR4 Location of stress and strain output 4 UNDEF(4 ) none Not used NX 10 1 PID I Property identification number 2 MID I Material identification number 3 STR CHAR4 Location of stress and strain output 4 CSOPT I Reserved for coordinate system definition of plane 5 UNDEF(3) None .. warning:: CSOPT is not supported """ op2: OP2Geom = self.op2 ntotal = 28 * self.factor # 4*7 if self.size == 4: struct1 = Struct(op2._endian + b'2i 4s 4i') else: struct1 = Struct(op2._endian + b'2q 8s 4q') nentries = (len(data) - n) // ntotal for unused_i in range(nentries): out = struct1.unpack(data[n:n+ntotal]) pid, mid, location, unused_csopt, unused_null_a, unused_null_b, unused_null_c = out location = location.decode('latin1') #op2.show_data(data[n:n+ntotal], 'ifs') op2.add_plsolid(pid, mid, stress_strain=location, ge=0.) n += ntotal op2.card_count['PLSOLID'] = nentries return n
[docs] def read_pmass(self, data: bytes, n: int) -> int: """ PMASS(402,4,44) - the marker for Record 48 """ op2: OP2Geom = self.op2 ntotal = 8 * self.factor # 2*4 nentries = (len(data) - n) // ntotal struct_if = Struct(mapfmt(op2._endian + b'if', self.size)) for unused_i in range(nentries): edata = data[n:n + ntotal] out = struct_if.unpack(edata) #out = (pid, mass) if op2.is_debug_file: op2.binary_debug.write(' PMASS=%s\n' % str(out)) prop = PMASS.add_op2_data(out) self._add_op2_property_mass(prop) n += ntotal return n
[docs] def read_prod(self, data: bytes, n: int) -> int: """ PROD(902,9,29) - the marker for Record 49 """ op2: OP2Geom = self.op2 ntotal = 24 * self.factor # 6*4 struct_2i4f = Struct(mapfmt(op2._endian + b'2i4f', self.size)) nproperties = (len(data) - n) // ntotal for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_2i4f.unpack(edata) #(pid, mid, a, j, c, nsm) = out prop = PROD.add_op2_data(out) if op2.is_debug_file: op2.binary_debug.write(' PROD=%s\n' % str(out)) self._add_op2_property(prop) n += ntotal op2.card_count['PROD'] = nproperties return n
[docs] def read_pshear(self, data: bytes, n: int) -> int: """ PSHEAR(1002,10,42) - the marker for Record 50 """ op2: OP2Geom = self.op2 ntotal = 24 * self.factor nproperties = (len(data) - n) // ntotal struct_2i4f = Struct(mapfmt(op2._endian + b'2i4f', self.size)) for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_2i4f.unpack(edata) #(pid, mid, t, nsm, f1, f2) = out if op2.is_debug_file: op2.binary_debug.write(' PSHEAR=%s\n' % str(out)) prop = PSHEAR.add_op2_data(out) self._add_op2_property(prop) n += ntotal op2.card_count['PSHEAR'] = nproperties return n
[docs] def read_pshell(self, data: bytes, n: int) -> int: """ PSHELL(2302,23,283) - the marker for Record 51 """ op2: OP2Geom = self.op2 ntotal = 44 * self.factor # 11*4 nproperties = (len(data) - n) // ntotal s = Struct(mapfmt(op2._endian + b'iififi4fi', self.size)) for unused_i in range(nproperties): edata = data[n:n+ntotal] out = s.unpack(edata) (pid, mid1, unused_t, mid2, unused_bk, mid3, unused_ts, unused_nsm, unused_z1, unused_z2, mid4) = out if op2.is_debug_file: op2.binary_debug.write(' PSHELL=%s\n' % str(out)) prop = PSHELL.add_op2_data(out) n += ntotal if pid in op2.properties: # this is a fake PSHELL propi = op2.properties[pid] if prop == propi: op2.log.warning(f'Fake PSHELL {pid:d} (skipping):\n{propi}') nproperties -= 1 continue #assert propi.type in ['PCOMP', 'PCOMPG'], propi.get_stats() op2.log.error(f'PSHELL {pid:d} is also {propi.type} (skipping PSHELL):\n{propi}{prop}') nproperties -= 1 continue #continue #if max(pid, mid1, mid2, mid3, mid4) > 1e8: #self.big_properties[pid] = prop #else: self._add_op2_property(prop) if nproperties: op2.card_count['PSHELL'] = nproperties return n
[docs] def read_pcompls(self, data: bytes, n: int) -> int: """ 1 Each PCOMPLS creates a fake PSOLID with MID from its first ply, see ifp6nlm.F 2 # of , see also ta0n2m.F 3 PID I #01, Property ID 4 DIRECT I #02, Layer direction 5 CORDM I #03, ID of the Material coordinate system 6 SB RS #04, Allowable shear stress of bonding material 7 IANAL I #05, Implicit/Explicit/Structure/Heat, see nlmanal.prm 8 UNDEF(3) none #06-08 11 MICRO CHAR4 #09, If 'MICR', activates Micro-Mechanics progressive failure analysis 12 BEH8 CHAR4 ?01, Structual Behavior for 8-noded elements 13 INT8 CHAR4 ?02, Integration Scheme for 8-noded elements 14 BEH8H CHAR4 ?03, Heat Transfer Behavior for 8-noded elements 15 INT8H CHAR4 ?04, Heat Transfer Integration Scheme for 8-noded elements 16 BEH20 CHAR4 ?01, Structual Behavior for 20-noded elements 17 INT20 CHAR4 ?02, Integration Scheme for 20-noded elements 18 BEH20H CHAR4 ?03, Heat Transfer Behavior for 20-noded elements 19 INT20H CHAR4 ?04, Heat Transfer Integration Scheme for 20-noded elements 20 NPLY(C) I ?xx, Number of plies, =0 before IFP6, >0 after IFP6 NPLY =0 before IFP6 21 GPLYID I ?01, Global Ply ID 22 MID I ?02, Material ID 23 THICK RS ?03, Thicknesses of the ply, fractional if DIRECT > 0 24 THETA RS ?04, Orientation angle of the ply 25 SOUT CHAR4 ?05, Stress or strain output request (YES or NO) 26 MIDMTX I ?06, Matrix material ID 27 VF RS ?07, Fiber volume fraction 28 VV RS ?08, Void volume fraction 29 CTEMP RS ?09, Reference temperature 30 MOIST RS ?10, Moisture percentage 31 CRIT CHAR4 ?11, CRIT=critical or NONC=non-critical 32 NFTI I ?12, Number of non-blank Failure Theories coming next 33 FTI(24) CHAR4 ?13-36, Failure Theories Words 21 through 56 repeat until End of Record NPLY = after IFP6 21 GPLYID I ?01, Global Ply ID 22 MID I ?02, Material ID 23 THICK RS ?03, Thicknesses of the ply, fractional if DIRECT > 0 24 THETA RS ?04, Orientation angle of the ply 25 SOUT CHAR4 ?05, Stress or strain output request (YES or NO) 26 MIDMTX I ?06, Matrix material ID 27 VF RS ?07, Fiber volume fraction 28 VV RS ?08, Void volume fraction 29 CTEMP RS ?09, Reference temperature 30 MOIST RS ?10, Moisture percentage 31 CRIT CHAR4 ?11, CRIT=critical or NONC=non-critical 32 NFTI I ?12, Number of non-blank Failure Theories coming next 33 FTI(24) CHAR4 ?13-36, Failure Theories Words 21 through 56 repeat NPLY times End NPLY """ op2: OP2Geom = self.op2 struct_base = Struct('3i f i 3i 4s4s4s4s4s4s4s4s4s i') struct1 = Struct(b'2i 2f 4s i 4f 4s i 4s4s4s4s 4s4s4s4s 4s4s4s4s 4s4s4s4s 4s4s4s4s 4s4s4s4s ') nbase = 18 * 4 * self.factor n1 = 144 * self.factor while n < len(data): data_base = data[n:n+nbase] #op2.show_data(data_base) out = struct_base.unpack(data_base) #print(out) pid, direct, cordm, sb, ianal, dunnoa, dunno_b, dunno_c, micro, beh8, int8, beh8h, int8h, beh20, int20, beh20h, int20h, nply = out #3 PID I #01, Property ID #4 DIRECT I #02, Layer direction #5 CORDM I #03, ID of the Material coordinate system #6 SB RS #04, Allowable shear stress of bonding material #7 IANAL I #05, Implicit/Explicit/Structure/Heat, see nlmanal.prm #8 UNDEF(3) none #06-08 #11 MICRO CHAR4 #09, If 'MICR', activates Micro-Mechanics progressive failure analysis #12 BEH8 CHAR4 ?01, Structual Behavior for 8-noded elements #13 INT8 CHAR4 ?02, Integration Scheme for 8-noded elements #14 BEH8H CHAR4 ?03, Heat Transfer Behavior for 8-noded elements #15 INT8H CHAR4 ?04, Heat Transfer Integration Scheme for 8-noded elements #16 BEH20 CHAR4 ?01, Structual Behavior for 20-noded elements #17 INT20 CHAR4 ?02, Integration Scheme for 20-noded elements #18 BEH20H CHAR4 ?03, Heat Transfer Behavior for 20-noded elements #19 INT20H CHAR4 ?04, Heat Transfer Integration Scheme for 20-noded elements #20 NPLY(C) I ?xx, Number of plies, =0 before IFP6, >0 after IFP6 n += nbase if nply == 0: adsf else: mids = [] thicknesses = [] thetas = [] souts = [] for iply in range(nply): data1 = data[n:n+n1] #op2.show_data(data1) out1 = struct1.unpack(data1) #print(' ', out1) (gply_id, mid, thick, theta, sout, mid_mtx, vf, vv, ctemp, moist, crit_bytes, nfti, ft_bytes1, ft_bytes2, ft_bytes3, ft_bytes4, ft_bytes5, ft_bytes6, ft_bytes7, ft_bytes8, ft_bytes9, ft_bytes10, ft_bytes11, ft_bytes12, ft_bytes13, ft_bytes14, ft_bytes15, ft_bytes16, ft_bytes17, ft_bytes18, ft_bytes19, ft_bytes20, ft_bytes21, ft_bytes22, ft_bytes23, ft_bytes24,) = out1 #21 GPLYID I ?01, Global Ply ID #22 MID I ?02, Material ID #23 THICK RS ?03, Thicknesses of the ply, fractional if DIRECT > 0 #24 THETA RS ?04, Orientation angle of the ply #25 SOUT CHAR4 ?05, Stress or strain output request (YES or NO) #26 MIDMTX I ?06, Matrix material ID #27 VF RS ?07, Fiber volume fraction #28 VV RS ?08, Void volume fraction #29 CTEMP RS ?09, Reference temperature #30 MOIST RS ?10, Moisture percentage #31 CRIT CHAR4 ?11, CRIT=critical or NONC=non-critical #32 NFTI I ?12, Number of non-blank Failure Theories coming next #33 FTI(24) CHAR4 ?13-36, Failure Theories #Words 21 through 56 repeat NPLY times n += n1 mids.append(mid) thicknesses.append(thick) thetas.append(theta) souts.append('YES') #raise RuntimeError(nply) op2.show_data(data[n:]) op2.add_pcomp(pid, mids, thicknesses, thetas=thetas, souts=souts, nsm=0., sb=0., ft=None, tref=0., ge=0., lam=None, z0=None, comment='') #op2.add_pcompls(pid, ) #asdf op2.log.error('representing PCOMPLS (solid composite) as PCOMP (shell composite)') return n
[docs] def read_psolid(self, data: bytes, n: int) -> int: """ PSOLID(2402,24,281) - the marker for Record 52 """ op2: OP2Geom = self.op2 #print("reading PSOLID") #op2.show_data(data[n:]) if self.size == 4: ntotal = 28 # 7*4 struct_6i4s = Struct(op2._endian + b'6i4s') else: ntotal = 28 * 2 struct_6i4s = Struct(op2._endian + b'6q8s') nproperties = (len(data) - n) // ntotal nproperties_found = 0 for unused_i in range(nproperties): edata = data[n:n+ntotal] out = struct_6i4s.unpack(edata) #(pid, mid, cid, inp, stress, isop, fctn) = out #data_in = [pid, mid, cid, inp, stress, isop, fctn] if op2.is_debug_file: op2.binary_debug.write(' PSOLID=%s\n' % str(out)) n += ntotal fctn = out[-1] if fctn == b'FAKE': op2.log.warning(' PSOLID=%s; is this a PCOMPLS?' % str(out)) continue prop = PSOLID.add_op2_data(out) self._add_op2_property(prop) nproperties_found += 1 op2.card_count['PSOLID'] = nproperties_found return n
# PSOLIDL # PTRIA6 # PTSHELL
[docs] def read_ptube(self, data: bytes, n: int) -> int: """ PTUBE(1602,16,30) - the marker for Record 56 .. todo:: OD2 only exists for heat transfer... how do i know if there's heat transfer at this point? I could store all the tubes and add them later, but what about themal/non-thermal subcases? .. warning:: assuming OD2 is not written (only done for thermal) """ op2: OP2Geom = self.op2 ntotal = 20 * self.factor # 5*4 nproperties = (len(data) - n) // ntotal struct_2i3f = Struct(op2._endian + b'2i3f') for unused_i in range(nproperties): edata = data[n:n+20] # or 24??? out = struct_2i3f.unpack(edata) (pid, mid, OD, t, nsm) = out data_in = [pid, mid, OD, t, nsm] if op2.is_debug_file: op2.binary_debug.write(' PTUBE=%s\n' % str(out)) prop = PTUBE.add_op2_data(data_in) self._add_op2_property(prop) n += 20 op2.card_count['PTUBE'] = nproperties return n
[docs] def read_pset(self, data: bytes, n: int) -> int: op2: OP2Geom = self.op2 struct_5i4si = Struct(op2._endian + b'5i4si') nentries = 0 while n < len(data): edata = data[n:n+28] out = struct_5i4si.unpack(edata) #print(out) idi, poly1, poly2, poly3, cid, typei, typeid = out typei = typei.rstrip().decode('latin1') assert typei in ['SET', 'ELID'], (idi, poly1, poly2, poly3, cid, typei, typeid) if op2.is_debug_file: op2.binary_debug.write(' PVAL=%s\n' % str(out)) #print(idi, poly1, poly2, poly3, cid, typei, typeid) typeids = [] n += 28 while typeid != -1: typeids.append(typeid) typeid, = op2.struct_i.unpack(data[n:n+4]) n += 4 #print(val) #print(typeids) # PSET ID POLY1 POLY2 POLY3 CID SETTYP ID if len(typeids) == 1: typeids = typeids[0] op2.add_pset(idi, poly1, poly2, poly3, cid, typei, typeids) op2.card_count['PSET'] = nentries return n
[docs] def read_pval(self, data: bytes, n: int) -> int: # pragma: no cover """ PVAL(10201,102,400) Word Name Type Description 1 ID I p-value set identification number 2 POLY1 I Polynomial order in 1 direction of the CID system 3 POLY2 I Polynomial order in 2 direction of the CID system 4 POLY3 I Polynomial order in 2 direction of the CID system 5 CID I Coordinate system identification number 6 TYPE CHAR4 Type of set provided: "SET" or "ELID" 7 TYPEID I SET identification number or element identification number with this p-value specification. Words 1 through 7 repeat until End of Record """ raise UnsupportedCard('PVAL') op2: OP2Geom = self.op2 #op2.show_data(data[n:]) if self.size == 4: struct_5i4si = Struct(op2._endian + b'5i 4s i') struct_i = op2.struct_i else: struct_5i4si = Struct(op2._endian + b'5q 8s q') struct_i = op2.struct_q nentries = 0 ntotal = 28 * self.factor size = self.size while n < len(data): edata = data[n:n+ntotal] out = struct_5i4si.unpack(edata) #print(out) idi, poly1, poly2, poly3, cid, typei, typeid = out typei = typei.rstrip().decode('latin1') assert typei in ['SET', 'ELID'], f'idi={idi} poly1={poly1} poly2={poly2} poly3={poly3} cid={cid} typei={typei} typeid={typeid}' if op2.is_debug_file: op2.binary_debug.write(' PVAL=%s\n' % str(out)) #print(idi, poly1, poly2, poly3, cid, typei, typeid) typeids = [] n += ntotal while typeid != -1: typeids.append(typeid) typeid, = struct_i.unpack(data[n:n+size]) n += size #print(val) #print(typeids) # PVAL ID POLY1 POLY2 POLY3 CID SETTYP ID op2.add_pval(idi, poly1, poly2, poly3, cid, typei, typeids) op2.card_count['PVAL'] = nentries return n
[docs] def read_pvisc(self, data: bytes, n: int) -> int: """PVISC(1802,18,31) - the marker for Record 39""" op2: OP2Geom = self.op2 struct_i2f = Struct(op2._endian + b'i2f') nproperties = (len(data) - n) // 12 for unused_i in range(nproperties): edata = data[n:n+12] out = struct_i2f.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' PVISC=%s\n' % str(out)) #(pid, ce, cr) = out prop = PVISC.add_op2_data(out) self._add_op2_property(prop) n += 12 op2.card_count['PVISC'] = nproperties return n
# PWELD # PWSEAM
[docs] def read_view(self, data: bytes, n: int) -> int: """ RECORD – VIEW(2606,26,289) Word Name Type Description 1 IVIEW I View identification number 2 ICAVITY I Cavity identification number 3 SHADE I Shadowing flag for the face of CHBDYi element 4 NB I Subelement mesh size in the beta direction 5 NG I Subelement mesh size in the gamma direction 6 DISLIN RS Displacement """ op2: OP2Geom = self.op2 ntotal = 6 * op2.size structi = Struct(op2._endian + b'5if') ncards = (len(data) - n) // ntotal for unused_i in range(ncards): edata = data[n:n+ntotal] out = structi.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' VIEW=%s\n' % str(out)) iview, icavity, shade, nbeta, ngamma, dislin = out if shade == 1: shade_str = 'NONE' elif shade == 2: shade_str = 'KSHD' elif shade == 3: shade_str = 'KBSHD' elif shade == 4: shade_str = 'BOTH' else: # pragma: no cover raise NotImplementedError(shade) view = op2.add_view( iview, icavity, shade=shade_str, nbeta=nbeta, ngamma=ngamma, dislin=dislin) #print(view) n += ntotal op2.card_count['VIEW'] = ncards return len(data)
[docs] def read_view3d(self, data: bytes, n: int) -> int: """ RECORD – VIEW3D(3002,30,415) Word Name Type Description 1 ICAVITY I Radiant cavity identification number 2 GITB I Gaussian integration order for third-body shadowing 3 GIPS I Gaussian integration order for self-shadowing 4 CIER I Discretization level 5 ETOL RS Error estimate 6 ZTOL RS Zero tolerance 7 WTOL RS Warpage tolerance 8 RADCHK I Radiation exchange diagnostic output level """ op2: OP2Geom = self.op2 ntotal = 8 * self.size structi = Struct(mapfmt(op2._endian + b'4i 3f i', self.size)) ncards = (len(data) - n) // ntotal for unused_i in range(ncards): edata = data[n:n+ntotal] out = structi.unpack(edata) if op2.is_debug_file: op2.binary_debug.write(' VIEW3D=%s\n' % str(out)) icavity, gitb, gips, cier, etol, ztol, wtol, radcheck = out view = op2.add_view3d(icavity, gitb=gitb, gips=gips, cier=cier, error_tol=etol, zero_tol=ztol, warp_tol=wtol, rad_check=radcheck) str(view) n += ntotal op2.card_count['VIEW3D'] = ncards #asdf #self.op2.log.info('geom skipping VIEW3D in EPT') return len(data)
[docs] def break_by_minus1(idata): """helper for ``read_nsm_nx``""" i1 = 0 i = 0 i2 = None packs = [] for idatai in idata: #print('data[i:] = ', data[i:]) if idatai == -1: i2 = i packs.append((i1, i2)) i1 = i2 + 1 i += 1 continue i += 1 #print(packs) return packs