pyNastran
0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
|
00001 ## GNU Lesser General Public License 00002 ## 00003 ## Program pyNastran - a python interface to NASTRAN files 00004 ## Copyright (C) 2011-2012 Steven Doyle, Al Danial 00005 ## 00006 ## Authors and copyright holders of pyNastran 00007 ## Steven Doyle <mesheb82@gmail.com> 00008 ## Al Danial <al.danial@gmail.com> 00009 ## 00010 ## This file is part of pyNastran. 00011 ## 00012 ## pyNastran is free software: you can redistribute it and/or modify 00013 ## it under the terms of the GNU Lesser General Public License as published by 00014 ## the Free Software Foundation, either version 3 of the License, or 00015 ## (at your option) any later version. 00016 ## 00017 ## pyNastran is distributed in the hope that it will be useful, 00018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 ## GNU General Public License for more details. 00021 ## 00022 ## You should have received a copy of the GNU Lesser General Public License 00023 ## along with pyNastran. If not, see <http://www.gnu.org/licenses/>. 00024 ## 00025 # pylint: disable=C0103,R0902,R0904,R0914 00026 00027 from __future__ import division, print_function 00028 00029 from pyNastran.bdf.fieldWriter import set_blank_if_default 00030 from pyNastran.bdf.cards.baseCard import BaseCard, expandThruBy, collapseThruBy 00031 00032 class ThermalCard(BaseCard): 00033 def __init__(self, card, data): 00034 pass 00035 def crossReference(self,model): 00036 raise NotImplementedError('%s has not defined the crossReference' 00037 'method' %(self.type)) 00038 00039 def isSameCard(self, obj, debug=False): 00040 return False 00041 00042 class ThermalBC(ThermalCard): 00043 def __init__(self, card, data): 00044 pass 00045 00046 class ThermalElement(ThermalCard): 00047 pid = 0 00048 def __init__(self, card, data): 00049 pass 00050 00051 def nodeIDs(self): 00052 return [] 00053 00054 def Pid(self): 00055 if isinstance(self.pid, int): 00056 return self.pid 00057 else: 00058 return self.pid.pid 00059 ### 00060 00061 class ThermalProperty(ThermalCard): 00062 def __init__(self, card, data): 00063 pass 00064 00065 #------------------------------------------------------- 00066 # Elements 00067 00068 class CHBDYE(ThermalElement): 00069 """ 00070 Defines a boundary condition surface element with reference to a heat 00071 conduction element. 00072 """ 00073 type = 'CHBDYE' 00074 00075 hexMap = {1: [4, 3, 2, 1], # CHEXA8/CHEXA20 00076 2: [1, 2, 6, 5], 00077 3: [2, 3, 7, 6], 00078 4: [3, 4, 8, 7], 00079 5: [4, 1, 5, 8], 00080 6: [5, 6, 7, 8], 00081 } 00082 00083 pentMap = {1: [3, 2, 1], # CPENTA 00084 2: [1, 2, 5, 4], 00085 3: [2, 3, 6, 5], 00086 4: [3, 1, 4, 6], 00087 5: [4, 5, 6], 00088 } 00089 00090 tetMap = {1: [1, 3, 2], # CTETRA 00091 2: [1, 2, 4], 00092 3: [2, 3, 4], 00093 4: [3, 1, 4], 00094 } 00095 00096 sideMaps = {'CHEXA': hexMap, 'CPENTA':pentMap, 'CTETRA':tetMap, 00097 'CTRIA3':[1,2,3], 'CQUAD4':[1,2,3,4]} 00098 00099 def __init__(self, card=None, data=None): 00100 ThermalElement.__init__(self, card, data) 00101 ## Surface element ID number for a side of an 00102 ## element. (0 < Integer < 100,000,000) 00103 self.eid = card.field(1) 00104 00105 ## A heat conduction element identification 00106 self.eid2 = card.field(2) 00107 00108 ## A consistent element side identification number (1 < Integer < 6) 00109 self.side = card.field(3) 00110 assert 0 < self.side < 7 00111 00112 ## A VIEW entry identification number for the front face 00113 self.iViewFront = card.field(4, 0) 00114 ## A VIEW entry identification number for the back face 00115 self.iViewBack = card.field(5, 0) 00116 00117 ## RADM identification number for front face of surface element (Integer > 0) 00118 self.radMidFront = card.field(6, 0) 00119 ## RADM identification number for back face of surface element (Integer > 0) 00120 self.radMidBack = card.field(7, 0) 00121 00122 self.grids = [] 00123 00124 #def crossReference(self,model): 00125 # pass 00126 00127 def sideToEIDs(self, eid): 00128 sideIDs = self.sideMaps[eid.type][self.side] 00129 ## [1,2,3] 00130 00131 # id-1 is for the 0 based python index 00132 nodes = [enodes[id-1] for id in xrange(len(eid.nodes)) if id in sideIDs ] 00133 return side 00134 00135 def rawFields(self): 00136 fields = ['CHBDYE', self.eid, self.eid2, self.side, self.iViewFront, 00137 self.iViewBack,self.radMidFront,self.radMidBack] 00138 return fields 00139 00140 def reprFields(self): 00141 #eids = collapseThruBy(self.eids) ## @todo is this done 00142 fields = ['CHBDYE', self.eid, self.eid2, self.side, self.iViewFront, 00143 self.iViewBack,self.radMidFront,self.radMidBack] 00144 return fields 00145 00146 class CHBDYG(ThermalElement): 00147 """ 00148 Defines a boundary condition surface element without reference to a 00149 property entry. 00150 """ 00151 type = 'CHBDYG' 00152 def __init__(self, card=None, data=None): 00153 ThermalElement.__init__(self, card, data) 00154 00155 if card: 00156 ## Surface element ID 00157 self.eid = card.field(1) 00158 # no field 2 00159 00160 ## Surface type 00161 self.Type = card.field(3) 00162 assert self.Type in ['REV','AREA3','AREA4','AREA6','AREA8'] 00163 00164 ## A VIEW entry identification number for the front face 00165 self.iViewFront = card.field(4,0) 00166 00167 ## A VIEW entry identification number for the back face 00168 self.iViewBack = card.field(8,0) 00169 00170 ## RADM identification number for front face of surface element 00171 ## (Integer > 0) 00172 self.radMidFront = card.field(6,0) 00173 00174 ## RADM identification number for back face of surface element 00175 ## (Integer > 0) 00176 self.radMidBack = card.field(7,0) 00177 # no field 8 00178 00179 ## Grid point IDs of grids bounding the surface (Integer > 0) 00180 self.grids = card.fields(9) 00181 else: 00182 self.eid = data[0] 00183 self.Type = data[1] 00184 self.iViewFront = data[2] 00185 self.iViewBack = data[3] 00186 self.radMidFront = data[4] 00187 self.radMidBack = data[5] 00188 self.grids = data[6:14] 00189 ### 00190 00191 def crossReference(self,mesh): 00192 pass 00193 #self.pid = mesh.Phbdy(self.pid) 00194 00195 def rawFields(self): 00196 fields = ['CHBDYG',self.eid,None,self.Type,self.iViewFront,self.iViewBack,self.radMidFront,self.radMidBack,None, 00197 ]+self.grids 00198 return fields 00199 00200 def reprFields(self): 00201 iViewFront = set_blank_if_default(self.iViewFront, 0) 00202 iViewBack = set_blank_if_default(self.iViewBack, 0) 00203 radMidFront = set_blank_if_default(self.radMidFront, 0) 00204 radMidBack = set_blank_if_default(self.radMidBack, 0) 00205 00206 fields = ['CHBDYG',self.eid,None,self.Type,iViewFront,iViewBack,radMidFront,radMidBack,None, 00207 ]+self.grids 00208 #print "chbdyg fields = %s" %(fields) 00209 return fields 00210 00211 class CHBDYP(ThermalElement): 00212 """ 00213 Defines a boundary condition surface element with reference to a PHBDY entry 00214 """ 00215 type = 'CHBDYP' 00216 def __init__(self, card=None, data=None): 00217 ThermalElement.__init__(self, card, data) 00218 if card: 00219 ## Surface element ID 00220 self.eid = card.field(1) 00221 00222 ## PHBDY property entry identification numbers. (Integer > 0) 00223 self.pid = card.field(2) 00224 00225 self.Type = card.field(3) 00226 #print "self.Type = ",self.Type 00227 #assert self.Type in ['POINT','LINE','ELCYL','FTUBE','TUBE'],'CHBDYP Type=|%s|' (self.Type) 00228 00229 ## A VIEW entry identification number for the front face. 00230 self.iViewFront = card.field(4,0) 00231 00232 ## A VIEW entry identification number for the back face. 00233 self.iViewBack = card.field(5,0) 00234 00235 ## Grid point identification numbers of grids bounding the surface. (Integer > 0) 00236 self.g1 = card.field(6) 00237 ## Grid point identification numbers of grids bounding the surface. (Integer > 0) 00238 self.g2 = card.field(7) 00239 00240 ## Orientation grid point. (Integer > 0; Default = 0) 00241 self.g0 = card.field(8,0) 00242 00243 ## RADM identification number for front face of surface element. (Integer > 0) 00244 self.radMidFront = card.field(9,0) 00245 00246 ## RADM identification number for back face of surface element. (Integer > 0) 00247 self.radMidBack = card.field(10,0) 00248 00249 ## Grid point identification number of a midside node if it is used with the line type surface element. 00250 self.gmid = card.field(11) 00251 ## Coordinate system for defining orientation vector. (Integer > 0;Default = 0 00252 self.ce = card.field(12,0) 00253 00254 ## Components of the orientation vector in coordinate system CE. The origin of the orientation vector is grid point G1. (Real or blank) 00255 self.e1 = card.field(13) 00256 self.e2 = card.field(14) 00257 self.e3 = card.field(15) 00258 else: 00259 raise NotImplementedError() 00260 00261 def crossReference(self,mesh): 00262 self.pid = mesh.Phbdy(self.pid) 00263 00264 def rawFields(self): 00265 fields = ['CHBDYP',self.eid,self.Pid(),self.Type,self.iViewFront,self.iViewBack,self.g1,self.g2,self.g0, 00266 self.radMidFront,self.radMidBack,self.gmid,self.ce,self.e1,self.e2,self.e3] 00267 return fields 00268 00269 def reprFields(self): 00270 iViewFront = set_blank_if_default(self.iViewFront, 0) 00271 iViewBack = set_blank_if_default(self.iViewBack, 0) 00272 radMidFront = set_blank_if_default(self.radMidFront, 0) 00273 radMidBack = set_blank_if_default(self.radMidBack, 0) 00274 00275 g0 = set_blank_if_default(self.g0, 0) 00276 ce = set_blank_if_default(self.ce, 0) 00277 00278 fields = ['CHBDYP',self.eid,self.Pid(),self.Type,iViewFront,iViewBack,self.g1,self.g2,g0, 00279 radMidFront,radMidBack,self.gmid,ce,self.e1,self.e2,self.e3] 00280 return fields 00281 00282 # Elements 00283 #------------------------------------------------------- 00284 # Properties 00285 00286 00287 class PCONV(ThermalProperty): 00288 """ 00289 Specifies the free convection boundary condition properties of a boundary condition 00290 surface element used for heat transfer analysis. 00291 """ 00292 type = 'PCONV' 00293 def __init__(self, card=None, data=None): 00294 ## Convection property identification number. (Integer > 0) 00295 self.pconid = card.field(1) 00296 ## Material property identification number. (Integer > 0) 00297 self.mid = card.field(2) 00298 ## Type of formula used for free convection. (Integer 0, 1, 10, 11, 20, or 21) 00299 self.form = card.field(3,0) 00300 assert self.form in [0,1,10,11,20,21] 00301 00302 ## Free convection exponent as implemented within the context of the 00303 ## particular form that is chosen 00304 self.expf = card.field(4,0.0) 00305 ## Formula type for various configurations of free convection 00306 self.ftype = card.field(5,0) 00307 ## Identification number of a TABLEHT entry that specifies the twovariable 00308 ## tabular function of the free convection heat transfer coefficient 00309 self.tid = card.field(6) 00310 #7 00311 #8 00312 ## Characteristic length 00313 self.chlen = card.field(9) 00314 ## Grid ID of the referenced inlet point 00315 self.gidin = card.field(10) 00316 ## Coordinate system for defining orientation vector. (Integer > 0;Default = 0 00317 self.ce = card.field(11,0) 00318 ## Components of the orientation vector in coordinate system CE. The origin of the orientation vector is grid point G1. (Real or blank) 00319 self.e1 = card.field(12) 00320 self.e2 = card.field(13) 00321 self.e3 = card.field(14) 00322 00323 #def crossReference(self,model): 00324 # pass 00325 00326 def rawFields(self): 00327 fields = ['PCONV',self.pconid,self.mid,self.form,self.expf,self.ftype,self.tid,None,None, 00328 self.chlen,self.gidin,self.ce,self.e1,self.e2,self.e3] 00329 return fields 00330 00331 def reprFields(self): 00332 form = set_blank_if_default(self.form, 0) 00333 expf = set_blank_if_default(self.expf,0.0) 00334 ftype = set_blank_if_default(self.ftype, 0) 00335 ce = set_blank_if_default(self.ce, 0) 00336 fields = ['PCONV',self.pconid,self.mid,form,expf,ftype,self.tid,None,None, 00337 self.chlen,self.gidin,ce,self.e1,self.e2,self.e3] 00338 return fields 00339 00340 class PCONVM(ThermalProperty): 00341 """ 00342 Specifies the free convection boundary condition properties of a boundary condition 00343 surface element used for heat transfer analysis. 00344 """ 00345 type = 'PCONVM' 00346 def __init__(self, card=None, data=None): 00347 ## Convection property identification number. (Integer > 0) 00348 self.pconid = card.field(1) 00349 ## Material property identification number. (Integer > 0) 00350 self.mid = card.field(2) 00351 ## Type of formula used for free convection. (Integer 0, 1, 10, 11, 20, or 21) 00352 self.form = card.field(3,0) 00353 assert self.form in [0,1,10,11,20,21] 00354 00355 ## Flag for mass flow convection. (Integer = 0 or 1; Default = 0) 00356 self.flag = card.field(4,0) 00357 ## Constant coefficient used for forced convection 00358 self.coef = card.field(5) 00359 ## Reynolds number convection exponent. (Real > 0.0; Default = 0.0) 00360 self.expr = card.field(6,0.0) 00361 ## Prandtl number convection exponent for heat transfer into the working 00362 ## fluid. (Real > 0.0; Default = 0.0) 00363 self.exppi = card.field(7,0.0) 00364 ## Prandtl number convection exponent for heat transfer into the working 00365 ## fluid. (Real > 0.0; Default = 0.0) 00366 self.exppo = card.field(8,0.0) 00367 00368 #def crossReference(self,model): 00369 # pass 00370 00371 def rawFields(self): 00372 fields = ['PCONVM',self.pconid,self.mid,self.form,self.flag,self.coef,self.expr,self.exppi,self.exppo] 00373 return fields 00374 00375 def reprFields(self): 00376 form = set_blank_if_default(self.form, 0) 00377 flag = set_blank_if_default(self.flag, 0) 00378 expr = set_blank_if_default(self.expr, 0.0) 00379 exppi = set_blank_if_default(self.exppi,0.0) 00380 exppo = set_blank_if_default(self.exppo,0.0) 00381 fields = ['PCONVM',self.pconid,self.mid,form,flag,self.coef,expr,exppi,exppo] 00382 return fields 00383 00384 class PHBDY(ThermalProperty): 00385 """ 00386 A property entry referenced by CHBDYP entries to give auxiliary geometric 00387 information for boundary condition surface elements 00388 """ 00389 type = 'PHBDY' 00390 def __init__(self, card=None, data=None): 00391 ## Property identification number. (Unique Integer among all PHBDY entries). (Integer > 0) 00392 self.pid = card.field(1) 00393 00394 ## Area factor of the surface used only for CHBDYP element 00395 ## TYPE = 'POINT', TYPE = 'LINE', TYPE = 'TUBE', or 00396 ## TYPE = 'ELCYL'. For TYPE = 'TUBE', AF is the constant thickness of 00397 ## the hollow tube. (Real > 0.0 or blank) 00398 self.af = card.field(2) 00399 00400 ## Diameters associated with the surface. Used with CHBDYP element TYPE='ELCYL','TUBE','FTUBE' 00401 self.d1 = card.field(3) 00402 self.d2 = card.field(4,self.d1) 00403 00404 00405 #def crossReference(self,model): 00406 # pass 00407 00408 def rawFields(self): 00409 fields = ['PHBDY',self.pid,self.af,self.d1,self.d2] 00410 return fields 00411 00412 def reprFields(self): 00413 d2 = set_blank_if_default(self.d2,self.d1) 00414 fields = ['PHBDY',self.pid,self.af,self.d1,d2] 00415 return fields 00416 00417 00418 # Properties 00419 #------------------------------------------------------- 00420 # Boundary Conditions 00421 00422 class CONV(ThermalBC): 00423 """ 00424 Specifies a free convection boundary condition for heat transfer analysis through 00425 connection to a surface element (CHBDYi entry). 00426 """ 00427 type = 'CONV' 00428 def __init__(self, card=None, data=None): 00429 #ThermalBC.__init__(self, card, data) 00430 ## CHBDYG, CHBDYE, or CHBDYP surface element identification number. (Integer > 0) 00431 self.eid = card.field(1) 00432 00433 ## Convection property identification number of a PCONV entry 00434 self.pconID = card.field(2) 00435 ## Point for film convection fluid property temperature 00436 self.flmnd = card.field(3,0) 00437 ## Control point for free convection boundary condition. 00438 self.cntrlnd = card.field(4,0) 00439 00440 TA1 = card.field(5) 00441 nFields = card.nFields()-1 # maybe off by 1... 00442 00443 ## Ambient points used for convection 0's are allowed for TA2 and higher. 00444 self.ta = card.fields(5,card.nfields,[TA1]*nFields) 00445 00446 def crossReference(self,model): 00447 self.eid = model.Element(self.eid) 00448 assert self.eid.type in ['CHBDYG','CHBDYE','CHBDYP'] 00449 00450 def TA(self,i=None): 00451 if i is None: 00452 return self.ta 00453 return self.ta[i] 00454 00455 def rawFields(self): 00456 fields = ['CONV',self.eid,self.pconID,self.flmnd,self.cntrlnd]+self.ta 00457 return fields 00458 00459 def reprFields(self): 00460 flmnd = set_blank_if_default(self.flmnd, 0) 00461 cntrlnd = set_blank_if_default(self.cntrlnd,0) 00462 fields = ['CONV',self.eid,self.pconID,flmnd,cntrlnd]+self.ta 00463 return fields 00464 00465 class RADM(ThermalBC): 00466 """ 00467 Defines the radiation properties of a boundary element for heat transfer analysis 00468 """ 00469 type = 'RADM' 00470 def __init__(self, card=None, data=None): 00471 ThermalBC.__init__(self, card, data) 00472 ## Material identification number 00473 self.radmid = card.field(1) 00474 self.absorb = card.field(2) 00475 self.emissivity = card.fields(3) 00476 assert self.radmid > 0 00477 assert 0. <= self.absorb <= 1.0 00478 for e in self.emissivity: 00479 assert 0. <= e <= 1.0 00480 00481 #def crossReference(self,model): 00482 # pass 00483 00484 def reprFields(self): 00485 fields = ['RADM',self.radmid,self.absorb] + self.emissivity 00486 return fields 00487 00488 class RADBC(ThermalBC): 00489 """ 00490 Specifies an CHBDYi element face for application of radiation boundary conditions 00491 """ 00492 type = 'RADBC' 00493 def __init__(self, card=None, data=None): 00494 ThermalBC.__init__(self, card, data) 00495 00496 ## NODAMB Ambient point for radiation exchange. (Integer > 0) 00497 self.nodamb = card.field(1) 00498 ## Radiation view factor between the face and the ambient point. (Real > 0.0) 00499 self.famb = card.field(2) 00500 ## Control point for thermal flux load. (Integer > 0; Default = 0) 00501 self.cntrlnd = card.field(3,0) 00502 00503 eids = card.fields(4) 00504 ## CHBDYi element identification number 00505 self.eids = expandThruBy(eids) 00506 00507 def crossReference(self,model): 00508 for i,eid in enumerate(self.eids): 00509 self.eids[i] = model.Element(eid) 00510 ### 00511 00512 def Eids(self): 00513 eids = [] 00514 for eid in self.eids: 00515 eids.append(self.Eid(eid)) 00516 ### 00517 return eids 00518 00519 def Eid(self,eid): 00520 if isinstance(eid,int): 00521 return eid 00522 return eid.eid 00523 00524 def rawFields(self): 00525 fields = ['RADBC',self.nodamb,self.famb,self.cntrlnd]+self.Eids() 00526 return fields 00527 00528 def reprFields(self): 00529 cntrlnd = set_blank_if_default(self.cntrlnd,0) 00530 eids = collapseThruBy(self.Eids()) 00531 fields = ['RADBC',self.nodamb,self.famb,cntrlnd]+eids 00532 return fields 00533 00534 # Boundary Conditions 00535 #------------------------------------------------------- 00536