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=R0904,R0902 00026 00027 from __future__ import division, print_function 00028 from itertools import izip, count 00029 00030 from pyNastran.bdf.cards.baseCard import BaseCard, expandThru 00031 00032 00033 class constraintObject2(object): 00034 def __init__(self): 00035 self.constraints = {} # SPC, SPC1, SPCD, etc... 00036 self.addConstraints = {} # SPCADD 00037 00038 def Add(self, ADD_Constraint): 00039 """bad name, but adds an SPCADD or MPCADD""" 00040 key = ADD_Constraint.conid 00041 if key in self.addConstraints: 00042 print("already has key...key=%s\n%s" %(key, str(ADD_Constraint))) 00043 else: 00044 self.addConstraints[key] = ADD_Constraint 00045 ### 00046 ### 00047 00048 def append(self, constraint): 00049 key = constraint.conid 00050 if key in self.constraints: 00051 #print "already has key...key=%s\n%s" %(key,str(constraint)) 00052 self.constraints[key].append(constraint) 00053 else: 00054 self.constraints[key] = [constraint] 00055 ### 00056 00057 def _spc(self, spcID): 00058 """could be an spcadd/mpcadd or spc/mpc,spc1,spcd,spcax,suport1""" 00059 if spcID in self.addConstraints: 00060 return self.addConstraints[spcID] 00061 return self.constraints[spcID] 00062 00063 def crossReference(self, model): 00064 #return 00065 #addConstraints2 = {} 00066 for key,addConstraint in sorted(self.addConstraints.iteritems()): 00067 for i,spcID in enumerate(addConstraint.sets): 00068 addConstraint.sets[i] = self._spc(spcID) 00069 ### 00070 self.addConstraints[key] = addConstraint 00071 ### 00072 #self.addConstraints = addConstraints2 00073 00074 constraints2 = {} 00075 for key,constraints in sorted(self.constraints.iteritems()): 00076 constraints2[key] = [] 00077 for constraint in constraints: 00078 constraints2[key].append( constraint.crossReference(model) ) 00079 ### 00080 ### 00081 self.constraints = constraints2 00082 00083 def createConstraintsForID(self): 00084 """ 00085 This function returns all the constraints with an given constraint ID. 00086 For example an MPCADD that references 2 MPCADDs which reference 4 MPCs 00087 should return 4 MPCs (or rather the IDs of those MPCs). 00088 @todo This function *should* also find unassociated constraints. 00089 00090 not really done yet, idea needs to be integrated/separated from 00091 cross-referencing. no point in doing it twice 00092 """ 00093 constraints2 = {} 00094 referencedConstraints = {} 00095 # some of the ADDConstraint keys are MPCADDs/SPCADDs, some are not 00096 for key,addConstraint in sorted(self.addConstraints.iteritems()): 00097 constraints = [] 00098 for i,spcID in enumerate(addConstraint.sets): 00099 constraintIDs = addConstraint.getConstraintIDs() 00100 constraints[spcID] = constraintIDs 00101 constraints += constraintIDs 00102 #constraints.append(spcID) 00103 constraints2[key] = [spcID] 00104 ### 00105 constraints2[key] = constraints 00106 00107 ## not needed b/c there are no MPCADD/SPCADD 00108 #for key,constraints in sorted(self.constraints.iteritems()): 00109 #for constraint in constraints: 00110 #conID = constraint.ConID() 00111 #constraints2[conID] 00112 constraints3 = self.remapSPCs(constraints2) 00113 00114 def remapSPCs(self, constraints): 00115 """not really done yet""" 00116 ## takes the MPCADDs that reference MPCADDs and makes them 00117 ## reference MPCs 00118 00119 constraints2 = {} 00120 Keys = constraints.keys() 00121 nKeys = len(Keys)-1 00122 for i in xrange(nKeys): 00123 Key = Keys[i] 00124 constraints2[Key] 00125 for j in xrange(nKeys): 00126 if i > j: 00127 constraints2[Key].append(constraints[Key]) 00128 ### 00129 ### 00130 ### 00131 return constraints2 00132 00133 def ConstraintID(self): 00134 if isinstance(self.conid, int): 00135 return self.conid 00136 return self.conid.conid 00137 00138 def getConstraintIDs(self): 00139 IDs = [] 00140 for key,constraints in sorted(self.addConstraints.iteritems()): 00141 conID = constraints.ConID() 00142 IDs.append(conID) 00143 00144 for key,constraints in sorted(self.constraints.iteritems()): 00145 for constraint in constraints: 00146 conID = constraint.ConID() 00147 IDs.append(conID) 00148 00149 IDs = list(set(IDs)) 00150 IDs.sort() 00151 return IDs 00152 00153 def __repr__(self): 00154 msg = '' 00155 # write the SPCADD/MPCADD cards 00156 for key,addConstraint in sorted(self.addConstraints.iteritems()): 00157 msg += str(addConstraint) 00158 00159 for key,constraints in sorted(self.constraints.iteritems()): 00160 for constraint in constraints: 00161 msg += str(constraint) 00162 return msg 00163 00164 class constraintObject(object): 00165 00166 def __init__(self): 00167 self.constraints = {} # SPC, SPC1, SPCD, etc... 00168 self.addConstraints = {} # SPCADD 00169 self.resolvedConstraints = [] 00170 00171 def add(self, constraint): 00172 conid = constraint.conid 00173 assert conid not in self.addConstraints 00174 self.addConstraints[conid] = constraint 00175 00176 def append(self,constraint): 00177 key = constraint.conid 00178 if self.constraints.has_key(key): 00179 self.constraints[key].append(constraint) 00180 else: 00181 self.constraints[key] = [constraint] 00182 00183 def getConstraintIDs(self): 00184 IDs = [] 00185 for key,constraints in sorted(self.constraints.iteritems()): 00186 for constraint in constraints: 00187 conID = constraint.ConID() 00188 IDs.append(conID) 00189 return IDs 00190 00191 def ConstraintID(self): 00192 if isinstance(self.conid,int): 00193 return self.conid 00194 return self.conid.conid 00195 00196 def crossReference(self,model): 00197 #print "xref spcadds..." 00198 #print "spcadds = ",self.addConstraints 00199 if self.addConstraints: 00200 for (key,addConstraint) in sorted(self.addConstraints.iteritems()): # SPCADDs 00201 self.crossReference_AddConstraint(key,addConstraint) 00202 #print "spcadds2 = ",self.addConstraints 00203 else: 00204 pass # not done, no spcsets 00205 ### 00206 00207 # xrefs nodes...not done... 00208 #print "xref spc/spc1/spcd..." 00209 return 00210 for key,constraints in sorted(self.constraints.iteritems()): # SPC, SPC1, SPCD 00211 for constraint in constraints: 00212 #constraint.crossR 00213 pass 00214 #if constraint.type=='SPCADD' 00215 #else: 00216 #(conid,nodeDOFs) = constraint.getNodeDOFs(model) # the constrained nodes 00217 #for nodeDOF in nodeDOFs: 00218 # self.addConstraint(conid,nodeDOF) 00219 ### 00220 ### 00221 ### 00222 ### 00223 00224 def crossReference_AddConstraint(self, key, addConstraint): 00225 """ 00226 cross references MPCSETs and SPCSETs 00227 """ 00228 #print "add key=%s" %(key) 00229 #sets = type(addConstraint) 00230 spcsets = addConstraint.sets 00231 #sys.stdout.flush() 00232 #print str(addConstraint.sets) 00233 #sys.stdout.flush() 00234 #print "spcsets = ",spcsets 00235 for (i, conid) in enumerate(spcsets): 00236 #print "conid = ",conid 00237 #conid = spcset.conid 00238 #print "self.addConstraints[conid] = ",self.getConstraint(conid) 00239 constraint = self.getConstraint(conid) 00240 #print 'newSlot = ',self.addConstraints[key].gids[i] 00241 self.addConstraints[key].crossReference(i, constraint) 00242 #self.addConstraints[key].gids[i] = self.getConstraint(conid) 00243 #print "spcadds* = ",self.addConstraints 00244 ### 00245 ### 00246 00247 #def popConstraint(self, conid): # need to not throw away constraints... 00248 # if conid in self.addConstraints: 00249 # return self.addConstraints[conid] 00250 # elif conid in self.constraints: 00251 # return self.constraints[conid] 00252 # else: 00253 # return conid 00254 # ### 00255 00256 def getConstraint(self, conid): 00257 #print "sid=%s" %(conid) 00258 if conid in self.addConstraints: 00259 return self.addConstraints[conid] 00260 elif conid in self.constraints: 00261 return self.constraints[conid] 00262 else: 00263 return conid 00264 ### 00265 00266 def addConstraint(self, conid, nodeDOF): 00267 (nid,dofs) = nodeDOF 00268 for dof in dofs: 00269 self.resolvedConstraints.append( (nid,dof) ) 00270 ### 00271 00272 def __repr__(self): 00273 msg = '' 00274 for addID,spcadd in sorted(self.addConstraints.iteritems()): 00275 msg += str(spcadd) # this writes the SPC cards as well 00276 return msg 00277 00278 msg = '' 00279 #print "repr %s" %(self.addConstraints) 00280 if self.addConstraints: 00281 for addID,spcadd in sorted(self.addConstraints.iteritems()): 00282 msg += str(spcadd) # this writes the SPC cards as well 00283 else: 00284 for key,constraintSets in sorted(self.constraints.iteritems()): 00285 for constraint in constraintSets: 00286 msg += str(constraint) 00287 ### 00288 ### 00289 ### 00290 #print msg 00291 return msg 00292 00293 # works for spc, spc1, spcd 00294 #for key,constraintSets in sorted(self.constraints.iteritems()): 00295 # for constraint in constraintSets: 00296 # msg += str(constraint) 00297 return msg 00298 00299 class Constraint(BaseCard): 00300 def __init__(self,card,data): 00301 pass 00302 00303 def rawFields(self): 00304 fields = [self.type, self.conid] 00305 return fields 00306 00307 class SUPORT1(Constraint): 00308 """ 00309 SUPORT1 SID ID1 C1 ID2 C2 ID3 C3 00310 """ 00311 type = 'SUPORT1' 00312 def __init__(self, card=None, data=None): 00313 Constraint.__init__(self, card, data) 00314 self.conid = card.field(1) # really a support id sid 00315 fields = card.fields(2) 00316 00317 self.IDs = [] 00318 self.Cs = [] 00319 for i in xrange(0, len(fields), 2): 00320 self.IDs.append(fields[i ]) 00321 self.Cs.append( fields[i+1]) 00322 ### 00323 00324 def rawFields(self): 00325 fields = ['SUPORT1', self.conid] 00326 for ID,c in izip(self.IDs, self.Cs): 00327 fields += [ID,c] 00328 return fields 00329 00330 class SUPORT(Constraint): 00331 """ 00332 SUPORT ID1 C1 ID2 C2 ID3 C3 ID4 C4 00333 SUPORT1 SID ID1 C1 ID2 C2 ID3 C3 00334 """ 00335 type = 'SUPORT' 00336 def __init__(self, card=None, data=None): 00337 Constraint.__init__(self, card, data) 00338 if card: 00339 fields = card.fields(1) 00340 else: 00341 fields = data 00342 00343 self.IDs = [] 00344 self.Cs = [] 00345 for i in xrange(0,len(fields),2): 00346 self.IDs.append(fields[i ]) 00347 self.Cs.append( fields[i+1]) 00348 ### 00349 00350 def rawFields(self): 00351 fields = ['SUPORT'] 00352 for ID,c in izip(self.IDs,self.Cs): 00353 fields += [ID,c] 00354 return fields 00355 00356 class MPC(Constraint): 00357 type = 'MPC' 00358 def __init__(self, card=None, data=None): 00359 Constraint.__init__(self, card, data) 00360 self.conid = card.field(1) 00361 #self.gids = [card.field(2),card.field(5,None)] 00362 #self.constraints = [card.field(3),card.field(6,None)] # 0 if scalar point 1-6 if grid 00363 #self.enforced = [card.field(4),card.field(7,None)] 00364 00365 self.gids = [] 00366 self.constraints = [] # 0 if scalar point 1-6 if grid 00367 self.enforced = [] 00368 #print "-----------" 00369 00370 fields = card.fields(0) 00371 nFields = len(fields)-1 00372 #print "fields = ",fields 00373 #print "nFields = ",nFields 00374 for iField in xrange(2,nFields, 8): 00375 pack1 = [card.field(iField), card.field(iField+1, 0), card.field(iField+2, 0.)] 00376 #print "pack1 = ",pack1 00377 self.gids.append( pack1[0]) 00378 self.constraints.append(pack1[1]) # default=0 scalar point 00379 self.enforced.append( pack1[2]) # default=0.0 00380 00381 pack2 = [card.field(iField+3), card.field(iField+4, 0), card.field(iField+5, 0.)] 00382 if pack2 != [None, 0, 0.]: 00383 #print "pack2 = ",pack2 00384 #print "adding pack2" 00385 self.gids.append( pack2[0]) 00386 self.constraints.append(pack2[1]) # default=0 scalar point 00387 self.enforced.append( pack2[2]) # default=0.0 00388 ### 00389 ### 00390 00391 # reduce the size if there are duplicate Nones 00392 #nConstraints = max(len(self.gids ), 00393 # len(self.constraints), 00394 # len(self.enforced )) 00395 #self.gids = self.gids[ 0:nConstraints] 00396 #self.constraints = self.constraints[0:nConstraints] 00397 #self.enforced = self.enforced[ 0:nConstraints] 00398 00399 def rawFields(self): # MPC 00400 fields = ['MPC', self.conid] 00401 for (i, gid, constraint, enforced) in izip(count(), self.gids, self.constraints, self.enforced): 00402 #print [gid,constraint,enforced] 00403 fields += [gid, constraint, enforced] 00404 if i%2==1 and i>0: 00405 fields.append(None) 00406 fields.append(None) 00407 return fields 00408 00409 class SPC(Constraint): 00410 """ 00411 Defines enforced displacement/temperature (static analysis) 00412 velocity/acceleration (dynamic analysis) 00413 SPC SID G1 C1 D1 G2 C2 D2 00414 SPC 2 32 3 -2.6 5 00415 """ 00416 type = 'SPC' 00417 def __init__(self,card=None,data=None): 00418 Constraint.__init__(self,card,data) 00419 00420 if card: 00421 self.conid = card.field(1) 00422 self.gids = [card.field(2), card.field(5, None)] 00423 self.constraints = [card.field(3), card.field(6, None)] # 0 if scalar point 1-6 if grid 00424 self.enforced = [card.field(4), card.field(7, None)] 00425 00426 # reduce the size if there are duplicate Nones 00427 nConstraints = max(len(self.gids ), 00428 len(self.constraints), 00429 len(self.enforced )) 00430 self.gids = self.gids[ 0:nConstraints] 00431 self.constraints = self.constraints[0:nConstraints] 00432 self.enforced = self.enforced[ 0:nConstraints] 00433 else: 00434 self.conid = data[0] 00435 self.gids = [data[1]] 00436 self.constraints = [data[2]] 00437 self.enforced = [data[3]] 00438 ### 00439 00440 def getNodeDOFs(self, model): 00441 pass 00442 #return conid,dofs 00443 00444 def crossReference(self, i, node): 00445 dofCount = 0 00446 self.gids[i] = node 00447 #for (i,constraint) in enumerate(self.constraints): 00448 # if self.constraint is None: 00449 # node = self.Node(self.gids[i]) 00450 # if not node.Is('GRID'): # SPOINT, EPOINT, DPOINT 00451 # dofCount+=1 00452 # else: 00453 # dofCount+=6 00454 # ### 00455 # ### 00456 return dofCount 00457 00458 def rawFields(self): 00459 fields = ['SPC', self.conid] 00460 for (gid, constraint, enforced) in izip(self.gids, self.constraints, self.enforced): 00461 fields += [gid, constraint, enforced] 00462 return fields 00463 00464 class SPCD(SPC): 00465 """ 00466 Defines an enforced displacement value for static analysis and an enforced 00467 motion value (displacement, velocity or acceleration) in dynamic analysis. 00468 SPCD SID G1 C1 D1 G2 C2 D2 00469 SPCD 100 32 436 -2.6 5 2.9 00470 """ 00471 type = 'SPCD' 00472 def __init__(self, card=None, data=None): 00473 # defines everything :) at least until cross-referencing methods are 00474 # implemented 00475 SPC.__init__(self, card, data) 00476 00477 def rawFields(self): 00478 fields = ['SPCD', self.conid] 00479 for (gid, constraint, enforced) in izip(self.gids, self.constraints, self.enforced): 00480 fields += [gid, constraint, enforced] 00481 return fields 00482 00483 class SPCAX(Constraint): 00484 """ 00485 Defines a set of single-point constraints or enforced displacements 00486 for conical shell coordinates. 00487 SPCAX SID RID HID C D 00488 SPCAX 2 3 4 13 6.0 00489 """ 00490 type = 'SPCAX' 00491 def __init__(self,card=None,data=None): 00492 # defines everything :) at least until cross-referencing methods are 00493 # implemented 00494 SPC.__init__(self,card,data) 00495 00496 ## Identification number of a single-point constraint set. 00497 self.conid = card.field(1) 00498 ## Ring identification number. See RINGAX entry. 00499 self.rid = card.field(2) 00500 ## Harmonic identification number. (Integer >= 0) 00501 self.hid = card.field(3) 00502 ## Component identification number. (Any unique combination of the 00503 ## Integers 1 through 6.) 00504 self.c = card.field(4) 00505 ## Enforced displacement value 00506 self.d = card.field(5) 00507 00508 def crossReference(self,i,node): 00509 pass 00510 00511 def rawFields(self): 00512 fields = ['SPCAX', self.conid, self.rid, self.hid, self.c, self.d] 00513 return fields 00514 00515 class SPC1(Constraint): 00516 """ 00517 SPC1 SID C G1 G2 G3 G4 G5 G6 00518 G7 G8 G9 -etc.- 00519 00520 SPC1 3 246 209075 209096 209512 209513 209516 00521 SPC1 3 2 1 3 10 9 6 5 00522 2 8 00523 00524 SPC1 SID C G1 THRU G2 00525 SPC1 313 12456 6 THRU 32 00526 """ 00527 type = 'SPC1' 00528 def __init__(self, card=None, data=None): 00529 Constraint.__init__(self, card, data) 00530 self.conid = card.field(1) 00531 self.constraints = str(card.field(2, '')) # 246 = y; dx, dz dir 00532 nodes = card.fields(3) 00533 self.nodes = expandThru(nodes) 00534 self.nodes.sort() 00535 00536 def crossReference(self, i, node): 00537 self.nodes[i] = node 00538 00539 def rawFields(self): # SPC1 00540 #test = [i for i in xrange(self.nodes[0],self.nodes[-1]+1)] 00541 #print "self.nodes = ",self.nodes 00542 #print "test = ",test 00543 #if self.nodes==test: 00544 # nodes = [self.nodes[0],'THRU',self.nodes[-1]] 00545 #else: 00546 #print "SPC1 self.nodes = ",self.nodes 00547 nodes = [int(i) for i in self.nodes] # SPC1 00548 fields = ['SPC1', self.conid, self.constraints]+nodes 00549 return fields 00550 00551 #class ADDConstraint(Constraint): 00552 # def __init__(self,card,data): 00553 # self.__init__(Constraint) 00554 00555 class ConstraintADD(Constraint): 00556 def __init__(self, card, data): 00557 Constraint.__init__(self, card, data) 00558 00559 def _reprSpcMpcAdd(self, fields): 00560 outSPCs = '' 00561 fieldSets = [] 00562 00563 #print "repr---mpcadd" 00564 #print self.sets 00565 for spcsets in sorted(self.sets): 00566 #print "*spcsets",spcsets 00567 if isinstance(spcsets,int): # spcset wasnt found 00568 #print "int unfound...%s" %(spcsets) 00569 #outSPCs += str(spcsets) 00570 fields.append(spcsets) 00571 elif isinstance(spcsets, list): 00572 #print 'list' 00573 for spcset in sorted(spcsets): 00574 fieldSets.append(spcset.conid) 00575 outSPCs += str(spcset) 00576 ### 00577 else: 00578 #print 'dict' 00579 #outSPCs += str(spcsets.conid) 00580 for (key, spcset) in sorted(spcsets.iteritems()): 00581 fieldSets.append(spcsets.conid) 00582 ### 00583 ### 00584 return self.printCard(fields+list(set(fieldSets)))+outSPCs # SPCADD 00585 00586 00587 class SPCADD(ConstraintADD): 00588 """ 00589 Defines a single-point constraint set as a union of single-point constraint 00590 sets defined on SPC or SPC1 entries. 00591 SPCADD 2 1 3 00592 """ 00593 type = 'SPCADD' 00594 def __init__(self, card=None, data=None): 00595 ConstraintADD.__init__(self, card, data) 00596 self.conid = card.field(1) 00597 sets = card.fields(2) 00598 self.sets = expandThru(sets) 00599 self.sets.sort() 00600 00601 def organizeConstraints(self, model): 00602 """ 00603 Figures out magnitudes of the loads to be applied to the various nodes. 00604 This includes figuring out scale factors. 00605 """ 00606 positionSPCs = [] 00607 typesFound = ['SPCADD'] 00608 (scaleFactors, loads) = self.getReducedConstraints() 00609 return (typesFound, positionSPCs) 00610 00611 def crossReference(self, i, node): 00612 #dofCount = 0 00613 self.sets.sort() 00614 self.sets[i] = node 00615 00616 def rawFields(self): 00617 fields = ['SPCADD', self.conid] #+self.sets 00618 for setID in self.sets: 00619 #print "setID = ",setID 00620 fields.append(setID) 00621 return fields 00622 #return self._reprSpcMpcAdd(fields) 00623 00624 class MPCADD(ConstraintADD): 00625 """ 00626 Defines a multipoint constraint equation of the form 00627 \f$ \Sigma_j A_j u_j =0 \f$ where \f$ u_j \f$ represents 00628 degree-of-freedom \f$ C_j \f$ at grid or scalar point \f$ G_j \f$. 00629 mPCADD 2 1 3 00630 """ 00631 type = 'MPCADD' 00632 def __init__(self, card=None, data=None): 00633 ConstraintADD.__init__(self, card, data) 00634 self.conid = card.field(1) 00635 sets = card.fields(2) 00636 self.sets = expandThru(sets) 00637 self.sets.sort() 00638 00639 def crossReference(self, i, node): 00640 #dofCount = 0 00641 self.sets.sort() 00642 self.sets[i] = node 00643 00644 def rawFields(self): 00645 #outSPCs = '' 00646 fields = ['MPCADD', self.conid] #+self.sets 00647 for setID in self.sets: 00648 fields.append(setID) 00649 return fields 00650 #return self._reprSpcMpcAdd(fields) 00651