pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
constraints.py
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables