Source code for pyNastran.bdf.cards.thermal.thermal

# pylint: disable=R0902,R0904,R0914,C0111
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np

from pyNastran.utils.numpy_utils import integer_types
from pyNastran.bdf.field_writer_8 import set_blank_if_default, print_card_8
from pyNastran.bdf.field_writer_16 import print_card_16
from pyNastran.bdf.cards.base_card import BaseCard, _node_ids
#from pyNastran.bdf.cards.collpase_card import collapse_thru_by
from pyNastran.bdf.bdf_interface.assign_type import (
    integer, double, integer_or_blank, double_or_blank,
    string, blank, string_or_blank)
if TYPE_CHECKING:  # pragma: no cover
    from pyNastran.bdf.bdf import BDF


[docs] class ThermalCard(BaseCard): def __init__(self): BaseCard.__init__(self)
[docs] def cross_reference(self, model: BDF) -> None: raise NotImplementedError('%s has not defined the cross_reference ' 'method' % self.__class__.__name__)
[docs] class ThermalBC(ThermalCard): def __init__(self): ThermalCard.__init__(self)
[docs] class ThermalElement(ThermalCard): def __init__(self): ThermalCard.__init__(self)
#def Centroid(self): #return np.zeros(3) #def center_of_mass(self): #return self.Centroid()
[docs] class ThermalProperty(ThermalCard): def __init__(self): ThermalCard.__init__(self)
#------------------------------------------------------- # Elements
[docs] class CHBDYE(ThermalElement): """ Defines a boundary condition surface element with reference to a heat conduction element. +--------+-----+------+------+--------+--------+---------+---------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +========+=====+======+======+========+========+=========+=========+ | CHBDYE | EID | EID2 | SIDE | IVIEWF | IVIEWB | RADMIDF | RADMIDB | +--------+-----+------+------+--------+--------+---------+---------+ """ type = 'CHBDYE' _properties = ['hex_map', 'pent_map', 'tet_map', 'side_maps'] hex_map = { 1: [4, 3, 2, 1], 2: [1, 2, 6, 5], 3: [2, 3, 7, 6], 4: [3, 4, 8, 7], 5: [4, 1, 5, 8], 6: [5, 6, 7, 8], } pent_map = { 1: [3, 2, 1], 2: [1, 2, 5, 4], 3: [2, 3, 6, 5], 4: [3, 1, 4, 6], 5: [4, 5, 6], } tet_map = { 1: [1, 3, 2], 2: [1, 2, 4], 3: [2, 3, 4], 4: [3, 1, 4], } side_maps = { 'CHEXA': hex_map, 'CPENTA': pent_map, 'CTETRA': tet_map, 'CTRIA3': [1, 2, 3], 'CQUAD4': [1, 2, 3, 4], } #pid = 0
[docs] @classmethod def _init_from_empty(cls): eid = 1 eid2 = 2 side = 1 return CHBDYE(eid, eid2, side, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, comment='')
def __init__(self, eid, eid2, side, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, comment=''): """ Creates a CHBDYE card Parameters ---------- eid : int surface element ID number for a side of an element eid2: int a heat conduction element identification side: int a consistent element side identification number (1-6) iview_front: int; default=0 a VIEW entry identification number for the front face iview_back: int; default=0 a VIEW entry identification number for the back face rad_mid_front: int; default=0 RADM identification number for front face of surface element rad_mid_back: int; default=0 RADM identification number for back face of surface element comment : str; default='' a comment for the card """ ThermalElement.__init__(self) if comment: self.comment = comment #: Surface element ID number for a side of an #: element. (0 < Integer < 100,000,000) self.eid = eid #: A heat conduction element identification self.eid2 = eid2 #: A consistent element side identification number #: (1 < Integer < 6) self.side = side assert 0 < side < 7 #: A VIEW entry identification number for the front face self.iview_front = iview_front #: A VIEW entry identification number for the back face self.iview_back = iview_back #: RADM identification number for front face of surface element #: (Integer > 0) self.rad_mid_front = rad_mid_front #: RADM identification number for back face of surface element #: (Integer > 0) self.rad_mid_back = rad_mid_back self.grids = []
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a CHBDYE card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ eid = integer(card, 1, 'eid') eid2 = integer(card, 2, 'eid2') side = integer(card, 3, 'side') iview_front = integer_or_blank(card, 4, 'iview_front', 0) iview_back = integer_or_blank(card, 5, 'iview_back', 0) rad_mid_front = integer_or_blank(card, 6, 'rad_mid_front', 0) rad_mid_back = integer_or_blank(card, 7, 'rad_mid_back', 0) assert len(card) <= 8, f'len(CHBDYE card) = {len(card):d}\ncard={card}' return CHBDYE(eid, eid2, side, iview_front, iview_back, rad_mid_front, rad_mid_back, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a CHBDYE card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ eid, eid2, side, iviewf, iviewb, radmidf, radmidb = data return CHBDYE(eid, eid2, side, iviewf, iviewb, radmidf, radmidb, comment=comment)
[docs] def cross_reference(self, model: BDF) -> None: pass
[docs] def safe_cross_reference(self, model: BDF, xref_errors): pass
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" pass
@property def nodes(self): return [] @property def node_ids(self): return _node_ids(self, nodes=self.grids, allow_empty_nodes=False, msg='')
[docs] def Pid(self): return 0
#if self.pid_ref is not None: #return self.pid_ref.pid #return self.pid
[docs] def get_edge_ids(self): # TODO: not implemented return []
def _verify(self, xref): eid = self.Eid() eid2 = self.Eid2() pid = self.Pid() assert isinstance(eid, integer_types) assert isinstance(eid2, integer_types) assert isinstance(pid, integer_types) #def side_to_eids(self, eid): #side_ids = self.side_maps[eid.type][self.side] ## [1,2,3] ## id-1 is for the 0 based python index #nodes = [enodes[id - 1] for id in range(len(eid.nodes)) #if id in side_ids] #return side
[docs] def Eid(self): return self.eid
[docs] def Eid2(self): return self.eid2
[docs] def raw_fields(self): list_fields = ['CHBDYE', self.eid, self.eid2, self.side, self.iview_front, self.iview_back, self.rad_mid_front, self.rad_mid_back] return list_fields
[docs] def repr_fields(self): """ .. todo:: is this done """ #eids = collapse_thru_by(self.eids) list_fields = ['CHBDYE', self.eid, self.eid2, self.side, self.iview_front, self.iview_back, self.rad_mid_front, self.rad_mid_back] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class CHBDYG(ThermalElement): """ Defines a boundary condition surface element without reference to a property entry. +--------+-----+----+------+--------+--------+---------+---------+-----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=====+====+======+========+========+=========+=========+=====+ | CHBDYG | EID | | TYPE | IVIEWF | IVIEWB | RADMIDF | RADMIDB | | +--------+-----+----+------+--------+--------+---------+---------+-----+ | | G1 | G2 | G3 | G4 | G5 | G6 | G7 | G8 | +--------+-----+----+------+--------+--------+---------+---------+-----+ """ type = 'CHBDYG' _properties = ['node_ids']
[docs] @classmethod def _init_from_empty(cls): eid = 1 surface_type = 'AREA3' nodes = [1, 2] return CHBDYG(eid, surface_type, nodes, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, comment='')
def __init__(self, eid, surface_type, nodes, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, comment=''): ThermalElement.__init__(self) if comment: self.comment = comment #: Surface element ID self.eid = eid #: Surface type self.surface_type = surface_type #: A VIEW entry identification number for the front face self.iview_front = iview_front #: A VIEW entry identification number for the back face self.iview_back = iview_back #: RADM identification number for front face of surface element #: (Integer > 0) self.rad_mid_front = rad_mid_front #: RADM identification number for back face of surface element #: (Integer > 0) self.rad_mid_back = rad_mid_back #: Grid point IDs of grids bounding the surface (Integer > 0) self.nodes = nodes assert self.surface_type in ['REV', 'AREA3', 'AREA4', 'AREA6', 'AREA8'], 'surface_type=%r' % surface_type assert len(nodes) > 0, nodes self.nodes_ref = None
[docs] def validate(self): #assert self.surface_type in ['REV', 'AREA3', 'AREA4', 'AREA6', 'AREA8'], 'surface_type=%r' % self.surface_type if self.surface_type == 'REV': assert len(self.nodes) in [2, 3], 'CHBDYG: REV; nodes=%s' % str(self.nodes) elif self.surface_type == 'REV1': assert len(self.nodes) == 3, 'CHBDYG: REV; nodes=%s' % str(self.nodes) else: if self.surface_type == 'AREA3': nnodes_required = 3 nnodes_allowed = 3 elif self.surface_type == 'AREA4': nnodes_required = 4 nnodes_allowed = 4 elif self.surface_type == 'AREA6': nnodes_required = 3 nnodes_allowed = 6 elif self.surface_type == 'AREA8': nnodes_required = 4 nnodes_allowed = 8 else: raise RuntimeError('CHBDYG surface_type=%r' % self.surface_type) if len(self.nodes) < nnodes_required: msg = 'nnodes=%s nnodes_required=%s; surface_type=%r' % ( len(self.nodes), nnodes_required, self.surface_type) raise ValueError(msg) if len(self.nodes) > nnodes_allowed: msg = 'nnodes=%s nnodes_allowed=%s; surface_type=%r' % ( len(self.nodes), nnodes_allowed, self.surface_type) raise ValueError(msg)
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a CHBDYG card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ eid = integer(card, 1, 'eid') # no field 2 surface_type = string(card, 3, 'Type') iview_front = integer_or_blank(card, 4, 'iview_front', default=0) iview_back = integer_or_blank(card, 8, 'iview_back', default=0) rad_mid_front = integer_or_blank(card, 6, 'rad_mid_front', default=0) rad_mid_back = integer_or_blank(card, 7, 'rad_mid_back', default=0) # no field 8 n = 1 nodes = [] for i in range(9, len(card)): grid = integer_or_blank(card, i, 'grid%d' % n) nodes.append(grid) # used to have a None option assert len(nodes) > 0, 'card=%s' % card return CHBDYG(eid, surface_type, nodes, iview_front=iview_front, iview_back=iview_back, rad_mid_front=rad_mid_front, rad_mid_back=rad_mid_back, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a CHBDYG card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ eid = data[0] surface_type = data[1] i_view_front = data[2] i_view_back = data[3] rad_mid_front = data[4] rad_mid_back = data[5] nodes = [datai for datai in data[6:14] if datai > 0] surface_type_int_to_str = { 3 : 'REV', 4 : 'AREA3', 5 : 'AREA4', #7: 'AREA6',# ??? 8 : 'AREA6', 9 : 'AREA8', } try: surface_type = surface_type_int_to_str[surface_type] except KeyError: raise NotImplementedError('eid=%s surface_type=%r' % (eid, surface_type)) assert surface_type in ['REV', 'AREA3', 'AREA4', 'AREA6', 'AREA8'], 'surface_type=%r data=%s' % (surface_type, data) return CHBDYG(eid, surface_type, nodes, iview_front=i_view_front, iview_back=i_view_back, rad_mid_front=rad_mid_front, rad_mid_back=rad_mid_back, comment=comment) def _verify(self, xref): eid = self.Eid() assert isinstance(eid, integer_types) @property def node_ids(self): if self.nodes_ref is None: return self.nodes # TODO: is this correct? return _node_ids(self, nodes=self.nodes_ref, allow_empty_nodes=True, msg='')
[docs] def get_edge_ids(self): # TODO: not implemented return []
[docs] def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CHBDYG eid=%s' % self.eid self.nodes_ref = model.EmptyNodes(self.nodes, msg=msg)
[docs] def safe_cross_reference(self, model: BDF, xref_errors): msg = ', which is required by CHBDYG eid=%s' % self.eid self.nodes_ref = model.EmptyNodes(self.nodes, msg=msg)
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" self.nodes = self.node_ids self.nodes_ref = None
[docs] def Eid(self): return self.eid
[docs] def raw_fields(self): list_fields = ( ['CHBDYG', self.eid, None, self.surface_type, self.iview_front, self.iview_back, self.rad_mid_front, self.rad_mid_back, None,] + self.node_ids) return list_fields
[docs] def repr_fields(self): i_view_front = set_blank_if_default(self.iview_front, 0) i_view_back = set_blank_if_default(self.iview_back, 0) rad_mid_front = set_blank_if_default(self.rad_mid_front, 0) rad_mid_back = set_blank_if_default(self.rad_mid_back, 0) list_fields = (['CHBDYG', self.eid, None, self.surface_type, i_view_front, i_view_back, rad_mid_front, rad_mid_back, None, ] + self.node_ids) return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class CHBDYP(ThermalElement): """ Defines a boundary condition surface element with reference to a PHBDY entry +--------+---------+---------+------+--------+--------+----+----+----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=========+=========+======+========+========+====+====+====+ | CHBDYP | EID | PID | TYPE | IVIEWF | IVIEWB | G1 | G2 | G0 | +--------+---------+---------+------+--------+--------+----+----+----+ | | RADMIDF | RADMIDB | GMID | CE | E1 | E2 | E3 | | +--------+---------+---------+------+--------+--------+----+----+----+ """ type = 'CHBDYP' _properties = ['node_ids']
[docs] @classmethod def _init_from_empty(cls): eid = 1 pid = 2 surface_type = 'POINT' g1 = 1 g2 = None return CHBDYP(eid, pid, surface_type, g1, g2, g0=0, gmid=None, ce=0, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, e1=None, e2=None, e3=None, comment='')
[docs] def _finalize_hdf5(self, encoding): """hdf5 helper function""" if isinstance(self.nodes, np.ndarray): self.nodes = self.nodes.tolist() self.nodes = [None if (nid is None or np.isnan(nid)) else nid for nid in self.nodes]
def __init__(self, eid, pid, surface_type, g1, g2, g0=0, gmid=None, ce=0, iview_front=0, iview_back=0, rad_mid_front=0, rad_mid_back=0, e1=None, e2=None, e3=None, comment=''): """ Creates a CHBDYP card Parameters ---------- eid : int Surface element ID pid : int PHBDY property entry identification numbers. (Integer > 0) surface_type : str Surface type Must be {POINT, LINE, ELCYL, FTUBE, TUBE} iview_front : int; default=0 A VIEW entry identification number for the front face. iview_back : int; default=0 A VIEW entry identification number for the back face. g1 / g2 : int Grid point identification numbers of grids bounding the surface g0 : int; default=0 Orientation grid point rad_mid_front : int RADM identification number for front face of surface element rad_mid_back : int RADM identification number for back face of surface element. gmid : int Grid point identification number of a midside node if it is used with the line type surface element. ce : int; default=0 Coordinate system for defining orientation vector e1 / e2 / e3 : float; default=None Components of the orientation vector in coordinate system CE. The origin of the orientation vector is grid point G1. comment : str; default='' a comment for the card """ ThermalElement.__init__(self) if comment: self.comment = comment #: Surface element ID self.eid = eid #: PHBDY property entry identification numbers. (Integer > 0) self.pid = pid self.surface_type = surface_type #: A VIEW entry identification number for the front face. self.iview_front = iview_front #: A VIEW entry identification number for the back face. self.iview_back = iview_back #: Grid point identification numbers of grids bounding the surface. #: (Integer > 0) self.g1 = g1 #: Grid point identification numbers of grids bounding the surface. #: (Integer > 0) self.g2 = g2 #: Orientation grid point. (Integer > 0; Default = 0) self.g0 = g0 #: RADM identification number for front face of surface element. #: (Integer > 0) self.rad_mid_front = rad_mid_front #: RADM identification number for back face of surface element. #: (Integer > 0) self.rad_mid_back = rad_mid_back #: Grid point identification number of a midside node if it is used #: with the line type surface element. self.gmid = gmid #: Coordinate system for defining orientation vector. #: (Integer > 0; Default = 0 self.ce = ce #: Components of the orientation vector in coordinate system CE. #: The origin of the orientation vector is grid point G1. #: (Real or blank) self.e1 = e1 self.e2 = e2 self.e3 = e3 assert self.pid > 0 self.nodes_ref = None self.pid_ref = None self.ce_ref = None assert surface_type in ['POINT', 'LINE', 'ELCYL', 'FTUBE', 'TUBE'], surface_type @property def Type(self): return self.surface_type @Type.setter def Type(self, surface_type): self.surface_type = surface_type
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a CHBDYP card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ eid = integer(card, 1, 'eid') pid = integer(card, 2, 'pid') surface_type = string(card, 3, 'Type') iview_front = integer_or_blank(card, 4, 'iview_front', default=0) iview_back = integer_or_blank(card, 5, 'iview_back', default=0) g1 = integer(card, 6, 'g1') if surface_type != 'POINT': g2 = integer(card, 7, 'g2') else: g2 = blank(card, 7, 'g2') g0 = integer_or_blank(card, 8, 'g0', default=0) rad_mid_front = integer_or_blank(card, 9, 'rad_mid_front', default=0) rad_mid_back = integer_or_blank(card, 10, 'rad_mid_back', default=0) gmid = integer_or_blank(card, 11, 'gmid') ce = integer_or_blank(card, 12, 'ce', default=0) e1 = double_or_blank(card, 13, 'e1') e2 = double_or_blank(card, 14, 'e2') e3 = double_or_blank(card, 15, 'e3') assert len(card) <= 16, f'len(CHBDYP card) = {len(card):d}\ncard={card}' return CHBDYP(eid, pid, surface_type, g1, g2, g0=g0, gmid=gmid, ce=ce, iview_front=iview_front, iview_back=iview_back, rad_mid_front=rad_mid_front, rad_mid_back=rad_mid_back, e1=e1, e2=e2, e3=e3, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a CHBDYP card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ [eid, pid, surface_type, iview_front, iview_back, g1, g2, g0, radmidf, radmidb, dislin, ce, e1, e2, e3] = data #eid = data[0] #surface_type = data[1] #iview_front = data[2] #iview_back = data[3] #rad_mid_front = data[4] #rad_mid_back = data[5] #nodes = [datai for datai in data[6:14] if datai > 0] surface_type_int_to_str = { 1 : 'POINT', 2 : 'LINE', 6 : 'ELCYL', 7 : 'FTUBE', 10 : 'TUBE', } try: surface_type = surface_type_int_to_str[surface_type] except KeyError: # pragma: no cover raise NotImplementedError('CHBDYP surface_type=%r data=%s' % (surface_type, data)) #assert dislin == 0, 'CHBDYP dislin=%r data=%s' % (dislin, data) if dislin == 0: gmid = None else: gmid = dislin return CHBDYP(eid, pid, surface_type, g1, g2, g0=g0, gmid=gmid, ce=ce, iview_front=iview_front, iview_back=iview_back, rad_mid_front=radmidf, rad_mid_back=radmidb, e1=e1, e2=e2, e3=e3, comment=comment) @property def nodes(self): return [self.g1, self.g2, self.g0, self.gmid] @nodes.setter def nodes(self, nodes): self.g1 = nodes[0] self.g2 = nodes[1] self.g0 = nodes[2] self.gmid = nodes[3] assert len(nodes) == 4, len(nodes) @property def node_ids(self): return _node_ids(self, nodes=self.nodes, allow_empty_nodes=True, msg='')
[docs] def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ try: msg = ', which is required by CHBDYP pid=%s' % self.pid self.pid_ref = model.Phbdy(self.pid, msg=msg) self.nodes_ref = model.EmptyNodes(self.nodes, msg=msg) self.ce_ref = model.Coord(self.ce, msg) except KeyError: print(self.get_stats()) raise
[docs] def safe_cross_reference(self, model: BDF, xref_errors): msg = ', which is required by CHBDYP pid=%s' % self.pid self.pid_ref = model.Phbdy(self.pid, msg=msg) self.nodes_ref = model.EmptyNodes(self.nodes, msg=msg) self.ce_ref = model.safe_coord(self.ce, self.pid, xref_errors, msg)
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" self.nodes = self.node_ids self.pid = self.Pid() self.ce = self.Ce() self.nodes_ref = None self.pid_ref = None self.ce_ref = None
def _verify(self, xref): eid = self.Eid() pid = self.Pid() ce = self.Ce() assert isinstance(eid, integer_types) assert isinstance(pid, integer_types) assert isinstance(ce, integer_types)
[docs] def Eid(self): return self.eid
[docs] def Pid(self): if self.pid_ref is not None: return self.pid_ref.pid return self.pid
[docs] def Ce(self): """gets the coordinate system, CE""" if self.ce_ref is not None: return self.ce_ref.cid return self.ce
[docs] def raw_fields(self): (g1, g2, g0, gmid) = self.node_ids list_fields = ['CHBDYP', self.eid, self.Pid(), self.surface_type, self.iview_front, self.iview_back, g1, g2, g0, self.rad_mid_front, self.rad_mid_back, gmid, self.Ce(), self.e1, self.e2, self.e3] return list_fields
[docs] def repr_fields(self): iview_front = set_blank_if_default(self.iview_front, 0) iview_back = set_blank_if_default(self.iview_back, 0) rad_mid_front = set_blank_if_default(self.rad_mid_front, 0) rad_mid_back = set_blank_if_default(self.rad_mid_back, 0) (g1, g2, g0, gmid) = self.node_ids g0 = set_blank_if_default(g0, 0) ce = set_blank_if_default(self.Ce(), 0) list_fields = ['CHBDYP', self.eid, self.Pid(), self.surface_type, iview_front, iview_back, g1, g2, g0, rad_mid_front, rad_mid_back, gmid, ce, self.e1, self.e2, self.e3] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
# Elements #------------------------------------------------------- # Properties
[docs] class PCONV(ThermalProperty): """ Specifies the free convection boundary condition properties of a boundary condition surface element used for heat transfer analysis. Format (MSC 2005.2) +-------+--------+-------+-------+-------+-------+-----+----+----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +=======+========+=======+=======+=======+=======+=====+====+====+ | PCONV | PCONID | MID | FORM | EXPF | FTYPE | TID | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ | | CHLEN | GIDIN | CE | E1 | E2 | E3 | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ | PCONV | 38 | 21 | 2 | 54 | | | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ | | 2.0 | 235 | 0 | 1.0 | 0.0 | 0.0 | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ Alternate format (MSC 2005.2): +-------+--------+-------+-------+-------+-------+-----+----+----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +=======+========+=======+=======+=======+=======+=====+====+====+ | PCONV | PCONID | MID | FORM | EXPF | 3 | H1 | H2 | H3 | +-------+--------+-------+-------+-------+-------+-----+----+----+ | | H4 | H5 | H6 | H7 | H8 | | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ | PCONV | 7 | 3 | 10.32 | 10.05 | 10.09 | | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ | | 10.37 | | | | | | | | +-------+--------+-------+-------+-------+-------+-----+----+----+ .. todo:: alternate format is not supported; NX not checked """ type = 'PCONV'
[docs] @classmethod def _init_from_empty(cls): pconid = 1 #mid = 1 return PCONV(pconid, mid=None, form=0, expf=0.0, ftype=0, tid=None, chlen=None, gidin=None, ce=0, e1=None, e2=None, e3=None, comment='')
def __init__(self, pconid, mid=None, form=0, expf=0.0, ftype=0, tid=None, chlen=None, gidin=None, ce=0, e1=None, e2=None, e3=None, comment=''): """ Creates a PCONV card Parameters ---------- pconid : int Convection property ID mid : int Material ID form : int; default=0 Type of formula used for free convection Must be {0, 1, 10, 11, 20, or 21} expf : float; default=0.0 Free convection exponent as implemented within the context of the particular form that is chosen ftype : int; default=0 Formula type for various configurations of free convection tid : int; default=None Identification number of a TABLEHT entry that specifies the two variable tabular function of the free convection heat transfer coefficient chlen : float; default=None Characteristic length gidin : int; default=None Grid ID of the referenced inlet point ce : int; default=0 Coordinate system for defining orientation vector. e1 / e2 / e3 : list[float]; default=None Components of the orientation vector in coordinate system CE. The origin of the orientation vector is grid point G1 comment : str; default='' a comment for the card """ ThermalProperty.__init__(self) if comment: self.comment = comment #: Convection property identification number. (Integer > 0) self.pconid = pconid #: Material property identification number. (Integer > 0) self.mid = mid #: Type of formula used for free convection. #: (Integer 0, 1, 10, 11, 20, or 21) self.form = form #: Free convection exponent as implemented within the context of the #: particular form that is chosen self.expf = expf #: Formula type for various configurations of free convection self.ftype = ftype #: Identification number of a TABLEHT entry that specifies the two #: variable tabular function of the free convection heat transfer #: coefficient self.tid = tid #: Characteristic length self.chlen = chlen #: Grid ID of the referenced inlet point self.gidin = gidin #: Coordinate system for defining orientation vector. #: (Integer > 0;Default = 0 self.ce = ce #: Components of the orientation vector in coordinate system CE. The #: origin of the orientation vector is grid point G1. (Real or blank) self.e1 = e1 self.e2 = e2 self.e3 = e3 assert self.pconid > 0 assert mid is None or self.mid > 0 assert self.form in [0, 1, 10, 11, 20, 21] self.ce_ref = None self.gidin_ref = None
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a PCONV card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ pconid = integer(card, 1, 'pconid') mid = integer_or_blank(card, 2, 'mid') form = integer_or_blank(card, 3, 'form', default=0) expf = double_or_blank(card, 4, 'expf', default=0.0) ftype = integer_or_blank(card, 5, 'ftype', default=0) tid = integer_or_blank(card, 6, 'tid') chlen = double_or_blank(card, 9, 'chlen') gidin = integer_or_blank(card, 10, 'gidin') ce = integer_or_blank(card, 11, 'ce', default=0) e1 = double_or_blank(card, 12, 'e1') e2 = double_or_blank(card, 13, 'e2') e3 = double_or_blank(card, 14, 'e3') assert len(card) <= 15, f'len(PCONV card) = {len(card):d}\ncard={card}' return PCONV(pconid, mid=mid, form=form, expf=expf, ftype=ftype, tid=tid, chlen=chlen, gidin=gidin, ce=ce, e1=e1, e2=e2, e3=e3, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a PCONV card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ (pconid, mid, form, expf, ftype, tid, chlen, gidin, ce, e1, e2, e3) = data return PCONV(pconid, mid, form, expf, ftype, tid, chlen, gidin, ce, e1, e2, e3, comment=comment)
[docs] def Ce(self): """gets the coordinate system, CE""" if self.ce_ref is not None: return self.ce_ref.cid return self.ce
[docs] def Gidin(self): """gets the grid input node, gidin""" if self.gidin_ref is not None: return self.gidin_ref.nid return self.gidin
[docs] def cross_reference(self, model: BDF) -> None: msg = 'which is required by PCONV pconid=%s' % self.pconid self.ce_ref = model.Coord(self.ce, msg) if self.gidin is not None: self.gidin_ref = model.Node(self.gidin, msg)
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" self.ce = self.Ce() self.ce_ref = None self.gidin = self.Gidin() self.gidin_ref = None
[docs] def raw_fields(self): list_fields = ['PCONV', self.pconid, self.mid, self.form, self.expf, self.ftype, self.tid, None, None, self.chlen, self.Gidin(), self.Ce(), self.e1, self.e2, self.e3] return list_fields
[docs] def repr_fields(self): form = set_blank_if_default(self.form, 0) expf = set_blank_if_default(self.expf, 0.0) ftype = set_blank_if_default(self.ftype, 0) ce = set_blank_if_default(self.Ce(), 0) list_fields = ['PCONV', self.pconid, self.mid, form, expf, ftype, self.tid, None, None, self.chlen, self.Gidin(), ce, self.e1, self.e2, self.e3] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class PCONVM(ThermalProperty): """ Specifies the free convection boundary condition properties of a boundary condition surface element used for heat transfer analysis. +--------+--------+-----+------+------+-------+------+-------+-------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+========+=====+======+======+=======+======+=======+=======+ | PCONVM | PCONID | MID | FORM | FLAG | COEF | EXPR | EXPPI | EXPPO | +--------+--------+-----+------+------+-------+------+-------+-------+ | PCONVM | 3 | 2 | 1 | 1 | 0.023 | 0.80 | 0.40 | 0.30 | +--------+--------+-----+------+------+-------+------+-------+-------+ """ type = 'PCONVM'
[docs] @classmethod def _init_from_empty(cls): pconid = 1 mid = 1 coeff = 0.1 return PCONVM(pconid, mid, coeff, form=0, flag=0, expr=0.0, exppi=0.0, exppo=0.0, comment='')
def __init__(self, pconid, mid, coeff, form=0, flag=0, expr=0.0, exppi=0.0, exppo=0.0, comment=''): """ Creates a PCONVM card Parameters ---------- pconid : int Convection property ID mid: int Material ID coeff: float Constant coefficient used for forced convection form: int; default=0 Type of formula used for free convection Must be {0, 1, 10, 11, 20, or 21} flag: int; default=0 Flag for mass flow convection expr: float; default=0.0 Reynolds number convection exponent exppi: float; default=0.0 Prandtl number convection exponent for heat transfer into the working fluid exppo: float; default=0.0 Prandtl number convection exponent for heat transfer out of the working fluid comment : str; default='' a comment for the card """ ThermalProperty.__init__(self) if comment: self.comment = comment #: Convection property identification number. (Integer > 0) self.pconid = pconid assert self.pconid > 0 #: Material property identification number. (Integer > 0) self.mid = mid assert self.mid > 0 #: Type of formula used for free convection. #: (Integer 0, 1, 10, 11, 20, or 21) self.form = form assert self.form in [0, 1, 10, 11, 20, 21] #: Flag for mass flow convection. (Integer = 0 or 1; Default = 0) self.flag = flag #: Constant coefficient used for forced convection self.coef = coeff #: Reynolds number convection exponent. (Real > 0.0; Default = 0.0) self.expr = expr #: Prandtl number convection exponent for heat transfer into the #: working fluid. (Real > 0.0; Default = 0.0) self.exppi = exppi #: Prandtl number convection exponent for heat transfer out of the #: working fluid. (Real > 0.0; Default = 0.0) self.exppo = exppo
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a PCONVM card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ pconid = integer(card, 1, 'pconid') mid = integer(card, 2, 'mid') form = integer_or_blank(card, 3, 'form', default=0) flag = integer_or_blank(card, 4, 'flag', default=0) coef = double(card, 5, 'coef') expr = double_or_blank(card, 6, 'expr', default=0.0) exppi = double_or_blank(card, 7, 'exppi', default=0.0) exppo = double_or_blank(card, 8, 'exppo', default=0.0) assert len(card) <= 9, f'len(PCONVM card) = {len(card):d}\ncard={card}' return PCONVM(pconid, mid, coef, form=form, flag=flag, expr=expr, exppi=exppi, exppo=exppo, comment=comment)
#def cross_reference(self, model: BDF) -> None: #pass
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" pass
[docs] def raw_fields(self): list_fields = ['PCONVM', self.pconid, self.mid, self.form, self.flag, self.coef, self.expr, self.exppi, self.exppo] return list_fields
[docs] def repr_fields(self): form = set_blank_if_default(self.form, 0) flag = set_blank_if_default(self.flag, 0) expr = set_blank_if_default(self.expr, 0.0) exppi = set_blank_if_default(self.exppi, 0.0) exppo = set_blank_if_default(self.exppo, 0.0) list_fields = ['PCONVM', self.pconid, self.mid, form, flag, self.coef, expr, exppi, exppo] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class PHBDY(ThermalProperty): """ A property entry referenced by CHBDYP entries to give auxiliary geometric information for boundary condition surface elements +-------+-----+------+-----+-----+ | 1 | 2 | 3 | 4 | 5 | +=======+=====+======+=====+=====+ | PHBDY | PID | AF | D1 | D2 | +-------+-----+------+-----+-----+ | PHBDY | 2 | 0.02 | 1.0 | 1.0 | +-------+-----+------+-----+-----+ """ type = 'PHBDY'
[docs] @classmethod def _init_from_empty(cls): pid = 1 return PHBDY(pid, af=None, d1=None, d2=None, comment='')
def __init__(self, pid, af=None, d1=None, d2=None, comment=''): """ Creates a PHBDY card Parameters ---------- eid : int element id pid : int property id af : int Area factor of the surface used only for CHBDYP element Must be {POINT, LINE, TUBE, ELCYL} TUBE : constant thickness of hollow tube d1, d2 : float; default=None Diameters associated with the surface Used with CHBDYP [ELCYL, TUBE, FTUBE] surface elements comment : str; default='' a comment for the card """ ThermalProperty.__init__(self) if comment: self.comment = comment if d2 is None: d2 = d1 #: Property identification number. (Unique Integer among all PHBDY #: entries). (Integer > 0) self.pid = pid assert self.pid > 0 #: Area factor of the surface used only for CHBDYP element #: TYPE = 'POINT', TYPE = 'LINE', TYPE = 'TUBE', or #: TYPE = 'ELCYL'. For TYPE = 'TUBE', AF is the constant thickness #: of the hollow tube. (Real > 0.0 or blank) self.af = af #: Diameters associated with the surface. Used with CHBDYP element #: TYPE='ELCYL','TUBE','FTUBE' self.d1 = d1 self.d2 = d2
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a PHBDY card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ pid = integer(card, 1, 'pid') af = double_or_blank(card, 2, 'af', default=None) d1 = double_or_blank(card, 3, 'd1', default=None) d2 = double_or_blank(card, 4, 'd2', default=d1) assert len(card) <= 5, f'len(PHBDY card) = {len(card):d}\ncard={card}' return PHBDY(pid, af, d1, d2, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a PHBDY card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ pid = data[0] af = data[1] d1 = data[2] d2 = data[3] assert len(data) == 4, 'data = %s' % data return PHBDY(pid, af, d1, d2, comment=comment) #def cross_reference(self, model: BDF) -> None: #pass
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" pass
[docs] def raw_fields(self): list_fields = ['PHBDY', self.pid, self.af, self.d1, self.d2] return list_fields
[docs] def repr_fields(self): d2 = set_blank_if_default(self.d2, self.d1) list_fields = ['PHBDY', self.pid, self.af, self.d1, d2] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
# Properties #------------------------------------------------------- # Boundary Conditions
[docs] class CONV(ThermalBC): """ Specifies a free convection boundary condition for heat transfer analysis through connection to a surface element (CHBDYi entry). """ type = 'CONV'
[docs] @classmethod def _init_from_empty(cls): eid = 1 #nodamb = 1 pconid = 2 ta = 1.0 return CONV(eid, pconid, ta, film_node=0, cntrlnd=0, comment='')
def __init__(self, eid, pconid, ta, film_node=0, cntrlnd=0, comment=''): """ Creates a CONV card Parameters ---------- eid : int element id pconid : int Convection property ID mid : int Material ID ta : list[int] Ambient points used for convection 0's are allowed for TA2 and higher film_node : int; default=0 Point for film convection fluid property temperature cntrlnd : int; default=0 Control point for free convection boundary condition comment : str; default='' a comment for the card """ ThermalBC.__init__(self) if comment: self.comment = comment #: CHBDYG, CHBDYE, or CHBDYP surface element identification number. #: (Integer > 0) self.eid = eid #: Convection property identification number of a PCONV entry self.pconid = pconid #: Point for film convection fluid property temperature self.film_node = film_node #: Control point for free convection boundary condition. self.cntrlnd = cntrlnd #: Ambient points used for convection 0's are allowed for TA2 and #: higher. (Integer > 0 for TA1 and Integer > 0 for TA2 through TA8; #: Default for TA2 through TA8 is TA1.) if isinstance(ta, integer_types): self.ta = [ta] else: self.ta = ta assert self.eid > 0, 'eid=%s\n%s' % (eid, str(self)) self.eid_ref = None
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a CONV card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ eid = integer(card, 1, 'eid') pconid = integer(card, 2, 'pconid') film_node = integer_or_blank(card, 3, 'film_node', 0) cntrlnd = integer_or_blank(card, 4, 'cntrlnd', 0) ta1 = integer(card, 5, 'TA1') assert ta1 > 0, ta1 ta2 = integer_or_blank(card, 6, 'ta2', ta1) ta3 = integer_or_blank(card, 7, 'ta3', ta1) ta4 = integer_or_blank(card, 8, 'ta4', ta1) ta5 = integer_or_blank(card, 9, 'ta5', ta1) ta6 = integer_or_blank(card, 10, 'ta6', ta1) ta7 = integer_or_blank(card, 11, 'ta7', ta1) ta8 = integer_or_blank(card, 12, 'ta8', ta1) ta = [ta1, ta2, ta3, ta4, ta5, ta6, ta7, ta8] assert len(card) <= 13, f'len(CONV card) = {len(card):d}\ncard={card}' return CONV(eid, pconid, ta, film_node, cntrlnd, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a CONV card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ #data_in = [eid, pconid, flmnd, cntrlnd, #[ta1, ta2, ta3, ta5, ta6, ta7, ta8], #[wt1, wt2, wt3, wt5, wt6, wt7, wt8]] ## weights are unique to MSC nastran eid, pconid, film_node, cntrlnd, ta, weights = data del weights #ta1, ta2, ta3, ta5, ta6, ta7, ta8 = ta #wt1, wt2, wt3, wt5, wt6, wt7, wt8 = aft return CONV(eid, pconid, ta, film_node, cntrlnd, comment=comment)
[docs] def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CONV eid=%s' % self.eid ## TODO: eid??? self.eid_ref = model.Element(self.eid, msg=msg) if model._xref == 1: # True assert self.eid_ref.type in ['CHBDYG', 'CHBDYE', 'CHBDYP']
[docs] def uncross_reference(self) -> None: """Removes cross-reference links""" self.eid_ref = None
[docs] def Eid(self): if self.eid_ref is not None: return self.eid_ref.eid return self.eid
[docs] def TA(self, i=None): if i is None: return self.ta return self.ta[i]
[docs] def raw_fields(self): list_fields = ['CONV', self.Eid(), self.pconid, self.film_node, self.cntrlnd] + self.ta return list_fields
[docs] def repr_fields(self): film_node = set_blank_if_default(self.film_node, 0) cntrlnd = set_blank_if_default(self.cntrlnd, 0) ta0 = self.ta[0] ta = [ta0] for tai in self.ta[1:]: ta.append(set_blank_if_default(tai, ta0)) list_fields = ['CONV', self.Eid(), self.pconid, film_node, cntrlnd] + ta return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class TEMPBC(ThermalBC): type = 'TEMPBC' _properties = ['eid']
[docs] @classmethod def _init_from_empty(cls): sid = 1 Type = 1 nodes = [1, 2] temps = [10., 20.] return TEMPBC(sid, Type, nodes, temps, comment='')
def __init__(self, sid, Type, nodes, temps, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment self.sid = sid self.Type = Type self.nodes = nodes self.temps = temps
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a TEMPBC card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ sid = integer(card, 1, 'sid') Type = string_or_blank(card, 2, 'Type', 'STAT') nfields_left = len(card) - 3 assert nfields_left > 0, card assert nfields_left % 2 == 0, card temps = [] nodes = [] for i in range(nfields_left // 2): ifield = 3 + i*2 temp = double(card, ifield, 'temp_%i'% ((i+1))) nid = integer(card, ifield+1, 'temp_%i'% ((i+1))) temps.append(temp) nodes.append(nid) return TEMPBC(sid, Type, nodes, temps, comment=comment)
@property def eid(self): return self.sid
[docs] def raw_fields(self): list_fields = ['TEMPBC', self.sid, self.Type] for temp, node in zip(self.temps, self.nodes): list_fields.extend([temp, node]) return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
[docs] class CONVM(ThermalBC): """ Specifies a forced convection boundary condition for heat transfer analysis through connection to a surface element (CHBDYi entry). +-------+-----+--------+-------+---------+-----+-----+------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +=======+=====+========+=======+=========+=====+=====+======+ | CONVM | EID | PCONID | FLMND | CNTMDOT | TA1 | TA2 | Mdot | +-------+-----+--------+-------+---------+-----+-----+------+ | CONVM | 101 | 1 | 201 | 301 | 20 | 21 | | +-------+-----+--------+-------+---------+-----+-----+------+ """ type = 'CONVM' _properties = ['film_node_id', 'pconvm_id']
[docs] @classmethod def _init_from_empty(cls): eid = 1 pconvm = 2 ta1 = 1.0 return CONVM(eid, pconvm, ta1, film_node=0, cntmdot=0, ta2=None, mdot=1.0, comment='')
def __init__(self, eid, pconvm, ta1, film_node=0, cntmdot=0, ta2=None, mdot=1.0, comment=''): """ Creates a CONVM card Parameters ---------- eid : int element id (CHBDYP) pconid : int property ID (PCONVM) ta1 : int ambient point for convection ta2 : int; default=None None : ta1 ambient point for convection film_node : int; default=0 cntmdot : int; default=0 control point used for controlling mass flow 0/blank is only allowed when mdot > 0 mdot : float; default=1.0 a multiplier for the mass flow rate in case there is no point associated with the CNTRLND field required if cntmdot = 0 comment : str; default='' a comment for the card """ ThermalBC.__init__(self) if comment: self.comment = comment if ta2 is None: ta2 = ta1 self.eid = eid self.pconvm = pconvm self.film_node = film_node self.cntmdot = cntmdot self.ta1 = ta1 self.ta2 = ta2 self.mdot = mdot assert film_node >= 0 if self.cntmdot == 0: if self.mdot is None: self.mdot = 1.0 else: assert self.cntmdot > 0 self.eid_ref = None self.pconvm_ref = None self.film_node_ref = None
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a CONVM card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ eid = integer(card, 1, 'eid') pconvm = integer(card, 2, 'pconvm') film_node = integer_or_blank(card, 3, 'film_node', default=0) cntmdot = integer_or_blank(card, 4, 'cntmdot', default=0) ta1 = integer(card, 5, 'ta1') ta2 = integer_or_blank(card, 6, 'ta2', default=ta1) mdot = double_or_blank(card, 7, 'mdot', default=1.0) assert len(card) <= 8, f'len(CONVM card) = {len(card):d}\ncard={card}' return CONVM(eid, pconvm, ta1, film_node=film_node, cntmdot=cntmdot, ta2=ta2, mdot=mdot, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a CONVM card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ (eid, pconvm_id, film_node, cntrlnd, ta1, ta2, mdot) = data return CONVM(eid, pconvm_id, ta1, film_node, cntrlnd, ta2, mdot, comment=comment)
[docs] def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CONVM eid=%s' % self.eid self.eid_ref = model.CYBDY(self.eid, msg=msg) self.pconvm_ref = model.PCONV(self.pconvm, msg=msg) self.film_node_ref = model.Grid(self.film_node, msg=msg)
[docs] def Eid(self): if self.eid_ref is not None: return self.eid_ref.eid return self.eid
@property def film_node_id(self): if self.film_node_ref is not None: return self.film_node_ref.nid return self.film_node @property def pconvm_id(self): if self.pconvm_ref is not None: return self.pconvm_ref.pconid return self.pconvm
[docs] def raw_fields(self): list_fields = ['CONVM', self.Eid(), self.pconvm_id, self.film_node_id, self.cntmdot, self.ta1, self.ta2, self.mdot] return list_fields
[docs] def repr_fields(self): film_node_id = set_blank_if_default(self.film_node_id, 0) ta2 = set_blank_if_default(self.ta2, self.ta1) mdot = set_blank_if_default(self.mdot, 1.0) list_fields = ['CONVM', self.Eid(), self.pconvm_id, film_node_id, self.cntmdot, self.ta1, ta2, mdot] return list_fields
[docs] def write_card(self, size: int=8, is_double: bool=False) -> str: """ The writer method used by BDF.write_card() Parameters ----------- size : int; default=8 the size of the card (8/16) """ card = self.repr_fields() if size == 8: return self.comment + print_card_8(card) return self.comment + print_card_16(card)
# Boundary Conditions #-------------------------------------------------------