pyNastran
0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
|
00001 ## GNU Lesser General Public License 00002 ## 00003 ## Program pyNastran - a python interface to NASTRAN files 00004 ## Copyright (C) 2011-2012 Steven Doyle, Al Danial 00005 ## 00006 ## Authors and copyright holders of pyNastran 00007 ## Steven Doyle <mesheb82@gmail.com> 00008 ## Al Danial <al.danial@gmail.com> 00009 ## 00010 ## This file is part of pyNastran. 00011 ## 00012 ## pyNastran is free software: you can redistribute it and/or modify 00013 ## it under the terms of the GNU Lesser General Public License as published by 00014 ## the Free Software Foundation, either version 3 of the License, or 00015 ## (at your option) any later version. 00016 ## 00017 ## pyNastran is distributed in the hope that it will be useful, 00018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 ## GNU General Public License for more details. 00021 ## 00022 ## You should have received a copy of the GNU Lesser General Public License 00023 ## along with pyNastran. If not, see <http://www.gnu.org/licenses/>. 00024 ## 00025 # pylint: disable=C0103,R0902,R0904,R0914 00026 00027 from __future__ import division, print_function 00028 #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