pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
fieldWriter.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,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()
 All Classes Namespaces Files Functions Variables