pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
tableObject.py
Go to the documentation of this file.
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)
 All Classes Namespaces Files Functions Variables