pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
nodes.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 #import sys
00029 from numpy import array
00030 
00031 from pyNastran.bdf.fieldWriter import set_blank_if_default
00032 from pyNastran.bdf.cards.baseCard import BaseCard, expandThru, collapseThru
00033 
00034 class Ring(BaseCard):
00035     """Generic Ring base class"""
00036     def __init__(self, card, data):
00037         assert card is None or data is None
00038 
00039 class Node(BaseCard):
00040     """Generic Node base class"""
00041     def __init__(self, card, data):
00042         assert card is None or data is None
00043 
00044     def crossReference(self, model):
00045         msg = '%s hasnt implemented a crossReference method' %(self.type)
00046         raise NotImplementedError(msg)
00047 
00048     def Cp(self):
00049         if isinstance(self.cp, int):
00050             return self.cp
00051         else:
00052             return self.cp.cid
00053         ###
00054 
00055     def Seid(self):
00056         if isinstance(self.seid, int):
00057             return self.seid
00058         else:
00059             return self.seid.seid
00060         ###
00061         
00062     def Cd(self):
00063         if isinstance(self.cd, int):
00064             return self.cd
00065         else:
00066             return self.cd.cid
00067         ###
00068 
00069 class RINGAX(Ring):
00070     """
00071     Defines a ring for conical shell problems
00072     RINGAX ID R    Z    PS
00073     RINGAX 3  2.0 -10.0 162
00074     """
00075     type = 'RINGAX'
00076     def __init__(self, card=None, data=None): # this card has missing fields
00077         Ring.__init__(self, card, data)
00078         self.nid = card.field(1)
00079         self.R   = card.field(3)
00080         self.z   = card.field(4)
00081         self.ps  = card.field(7)
00082 
00083     def Position(self):
00084         return array([0., 0., 0.])
00085 
00086     def rawFields(self):
00087         fields = ['RINGAX', self.nid, None, self.R, self.z, None, None, self.ps]
00088         return fields
00089         
00090     
00091 class SPOINT(Node):
00092     type = 'SPOINT'
00093     def __init__(self, nid):
00094         Node.__init__(self, card=None, data=None)
00095         self.nid = nid
00096 
00097     def crossReference(self, model):
00098         pass
00099 
00100     def Position(self):
00101         return array([0., 0., 0.])
00102 
00103     def rawFields(self):
00104         """
00105         @todo support THRU in output
00106         """
00107         #print("SPOINT")
00108         if isinstance(self.nid, int):
00109             fields = ['SPOINT']+[self.nid]
00110         else:
00111             #print "self.nid = ",self.nid
00112             fields = ['SPOINT']+self.nid
00113         return fields
00114 
00115 class SPOINTs(Node):
00116     """
00117     SPOINT ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8
00118     or
00119     SPOINT ID1 THRU ID2
00120     SPOINT 5   THRU 649
00121     """
00122     type = 'SPOINT'
00123     def __init__(self, card=None, data=None):
00124         Node.__init__(self, card, data)
00125         #nFields = card.nFields()
00126         
00127         if card:
00128             fields  = card.fields(1)
00129         else:
00130             fields = data
00131         self.spoints = set(expandThru(fields))
00132         #i = 0
00133         #while i<nFields: # =1 ???
00134         #    if fields[i]=='THRU':
00135         #        self.spoints += [fields[i-1],fields[i]+1]
00136         #        i+=1
00137         #    else:
00138         #        self.spoints.append(fields[i])
00139         #    i+=1
00140         ###
00141 
00142     def nDOF(self):
00143         return len(self.spoints)
00144 
00145     def addSPoints(self, sList):
00146         #print('old=%s new=%s' %(self.spoints,sList))
00147         self.spoints = self.spoints.union(set(sList))
00148         
00149     def crossReference(self, model):
00150         pass
00151 
00152     def createSPOINTi(self):
00153         spoints = []
00154         for nid in self.spoints:
00155             spoints.append(SPOINT(nid))
00156         ###
00157         return spoints
00158 
00159     def rawFields(self):
00160         #print("SPOINTi")
00161         spoints = list(self.spoints)
00162         spoints.sort()
00163         #print("self.spoints = %s" %(self.spoints))
00164         spoints = collapseThru(spoints)
00165         fields = ['SPOINT']+spoints
00166         return fields
00167 
00168     def reprFields(self):
00169         return self.rawFields()
00170 
00171 class GRDSET(Node):
00172     """
00173     Defines default options for fields 3, 7, 8, and 9 of all GRID entries.
00174     """
00175     type = 'GRDSET'
00176     def __init__(self, card=None, data=None):
00177         ## Grid point coordinate system
00178         self.cp  = card.field(2, 0)
00179         
00180         ## Analysis coordinate system
00181         self.cd   = card.field(6, 0)
00182         
00183         ## Default SPC constraint on undefined nodes
00184         self.ps   = str(card.field(7, ''))
00185         
00186         ## Superelement ID
00187         self.seid = card.field(8, 0)
00188 
00189     def crossReference(self, model):
00190         self.cp = model.Coord(self.cp)
00191         self.cd = model.Coord(self.cd)
00192         #self.seid = model.SuperElement(self.seid)
00193 
00194     def rawFields(self):
00195         fields = ['GRDSET', None, self.Cp(), None, None, None, self.Cd(), self.ps, self.Seid()]
00196         return fields
00197 
00198     def reprFields(self):
00199         cp   = set_blank_if_default(self.Cp(), 0)
00200         cd   = set_blank_if_default(self.Cd(), 0)
00201         ps   = set_blank_if_default(self.ps, 0)
00202         seid = set_blank_if_default(self.Seid(), 0)
00203         fields = ['GRDSET', None, cp, None, None, None, cd, ps, seid]
00204         return fields
00205 
00206 class GRIDB(Node):
00207     type = 'GRIDB'
00208     def __init__(self, card=None, data=None):
00209         """
00210         if coming from a BDF object, card is used
00211         if coming from the OP2, data is used
00212         """
00213         Node.__init__(self, card, data)
00214 
00215         if card:
00216             raise NotImplementedError('GRIDB data')
00217         else:
00218             print(data)
00219             self.nid = data[0]
00220             self.phi = data[1]
00221             self.cd  = data[2]
00222             self.ps  = data[3]
00223             self.idf = data[4]
00224         ###
00225         assert self.nid > 0,  'nid=%s'  %(self.nid)
00226         assert self.phi >= 0, 'phi=%s'  %(self.phi)
00227         assert self.cd  >= 0, 'cd=%s'   %(self.cd)
00228         assert self.ps  >= 0, 'ps=%s'   %(self.ps)
00229         assert self.idf >= 0, 'idf=%s'  %(self.idf)
00230 
00231     def rawFields(self):
00232         fields = ['GRIDB', self.nid, None, None, self.phi, None, self.Cd(), self.ps, self.idf]
00233         return fields
00234 
00235     def reprFields(self):
00236         #phi = set_blank_if_default(self.phi,0.0)
00237         cd  = set_blank_if_default(self.Cd(), 0)
00238         ps  = set_blank_if_default(self.ps, 0)
00239         idf = set_blank_if_default(self.idf, 0)
00240         fields = ['GRIDB', self.nid, None, None, self.phi, None, cd, ps, idf]
00241         return fields
00242 
00243 class GRID(Node):
00244     type = 'GRID'
00245     def __init__(self, card=None, data=None):
00246         """
00247         if coming from a BDF object, card is used
00248         if coming from the OP2, data is used
00249         """
00250         Node.__init__(self, card, data)
00251 
00252         if card:
00253             ## Node ID
00254             self.nid = int(card.field(1))
00255 
00256             ## Grid point coordinate system
00257             self.cp = card.field(2, 0)
00258 
00259             xyz = card.fields(3, 6, [0., 0., 0.])
00260             #displayCard(card)
00261             #print "xyz = ",xyz
00262             self.xyz = array(xyz)
00263 
00264             ## Analysis coordinate system
00265             self.cd = card.field(6, 0)
00266 
00267             ## SPC constraint
00268             self.ps = str(card.field(7, ''))
00269 
00270             ## Superelement ID
00271             self.seid = card.field(8, 0)
00272 
00273             #print "xyz = ",self.xyz
00274             #print "cd = ",self.cd
00275             #print "ps = ",self.ps
00276         else:
00277             #print data
00278             self.nid  = data[0]
00279             self.cp   = data[1]
00280             self.xyz  = array(data[2:5])
00281             self.cd   = data[5]
00282             self.ps   = data[6]
00283             self.seid = data[7]
00284             if self.ps==0:
00285                 self.ps=''
00286             assert len(self.xyz)==3
00287         ###
00288         assert self.nid  >   0,  'nid=%s' %(self.nid)
00289         assert self.cp   >=  0,  'cp=%s'  %(self.cp)
00290         assert self.cd   >= -1,  'cd=%s'  %(self.cd)
00291         assert self.seid >=  0,'seid=%s'  %(self.seid)
00292 
00293     def nDOF(self):
00294         return 6
00295 
00296     def UpdatePosition(self, model, xyz, cid):
00297         self.xyz = xyz
00298         self.cp = model.Coord(cid)
00299         #assert cid == 0
00300         
00301     def Position(self, debug=False):
00302         """
00303         returns the point in the global XYZ coordinate system
00304         @param self the object pointer
00305         @param debug developer debug
00306         """
00307         p,matrix = self.cp.transformToGlobal(self.xyz, debug=debug)
00308         return p
00309 
00310     def PositionWRT(self, model, cid, debug=False):
00311         """
00312         returns the point which started in some arbitrary local coordinate
00313         system and returns it in the desired coordinate system
00314         @param self the object pointer
00315         @param model the BDF model object
00316         @param cid the desired coordinate ID (int)
00317         @param debug developer debug
00318         """
00319         if cid==self.Cp():
00320             return self.xyz
00321         #coordA = model.Coord(cid)
00322         # converting the xyz point arbitrary->global
00323         p,matrixDum = self.cp.transformToGlobal(self.xyz, debug=debug)
00324         #print "wrt = ",p
00325         coordB = model.Coord(cid)
00326         
00327         # a matrix global->local matrix is found
00328         pdum,matrix = coordB.transformToGlobal(array([1.,0.,0]), debug=debug)
00329         p2          = coordB.transformToLocal(p, matrix, debug=debug)
00330         return p2
00331 
00332     def crossReference(self, model, grdset=None):
00333         """
00334         the gridset object will only update the fields that have not been set
00335         """
00336         #print str(self)
00337         if grdset: # update using a gridset object
00338             if not self.cp:   self.cp   = grdset.cp
00339             if not self.cd:   self.cd   = grdset.cd
00340             if not self.ps:   self.ps   = grdset.ps
00341             if not self.seid: self.seid = grdset.seid
00342         self.cp = model.Coord(self.cp)
00343         if self.cd != -1:
00344             self.cd = model.Coord(self.cd)
00345         #self.xyzGlobal = coord.transformToGlobal(self.xyz)
00346 
00347     def rawFields(self):
00348         fields = ['GRID', self.nid, self.Cp()]+list(self.xyz)+[self.Cd(), self.ps, self.Seid()]
00349         return fields
00350 
00351     def reprFields(self):
00352         cp   = set_blank_if_default(self.Cp(), 0)
00353         cd   = set_blank_if_default(self.Cd(), 0)
00354         seid = set_blank_if_default(self.Seid(), 0)
00355         fields = ['GRID', self.nid, cp]+list(self.xyz)+[cd, self.ps, seid]
00356         return fields
00357 
 All Classes Namespaces Files Functions Variables