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,W0201,W0223,R0901,R0902,R0904 00026 00027 from __future__ import division, print_function 00028 import os 00029 import sys 00030 from numpy import array 00031 from struct import unpack 00032 00033 from pyNastran.op2.fortranFile import FortranFile 00034 from pyNastran.op2.op2Codes import Op2Codes 00035 from pyNastran.op2.op2Errors import (EndOfFileError, InvalidMarkersError, 00036 TapeCodeError) 00037 00038 from pyNastran.op2.tables.resultTable import ResultTable 00039 from pyNastran.op2.tables.geom.geometryTables import GeometryTables 00040 00041 from pyNastran.bdf.bdf import BDF 00042 from pyNastran.f06.f06Writer import F06Writer 00043 from pyNastran.f06.matlabWriter import MatlabWriter 00044 00045 class OP2(BDF, 00046 FortranFile, Op2Codes, GeometryTables, ResultTable, F06Writer, 00047 MatlabWriter): 00048 00049 def setSubcases(self, iSubcases=None): 00050 """ 00051 Allows you to read only the subcases in the list of iSubcases 00052 @param iSubcases 00053 list of [subcase1_ID,subcase2_ID] (default=None; all subcases) 00054 """ 00055 ## stores the set of all subcases that are in the OP2 00056 self.subcases = set() 00057 if iSubcases is None or iSubcases==[]: 00058 ## stores if the user entered [] for iSubcases 00059 self.isAllSubcases = True 00060 self.validSubcases = [] 00061 else: 00062 ## should all the subcases be read (default=True) 00063 self.isAllSubcases = False 00064 ## the set of valid subcases -> set([1,2,3]) 00065 self.validSubcases = set(iSubcases) 00066 self.log.debug("setSubcases - iSubcases = %s" % (self.validSubcases)) 00067 00068 def isValidSubcase(self): 00069 """ 00070 lets the code check whether or not to read a subcase 00071 """ 00072 if not self.isAllSubcases: 00073 if self.iSubcase in self.validSubcases: 00074 return True 00075 return False 00076 return True 00077 00078 def __init__(self, op2FileName, makeGeom=False, debug=True, log=None): 00079 """ 00080 Initializes the Op2 object 00081 @param op2FileName 00082 the file to be parsed 00083 @param makeGeom 00084 reads the BDF tables (default=False) 00085 @param debug 00086 prints data about how the OP2 was parsed (default=False) 00087 @param log 00088 a logging object to write debug messages to (@see import logging) 00089 """ 00090 BDF.__init__(self, debug=debug, log=log) 00091 self.setSubcases() # initializes the variables 00092 self.log.debug('op2FileName = %s' % (op2FileName)) 00093 bdfExtension = '.bdf' 00094 f06Extension = '.f06' 00095 (fname, extension) = os.path.splitext(op2FileName) 00096 self.tableName = 'temp' 00097 00098 ## should the BDF tables be parsed 00099 self.makeGeom = makeGeom 00100 00101 ## the input OP2 filename 00102 self.op2FileName = op2FileName 00103 00104 ## the expected BDF filename (guessed) 00105 self.bdfFileName = fname+bdfExtension 00106 00107 ## the expected F06 filename (guessed) 00108 self.f06FileName = fname+f06Extension 00109 #print "bdfFileName = ",self.bdfFileName 00110 00111 ## developer parameter to write the OP2 is ASCII format 00112 ## to better understand it 00113 self.makeOp2Debug = False 00114 00115 ## BDF Title 00116 self.Title = '' 00117 ## limit output DTs 00118 self.expectedTimes = {} 00119 #self.expectedTimes = {1:array([0.1,0.12])} 00120 00121 ## file object containing the skipped cards 00122 self.skippedCardsFile = open('skippedCards.out','a') 00123 00124 ## the list of supported tables (dont edit this) 00125 self.tablesToRead = [ 00126 'GEOM1', 'GEOM2', 'GEOM3', 'GEOM4', # nodes/geometry/loads/BCs 00127 'GEOM1S','GEOM2S','GEOM3S','GEOM4S', # nodes/geometry/loads/BCs - superelements 00128 'GEOM1OLD','GEOM1N', #??? 00129 'EPT', 'MPT', # properties/materials 00130 'EPTS','MPTS', # properties/materials - superelements 00131 'EDTS', # ??? 00132 'DYNAMIC','DYNAMICS', 00133 'DIT', # tables (e.g. TABLED1) 00134 'LAMA','BLAMA', # eigenvalues 00135 00136 'BGPDT','BGPDTS', # boundary grids??? 00137 'EQEXIN','EQEXINS','PVT0','CASECC','EDOM', 00138 'DESTAB', # design variables 00139 'OQG1','OQGV1', # spc forces 00140 'OQMG1', # mpc forces 00141 00142 'OUGV1', # displacements 00143 'OGPFB1', # grid point forces 00144 'OGS1', # grid point stresses 00145 00146 'OEF1X', 'DOEF1','OEFIT', # element forces 00147 'OPG1','OPGV1','OPNL1', # applied forces 00148 'OES1','OES1X','OES1X1','OES1C', # stress 00149 'OSTR1C','OSTR1X', # strains 00150 'OESNLXR','OESNLXD','OESNL1X','OESNLBR', # nonlinear stress 00151 00152 'OESCP', # cylinder stress??? 00153 'OESTRCP', # cylinder strain??? 00154 'OESRT', # rotational stress? 00155 00156 'ONRGY1', # energy 00157 'ONRGY2', # energy (sort2, unsupported) 00158 00159 'R1TABRG','HISADD', # SOL 200 00160 00161 # unsupported frequency results 00162 'OAGPSD2', 'OAGATO2', 'OAGRMS2', 'OAGNO2', 'OAGCRM2', 00163 'OEFPSD2', 'OEFATO2', 'OEFRMS2', 'OEFNO2', 'OEFCRM2', 00164 'OESPSD2', 'OESATO2', 'OESRMS2', 'OESNO2', 'OESCRM2', 00165 'OPGPSD2', 'OPGATO2', 'OPGRMS2', 'OPGNO2', 'OPGCRM2', 00166 'OQGPSD2', 'OQGATO2', 'OQGRMS2', 'OQGNO2', 'OQGCRM2', 00167 00168 # supported-ish 00169 'OQMPSD2', 'OQMATO2', 'OQMRMS2', 'OQMNO2', 'OQMCRM2', 00170 'OSTRPSD2','OSTRATO2','OSTRRMS2','OSTRNO2','OSTRCRM2', 00171 'OUGPSD2', 'OUGATO2', 'OUGCRM2', 'OUGNO2', 'OUGRMS2', 00172 'OVGPSD2', 'OVGATO2', 'OVGRMS2', 'OVGNO2', 'OVGCRM2', 00173 00174 ## @todo what do these do??? 00175 'OUPV1', 00176 'VIEWTB','ERRORN', 00177 'OFMPF2M','OSMPF2M','OPMPF2M','OGPMPF2M','OLMPF2M', 00178 'PCOMPTS', 00179 'OMM2', 00180 'EDOM', 00181 'STDISP','SDF','MONITOR','AEMONPT', 00182 'OGPWG', # grid point weight 00183 'OQP1', 00184 'OCRUG','OCRPG', 00185 00186 # new 00187 'AFRF', 'AGRF', 00188 'PMRF','PERF','PFRF', 00189 'FOL', 00190 ] 00191 00192 ## a dictionary that maps an integer of the subcaseName to the 00193 ## subcaseID 00194 self.iSubcaseNameMap = {} 00195 00196 ## list of OP2 tables that were read 00197 ## mainly for debugging 00198 self.tableNames = [] 00199 00200 self.__objectsInit__() 00201 00202 def __objectsInit__(self): 00203 ## ESE 00204 self.eigenvalues = {} 00205 00206 ## OUG - displacement 00207 self.displacements = {} # tCode=1 thermal=0 00208 self.displacementsPSD = {} # random 00209 self.displacementsATO = {} # random 00210 self.displacementsRMS = {} # random 00211 self.displacementsCRM = {} # random 00212 self.displacementsNO = {} # random 00213 self.scaledDisplacements = {} # tCode=1 thermal=8 00214 00215 ## OUG - temperatures 00216 self.temperatures = {} # tCode=1 thermal=1 00217 00218 ## OUG - eigenvectors 00219 self.eigenvectors = {} # tCode=7 thermal=0 00220 00221 ## OUG - velocity 00222 self.velocities = {} # tCode=10 thermal=0 00223 00224 ## OUG - acceleration 00225 self.accelerations = {} # tCode=11 thermal=0 00226 00227 # OEF - Forces - tCode=4 thermal=0 00228 self.rodForces = {} 00229 self.barForces = {} 00230 self.bar100Forces = {} 00231 self.beamForces = {} 00232 self.bendForces = {} 00233 self.bushForces = {} 00234 self.coneAxForces = {} 00235 self.damperForces = {} 00236 self.gapForces = {} 00237 self.plateForces = {} 00238 self.plateForces2 = {} 00239 self.shearForces = {} 00240 self.solidPressureForces = {} 00241 self.springForces = {} 00242 self.viscForces = {} 00243 00244 self.force_VU = {} 00245 self.force_VU_2D = {} 00246 00247 #OEF - Fluxes - tCode=4 thermal=1 00248 self.thermalLoad_CONV = {} 00249 self.thermalLoad_CHBDY = {} 00250 self.thermalLoad_1D = {} 00251 self.thermalLoad_2D_3D = {} 00252 self.thermalLoad_VU = {} 00253 self.thermalLoad_VU_3D = {} 00254 self.thermalLoad_VUBeam = {} 00255 #self.temperatureForces = {} # aCode=1 tCode=4 fCode=1 sortCode=0 thermal=1 00256 00257 # OES - tCode=5 thermal=0 sCode=0,1 (stress/strain) 00258 ## OES - CELAS1/CELAS2/CELAS3/CELAS4 stress 00259 self.celasStress = {} 00260 ## OES - CELAS1/CELAS2/CELAS3/CELAS4 strain 00261 self.celasStrain = {} 00262 00263 ## OES - CTRIAX6 00264 self.ctriaxStress = {} 00265 self.ctriaxStrain = {} 00266 00267 ## OES - isotropic CROD/CONROD/CTUBE stress 00268 self.rodStress = {} 00269 ## OES - isotropic CROD/CONROD/CTUBE strain 00270 self.rodStrain = {} 00271 ## OES - nonlinear CROD/CONROD/CTUBE stress 00272 self.nonlinearRodStress = {} 00273 ## OES - nonlinear CROD/CONROD/CTUBE strain 00274 self.nonlinearRodStrain = {} 00275 ## OES - isotropic CBAR stress 00276 self.barStress = {} 00277 ## OES - isotropic CBAR strain 00278 self.barStrain = {} 00279 ## OES - isotropic CBEAM stress 00280 self.beamStress = {} 00281 ## OES - isotropic CBEAM strain 00282 self.beamStrain = {} 00283 00284 ## OES - isotropic CTRIA3/CQUAD4 stress 00285 self.plateStress = {} 00286 ## OES - isotropic CTRIA3/CQUAD4 strain 00287 self.plateStrain = {} 00288 ## OESNLXR - CTRIA3/CQUAD4 stress 00289 self.nonlinearPlateStress = {} 00290 ## OESNLXR - CTRIA3/CQUAD4 strain 00291 self.nonlinearPlateStrain = {} 00292 self.hyperelasticPlateStress = {} 00293 self.hyperelasticPlateStrain = {} 00294 00295 ## OES - isotropic CTETRA/CHEXA/CPENTA stress 00296 self.solidStress = {} 00297 ## OES - isotropic CTETRA/CHEXA/CPENTA strain 00298 self.solidStrain = {} 00299 ## OES - composite CTRIA3/CQUAD4 stress 00300 self.compositePlateStress = {} 00301 ## OES - composite CTRIA3/CQUAD4 strain 00302 self.compositePlateStrain = {} 00303 00304 ## OES - CSHEAR stress 00305 self.shearStress = {} 00306 ## OES - CSHEAR strain 00307 self.shearStrain = {} 00308 00309 00310 # OQG - spc/mpc forces 00311 self.spcForces = {} # tCode=3? 00312 self.mpcForces = {} # tCode=39 00313 00314 ## OGF - grid point forces 00315 self.gridPointForces = {} # tCode=19 00316 00317 ## OGS1 - grid point stresses 00318 self.gridPointStresses = {} # tCode=26 00319 self.gridPointVolumeStresses = {} # tCode=27 00320 00321 ## OPG - summation of loads for each element 00322 self.loadVectors = {} # tCode=2 thermal=0 00323 self.thermalLoadVectors = {} # tCode=2 thermal=1 00324 self.appliedLoads = {} # tCode=19 thermal=0 00325 self.forceVectors = {} # tCode=12 thermal=0 00326 00327 ## OEE - strain energy density 00328 self.strainEnergy = {} # tCode=18 00329 00330 def readTapeCode2(self): 00331 data = self.op2.read(28) 00332 (f1, two, f2, f3, tableName, f4) = unpack('4i8si', data) 00333 #print("tableName = ",tableName) 00334 #data = self.op2.read(16) 00335 #print(self.printSection(200)) 00336 00337 sys.exit('') 00338 00339 def readTapeCode(self): 00340 """ 00341 Reads the OP2 header. This table is still very much in development. 00342 @todo whats in this table? 00343 """ 00344 #self.printSection(500) 00345 #sys.exit('op2-readTapeCode') 00346 00347 if 0: # param post 0 00348 marker = 0 00349 #print self.printSection(200) 00350 sys.exit('stopping in readTapeCode in op2.py') 00351 while marker != -1: 00352 ints = self.readIntBlock() 00353 marker = ints[0] 00354 #print "ints1 = ",ints 00355 #print "" 00356 00357 while marker != -2: 00358 ints = self.readIntBlock() 00359 marker = ints[0] 00360 #print "ints2 = ",ints 00361 #print "" 00362 while marker != -3: 00363 ints = self.readIntBlock() 00364 marker = ints[0] 00365 #print "ints3 = ",ints 00366 #print "" 00367 while marker != -4: 00368 ints = self.readIntBlock() 00369 marker = ints[0] 00370 #print "ints4 = ",ints 00371 #print "" 00372 #while marker != -1: 00373 #ints = self.readIntBlock() 00374 #marker = ints[0] 00375 #print "ints1 = ",ints 00376 #print "" 00377 self.readMarkers([2]) 00378 00379 #print self.printSection(200) 00380 ints2 = self.readIntBlock() 00381 ints3 = self.readIntBlock() 00382 #print "ints2 = ",ints2 00383 #print "ints3 = ",ints3 00384 sys.exit('stopping...') 00385 00386 self.readMarkers([3]) 00387 #print(self.printSection(20)) 00388 ints = self.readIntBlock() 00389 if self.makeOp2Debug: 00390 self.op2Debug.write('%s\n' %(str(ints))) 00391 #print "*ints = ",ints 00392 self.readMarkers([7]) 00393 00394 word = self.readStringBlock() # Nastran Fort Tape ID Code - 00395 #print "word = |%r|" %(word) 00396 00397 self.readMarkers([2]) 00398 ints = self.readIntBlock() 00399 #print "*ints = ",ints 00400 00401 self.readMarkers([-1]) 00402 00403 #data = self.getData(60) 00404 #self.printBlock(data) 00405 00406 def readOP2(self): 00407 """ 00408 reads the op2 file 00409 """ 00410 ## the OP2 file object 00411 self.op2 = open(self.op2FileName,'rb') 00412 00413 if self.makeOp2Debug: 00414 ## a developer debug file (largely unsupported) 00415 self.op2Debug = open('debug.out','wb') 00416 ## the byte position in the OP2 00417 self.n = self.op2.tell() 00418 00419 try: 00420 self.readTapeCode() 00421 except: 00422 msg = 'When this happens, the analysis failed or the code bombed...check the F06.\n' 00423 msg += ' If the F06 is OK:\n' 00424 msg += ' 1. Make sure you used PARAM,POST,-1 in your BDF/DAT/NAS\n' 00425 msg += ' 2. Run the problem on a different Operating System\n' 00426 msg += ' 3. Are you running an OP2? :) \nfname=%s' %(self.op2FileName) 00427 raise TapeCodeError(msg) 00428 00429 isAnotherTable = True 00430 while isAnotherTable: 00431 self.log.debug('-'*80) 00432 try: 00433 tableName = self.readTableName(rewind=True, stopOnFailure=False) 00434 print("tableName = %s" %(tableName)) 00435 except EndOfFileError: # the isAnotherTable method sucks... 00436 isAnotherTable = False 00437 self.log.debug("***ok exit, but it could be better...") 00438 break 00439 except InvalidMarkersError: # the isAnotherTable method sucks... 00440 isAnotherTable = False 00441 self.log.debug("***poor exit, but it worked...") 00442 #raise 00443 break 00444 except: 00445 raise 00446 self.log.debug("tableName = |%r|" % (tableName)) 00447 #print("tableName = |%r|" %(tableName)) 00448 00449 if tableName == None: 00450 break 00451 else: 00452 isAnotherTable = self.readTable(tableName) 00453 ### 00454 00455 self.log.debug("---end of all tables---") 00456 self.skippedCardsFile.close() 00457 00458 def readTable(self, tableName): 00459 if tableName in self.tablesToRead: 00460 self.tableName = tableName 00461 self.isRegular = True 00462 try: 00463 #print("startTell = %s" %(self.op2.tell())) 00464 if tableName == 'GEOM1': # nodes,coords,etc. 00465 self.readTable_Geom1() 00466 elif tableName == 'GEOM1S': # superelements - nodes,coords,etc. 00467 self.readTable_Geom1S() 00468 elif tableName == 'GEOM2S': # superelements - elements 00469 self.readTable_Geom2S() 00470 elif tableName == 'GEOM3S': # superelements - static/thermal loads 00471 self.readTable_Geom3S() 00472 elif tableName == 'GEOM4S': # superelements - constraints 00473 self.readTable_Geom4S() 00474 00475 #elif tableName=='GEOM1OLD': 00476 # self.readTable_Geom1Old() 00477 #elif tableName=='GEOM1N': 00478 # self.readTable_Geom1N() 00479 elif tableName == 'GEOM2': # elements 00480 self.readTable_Geom2() 00481 elif tableName == 'GEOM3': # static/thermal loads 00482 self.readTable_Geom3() 00483 elif tableName == 'GEOM4': # constraints 00484 self.readTable_Geom4() 00485 00486 elif tableName in ['EPT', 'EPTS']: # element properties 00487 self.readTable_EPT() 00488 elif tableName in ['MPT', 'MPTS']: # material properties 00489 self.readTable_MPTS() 00490 elif tableName in ['DYNAMIC', 'DYNAMICS']: # dyanmic info 00491 self.readTable_DYNAMICS() 00492 elif tableName in ['DIT']: # tables...TABLED1/TABLEM1/TABLES1/GUST 00493 self.readTable_DIT() 00494 elif tableName in ['LAMA', 'BLAMA']: # eigenvalue 00495 self.readTable_LAMA() 00496 00497 elif tableName in ['VIEWTB', 'EQEXIN', 'EQEXINS', 'OEFIT', 00498 'GEOM1N', 'OGPWG','GEOM1OLD']: 00499 self.readTable_DUMMY_GEOM(tableName) 00500 elif tableName in ['OMM2']: 00501 self.readTable_OMM2() 00502 elif tableName in ['DESTAB']: # design variable table 00503 self.readTable_DesTab() 00504 elif tableName in ['R1TABRG']: # not done - response table 00505 self.readTable_R1TAB() 00506 self.isOptimization = True 00507 elif tableName in ['HISADD']: # not done 00508 self.readTable_R1TAB() 00509 self.isOptimization = True 00510 elif tableName in ['ERRORN']: # not done 00511 self.readTable_R1TAB() 00512 00513 elif tableName in ['OPG1', 'OPNL1', 'OGS1', 'OPGV1']: 00514 self.readTable_OPG() # table of applied loads 00515 elif tableName in ['OGPFB1',]: 00516 self.readTable_OGF() 00517 elif tableName in ['OCRUG','OCRPG']: # totally guessing... 00518 self.readTable_OUG() 00519 00520 00521 elif tableName in ['OEF1X','DOEF1', 'OEFPSD2', 'OEFATO2', 00522 'OEFRMS2','OEFNO2','OEFCRM2',]: 00523 self.readTable_OEF() # applied loads 00524 elif tableName in ['OQG1', 'OQGV1', 'OQP1',]: # spc forces 00525 self.readTable_OQG() 00526 elif tableName in ['OQMG1', 'OQMPSD2', 'OQMATO2', 'OQMRMS2', 00527 'OQMNO2', 'OQMCRM2',]: # mpc forces 00528 #self.readTable_OQG() 00529 self.readTable_DUMMY_GEOM(tableName) 00530 00531 elif tableName in ['OUGV1', 'OUPV1']: 00532 self.readTable_OUG() # displacements/velocity/acceleration 00533 elif tableName in ['OUGPSD2', 'OUGATO2', 'OUGRMS2', 'OUGNO2', 00534 'OUGCRM2']: # OUG tables??? 00535 self.readTable_OUG() 00536 00537 elif tableName in ['OES1', 'OES1X', 'OES1X1', 'OSTR1X', 00538 'OES1C', 'OESCP', 'OESRT', 'OESNLXR', 00539 'OESNL1X']: 00540 self.readTable_OES() # stress 00541 elif tableName in ['OSTR1X','OSTR1C',]: 00542 self.readTable_OES() # strain 00543 elif tableName in ['OESTRCP', 'OESNLXD', 'OESNLXR',]: 00544 self.readTable_OES() # ??? stress/strain 00545 elif tableName in ['OSTRATO2', 'OSTRPSD2', 'OESRMS2', 'OESNO2', 00546 'OESCRM2', 'OSTRRMS2', 'OESRMS2', 'OSTRNO2', 00547 'OESCRM2', 'OSTRCRM2',]: # unhandled 00548 self.readTable_OES() 00549 00550 #elif tableName in ['OESNLXD',]: # dont use this, testing only 00551 #self.readTable_OES() # NLXD 00552 #elif tableName in ['OESNLXR',]: # dont use this 00553 #self.readTable_OES() # NLXR 00554 00555 elif tableName in ['ONRGY1']: # energy 00556 self.readTable_OEE() 00557 elif tableName in ['ONRGY2']: 00558 self.readTable_OEE() 00559 00560 elif tableName in ['PCOMPTS']: 00561 self.readTable_PCOMPTS() 00562 elif tableName in ['SDF']: # ??? 00563 self.readTable_SDF() 00564 #elif tableName in ['CASECC']: 00565 #self.readTable_CASECC() 00566 00567 # not done 00568 elif tableName in []: 00569 self.readTableB_DUMMY() 00570 elif tableName in ['MONITOR', 'PMRF', 'PERF', 'PFRF', 00571 'AEMONPT', 'FOL', 'AFRF', 'AGRF',]: 00572 self.readTableB_DUMMY() 00573 #elif tableName in []: 00574 # self.readTableB_DUMMY() 00575 00576 elif tableName in ['STDISP', 'FOL', 'OFMPF2M', 'OSMPF2M', 00577 'OPMPF2M', 'OGPMPF2M', 'OLMPF2M', 00578 'OVGPSD2']: 00579 self.readTable_DUMMY_GEOM(tableName) 00580 elif tableName in ['OVGATO2', 'OVGRMS2', 'OVGNO2']: 00581 self.readTable_DUMMY_GEOM(tableName) 00582 00583 elif tableName in ['OESNLXR', 'OESNL1X', 'OESPSD2', 'OESNLBR', 00584 'OESATO2',]: 00585 self.readTable_DUMMY_GEOM(tableName) 00586 elif tableName in ['OVGCRM2', 'OAGPSD2', 'OAGATO2', 'OAGRMS2', 00587 'OAGNO2', 'OAGCRM2', 'OPGPSD2', 'OPGPSD2', 00588 'OPGPSD2', 'OPGATO2']: 00589 self.readTable_DUMMY_GEOM(tableName) 00590 elif tableName in ['OPGRMS2', 'OPGNO2', 'OPGCRM2', 'OQGPSD2',]: 00591 self.readTable_DUMMY_GEOM(tableName) 00592 elif tableName in ['OQGPSD2', 'OQGATO2', 'OQGRMS2', 'OQGNO2', 00593 'OQGCRM2', 'PVT0', 'CASECC', 'EDOM',]: 00594 self.readTable_DUMMY_GEOM(tableName) 00595 elif tableName in ['BGPDT', 'BGPDTS', 'EDTS',]: 00596 self.readTable_DUMMY_GEOM(tableName) 00597 else: 00598 msg = 'unhandled tableName=|%s|' % (tableName) 00599 raise KeyError(msg) 00600 #print("endTell = ",self.op2.tell()) 00601 #print("---isAnotherTable---") 00602 (isAnotherTable) = self.hasMoreTables() 00603 #isAnotherTable = True 00604 except EndOfFileError: 00605 isAnotherTable = False 00606 ### 00607 else: 00608 if tableName not in [None]: 00609 assert 1 == 0, '%s is not supported' % (tableName) 00610 (isAnotherTable) = self.skipNextTable() 00611 #return isAnotherTable 00612 #print(self.printSection(140)) 00613 self.log.debug("*** finished tableName = |%r|" % (tableName)) 00614 ### 00615 return isAnotherTable 00616 00617 def parseSortCode(self): 00618 """ 00619 sortCode = 0 -> sortBits = [0,0,0] 00620 sortCode = 1 -> sortBits = [0,0,1] 00621 sortCode = 2 -> sortBits = [0,1,0] 00622 sortCode = 3 -> sortBits = [0,1,1] 00623 etc. 00624 sortCode = 7 -> sortBits = [1,1,1] 00625 00626 sortBits[0] = 0 -> isSort1=True isSort2=False 00627 sortBits[1] = 0 -> isReal=True isReal/Imaginary=False 00628 sortBits[2] = 0 -> isSorted=True isRandom=False 00629 """ 00630 bits = [0, 0, 0] 00631 00632 sortCode = self.sortCode 00633 i = 2 00634 #print("***sortCode = ",self.sortCode) 00635 while sortCode > 0: 00636 value = sortCode % 2 00637 sortCode = (sortCode - value)//2 00638 bits[i] = value 00639 #print(" *bit = %s" %(value)) 00640 #print(" sortCode = %s" %(sortCode)) 00641 i -= 1 00642 #print("sortBits = %s" %(bits)) 00643 ## the bytes describe the SORT information 00644 self.sortBits = bits 00645 00646 self.dataCode['sortBits'] = self.sortBits 00647 00648 def parseApproachCode(self, data): 00649 """ 00650 int3 is the 3rd word in table=-3 and may be 00651 elementType or something else depending on the table type 00652 """ 00653 (aCode, tCode, int3, iSubcase) = unpack(b'iiii', data[:16]) 00654 ## the local subcase ID 00655 self.iSubcase = iSubcase 00656 #print("iSubcase = %s" %(iSubcase)) 00657 self.subcases.add(self.iSubcase) # set notation 00658 00659 ## the type of result being processed 00660 self.tableCode = tCode % 1000 00661 ## used to create sortBits 00662 self.sortCode = tCode//1000 00663 ## what type of data was saved from the run; used to parse the 00664 ## approachCode and gridDevice. deviceCode defines what options 00665 ## inside a result, STRESS(PLOT,PRINT), are used. 00666 self.deviceCode = aCode % 10 00667 ## what solution was run (e.g. Static/Transient/Modal) 00668 self.analysisCode = (aCode-self.deviceCode) // 10 00669 00670 if self.deviceCode == 3: 00671 #sys.stderr.write('The op2 may be inconsistent...\n') 00672 #sys.stderr.write(" print and plot can cause bad results...if there's a crash, try plot only\n") 00673 self.deviceCode = 1 00674 00675 #self.log.info('The op2 may be inconsistent...') 00676 #self.log.info(" print and plot can cause bad results...if there's a crash, try plot only") 00677 #pass 00678 00679 ## dataCode stores the active variables; these pass important 00680 ## self variables into the result object 00681 self.dataCode = {'analysisCode': self.analysisCode, 00682 'deviceCode' : self.deviceCode, 00683 'tableCode' : self.tableCode, 00684 'sortCode' : self.sortCode, 00685 'dt' : None, 00686 'log' : self.log, 00687 } 00688 #print("iSubcase = ",self.iSubcase) 00689 self.parseSortCode() 00690 00691 #print("aCode(1)=%s analysisCode=%s deviceCode=%s tCode(2)=%s tableCode=%s sortCode=%s iSubcase(4)=%s" %(aCode,self.analysisCode,self.deviceCode,tCode,self.tableCode,self.sortCode,self.iSubcase)) 00692 #self.log.debug(self.printTableCode(self.tableCode)) 00693 return (int3) 00694 00695 def getValues(self, data, iFormat, iWordStart, iWordStop=None): 00696 """ 00697 extracts the ith word from the data structure as the provided type 00698 supports multiple inputs with iWordStop (note this is words, 00699 not outputs) 00700 @param self the object pointer 00701 @param data the binary data that is as long as the buffer size 00702 @param iWordStart the word to start reading from 00703 @param iWordStop the word to stop reading on (largely unused) 00704 @warning 00705 works with nastran syntax, not standard python syntax 00706 this makes it work with what's documented in the DMAP manual 00707 """ 00708 if iWordStop == None: 00709 #print("iWordStart=%s data[%s:%s]" %(iWordStart,iWordStart*4,(iWordStart+1)*4)) 00710 ds = data[(iWordStart-1)*4:iWordStart*4] 00711 iFormat = bytes(iFormat) 00712 return unpack(iFormat, ds)[0] 00713 #print("type(data) = ",type(data)) 00714 ds = data[(iWordStart-1)*4:(iWordStop-1)*4] 00715 return unpack(iFormat, ds) 00716 00717 def deleteAttributes(self, params): 00718 """ 00719 deletes any parameters before going to the next table to avoid 00720 messing up data 00721 """ 00722 params += ['dataCode', 'deviceCode', 'analysisCode', 'tableCode', 00723 'sortCode', 'iSubcase', 'data', 'numWide', 00724 'nonlinearFactor', 'obj', 'subtitle', 'label'] 00725 for param in params: 00726 if hasattr(self, param): 00727 delattr(self, param) 00728 00729 def getBufferWords(self): 00730 bufferWords = self.getMarker() 00731 #print("buffMarker = |%s|" %(bufferWords)) 00732 #print("bufferWords = ",bufferWords,bufferWords*4) 00733 if bufferWords <=0: 00734 raise BufferError('An invalid buffersize was found...' 00735 'bufferWords=%s tableName=%s section=\n%s' 00736 % (bufferWords,self.tableName,self.printSection(200))) 00737 return bufferWords 00738 00739 def verifyBufferSize(self, bufferWords): 00740 assert bufferWords > 0, self.printSection(220) 00741 00742 def readTitle(self): 00743 """ 00744 reads the Title, Subtitle, and Label. 00745 Puts them in self.iSubcaseNameMap[iSubcase] = [Subtitle,Label] 00746 """ 00747 ## the title of the analysis 00748 word = self.readString(384) # titleSubtitleLabel 00749 self.Title = word[0:128].strip() 00750 ## the subtitle of the subcase 00751 self.subtitle = word[128:256].strip() 00752 ## the label of the subcase 00753 self.label = word[256:328].strip() 00754 00755 # not really a hollerith, just the end of the block (so bufferWords*4) 00756 self.readHollerith() 00757 00758 self.dataCode['subtitle'] = self.subtitle 00759 self.dataCode['label'] = self.label 00760 00761 if self.iSubcase not in self.iSubcaseNameMap: 00762 self.iSubcaseNameMap[self.iSubcase] = [self.subtitle, self.label] 00763 00764 def tableInit(self, word): 00765 """ 00766 starts a new table 00767 """ 00768 ## the local table name 00769 self.tableName = word.strip() 00770 ## the names of all the tables 00771 self.tableNames.append(word) 00772 msg = '*'*20+word+'*'*20+'\n' 00773 #print(msg) 00774 00775 def getTableNamesFromOP2(self): 00776 """ 00777 returns the list of parsed tables 00778 """ 00779 return self.tableNames 00780 00781 def printResults(self): 00782 results = [ 00783 # OUG - Displacements/Velocity/Acceleration/Temperature 00784 self.displacements, self.displacementsPSD, 00785 self.displacementsATO, 00786 self.temperatures, 00787 self.eigenvalues, 00788 self.eigenvectors, 00789 self.velocities, 00790 self.accelerations, 00791 00792 # OEF - Applied Forces/Temperatures - ??? 00793 00794 # OQG1 - SPC/MPC Forces 00795 self.spcForces, self.mpcForces, 00796 00797 # OGF - Grid Point Forces 00798 self.gridPointForces, 00799 00800 # OPG - Applied Force/Moment 00801 self.appliedLoads, 00802 self.loadVectors, self.thermalLoadVectors, 00803 self.forceVectors, 00804 00805 # OES - Stress/Strain 00806 self.celasStress, self.celasStrain, 00807 self.rodStress, self.rodStrain, 00808 self.nonlinearRodStress, self.nonlinearRodStrain, 00809 00810 self.barStress, self.barStrain, 00811 self.beamStress, self.beamStrain, 00812 self.plateStress, self.plateStrain, 00813 self.solidStress, self.solidStrain, 00814 self.compositePlateStress, self.compositePlateStrain, 00815 self.ctriaxStress, self.ctriaxStrain, 00816 00817 # OEE - Strain Energy 00818 self.strainEnergy, 00819 ] 00820 00821 msg = '---ALL RESULTS---\n' 00822 for result in results: 00823 for (iSubcase, res) in sorted(result.iteritems()): 00824 msg += 'iSubcase = %s\n' % (iSubcase) 00825 try: 00826 msg += str(res) + '\n' 00827 except: 00828 print('failed on %s' % (res.__class__.__name__)) 00829 raise 00830 return msg 00831