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 math import isnan 00029 00030 from .real.oes_objects import stressObject,strainObject #,array 00031 00032 00033 class NonlinearQuadObject(stressObject): 00034 def __init__(self,dataCode,isSort1,iSubcase,dt=None): 00035 stressObject.__init__(self,dataCode,iSubcase) 00036 #self.eType = 'QUAD4FD' # or CTRIA3 00037 00038 self.code = [self.formatCode,self.sortCode,self.sCode] 00039 self.eType = {} 00040 self.fiberDistance = {} 00041 self.oxx = {} 00042 self.oyy = {} 00043 self.ozz = {} 00044 self.txy = {} 00045 00046 self.exx = {} 00047 self.eyy = {} 00048 self.ezz = {} 00049 self.exy = {} 00050 00051 self.es = {} 00052 self.eps = {} 00053 self.ecs = {} 00054 00055 self.dt = dt 00056 if isSort1: 00057 if dt is not None: 00058 self.add = self.addSort1 00059 self.addNewEid = self.addNewEidSort1 00060 ### 00061 else: 00062 assert dt is not None 00063 self.add = self.addSort2 00064 self.addNewEid = self.addNewEidSort2 00065 ### 00066 00067 def deleteTransient(self,dt): 00068 del self.fiberDistance[dt] 00069 del self.oxx[dt] 00070 del self.oyy[dt] 00071 del self.ozz[dt] 00072 del self.txy[dt] 00073 00074 del self.exx[dt] 00075 del self.eyy[dt] 00076 del self.ezz[dt] 00077 del self.exy[dt] 00078 00079 del self.es[dt] 00080 del self.eps[dt] 00081 del self.ecs[dt] 00082 00083 def getTransients(self): 00084 k = self.oxx.keys() 00085 k.sort() 00086 return k 00087 00088 def addNewTransient(self,dt): 00089 self.fiberDistance[dt] = {} 00090 self.oxx[dt] = {} 00091 self.oyy[dt] = {} 00092 self.ozz[dt] = {} 00093 self.txy[dt] = {} 00094 00095 self.exx[dt] = {} 00096 self.eyy[dt] = {} 00097 self.ezz[dt] = {} 00098 self.exy[dt] = {} 00099 00100 self.es[dt] = {} 00101 self.eps[dt] = {} 00102 self.ecs[dt] = {} 00103 00104 def addNewEidSort1(self,eType,dt,data): 00105 if dt not in self.oxx: 00106 self.addNewTransient(dt) 00107 (eid,fd,sx,sy,sz,txy,es,eps,ecs,ex,ey,ez,exy) = data 00108 self.fiberDistance[dt][eid] = [fd] 00109 if isnan(sz): sz = 0. 00110 if isnan(ez): ez = 0. 00111 self.eType[eid] = eType 00112 self.oxx[dt][eid] = [sx] 00113 self.oyy[dt][eid] = [sy] 00114 self.ozz[dt][eid] = [sz] 00115 self.txy[dt][eid] = [txy] 00116 00117 self.exx[dt][eid] = [ex] 00118 self.eyy[dt][eid] = [ey] 00119 self.ezz[dt][eid] = [ez] 00120 self.exy[dt][eid] = [exy] 00121 00122 self.es[dt][eid] = [es] 00123 self.eps[dt][eid] = [eps] 00124 self.ecs[dt][eid] = [ecs] 00125 00126 def addSort1(self,dt,data): 00127 (eid,fd,sx,sy,sz,txy,es,eps,ecs,ex,ey,ez,exy) = data 00128 self.fiberDistance[dt][eid].append(fd) 00129 if isnan(sz): sz = 0. 00130 if isnan(ez): ez = 0. 00131 00132 self.oxx[dt][eid].append(sx) 00133 self.oyy[dt][eid].append(sy) 00134 self.ozz[dt][eid].append(sz) 00135 self.txy[dt][eid].append(txy) 00136 00137 self.exx[dt][eid].append(ex) 00138 self.eyy[dt][eid].append(ey) 00139 self.ezz[dt][eid].append(ez) 00140 self.exy[dt][eid].append(exy) 00141 00142 self.es[dt][eid].append(es) 00143 self.eps[dt][eid].append(eps) 00144 self.ecs[dt][eid].append(ecs) 00145 00146 def writeF06(self,header,pageStamp,pageNum=1,f=None,isMagPhase=None): 00147 msgStart = [' ELEMENT-ID = 129\n' 00148 ' N O N L I N E A R S T R E S S E S I N Q U A D R I L A T E R A L E L E M E N T S ( Q U A D 4 )\n' 00149 ' \n', 00150 ' TIME FIBER STRESSES/ TOTAL STRAINS EQUIVALENT EFF. STRAIN EFF. CREEP\n' 00151 ' DISTANCE X Y Z XY STRESS PLASTIC/NLELAST STRAIN\n'] 00152 #0 5.000E-05 -5.000000E-01 -4.484895E+01 -1.561594E+02 -2.008336E-02 1.392609E+02 0.0 0.0 00153 msgE = {} 00154 msgT = {} 00155 for (dt,Oxxs) in sorted(self.oxx.iteritems()): 00156 header[1] = ' %s = %10.4E\n' %(self.dataCode['name'],dt) 00157 00158 for (eid,oxxs) in sorted(Oxxs.iteritems()): 00159 msgE[eid] = header+[' ELEMENT-ID = %8i\n' %(eid)] 00160 if eid not in msgT: 00161 msgT[eid] = [] 00162 for i,oxx in enumerate(oxxs): 00163 fd = self.fiberDistance[dt][eid][i] 00164 oxx = self.oxx[dt][eid][i] 00165 oyy = self.oyy[dt][eid][i] 00166 ozz = self.ozz[dt][eid][i] 00167 txy = self.txy[dt][eid][i] 00168 00169 exx = self.exx[dt][eid][i] 00170 eyy = self.eyy[dt][eid][i] 00171 ezz = self.ezz[dt][eid][i] 00172 exy = self.exy[dt][eid][i] 00173 00174 es = self.es[dt][eid][i] 00175 eps = self.eps[dt][eid][i] 00176 ecs = self.ecs[dt][eid][i] 00177 ([oxx,oyy,ozz,txy,exx,eyy,es,eps,ecs,exx,eyy,ezz,exy],isAllZeros) = self.writeFloats13E([oxx,oyy,ozz,txy,exx,eyy,es,eps,ecs,exx,eyy,ezz,exy]) 00178 if i==0: 00179 msgT[eid].append( '0 %9.3E %13s %13s %13s %13s %13s %13s %13s %-s\n' %(dt,fd,oxx,oyy,ozz,txy,es,eps,ecs)) 00180 else: 00181 msgT[eid].append(' %9s %13s %13s %13s %13s %13s\n' %('','',exx,eyy,ezz,exy)) 00182 ### 00183 ### 00184 ### 00185 ### 00186 msg = [] 00187 for eid,e in sorted(msgE.iteritems()): 00188 msg += header+e+msgStart+msgT[eid] 00189 msg.append(pageStamp+str(pageNum)+'\n') 00190 pageNum+=1 00191 00192 return (''.join(msg),pageNum-1) 00193 00194 def __repr__(self): 00195 return self.writeF06([],'PAGE ',1)[0] 00196 00197 00198 class HyperelasticQuadObject(stressObject): 00199 def __init__(self,dataCode,isSort1,iSubcase,dt=None): 00200 stressObject.__init__(self,dataCode,iSubcase) 00201 self.eType = 'QUAD4FD' 00202 00203 self.code = [self.formatCode,self.sortCode,self.sCode] 00204 self.Type = {} 00205 self.IDs = {} 00206 self.oxx = {} 00207 self.oyy = {} 00208 self.txy = {} 00209 self.angle = {} 00210 self.majorP = {} 00211 self.minorP = {} 00212 00213 self.dt = dt 00214 if isSort1: 00215 if dt is not None: 00216 self.add = self.addSort1 00217 self.addNewEid = self.addNewEidSort1 00218 ### 00219 else: 00220 assert dt is not None 00221 self.add = self.addSort2 00222 self.addNewEid = self.addNewEidSort2 00223 ### 00224 00225 def deleteTransient(self,dt): 00226 del self.fiberDistance[dt] 00227 del self.oxx[dt] 00228 del self.oyy[dt] 00229 del self.txy[dt] 00230 00231 del self.angle[dt] 00232 del self.majorP[dt] 00233 del self.minorP[dt] 00234 00235 def getTransients(self): 00236 k = self.oxx.keys() 00237 k.sort() 00238 return k 00239 00240 def addNewTransient(self,dt): 00241 self.oxx[dt] = {} 00242 self.oyy[dt] = {} 00243 self.txy[dt] = {} 00244 self.angle[dt] = {} 00245 self.majorP[dt] = {} 00246 self.minorP[dt] = {} 00247 00248 def addNewEidSort1(self,dt,data): 00249 if dt not in self.oxx: 00250 self.addNewTransient(dt) 00251 (eid,Type,oxx,oyy,txy,angle,majorP,minorP) = data 00252 self.Type[eid] = Type 00253 self.oxx[dt] = {eid:[oxx]} 00254 self.oyy[dt] = {eid:[oyy]} 00255 self.txy[dt] = {eid:[txy]} 00256 self.angle[dt] = {eid:[angle]} 00257 self.majorP[dt] = {eid:[majorP]} 00258 self.minorP[dt] = {eid:[minorP]} 00259 00260 def addSort1(self,dt,eid,data): 00261 (ID,oxx,oyy,txy,angle,majorP,minorP) = data 00262 self.oxx[dt][eid].append(oxx) 00263 self.oyy[dt][eid].append(oyy) 00264 self.txy[dt][eid].append(txy) 00265 self.angle[dt][eid].append(angle) 00266 self.majorP[dt][eid].append(majorP) 00267 self.minorP[dt][eid].append(minorP) 00268 00269 def writeF06(self,header,pageStamp,pageNum=1,f=None,isMagPhase=False): ## @todo doesnt support CTRIA3NL (calls them CQUAD4s) 00270 msg = [' S T R E S S E S I N H Y P E R E L A S T I C Q U A D R I L A T E R A L E L E M E N T S ( QUAD4FD )\n', 00271 ' ELEMENT GRID/ POINT ---------CAUCHY STRESSES-------- PRINCIPAL STRESSES (ZERO SHEAR)\n', 00272 ' ID GAUSS ID NORMAL-X NORMAL-Y SHEAR-XY ANGLE MAJOR MINOR\n',] 00273 #0 1 GAUS 1 7.318995E+00 6.367099E-01 -6.551054E+00 -31.4888 1.133173E+01 -3.376026E+00 00274 # 2 1.097933E+01 4.149028E+00 6.278160E+00 30.7275 1.471111E+01 4.172537E-01 00275 00276 for dt,Oxxs in sorted(self.oxx.iteritems()): 00277 #header[-1] = ' LOAD STEP = %12.5E' %(dt) 00278 msg += header 00279 for eid,oxxs in sorted(Oxxs.iteritems()): 00280 gauss = self.Type[eid] 00281 oxx = self.oxx[dt][eid] 00282 oyy = self.oyy[dt][eid] 00283 txy = self.txy[dt][eid] 00284 angle = self.angle[dt][eid] 00285 majorP = self.majorP[dt][eid] 00286 minorP = self.minorP[dt][eid] 00287 00288 for i in xrange(4): # 1,2,3,4 00289 if i == 0: 00290 msg.append('0%8i %8s %8i %13E.6 %13E.6 %13E.6 %13E.6 %13E.6 %13E.6\n' %(eid,gauss,i+1,oxx[i],oyy[i],txy[i],angle[i],majorP[i],minorP[i])) 00291 else: 00292 msg.append(' %8s %8s %8i %13E.6 %13E.6 %13E.6 %13E.6 %13E.6 %13E.6\n' %('','', i+1,oxx[i],oyy[i],txy[i],angle[i],majorP[i],minorP[i])) 00293 ### 00294 ### 00295 ### 00296 ### 00297 return (''.join(msg),pageNum) 00298 00299 def __repr__(self): 00300 return self.writeF06([],'PAGE ',1)[0] 00301 00302 class NonlinearRodObject(stressObject): 00303 def __init__(self,dataCode,isSort1,iSubcase,dt=None): 00304 stressObject.__init__(self,dataCode,iSubcase) 00305 #self.eType = 'CROD' 00306 self.eTypeMap = {89:'CRODNL',92:'CONRODNL'} 00307 self.code = [self.formatCode,self.sortCode,self.sCode] 00308 00309 self.eType = {} 00310 self.axialStress = {} 00311 self.equivStress = {} 00312 self.totalStrain = {} 00313 self.effectivePlasticCreepStrain = {} 00314 self.effectiveCreepStrain = {} 00315 self.linearTorsionalStress = {} 00316 00317 self.dt = dt 00318 if isSort1: 00319 if dt is not None: 00320 self.add = self.addSort1 00321 #self.addNewEid = self.addNewEidSort1 00322 ### 00323 else: 00324 assert dt is not None 00325 self.add = self.addSort2 00326 #self.addNewEid = self.addNewEidSort2 00327 ### 00328 00329 def deleteTransient(self,dt): 00330 del self.axialStress[dt] 00331 del self.equivStress[dt] 00332 del self.totalStrain[dt] 00333 del self.effectivePlasticCreepStrain[dt] 00334 00335 del self.effectiveCreepStrain[dt] 00336 del self.linearTorsionalStress[dt] 00337 00338 def getTransients(self): 00339 k = self.axialStress.keys() 00340 k.sort() 00341 return k 00342 00343 def addNewTransient(self,dt): 00344 self.axialStress[dt] = {} 00345 self.equivStress[dt] = {} 00346 self.totalStrain[dt] = {} 00347 self.effectivePlasticCreepStrain[dt] = {} 00348 self.effectiveCreepStrain[dt] = {} 00349 self.linearTorsionalStress[dt] = {} 00350 00351 def addSort1(self,eType,dt,data): 00352 if dt not in self.axialStress: 00353 self.addNewTransient(dt) 00354 eid = data[0] 00355 self.eType[eid] = eType 00356 self.axialStress[dt][eid] = data[1] 00357 self.equivStress[dt][eid] = data[2] 00358 self.totalStrain[dt][eid] = data[3] 00359 self.effectivePlasticCreepStrain[dt][eid] = data[4] 00360 self.effectiveCreepStrain[dt][eid] = data[5] 00361 self.linearTorsionalStress[dt][eid] = data[6] 00362 #print data 00363 00364 def writeF06(self,header,pageStamp,pageNum=1,f=None,isMagPhase=False): ## @todo doesnt support CONROD/CTUBE (calls them CRODs) 00365 """ 00366 ELEMENT-ID = 102 00367 N O N L I N E A R S T R E S S E S I N R O D E L E M E N T S ( C R O D ) 00368 TIME AXIAL STRESS EQUIVALENT TOTAL STRAIN EFF. STRAIN EFF. CREEP LIN. TORSIONAL 00369 STRESS PLASTIC/NLELAST STRAIN STRESS 00370 2.000E-02 1.941367E+01 1.941367E+01 1.941367E-04 0.0 0.0 0.0 00371 3.000E-02 1.941367E+01 1.941367E+01 1.941367E-04 0.0 0.0 0.0 00372 """ 00373 msg = [] 00374 msgStart = [' N O N L I N E A R S T R E S S E S I N R O D E L E M E N T S ( C R O D )\n', 00375 ' \n', 00376 ' TIME AXIAL STRESS EQUIVALENT TOTAL STRAIN EFF. STRAIN EFF. CREEP LIN. TORSIONAL\n', 00377 ' STRESS PLASTIC/NLELAST STRAIN STRESS\n'] 00378 msgE = {} 00379 msgT = {} 00380 for dt,axials in sorted(self.axialStress.iteritems()): 00381 for eid,axial in sorted(axials.iteritems()): 00382 eqs = self.equivStress[dt][eid] 00383 ts = self.totalStrain[dt][eid] 00384 epcs = self.effectivePlasticCreepStrain[dt][eid] 00385 ecs = self.effectiveCreepStrain[dt][eid] 00386 lts = self.linearTorsionalStress[dt][eid] 00387 #print "dt=%s axials=%s eqs=%s ts=%s epcs=%s ecs=%s lts=%s" %(dt,axial,eqs,ts,epcs,ecs,lts) 00388 msgE[eid] = ' ELEMENT-ID = %8i\n' %(eid) 00389 if eid not in msgT: 00390 msgT[eid] = [] 00391 msgT[eid].append(' %9.3E %13.6E %13.6E %13.6E %13.6E %13.6E %13.6E\n'%(dt,axial,eqs,ts,epcs,ecs,lts)) 00392 ### 00393 ### 00394 for eid,e in sorted(msgE.iteritems()): 00395 msg += header+[e]+msgStart+msgT[eid] 00396 msg.append(pageStamp+str(pageNum)) 00397 00398 return (''.join(msg),pageNum) 00399 00400 def __repr__(self): 00401 return self.writeF06([],'PAGE ',1)[0] 00402