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 from numpy import zeros,array 00029 00030 from pyNastran.bdf.fieldWriter import set_blank_if_default 00031 from pyNastran.bdf.cards.baseCard import Element, BaseCard 00032 00033 00034 class PointElement(Element): 00035 def __init__(self, card=None, data=None): 00036 Element.__init__(self, card, data) 00037 00038 class PointMassElement(PointElement): 00039 def __init__(self, card=None, data=None): 00040 self.mass = None 00041 PointElement.__init__(self, card, data) 00042 00043 def Mass(self): 00044 return self.mass 00045 00046 class PointMass(BaseCard): 00047 def __init__(self, card=None, data=None): 00048 self.mass = None 00049 00050 def Mass(self): 00051 return self.mass 00052 00053 00054 class CMASS1(PointMass): 00055 """ 00056 Defines a scalar mass element. 00057 CMASS2 EID M G1 C1 G2 C2 00058 CMASS1 EID PID G1 C1 G2 C2 00059 """ 00060 type = 'CMASS1' 00061 def __init__(self, card=None, data=None): 00062 PointMass.__init__(self, card, data) 00063 if card: 00064 self.eid = card.field(1) 00065 self.pid = card.field(2, self.eid) 00066 self.g1 = card.field(3) 00067 self.c1 = card.field(4) 00068 self.g2 = card.field(5) 00069 self.c2 = card.field(6) 00070 else: 00071 self.eid = data[0] 00072 self.pid = data[1] 00073 self.g1 = data[2] 00074 self.g2 = data[3] 00075 self.c1 = data[4] 00076 self.c2 = data[5] 00077 ### 00078 00079 def Mass(self): 00080 return self.pid.mass 00081 00082 def crossReference(self, model): 00083 #self.g1 = model.Node(self.g1) 00084 #self.g2 = model.Node(self.g2) 00085 self.pid = model.Property(self.pid) 00086 00087 def Pid(self): 00088 if isinstance(self.pid, int): 00089 return self.pid 00090 return self.pid.pid 00091 00092 def rawFields(self): 00093 fields = ['CMASS1',self.eid,self.Pid(),self.g1,self.c1,self.g2,self.c2] 00094 return fields 00095 00096 class CMASS2(PointMassElement): 00097 """ 00098 Defines a scalar mass element without reference to a property entry. 00099 CMASS2 EID M G1 C1 G2 C2 00100 """ 00101 type = 'CMASS2' 00102 def __init__(self, card=None, data=None): 00103 PointMassElement.__init__(self, card, data) 00104 if card: 00105 self.eid = card.field(1) 00106 self.mass = card.field(2, 0.) 00107 self.g1 = card.field(3) 00108 self.c1 = card.field(4) 00109 self.g2 = card.field(5) 00110 self.c2 = card.field(6) 00111 else: 00112 self.eid = data[0] 00113 self.mass = data[1] 00114 self.g1 = data[2] 00115 self.g2 = data[3] 00116 self.c1 = data[4] 00117 self.c2 = data[5] 00118 ### 00119 00120 def nodeIDs(self): 00121 g1 = self.G1() 00122 g2 = self.G2() 00123 nodes = [] 00124 if g1: 00125 nodes.append(g1) 00126 if g2: 00127 nodes.append(g2) 00128 return nodes 00129 00130 def Mass(self): 00131 return self.mass 00132 00133 def Centroid(self): 00134 """ 00135 Centroid is assumed to be c=(g1+g2)/2. 00136 If g2 is blank, then the centroid is the location of g1. 00137 """ 00138 f=0. 00139 p1=array([0.,0.,0.]) 00140 p2=array([0.,0.,0.]) 00141 if self.g1 is not None: 00142 p1 = self.g1.Position() 00143 f+=1. 00144 if self.g2 is not None: 00145 p2 = self.g2.Position() 00146 f+=1. 00147 00148 c = (p1+p2)/f 00149 return c 00150 00151 def crossReference(self,mesh): 00152 if isinstance(self.g1,int): 00153 self.g1 = mesh.Node(self.g1) 00154 if isinstance(self.g2,int): 00155 self.g2 = mesh.Node(self.g2) 00156 ### 00157 00158 def G1(self): 00159 if isinstance(self.g1,int): 00160 return self.g1 00161 elif self.g1 is None: 00162 return self.g1 00163 return self.g1.nid 00164 00165 def G2(self): 00166 if isinstance(self.g2,int): 00167 return self.g2 00168 elif self.g2 is None: 00169 return self.g2 00170 return self.g2.nid 00171 00172 def rawFields(self): 00173 fields = ['CMASS2',self.eid,self.mass,self.G1(),self.c1,self.G2(),self.c2] 00174 return fields 00175 00176 def reprFields(self): 00177 mass = set_blank_if_default(self.mass, 0.) 00178 fields = ['CMASS2', self.eid, mass,self.G1(),self.c1,self.G2(),self.c2] 00179 #print "cmass2 fields = ",fields 00180 return fields 00181 00182 class CMASS3(PointMassElement): 00183 """ 00184 Defines a scalar mass element that is connected only to scalar points. 00185 CMASS3 EID PID S1 S2 00186 """ 00187 type = 'CMASS3' 00188 def __init__(self, card=None, data=None): 00189 PointMass.__init__(self, card, data) 00190 00191 if card: 00192 self.eid = card.field(1) 00193 self.pid = card.field(2,self.eid) 00194 self.s1 = card.field(3) 00195 self.s2 = card.field(4) 00196 else: 00197 self.eid = data[0] 00198 self.pid = data[1] 00199 self.s1 = data[2] 00200 self.s2 = data[3] 00201 ### 00202 00203 def Mass(self): 00204 return self.pid.mass 00205 00206 def isSameCard(self, elem, debug=False): 00207 if self.type!=elem.type: return False 00208 fields1 = [self.eid,self.Pid(),self.s1,self.s2] 00209 fields2 = [elem.eid,elem.Pid(),elem.s1,elem.s2] 00210 if debug: 00211 print("fields1=%s fields2=%s" %(fields1, fields2)) 00212 return self.isSameFields(fields1,fields2) 00213 00214 def crossReference(self,mesh): 00215 """ 00216 links up the propertiy ID 00217 """ 00218 #self.s1 = mesh.Node(self.s1) 00219 #self.s2 = mesh.Node(self.s2) 00220 self.pid = mesh.Property(self.pid) 00221 00222 def rawFields(self): 00223 fields = ['CMASS3',self.eid,self.Pid(),self.s1,self.s2] 00224 return fields 00225 00226 class CMASS4(PointMassElement): 00227 """ 00228 Defines a scalar mass element that is connected only to scalar points, without reference to a property entry 00229 CMASS4 EID M S1 S2 00230 """ 00231 type = 'CMASS4' 00232 def __init__(self, card=None, data=None): 00233 PointMass.__init__(self, card, data) 00234 00235 if card: 00236 self.eid = card.field(1) 00237 self.mass = card.field(2,0.) 00238 self.s1 = card.field(3) 00239 self.s2 = card.field(4) 00240 else: 00241 self.eid = data[0] 00242 self.mass = data[1] 00243 self.s1 = data[2] 00244 self.s2 = data[3] 00245 ### 00246 00247 def Mass(self): 00248 return self.mass 00249 00250 def isSameCard(self, elem, debug=False): 00251 if self.type!=elem.type: return False 00252 fields1 = [self.eid,self.Pid(),self.s1,self.s2] 00253 fields2 = [elem.eid,elem.Pid(),elem.s1,elem.s2] 00254 if debug: 00255 print("fields1=%s fields2=%s" %(fields1, fields2)) 00256 return self.isSameFields(fields1,fields2) 00257 00258 def crossReference(self,mesh): 00259 """ 00260 """ 00261 #self.s1 = mesh.Node(self.s1) 00262 #self.s2 = mesh.Node(self.s2) 00263 pass 00264 00265 def rawFields(self): 00266 fields = ['CMASS4',self.eid,self.mass,self.s1,self.s2] 00267 return fields 00268 00269 00270 class CONM1(PointMass): 00271 type = 'CONM1' 00272 def __init__(self, card=None, data=None): 00273 """ 00274 Concentrated Mass Element Connection, General Form 00275 Defines a 6 x 6 symmetric mass matrix at a geometric grid point 00276 00277 CONM1 EID G CID M11 M21 M22 M31 M32 00278 M33 M41 M42 M43 M44 M51 M52 M53 00279 M54 M55 M61 M62 M63 M64 M65 M66 00280 00281 [M] = [M11 M21 M31 M41 M51 M61] 00282 [ M22 M32 M42 M52 M62] 00283 [ M33 M43 M53 M63] 00284 [ M44 M54 M64] 00285 [ Sym M55 M65] 00286 [ M66] 00287 """ 00288 PointMass.__init__(self, card, data) 00289 m = zeros((6,6)) 00290 if card: 00291 #self.nids = [ card[1] ] 00292 #del self.nids 00293 #self.pid = None 00294 self.eid = card.field(1) 00295 self.nid = card.field(2) 00296 self.cid = card.field(3,0) 00297 00298 m[0,0] = card.field(4, 0.) # M11 00299 m[1,0] = card.field(5, 0.) # M21 00300 m[1,1] = card.field(6, 0.) # M22 00301 m[2,0] = card.field(7, 0.) # M31 00302 m[2,1] = card.field(8, 0.) # M32 00303 m[2,2] = card.field(9, 0.) # M33 00304 m[3,0] = card.field(10, 0.) # M41 00305 m[3,1] = card.field(11, 0.) # M42 00306 m[3,2] = card.field(12, 0.) # M43 00307 m[3,3] = card.field(13, 0.) # M44 00308 m[4,0] = card.field(14, 0.) # M51 00309 m[4,1] = card.field(15, 0.) # M52 00310 m[4,2] = card.field(16, 0.) # M53 00311 m[4,3] = card.field(17, 0.) # M54 00312 m[4,4] = card.field(18, 0.) # M55 00313 m[5,0] = card.field(19, 0.) # M61 00314 m[5,1] = card.field(20, 0.) # M62 00315 m[5,2] = card.field(21, 0.) # M63 00316 m[5,3] = card.field(22, 0.) # M64 00317 m[5,4] = card.field(23, 0.) # M65 00318 m[5,5] = card.field(24, 0.) # M66 00319 ### 00320 else: 00321 (eid,nid,cid,m1, m2a,m2b, m3a,m3b,m3c, m4a,m4b,m4c,m4d, 00322 m5a,m5b,m5c,m5d,m5e, m6a,m6b,m6c,m6d,m6e,m6f) = data 00323 self.eid = eid 00324 self.nid = nid 00325 self.cid = cid 00326 m[0,0] = m1 # M11 00327 m[1,0] = m2a # M21 00328 m[1,1] = m2b # M22 00329 m[2,0] = m3a # M31 00330 m[2,1] = m3b # M32 00331 m[2,2] = m3c # M33 00332 m[3,0] = m4a # M41 00333 m[3,1] = m4b # M42 00334 m[3,2] = m4c # M43 00335 m[3,3] = m4d # M44 00336 m[4,0] = m5a # M51 00337 m[4,1] = m5b # M52 00338 m[4,2] = m5c # M53 00339 m[4,3] = m5d # M54 00340 m[4,4] = m5e # M55 00341 m[5,0] = m6a # M61 00342 m[5,1] = m6b # M62 00343 m[5,2] = m6c # M63 00344 m[5,3] = m6d # M64 00345 m[5,4] = m6e # M65 00346 m[5,5] = m6f # M66 00347 ### 00348 self.massMatrix = m 00349 00350 def nodeIDs(self): 00351 return [self.Nid()] 00352 00353 def Nid(self): 00354 if isinstance(self.nid, int): 00355 return self.nid 00356 return self.nid.nid 00357 00358 def Cid(self): 00359 if isinstance(self.cid, int): 00360 return self.cid 00361 return self.cid.cid 00362 00363 def crossReference(self, model): 00364 self.nid = model.Node(self.nid) 00365 self.cid = model.Coord(self.cid) 00366 00367 def MassMatrix(self): 00368 return self.massMatrix 00369 00370 def rawFields(self): 00371 cid = set_blank_if_default(self.Cid(), 0) 00372 nid = self.Nid() 00373 m = self.massMatrix 00374 fields = ['CONM1',self.eid,nid,cid,m[0,0],m[1,0],m[1,1],m[2,0],m[2,1], 00375 m[2,2],m[3,0],m[3,1],m[3,2],m[3,3],m[4,0],m[4,1],m[4,2], 00376 m[4,3],m[4,4],m[5,0],m[5,1],m[5,2],m[5,3],m[5,4],m[5,5] ] 00377 return fields 00378 00379 def reprFields(self): 00380 fields = self.rawFields() 00381 fields2 = fields[0:4] 00382 for field in fields[4:]: 00383 val = set_blank_if_default(field, 0.) 00384 #print "field=%s value=%s" %(field,val) 00385 fields2.append(val) 00386 #print "fields = ",fields 00387 #print "fields2 = ",fields2 00388 return fields2 00389 00390 class CONM2(PointMassElement): ## @todo not done 00391 """ 00392 @param self the CONM2 object 00393 @param eid element ID 00394 @param nid node ID 00395 @param cid coordinate frame of the offset (-1=absolute coordinates) 00396 @param X offset vector 00397 @param I mass moment of inertia matrix about the CG 00398 """ 00399 type = 'CONM2' 00400 # 'CONM2 501274 11064 132.274' 00401 def __init__(self, card=None, data=None): 00402 PointMassElement.__init__(self, card, data) 00403 if card: 00404 #self.nids = [ card[1] ] 00405 #del self.nids 00406 #self.pid = None 00407 self.eid = card.field(1) 00408 self.nid = card.field(2) 00409 self.cid = card.field(3, 0) 00410 self.mass = card.field(4, 0.) 00411 self.X = array(card.fields(5, 8, [0., 0., 0.])) 00412 self.I = card.fields(9, 15, [0.]*6) 00413 else: 00414 self.eid = data[0] 00415 self.nid = data[1] 00416 self.cid = data[2] 00417 self.mass = data[3] 00418 self.X = data[4:7] 00419 self.I = data[7:] 00420 ### 00421 00422 def Mass(self): 00423 return self.mass 00424 00425 def Inertia(self): 00426 """ 00427 Returns the 3x3 inertia matrix 00428 @warning doesnt handle offsets or coordinate systems 00429 """ 00430 I = self.I 00431 A = [ [ I[0], I[1], I[3] ], 00432 [ I[1], I[2], I[4] ], 00433 [ I[3], I[4], I[5] ]] 00434 if self.Cid()==-1: 00435 return A 00436 else: 00437 # transform to global 00438 (dx, matrix) = self.cid.transformToGlobal(self.X) 00439 raise NotImplementedError() 00440 A2 = A*matrix 00441 return A2 # correct for offset using dx??? 00442 00443 def Centroid(self): 00444 if self.Cid()==0: 00445 X2 = self.nid.Position()+self.X 00446 elif self.Cid()==-1: 00447 return self.X 00448 else: 00449 dx,matrix = self.cid.transformToGlobal(self.X) 00450 #print "dx = ",dx 00451 #print "X = ",self.nid.Position() 00452 X2 = self.nid.Position()+dx 00453 return X2 00454 00455 def crossReference(self, model): 00456 if self.Cid()!=-1: 00457 self.cid = model.Coord(self.cid) 00458 self.nid = model.Node(self.nid) 00459 00460 def nodeIDs(self): 00461 return [self.Nid()] 00462 00463 def Nid(self): 00464 if isinstance(self.nid, int): 00465 return self.nid 00466 return self.nid.nid 00467 00468 def Cid(self): 00469 if isinstance(self.cid, int): 00470 return self.cid 00471 return self.cid.cid 00472 00473 def writeCodeAster(self): 00474 msg = '' 00475 msg += " DISCRET=_F(\n" 00476 msg += " 'CARA='M_T_D_N'\n" 00477 msg += " NOEUD=N%s\n" %(self.Nid()) 00478 msg += " VALE=%g),\n" %(self.mass) 00479 return msg 00480 00481 def rawFields(self): 00482 #print "X=%r" %(self.X) 00483 #print "I=%r" %(self.I) 00484 fields = ['CONM2', self.eid, self.Nid(), self.Cid(), self.mass]+list(self.X)+[None]+list(self.I) 00485 return fields 00486 00487 def reprFields(self): 00488 I = [] 00489 for i in self.I: 00490 if i==0.: 00491 I.append(None) 00492 else: 00493 I.append(i) 00494 ### 00495 ### 00496 X = [] 00497 for x in self.X: 00498 if x==0.: 00499 X.append(None) 00500 else: 00501 X.append(x) 00502 ### 00503 ### 00504 00505 cid = set_blank_if_default(self.Cid(), 0) 00506 mass = set_blank_if_default(self.mass, 0.) 00507 fields = ['CONM2', self.eid, self.Nid(), cid, mass]+X+[None]+I 00508 return fields 00509