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

"""
All set cards are defined in this file.  This includes:

* bcs
  * RADM, RADBC
* views
  * VIEW, VIEW3D

"""
from __future__ import annotations
from typing import TYPE_CHECKING
import warnings

from pyNastran.utils.numpy_utils import integer_types, float_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, expand_thru_by
from pyNastran.bdf.cards.collpase_card import collapse_thru_by
from pyNastran.bdf.bdf_interface.assign_type import (
    fields, integer, double, integer_or_blank, double_or_blank,
    integer_or_string, string_or_blank)

from pyNastran.bdf.cards.thermal.thermal import ThermalBC
if TYPE_CHECKING:  # pragma: no cover
    from pyNastran.bdf.bdf import BDF


[docs] class RADM(ThermalBC): """ Defines the radiation properties of a boundary element for heat transfer analysis """ type = 'RADM' @classmethod def _init_from_empty(cls): radmid = 2 absorb = 2.0 emissivity = 1.0 return RADM(radmid, absorb, emissivity, comment='') def __init__(self, radmid, absorb, emissivity, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment #: Material identification number self.radmid = radmid self.absorb = absorb if isinstance(emissivity, float_types): self.emissivity = [emissivity] else: self.emissivity = emissivity
[docs] def validate(self): assert self.radmid > 0, str(self) msg = '' if self.absorb is not None: if not 0. <= self.absorb <= 1.0: msg += 'absorb=%s not in range 0.0 <= absorb <= 1.0\n' % (self.absorb) for i, emissivityi in enumerate(self.emissivity): if not 0. <= emissivityi <= 1.0: msg += 'emissivity[%i]=%s\n' % (i, emissivityi) if msg: warnings.warn(msg + str(self))
#raise RuntimeError(msg + str(self))
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a RADM card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ nfields = card.nfields radmid = integer(card, 1, 'radmid') absorb = double_or_blank(card, 2, 'absorb') emissivity = fields(double, card, 'emissivity', i=3, j=nfields) return RADM(radmid, absorb, emissivity, comment=comment)
@classmethod def add_op2_data(cls, data, comment=''): """ Adds a RADM card from the OP2 Parameters ---------- data : list[varies] a list of fields defined in OP2 format comment : str; default='' a comment for the card """ radmid, absorb = data[:2] emissivity = data[2:] return RADM(radmid, absorb, emissivity, comment=comment) #def cross_reference(self, model: BDF) -> None: #pass
[docs] def raw_fields(self): list_fields = ['RADM', self.radmid, self.absorb] + self.emissivity return list_fields
[docs] def repr_fields(self): list_fields = ['RADM', self.radmid, self.absorb] + self.emissivity 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 RADBC(ThermalBC): """ Specifies an CHBDYi element face for application of radiation boundary conditions """ type = 'RADBC' @classmethod def _init_from_empty(cls): nodamb = 1 famb = 1.0 cntrlnd = 10 eids = [1, 2] return RADBC(nodamb, famb, cntrlnd, eids, comment='') def __init__(self, nodamb, famb, cntrlnd, eids, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment #: NODAMB Ambient point for radiation exchange. (Integer > 0) self.nodamb = nodamb #: Radiation view factor between the face and the ambient point. #: (Real > 0.0) self.famb = famb #: Control point for thermal flux load. (Integer > 0; Default = 0) self.cntrlnd = cntrlnd #: CHBDYi element identification number if isinstance(eids, int): eids = [eids] self.eids = expand_thru_by(eids) assert self.nodamb > 0 assert self.famb > 0.0 assert self.cntrlnd >= 0 self.eids_ref = None
[docs] def validate(self): min_eid = min(self.eids) if min_eid < 1: msg = 'min(eids)=%i' % min_eid warnings.warn(msg)
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a RADBC card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ nodamb = integer(card, 1, 'nodamb') famb = double(card, 2, 'famb') cntrlnd = integer_or_blank(card, 3, 'cntrlnd', default=0) nfields = card.nfields eids = fields(integer_or_string, card, 'eid', i=4, j=nfields) return RADBC(nodamb, famb, cntrlnd, eids, 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 RADBC pid=%s' % self.nodamb elems = [] for eid in self.eids: elem = model.Element(eid, msg=msg) elems.append(elem) self.eids_ref = elems
[docs] def Eids(self): if self.eids_ref is None: return self.eids eids = [] for eid_ref in self.eids_ref: eids.append(eid_ref.eid) return eids
[docs] def raw_fields(self): list_fields = (['RADBC', self.nodamb, self.famb, self.cntrlnd] + self.Eids()) return list_fields
[docs] def repr_fields(self): cntrlnd = set_blank_if_default(self.cntrlnd, 0) eids = collapse_thru_by(self.Eids()) list_fields = ['RADBC', self.nodamb, self.famb, cntrlnd] + eids 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 #------------------------------------------------------- # View Factors
[docs] class VIEW(BaseCard): """ Defines radiation cavity and shadowing for radiation view factor calculations. +------+-------+---------+-------+----+----+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +======+=======+=========+=======+====+====+========+ | VIEW | IVIEW | ICAVITY | SHADE | NB | NG | DISLIN | +------+-------+---------+-------+----+----+--------+ | VIEW | 1 | 1 | BOTH | 2 | 3 | 0.25 | +------+-------+---------+-------+----+----+--------+ """ type = 'VIEW' @classmethod def _init_from_empty(cls): iview = 2 icavity = 2 return VIEW(iview, icavity, shade='BOTH', nbeta=1, ngamma=1, dislin=0.0, comment='') def __init__(self, iview, icavity, shade='BOTH', nbeta=1, ngamma=1, dislin=0.0, comment=''): """ Creates a VIEW, which defines a 2D view factor Parameters ---------- iview : int Identification number icavity : int Cavity identification number for grouping the radiant exchange faces of CHBDYi elements shade : str; default='BOTH' Shadowing flag for the face of CHBDYi element - NONE means the face can neither shade nor be shaded by other faces - KSHD means the face can shade other faces - KBSHD means the face can be shaded by other faces - BOTH means the face can both shade and be shaded by other faces nbeta / ngamma : int; default=1 / 1 Subelement mesh size in the beta/gamma direction. (Integer > 0) dislin : float; default=0.0 The displacement of a surface perpendicular to the surface comment : str; default='' a comment for the card """ BaseCard.__init__(self) if comment: self.comment = comment #: Material identification number self.iview = iview self.icavity = icavity self.shade = shade self.nbeta = nbeta self.ngamma = ngamma self.dislin = dislin
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a VIEW card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ iview = integer(card, 1, 'iview') icavity = integer(card, 2, 'icavity') shade = string_or_blank(card, 3, 'shade', default='BOTH') nbeta = integer_or_blank(card, 4, 'nbeta', default=1) ngamma = integer_or_blank(card, 5, 'ngamma', default=1) dislin = double_or_blank(card, 6, 'dislin', default=0.0) return VIEW(iview, icavity, shade=shade, nbeta=nbeta, ngamma=ngamma, dislin=dislin, comment=comment)
#def cross_reference(self, model: BDF) -> None: #pass
[docs] def raw_fields(self): list_fields = ['VIEW', self.iview, self.icavity, self.shade, self.nbeta, self.ngamma, self.dislin] return list_fields
[docs] def repr_fields(self): list_fields = ['VIEW', self.iview, self.icavity, self.shade, self.nbeta, self.ngamma, self.dislin] 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 VIEW3D(BaseCard): """ View Factor Definition - Gaussian Integration Method Defines parameters to control and/or request the Gaussian Integration method of view factor calculation for a specified cavity. +--------+---------+------+------+------+------+--------+------+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=========+======+======+======+======+========+======+========+ | VIEW3D | ICAVITY | GITB | GIPS | CIER | ETOL | ZTOL | WTOL | RADCHK | +--------+---------+------+------+------+------+--------+------+--------+ | VIEW3D | 1 | 2 | 2 | 4 | | 1.0E-6 | | | +--------+---------+------+------+------+------+--------+------+--------+ """ type = 'VIEW3D' @classmethod def _init_from_empty(cls): icavity = 2 return VIEW3D(icavity, gitb=4, gips=4, cier=4, error_tol=0.1, zero_tol=1e-10, warp_tol=0.01, rad_check=3, comment='') def __init__(self, icavity, gitb=4, gips=4, cier=4, error_tol=0.1, zero_tol=1e-10, warp_tol=0.01, rad_check=3, comment=''): """ Creates a VIEW3D, which defines a 3D view factor Parameters ---------- icavity : int Radiant cavity identification number on RADCAV entry. (Integer > 0) gitb : int; default=4 Gaussian integration order to be implemented in calculating net effective view factors in the presence of third-body shadowing. (Integer 2, 3, 4, 5, 6 or 10) gips : int; default=4 Gaussian integration order to be implemented in calculating net effective view factors in the presence of self-shadowing. (Integer 2, 3, 4, 5, 6 or 10) cier : int; default=4 Discretization level used in the semi-analytic contour integration method. (1 < Integer < 20) error_tol : float; default=0.1 Error estimate above which a corrected view factor is calculated using the semi-analytic contour integration method. (Real > 0.0) zero_tol : float; default=1e-10 Assumed level of calculation below which the numbers are considered to be zero. (Real > 0.0) warp_tol : float; default=0.01 Assumed degree of warpage above which the actual value of will be calculated. (0.0 < Real < 1.0) rad_check : int; default=3 Type of diagnostic output desired for the radiation exchange surfaces. comment : str; default='' a comment for the card """ BaseCard.__init__(self) if comment: self.comment = comment #: Material identification number self.icavity = icavity self.gitb = gitb self.gips = gips self.cier = cier self.error_tol = error_tol self.zero_tol = zero_tol self.warp_tol = warp_tol self.rad_check = rad_check
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a VIEW3D card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ icavity = integer(card, 1, 'icavity') gitb = integer_or_blank(card, 2, 'gitb', default=4) gips = integer_or_blank(card, 3, 'gips', default=4) cier = integer_or_blank(card, 4, 'cier', default=4) error_tol = double_or_blank(card, 5, 'error_tol', default=0.1) zero_tol = double_or_blank(card, 6, 'zero_tol', default=1e-10) warp_tol = double_or_blank(card, 7, 'warp_tol', default=0.01) rad_check = integer_or_blank(card, 8, 'rad_check', default=3) return VIEW3D(icavity, gitb=gitb, gips=gips, cier=cier, error_tol=error_tol, zero_tol=zero_tol, warp_tol=warp_tol, rad_check=rad_check, comment=comment)
#def cross_reference(self, model: BDF) -> None: #pass
[docs] def raw_fields(self): list_fields = ['VIEW3D', self.icavity, self.gitb, self.gips, self.cier, self.error_tol, self.zero_tol, self.warp_tol, self.rad_check] return list_fields
[docs] def repr_fields(self): list_fields = ['VIEW3D', self.icavity, self.gitb, self.gips, self.cier, self.error_tol, self.zero_tol, self.warp_tol, self.rad_check] 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 RADCAV(ThermalBC): """ Identifies the characteristics of each radiant enclosure. +--------+---------+--------+------+---------+--------+-------+------+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=========+========+========+=======+========+=======+======+========+ | RADCAV | ICAVITY | ELEAMB | SHADOW | SCALE | PRTPCH | NFECI | RMAX | | +--------+---------+--------+------+---------+--------+-------+------+--------+ | | SET11 | SET12 | SET21 | SET22 | SET31 | SET32 | etc. | | +--------+---------+--------+------+---------+--------+-------+------+--------+ | RADCAV | 1 | 1 | | | | | .99 | | +--------+---------+--------+------+---------+--------+-------+------+--------+ | | 3 | 5 | 4 | 5 | 7 | 5 | | | +--------+---------+--------+------+---------+--------+-------+------+--------+ """ type = 'RADCAV' @classmethod def _init_from_empty(cls): icavity = 2 sets = [1, 2, 3] return RADCAV(icavity, sets, ele_amb=None, shadow='YES', scale=0.0, prtpch=None, nefci=None, rmax=0.1, ncomp=32, comment='') def __init__(self, icavity, sets, ele_amb=None, shadow='YES', scale=0.0, prtpch=None, nefci=None, rmax=0.1, ncomp=32, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment self.icavity = icavity self.ele_amb = ele_amb self.shadow = shadow self.scale = scale self.prtpch = prtpch self.nefci = nefci self.rmax = rmax self.ncomp = ncomp if isinstance(sets, integer_types): sets = [sets] self.sets = sets
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a RADCAV card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ icavity = integer(card, 1, 'icavity') ele_amb = integer_or_blank(card, 2, 'ele_amb') shadow = string_or_blank(card, 3, 'shadow', 'YES') scale = double_or_blank(card, 4, 'scale', 0.0) prtpch = integer_or_blank(card, 5, 'prtpch') nefci = string_or_blank(card, 6, 'nefci') rmax = double_or_blank(card, 7, 'rmax', 1.0) ncomp = integer_or_blank(card, 8, 'ncomp', 32) sets = fields(integer, card, 'set', i=9, j=card.nfields) return RADCAV(icavity, sets, ele_amb=ele_amb, shadow=shadow, scale=scale, prtpch=prtpch, nefci=nefci, rmax=rmax, ncomp=ncomp, comment=comment)
#@classmethod #def add_op2_data(cls, data, comment=''): #""" #Adds a RADM card from the OP2 #Parameters #---------- #data : list[varies] #a list of fields defined in OP2 format #comment : str; default='' #a comment for the card #""" #radmid, absorb = data[:2] #emissivity = data[2:] #def cross_reference(self, model: BDF) -> None: #pass
[docs] def raw_fields(self): list_fields = ['RADCAV', self.icavity, self.ele_amb, self.shadow, self.scale, self.prtpch, self.nefci, self.rmax, self.ncomp] + self.sets return list_fields
[docs] def repr_fields(self): list_fields = ['RADCAV', self.icavity, self.ele_amb, self.shadow, self.scale, self.prtpch, self.nefci, self.rmax, self.ncomp] + self.sets 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 RADLST(ThermalBC): """ Identifies the characteristics of each radiant enclosure. +--------+---------+--------+------+-------+--------+-------+------+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=========+========+======+=======+========+=======+======+========+ | RADLST | ICAVITY | MTXTYP | EID1 | EID2 | EID3 | EID4 | EID5 | EID6 | +--------+---------+--------+------+-------+--------+-------+------+--------+ | | EID7 | etc. | | | | | | | +--------+---------+--------+------+-------+--------+-------+------+--------+ | RADLST | 3 | 5 | 4 | 5 | 7 | 5 | | | +--------+---------+--------+------+-------+--------+-------+------+--------+ """ type = 'RADCAV' @classmethod def _init_from_empty(cls): icavity = 2 eids = [1, 2, 3] return RADLST(icavity, eids, matrix_type=1, comment='') def __init__(self, icavity, eids, matrix_type=1, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment self.icavity = icavity self.matrix_type = matrix_type assert isinstance(matrix_type, integer_types), matrix_type if isinstance(eids, integer_types): eids = [eids] self.eids = eids
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a RADLST card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ icavity = integer(card, 1, 'icavity') matrix_type = integer_or_blank(card, 2, 'matrix_type', 1) eids = fields(integer, card, 'eid', i=3, j=card.nfields) return RADLST(icavity, eids, matrix_type=matrix_type, comment=comment)
[docs] def raw_fields(self): list_fields = ['RADLST', self.icavity, self.matrix_type] + self.eids return list_fields
#def repr_fields(self): #list_fields = ['RADCAV', self.icavity, self.ele_amb, self.shadow, self.scale, #self.prtpch, self.nefci, self.rmax, self.ncomp] + self.sets #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 RADMTX(ThermalBC): """ Provides the Fji=Aj*fji exchange factors for all the faces of a radiation enclosure specified in the corresponding RADLST entry. +--------+---------+--------+--------+--------+--------+--------+--------+--------+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +========+=========+========+========+========+========+========+========+========+ | RADMTX | ICAVITY | INDEX | Fi,j | Fi+1,j | Fi+2,j | Fi+3,j | Fi+4,j | Fi+5,j | +--------+---------+--------+--------+--------+--------+--------+--------+--------+ | | Fi+6,j | etc. | | | | | | | +--------+---------+--------+--------+--------+--------+--------+--------+--------+ | RADMTX | 2 | 1 | 0.0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.2 | +--------+---------+--------+--------+--------+--------+--------+--------+--------+ """ type = 'RADMTX' @classmethod def _init_from_empty(cls): icavity = 1 index = 2 exchange_factors = [1., 2.] return RADMTX(icavity, index, exchange_factors, comment='') def __init__(self, icavity, index, exchange_factors, comment=''): ThermalBC.__init__(self) if comment: self.comment = comment self.icavity = icavity assert isinstance(index, integer_types), type(index) self.index = index if isinstance(exchange_factors, float_types): exchange_factors = [exchange_factors] self.exchange_factors = exchange_factors
[docs] @classmethod def add_card(cls, card, comment=''): """ Adds a RADMTX card from ``BDF.add_card(...)`` Parameters ---------- card : BDFCard() a BDFCard object comment : str; default='' a comment for the card """ icavity = integer(card, 1, 'icavity') index = integer(card, 2, 'index') exchange_factors = fields(double, card, 'eid', i=3, j=card.nfields) return RADMTX(icavity, index, exchange_factors, comment=comment)
[docs] def raw_fields(self): assert isinstance(self.index, integer_types), type(self.index) list_fields = ['RADMTX', self.icavity, self.index] + self.exchange_factors return list_fields
#def repr_fields(self): #list_fields = ['RADCAV', self.icavity, self.ele_amb, self.shadow, self.scale, #self.prtpch, self.nefci, self.rmax, self.ncomp] + self.sets #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)