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 import sys 00026 #from struct import pack 00027 from numpy import array, sqrt, abs, angle # dot, 00028 00029 from pyNastran.op2.resultObjects.op2_Objects import scalarObject 00030 00031 try: 00032 from pylab import xlabel, ylabel, show, grid, legend, plot, title 00033 import matplotlib.pyplot as plt 00034 except ImportError: 00035 pass 00036 00037 class TableObject(scalarObject): # displacement style table 00038 def __init__(self,dataCode,isSort1,iSubcase,dt): 00039 self.nonlinearFactor = None 00040 self.tableName = None 00041 self.analysisCode = None 00042 scalarObject.__init__(self,dataCode,iSubcase) 00043 self.gridTypes = {} 00044 self.translations = {} 00045 self.rotations = {} 00046 00047 self.dt = dt 00048 if isSort1: 00049 if dt is not None: 00050 self.add = self.addSort1 00051 ### 00052 else: 00053 assert dt is not None 00054 self.add = self.addSort2 00055 ### 00056 00057 def isImaginary(self): 00058 return False 00059 00060 def addF06Data(self,data,transient): 00061 if transient is None: 00062 for line in data: 00063 (nodeID,gridType,t1,t2,t3,r1,r2,r3) = line 00064 self.gridTypes[nodeID] = gridType 00065 self.translations[nodeID] = array([t1,t2,t3]) 00066 self.rotations[nodeID] = array([r1,r2,r3]) 00067 ### 00068 return 00069 00070 (dtName,dt) = transient 00071 self.dataCode['name'] = dtName 00072 if dt not in self.translations: 00073 self.updateDt(self.dataCode,dt) 00074 00075 for line in data: 00076 (nodeID,gridType,t1,t2,t3,r1,r2,r3) = line 00077 self.gridTypes[nodeID] = gridType 00078 self.translations[dt][nodeID] = array([t1,t2,t3]) 00079 self.rotations[dt][nodeID] = array([r1,r2,r3]) 00080 ### 00081 00082 def updateDt(self, dataCode, dt): 00083 self.dataCode = dataCode 00084 self.applyDataCode() 00085 if dt is not None: 00086 self.log.debug("updating %s...%s=%s iSubcase=%s" %(self.dataCode['name'],self.dataCode['name'], dt, self.iSubcase)) 00087 self.dt = dt 00088 self.addNewTransient(dt) 00089 ### 00090 00091 def deleteTransient(self, dt): 00092 del self.translations[dt] 00093 del self.rotations[dt] 00094 00095 def getTransients(self): 00096 k = self.translations.keys() 00097 k.sort() 00098 return k 00099 00100 def addNewTransient(self,dt): 00101 """initializes the transient variables""" 00102 self.dt = dt 00103 self.translations[dt] = {} 00104 self.rotations[dt] = {} 00105 00106 #def addBinary(self,deviceCode,data): 00107 #(nodeID,v1,v2,v3,v4,v5,v6) = unpack('iffffff',data) 00108 #msg = "nodeID=%s v1=%s v2=%s v3=%s" %(nodeID,v1,v2,v3) 00109 #assert -1<nodeID<1000000000,msg 00110 #assert nodeID not in self.translations 00111 00112 #self.translations[nodeID] = array([v1,v2,v3]) # dx,dy,dz 00113 #self.rotations[nodeID] = array([v4,v5,v6]) # rx,ry,rz 00114 ### 00115 00116 def add(self, dt, out): 00117 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = out 00118 msg = "nodeID=%s gridType=%s v1=%s v2=%s v3=%s" %(nodeID,gridType,v1,v2,v3) 00119 #print msg 00120 assert -1<nodeID<1000000000,msg 00121 assert isinstance(nodeID,int),msg 00122 #assert nodeID not in self.translations,'displacementObject - static failure' 00123 00124 self.gridTypes[nodeID] = self.recastGridType(gridType) 00125 self.translations[nodeID] = array([v1,v2,v3]) # dx,dy,dz 00126 self.rotations[nodeID] = array([v4,v5,v6]) # rx,ry,rz 00127 ### 00128 00129 def addSort1(self,dt,out): 00130 #print "dt=%s out=%s" %(dt,out) 00131 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = out 00132 if dt not in self.translations: 00133 self.addNewTransient(dt) 00134 msg = "nodeID=%s v1=%s v2=%s v3=%s\n" %(nodeID,v1,v2,v3) 00135 msg += " v4=%s v5=%s v6=%s" %( v4,v5,v6) 00136 #print msg 00137 assert -1<nodeID<1000000000,msg 00138 #assert isinstance(nodeID,int),msg 00139 #assert nodeID not in self.translations[self.dt],'displacementObject - transient failure' 00140 00141 self.gridTypes[nodeID] = self.recastGridType(gridType) 00142 self.translations[dt][nodeID] = array([v1,v2,v3]) # dx,dy,dz 00143 self.rotations[dt][nodeID] = array([v4,v5,v6]) # rx,ry,rz 00144 ### 00145 00146 def addSort2(self,nodeID,out): 00147 (dt,gridType,v1,v2,v3,v4,v5,v6) = out 00148 if dt not in self.translations: 00149 self.addNewTransient(dt) 00150 msg = "nodeID=%s v1=%s v2=%s v3=%s\n" %(nodeID,v1,v2,v3) 00151 msg += " v4=%s v5=%s v6=%s" %( v4,v5,v6) 00152 msg = 'dt=%s nodeID=%s' %(dt,nodeID) 00153 #print msg 00154 assert 0<nodeID<1000000000,msg # remove 00155 assert isinstance(nodeID,int),msg # remove 00156 assert -0.5<dt,msg # remove 00157 #assert nodeID not in self.translations[self.dt],'displacementObject - transient failure' 00158 00159 self.gridTypes[nodeID] = self.recastGridType(gridType) 00160 self.translations[dt][nodeID] = array([v1,v2,v3]) # dx,dy,dz 00161 self.rotations[dt][nodeID] = array([v4,v5,v6]) # rx,ry,rz 00162 ### 00163 00164 #def writeOp2(self,block3,deviceCode=1): 00165 #""" 00166 #creates the binary data for writing the table 00167 #@warning hasnt been tested... 00168 #""" 00169 #msg = block3 00170 #for nodeID,translation in sorted(self.translations.iteritems()): 00171 #rotation = self.rotations[nodeID] 00172 #(dx,dy,dz) = translation 00173 #(rx,ry,rz) = rotation 00174 #grid = nodeID*10+deviceCode 00175 #msg += pack('iffffff',grid,dx,dy,dz,rx,ry,rz) 00176 ### 00177 #return msg 00178 00179 #def writeOp2Transient(self,block3,deviceCode=1): 00180 # """ 00181 # creates the binary data for writing the table 00182 # @warning hasnt been tested... 00183 # @warning dt slot needs to be fixed... 00184 # """ 00185 # msg = '' 00186 # for dt,displacements in sorted(self.displacements.iteritems()): 00187 # XXX = 50 ## this isnt correct... @todo update dt 00188 # msg += block3[0:XXX] + pack('i',dt) + block3[XXX+4:] 00189 # #msg += '%s = %g\n' %(self.dataCode['name'],dt) 00190 # 00191 # for nodeID,displacement in sorted(displacements.iteritems()): 00192 # rotation = self.rotations[nodeID] 00193 # (dx,dy,dz) = displacement 00194 # (rx,ry,rz) = rotation 00195 # 00196 # grid = nodeID*10+deviceCode 00197 # msg += pack('iffffff',grid,dx,dy,dz,rx,ry,rz) 00198 # ### 00199 # ### 00200 # return msg 00201 00202 def writeHeader(self): 00203 #(mainHeaders,headers) = self.getHeaders() 00204 mainHeaders = ('nodeID','gridType') 00205 headers = ('T1','T2','T3','R1','R2','R3') 00206 msg = '%-10s %8s ' %(mainHeaders) 00207 for header in headers: 00208 msg += '%10s ' %(header) 00209 msg += '\n' 00210 return msg 00211 00212 def getAsSort1(self): 00213 return (self.translations,self.rotations) 00214 00215 def getAsSort2(self): 00216 """returns translations and rotations in sort2 format""" 00217 translations2 = {} 00218 rotations2 = {} 00219 if self.dt is not None: 00220 #return self.__reprTransient__() 00221 00222 for dt,translations in sorted(self.translations.iteritems()): 00223 nodeIDs = translations.keys() 00224 for nodeID in nodeIDs: 00225 translations2[nodeID] = {} 00226 rotations2[nodeID] = {} 00227 00228 for dt,translations in sorted(self.translations.iteritems()): 00229 for nodeID,translation in sorted(translations.iteritems()): 00230 rotation = self.rotations[dt][nodeID] 00231 translations2[nodeID][dt] = translation 00232 rotations2[nodeID][dt] = rotation 00233 ### 00234 else: 00235 return (self.translations,self.rotations) 00236 #for nodeID,translation in sorted(self.translations.iteritems()): 00237 # rotation = self.rotations[nodeID] 00238 # translations2[nodeID] = translation 00239 # rotations2[nodeID] = rotation 00240 ### 00241 ### 00242 return (translations2,rotations2) 00243 00244 def _writeMatlab(self,name,iSubcase,f=None,isMagPhase=False): 00245 """ 00246 name = displacements 00247 """ 00248 if self.nonlinearFactor is not None: 00249 self.writeMatlabTransient(name,iSubcase,f,isMagPhase) 00250 #print "static!!!!" 00251 #msg = [] 00252 #magPhase = 0 00253 #if isMagPhase: 00254 # magPhase = 1 00255 #msg.append('fem.%s.isMagPhase = %s' %(name,magPhase)) 00256 00257 nodes = self.translations.keys() 00258 00259 nodes.sort() 00260 #nNodes = len(nodes) 00261 self.writeMatlabArgs(name,iSubcase,f) 00262 f.write('fem.%s(%i).nodes = %s;\n' %(name,iSubcase,nodes)) 00263 00264 msgG = "fem.%s(%i).gridTypes = ['" %(name,iSubcase) 00265 msgT = 'fem.%s(%i).translations = [' %(name,iSubcase) 00266 msgR = 'fem.%s(%i).rotations = [' %(name,iSubcase) 00267 spaceT = ' '*len(msgT) 00268 spaceR = ' '*len(msgR) 00269 i=0 00270 for nodeID,translation in sorted(self.translations.iteritems()): 00271 rotation = self.rotations[nodeID] 00272 gridType = self.gridTypes[nodeID] 00273 msgG += '%s' %(gridType) 00274 00275 (dx,dy,dz) = translation 00276 (rx,ry,rz) = rotation 00277 vals = [dx,dy,dz,rx,ry,rz] 00278 (vals2,isAllZeros) = self.writeFloats13E(vals) 00279 msgT += '[%s,%s,%s];' %(dx,dy,dz) 00280 msgR += '[%s,%s,%s];' %(rx,ry,rz) 00281 i+=1 00282 if i==100: 00283 msgT += '\n%s' %(spaceT) 00284 msgR += '\n%s' %(spaceR) 00285 i=0 00286 ### 00287 ### 00288 msgG += "'];\n" 00289 msgT += '];\n' 00290 msgR += '];\n' 00291 f.write(msgG) 00292 f.write(msgT) 00293 f.write(msgR) 00294 00295 def _writeMatlabTransient(self,name,iSubcase,f=None,isMagPhase=False): 00296 """ 00297 name = displacements 00298 """ 00299 #print("transient!!!!") 00300 #msg = [] 00301 00302 times = self.translations.keys() 00303 nodes = self.translations[times[0]].keys() 00304 times.sort() 00305 nodes.sort() 00306 #nNodes = len(nodes) 00307 self.writeMatlabArgs(name,iSubcase,f) 00308 dtName = '%s' %(self.dataCode['name']) 00309 f.write('fem.%s(%i).nodes = %s;\n' %(name,iSubcase,nodes)) 00310 f.write('fem.%s(%i).%s = %s;\n' %(name,iSubcase,dtName,times)) 00311 00312 msgG = "fem.%s(%i).gridTypes = ['" %(name,iSubcase) 00313 00314 for nodeID,gridType in sorted(self.gridTypes.items()): 00315 msgG += '%s' %(gridType) 00316 msgG += "'];\n" 00317 f.write(msgG) 00318 del msgG 00319 00320 nDt = len(self.translations) 00321 msgT = 'fem.%s(%i).translations.%s = cell(1,%i);\n' %(name,iSubcase,dtName,nDt) 00322 msgR = 'fem.%s(%i).rotations.%s = cell(1,%i);\n' %(name,iSubcase,dtName,nDt) 00323 #msgT = 'fem.%s(%i).translations.%s = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00324 #msgR = 'fem.%s(%i).rotations.%s = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00325 for n,(dt,translations) in enumerate(sorted(self.translations.iteritems())): 00326 #msgT = 'fem.%s(%i).translations.%s(%i) = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00327 #msgR = 'fem.%s(%i).rotations.%s(%i) = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00328 00329 msgT += 'fem.%s(%i).translations.%s(%i) = [' %(name,iSubcase,dtName,n+1) 00330 msgR += 'fem.%s(%i).rotations.%s(%i) = [' %(name,iSubcase,dtName,n+1) 00331 00332 i=0 00333 for nodeID,translation in sorted(translations.iteritems()): 00334 rotation = self.rotations[dt][nodeID] 00335 #gridType = self.gridTypes[nodeID] 00336 00337 (dx,dy,dz) = translation 00338 (rx,ry,rz) = rotation 00339 #vals = [dx,dy,dz,rx,ry,rz] 00340 msgT += '[%s,%s,%s];' %(dx,dy,dz) 00341 msgR += '[%s,%s,%s];' %(rx,ry,rz) 00342 i+=1 00343 if i==100: 00344 msgT += '\n' 00345 msgR += '\n' 00346 i=0 00347 ### 00348 ### 00349 msgT += '];\n' 00350 msgR += '];\n' 00351 f.write(msgT) 00352 f.write(msgR) 00353 msgT = '' 00354 msgR = '' 00355 ### 00356 00357 def _writeF06Block(self,words,header,pageStamp,pageNum=1,f=None): 00358 msg = words 00359 #assert f is not None # remove 00360 for nodeID,translation in sorted(self.translations.iteritems()): 00361 rotation = self.rotations[nodeID] 00362 gridType = self.gridTypes[nodeID] 00363 00364 (dx,dy,dz) = translation 00365 (rx,ry,rz) = rotation 00366 vals = [dx,dy,dz,rx,ry,rz] 00367 (vals2,isAllZeros) = self.writeFloats13E(vals) 00368 if not isAllZeros: 00369 [dx,dy,dz,rx,ry,rz] = vals2 00370 msg.append('%14i %6s %13s %13s %13s %13s %13s %-s\n' %(nodeID,gridType,dx,dy,dz,rx,ry,rz.rstrip())) 00371 ### 00372 ### 00373 msg.append(pageStamp+str(pageNum)+'\n') 00374 if f is not None: 00375 f.write(''.join(msg)) 00376 msg = [''] 00377 return (''.join(msg),pageNum) 00378 00379 def _writeF06TransientBlock(self,words,header,pageStamp,pageNum=1,f=None): 00380 msg = [] 00381 #assert f is not None # remove 00382 for dt,translations in sorted(self.translations.iteritems()): 00383 if isinstance(dt,float): # fix 00384 header[1] = ' %s = %10.4E float %s\n' %(self.dataCode['name'],dt,self.analysisCode) 00385 else: 00386 header[1] = ' %s = %10i integer %s\n' %(self.dataCode['name'],dt,self.analysisCode) 00387 msg += header+words 00388 for nodeID,translation in sorted(translations.iteritems()): 00389 rotation = self.rotations[dt][nodeID] 00390 gridType = self.gridTypes[nodeID] 00391 00392 (dx,dy,dz) = translation 00393 (rx,ry,rz) = rotation 00394 vals = [dx,dy,dz,rx,ry,rz] 00395 (vals2,isAllZeros) = self.writeFloats13E(vals) 00396 if not isAllZeros: 00397 [dx,dy,dz,rx,ry,rz] = vals2 00398 msg.append('%14i %6s %13s %13s %13s %13s %13s %-s\n' %(nodeID,gridType,dx,dy,dz,rx,ry,rz.rstrip())) 00399 ### 00400 ### 00401 msg.append(pageStamp+str(pageNum)+'\n') 00402 if f is not None: 00403 f.write(''.join(msg)) 00404 msg = [''] 00405 pageNum+=1 00406 return (''.join(msg),pageNum-1) 00407 00408 def getTableMarker(self): 00409 if self.isATO(): 00410 words = self.ATO_words() 00411 elif self.isCRM(): 00412 words = self.CRM_words() 00413 elif self.isPSD(): 00414 words = self.PSD_words() 00415 elif self.isRMS(): 00416 words = self.RMS_words() 00417 elif self.isZERO(): 00418 return self.ZERO_words() 00419 else: 00420 words = [''] 00421 return words 00422 00423 def isATO(self): 00424 """Auto-Correlation Function""" 00425 if 'ATO' in self.tableName: 00426 return True 00427 return False 00428 00429 def isCRM(self): 00430 """Correlated Root-Mean Square""" 00431 if 'CRM' in self.tableName: 00432 return True 00433 return False 00434 00435 def isPSD(self): 00436 """Power Spectral Density""" 00437 if 'PSD' in self.tableName: 00438 return True 00439 return False 00440 00441 def isRMS(self): 00442 """Root-Mean Square""" 00443 if 'RMS' in self.tableName: 00444 return True 00445 return False 00446 00447 def isZERO(self): 00448 """Zero Crossings""" 00449 if 'NO' in self.tableName: 00450 return True 00451 return False 00452 00453 00454 def ATO_words(self): 00455 words = [' ( AUTO-CORRELATION FUNCTION )\n',' \n'] 00456 return words 00457 00458 def CRM_words(self): 00459 words = [' ( CUMULATIVE ROOT MEAN SQUARE )\n',' \n'] 00460 return words 00461 00462 def PSD_words(self): 00463 words = [' ( POWER SPECTRAL DENSITY FUNCTION )\n',' \n'] 00464 return words 00465 00466 def RMS_words(self): 00467 words = [' ( ROOT MEAN SQUARE )\n',' \n'] 00468 return words 00469 00470 def ZERO_words(self): 00471 words = [' ( NUMBER OF ZERO CROSSINGS )\n',' \n'] 00472 return words 00473 00474 def plot(self,nodeList=None,resultType='Translation',coord=3,markers=None, 00475 Title=None,hasLegend=True,Legend=None,xLabel=None,yLabel=None,alphaLegend=0.5): 00476 """ 00477 @param nodeList a list of the node IDs to plot vs the 00478 independent variable (default=None; all nodes) 00479 @param resultType the variable to plot ('Translation','Rotation') 00480 @param coord the coordinate to plot (for <x,y,z>, x=0,y=1,z=2,Mag=3); 00481 default=Magnitude 00482 @param markers a list of colors/marker shapes for each line 00483 @param Title title of the plot (default=the object name) 00484 @param hasLegend should a legend be shown (default=False) 00485 @param Legend the list of the legend titles (default=No Legend) 00486 @param xLabel the name of the xAxis (default=the name of 00487 the independent variable; string) 00488 @param yLabel the name of the xAxis (default=the name of 00489 the dependent variable; string) 00490 @param alphaLegend the transparency of the legend; 00491 (0.0=solid; 1.0=transparent; default=0.5) 00492 00493 @todo fix alphaLegend; test options more... 00494 """ 00495 (results,nodeList,markers,Title,xLabel,yLabel) = getPlotData( 00496 self,nodeList,resultType,coord,markers,Title,hasLegend,Legend,xLabel,yLabel) 00497 00498 i = 0 00499 Labels = [] 00500 #print "nodeList = ",nodeList 00501 node0 = nodeList[0] 00502 Xs = sorted(results[node0].keys()) 00503 00504 (fig,ax) = plt.subplots(1) 00505 #leg = plt.legend(loc='best', fancybox=True,alpha=0.5) 00506 for nodeID in nodeList: # translation/rotation 00507 result = results[nodeID] 00508 Ys = [] 00509 for dt,res in sorted(result.iteritems()): 00510 if coord==3: 00511 val = sqrt(res.dot(res)) 00512 else: 00513 val = res[coord] 00514 ### 00515 Ys.append(val) 00516 Label = 'Node %s' %(nodeID) 00517 Labels.append(Label) 00518 #ax.plot(Xs,Ys,markers[i],label=Label) 00519 #plot(Xs,Ys,Label) 00520 plot(Xs,Ys) 00521 i+=1 00522 plt.legend(Labels,loc='best',fancybox=True) 00523 #print dir(leg) 00524 #leg.get_frame().set_alpha(0.5) 00525 ax.set_title(Title) 00526 #ax.set_legend(Labels) 00527 #if hasLegend and Legend is None: 00528 # plt.legend(Labels) 00529 #elif hasLegend: 00530 # plt.legend(Legend) 00531 #plt.axes 00532 #print dir(plt) 00533 ax.grid(True) 00534 ax.set_ylabel(yLabel) 00535 ax.set_xlabel(xLabel) 00536 #alpha(alphaLegend) 00537 show() 00538 00539 00540 class ComplexTableObject(scalarObject): 00541 def __init__(self,dataCode,isSort1,iSubcase,dt): 00542 self.nonlinearFactor = None 00543 self.tableName = None 00544 self.analysisCode = None 00545 scalarObject.__init__(self,dataCode,iSubcase) 00546 self.gridTypes = {} 00547 self.translations = {} 00548 self.rotations = {} 00549 00550 self.dt = dt 00551 if isSort1: 00552 if dt is not None: 00553 self.add = self.addSort1 00554 ### 00555 else: 00556 assert dt is not None 00557 self.add = self.addSort2 00558 ### 00559 00560 def isImaginary(self): 00561 return True 00562 00563 def addF06Data(self,data,transient): 00564 if transient is None: 00565 for line in data: 00566 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = line 00567 self.gridTypes[nodeID] = gridType 00568 self.translations[self.dt][nodeID] = [v1,v2,v3] # dx,dy,dz 00569 self.rotations[self.dt][nodeID] = [v4,v5,v6] # rx,ry,rz 00570 ### 00571 return 00572 00573 (dtName,dt) = transient 00574 self.dataCode['name'] = dtName 00575 if dt not in self.translations: 00576 self.updateDt(self.dataCode,dt) 00577 00578 for line in data: 00579 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = line 00580 self.gridTypes[nodeID] = gridType 00581 self.translations[self.dt][nodeID] = [v1,v2,v3] # dx,dy,dz 00582 self.rotations[self.dt][nodeID] = [v4,v5,v6] # rx,ry,rz 00583 ### 00584 00585 def updateDt(self,dataCode,dt): 00586 self.dataCode = dataCode 00587 self.applyDataCode() 00588 if dt is not None: 00589 self.log.debug("updating %s...%s=%s iSubcase=%s" %(self.dataCode['name'],self.dataCode['name'],dt,self.iSubcase)) 00590 self.addNewTransient(dt) 00591 ### 00592 00593 def deleteTransient(self,dt): 00594 del self.translations[dt] 00595 del self.rotations[dt] 00596 00597 def getTransients(self): 00598 k = self.translations.keys() 00599 k.sort() 00600 return k 00601 00602 def addNewTransient(self,dt): 00603 """initializes the transient variables""" 00604 self.translations[dt] = {} 00605 self.rotations[dt] = {} 00606 00607 def add(self,dt,out): 00608 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = out 00609 #msg = "dt=%s nodeID=%s v1=%s v2=%s v3=%s" %(dt,nodeID,v1,v2,v3) 00610 #assert isinstance(nodeID,int),nodeID 00611 msg = "nodeID=%s v1=%s v2=%s v3=%s\n" %(nodeID,v1,v2,v3) 00612 msg += " v4=%s v5=%s v6=%s" %( v4,v5,v6) 00613 #print msg 00614 assert 0<nodeID<1000000000,msg # -1 00615 assert -0.5<dt,msg # remove 00616 assert isinstance(nodeID,int),msg 00617 #assert nodeID not in self.translations,'complexDisplacementObject - static failure' 00618 00619 self.gridTypes[nodeID] = self.recastGridType(gridType) 00620 self.translations[nodeID] = [v1,v2,v3] # dx,dy,dz 00621 self.rotations[nodeID] = [v4,v5,v6] # rx,ry,rz 00622 ### 00623 00624 def addSort1(self,dt,out): 00625 (nodeID,gridType,v1,v2,v3,v4,v5,v6) = out 00626 #msg = "dt=%s nodeID=%s v1=%s v2=%s v3=%s" %(dt,nodeID,v1,v2,v3) 00627 #print msg 00628 if dt not in self.translations: 00629 self.addNewTransient(dt) 00630 assert isinstance(nodeID,int),nodeID # remove 00631 msg = "nodeID=%s v1=%s v2=%s v3=%s\n" %(nodeID,v1,v2,v3) 00632 msg += " v4=%s v5=%s v6=%s" %( v4,v5,v6) 00633 #print msg 00634 assert 0<nodeID<1000000000,msg # -1 00635 assert -0.5<dt,msg # remove 00636 assert isinstance(nodeID,int),msg 00637 #assert nodeID not in self.translations,'complexDisplacementObject - static failure' 00638 00639 self.gridTypes[nodeID] = self.recastGridType(gridType) 00640 self.translations[dt][nodeID] = [v1,v2,v3] # dx,dy,dz 00641 self.rotations[dt][nodeID] = [v4,v5,v6] # rx,ry,rz 00642 00643 def addSort2(self,nodeID,data): 00644 [dt,gridType,v1,v2,v3,v4,v5,v6] = data 00645 00646 if dt not in self.translations: 00647 self.addNewTransient(dt) 00648 00649 msg = "dt=%s nodeID=%s v1=%s v2=%s v3=%s\n" %(dt,nodeID,v1,v2,v3) 00650 msg += " v4=%s v5=%s v6=%s" %( v4,v5,v6) 00651 #print msg 00652 assert 0<nodeID<1000000000,msg # -1 00653 assert -0.5<dt,msg # remove 00654 assert isinstance(nodeID,int),msg 00655 00656 self.gridTypes[nodeID] = self.recastGridType(gridType) 00657 self.translations[dt][nodeID] = [v1,v2,v3] # dx,dy,dz 00658 self.rotations[dt][nodeID] = [v4,v5,v6] # rx,ry,rz 00659 00660 def _writeMatlabTransient(self,name,iSubcase,f=None,isMagPhase=False): 00661 """ 00662 name = displacements 00663 """ 00664 #msg = [] 00665 times = self.translations.keys() 00666 nodes = self.translations[times[0]].keys() 00667 times.sort() 00668 nodes.sort() 00669 #nNodes = len(nodes) 00670 self.writeMatlabArgs(name,iSubcase,f) 00671 dtName = '%s' %(self.dataCode['name']) 00672 f.write('fem.%s(%i).nodes = %s;\n' %(name,iSubcase,nodes)) 00673 f.write('fem.%s(%i).%s = %s;\n' %(name,iSubcase,dtName,times)) 00674 00675 msgG = "fem.%s(%i).gridTypes = ['" %(name,iSubcase) 00676 for nodeID,gridType in sorted(self.gridTypes.items()): 00677 msgG += '%s' %(gridType) 00678 msgG += "'];\n" 00679 f.write(msgG) 00680 del msgG 00681 00682 for n,(dt,translations) in enumerate(sorted(self.translations.iteritems())): 00683 #msgT = 'fem.%s(%i).translations.%s(%i) = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00684 #msgR = 'fem.%s(%i).rotations.%s(%i) = zeros(%i,3);\n' %(name,iSubcase,dtName,n+1,nNodes) 00685 00686 msgT = 'fem.%s(%i).translations.%s(%i) = [' %(name,iSubcase,dtName,n+1) 00687 msgR = 'fem.%s(%i).rotations.%s(%i) = [' %(name,iSubcase,dtName,n+1) 00688 00689 i=0 00690 for nodeID,translation in sorted(translations.iteritems()): 00691 rotation = self.rotations[dt][nodeID] 00692 (dx,dy,dz) = translation 00693 (rx,ry,rz) = rotation 00694 00695 msgT += '[%s+%sj,%s+%sj,%s+%sj];' %(dx.real,dx.imag,dy.real,dy.imag,dz.real,dz.imag) 00696 msgR += '[%s+%sj,%s+%sj,%s+%sj];' %(rx.real,rx.imag,ry.real,ry.imag,rz.real,rz.imag) 00697 i+=1 00698 if i==100: 00699 msgT += '\n' 00700 msgR += '\n' 00701 i=0 00702 ### 00703 ### 00704 msgT += '];\n' 00705 msgR += '];\n' 00706 f.write(msgT) 00707 f.write(msgR) 00708 ### 00709 ### 00710 00711 def _writeF06Block(self,words,header,pageStamp,pageNum=1,f=None,isMagPhase=False): 00712 #words += self.getTableMarker() 00713 if isMagPhase: 00714 words += [' (MAGNITUDE/PHASE)\n',] 00715 else: 00716 words += [' (REAL/IMAGINARY)\n',] 00717 00718 words += [' \n',' POINT ID. TYPE T1 T2 T3 R1 R2 R3\n'] 00719 00720 msg = words 00721 for nodeID,translation in sorted(self.translations.iteritems()): 00722 rotation = self.rotations[nodeID] 00723 gridType = self.gridTypes[nodeID] 00724 00725 (dx,dy,dz) = translation 00726 (rx,ry,rz) = rotation 00727 00728 vals = [dx,dy,dz,rx,ry,rz] 00729 (vals2,isAllZeros) = self.writeImagFloats13E(vals) 00730 [dxr,dyr,dzr,rxr,ryr,rzr,dxi,dyi,dzi,rxi,ryi,rzi] = vals2 00731 msg.append('0 %12i %6s %13s %13s %13s %13s %13s %-s\n' %(nodeID,gridType,dxr,dyr,dzr,rxr,ryr,rzr.rstrip())) 00732 msg.append(' %12s %6s %13s %13s %13s %13s %13s %-s\n' %('','', dxi,dyi,dzi,rxi,ryi,rzi.rstrip())) 00733 ### 00734 msg.append(pageStamp+str(pageNum)+'\n') 00735 if f is not None: 00736 f.write(''.join(msg)) 00737 msg = [''] 00738 return (''.join(msg),pageNum) 00739 00740 def _writeF06TransientBlock(self,words,header,pageStamp,pageNum=1,f=None,isMagPhase=False): 00741 if isMagPhase: 00742 words += [' (MAGNITUDE/PHASE)\n',] 00743 else: 00744 words += [' (REAL/IMAGINARY)\n',] 00745 00746 words += [' \n',' POINT ID. TYPE T1 T2 T3 R1 R2 R3\n'] 00747 #words += self.getTableMarker() 00748 00749 msg = [] 00750 #assert f is not None 00751 for dt,translations in sorted(self.translations.iteritems()): 00752 #print "dt = ",dt 00753 #sys.stdout.flush() 00754 header[2] = ' %s = %10.4E\n' %(self.dataCode['name'],dt) 00755 msg += header+words 00756 for nodeID,translation in sorted(translations.iteritems()): 00757 rotation = self.rotations[dt][nodeID] 00758 gridType = self.gridTypes[nodeID] 00759 00760 (dx,dy,dz) = translation 00761 (rx,ry,rz) = rotation 00762 00763 vals = [dx,dy,dz,rx,ry,rz] 00764 (vals2,isAllZeros) = self.writeImagFloats13E(vals,isMagPhase) 00765 [dxr,dyr,dzr,rxr,ryr,rzr,dxi,dyi,dzi,rxi,ryi,rzi] = vals2 00766 if not isAllZeros: 00767 msg.append('0 %12i %6s %13s %13s %13s %13s %13s %-s\n' %(nodeID,gridType,dxr,dyr,dzr,rxr,ryr,rzr.rstrip())) 00768 msg.append(' %12s %6s %13s %13s %13s %13s %13s %-s\n' %('','', dxi,dyi,dzi,rxi,ryi,rzi.rstrip())) 00769 ### 00770 msg.append(pageStamp+str(pageNum)+'\n') 00771 if f is not None: 00772 f.write(''.join(msg)) 00773 msg = [''] 00774 pageNum+=1 00775 return (''.join(msg),pageNum-1) 00776 00777 def plot(self,nodeList=None,resultType='Translation',displayType='Real Imag',coord=3,markers=None, 00778 Title=None,hasLegend=True,Legend=None,xLabel=None,yLabel=None,alphaLegend=0.5): 00779 """ 00780 @param nodeList a list of the node IDs to plot vs the 00781 independent variable (default=None; all nodes) 00782 @param resultType the variable to plot ('Translation','Rotation') 00783 @param displayType 'Real Imag' or 'Mag Phase' 00784 @param coord the coordinate to plot (for <x,y,z>, x=0,y=1,z=2,Mag=3); 00785 default=Magnitude 00786 @param markers a list of colors/marker shapes for each line 00787 @param Title title of the plot (default=the object name) 00788 @param hasLegend should a legend be shown (default=False) 00789 @param Legend the list of the legend titles (default=No Legend) 00790 @param xLabel the name of the xAxis (default=the name of 00791 the independent variable; string) 00792 @param yLabel the name of the xAxis (default=the name of 00793 the dependent variable; string) 00794 @param alphaLegend the transparency of the legend; 00795 (0.0=solid; 1.0=transparent; default=0.5) 00796 00797 @todo fix alphaLegend; test options more... 00798 """ 00799 displayType = displayType.title() 00800 (results,nodeList,markers,Title,xLabel,yLabel) = getPlotData( 00801 self,nodeList,resultType,coord,markers,Title,hasLegend,Legend,xLabel,yLabel) 00802 00803 i = 0 00804 Labels = [] 00805 node0 = nodeList[0] 00806 Xs = sorted(results[node0].keys()) 00807 00808 (fig,ax) = plt.subplots(1) 00809 leg = plt.legend(loc='best', fancybox=True,alpha=0.5) 00810 for nodeID in nodeList: # translation/rotation 00811 result = results[nodeID] 00812 Ys = [] 00813 for dt,res in sorted(result.iteritems()): 00814 if coord==3: 00815 val = sqrt(res.dot(res)) 00816 else: 00817 val = res[coord] 00818 ### 00819 mag = abs(val) 00820 phase = angle(val,deg=True) 00821 Ys.append(val) 00822 Label = 'Node %s' %(nodeID) 00823 Labels.append(Label) 00824 ax.plot(Xs,Ys,markers[i]) 00825 #plot(Xs,Ys,Label) 00826 i+=1 00827 #print dir(leg) 00828 #leg.get_frame().set_alpha(0.5) 00829 ax.set_title(Title) 00830 #ax.set_legend(Labels) 00831 if hasLegend and Legend is None: 00832 plt.legend(Labels) 00833 elif hasLegend: 00834 plt.legend(Legend) 00835 #plt.axes 00836 #print dir(plt) 00837 ax.grid(True) 00838 ax.set_ylabel(yLabel) 00839 ax.set_xlabel(xLabel) 00840 #alpha(alphaLegend) 00841 show() 00842 00843 def getPlotData(obj,nodeList,resultType,coord,markers,Title,hasLegend,Legend,xLabel,yLabel): 00844 if Title is None: 00845 label = '' 00846 subtitle = '' 00847 if obj.label: 00848 label = ' - %s' %(obj.label) 00849 if obj.subtitle: 00850 subtitle = ' - %s' %(obj.subtitle) 00851 Title = '%s%s%s - Subcase %s' %(obj.__class__.__name__,label,subtitle,obj.iSubcase) 00852 00853 resultType = resultType.title() 00854 assert coord in [0,1,2,3],'invalid coord...options=[0,1,2,3]. coord=%s' %(coord) 00855 assert resultType in ['Translation','Rotation'],"invalid resultType...options=['Translation','Rotation']." 00856 00857 if xLabel is None: 00858 xLabel = obj.dataCode['name'].title() 00859 if yLabel is None: 00860 if coord==0: yLabel='X %s' %(resultType) 00861 elif coord==1: yLabel='Y %s' %(resultType) 00862 elif coord==2: yLabel='Z %s' %(resultType) 00863 elif coord==3: yLabel='%s (Magnitude)' %(resultType) 00864 else: raise RuntimeError('invalid coord...options=[0,1,2,3]. choice=%s' %(coord)) 00865 00866 (translations,rotations) = obj.getAsSort2() 00867 00868 if resultType=='Translation': 00869 results = translations 00870 else: 00871 results = rotations 00872 00873 nodeListAll = results.keys() 00874 if nodeList is None: 00875 nodeList = nodeListAll 00876 00877 if hasLegend and Legend is not None: 00878 assert len(nodeList)==len(Legend),'len(nodeList)=%s len(legend)=%s' %(len(nodeList),len(legend)) 00879 if markers==None: 00880 markers = ['-']*len(nodeList) 00881 #print "subcase = ",obj.iSubcase 00882 return (results,nodeList,markers,Title,xLabel,yLabel)