pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
subcase.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 # pylint: disable=C0103,R0201
00026 import sys
00027 import warnings
00028 
00029 class Subcase(object):
00030     solCodeMap = {
00031                   1:  101,
00032                  21:  101,
00033                  24:  101,
00034                  26:  101,
00035                  61:  101,
00036                  64:  106,  # correct
00037                  66:  106,  # correct
00038                  68:  106,  # correct
00039                  76:  101,
00040                  99:  129,  # correct
00041                 144:  101,  # correct
00042                 187:  101,
00043              }
00044 
00045     def __init__(self, id=0):
00046         self.id = id
00047         self.params = {}
00048         self.sol = None
00049         #print "\n***adding subcase %s***" %(self.id)
00050 
00051     def get_stress_code(self, key, options, value):
00052         """@note the individual element must take
00053         the stressCode and reduce it to what the element can
00054         return.  For example, for an isotropic CQUAD4
00055         the fiber field doesnt mean anything.
00056         
00057         BAR       - no von mises/fiber
00058         ISOTROPIC - no fiber
00059         
00060         @todo how does the MATERIAL bit get turned on?  I'm assuming it's element dependent...
00061         """
00062         stressCode = 0
00063         if 'VONMISES'  in options:
00064             stressCode += 1
00065         if key == 'STRAIN':
00066             stressCode += 10 # 2+8=10 - fields 2 and 4
00067         if 'FIBER'     in options:
00068             stressCode += 4
00069         #if 'MATERIAL' in options:
00070         #    stressCode += 16  material coord (1) vs element (0)
00071         return stressCode
00072 
00073     def get_format_code(self, options, value):
00074         """@todo not done..."""
00075         formatCode = 0
00076         if 'REAL'  in options:
00077             formatCode += 1
00078         if 'IMAG'  in options:
00079             formatCode += 2
00080         if 'PHASE' in options:
00081             formatCode += 4
00082         formatCode = max(formatCode, 1)
00083         return formatCode
00084 
00085     def get_sort_code(self, options, value):
00086         sortCode = 0
00087         if 'COMPLEX' in options:
00088             sortCode += 1
00089         if 'SORT2'   in options:
00090             sortCode += 2
00091         if 'RANDOM'  in options:
00092             sortCode += 4
00093         return sortCode
00094 
00095     def get_device_code(self, options, value):
00096         deviceCode = 0
00097         if 'PRINT' in options:
00098             deviceCode += 1
00099         if 'PLOT'  in options:
00100             deviceCode += 2
00101         if 'PUNCH' in options:
00102             deviceCode += 4
00103         deviceCode = max(deviceCode, 1)
00104         #if deviceCode==0:
00105         #    deviceCode=1  # PRINT
00106         return deviceCode
00107         
00108     def get_analysis_code(self, sol):
00109         """
00110         8 - post-buckling (maybe 7 depending on NLPARM???)
00111 
00112         # not important
00113         3/4 - differential stiffness (obsolete)
00114         11  - old geometric nonlinear statics
00115         12  - contran (???)
00116         @todo verify
00117         """
00118         codes = {
00119                  101: 1,  # staics
00120                  103: 2,  # modes
00121                  105: 7,  # pre-buckling
00122                  106: 10, # nonlinear statics
00123                  107: 9,  # complex eigenvalues
00124                  108: 5,  # frequency
00125                  111: 5,
00126                  112: 6,
00127                  114: 1,
00128                  115: 2,
00129                  116: 7,
00130                  118: 5,
00131                  129: 6, # nonlinear
00132                  144: 1, # static aero
00133                  145: 1, # 
00134                  146: 1, # flutter
00135                  153: 10,
00136                  159: 6,  # transient thermal
00137                  }
00138         #print "sol=%s" %(sol)
00139         approachCode = codes[sol]
00140         #print 'approachCode = ',approachCode
00141         return approachCode
00142         
00143     def get_table_code(self, sol, tableName, options):
00144         if tableName in ['VECTOR', 'PRESSURE']:
00145             tableName = 'DISPLACEMENT' # equivalent tables...
00146 
00147         key = (sol, tableName)
00148         tables = { #SOL, tableName      tableCode
00149 
00150                   (101,'ACCELERATION'): 11,
00151                   (103,'ACCELERATION'): 11,
00152                   (106,'ACCELERATION'): 11,
00153                   (107,'ACCELERATION'): 11,
00154                   (108,'ACCELERATION'): 11,
00155                   (129,'ACCELERATION'): 11,
00156                  #(144,'ACCELERATION'): 11,
00157                   (145,'ACCELERATION'): 11,
00158                   (146,'ACCELERATION'): 11,
00159 
00160 
00161                   (101,'DISPLACEMENT'): 1,
00162                   (103,'DISPLACEMENT'): 7, # VECTOR
00163                   (105,'DISPLACEMENT'): 7,
00164                   (106,'DISPLACEMENT'): 1,
00165                   (107,'DISPLACEMENT'): 7,
00166                   (108,'DISPLACEMENT'): 1,
00167                   (109,'DISPLACEMENT'): 1,
00168                   (111,'DISPLACEMENT'): 7,
00169                   (112,'DISPLACEMENT'): 1,
00170                   (129,'DISPLACEMENT'): 7,
00171                  #(144,'DISPLACEMENT'): 1,
00172                   (145,'DISPLACEMENT'): 1,
00173                   (146,'DISPLACEMENT'): 1,
00174 
00175                   (101,'ESE'):          18, # energy
00176                   (103,'ESE'):          18, # energy
00177                   (105,'ESE'):          18, # energy
00178                   (106,'ESE'):          18, # energy
00179                   (107,'ESE'):          18, # energy
00180                   (108,'ESE'):          18, # energy
00181                   (109,'ESE'):          18, # energy
00182                   (110,'ESE'):          18, # energy
00183                   (111,'ESE'):          18, # energy
00184                   (112,'ESE'):          18, # energy
00185                   (145,'ESE'):          18, # energy
00186                   (146,'ESE'):          18, # energy
00187 
00188                   (101,'FORCE'):        3, # ???
00189                   (103,'FORCE'):        3, # ???
00190                   (105,'FORCE'):        3, # ???
00191                   (106,'FORCE'):        3, # ???
00192                   (107,'FORCE'):        4, # ???
00193                   (108,'FORCE'):        3, # ???
00194                   (111,'FORCE'):        3, # ???
00195                   (112,'FORCE'):        3, # ???
00196                   (129,'FORCE'):        3, # ???
00197                   (145,'FORCE'):        3, # ???
00198                   (146,'FORCE'):        3, # ???
00199 
00200                   (101,'GPFORCE'):      19,
00201                   (105,'GPFORCE'):      19,
00202                   (106,'GPFORCE'):      19,
00203                   (107,'GPFORCE'):      19,
00204                   (108,'GPFORCE'):      19,
00205                   (111,'GPFORCE'):      19,
00206                   (112,'GPFORCE'):      19,
00207                   (129,'GPFORCE'):      19,
00208                   (145,'GPFORCE'):      19,
00209                   (146,'GPFORCE'):      19,
00210 
00211                   (101,'GPSTRESS'):     20,
00212                   (105,'GPSTRESS'):     20,
00213                   (106,'GPSTRESS'):     20,
00214                   (107,'GPSTRESS'):     20,
00215                   (108,'GPSTRESS'):     20,
00216                   (111,'GPSTRESS'):     20,
00217                   (112,'GPSTRESS'):     20,
00218                   (129,'GPSTRESS'):     20,
00219                   (145,'GPSTRESS'):     20,
00220                   (146,'GPSTRESS'):     20,
00221 
00222                   (101,'GPSTRAIN'):     21,
00223                   (105,'GPSTRAIN'):     21,
00224                   (106,'GPSTRAIN'):     21,
00225                   (107,'GPSTRAIN'):     21,
00226                   (108,'GPSTRAIN'):     21,
00227                   (111,'GPSTRAIN'):     21,
00228                   (112,'GPSTRAIN'):     21,
00229                   (129,'GPSTRAIN'):     21,
00230                   (145,'GPSTRAIN'):     21,
00231                   (146,'GPSTRAIN'):     21,
00232 
00233                   (101,'MPCFORCES'):    3,
00234                   (103,'MPCFORCES'):    3,
00235                   (106,'MPCFORCES'):    3,
00236                   (108,'MPCFORCES'):    3,
00237                   (112,'MPCFORCES'):    3,
00238                   (129,'MPCFORCES'):    3,
00239                  #(144,'MPCFORCES'):    3,
00240                   (145,'MPCFORCES'):    3,
00241                   (146,'MPCFORCES'):    3,
00242 
00243                   (101,'OLOAD'):        2,
00244                   (103,'OLOAD'):        2,
00245                   (105,'OLOAD'):        2,
00246                   (106,'OLOAD'):        2,
00247                   (107,'OLOAD'):        2,
00248                   (108,'OLOAD'):        2,
00249                   (111,'OLOAD'):        2,
00250                   (112,'OLOAD'):        2,
00251                   (129,'OLOAD'):        2,
00252                  #(144,'OLOAD'):        2,
00253                   (145,'OLOAD'):        2,
00254                   (146,'OLOAD'):        2,
00255 
00256                   (101,'SPCFORCES'):    3,
00257                   (103,'SPCFORCES'):    3,
00258                   (105,'SPCFORCES'):    3,
00259                   (106,'SPCFORCES'):    3,
00260                   (107,'SPCFORCES'):    3,
00261                   (108,'SPCFORCES'):    3,
00262                   (110,'SPCFORCES'):    3,
00263                   (111,'SPCFORCES'):    3,
00264                   (112,'SPCFORCES'):    3,
00265                   (129,'SPCFORCES'):    3,
00266                  #(144,'SPCFORCES'):    3,
00267                   (145,'SPCFORCES'):    3,
00268                   (146,'SPCFORCES'):    3,
00269 
00270                   (101,'STRAIN'):       5,# 5/20/21 ???
00271                   (105,'STRAIN'):       5,
00272                   (106,'STRAIN'):       5,
00273                   (107,'STRAIN'):       5,
00274                   (108,'STRAIN'):       5,
00275                   (110,'STRAIN'):       5,
00276                   (111,'STRAIN'):       5,
00277                   (112,'STRAIN'):       5,
00278                   (129,'STRAIN'):       5,
00279                   (145,'STRAIN'):       5,
00280                   (146,'STRAIN'):       5,
00281 
00282                   (101,'STRESS'):       5,# 5/20/21 ???
00283                   (103,'STRESS'):       5,
00284                   (105,'STRESS'):       5,
00285                   (106,'STRESS'):       5,
00286                   (107,'STRESS'):       5,
00287                   (108,'STRESS'):       5,
00288                   (111,'STRESS'):       5,
00289                   (112,'STRESS'):       5,
00290                   (129,'STRESS'):       5,
00291                   (145,'STRESS'):       5,
00292                   (146,'STRESS'):       5,
00293 
00294                   (145,'SVECTOR'):      14,
00295 
00296                   (101,'FLUX'):         4,
00297                   (103,'FLUX'):         4,
00298                   (106,'FLUX'):         4,
00299                   (112,'FLUX'):         4,
00300                   (108,'FLUX'):         4,
00301                   (153,'FLUX'):         4,
00302                   (159,'FLUX'):         4,
00303 
00304                   (101,'THERMAL'):      3, # 3/4 ???
00305                   (159,'THERMAL'):      3, # 3/4 ???
00306 
00307                   (101,'VELOCITY'):    10,
00308                   (103,'VELOCITY'):    10,
00309                   (106,'VELOCITY'):    10,
00310                   (107,'VELOCITY'):    10,
00311                   (108,'VELOCITY'):    10,
00312                   (111,'VELOCITY'):    10,
00313                   (112,'VELOCITY'):    10,
00314                   (129,'VELOCITY'):    10,
00315                  #(144,'VELOCITY'):    10,
00316                   (145,'VELOCITY'):    10,
00317                   (146,'VELOCITY'):    10,
00318 
00319                   (101,'VUGRID'):    10,
00320 
00321                  }
00322         print("key=%s" %(str(key)))
00323         if key not in tables:
00324             raise KeyError(key)
00325         tableCode = tables[key]
00326         return tableCode
00327         
00328     def hasParameter(self, paramName):
00329         warnings.warn('hasParameter has been deprecated; use has_parameter',
00330                       DeprecationWarning, stacklevel=2)
00331         self.has_parameter(paramName)
00332 
00333     def getParameter(self, paramName):
00334         warnings.warn('getParameter has been deprecated; use get_parameter',
00335                       DeprecationWarning, stacklevel=2)
00336         self.get_parameter(paramName)
00337 
00338     def updateParamName(self, paramName):
00339         warnings.warn('updateParamName has been deprecated; use '
00340                       'update_param_name', DeprecationWarning, stacklevel=2)
00341         self.update_param_name(paramName)
00342 
00343     def writeSubcase(self, subcase0):
00344         warnings.warn('writeSubcase has been deprecated; use write_subcase',
00345                       DeprecationWarning, stacklevel=2)
00346         self.write_subcase(subcase0)
00347 
00348 #-----------------
00349     def has_parameter(self, paramName):
00350         if paramName in self.params:
00351             return True
00352         return False
00353 
00354     def get_parameter(self, paramName):
00355         paramName = self.update_param_name(paramName)
00356         if paramName not in self.params:
00357             raise KeyError('%s doesnt exist in subcase=%s in the case control deck.' %(paramName, self.id))
00358         return self.params[paramName][0:2]
00359 
00360     def update_param_name(self, paramName):
00361         """
00362         takes an abbreviated name and expands it so the user can type DISP or 
00363         DISPLACEMENT and get the same answer
00364         @todo not a complete list
00365         @warning fully tested yet...
00366         """
00367         #print 'paramName  = ',paramName
00368         if   paramName.startswith('ACCE'):  paramName = 'ACCELERATION'
00369         elif paramName.startswith('DESO'):  paramName = 'DESOBJ'
00370         elif paramName.startswith('DESS'):  paramName = 'DESSUB'
00371         elif paramName.startswith('DISP'):  paramName = 'DISPLACEMENT'
00372         elif paramName.startswith('EXPO'):  paramName = 'EXPORTLID'
00373         elif paramName.startswith('ELFO'):  paramName = 'FORCE'
00374         elif paramName.startswith('FORC'):  paramName = 'FORCE'
00375         elif paramName.startswith('FREQ'):  paramName = 'FREQUENCY'
00376         elif paramName.startswith('GPFO'):  paramName = 'GPFORCE'
00377         elif paramName == 'GPST':           raise SyntaxError('invalid GPST stress/strain')
00378         elif paramName.startswith('METH'):  paramName = 'METHOD'
00379         elif paramName.startswith('MPCF'):  paramName = 'MPCFORCES'
00380         elif paramName.startswith('OLOA'):  paramName = 'OLOAD'
00381         elif paramName.startswith('PRES'):  paramName = 'PRESSURE'
00382 
00383         elif paramName.startswith('SPCF'):  paramName = 'SPCFORCES'
00384 
00385         elif paramName.startswith('STRA'):  paramName = 'STRAIN'
00386         elif paramName.startswith('STRE'):  paramName = 'STRESS'
00387         elif paramName.startswith('SUPO'):  paramName = 'SUPORT1'
00388         elif paramName.startswith('SVEC'):  paramName = 'SVECTOR'
00389         elif paramName.startswith('THER'):  paramName = 'THERMAL'
00390         elif paramName.startswith('VECT'):  paramName = 'VECTOR'
00391         elif paramName.startswith('VELO'):  paramName = 'VELOCITY'
00392 
00393 
00394 
00395         #elif paramName.startswith('DFRE'):  paramName = 'D'
00396         #elif paramName.startswith('TEMP'):  paramName = 'TEMPERATURE'  # handled in caseControlDeck.py
00397         #print '*paramName = ',paramName
00398         return  paramName
00399 
00400     def _add_data(self, key, value, options, paramType):
00401         key = self.update_param_name(key)
00402         #print("adding iSubcase=%s key=|%s| value=|%s| options=|%s| "
00403         #      "paramType=%s" %(self.id, key, value, options, paramType))
00404         if isinstance(value, str) and value.isdigit():
00405             value = int(value)
00406 
00407         (key, value, options) = self._simplify_data(key, value, options,
00408                                                     paramType)
00409         self.params[key] = [value, options, paramType]
00410 
00411     def _simplify_data(self, key, value, options, paramType):
00412         if paramType == 'SET-type':
00413             #print("adding iSubcase=%s key=|%s| value=|%s| options=|%s| "
00414             #      "paramType=%s" %(self.id, key, value, options, paramType))
00415             values2 = []
00416             for (i, ivalue) in enumerate(value):
00417                 ivalue = ivalue.strip()
00418                 if ivalue.isdigit():
00419                     values2.append(int(ivalue))
00420                 else:
00421                     if value is 'EXCLUDE':
00422                         raise RuntimeError('EXCLUDE is not supported on CaseControlDeck SET card\n')
00423                     values2.append(ivalue)
00424                 ###
00425             ###
00426             
00427             ## @todo expand values with THRU and EXCLUDE
00428             ## @todo sort values
00429             ## @todo collapse values when printing
00430             
00431             #print "values2 = ",values2
00432             options = int(options)
00433             return (key, values2, options)
00434 
00435         elif paramType == 'CSV-type':
00436             #print("adding iSubcase=%s key=|%s| value=|%s| options=|%s| "
00437             #      "paramType=%s" %(self.id, key, value, options, paramType))
00438             if value.isdigit():  # PARAM,DBFIXED,-1
00439                 value = value
00440             ###
00441         else:
00442             #a = 'key=|%s|'       %(key)
00443             #b = 'value=|%s|'     %(value)
00444             #c = 'options=|%s|'   %(options)
00445             #d = 'paramType=|%s|' %(paramType)
00446             #print("_adding iSubcase=%s %-18s %-12s %-12s %-12s" %(self.id, a,
00447             #                                                      b, c, d))
00448             if isinstance(value, int) or value is None:
00449                 pass
00450             elif value.isdigit():  # STRESS = ALL
00451                 value = value
00452             #else: pass
00453         return (key, value, options)
00454 
00455     def get_op2_data(self, sol, solmap_toValue):
00456         self.sol = sol
00457         label = 'SUBCASE %s' %(self.id)
00458         op2Params = {'iSubcase':None, 'tables':[], 'analysisCodes':[], 
00459                      'deviceCodes':[], 'sortCodes':[], 'tableCodes':[],
00460                      'label':label,'subtitle':None, 'title':None,
00461                      'formatCodes':[], 'stressCodes':[], 'thermal':None}
00462         
00463         results = ['DISPLACEMENT', 'EKE', 'EDE', 'ELSDCON', 'ENTHALPY',
00464                    'EQUILIBRIUM', 'ESE', 'FLUX', 'FORCE', 'GPFORCE', 'GPKE',
00465                    'GPSDCON', 'GPSTRAIN', 'GPSTRESS', 'HOUTPUT', 'MODALKE',
00466                    'MODALSE', 'MPCFORCES', 'NLSTRESS', 'NOUTPUT', 'OLOAD',
00467                    'PFGRID', 'PFMODE', 'PFPANEL', 'RCROSS', 'RESVEC',
00468                    'SACCELERATION', 'SDISPACEMENT', 'SPCFORCES', 'STRAIN',
00469                    'STRESS', 'SVECTOR', 'SVELOCITY', 'THERMAL', 'VECTOR',
00470                    'VELOCITY', 'VUGRID', 'WEIGHTCHECK']
00471 
00472         # converts from solution 200 to solution 144
00473         if self.sol == 200 or 'ANALYSIS' in self.params:
00474             param = self.params['ANALYSIS']
00475             (value, options, paramType) = param
00476             
00477             sol = solmap_toValue[value.upper()]
00478             print("***value=%s sol=%s" %(value, sol))
00479         else:  # leaves SOL the same
00480             sol  = self.sol
00481         ###
00482         if sol in self.solCodeMap:  # reduces SOL 144 to SOL 101
00483             sol = self.solCodeMap[sol]
00484 
00485         for (key, param) in self.params.iteritems():
00486             key = key.upper()
00487             (value, options, paramType) = param
00488             #msg = ("  -key=|%s| value=|%s| options=%s paramType=|%s|"
00489             #    % (key, value, options, paramType))
00490 
00491         thermal = 0
00492         for (key, param) in self.params.iteritems():
00493             key = key.upper()
00494             (value, options, paramType) = param
00495             #msg = ("  *key=|%s| value=|%s| options=%s paramType=|%s|"
00496             #    % (key, value, options, paramType)
00497             #print(msg)
00498             #msg += self.printParam(key, param, printBeginBulk=False)
00499             if paramType == 'SUBCASE-type':
00500                 op2Params['iSubcase'].append(value)
00501             elif key in ['BEGIN', 'ECHO', 'ANALYSIS'] or 'SET' in key:
00502                 pass
00503             elif key == 'TEMPERATURE':
00504                 thermal = 1
00505             elif key in results:
00506                 sortCode   = self.get_sort_code(options, value)
00507                 deviceCode = self.get_device_code(options, value)
00508                 
00509                 if key in ['STRESS', 'STRAIN']:
00510                     stressCode = self.get_stress_code(key, options, value)
00511                     op2Params['stressCodes'].append(stressCode)
00512                 else:
00513                     op2Params['stressCodes'].append(0)
00514                 ###
00515                 
00516                 formatCode   = self.get_format_code(options, value)
00517                 tableCode    = self.get_table_code(sol, key, options)
00518                 analysisCode = self.get_analysis_code(sol)
00519                 
00520                 approachCode = analysisCode*10 + deviceCode
00521                 tCode        = tableCode*1000 + sortCode
00522                 op2Params['tables'].append(key)
00523                                 
00524                 op2Params['analysisCodes'].append(analysisCode)
00525                 #op2Params['approachCodes'].append(approachCode)
00526                 op2Params['deviceCodes'].append(deviceCode)
00527                 op2Params['formatCodes'].append(formatCode)
00528                 op2Params['sortCodes'].append(sortCode)
00529                 op2Params['tableCodes'].append(tableCode)
00530                 #analysisMethod = value
00531 
00532             #elif key in ['ADACT', 'ADAPT', 'AERCONFIG', 'TITLE', 'SUBTITLE',
00533             #             'LABEL', 'LOAD', 'SUPORT', 'SUPORT1', 'MPC', 'SPC',
00534             #            'TSTEPNL', 'NLPARM', 'TRIM', 'GUST', 'METHOD', 
00535             #            'DESOBJ', 'DESSUB', 'FMETHOD', 'SEALL']:
00536             else:
00537                 op2Params[key.lower()] = value
00538             ###
00539             #else:
00540             #    raise NotImplementedErrror('unsupported entry...\n%s' %(msg))
00541             ###
00542         ###
00543         op2Params['thermal'] = thermal
00544         
00545         print("\nThe estimated results...")
00546         for (key, value) in sorted(op2Params.iteritems()):
00547             if value is not None:
00548                 print("   key=|%s| value=|%s|" %(key, value))
00549         
00550 
00551     def print_param(self, key, param, printBeginBulk=True):
00552         """
00553         Prints a single entry of the a subcase from the global or local
00554         subcase list.
00555         """
00556         msg = ''
00557         #msg += 'id=%s   ' %(self.id)
00558         (value, options, paramType) = param
00559         
00560         spaces = ''
00561         if self.id > 0:
00562             spaces = '    '
00563 
00564         if paramType == 'SUBCASE-type':
00565             if self.id > 0:
00566                 msg += 'SUBCASE %s\n' %(self.id)
00567             ###
00568             #else:  global subcase ID=0 and is not printed
00569             #    pass
00570         elif paramType == 'KEY-type':
00571             #print "KEY-TYPE:  |%s|" %(value)
00572             assert value is not None, param
00573             msg += spaces + '%s\n' %(value)
00574         elif paramType == 'STRING-type':
00575             msg += spaces+'%s = %s\n' %(key, value)
00576         elif paramType == 'CSV-type':
00577             msg += spaces+'%s,%s,%s\n' %(key, value, options)
00578         elif paramType == 'STRESS-type':
00579             sOptions = ','.join(options)
00580             #print("sOptions = |%s|" %(sOptions))
00581             #print("STRESSTYPE key=%s value=%s options=%s"
00582             #    %(key, value, options))
00583             if len(sOptions) > 0:
00584                 msg += '%s(%s) = %s\n' %(key, sOptions, value)
00585             else:
00586                 msg += '%s = %s\n' %(key, value)
00587             msg = spaces + msg
00588 
00589         elif paramType == 'BEGIN_BULK-type':
00590             msg += '%s %s\n' %(key, value)
00591             if 'BEGIN BULK' not in msg:
00592                 msg = spaces + msg
00593             elif printBeginBulk:
00594                 pass
00595             else:
00596                 msg = ''
00597             ###
00598         elif paramType == 'SET-type':
00599             ## @todo collapse data...not written yet
00600             starter = 'SET %s = ' %(options)
00601             msg2 = spaces + starter
00602             nChars = len(msg2)
00603             
00604             i = 0
00605             while i < len(value):
00606                 #print "type(value[i]) = ",type(value[i])
00607                 newString = '%s, ' %(value[i])
00608                 #print "newString[%i] = |%s|" %(i,newString)
00609                 if len(msg2+newString) > 70:
00610                     msg += msg2+'\n'
00611                     msg2 = ' '*nChars+newString
00612                 else:
00613                     msg2 += newString
00614                 ###
00615                 i += 1
00616             ###
00617             msg += msg2.rstrip(' \n,')+'\n'
00618         else:
00619             # SET-type is not supported yet...
00620             raise NotImplementedError((key, param))
00621         ###
00622         #print "msg = |%r|" %(msg)
00623         return msg
00624 
00625     def crossReference(self, mesh):
00626         """
00627         @note this is not integrated and probably never will be as it's not really that necessary
00628         """
00629         print("keys = %s" %(sorted(self.params.keys())))
00630         if 'LOAD' in self.params:
00631             loadID = self.params['LOAD'][0]
00632             loadObj = mesh.loads[loadID]
00633             loadObj.crossReference(mesh)
00634         if 'SUPORT' in self.params:
00635             pass
00636         if 'MPC' in self.params:
00637             #mpcID = self.params['MPC'][0]
00638             #mpcObj = mesh.mpcs[mpcID]
00639             #mpcObj.crossReference(mesh)
00640             pass
00641         if 'SPC' in self.params:
00642             #spcID = self.params['SPC'][0]
00643             #print "SPC ID = ",spcID
00644             #spcObj = mesh.spcObject
00645             #spcObj.crossReference(spcID,mesh)
00646             pass
00647         if 'TSTEPNL' in self.params:
00648             tstepnlID = self.params['TSTEPNL'][0]
00649             tstepnlObj = mesh.tstepnl[tstepnlID]
00650             tstepnlObj.crossReference(mesh)
00651         if 'NLPARM' in self.params:
00652             nlparmID = self.params['NLPARM'][0]
00653             nlparmObj = mesh.nlparms[nlparmID]
00654             nlparmObj.crossReference(mesh)
00655         if 'TRIM' in self.params:
00656             trimID = self.params['TRIM'][0]
00657             trimObj = mesh.trims[trimID]
00658             trimObj.crossReference(mesh)
00659         if 'GUST' in self.params:
00660             gustID = self.params['GUST'][0]
00661             gustObj = mesh.gusts[gustID]
00662             gustObj.crossReference(mesh)
00663         if 'DLOAD' in self.params: # ???
00664             pass
00665     
00666     def finish_subcase(self):
00667         """
00668         Removes the subcase parameter from the subcase to avoid printing it in
00669         a funny spot
00670         """
00671         if 'SUBCASE' in self.params:
00672             del self.params['SUBCASE']
00673         #print "self.params %s = %s" %(self.id,self.params)
00674 
00675     def write_subcase(self, subcase0):
00676         """
00677         internal method to print a subcase
00678         @param self the subcase object
00679         @param subcase0 the global subcase
00680         """
00681         if self.id == 0:
00682             msg = str(self)
00683         else:
00684             msg = 'SUBCASE %s\n' %(self.id)
00685             for (key, param) in self.subcase_sorted(self.params.items()):
00686                 if key in subcase0.params and subcase0.params[key] == param:
00687                     pass # dont write global subcase parameters
00688                 else:
00689                     if 'key' == 'BEGIN':
00690                         continue
00691                     else:
00692                         #print "key=%s param=%s" %(key, param)
00693                         (value, options, paramType) = param
00694                         #print("  *key=|%s| value=|%s| options=%s "
00695                         #      "paramType=|%s|" % (key, value, options,
00696                         #                          paramType))
00697                         msg += self.print_param(key, param,
00698                                                 printBeginBulk=False)
00699                         #print ""
00700                     ###
00701                 ###
00702         
00703         ## self.id>0 and 'BEGIN' in self.params used to prevent printing of
00704         ## BEGIN BULK multiple times
00705         if self.id > 0 and 'BEGIN' in self.params:
00706             msg += self.print_param('BEGIN', self.params['BEGIN'])
00707         return msg
00708 
00709     def subcase_sorted(self, listA):
00710         """
00711         does a "smart" sort on the keys such that SET cards increment in
00712         numerical order.
00713         @param self
00714           the subcase object
00715         @param listA
00716           the list of subcase list objects
00717         @retval listB
00718           the sorted version of listA
00719         """
00720         # presort the list to put all the SET cards next to each other
00721         listA.sort()
00722         
00723         i = 0 # needed in case the loop doesnt execute
00724         iSet = None # index of first SET card in the deck
00725         setDict    = {} 
00726         listBefore = []
00727         listAfter  = []
00728         setKeys    = []
00729         for (i, entry) in enumerate(listA):
00730             key = entry[0]
00731             if 'SET' in key[0:3]:
00732                 if key == 'SET': # handles "SET = ALL"
00733                     key = 0
00734                 else: # handles "SET 100 = 1,2,3"
00735                     sline = key.split(' ')
00736                     key = int(sline[1])
00737 
00738                 # store the integer ID and the SET-type list
00739                 setDict[key] = entry
00740                 setKeys.append(key)
00741             else:
00742                 # only store the entries before the SET cards
00743                 listBefore.append(entry)
00744                 if iSet:
00745                     break
00746         
00747         # grab the other entries
00748         listAfter = listA[i+1:]
00749         
00750         # write the SET cards in a sorted order
00751         setList = []
00752         for key in sorted(setKeys):
00753             setList.append(setDict[key])
00754         
00755         # combine all the cards
00756         listB = listBefore+setList+listAfter
00757         return listB
00758 
00759     def __repr__(self):
00760         """
00761         Prints out every entry in the subcase.  Skips parameters already in
00762         the global subcase.
00763         """
00764         #msg = "-------SUBCASE %s-------\n" %(self.id)
00765         msg = ''
00766         if self.id > 0:
00767             msg += 'SUBCASE %s\n' %(self.id)
00768         ###
00769 
00770         for (key, param) in self.subcase_sorted(self.params.items()):
00771             if 'key' == 'BEGIN':
00772                 continue
00773             else:
00774                 #print "key=%s param=%s" %(key,param)
00775                 (value, options, paramType) = param
00776                 #print "  ?*key=|%s| value=|%s| options=%s paramType=|%s|" %(key,value,options,paramType)
00777                 msg += self.print_param(key, param, printBeginBulk=False)
00778                 #print ""
00779             ###
00780         ###
00781         if self.id > 0 and 'BEGIN' in self.params: # prevents 2 BEGIN BULKs
00782             msg += self.print_param('BEGIN', self.params['BEGIN'])
00783         return msg
00784 
 All Classes Namespaces Files Functions Variables