pyNastran
0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
|
00001 ## GNU Lesser General Public License 00002 ## 00003 ## Program pyNastran - a python interface to NASTRAN files 00004 ## Copyright (C) 2011-2012 Steven Doyle, Al Danial 00005 ## 00006 ## Authors and copyright holders of pyNastran 00007 ## Steven Doyle <mesheb82@gmail.com> 00008 ## Al Danial <al.danial@gmail.com> 00009 ## 00010 ## This file is part of pyNastran. 00011 ## 00012 ## pyNastran is free software: you can redistribute it and/or modify 00013 ## it under the terms of the GNU Lesser General Public License as published by 00014 ## the Free Software Foundation, either version 3 of the License, or 00015 ## (at your option) any later version. 00016 ## 00017 ## pyNastran is distributed in the hope that it will be useful, 00018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 ## GNU General Public License for more details. 00021 ## 00022 ## You should have received a copy of the GNU Lesser General Public License 00023 ## along with pyNastran. If not, see <http://www.gnu.org/licenses/>. 00024 ## 00025 # pylint: disable=C0103,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