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 00026 from __future__ import division, print_function 00027 #import sys 00028 from struct import unpack 00029 00030 from .opg_Objects import AppliedLoadsObject #ComplexAppliedLoadsObject 00031 from .opg_loadVector import LoadVectorObject, ComplexLoadVectorObject, ThermalLoadVectorObject 00032 from .opnl_forceVector import ForceVectorObject, ComplexForceVectorObject 00033 00034 # OGS table ## @todo move this... 00035 from ..ogf_gridPointForces.ogs_surfaceStresses import GridPointStressesObject,GridPointStressesVolumeObject 00036 00037 class OPG(object): 00038 """Table of element forces""" 00039 def readTable_OPG(self): 00040 table3 = self.readTable_OPG_3 00041 table4Data = self.readOPG_Data 00042 self.readResultsTable(table3,table4Data) 00043 self.deleteAttributes_OPG() 00044 00045 def deleteAttributes_OPG(self): 00046 params = ['lsdvm', 'mode', 'eigr', 'eign', 'eigi', 'modeCycle', 'freq', 00047 'time', 'lftsfq', 'dLoadID', 'formatCode', 'numWide','oCode'] 00048 self.deleteAttributes(params) 00049 00050 def readTable_OPG_3(self, iTable): # iTable=-3 00051 bufferWords = self.getMarker() 00052 #print "2-bufferWords = ",bufferWords,bufferWords*4,'\n' 00053 00054 data = self.getData(4) 00055 bufferSize, = unpack(b'i',data) 00056 data = self.getData(4*50) 00057 00058 #self.printBlock(data) 00059 00060 00061 aCode = self.getBlockIntEntry(data,1) 00062 #print "aCode = ",aCode 00063 self.parseApproachCode(data) 00064 #iSubcase = self.getValues(data,'i',4) 00065 00066 self.addDataParameter(data,'dLoadID', 'i', 8, False) ## dynamic load set ID/random code 00067 self.addDataParameter(data,'formatCode', 'i', 9, False) ## format code 00068 self.addDataParameter(data,'numWide', 'i', 10, False) ## number of words per entry in record; @note is this needed for this table ??? 00069 self.addDataParameter(data,'oCode', 'i', 11, False) ## undefined in DMAP... 00070 self.addDataParameter(data,'thermal', 'i', 23, False) ## thermal flag; 1 for heat ransfer, 0 otherwise 00071 00072 #print "dLoadID(8)=%s formatCode(9)=%s numWide(10)=%s oCode(11)=%s thermal(23)=%s" %(self.dLoadID,self.formatCode,self.numWide,self.oCode,self.thermal) 00073 if not self.isSort1(): 00074 raise NotImplementedError('sort2...') 00075 #assert self.isThermal()==False,self.thermal 00076 00077 ## assuming tCode=1 00078 if self.analysisCode == 1: # statics 00079 self.addDataParameter(data, 'lsdvmn', 'i', 5, False) ## load set number 00080 self.applyDataCodeValue('dataNames', ['lsdvmn']) 00081 self.setNullNonlinearFactor() 00082 elif self.analysisCode == 2: # normal modes/buckling (real eigenvalues) 00083 self.addDataParameter(data,'mode', 'i', 5) ## mode number 00084 self.addDataParameter(data, 'eign', 'f', 6, False) ## real eigenvalue 00085 self.addDataParameter(data, 'modeCycle', 'f', 7, False) ## mode or cycle @todo confused on the type - F1??? 00086 self.applyDataCodeValue('dataNames', ['mode', 'eign', 'modeCycle']) 00087 #elif self.analysisCode == 3: # differential stiffness 00088 # self.lsdvmn = self.getValues(data,'i',5) ## load set number 00089 #elif self.analysisCode == 4: # differential stiffness 00090 # self.lsdvmn = self.getValues(data,'i',5) ## load set number 00091 elif self.analysisCode == 5: # frequency 00092 self.addDataParameter(data,'freq', 'f', 5) ## frequency 00093 self.applyDataCodeValue('dataNames', ['freq']) 00094 elif self.analysisCode == 6: # transient 00095 self.addDataParameter(data,'time', 'f', 5) ## time step 00096 self.applyDataCodeValue('dataNames', ['time']) 00097 elif self.analysisCode == 7: # pre-buckling 00098 self.addDataParameter(data,'lsdvmn', 'i', 5) ## load set number 00099 self.applyDataCodeValue('dataNames', ['lsdvmn']) 00100 elif self.analysisCode == 8: # post-buckling 00101 self.addDataParameter(data,'lsdvmn', 'i', 5) ## load set number 00102 self.addDataParameter(data,'eigr', 'f', 6, False) ## real eigenvalue 00103 self.applyDataCodeValue('dataNames', ['lsdvmn', 'eigr']) 00104 elif self.analysisCode == 9: # complex eigenvalues 00105 self.addDataParameter(data, 'mode', 'i', 5) ## mode number 00106 self.addDataParameter(data, 'eigr', 'f', 6, False) ## real eigenvalue 00107 self.addDataParameter(data, 'eigi', 'f', 7, False) ## imaginary eigenvalue 00108 self.applyDataCodeValue('dataNames',['mode','eigr','eigi']) 00109 elif self.analysisCode == 10: # nonlinear statics 00110 self.addDataParameter(data,'lftsfq','f',5) ## load step 00111 self.applyDataCodeValue('dataNames',['lftsfq']) 00112 elif self.analysisCode == 11: # old geometric nonlinear statics 00113 self.addDataParameter(data, 'lsdvmn', 'i', 5) ## load set number 00114 self.applyDataCodeValue('dataNames', ['lsdvmn']) 00115 elif self.analysisCode == 12: # contran ? (may appear as aCode=6) --> straight from DMAP...grrr... 00116 self.addDataParameter(data,'lsdvmn', 'i', 5) ## load set number 00117 self.applyDataCodeValue('dataNames', ['lsdvmn']) 00118 else: 00119 raise RuntimeError('invalid analysisCode...analysisCode=%s' %(self.analysisCode)) 00120 ### 00121 # tCode=2 00122 #if self.analysisCode==2: # sort2 00123 # self.lsdvmn = self.getValues(data,'i',5) ## load set, Mode number 00124 00125 #print "*iSubcase=%s"%(self.iSubcase) 00126 #print "analysisCode=%s tableCode=%s thermal=%s" %(self.analysisCode,self.tableCode,self.thermal) 00127 #print self.codeInformation() 00128 00129 if not self.isSort1(): 00130 raise NotImplementedError('sort2...') 00131 00132 #self.printBlock(data) 00133 self.readTitle() 00134 00135 def readOPG_Data(self): 00136 #print "self.analysisCode=%s tableCode(1)=%s thermal(23)=%g" %(self.analysisCode,self.tableCode,self.thermal) 00137 #tfsCode = [self.tableCode,self.formatCode,self.sortCode] 00138 self.atfsCode = [self.analysisCode,self.tableCode,self.formatCode,self.sortCode] 00139 00140 00141 if self.tableCode == 19: 00142 assert self.tableName in [None],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00143 self.readOPG_Data_table19() # grid point force balance 00144 elif self.tableCode == 2: # load vector 00145 assert self.tableName in ['OPG1','OPGV1'],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00146 self.readOPG_Data_table2() 00147 elif self.tableCode == 12: # nonlinear force vector 00148 assert self.tableName in ['OPNL1'],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00149 self.readOPG_Data_table12() 00150 elif self.tableCode == 26: # OGS1 - grid point stresses - surface 00151 assert self.tableName in ['OGS1'],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00152 self.readOGS1_Data_table26() 00153 elif self.tableCode == 27: # OGS1 - grid point stresses - volume direct 00154 assert self.tableName in ['OGS1'],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00155 self.readOGS1_Data_table27() 00156 00157 #elif self.tableCode == 28: # OGS1- grid point stresses - principal 00158 #assert self.tableName in ['OGS1'],'tableName=%s tableCode=%s' %(self.tableName,self.tableCode) 00159 #self.readOGS1_Data_table28() 00160 #self.NotImplementedOrSkip() 00161 00162 #elif self.tableCode == 35: # OGS - Grid point stress discontinuities (plane strain) 00163 #self.NotImplementedOrSkip() 00164 00165 # OFMPF2M - does this belong here? 00166 #elif tfsCode==[51,3,3]: 00167 # self.readOPG_Data_format3_sort3() 00168 00169 # OSMPF2M - does this belong here? 00170 #elif tfsCode==[52,3,3]: 00171 # self.readOPG_Data_format3_sort3() 00172 00173 # OPMPF2M - does this belong here? 00174 #elif tfsCode==[53,3,3]: 00175 # self.readOPG_Data_format3_sort3() 00176 00177 # OLMPF2M - does this belong here? 00178 #elif tfsCode==[54,3,3]: 00179 # self.readOPG_Data_format3_sort3() 00180 00181 # OGMPF2M - does this belong here? 00182 #elif tfsCode==[55,3,3]: 00183 # self.readOPG_Data_format3_sort3() 00184 else: 00185 self.NotImplementedOrSkip('bad tableCode/formatCode/sortCode=%s on %s-OPG table' %(self.atfsCode,self.tableName)) 00186 ### 00187 #print self.obj 00188 00189 def readOPG_Data_table2(self): # Load Vector 00190 #isSort1 = self.isSort1() 00191 #print "********\n",self.codeInformation() 00192 if self.numWide==8: # real/random 00193 if self.thermal==0: 00194 resultName = 'loadVectors' 00195 self.createTransientObject(self.loadVectors,LoadVectorObject) # real 00196 self.handleResultsBuffer3(self.OUG_RealTable,resultName) 00197 elif self.thermal==1: 00198 resultName = 'thermalLoadVectors' 00199 self.createTransientObject(self.thermalLoadVectors,ThermalLoadVectorObject) # real 00200 self.handleResultsBuffer3(self.OUG_RealTable,resultName) 00201 else: 00202 self.NotImplementedOrSkip() 00203 elif self.numWide==14: # real/imaginary or mag/phase 00204 if self.thermal==0: 00205 resultName = 'loadVectors' 00206 self.createTransientObject(self.loadVectors,ComplexLoadVectorObject) # complex 00207 self.handleResultsBuffer3(self.OUG_ComplexTable,resultName) 00208 else: 00209 self.NotImplementedOrSkip() 00210 else: 00211 raise RuntimeError('only numWide=8 or 14 is allowed numWide=%s' %(self.numWide)) 00212 00213 def readOPG_Data_table12(self): # Nonlinear Force Vector (in progress) 00214 #isSort1 = self.isSort1() 00215 if self.numWide==8: # real/random 00216 if self.thermal==0: 00217 resultName = 'forceVectors' 00218 self.createTransientObject(self.forceVectors,ForceVectorObject) # real 00219 self.handleResultsBuffer3(self.OUG_RealTable,resultName) 00220 else: 00221 self.NotImplementedOrSkip() 00222 elif self.numWide==14: # real/imaginary or mag/phase 00223 if self.thermal==0: 00224 resultName = 'forceVectors' 00225 self.createTransientObject(self.forceVectors,ComplexForceVectorObject) # complex 00226 self.handleResultsBuffer3(self.OUG_ComplexTable,resultName) 00227 else: 00228 self.NotImplementedOrSkip() 00229 else: 00230 raise RuntimeError('only numWide=8 or 14 is allowed numWide=%s' %(self.numWide)) 00231 00232 def readOPG_Data_table19(self): # Applied Loads 00233 #isSort1 = self.isSort1() 00234 if self.numWide == 8: # real/random 00235 resultName = 'appliedLoads' 00236 if self.thermal == 0: 00237 self.createTransientObject(self.appliedLoads,AppliedLoadsObject) # real 00238 self.handleResultsBuffer3(self.readOPGForces,resultName) 00239 else: 00240 self.NotImplementedOrSkip() 00241 #elif self.numWide == 14: # real/imaginary or mag/phase 00242 # if self.thermal == 0: 00243 # self.createTransientObject(self.appliedLoads,ComplexAppliedLoadsObject) # complex 00244 # raise NotImplementedError('can this use a OUG_Complex table???') 00245 # else: 00246 # raise NotImplementedError(self.codeInformation()) 00247 # #self.handleResultsBuffer3(self.OUG_ComplexTable,resultName) 00248 # raise NotImplementedError(self.codeInformation()) 00249 else: 00250 raise RuntimeError('only numWide=8 or 14 is allowed numWide=%s' %(self.numWide)) 00251 00252 def readOGS1_Data_table26(self): # OGS1 - grid point stresses - surface 00253 #isSort1 = self.isSort1() 00254 resultName = 'gridPointStresses' 00255 if self.numWide==11: # real/random 00256 self.createTransientObject(self.gridPointStresses,GridPointStressesObject) # real 00257 self.handleResultsBuffer3(self.readOGS1_table26_numWide11,resultName) 00258 else: 00259 raise RuntimeError('only numWide=11 is allowed numWide=%s' %(self.numWide)) 00260 00261 def readOGS1_table26_numWide11(self): # surface stresses 00262 dt = self.nonlinearFactor 00263 (format1,extract) = self.getOEF_FormatStart() 00264 format1 += 'i4s8f' 00265 format1 = bytes(format1) 00266 00267 while len(self.data) >= 44: 00268 eData = self.data[0:44] 00269 self.data = self.data[44: ] # 11*4 00270 out = unpack(format1,eData) 00271 (eKey,eid,fiber,nx,ny,txy,angle,major,minor,tmax,ovm) = out 00272 eKey = extract(eKey,dt) 00273 fiber = fiber.strip() 00274 self.obj.add(dt,eKey,eid,fiber,nx,ny,txy,angle,major,minor,tmax,ovm) 00275 #print len(self.data) 00276 00277 def readOGS1_Data_table27(self): # OGS1 - grid point stresses - volume direct 00278 #isSort1 = self.isSort1() 00279 #print(self.codeInformation()) 00280 if self.numWide == 9: # real/random 00281 resultName = 'gridPointVolumeStresses' 00282 self.createTransientObject(self.gridPointVolumeStresses,GridPointStressesVolumeObject) # real 00283 self.handleResultsBuffer3(self.readOGS1_table27_numWide9,resultName) 00284 else: 00285 raise RuntimeError('only numWide=9 is allowed numWide=%s' %(self.numWide)) 00286 00287 def readOGS1_table27_numWide9(self): # surface stresses 00288 dt = self.nonlinearFactor 00289 (format1,extract) = self.getOEF_FormatStart() 00290 format1 += 'i7f' 00291 format1 = bytes(format1) 00292 00293 while len(self.data) >= 36: 00294 eData = self.data[0:36] 00295 self.data = self.data[36: ] # 9*4 00296 out = unpack(format1,eData) 00297 (eKey,nx,ny,nz,txy,tyz,txz,pressure,ovm) = out 00298 eKey = extract(eKey,dt) 00299 00300 self.obj.add(dt,eKey,nx,ny,nz,txy,tyz,txz,pressure,ovm) 00301 #print len(self.data) 00302 00303 00304 def readOPGForces(self): ## @todo needs some work... 00305 raise RuntimeError('this should never been called...') 00306 dt = self.nonlinearFactor 00307 (format1,extract) = self.getOUG_FormatStart() 00308 format1 += 'i' 00309 format1 = bytes(format1) 00310 00311 #nTotal = self.numWide*4 00312 nTotal = 40 # same as dn 00313 while len(data)>dn: 00314 #print "len(data) = ",len(data) 00315 eData = self.data[0:dn] 00316 #self.printBlock(data[:dn]) 00317 (gridDevice,eid) = unpack(format1,data[0:8]) 00318 nodeID = extract(gridDevice,dt) 00319 00320 source = unpack(b'8s',data[8:16]) 00321 (dx,dy,dz,rx,ry,rz) = unpack(b'6f',data[16:40]) 00322 #print "source = |%s|" %(source) 00323 00324 #print "nodeID=%s eid=%s source=|%s| dx=%-4i dy=%-4i dz=%-4i rx=%-4i ry=%-4i rz=%-4i" %(nodeID,eid,source,dx,dy,dz,rx,ry,rz) 00325 source2 = source.replace('*','').replace('-','').strip() 00326 assert source2.isalnum(), 'source=|%s| contains invalid characters...' % (source) 00327 00328 self.obj.add(nodeID,eid,source,dx,dy,dz,rx,ry,rz) 00329 #print "gridDevice = ",gridDevice 00330 #print "deviceCode = ",deviceCode 00331 #print "nodeID=%g dx=%g dy=%g dz=%g rx=%g ry=%g rz=%g" %(nodeID,xGrad,yGrad,zGrad,xFlux,yFlux,zFlux) 00332 self.data = self.data[dn:] 00333 ### 00334 #print "***********" 00335 #print self.obj 00336