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,R0902,R0904,R0914,C0301 00026 00027 from __future__ import division, print_function 00028 import sys 00029 from numpy import allclose, isinf 00030 00031 def is_same(value1, value2): 00032 """ 00033 checks to see if 2 values are the same 00034 @note this method is used by almost every card when printing 00035 """ 00036 #print "value=%s default=%s" %(value1,value2) 00037 if isinstance(value1, str) or value1 is None: 00038 if value1 == value2: 00039 return True 00040 return False 00041 elif (value1 == value2 or type(value1) == type(value2) and 00042 not isinf(value1) and allclose(value1, value2)): 00043 #print "value=%s value2=%s same=%s" %(value1, value2, True) 00044 return True 00045 #print "value1=%s value2=%s same=%s" %(value1, value2, False) 00046 return False 00047 00048 def set_blank_if_default(value, default): 00049 """ 00050 Used when setting the output data of a card to clear default values 00051 @param value 00052 the field value the may be set to None (blank) if value=default 00053 @param default 00054 the default value for the field 00055 @note 00056 this method is used by almost every card when printing 00057 """ 00058 if is_same(value, default): 00059 return None 00060 return value 00061 00062 def set_default_if_blank(value, default): 00063 """ 00064 used when initializing a card and the default value isnt set 00065 used on PBARL 00066 """ 00067 if value is None or value == '': 00068 return default 00069 return value 00070 00071 def print_scientific_8(value): 00072 """ 00073 Prints a value in 8-character scientific notation. 00074 This is a sub-method and shouldnt typically be called 00075 @see print_float for a better method 00076 """ 00077 #print "scientific...%s" %(value) 00078 pythonValue = '%8.11e' % (value) 00079 #print "pythonValue = ",pythonValue 00080 (svalue, sExponent) = pythonValue.strip().split('e') 00081 exponent = int(sExponent) # removes 0s 00082 #print "svalue=%s exponent=%s" %(svalue,exponent) 00083 00084 if abs(value)<0.01: 00085 sign = '-' 00086 else: 00087 sign = '+' 00088 sExp2 = str(exponent).strip('-+') # the exponent will be added later... 00089 #print "sExp2 = ",sExp2 00090 00091 value2 = float(svalue) 00092 #lenSValue = len(svalue) 00093 00094 lenSExp = len(sExp2)+1 # the plus 1 is for the sign 00095 leftover = 8-lenSExp 00096 00097 #svalue2 = svalue.strip('0') 00098 00099 if value < 0: 00100 #print "sExp2 = ",sExp2 00101 Format = "%%1.%sf" % (leftover-3) 00102 else: 00103 #print "greater..." 00104 Format = "%%1.%sf" % (leftover-2) 00105 00106 #print("Format = ",Format) 00107 svalue3 = Format % (value2) 00108 #print("svalue3 = ",svalue3) 00109 svalue4 = svalue3.strip('0') 00110 field = "%8s" % (svalue4 + sign +sExp2) 00111 #print("fieldA = ", field) 00112 00113 #print("Format=%s svalue4=%s sExp2=%s" %(Format,svalue4,sExp2)) 00114 #field = "%8s" %(svalue4 + sign +sExp2) 00115 #print("fieldB = ",field) 00116 00117 #if '+' in field and '-' in field: 00118 #print("scientific...value=%s field=%s" %(value, field)) 00119 return field 00120 00121 def print_float_8(value, tol=0.): 00122 """ 00123 Prints a float in nastran 8-character width syntax using the 00124 highest precision possbile. 00125 @todo bad for small values...positive or negative... 00126 @warning hasnt really be tested for tolerancing 00127 """ 00128 #value = round(value, 4) 00129 #print "float...%s" % value 00130 if abs(value) <= tol: # tol=1e-8 00131 #print "below tol %s" %(value) 00132 field = "%8s" % ('0.') 00133 else: 00134 if value > 0.: # positive, not perfect... 00135 #print("positive") 00136 00137 if value < 5e-8: ## @todo does this work properly with tol 00138 #print("scientific") 00139 field = print_scientific_8(value) 00140 return field 00141 elif value < 0.001: 00142 #print "A" 00143 #print value 00144 field = print_scientific_8(value) 00145 field2 = "%8.7f" % (value) # small value 00146 field2 = field2.strip('0 ') 00147 00148 #if 'e' not in field: 00149 field1 = field.replace('-', 'e-') 00150 00151 #print("value=|%s| field1=|%s| field2=|%s|" %(value, field, 00152 # field2)) 00153 #print("same - ", float(field1)==float(field2)) 00154 if field2 == '.': 00155 return "%8s" % (field) 00156 if len(field2) <= 8 and float(field1) == float(field2): 00157 field = field2 00158 #print("*field = ",field) 00159 field = field.strip(' 0') 00160 00161 #print "AA" 00162 #print "field = ",field 00163 #print "field1 = ",field1 00164 #print "field2 = ",field2 00165 #print "" 00166 ### 00167 elif value < 0.1: 00168 #print "B*" 00169 field = "%8.7f" % (value) 00170 #field = field.strip('0 ') 00171 #print field 00172 #field = field[1:] 00173 elif value < 1.: 00174 field = "%8.7f" % (value) 00175 elif value < 10: 00176 field = "%8.6f" % (value) 00177 elif value < 100.: 00178 field = "%8.5f" % (value) 00179 elif value < 1000.: 00180 field = "%8.4f" % (value) 00181 elif value < 10000.: 00182 field = "%8.3f" % (value) 00183 elif value < 100000.: 00184 field = "%8.2f" % (value) 00185 elif value < 1000000.: 00186 field = "%8.1f" % (value) 00187 else: # big value 00188 #print "big" 00189 field = "%8.1f" % (value) 00190 if field.index('.') < 8: 00191 field = '%8.1f' % (round(value)) 00192 field = field[0:8] 00193 #field = '%7s.' %(int(field)) 00194 assert '.' != field[0], field 00195 else: 00196 field = print_scientific_8(value) 00197 ### 00198 return field 00199 ### 00200 ### 00201 else: 00202 #print "negative" 00203 if value > -5e-7: ## @todo does this work properly with tol 00204 #print "really small" 00205 field = print_scientific_8(value) 00206 return field 00207 elif value > -0.01: # -0.001 00208 #print "tiny" 00209 field = print_scientific_8(value) 00210 field2 = "%8.6f" % (value) # small value 00211 field2 = field2.strip('0 ') 00212 00213 # get rid of the first minus sign, add it on afterwards 00214 field1 = '-'+field.strip(' 0-').replace('-', 'e-') 00215 00216 #print "value=%s field=%s field1=%s field2=%s" %(value, 00217 # field[1:], field1,field2) 00218 #print "same - ",float(field1)==float(field2) 00219 if len(field2) <= 8 and float(field1) == float(field2): 00220 field = field2.rstrip(' 0') 00221 field = field.replace('-0.', '-.') 00222 00223 #print "AA" 00224 #print "field = ",field 00225 #print "field1 = ",field1 00226 #print "field2 = ",field2 00227 #print "" 00228 ### 00229 #elif value>-0.01: 00230 # #print "A" 00231 # field = "%8.8f" %(value) # -0.001>x>-0.01..should be 4 00232 # field = '-'+field[2:] 00233 elif value > -0.1: 00234 #print "B" 00235 # -0.01 >x>-0.1...should be 5 (maybe scientific...) 00236 field = "%8.6f" % (value) 00237 field = field.replace('-0.', '-.') 00238 elif value > -1.: 00239 #print "C" 00240 # -0.1 >x>-1.....should be 6, but the baseline 0 is kept... 00241 field = "%8.6f" % (value) 00242 field = field.replace('-0.', '-.') 00243 elif value > -10.: 00244 field = "%8.5f" % (value) # -1 >x>-10 00245 elif value > -100: 00246 field = "%8.4f" % (value) # -10 >x>-100 00247 elif value > -1000: 00248 field = "%8.3f" % (value) # -100 >x>-1000 00249 elif value > -10000: 00250 field = "%8.2f" % (value) # -1000 >x>-10000 00251 elif value > -100000: 00252 field = "%8.1f" % (value) # -10000>x>-100000 00253 else: 00254 field = "%8.1f" % (value) 00255 if field.index('.') < 8: 00256 field = '%7s.' % (int(round(value, 0))) 00257 assert '.' != field[0], field 00258 else: 00259 field = print_scientific_8(value) 00260 ### 00261 return field 00262 ### 00263 ### 00264 field = field.strip(' 0') 00265 field = '%8s' % (field) 00266 ### 00267 #print len(field) 00268 #print "value=|%s| field=|%s|\n" %(value, field) 00269 assert len(field) == 8, ('value=|%s| field=|%s| is not 8 characters ' 00270 'long, its %s' %(value, field, len(field))) 00271 return field 00272 00273 def print_field(value, tol=0.): 00274 """ 00275 prints a single 8-character width field 00276 @param value the value to print 00277 @param tol the abs(tol) to consider value=0 (default=0.) 00278 @retval field an 8-character (tested) string 00279 """ 00280 if isinstance(value, int): 00281 field = "%8s" % (value) 00282 elif isinstance(value, float): 00283 field = print_float_8(value) 00284 elif value is None: 00285 field = " " 00286 else: 00287 field = "%8s" % (value) 00288 if len(field) != 8: 00289 msg = 'field=|%s| is not 8 characters long...rawValue=|%s|' % (field, 00290 value) 00291 raise RuntimeError(msg) 00292 return field 00293 00294 #def printCard(fields,size=8, tol=0.): 00295 #""" 00296 #prints a nastran-style card with 8 or 16-character width fields 00297 #@param fields all the fields in the BDF card (no blanks) 00298 #@param tol the abs(tol) to consider value=0 (default=0.) 00299 #@param size the width of a field (size=8 or 16) 00300 #@warning 8 or 16 is required, but 16 is not checked for 00301 #""" 00302 #if size==8: 00303 # return self.printCard_8(fields) 00304 #else: 00305 # return self.printCard_16(fields) 00306 ### 00307 00308 def printCard(fields, tol=0.): 00309 """ 00310 Prints a nastran-style card with 8-character width fields. 00311 @param fields all the fields in the BDF card (no blanks) 00312 @param tol the abs(tol) to consider value=0 (default=0.) 00313 @note A small field format follows the 8-8-8-8-8-8-8-8 = 80 00314 format where the first 8 is the card name or blank (continuation). 00315 The last 8-character field indicates an optional continuation, 00316 but because it's a left-justified unneccessary field, 00317 printCard doesnt use it. 00318 """ 00319 #print fields 00320 try: 00321 out = '%-8s' % (fields[0]) 00322 except: 00323 print("ERROR! fields=%s" %(fields)) 00324 sys.stdout.flush() 00325 raise 00326 00327 for i in xrange(1, len(fields)): 00328 field = fields[i] 00329 try: 00330 out += print_field(field, tol=tol) 00331 #print "|%r|" %(printField(field)) 00332 except: 00333 print("bad fields = %s" % (fields)) 00334 raise 00335 if i % 8 == 0: # allow 1+8 fields per line 00336 #print "-------------------------" 00337 #print "out = ***\n%s***" %(out) 00338 #print "fields = ",fields[:i+1] 00339 out = out.rstrip(' ') 00340 #print "out[-1] = |%r|" %(out[-1]) 00341 if out[-1] == '\n': # empty line 00342 out += '+' 00343 out += '\n ' 00344 ### 00345 ### 00346 #print "out = ",out 00347 out = out.rstrip(' \n+')+'\n' # removes blank lines at the end of cards 00348 return out 00349 00350 def print_int_card(fields, tol=0.): 00351 """ 00352 All fields (other than the first field must be integers. 00353 This is used to speed up SET cards. 00354 Prints a nastran-style card with 8-character width fields. 00355 @warning Blanks are not allowed! 00356 """ 00357 try: 00358 out = '%-8s' % (fields[0]) 00359 except: 00360 print("ERROR! fields=%s" % (fields)) 00361 sys.stdout.flush() 00362 raise 00363 00364 for i in xrange(1, len(fields)): 00365 field = fields[i] 00366 try: 00367 out += "%8i" % (field) # balks if you have None or string fields 00368 except: 00369 print("bad fields = %s" % (fields)) 00370 raise 00371 if i % 8 == 0: # allow 1+8 fields per line 00372 out = out.rstrip(' ') 00373 out += '\n ' 00374 ### 00375 ### 00376 out = out.rstrip(' \n+')+'\n' # removes blank lines at the end of cards 00377 return out 00378 00379 def main(): 00380 #print printField(1e20) 00381 #printField(-0.021004) 00382 #print printField(-4.21704e-6) 00383 #print printField(4.21704e-6) 00384 #print printField(8.17272e-6) 00385 #print printField(10300000.0) 00386 #print printField(-10300000.0) 00387 if 1: # works 00388 print_field(-0.021004) 00389 00390 field = print_field(1e20); assert ' 1.+20' == field,'|%s|' %(field) 00391 field = print_field(-.723476); assert '-.723476' == field,'|%s|' %(field) 00392 field = print_field(125000. ); assert ' 125000.' == field,'|%s|' %(field) 00393 field = print_field(12500000.); assert ' 1.25+7' == field,'|%s|' %(field) 00394 field = print_field(47.77267); assert '47.77267' == field,'|%s|' %(field) 00395 field = print_field(.001); assert ' .001' == field,'|%s|' %(field) 00396 field = print_field(.0000001); assert '.0000001' == field,'|%s|' %(field) 00397 field = print_field(-5.007e-3); assert '-5.007-3' == field,'|%s|' %(field) 00398 field = print_field(-0.0748662); assert '-.074866' == field,'|%s|' %(field) 00399 field = print_field(-999999.); assert '-999999.' == field,'|%s|' %(field) 00400 field = print_field(7.4851e-4); assert '7.4851-4' == field,'|%s|' %(field) 00401 00402 #print(printField(12500000.)) 00403 #print(printField(47.77267)) 00404 #print(printField(.0000001)) 00405 #print(printField(-5.007e-3)) 00406 00407 00408 #print(printField(1.60665017692e-09)) 00409 #print(printField(3.22614998029e-08)) 00410 #print(printField(1.33564999731e-09)) 00411 print(print_field(-0.00082999792)) 00412 00413 if __name__ == '__main__': 00414 main()