pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
staticLoads.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=C0103,R0902,R0904,R0914
00026 
00027 from __future__ import division, print_function
00028 from itertools import izip
00029 
00030 from numpy import array, cross, allclose
00031 from numpy.linalg import norm
00032 
00033 from pyNastran.bdf.cards.loads.loads import Load, LoadCombination
00034 from pyNastran.bdf.fieldWriter import set_blank_if_default
00035 from ..baseCard import BaseCard, expandThru, expandThruBy
00036 
00037 class LOAD(LoadCombination):
00038     type = 'LOAD'
00039     def __init__(self, card=None, data=None):
00040         LoadCombination.__init__(self, card, data)
00041 
00042     def getLoadIDs(self):
00043         """
00044         @note requires a cross referenced load
00045         """
00046         load_IDs = []
00047         for loads in self.loadIDs:
00048             for load in loads:
00049                 #if isinstance(load,int):
00050                     #load_IDs += [load]
00051                     
00052                 if isinstance(load, LOAD):
00053                     lid = load.lid
00054                     if isinstance(lid, list):
00055                         load_IDs += load.lid
00056                     else: # int
00057                         load_IDs += load.getLoadIDs()
00058                 elif (isinstance(load, Force)  or isinstance(load, Moment) or
00059                       isinstance(load, PLOAD4) or isinstance(load, GRAV)):
00060                     load_IDs += [load.lid]
00061                 else:
00062                     msg = ('The getLoadIDs method doesnt support %s cards.\n'
00063                            '%s' % (load.__class__.__name__,str(load)))
00064                     raise NotImplementedError(msg)
00065  
00066                 ###
00067         ###
00068         load_IDs = list(set(load_IDs))
00069         #print "load_IDs = ",load_IDs
00070         return load_IDs
00071 
00072     def getLoadTypes(self):
00073         """
00074         @note requires a cross referenced load
00075         """
00076         loadTypes = []
00077         for loads in self.loadIDs:
00078             for load in loads:
00079                 if isinstance(load, LOAD):
00080                     lid = load.lid
00081                     if isinstance(lid, list):
00082                         loadTypes += load.type
00083                     else: # int
00084                         loadTypes += [load.type]+load.getLoadTypes()
00085                 elif (isinstance(load, Force)  or isinstance(load, Moment) or
00086                       isinstance(load, PLOAD4) or isinstance(load, GRAV)):
00087                     loadTypes += [load.type]
00088                 else:
00089                     raise RuntimeError(load)
00090                 ###
00091         ###
00092         loadTypes = list(set(loadTypes))
00093         #print "loadTypes = ",loadTypes
00094         return loadTypes
00095 
00096     def writeCalculixGRAV(self, gx, gy, gz):
00097         msg  = '*DLOAD\n'
00098         msg += 'AllElements,GRAV,%s,%s,%s\n' % (gx, gy, gz)
00099         return msg
00100 
00101     def writeCodeAsterLoad(self, model, gridWord='node'):
00102         loadIDs   = self.getLoadIDs()
00103         loadTypes = self.getLoadTypes()
00104         
00105         #msg = '# Loads\n'
00106         msg = ''
00107         (typesFound, forceLoads, momentLoads,
00108                      forceConstraints, momentConstraints,
00109                      gravityLoads) = self.organizeLoads(model)
00110 
00111         nids = []
00112         for nid in forceLoads:
00113             nids.append(nid)
00114         for nid in momentLoads:
00115             nids.append(nid)
00116 
00117         if nids:
00118             msg += '# typesFound = %s\n' % (list(typesFound))
00119             msg += '# loadIDs    = %s\n' % (loadIDs)
00120             msg += "load_bc=AFFE_CHAR_MECA(MODELE=modmod,\n"
00121             #msg += "                      DDL_IMPO=(_F(GROUP_MA='Lleft',\n"
00122             msg += "                       FORCE_NODALE=(\n"
00123 
00124         #CHAR=AFFE_CHAR_MECA(MODELE=MODE,
00125         #             FORCE_NODALE=(
00126         #                     _F(NOEUD='N1',
00127         #                        FZ=-500.0),)
00128 
00129         #print("nids = ",nids)
00130         spaces = "                                 "
00131         for nid in sorted(nids): # ,load in sorted(forceLoads.iteritems())
00132             #print("nid = ",nid)
00133             msg += spaces + "_F(NOEUD='%s%s',\n" % (gridWord, nid)
00134             #print "load = ",load
00135             
00136             if nid in forceLoads:
00137                 force = forceLoads[nid]
00138                 if abs(force[0]) > 0.:
00139                     msg += spaces + "  FX=%s,\n" % (force[0])
00140                 if abs(force[1]) > 0.:
00141                     msg += spaces + "  FY=%s,\n" % (force[1])
00142                 if abs(force[2]) > 0.:
00143                     msg += spaces + "  FZ=%s,\n" % (force[2])
00144 
00145             if nid in momentLoads:
00146                 moment = momentLoads[nid]
00147                 if abs(moment[0]) > 0.:
00148                     msg += spaces + "  MX=%s,\n" % (moment[0])
00149                 if abs(moment[1]) > 0.:
00150                     msg += spaces + "  MY=%s,\n" % (moment[1])
00151                 if abs(moment[2]) > 0.:
00152                     msg += spaces + "  MZ=%s,\n" % (moment[2])
00153             msg = msg[:-2]
00154             msg += '),\n'
00155             # finish the load
00156             
00157             #if moment in
00158             #msg += "                                   DX=0.0,\n"
00159             #msg += "                                   DY=0.0,\n"
00160             #msg += "                                   DZ=0.0,),\n"
00161             #msg += "                                _F(GROUP_MA='Lright',\n"
00162             #msg += "                                   DZ=0.0,),),\n"
00163         msg = msg[:-2]
00164         msg += ');\n'
00165         
00166         for gravityLoad in gravityLoads:
00167             msg += 'CA_GRAVITY(%s);\n' % (str(gravityLoad))
00168         return (msg, loadIDs, loadTypes)
00169 
00170     def getReducedLoads(self):
00171         """
00172         Get all load objects in a simplified form,
00173         which means all scale factors are already applied and
00174         only base objects (no LOAD cards) will be returned.
00175         @todo lots more object types to support
00176         """
00177         scaleFactors = []
00178         loads  = []
00179         scale = self.scale
00180         for (loadsPack, scaleFactorI) in izip(self.loadIDs, self.scaleFactors):
00181             scale2 = scaleFactorI*scale
00182             for load in loadsPack:
00183                 if (isinstance(load, Force)  or isinstance(load, Moment) or 
00184                     isinstance(load, PLOAD4) or isinstance(load, GRAV)):
00185                     loads.append(load)
00186                     scaleFactors.append(scale2)
00187                 elif isinstance(load, LOAD):
00188                     (scaleFactorsi, loadsi) = load.getReducedLoads()
00189                     loads += loadsi
00190                     scaleFactors += [scale2*scalei for scalei in scaleFactorsi]
00191                 else:
00192                     msg = ('%s isnt supported in getReducedLoads method'
00193                         % (load.__class__.__name__))
00194                     raise NotImplementedError(msg)
00195                 ###
00196             ###
00197         ###
00198         return (scaleFactors, loads)
00199 
00200     def organizeLoads(self, model):
00201         """
00202         Figures out magnitudes of the loads to be applied to the various nodes.
00203         This includes figuring out scale factors.
00204         """
00205         forceLoads  = {} # spc enforced displacement (e.g. FORCE=0)
00206         momentLoads = {}
00207         forceConstraints  = {}
00208         momentConstraints = {}
00209         gravityLoads = []
00210         #print("self.loadIDs = ",self.loadIDs)
00211         
00212         typesFound = set()
00213         (scaleFactors, loads) = self.getReducedLoads()
00214 
00215         for (scaleFactor, load) in izip(scaleFactors, loads):
00216             #print("*load = ",load)
00217             out = load.transformLoad()
00218             typesFound.add(load.__class__.__name__)
00219             if isinstance(load, Force):
00220                 (isLoad, node, vector) = out
00221                 if isLoad:  #load
00222                     if node not in forceLoads:
00223                         forceLoads[node]  = vector*scaleFactor
00224                     else:
00225                         forceLoads[node] += vector*scaleFactor
00226                     ###
00227                 else: # constraint
00228                     if node not in forceLoads:
00229                         forceConstraints[node]  = vector*scaleFactor
00230                     else:
00231                         forceConstraints[node] += vector*scaleFactor
00232                     ###
00233                 ###
00234             elif isinstance(load, Moment):
00235                 (isLoad, node, vector) = out
00236                 if isLoad: # load
00237                     if node not in momentLoads:
00238                         momentLoads[node]  = vector*scaleFactor
00239                     else:
00240                         momentLoads[node] += vector*scaleFactor
00241                     ###
00242                 else: # constraint
00243                     if node not in momentLoads:
00244                         momentConstraints[node]  = vector*scaleFactor
00245                     else:
00246                         momentConstraints[node] += vector*scaleFactor
00247                     ###
00248                 ###
00249             elif isinstance(load, PLOAD4):
00250                 (isLoad, nodes, vectors) = out
00251                 for (nid, vector) in izip(nodes, vectors):
00252                     # not the same vector for all nodes
00253                     forceLoads[nid] = vector*scaleFactor
00254 
00255             elif isinstance(load, GRAV):
00256                 #(grav) = out
00257                 gravityLoads.append(out*scaleFactor) # grav
00258             else:
00259                 msg = '%s not supported' % (load.__class__.__name__)
00260                 raise NotImplementedError(msg)
00261             ###
00262         ###
00263         return (typesFound, forceLoads, momentLoads, forceConstraints,
00264                 momentConstraints, gravityLoads)
00265 
00266     def rawFields(self):
00267         fields = ['LOAD', self.sid, self.scale]
00268         for (scaleFactor, loadID) in izip(self.scaleFactors, self.loadIDs):
00269             fields += [scaleFactor, self.LoadID(loadID)]
00270         return fields
00271 
00272     def reprFields(self):
00273         return self.rawFields()
00274 
00275 #------------------------------------------------------------------------------
00276 class GRAV(BaseCard):
00277     """
00278     Defines acceleration vectors for gravity or other acceleration loading
00279     GRAV SID CID A     N1  N2 N3    MB
00280     GRAV 1   3   32.2 0.0 0.0 -1.0
00281     """
00282     type = 'GRAV'
00283     def __init__(self, card=None, data=None):
00284         if card:
00285             ## Set identification number
00286             self.sid = card.field(1)
00287             ## Coordinate system identification number.
00288             self.cid = card.field(2, 0)
00289             ## scale factor
00290             self.scale = card.field(3)
00291             ## Acceleration vector components measured in coordinate system CID
00292             self.N   = array(card.fields(4, 7, [0., 0., 0.]))
00293             ## Indicates whether the CID coordinate system is defined in the
00294             ## main Bulk Data Section (MB = -1) or the partitioned superelement
00295             ## Bulk Data Section (MB = 0). Coordinate systems referenced in the
00296             ## main Bulk Data Section are considered stationary with respect to
00297             ## the assembly basic coordinate system. See Remark 10.
00298             ## (Integer; Default = 0)
00299             self.mb  = card.field(7, 0)
00300         else:
00301             self.sid = data[0]
00302             self.cid = data[1]
00303             self.a   = data[2]
00304             self.N   = array(data[3:6])
00305             self.mb  = data[6]
00306             self.scale = 1.
00307             assert len(data)==7
00308 
00309         assert not allclose(max(abs(self.N)), 0.),('GRAV N is a zero vector, '
00310                                                    'N=%s' % (str(self.N)))
00311 
00312     def getLoads(self):
00313         return [self]
00314 
00315     def organizeLoads(self, model):
00316         typesFound = [self.type]
00317         forceLoads = {}
00318         momentLoads = {}
00319         forceConstraints = {}
00320         momentConstraints = {}
00321         gravityLoad = self.transformLoad()
00322         return (typesFound, forceLoads, momentLoads,
00323                            forceConstraints, momentConstraints,
00324                            gravityLoad)
00325 
00326     def transformLoad(self):
00327         g = self.GravityVector()
00328         (g2, matrix) = self.cid.transformToGlobal(g)
00329         return (g2)
00330 
00331     #def writeCodeAster(self,mag):
00332         #p = self.GravityVector()
00333         #msg = 'GRAV([%s,%s,%s])' %(p)
00334         #return msg
00335 
00336     def crossReference(self, model):
00337         #print("xref GRAV")
00338         self.cid = model.Coord(self.cid)
00339     
00340     def Cid(self):
00341         if isinstance(self.cid, int):
00342             return self.cid
00343         return self.cid.cid
00344 
00345     def GravityVector(self):
00346         """returns the gravity vector in absolute coordinates"""
00347         (p, matrix) = self.cid.transformToGlobal(self.N)
00348         return self.scale*p
00349         
00350     def rawFields(self):
00351         N = list(self.N)
00352         fields = ['GRAV', self.sid, self.Cid(), self.scale]+N+[self.mb]
00353         return fields
00354 
00355     def reprFields(self):
00356         N = []
00357         for n in self.N:
00358             N.append(set_blank_if_default(n, 0.0))
00359         
00360         mb = set_blank_if_default(self.mb, 0)
00361         fields = ['GRAV', self.sid, self.Cid(), self.scale]+N+[mb]
00362         return fields
00363 
00364 class ACCEL1(BaseCard):
00365     """
00366     Acceleration Load
00367     Defines static acceleration loads at individual GRID points.
00368     """
00369     type = 'ACCEL1'
00370     def __init__(self, card=None, data=None):
00371         ## Load set identification number (Integer>0)
00372         self.sid = card.field(1)
00373         
00374         ## Coordinate system identification number. (Integer>0: Default=0)
00375         self.cid = card.field(2, 0)
00376         
00377         ## Acceleration vector scale factor. (Real)
00378         self.scale = card.field(3)
00379         
00380         ## Components of the acceleration vector measured in coordinate system
00381         ## CID. (Real; at least one Ni != 0)
00382         self.N   = array(card.fields(4, 7, [0., 0., 0.]))
00383         assert max(abs(self.N))>0.
00384         ## nodes to apply the acceleration to
00385         self.nodes = expandThruBy(card.fields(9))
00386 
00387     def crossReference(self, model):
00388         self.cid = model.Coord(self.cid)
00389         self.nodes = model.Nodes(self.nodes, allowEmptyNodes=True)
00390     
00391     def Cid(self):
00392         if isinstance(self.cid, int):
00393             return self.cid
00394         return self.cid.cid
00395 
00396     def nodeIDs(self, nodes=None):  # this function comes from BaseCard.py
00397         """returns nodeIDs for repr functions"""
00398         if not nodes:
00399             nodes = self.nodes
00400         if isinstance(nodes[0], int):
00401             nodeIDs = [node     for node in nodes]
00402         else:
00403             nodeIDs = [node.nid for node in nodes]
00404         ###
00405         assert 0 not in nodeIDs, 'nodeIDs = %s' % (nodeIDs)
00406         return nodeIDs
00407 
00408     def rawFields(self):
00409         fields = ['ACCEL1', self.sid, self.Cid(), self.scale,
00410                   self.N[0], self.N[1], self.N[2], None, None]+self.nodeIDs()
00411         return fields
00412 
00413 
00414 #------------------------------------------------------------------------------
00415 class OneDeeLoad(Load): # FORCE/MOMENT
00416     type = '1D_Load'
00417     def __init__(self, card, data):
00418         self.cid = None
00419         self.mag = None
00420         self.xyz = None
00421         Load.__init__(self, card, data)
00422 
00423     def getLoads(self):
00424         return [self]
00425 
00426     def transformLoad(self):
00427         #print("self.xyz = ",self.xyz)
00428         (xyz, matrix) = self.cid.transformToGlobal(self.xyz)
00429         if self.mag > 0.:
00430             #print("mag=%s xyz=%s" % (self.mag, xyz))
00431             return (True, self.node, self.mag*xyz) # load
00432         return (False, self.node, xyz) # enforced displacement
00433 
00434     def normalize(self):
00435         """
00436         adjust the vector to a unit length
00437         scale up the magnitude of the vector
00438         """
00439         if self.mag != 0.0:  # enforced displacement
00440             normXYZ = norm(self.xyz)
00441             #mag = self.mag*normXYZ
00442             self.mag *= normXYZ
00443             self.xyz = self.xyz/normXYZ
00444 
00445 #------------------------------------------------------------------------------
00446 class Force(OneDeeLoad):
00447     """Generic class for all Forces"""
00448     type = '1D_Load'
00449     def __init__(self, card, data):
00450         OneDeeLoad.__init__(self, card, data)
00451 
00452     def getLoads(self):
00453         return [self]
00454 
00455     def F(self):
00456         return self.xyz*self.mag
00457 
00458     def getReducedLoads(self):
00459         scaleFactors = [1.]
00460         loads = self.F()
00461         return(scaleFactors, loads)
00462 
00463     def organizeLoads(self, model):
00464         (scaleFactors, forceLoads) = self.getReducedLoads()
00465 
00466         typesFound = [self.type]
00467         momentLoads = {}
00468         forceConstraints = {}
00469         momentConstraints = {}
00470         gravityLoads = []
00471         return (typesFound, forceLoads, momentLoads,
00472                            forceConstraints, momentConstraints,
00473                            gravityLoads)
00474 
00475 class Moment(OneDeeLoad):
00476     """Generic class for all Moments"""
00477     type = 'Moment'
00478     def __init__(self, card, data):
00479         OneDeeLoad.__init__(self, card, data)
00480 
00481     def getLoads(self):
00482         return [self]
00483 
00484     def getReducedLoads(self):
00485         scaleFactors = [1.]
00486         loads = self.F()
00487         return(scaleFactors, loads)
00488 
00489     def organizeLoads(self, model):
00490         (scaleFactors, momentLoads) = self.getReducedLoads()
00491 
00492         typesFound = [self.type]
00493         forceLoads = {}
00494         forceConstraints = {}
00495         momentConstraints = {}
00496         gravityLoads = []
00497         return (typesFound, forceLoads, momentLoads,
00498                             forceConstraints, momentConstraints,
00499                             gravityLoads)
00500     def M(self):
00501         return self.xyz*self.mag
00502 
00503 #------------------------------------------------------------------------------
00504 class FORCE(Force):
00505     type = 'FORCE'
00506     def __init__(self, card=None, data=None):
00507         """
00508         FORCE          3       1            100.      0.      0.      1.
00509         """
00510         Force.__init__(self, card, data)
00511         if card:
00512             self.sid  = card.field(1)
00513             self.node = card.field(2)
00514             self.cid  = card.field(3, 0)
00515             self.mag  = card.field(4)
00516             xyz = card.fields(5, 8, [0., 0., 0.])
00517         else:
00518             self.sid  = data[0]
00519             self.node = data[1]
00520             self.cid  = data[2]
00521             self.mag  = data[3]
00522             xyz  = data[4:7]
00523 
00524         assert len(xyz)==3, 'xyz=%s' % (xyz)
00525         self.xyz = array(xyz)
00526 
00527     def Cid(self):
00528         if isinstance(self.cid, int):
00529             return self.cid
00530         return self.cid.cid
00531 
00532     def F(self):
00533         return {self.node: self.mag*self.xyz}
00534 
00535     #def nodeID(self):
00536         #return self.node
00537 
00538     def crossReference(self, model):
00539         """@todo cross reference and fix repr function"""
00540         self.cid = model.Coord(self.cid)
00541 
00542     def rawFields(self):
00543         fields = ['FORCE', self.sid, self.node, self.Cid(), self.mag
00544                  ] + list(self.xyz)
00545         return fields
00546 
00547     def reprFields(self):
00548         cid = set_blank_if_default(self.Cid(), 0)
00549         fields = ['FORCE', self.sid, self.node, cid, self.mag] + list(self.xyz)
00550         return fields
00551 
00552 class FORCE1(Force):
00553     """
00554     Defines a static concentrated force at a grid point by specification of a
00555     magnitude and two grid points that determine the direction.
00556     """
00557     type = 'FORCE1'
00558     def __init__(self, card=None, data=None):
00559         Force.__init__(self, card, data)
00560         if card:
00561             self.sid  = card.field(1)
00562             self.node = card.field(2)
00563             self.mag  = card.field(3)
00564             self.g1   = card.field(4)
00565             self.g2   = card.field(5)
00566         else:
00567             self.sid  = data[0]
00568             self.node = data[1]
00569             self.mag  = data[2]
00570             self.g1   = data[3]
00571             self.g2   = data[4]
00572         ###
00573 
00574     def crossReference(self, model):
00575         """@todo cross reference and fix repr function"""
00576         self.node = model.Node(self.node)
00577         self.g1 = model.Node(self.g1)
00578         self.g2 = model.Node(self.g2)
00579         self.xyz = self.g2.Position()-self.g1.Position()
00580         self.Normalize()
00581     
00582     def G1(self):
00583         if isinstance(self.g1, int) or isinstance(self.g1, float):
00584             return self.g1
00585         return self.g1.nid
00586 
00587     def G2(self):
00588         if isinstance(self.g2, int) or isinstance(self.g1, float):
00589             return self.g2
00590         return self.g2.nid
00591 
00592     def NodeID(self):
00593         if isinstance(self.node, int):
00594             return self.node
00595         return self.node.nid
00596 
00597     def rawFields(self):
00598         (node, g1, g2) = self.nodeIDs([self.node, self.G1(), self.G2()])
00599         fields = ['FORCE1', self.sid, node, self.mag, g1, g2]
00600         return fields
00601 
00602     def reprFields(self):
00603         return self.rawFields()
00604 
00605 class FORCE2(Force):
00606     """
00607     Defines a static concentrated force at a grid point by specification of a
00608     magnitude and four grid points that determine the direction.
00609     """
00610     type = 'FORCE2'
00611     def __init__(self, card=None, data=None):
00612         """
00613         FORCE2 SID G F G1 G2 G3 G4
00614         """
00615         Force.__init__(self, card, data)
00616         if card:
00617             self.sid  = card.field(1)
00618             self.node = card.field(2)
00619             self.mag  = card.field(3)
00620             self.g1   = card.field(4)
00621             self.g2   = card.field(5)
00622             self.g3   = card.field(5)
00623             self.g4   = card.field(5)
00624         else:
00625             self.sid  = data[0]
00626             self.node = data[1]
00627             self.mag  = data[2]
00628             self.g1   = data[3]
00629             self.g2   = data[4]
00630             self.g3   = data[5]
00631             self.g4   = data[6]
00632         ###
00633 
00634     def crossReference(self, model):
00635         """@todo cross reference and fix repr function"""
00636         self.node = model.Node(self.node)
00637 
00638         v12 = model.Node(self.g2).Position() - model.Node(self.g1).Position()
00639         v34 = model.Node(self.g4).Position() - model.Node(self.g3).Position()
00640         v12 = v12/norm(v12)
00641         v34 = v34/norm(v34)
00642         self.xyz = cross(v12, v34)
00643         self.Normalize()
00644 
00645     def NodeID(self):
00646         if isinstance(self.node, int):
00647             return self.node
00648         return self.node.nid
00649 
00650     def rawFields(self):
00651         (node, g1, g2, g3, g4) = self.nodeIDs([self.node, self.g1, self.g2,
00652                                                self.g3, self.g4])
00653         fields = ['FORCE2', self.sid, node, self.mag, g1, g2, g3, g4]
00654         return fields
00655 
00656     def reprFields(self):
00657         return self.rawFields()
00658 
00659 #------------------------------------------------------------------------------
00660 class MOMENT(Moment):
00661     type = 'MOMENT'
00662     def __init__(self, card=None, data=None):
00663         """
00664         Defines a static concentrated moment at a grid point by specifying a
00665         scale factor and a vector that determines the direction.
00666 
00667         MOMENT SID G CID M    N1  N2  N3
00668         MOMENT 2   5   6 2.9 0.0 1.0 0.0
00669         """
00670         Moment.__init__(self, card, data)
00671         self.sid  = card.field(1)
00672         self.node = card.field(2)
00673         self.cid  = card.field(3, 0)
00674         self.mag  = card.field(4)
00675 
00676         xyz = card.fields(5, 8, [0., 0., 0.])
00677         assert len(xyz)==3,'xyz=%s' %(xyz)
00678         self.xyz = array(xyz)
00679 
00680     def Cid(self):
00681         if isinstance(self.cid, int):
00682             return self.cid
00683         return self.cid.cid
00684 
00685     def crossReference(self, model):
00686         """@todo cross reference and fix repr function"""
00687         pass
00688 
00689     def rawFields(self):
00690         fields = ['MOMENT', self.sid, self.node, self.Cid(), self.mag
00691                  ] + list(self.xyz)
00692         return fields
00693 
00694     def reprFields(self):
00695         cid = set_blank_if_default(self.Cid(), 0)
00696         fields = ['MOMENT', self.sid, self.node, cid, self.mag
00697                  ] + list(self.xyz)
00698         return fields
00699 
00700 class MOMENT1(Moment):
00701     type = 'MOMENT1'
00702     def __init__(self, card=None, data=None):
00703         """
00704         Defines a static concentrated moment at a grid point by specifying a
00705         magnitude and two grid points that determine the direction
00706 
00707         MOMENT1 SID G M G1 G2
00708         """
00709         Moment.__init__(self, card, data)
00710         if card:
00711             self.sid  = card.field(1)
00712             self.node = card.field(2)
00713             self.mag  = card.field(3)
00714             self.g1   = card.field(4)
00715             self.g2   = card.field(5)
00716             self.g3   = card.field(6)
00717             self.g4   = card.field(7)
00718             xyz = card.fields(5, 8, [0., 0., 0.])
00719         else:
00720             self.sid  = data[0]
00721             self.node = data[1]
00722             self.mag  = data[2]
00723             self.g1   = data[3]
00724             self.g2   = data[4]
00725             self.g3   = data[5]
00726             self.g4   = data[6]
00727             xyz       = data[7:10]
00728         ###
00729 
00730         assert len(xyz)==3, 'xyz=%s' %(xyz)
00731         self.xyz = array(xyz)
00732 
00733     def crossReference(self, model):
00734         """@todo cross reference and fix repr function"""
00735         self.node = model.Node(self.node)
00736         self.xyz = model.Node(self.g2).Position() - model.Node(self.g1).Position()
00737         self.Normalize()
00738 
00739     def rawFields(self):
00740         (node, g1, g2) = self.nodeIDs([self.node, self.g1, self.g2])
00741         fields = ['MOMENT1', self.sid, node, self.mag, g1, g2]
00742         return fields
00743 
00744     def reprFields(self):
00745         return self.rawFields()
00746 
00747 
00748 class MOMENT2(Moment):
00749     type = 'MOMENT2'
00750     def __init__(self, card=None, data=None):
00751         """
00752         Defines a static concentrated moment at a grid point by specification
00753         of a magnitude and four grid points that determine the direction.
00754 
00755         MOMENT2 SID G M G1 G2 G3 G4
00756         """
00757         Moment.__init__(self, card, data)
00758         if card:
00759             self.sid  = card.field(1)
00760             self.node = card.field(2)
00761             self.mag  = card.field(3)
00762             self.g1   = card.field(4)
00763             self.g2   = card.field(5)
00764             self.g3   = card.field(6)
00765             self.g4   = card.field(7)
00766             xyz = card.fields(5, 8, [0., 0., 0.])
00767         else:
00768             self.sid  = data[0]
00769             self.node = data[1]
00770             self.mag  = data[2]
00771             self.g1   = data[3]
00772             self.g2   = data[4]
00773             self.g3   = data[5]
00774             self.g4   = data[6]
00775             xyz       = data[7:10]
00776         ###
00777         assert len(xyz) == 3, 'xyz=%s' % (xyz)
00778         self.xyz = array(xyz)
00779 
00780     def crossReference(self, model):
00781         """@todo cross reference and fix repr function"""
00782         (self.g1, self.g2, self.g3, self.g4) = model.Nodes(self.g1, self.g2,
00783                                                            self.g3, self.g4)
00784         v12 = self.g2.Position()-self.g1.Position()
00785         v34 = self.g4.Position()-self.g3.Position()
00786         v12 = v12/norm(v12)
00787         v34 = v34/norm(v34)
00788         self.xyz = cross(v12, v34)
00789 
00790     def rawFields(self):
00791         (node, g1, g2, g3, g4) = self.nodeIDs([self.node, self.g1, self.g2,
00792                                                           self.g3, self.g4])
00793         fields = ['MOMENT2', self.sid, node, self.mag, g1, g2, g3, g4]
00794         return fields
00795 
00796     def reprFields(self):
00797         return self.rawFields()
00798 
00799 #------------------------------------------------------------------------------
00800 class PLOAD(Load):
00801     type = 'PLOAD'
00802     def __init__(self, card=None, data=None):
00803         if card:
00804             self.sid   = card.field(1)
00805             self.p     = card.field(2)
00806             nodes      = card.fields(3, 7)
00807             self.nodes = self._wipeEmptyFields(nodes)
00808         else:
00809             self.sid   = data[0]
00810             self.p     = data[1]
00811             self.nodes = data[2:]
00812             print("PLOAD = %s" %(data))
00813             raise NotImplementedError('PLOAD')
00814         assert len(self.nodes) in [3, 4], 'nodes=%s' %(self.nodes)
00815     
00816     def crossReference(self, model):
00817         """@todo cross reference and fix repr function"""
00818         pass
00819 
00820     def getLoads(self):
00821         return [self]
00822 
00823     def rawFields(self):
00824         fields = ['PLOAD', self.sid, self.p]+self.nodeIDs()
00825         return fields
00826 
00827     def reprFields(self):
00828         return self.rawFields()
00829 
00830 class PLOAD1(Load):
00831     type = 'PLOAD1'
00832     validTypes = ['FX', 'FY', 'FZ', 'FXE', 'FYE', 'FZE',
00833                   'MX', 'MY', 'MZ', 'MXE', 'MYE', 'MZE']
00834     validScales = ['LE', 'FR', 'LEPR', 'FRPR']
00835     def __init__(self, card=None, data=None):
00836         if card:
00837             self.sid   = card.field(1)
00838             self.eid   = card.field(2)
00839             self.Type  = card.field(3)
00840             self.scale = card.field(4)
00841             self.x1    = card.field(5)
00842             self.p1    = card.field(6)
00843             self.x2    = card.field(7)
00844             self.p2    = card.field(8)
00845         else:
00846             self.sid   = data[0]
00847             self.eid   = data[1]
00848             self.Type  = data[2]
00849             self.scale = data[3]
00850             self.x1    = data[4]
00851             self.p1    = data[5]
00852             self.x2    = data[6]
00853             self.p2    = data[7]
00854         ###
00855         assert self.Type  in self.validTypes,  '%s is an invalid type on the PLOAD1 card' % (self.Type)
00856         assert self.scale in self.validScales, '%s is an invalid scale on the PLOAD1 card' % (self.scale)
00857 
00858     def crossReference(self, model):
00859         """@todo cross reference and fix repr function"""
00860         pass
00861 
00862     def getLoads(self):
00863         return [self]
00864 
00865     def rawFields(self):
00866         fields = ['PLOAD1', self.sid, self.eid, self.Type, self.scale, self.x1,
00867                   self.p1, self.x2, self.p2]
00868         return fields
00869 
00870     def reprFields(self):
00871         return self.rawFields()
00872 
00873 class PLOAD2(Load):
00874     type = 'PLOAD2'
00875     def __init__(self, card=None, data=None):
00876         if card:
00877             self.sid = card.field(1)
00878             self.p   = card.field(2)
00879             eids = card.fields(3, 9)
00880 
00881             if card.field(4)=='THRU':
00882                 #print "PLOAD2 %s %s" %(eids[0],eids[-1])
00883                 eids = [i for i in xrange(eids[0], eids[2]+1)]
00884                 #print "found a THRU on PLOAD2"
00885                 #raise NotImplementedError('PLOAD2')
00886             ###
00887             self.eids = eids
00888         else:
00889             self.sid   = data[0]
00890             self.p     = data[1]
00891             self.eids = list(data[2:])
00892             #print "PLOAD2 = ",data
00893         ###
00894 
00895     def crossReference(self, model):
00896         """@todo cross reference and fix repr function"""
00897         pass
00898 
00899     def getLoads(self):
00900         return [self]
00901 
00902     def rawFields(self):
00903         fields = ['PLOAD2', self.sid, self.p]
00904         if len(self.eids)>6:
00905             fields += [self.eids[0], 'THRU', self.eids[-1]]
00906         else:
00907             fields += self.eids
00908         return fields
00909 
00910     def reprFields(self):
00911         return self.rawFields()
00912 
00913 class PLOAD4(Load):
00914     type = 'PLOAD4'
00915     def __init__(self, card=None, data=None):
00916         if card:
00917             self.sid = card.field(1)
00918             self.eid = card.field(2)
00919             p1 = card.field(3)
00920             p  = card.fields(4, 7, [p1, p1, p1]) # [p1,p1,p1] are the defaults
00921             self.pressures = [p1]+p
00922 
00923             self.eids = [self.eid]
00924             if card.field(7)=='THRU' and card.field(8): # plates
00925                 eid2 = card.field(8)
00926                 if eid2:
00927                     self.eids = expandThru([self.eid, 'THRU', eid2])
00928 
00929                 self.g1   = None
00930                 self.g34  = None
00931             else:
00932                 ## used for CPENTA, CHEXA
00933                 self.eids = [self.eid]
00934                 ## used for solid element only
00935                 self.g1   = card.field(7)
00936                 ## g3/g4 - different depending on CHEXA/CPENTA or CTETRA
00937                 self.g34  = card.field(8)
00938             ###
00939 
00940             ## Coordinate system identification number. See Remark 2.
00941             ## (Integer >= 0;Default=0)
00942             self.cid     = card.field(9, 0)
00943             #print "PLOAD4 cid = ",self.cid
00944             self.NVector = card.fields(10, 13, [0., 0., 0.])
00945             self.sorl    = card.field(13, 'SURF')
00946             self.ldir    = card.field(14, 'NORM')
00947         else:
00948             #print "PLOAD4 = ",data
00949             self.sid     = data[0]
00950             self.eid     = data[1]
00951             self.pressures = data[2]
00952 
00953             self.g1      = data[3]
00954             self.g34     = data[4]
00955             self.cid     = data[5]
00956             self.NVector = data[6]
00957 
00958             self.sorl    = data[7]
00959             #self.ldir    = data[8]
00960             #assert len(data)==8
00961             
00962             self.g1  = self.g1
00963             self.g34 = self.g34
00964             self.eids = [self.eid]
00965         ###
00966 
00967     def getLoads(self):
00968         return [self]
00969 
00970     def transformLoad(self):
00971         """
00972         @warning sorl=SURF is supported (not LINE)
00973         @warning ldir=NORM is supported (not X,Y,Z)
00974         """
00975         assert self.sorl == 'SURF', 'only surface loads are supported.  required_sorl=SURF.  actual=%s' % (self.sorl)
00976         assert self.ldir == 'NORM', 'only normal loads are supported.   required_ldir=NORM.  actual=%s' % (self.ldir)
00977         assert len(self.eids) == 1, 'only one load may be defined on each PLOAD4.  nLoads=%s\n%s' % (len(self.eids), str(self))
00978 
00979         if self.g1 and self.g34: # solid elements
00980             nid = self.g1.nid
00981             nidOpposite = self.g34.nid
00982             (faceNodeIDs, Area) = self.eid.getFaceNodesAndArea(self, nid,
00983                                                                nidOpposite)
00984         else:
00985             faceNodeIDs = self.eid.nodeIDs()
00986             Area = self.eid.Area()
00987         n = len(faceNodeIDs)
00988 
00989         vector = array(self.eid.Normal())
00990         vectors = []
00991         for (nid, p) in izip(faceNodeIDs, self.pressures):
00992             ## @warning only supports normal pressures
00993             vectors.append(vector*p*Area/n) # Force_i
00994             
00995         isLoad = None
00996         return (isLoad, faceNodeIDs, vectors)
00997 
00998     def Cid(self):
00999         if isinstance(self.cid, int):
01000             return self.cid
01001         return self.cid.cid
01002 
01003     def crossReference(self, model):
01004         self.eid = model.Element(self.eid)
01005         self.cid = model.Coord(self.cid)
01006         if self.g1:
01007             self.g1  = model.Node(self.g1)
01008         if self.g34:
01009             self.g34 = model.Node(self.g34)
01010         if self.eids:
01011             self.eids = model.Elements(self.eids)
01012 
01013     def Eid(self, eid):
01014         if isinstance(eid, int):
01015             return eid
01016         return eid.eid
01017 
01018     def getElementIDs(self, eid=None):
01019         if eid:
01020             return self.Eid(eid)
01021         eids = []
01022         for element in self.eids:
01023             eids.append(self.Eid(element))
01024         return eids
01025 
01026     def rawFields(self):
01027         eid  = self.Eid(self.eid)
01028         cid  = set_blank_if_default(self.Cid(), 0)
01029         sorl = set_blank_if_default(self.sorl, 'SURF')
01030         ldir = set_blank_if_default(self.ldir, 'NORM')
01031         p1   = self.pressures[0]
01032         p2   = set_blank_if_default(self.pressures[1], p1)
01033         p3   = set_blank_if_default(self.pressures[2], p1)
01034         p4   = set_blank_if_default(self.pressures[3], p1)
01035         fields = ['PLOAD4', self.sid, eid, self.pressures[0], p2, p3, p4]
01036 
01037         #print "g3=|%s| g4=%s eids=|%s|" %(self.g3,self.g4,self.eids)
01038         if self.g1 is not None: # is it a SOLID element
01039             (g1, g34) = self.nodeIDs([self.g1, self.g34])
01040             fields.append(g1)
01041             fields.append(g34)
01042         else:
01043             #print "eids = %s" %(self.eids)
01044             if len(self.eids) > 1:
01045                 #print("self.eids = %s" %(self.eids))
01046                 try:
01047                     fields.append('THRU')
01048                     eid = self.eids[-1]
01049                 except:
01050                     print("g1  = %s" % (self.g1))
01051                     print("g34 = %s" % (self.g34))
01052                     print("self.eids = %s" % (self.eids))
01053                     raise
01054                 ###
01055                 fields.append(self.getElementIDs(eid))
01056             else:
01057                 fields += [None, None]
01058             ###
01059         fields.append(cid)
01060         
01061         n1 = set_blank_if_default(self.NVector[0], 0.0)
01062         n2 = set_blank_if_default(self.NVector[1], 0.0)
01063         n3 = set_blank_if_default(self.NVector[2], 0.0)
01064         fields += [n1, n2, n3]
01065         fields.append(sorl)
01066         fields.append(ldir)
01067         return fields
01068 
01069     def reprFields(self):
01070         return self.rawFields()
01071 
01072 class PLOADX1(Load):
01073     type = 'PLOADX1'
01074     def __init__(self, card=None, data=None):
01075         if card:
01076             self.sid = card.field(1)
01077             self.eid = card.field(2)
01078             self.pa = card.field(3) # float
01079             self.pb = card.field(4,self.pa) # float
01080             self.ga = card.field(5) # int
01081             self.gb = card.field(6) # int
01082             self.theta = card.field(7,0.)
01083         else:
01084             self.sid   = data[0]
01085             print("PLOADX1 = %s" %(data))
01086             raise NotImplementedError('PLOADX1')
01087     
01088     def crossReference(self, model):
01089         #self.eid = model.Element(self.eid)
01090         #self.ga = model.Node(self.ga)
01091         #self.gb = model.Node(self.gb)
01092         pass
01093 
01094     def getLoads(self):
01095         return [self]
01096 
01097     def rawFields(self):
01098         fields = ['PLOADX1', self.sid, self.eid, self.pa, self.pb,
01099                   self.ga, self.gb, self.theta]
01100         return fields
01101 
01102     def reprFields(self):
01103         return self.rawFields()
01104 
 All Classes Namespaces Files Functions Variables