"""defines the BDF attributes"""
from __future__ import annotations
from collections import defaultdict
from typing import List, Dict, Optional, Any, Union, TYPE_CHECKING
from numpy import array # type: ignore
from pyNastran.utils import object_attributes, object_methods, deprecated
#from pyNastran.bdf.case_control_deck import CaseControlDeck
from pyNastran.bdf.cards.coordinate_systems import CORD2R
#from pyNastran.bdf.cards.constraints import ConstraintObject
from pyNastran.bdf.cards.aero.zona import ZONA
if TYPE_CHECKING: # pragma: no cover
from pyNastran.bdf import (
# BDF,
CaseControlDeck,
#params,
PARAM, MDLPRM,
# grids/points
POINT, SPOINT, EPOINT,
GRDSET, SEQGP, GRIDB,
# bar
BAROR, BEAMOR,
# plot
PLOTEL,
# dynamic
TSTEP, TSTEP1, TSTEPNL,
NLPCI, NLPARM,
TABLES1,
TABLED1, TABLED2, TABLED3, TABLED4,
TABLEM1, TABLEM2, TABLEM3, TABLEM4,
TABDMP1,
TF, DELAY, #DPHASE,
# axisymmetric
RINGAX, CYAX, AXIF, RINGFL, CYJOIN, AXIC,
# shells
SNORM,
#CQUAD4, CQUAD8, CQUADR, CQUAD,
#CTRIA3, CTRIA6, CTRIAR,
# solids
#CTETRA4, CPYRAM5, CPENTA6, CHEXA8,
#CTETRA10, CPYRAM13, CPENTA15, CHEXA20,
# loads
TEMPD,
# thermal
#CHBYDP, CHBDYE, CHBDYP,
PHBDY,
CONV, PCONV, PCONVM, #CONVM,
RADCAV, RADMTX, VIEW, VIEW3D,
RADBC, #TEMPBC,
# aero
MONPNT1, MONPNT2, MONPNT3,
AECOMP, AEFACT, AELINK, AELIST, AEPARAM, AESURF, AESURFS, AESTAT,
AERO, AEROS,
CAERO1, CAERO2, CAERO3, CAERO4, CAERO5,
PAERO1, PAERO2, PAERO3, PAERO4, PAERO5,
SPLINE1, SPLINE2, SPLINE3, SPLINE4, SPLINE5,
FLUTTER, MKAERO1, MKAERO2, FLFACT,
TRIM, TRIM2, GUST, GUST2, DIVERG, CSSCHD,
# roter
ROTORD, ROTORG,
# modal
EIGRL, EIGR, EIGP, EIGC, EIGB, MODTRAK,
# optimization
DESVAR, DLINK, TOPVAR, DVGRID,
DEQATN, DDVAL, DSCREEN,
DTABLE, DRESP1, DRESP2, DRESP3,
DVPREL1, DVCREL1, DVMREL1, DVTREL1,
DVPREL2, DVCREL2, DVMREL2, DVTREL2,
DCONADD, DCONSTR, DOPTPRM,
DMNCON, GROUP,
# contact
BCPARA, BCBODY, BCTPARAM, BGSET, BCTADD, BSURF, BSURFS, BCONP, BLSEG, BFRIC,
BCTSET, BCTPARA, BGADD, BCTPARA, BCRPARA,
# superelements
SEBULK, SENQSET, SENQSET1, SEBNDRY, RELEASE, SELOC, SEMPLN, SETREE,
SELABEL, SECONCT, SEEXCLD, SEELT, SELOAD, CSUPER, CSUPEXT,
)
#Coord = Union[CORD1R, CORD1C, CORD1S,
# CORD2R, CORD2C, CORD2S]
from pyNastran.bdf.cards.dmig import DMIG, DMI, DMIJ, DMIK, DMIJI, DMIAX
from pyNastran.bdf.subcase import Subcase
BDF_FORMATS = {'nx', 'msc', 'optistruct', 'zona'}
class BDFAttributes:
"""defines attributes of the BDF"""
def __init__(self):
"""creates the attributes for the BDF"""
self.__init_attributes()
self._is_cards_dict = False
self.is_nx = False
self.is_msc = False
self.is_nasa95 = False
self.is_zona = False
self.save_file_structure = False
self.is_superelements = False
self.set_as_msc()
self.units = [] # type: List[str]
def set_as_msc(self):
self._nastran_format = 'msc'
self.is_nx = False
self.is_msc = True
self.is_nasa95 = False
self.is_zona = False
def set_as_nx(self):
self._nastran_format = 'nx'
self.is_nx = True
self.is_msc = False
self.is_nasa95 = False
self.is_zona = False
def set_as_zona(self):
self._nastran_format = 'zona'
self.is_nx = False
self.is_msc = False
self.is_nasa95 = False
self.is_zona = True
def __properties__(self):
"""the list of @property attributes"""
return ['nastran_format', 'is_long_ids', 'sol', 'subcases',
'nnodes', 'node_ids', 'point_ids', 'npoints',
'nelements', 'element_ids', 'nproperties', 'property_ids',
'nmaterials', 'material_ids', 'ncoords', 'coord_ids',
'ncaeros', 'caero_ids', 'wtmass', 'is_bdf_vectorized', 'nid_map']
def object_attributes(self, mode: str='public',
keys_to_skip: Optional[List[str]]=None,
filter_properties: bool=False) -> List[str]:
"""
List the names of attributes of a class as strings. Returns public
attributes as default.
Parameters
----------
mode : str
defines what kind of attributes will be listed
* 'public' - names that do not begin with underscore
* 'private' - names that begin with single underscore
* 'both' - private and public
* 'all' - all attributes that are defined for the object
keys_to_skip : List[str]; default=None -> []
names to not consider to avoid deprecation warnings
filter_properties: bool: default=False
filters the @property objects
Returns
-------
attribute_names : List[str]
sorted list of the names of attributes of a given type or None
if the mode is wrong
"""
if keys_to_skip is None:
keys_to_skip = []
my_keys_to_skip = [
#'case_control_deck',
'log',
'node_ids', 'coord_ids', 'element_ids', 'property_ids',
'material_ids', 'caero_ids', 'is_long_ids',
'nnodes', 'ncoords', 'nelements', 'nproperties',
'nmaterials', 'ncaeros', 'npoints',
'point_ids', 'subcases',
'_card_parser', '_card_parser_b', '_card_parser_prepare',
'object_methods', 'object_attributes',
]
return object_attributes(self, mode=mode, keys_to_skip=keys_to_skip+my_keys_to_skip,
filter_properties=filter_properties)
def object_methods(self, mode: str='public', keys_to_skip: Optional[List[str]]=None) -> List[str]:
"""
List the names of methods of a class as strings. Returns public methods
as default.
Parameters
----------
obj : instance
the object for checking
mode : str
defines what kind of methods will be listed
* "public" - names that do not begin with underscore
* "private" - names that begin with single underscore
* "both" - private and public
* "all" - all methods that are defined for the object
keys_to_skip : List[str]; default=None -> []
names to not consider to avoid deprecation warnings
Returns
-------
method : List[str]
sorted list of the names of methods of a given type
or None if the mode is wrong
"""
if keys_to_skip is None:
keys_to_skip = []
my_keys_to_skip = [] # type: List[str]
my_keys_to_skip = [
#'case_control_deck',
'log', #'mpcObject', 'spcObject',
'node_ids', 'coord_ids', 'element_ids', 'property_ids',
'material_ids', 'caero_ids', 'is_long_ids',
'nnodes', 'ncoords', 'nelements', 'nproperties',
'nmaterials', 'ncaeros',
'point_ids', 'subcases',
'_card_parser', '_card_parser_b',
'object_methods', 'object_attributes',
]
return object_methods(self, mode=mode, keys_to_skip=keys_to_skip+my_keys_to_skip)
def deprecated(self, old_name: str, new_name: str, deprecated_version: str) -> None:
"""deprecates methods"""
return deprecated(old_name, new_name, deprecated_version, levels=[0, 1, 2])
def clear_attributes(self) -> None:
"""removes the attributes from the model"""
self.__init_attributes()
self.nodes = {}
self.loads = {} # type: Dict[int, List[Any]]
self.load_combinations = {} # type: Dict[int, List[Any]]
def reset_errors(self) -> None:
"""removes the errors from the model"""
self._ixref_errors = 0
self._stored_xref_errors = []
def __init_attributes(self) -> None:
"""
Creates storage objects for the BDF object.
This would be in the init but doing it this way allows for better
inheritance
References:
1. http://www.mscsoftware.com/support/library/conf/wuc87/p02387.pdf
"""
self.reset_errors()
self.bdf_filename = None
self.punch = None
self._encoding = None
self._is_long_ids = False # ids > 8 characters
#: ignore any ECHOON flags
self.force_echo_off = True
#: list of Nastran SYSTEM commands
self.system_command_lines = [] # type: List[str]
#: list of execive control deck lines
self.executive_control_lines = [] # type: List[str]
#: list of case control deck lines
self.case_control_lines = [] # type: List[str]
# dictionary of BDFs
self.superelement_models = {}
self.initial_superelement_models = [] # the keys before superelement mirroring
self._auto_reject = False
self._solmap_to_value = {
'NONLIN': 101, # 66 -> 101 per Reference 1
'SESTATIC': 101,
'SESTATICS': 101,
'SEMODES': 103,
'BUCKLING': 105,
'SEBUCKL': 105,
'NLSTATIC': 106,
'SEDCEIG': 107,
'SEDFREQ': 108,
'SEDTRAN': 109,
'SEMCEIG': 110,
'SEMFREQ': 111,
'SEMTRAN': 112,
'CYCSTATX': 114,
'CYCMODE': 115,
'CYCBUCKL': 116,
'CYCFREQ': 118,
'NLTRAN': 129,
'AESTAT': 144,
'FLUTTR': 145,
'SEAERO': 146,
'NLSCSH': 153,
'NLTCSH': 159,
'DBTRANS': 190,
'DESOPT': 200,
# guessing
#'CTRAN' : 115,
'CFREQ' : 118,
# solution 200 names
'STATICS': 101,
'MODES': 103,
'BUCK': 105,
'DFREQ': 108,
'MFREQ': 111,
'MTRAN': 112,
'DCEIG': 107,
'MCEIG': 110,
#'HEAT' : None,
#'STRUCTURE': None,
#'DIVERGE' : None,
'FLUTTER': 145,
'SAERO': 146,
}
self.rsolmap_to_str = {
66: 'NONLIN',
101: 'SESTSTATIC', # linear static
103: 'SEMODES', # modal
105: 'BUCKLING', # buckling
106: 'NLSTATIC', # non-linear static
107: 'SEDCEIG', # direct complex frequency response
108: 'SEDFREQ', # direct frequency response
109: 'SEDTRAN', # direct transient response
110: 'SEMCEIG', # modal complex eigenvalue
111: 'SEMFREQ', # modal frequency response
112: 'SEMTRAN', # modal transient response
114: 'CYCSTATX',
115: 'CYCMODE',
116: 'CYCBUCKL',
118: 'CYCFREQ',
129: 'NLTRAN', # nonlinear transient
144: 'AESTAT', # static aeroelastic
145: 'FLUTTR', # flutter/aeroservoelastic
146: 'SEAERO', # dynamic aeroelastic
153: 'NLSCSH', # nonlinear static thermal
159: 'NLTCSH', # nonlinear transient thermal
#187 - Dynamic Design Analysis Method
190: 'DBTRANS',
200: 'DESOPT', # optimization
}
# ------------------------ bad duplicates ----------------------------
self._iparse_errors = 0
self._nparse_errors = 0
self._stop_on_parsing_error = True
self._stop_on_duplicate_error = True
self._stored_parse_errors = [] # type: List[str]
self._duplicate_nodes = [] # type: List[str]
self._duplicate_elements = [] # type: List[str]
self._duplicate_properties = [] # type: List[str]
self._duplicate_materials = [] # type: List[str]
self._duplicate_masses = [] # type: List[str]
self._duplicate_thermal_materials = [] # type: List[str]
self._duplicate_coords = [] # type: List[str]
self.values_to_skip = {} # type: Dict[str, List[int]]
# ------------------------ structural defaults -----------------------
#: the analysis type
self._sol = None
#: used in solution 600, method
self.sol_method = None
#: the line with SOL on it, marks ???
self.sol_iline = None # type : Optional[int]
self.case_control_deck = None # type: Optional[CaseControlDeck]
#: store the PARAM cards
self.params = {} # type: Dict[str, PARAM]
# ------------------------------- nodes -------------------------------
# main structural block
#: stores POINT cards
self.points = {} # type: Dict[int, POINT]
#self.grids = {}
self.spoints = {} # type: Dict[int, SPOINT]
self.epoints = {} # type: Dict[int, EPOINT]
#: stores GRIDSET card
self.grdset = None # type: Optional[GRDSET]
#: stores SEQGP cards
self.seqgp = None # type: Optional[SEQGP]
## stores RINGAX
self.ringaxs = {} # type: Dict[int, RINGAX]
## stores GRIDB
self.gridb = {} # type: Dict[int, GRIDB]
#: stores elements (CQUAD4, CTRIA3, CHEXA8, CTETRA4, CROD, CONROD,
#: etc.)
self.elements = {} # type: Dict[int, Any]
#: stores CBARAO, CBEAMAO
self.ao_element_flags = {} # type: Dict[int, Any]
#: stores BAROR
self.baror = None # type: Optional[BAROR]
#: stores BEAMOR
self.beamor = None # type: Optional[BEAMOR]
#: stores SNORM
self.normals = {} # type: Dict[int, SNORM]
#: stores rigid elements (RBE2, RBE3, RJOINT, etc.)
self.rigid_elements = {} # type: Dict[int, Any]
#: stores PLOTELs
self.plotels = {} # type: Optional[PLOTEL]
#: stores CONM1, CONM2, CMASS1,CMASS2, CMASS3, CMASS4, CMASS5
self.masses = {} # type: Dict[int, Any]
#: stores PMASS
self.properties_mass = {} # type: Dict[int, Any]
#: stores NSM, NSM1, NSML, NSML1
self.nsms = {} # type: Dict[int, List[Any]]
#: stores NSMADD
self.nsmadds = {} # type: Dict[int, List[Any]]
#: stores LOTS of properties (PBAR, PBEAM, PSHELL, PCOMP, etc.)
self.properties = {} # type: Dict[int, Any]
#: stores MAT1, MAT2, MAT3, MAT8, MAT10, MAT11
self.materials = {} # type: Dict[int, Any]
#: defines the MAT4, MAT5
self.thermal_materials = {} # type: Dict[int, Any]
#: defines the MATHE, MATHP
self.hyperelastic_materials = {} # type: Dict[int, Any]
#: stores MATSx
self.MATS1 = {} # type: Dict[int, Any]
self.MATS3 = {} # type: Dict[int, Any]
self.MATS8 = {} # type: Dict[int, Any]
#: stores MATTx
self.MATT1 = {} # type: Dict[int, Any]
self.MATT2 = {} # type: Dict[int, Any]
self.MATT3 = {} # type: Dict[int, Any]
self.MATT4 = {} # type: Dict[int, Any]
self.MATT5 = {} # type: Dict[int, Any]
self.MATT8 = {} # type: Dict[int, Any]
self.MATT9 = {} # type: Dict[int, Any]
self.nxstrats = {} # type: Dict[int, Any]
#: stores the CREEP card
self.creep_materials = {} # type: Dict[int, Any]
self.tics = {} # type: Optional[Any]
# stores DLOAD entries.
self.dloads = {} # type: Dict[int, Any]
# stores ACSRCE, RLOAD1, RLOAD2, TLOAD1, TLOAD2, and ACSRCE,
# and QVECT entries.
self.dload_entries = {} # type: Dict[int, Any]
#self.gusts = {} # Case Control GUST = 100
#self.random = {} # Case Control RANDOM = 100
#: stores coordinate systems
origin = array([0., 0., 0.])
zaxis = array([0., 0., 1.])
xzplane = array([1., 0., 0.])
coord = CORD2R(cid=0, rid=0, origin=origin, zaxis=zaxis, xzplane=xzplane)
self.coords = {0 : coord} # type: Dict[int, Any]
# --------------------------- constraints ----------------------------
#: stores SUPORT1s
#self.constraints = {} # suport1, anything else???
self.suport = [] # type: List[Any]
self.suport1 = {} # type: Dict[int, Any]
self.se_suport = [] # type: List[Any]
#: stores SPC, SPC1, SPCAX, GMSPC
self.spcs = {} # type: Dict[int, List[Any]]
#: stores SPCADD
self.spcadds = {} # type: Dict[int, List[Any]]
self.spcoffs = {} # type: Dict[int, List[Any]]
self.mpcs = {} # type: Dict[int, List[Any]]
self.mpcadds = {} # type: Dict[int, List[Any]]
# --------------------------- dynamic ----------------------------
#: stores DAREA
self.dareas = {} # type: Dict[int, Any]
self.dphases = {} # type: Dict[int, Any]
self.pbusht = {} # type: Dict[int, Any]
self.pdampt = {} # type: Dict[int, Any]
self.pelast = {} # type: Dict[int, Any]
#: frequencies
self.frequencies = {} # type: Dict[int, List[Any]]
# ----------------------------------------------------------------
#: direct matrix input - DMIG
self.dmi = {} # type: Dict[str, DMI]
self.dmig = {} # type: Dict[str, DMIG]
self.dmij = {} # type: Dict[str, DMIJ]
self.dmiji = {} # type: Dict[str, DMIJI]
self.dmik = {} # type: Dict[str, DMIK]
self.dmiax = {} # type: Dict[str, DMIAX]
self.dti = {} # type: Dict[str, Any]
self._dmig_temp = defaultdict(list) # type: Dict[str, List[str]]
# ----------------------------------------------------------------
#: SETy
self.sets = {} # type: Dict[int, Any]
self.asets = [] # type: List[Any]
self.omits = [] # type: List[Any]
self.bsets = [] # type: List[Any]
self.csets = [] # type: List[Any]
self.qsets = [] # type: List[Any]
self.usets = {} # type: Dict[str, Any]
#: SExSETy
self.se_bsets = [] # type: List[Any]
self.se_csets = [] # type: List[Any]
self.se_qsets = [] # type: List[Any]
self.se_usets = {} # type: Dict[str, Any]
self.se_sets = {} # type: Dict[str, Any]
# ----------------------------------------------------------------
#: parametric
self.pset = {}
self.pval = {}
self.gmcurv = {}
self.gmsurf = {}
self.feedge = {}
self.feface = {}
# ----------------------------------------------------------------
#: tables
# TABLES1, ...
self.tables = {} # type: Dict[int, TABLES1]
# TABLEDx
self.tables_d = {} # type: Dict[int, Union[TABLED1, TABLED2, TABLED3, TABLED4]]
# TABLEMx
self.tables_m = {} # type: Dict[int, Union[TABLEM1, TABLEM2, TABLEM3, TABLEM4]]
#: random_tables
self.random_tables = {} # type: Dict[int, Any]
#: TABDMP1
self.tables_sdamping = {} # type: Dict[int, TABDMP1]
# ----------------------------------------------------------------
#: EIGB, EIGR, EIGRL methods
self.methods = {} # type: Dict[int, Union[EIGR, EIGRL, EIGB]]
# EIGC, EIGP methods
self.cMethods = {} # type: Dict[int, Union[EIGC, EIGP]]
# ---------------------------- optimization --------------------------
# optimization
self.dconadds = {} # type: Dict[int, DCONADD]
self.dconstrs = {} # type: Dict[int, DCONSTR]
self.desvars = {} # type: Dict[int, DESVAR]
self.topvar = {} # type: Dict[int, TOPVAR]
self.ddvals = {} # type: Dict[int, DDVAL]
self.dlinks = {} # type: Dict[int, DLINK]
self.dresps = {} # type: Dict[int, Union[DRESP1, DRESP2, DRESP3]]
self.dtable = None # type: Optional[DTABLE]
self.dequations = {} # type: Dict[int, DEQATN]
#: stores DVPREL1, DVPREL2...might change to DVxRel
self.dvprels = {} # type: Dict[int, Union[DVPREL1, DVPREL2]]
self.dvmrels = {} # type: Dict[int, Union[DVMREL1, DVMREL2]]
self.dvcrels = {} # type: Dict[int, Union[DVCREL1, DVCREL2]]
self.dvgrids = {} # type: Dict[int, DVGRID]
self.doptprm = None # type: Optional[DOPTPRM]
self.dscreen = {} # type: Dict[int, DSCREEN]
# nx optimization
self.group = {} # type: Dict[int, GROUP]
self.dmncon = {} # type: Dict[int, DMNCON]
self.dvtrels = {} # type: Dict[int, Union[DVTREL1, DVTREL2]]
# ------------------------- nonlinear defaults -----------------------
#: stores NLPCI
self.nlpcis = {} # type: Dict[int, NLPCI]
#: stores NLPARM
self.nlparms = {} # type: Dict[int, NLPARM]
#: stores TSTEPs, TSTEP1s
self.tsteps = {} # type: Dict[int, Union[TSTEP, TSTEP1]]
#: stores TSTEPNL
self.tstepnls = {} # type: Dict[int, TSTEPNL]
#: stores TF
self.transfer_functions = {} # type: Dict[int, TF]
#: stores DELAY
self.delays = {} # type: Dict[int, DELAY]
#: stores ROTORD, ROTORG
self.rotors = {} # type: Dict[int, Union[ROTORD, ROTORG]]
# --------------------------- aero defaults --------------------------
# aero cards
#: stores CAEROx
self.caeros = {} # type: Dict[int, Union[CAERO1, CAERO2, CAERO3, CAERO4, CAERO5]]
#: stores PAEROx
self.paeros = {} # type: Dict[int, Union[PAERO1, PAERO2, PAERO3, PAERO4, PAERO5]]
# stores MONPNT1
self.monitor_points = [] # type: List[Union[MONPNT1, MONPNT2, MONPNT3]]
#: stores AECOMP
self.aecomps = {} # type: Dict[int, AECOMP]
#: stores AEFACT
self.aefacts = {} # type: Dict[int, AEFACT]
#: stores AELINK
self.aelinks = {} # type: Dict[int, List[AELINK]]
#: stores AELIST
self.aelists = {} # type: Dict[int, AELIST]
#: stores AEPARAM
self.aeparams = {} # type: Dict[int, AEPARAM]
#: stores AESURF
self.aesurf = {} # type: Dict[int, AESURF]
#: stores AESURFS
self.aesurfs = {} # type: Dict[int, AESURFS]
#: stores AESTAT
self.aestats = {} # type: Dict[int, AESTAT]
#: stores CSSCHD
self.csschds = {} # type: Dict[int, CSSCHD]
#: store SPLINE1,SPLINE2,SPLINE4,SPLINE5
self.splines = {} # type: Dict[int, Union[SPLINE1, SPLINE2, SPLINE3, SPLINE4, SPLINE5]]
self.zona = ZONA(self)
# axisymmetric
self.axic = None # type: Optional[AXIC]
self.axif = None # type: Optional[AXIF]
self.ringfl = {} # type: Dict[int, RINGFL]
self._is_axis_symmetric = False
# cyclic
self.cyax = None # type: Optional[CYAX]
self.cyjoin = {} # type: Dict[int, CYJOIN]
self.modtrak = None # type: Optional[MODTRAK]
# acoustic
self.acmodl = None
# ------ SOL 144 ------
#: stores AEROS
self.aeros = None # type: Optional[AEROS]
#: stores TRIM, TRIM2
self.trims = {} # type: Dict[int, Union[TRIM, TRIM2]]
#: stores DIVERG
self.divergs = {} # type: Dict[int, DIVERG]
# ------ SOL 145 ------
#: stores AERO
self.aero = None # type: Optional[AERO]
#: stores FLFACT
self.flfacts = {} # type: Dict[int, FLFACT]
#: stores FLUTTER
self.flutters = {} # type: Dict[int, FLUTTER]
#: mkaeros
self.mkaeros = [] # type: List[Union[MKAERO1,MKAERO2]]
# ------ SOL 146 ------
#: stores GUST cards
self.gusts = {} # type: Dict[int, GUST]
# ------------------------- thermal defaults -------------------------
# BCs
#: stores thermal boundary conditions - CONV,RADBC
self.bcs = {} # type: Dict[int, Union[CONV, RADBC]]
#: stores PHBDY
self.phbdys = {} # type: Dict[int, PHBDY]
#: stores convection properties - PCONV, PCONVM ???
self.convection_properties = {} # type: Dict[int, Union[PCONV, PCONVM]]
#: stores TEMPD
self.tempds = {} # type: Dict[int, TEMPD]
#: stores VIEW
self.views = {} # type: Dict[int, VIEW]
#: stores VIEW3D
self.view3ds = {} # type: Dict[int, VIEW3D]
self.radset = None
self.radcavs = {} # type: Dict[int, RADCAV]
self.radmtx = {} # type: Dict[int, RADMTX]
# -------------------------contact cards-------------------------------
self.bcbodys = {} # type: Dict[int, BCBODY]
self.bcparas = {} # type: Dict[int, BCPARA]
self.bcrparas = {} # type: Dict[int, BCRPARA]
self.bctparas = {} # type: Dict[int, BCTPARA]
self.bctadds = {} # type: Dict[int, BCTADD]
self.bctsets = {} # type: Dict[int, BCTSET]
self.bsurf = {} # type: Dict[int, BSURF]
self.bsurfs = {} # type: Dict[int, BSURFS]
self.bconp = {} # type: Dict[int, BCONP]
self.blseg = {} # type: Dict[int, BLSEG]
self.bfric = {} # type: Dict[int, BFRIC]
self.bgadds = {} # type: Dict[int, BGADD]
self.bgsets = {} # type: Dict[int, BGSET]
self.bctparms = {} # type: Dict[int, BCTPARAM]
#--------------------------superelements------------------------------
self.setree = {} # type: Dict[int, SETREE]
self.senqset = {} # type: Dict[int, Union[SENQSET, SENQSET1]]
self.sebulk = {} # type: Dict[int, SEBULK]
self.sebndry = {} # type: Dict[int, SEBNDRY]
self.release = {} # type: Dict[int, RELEASE]
self.seloc = {} # type: Dict[int, SELOC]
self.sempln = {} # type: Dict[int, SEMPLN]
self.seconct = {} # type: Dict[int, SECONCT]
self.selabel = {} # type: Dict[int, SELABEL]
self.seexcld = {} # type: Dict[int, SEEXCLD]
self.seelt = {} # type: Dict[int, SEELT]
self.seload = {} # type: Dict[int, SELOAD]
self.csuper = {} # type: Dict[int, CSUPER]
self.csupext = {} # type: Dict[int, CSUPEXT]
# ---------------------------------------------------------------------
self._type_to_id_map = defaultdict(list) # type: Dict[int, List[Any]]
self._slot_to_type_map = {
'params' : ['PARAM'],
'mdlprm': ['MDLPRM'],
'nodes' : ['GRID', 'SPOINT', 'EPOINT'], # 'RINGAX',
'points' : ['POINT'],
'ringaxs' : ['RINGAX', 'POINTAX'],
'ringfl' : ['RINGFL'],
'axic' : ['AXIC'],
'axif' : ['AXIF'],
'acmodl' : ['ACMODL'],
'grdset' : ['GRDSET'],
'gridb' : ['GRIDB'],
'seqgp' : ['SEQGP'],
'ao_element_flags' : ['CBARAO'],
#'POINTAX', 'RINGAX',
# CMASS4 lies in the QRG
'masses' : ['CONM1', 'CONM2', 'CMASS1', 'CMASS2', 'CMASS3', 'CMASS4'],
'elements' : [
'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4',
# 'CELAS5',
'CBUSH', 'CBUSH1D', 'CBUSH2D',
'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', 'CDAMP5',
'CFAST', 'GENEL',
'CBAR', 'CROD', 'CTUBE', 'CBEAM', 'CBEAM3', 'CONROD', 'CBEND',
'CTRIA3', 'CTRIA6', 'CTRIAR',
'CQUAD4', 'CQUAD8', 'CQUADR', 'CQUAD',
'CPLSTN3', 'CPLSTN6', 'CPLSTN4', 'CPLSTN8',
'CPLSTS3', 'CPLSTS6', 'CPLSTS4', 'CPLSTS8',
'CTRAX3', 'CTRAX6', 'CTRIAX', 'CTRIAX6',
'CQUADX', 'CQUADX4', 'CQUADX8',
'CCONEAX',
'CTETRA', 'CPYRAM', 'CPENTA', 'CHEXA', 'CIHEX1', 'CIHEX2',
'CSHEAR', 'CVISC', 'CRAC2D', 'CRAC3D',
'CGAP',
# thermal
'CHBDYE', 'CHBDYG', 'CHBDYP',
# acoustic
'CHACAB', 'CAABSF', 'CHACBR',
],
'normals' : ['SNORM'],
'nsms' : ['NSM', 'NSM1', 'NSML', 'NSML1'],
'nsmadds' : ['NSMADD'],
'rigid_elements' : ['RBAR', 'RBAR1', 'RBE1', 'RBE2', 'RBE3', 'RROD', 'RSPLINE', 'RSSCON'],
'plotels' : ['PLOTEL'],
'properties_mass' : ['PMASS'],
#'properties_acoustic' : ['PACABS'],
'properties' : [
# acoustic
'PACABS', 'PAABSF', 'PACBAR',
# 0d
'PELAS', 'PGAP', 'PFAST',
'PBUSH', 'PBUSH1D',
'PDAMP', 'PDAMP5',
# 1d
'PROD', 'PBAR', 'PBARL', 'PBEAM', 'PTUBE', 'PBEND', 'PBCOMP', 'PBRSECT', 'PBMSECT',
'PBEAML', # not fully supported
'PBEAM3',
# 2d
'PLPLANE', 'PPLANE',
'PSHELL', 'PCOMP', 'PCOMPG', 'PSHEAR',
'PSOLID', 'PLSOLID', 'PVISC', 'PRAC2D', 'PRAC3D',
'PIHEX', 'PCOMPS',
'PCONEAX',
],
'pdampt' : ['PDAMPT'],
'pelast' : ['PELAST'],
'pbusht' : ['PBUSHT'],
# materials
'materials' : ['MAT1', 'MAT2', 'MAT3', 'MAT8', 'MAT9', 'MAT10', 'MAT11',
'MAT3D', 'MATG'],
'hyperelastic_materials' : ['MATHE', 'MATHP'],
'creep_materials' : ['CREEP'],
'MATT1' : ['MATT1'],
'MATT2' : ['MATT2'],
'MATT3' : ['MATT3'],
'MATT4' : ['MATT4'], # thermal
'MATT5' : ['MATT5'], # thermal
'MATT8' : ['MATT8'],
'MATT9' : ['MATT9'],
'MATS1' : ['MATS1'],
'MATS3' : ['MATS3'],
'MATS8' : ['MATS8'],
'nxstrats' : ['NXSTRAT'],
# 'MATHE'
#'EQUIV', # testing only, should never be activated...
# thermal materials
'thermal_materials' : ['MAT4', 'MAT5'],
# spc/mpc constraints - TODO: is this correct?
'spcadds' : ['SPCADD'],
'spcs' : ['SPC', 'SPC1', 'SPCAX', 'GMSPC'],
'spcoffs' : ['SPCOFF', 'SPCOFF1'],
'mpcadds' : ['MPCADD'],
'mpcs' : ['MPC'],
'suport' : ['SUPORT'],
'suport1' : ['SUPORT1'],
'se_suport' : ['SESUP'],
'setree' : ['SETREE'],
'senqset' : ['SENQSET'],
'sebulk' : ['SEBULK'],
'sebndry' : ['SEBNDRY'],
'release' : ['RELEASE'],
'seloc' : ['SELOC'],
'sempln' : ['SEMPLN'],
'seconct' : ['SECONCT'],
'selabel' : ['SELABEL'],
'seexcld' : ['SEEXCLD'],
'seelt' : ['SEELT'],
'seload' : ['SELOAD'],
'csuper' : ['CSUPER'],
'csupext' : ['CSUPEXT'],
# loads
'load_combinations' : ['LOAD', 'LSEQ', 'CLOAD'],
'loads' : [
'FORCE', 'FORCE1', 'FORCE2',
'MOMENT', 'MOMENT1', 'MOMENT2',
'GRAV', 'ACCEL', 'ACCEL1',
'PLOAD', 'PLOAD1', 'PLOAD2', 'PLOAD4',
'RFORCE', 'RFORCE1', 'SLOAD',
'GMLOAD', 'SPCD', 'LOADCYN', 'LOADCYH', 'DEFORM',
# thermal
'TEMP', 'TEMPB3', 'TEMPRB',
'QBDY1', 'QBDY2', 'QBDY3', 'QHBDY', 'QVOL',
# axisymmetric
'PLOADX1', 'FORCEAX', 'PRESAX', 'TEMPAX',
],
'cyjoin' : ['CYJOIN'],
'cyax' : ['CYAX'],
'modtrak' : ['MODTRAK'],
'dloads' : ['DLOAD'],
# stores RLOAD1, RLOAD2, TLOAD1, TLOAD2, and ACSRCE entries.
'dload_entries' : ['ACSRCE', 'TLOAD1', 'TLOAD2', 'RLOAD1', 'RLOAD2',
'QVECT', 'RANDPS', 'RANDT1'],
# aero cards
'aero' : ['AERO'],
'aeros' : ['AEROS'],
'gusts' : ['GUST', 'GUST2'],
'flutters' : ['FLUTTER'],
'flfacts' : ['FLFACT'],
'mkaeros' : ['MKAERO1', 'MKAERO2'],
'aecomps' : ['AECOMP', 'AECOMPL'],
'aefacts' : ['AEFACT'],
'aelinks' : ['AELINK'],
'aelists' : ['AELIST'],
'aeparams' : ['AEPARM'],
'aesurf' : ['AESURF'],
'aesurfs' : ['AESURFS'],
'aestats' : ['AESTAT'],
'caeros' : ['CAERO1', 'CAERO2', 'CAERO3', 'CAERO4', 'CAERO5', 'CAERO7', 'BODY7'],
'paeros' : ['PAERO1', 'PAERO2', 'PAERO3', 'PAERO4', 'PAERO5', 'SEGMESH'],
'monitor_points' : ['MONPNT1', 'MONPNT2', 'MONPNT3', 'MONDSP1'],
'splines' : ['SPLINE1', 'SPLINE2', 'SPLINE3', 'SPLINE4', 'SPLINE5', 'SPLINE6', 'SPLINE7'],
'panlsts' : ['PANLST1', 'PANLST2', 'PANLST3'],
'csschds' : ['CSSCHD',],
#'SPLINE3', 'SPLINE6', 'SPLINE7',
'trims' : ['TRIM', 'TRIM2'],
'divergs' : ['DIVERG'],
# coords
'coords' : ['CORD1R', 'CORD1C', 'CORD1S',
'CORD2R', 'CORD2C', 'CORD2S',
'GMCORD', 'ACOORD', 'CORD3G'],
# temperature cards
'tempds' : ['TEMPD'],
'phbdys' : ['PHBDY'],
'convection_properties' : ['PCONV', 'PCONVM'],
# stores thermal boundary conditions
'bcs' : ['CONV', 'CONVM', 'RADBC', 'RADM', 'TEMPBC'],
# dynamic cards
'dareas' : ['DAREA'],
'tics' : ['TIC'],
'dphases' : ['DPHASE'],
'nlparms' : ['NLPARM'],
'nlpcis' : ['NLPCI'],
'tsteps' : ['TSTEP'],
'tstepnls' : ['TSTEPNL', 'TSTEP1'],
'transfer_functions' : ['TF'],
'delays' : ['DELAY'],
'rotors' : ['ROTORG', 'ROTORD'],
'frequencies' : ['FREQ', 'FREQ1', 'FREQ2', 'FREQ3', 'FREQ4', 'FREQ5'],
# direct matrix input cards
'dmig' : ['DMIG'],
'dmiax' : ['DMIAX'],
'dmij' : ['DMIJ'],
'dmiji' : ['DMIJI'],
'dmik' : ['DMIK'],
'dmi' : ['DMI'],
'dti' : ['DTI'],
# optimzation
'dequations' : ['DEQATN'],
'dtable' : ['DTABLE'],
'dconstrs' : ['DCONSTR', 'DCONADD'],
'desvars' : ['DESVAR'],
'topvar' : ['TOPVAR'],
'ddvals' : ['DDVAL'],
'dlinks' : ['DLINK'],
'dresps' : ['DRESP1', 'DRESP2', 'DRESP3'],
'dvprels' : ['DVPREL1', 'DVPREL2'],
'dvmrels' : ['DVMREL1', 'DVMREL2'],
'dvcrels' : ['DVCREL1', 'DVCREL2'],
'dvgrids' : ['DVGRID'],
'doptprm' : ['DOPTPRM'],
'dscreen' : ['DSCREEN'],
# optimization - nx
'dmncon' : ['DMNCON'],
'dvtrels' : ['DVTREL1'],
'group' : ['GROUP'],
# sets
'asets' : ['ASET', 'ASET1'],
'omits' : ['OMIT', 'OMIT1'],
'bsets' : ['BSET', 'BSET1'],
'qsets' : ['QSET', 'QSET1'],
'csets' : ['CSET', 'CSET1'],
'usets' : ['USET', 'USET1'],
'sets' : ['SET1', 'SET3'],
# super-element sets
'se_bsets' : ['SEBSET', 'SEBSET1'],
'se_csets' : ['SECSET', 'SECSET1'],
'se_qsets' : ['SEQSET', 'SEQSET1'],
'se_usets' : ['SEUSET', 'SEQSET1'],
'se_sets' : ['SESET'],
'radset' : ['RADSET'],
'radcavs' : ['RADCAV', 'RADLST'],
'radmtx' : ['RADMTX'],
# SEBSEP
# parametric
'pset' : ['PSET'],
'pval' : ['PVAL'],
'gmcurv' : ['GMCURV'],
'gmsurf' : ['GMSURF'],
'feedge' : ['FEEDGE'],
'feface' : ['FEFACE'],
# tables
'tables' : [
'TABLEH1', 'TABLEHT',
'TABLES1', 'TABLEST',
],
'tables_d' : ['TABLED1', 'TABLED2', 'TABLED3', 'TABLED4', 'TABLED5'],
'tables_m' : ['TABLEM1', 'TABLEM2', 'TABLEM3', 'TABLEM4'],
'tables_sdamping' : ['TABDMP1'],
'random_tables' : ['TABRND1', 'TABRNDG'],
# initial conditions - sid (set ID)
##'TIC', (in bdf_tables.py)
# methods
'methods' : ['EIGB', 'EIGR', 'EIGRL'],
# cMethods
'cMethods' : ['EIGC', 'EIGP'],
# contact
'bcbodys' : ['BCBODY'],
'bcparas' : ['BCPARA'],
'bctparas' : ['BCTPARA'],
'bcrparas' : ['BCRPARA'],
'bctparms' : ['BCTPARM'],
'bctadds' : ['BCTADD'],
'bctsets' : ['BCTSET'],
'bgadds' : ['BGADD'],
'bgsets' : ['BGSET'],
'bsurf' : ['BSURF'],
'bsurfs' : ['BSURFS'],
'bconp' : ['BCONP'],
'blseg' : ['BLSEG'],
'bfric' : ['BFRIC'],
'views' : ['VIEW'],
'view3ds' : ['VIEW3D'],
## other
#'INCLUDE', # '='
#'ENDDATA',
} # type: Dict[str, List[str]]
self._type_to_slot_map = self.get_rslot_map()
@property
def type_slot_str(self) -> str:
"""helper method for printing supported cards"""
nchars = len('Card Group')
#nchars_cards = 0
for card_group in self._slot_to_type_map:
nchars = max(nchars, len(card_group))
nline = 58
fmt = '| %%-%ss | %%-%ss |\n' % (nchars, nline)
fmt_plus = '+%%-%ss+%%-%ss+\n' % (nchars + 2, nline + 2)
dash1 = '-' * (nchars + 2)
dash2 = '-' * (nline + 2)
dash_plus = fmt_plus % (dash1, dash2)
html_msg = [
dash_plus,
fmt % ('Card Group', 'Cards'),
]
for card_group, card_types in sorted(self._slot_to_type_map.items()):
valid_cards = [card_type for card_type in card_types
if card_type in self.cards_to_read]
valid_cards.sort()
if len(valid_cards) == 0:
continue
#i = 0
sublines = []
subline = ''
while valid_cards:
card_type = valid_cards.pop(0)
# the +2 is for the comma and space
len_card_type = len(card_type) + 2
nline_new = len(subline) + len_card_type
if nline_new > nline:
sublines.append(subline.rstrip(' '))
subline = ''
subline += '%s, ' % card_type
if subline:
sublines.append(subline.rstrip(', '))
html_msg.append(dash_plus)
for isub, subline in enumerate(sublines):
if isub > 0: # adds intermediate dash lines
html_msg.append(dash_plus)
html_msg.append(fmt % (card_group, subline))
card_group = ''
html_msg.append(dash_plus)
#for card_group, card_types in sorted(self._slot_to_type_map.items()):
#html_msg.append('| %s | %s |' % (card_group, ', '.join(card_types)))
#html_msg.append(
#fmt_plus % ('-'*(nchars + 2), '-'*(nline + 2))
#)
msg = ''.join(html_msg)
return msg
@property
def nastran_format(self) -> str:
return self._nastran_format
@nastran_format.setter
def nastran_format(self, nastran_format: str) -> None:
assert isinstance(nastran_format, str), nastran_format
fmt_lower = nastran_format.lower().strip()
if fmt_lower not in BDF_FORMATS:
raise RuntimeError(nastran_format)
self._nastran_format = fmt_lower
@property
def is_long_ids(self) -> bool:
return self._is_long_ids
#if self._nastran_format == 'nx' or self._is_long_ids:
#return True
#return False
def _set_punch(self) -> None:
"""updates the punch flag"""
if self.punch is None:
# writing a mesh without using read_bdf
if self.system_command_lines or self.executive_control_lines or self.case_control_deck:
self.punch = False
else:
self.punch = True
@property
def sol(self) -> int:
"""gets the solution (e.g. 101, 103)"""
return self._sol
@sol.setter
def sol(self, sol: int) -> int:
"""sets the solution (e.g. 101, 103)"""
self._sol = sol
if len(self.executive_control_lines) == 0:
self.executive_control_lines = ['SOL %s' % sol, 'CEND']
self.sol_iline = 0
return self._sol
@property
def subcases(self) -> Dict[int, Subcase]:
"""gets the subcases"""
if self.case_control_deck is None:
return {}
return self.case_control_deck.subcases
#@property
#def grids(self):
#"""might be renaming self.nodes to self.grids"""
#return self.nodes
#@property.setter
#def grids(self, grids):
#"""might be renaming self.nodes to self.grids"""
#self.nodes = grids
@property
def nnodes(self) -> int:
"""gets the number of GRIDs"""
return len(self.nodes)
@property
def node_ids(self):
"""gets the GRID ids"""
return self.nodes.keys()
@property
def point_ids(self):
"""gets the GRID, SPOINT, EPOINT ids"""
return set(self.node_ids) | set(list(self.spoints.keys())) | set(list(self.epoints.keys()))
@property
def npoints(self) -> int:
"""gets the number of GRID, SPOINT, EPOINT ids"""
return len(self.point_ids)
#--------------------
# Elements CARDS
@property
def nelements(self) -> int:
"""gets the number of element"""
return len(self.elements)
@property
def element_ids(self):
"""gets the element ids"""
return self.elements.keys()
#--------------------
# Property CARDS
@property
def nproperties(self) -> int:
"""gets the number of properties"""
return len(self.properties)
@property
def property_ids(self):
"""gets the property ids"""
return self.properties.keys()
#--------------------
# Material CARDS
@property
def nmaterials(self) -> int:
"""gets the number of materials"""
return len(self.materials)
@property
def material_ids(self):
"""gets the material ids"""
return self.materials.keys()
#--------------------
# Coords CARDS
@property
def ncoords(self) -> int:
"""gets the number of coordinate systems"""
return len(self.coords)
@property
def coord_ids(self):
"""gets the number of coordinate system ids"""
return self.coords.keys()
#--------------------
@property
def ncaeros(self) -> int:
"""gets the number of CAEROx panels"""
return len(self.caeros)
@property
def caero_ids(self):
"""gets the CAEROx ids"""
return self.caeros.keys()
@property
def wtmass(self):
"""
Gets the PARAM,WTMASS value, which defines the weight to mass
conversion factor
kg -> kg : 1.0
lb -> slug : 1/32.2
lb -> slinch : 1/(32.2*12)=1/386.4
"""
wtmass = 1.0
if 'WTMASS' in self.params:
param = self.params['WTMASS']
wtmass = param.values[0]
return wtmass
def set_param(self, key: str, values: Union[int, float, str, List[float]], comment: str='') -> None:
"""sets a param card; creates it if necessary"""
if isinstance(values, (int, float, str)):
values = [values]
key = key.upper()
if key in self.params:
param = self.params[key]
param.update_values(*values)
else:
self.add_param(key, values, comment=comment)
def get_param(self, key: str, default: Union[int, float, str, List[float]]
) -> Union[int, float, str, List[float]]:
"""gets a param card"""
key = key.upper()
if key in self.params:
param = self.params[key]
return param.value
return default
#--------------------
# deprecations
@property
def dmis(self) -> Dict[str, DMI]:
return self.dmi
@property
def dmigs(self) -> Dict[str, DMIG]:
return self.dmig
@property
def dmiks(self) -> Dict[str, DMIK]:
return self.dmik
@property
def dmijs(self) -> Dict[str, DMIJ]:
return self.dmij
@property
def dmijis(self) -> Dict[str, DMIJI]:
return self.dmiji
@dmis.setter
def dmis(self, dmi):
self.dmi = dmi
@dmigs.setter
def dmigs(self, dmig):
self.dmig = dmig
@dmiks.setter
def dmiks(self, dmik):
self.dmik = dmik
@dmijs.setter
def dmijs(self, dmij):
self.dmij = dmij
@dmijis.setter
def dmijis(self, dmiji):
self.dmiji = dmiji