pyNastran  0.5.0
pyNastran BDF Reader/Writer, OP2 Parser, and GUI
bdf_writeMesh.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,C0111,W0612,R0912,R0914,R0904,W0613,E1101
00026 
00027 from __future__ import division, print_function
00028 
00029 from pyNastran.bdf.fieldWriter import printCard
00030 
00031 class WriteMesh(object):
00032     def __init__(self):
00033         pass
00034 
00035     def echoBDF(self, infileName):
00036         """
00037         This method removes all comment lines from the bdf
00038         A write method is stil required.
00039         @todo maybe add the write method
00040         """
00041         self.cardsToRead = set([])
00042         return self.readBDF(infileName)
00043 
00044     def autoRejectBDF(self, infileName):
00045         """
00046         This method parses supported cards, but does not group them into
00047         nodes, elements, properties, etc.
00048         @todo maybe add the write method
00049         """
00050         self.autoReject = True
00051         return self.readBDF(infileName)
00052 
00053     def write_elements_as_CTRIA3(self):
00054         """
00055         takes the cquad4 elements and splits them
00056         @retval msg  string representation of the elements
00057         """
00058         eids = self.elementIDs()
00059         #print "eids = ",eids
00060         nextEID = max(eids)+1  # set the new ID
00061         msg = '$ELEMENTS\n'
00062         for eid, element in sorted(self.elements.iteritems()):
00063             if element.Is('CQUAD4'):
00064                 msg += element.writeAsCTRIA3(nextEID)
00065                 nextEID += 1
00066             else:
00067                 msg += str(element)
00068             ###
00069         ###
00070         return msg
00071 
00072     def write_DMIGs(self):
00073         msg = ''
00074         for (name, dmig) in sorted(self.dmigs.iteritems()):
00075             msg += str(dmig)
00076         for (name, dmi) in sorted(self.dmis.iteritems()):
00077             msg += str(dmi)
00078         for (name, dmij) in sorted(self.dmijs.iteritems()):
00079             msg += str(dmij)
00080         for (name, dmiji) in sorted(self.dmijis.iteritems()):
00081             msg += str(dmiji)
00082         for (name, dmik) in sorted(self.dmiks.iteritems()):
00083             msg += str(dmik)
00084         return msg
00085 
00086     def write_common(self):
00087         """
00088         method to write the common outputs so none get missed...
00089         @param self the object pointer
00090         @retval msg part of the bdf
00091         """
00092         msg = ''
00093         msg += self.write_rigid_elements()
00094         msg += self.write_DMIGs()
00095         msg += self.write_loads()
00096         msg += self.write_dynamic()
00097         msg += self.write_aero()
00098         msg += self.write_aero_control()
00099         msg += self.write_flutter()
00100         msg += self.write_thermal()
00101         msg += self.write_thermal_materials()
00102 
00103         msg += self.write_constraints()
00104         msg += self.write_optimization()
00105         msg += self.write_tables()
00106         msg += self.write_sets()
00107         msg += self.write_rejects()
00108         msg += self.write_coords()
00109         return msg
00110 
00111     def writeBDFAsPatran(self, outFileName='fem.out.bdf', debug=False):
00112         """
00113         Writes a bdf with properties & elements interspersed like how
00114         Patran writes the bdf.  This takes longer than the write method
00115         but makes it easier to compare to a Patran-formatted bdf.
00116         @param self the object pointer
00117         @param outFileName the name to call the output bdf
00118         @param debug developer debug (unused)
00119         """
00120         msg  = self.write_header()
00121         msg += self.write_params()
00122         msg += self.write_nodes()
00123 
00124         msg += self.write_elements_properties()
00125         msg += self.write_materials()
00126 
00127         msg += self.write_common()
00128         msg += 'ENDDATA\n'
00129 
00130         fname = self.print_filename(outFileName)
00131         self.log.debug("***writing %s" %(fname))
00132         
00133         outfile = open(outFileName,'wb')
00134         outfile.write(msg)
00135         outfile.close()
00136     
00137     def writeBDF(self, outFileName='fem.out.bdf', debug=False):
00138         """
00139         Writes the bdf.  It groups the various sections together to make it
00140         easy to find cards.  This method is slightly more stable than 
00141         writeAsPatran due to the properties sometimes being a little funny.
00142         @param self the object pointer
00143         @param outFileName the name to call the output bdf
00144         @param debug developer debug (unused)
00145         """
00146         msg  = self.write_header()
00147         msg += self.write_params()
00148         msg += self.write_nodes()
00149 
00150         msg += self.write_elements()
00151         msg += self.write_properties()
00152         msg += self.write_materials()
00153 
00154         msg += self.write_common()
00155         msg += 'ENDDATA\n'
00156 
00157         fname = self.print_filename(outFileName)
00158         self.log.debug("***writing %s" %(fname))
00159 
00160         outfile = open(outFileName, 'wb')
00161         outfile.write(msg)
00162         outfile.close()
00163 
00164     def write_as_CTRIA3(self, outFileName='fem.out.bdf', debug=False):
00165         """
00166         Writes a series of CQUAD4s as CTRIA3s.  All other cards are echoed.
00167         @param self the object pointer
00168         @param outFileName the name to call the output bdf
00169         @param debug developer debug (unused)
00170         @warning not tested in a long time
00171         """
00172         msg  = self.write_header()
00173         msg += self.write_params()
00174         msg += self.write_nodes()
00175         msg += self.write_elements_as_CTRIA3()
00176         msg += self.write_properties()
00177         msg += self.write_materials()
00178 
00179         msg += self.write_common()
00180         msg += 'ENDDATA\n'
00181 
00182         fname = self.print_filename(outFileName)
00183         self.log.debug("***writing %s" % (fname))
00184 
00185         outfile = open(outFileName, 'wb')
00186         outfile.write(msg)
00187         outfile.close()
00188 
00189     def write_header(self):
00190         """
00191         Writes the executive and case control decks.
00192         @param self the object pointer
00193         """
00194         msg  = self.write_executive_control_deck()
00195         msg += self.write_case_control_deck()
00196         return msg
00197 
00198     def write_executive_control_deck(self):
00199         """
00200         Writes the executive control deck.
00201         @param self the object pointer
00202         """
00203         msg = '$EXECUTIVE CONTROL DECK\n'
00204         
00205         if self.sol == 600:
00206             newSol = 'SOL 600,%s' % (self.solMethod)
00207         else:
00208             newSol = 'SOL %s' % (self.sol)
00209         
00210         if self.iSolLine is not None:
00211             self.executive_control_lines[self.iSolLine] = newSol
00212 
00213         for line in self.executive_control_lines:
00214             msg += line+'\n'
00215         return msg
00216 
00217     def write_case_control_deck(self):
00218         """
00219         Writes the Case Control Deck.
00220         @param self the object pointer
00221         """
00222         msg = ''
00223         if self.caseControlDeck:
00224             msg += '$CASE CONTROL DECK\n'
00225             msg += str(self.caseControlDeck)
00226         assert 'BEGIN BULK' in msg, msg
00227 
00228         return msg
00229 
00230     def write_params(self):
00231         """writes the PARAM cards"""
00232         msg = ''
00233         if self.params:
00234             msg += '$PARAMS\n'
00235         #print "self.nodes = ",self.nodes
00236         for (key, param) in sorted(self.params.iteritems()):
00237             #print "param = ",param
00238             msg += str(param)
00239         return msg
00240 
00241     def write_nodes(self):
00242         """writes the NODE-type cards"""
00243         msg = []
00244         if self.nodes:
00245             msg = ['$NODES\n']
00246             if self.gridSet:
00247                 msg.append(str(self.gridSet))
00248             for (nid, node) in sorted(self.nodes.iteritems()):
00249                 msg.append(str(node))
00250 
00251         if 0:
00252             self.write_nodes_associated()
00253 
00254         if self.spoints:
00255             msg.append('$SPOINTS\n')
00256             msg.append(str(self.spoints))
00257         ###
00258         return ''.join(msg)
00259 
00260     def write_nodes_associated(self):
00261         """
00262         Writes the NODE-type in associated and unassociated groups.
00263         @warning Sometimes crashes, probably on invalid BDFs.
00264         """
00265         msg = ''
00266 
00267         associatedNodes = set([])
00268         for (eid, element) in self.elements.iteritems():
00269             print(element)
00270             associatedNodes = associatedNodes.union(set(element.nodeIDs()))
00271 
00272         allNodes = set(self.nodes.keys())
00273         unassociatedNodes = list(allNodes.difference(associatedNodes))
00274         #missingNodes = allNodes.difference(
00275         associatedNodes = list(associatedNodes)
00276 
00277 
00278         if associatedNodes:
00279             msg += '$ASSOCIATED NODES\n'
00280             if self.gridSet:
00281                 msg += str(self.gridSet)
00282             for key in sorted(associatedNodes):
00283                 msg += str(self.nodes[key])
00284 
00285         if unassociatedNodes:
00286             msg += '$UNASSOCIATED NODES\n'
00287             if self.gridSet and not associatedNodes:
00288                 msg += str(self.gridSet)
00289             for key in sorted(unassociatedNodes):
00290                 if key in self.nodes:
00291                     msg += str(self.nodes[key])
00292                 else:
00293                     msg += '$ Missing NodeID=%s' % (key)
00294         return msg
00295 
00296     def write_elements(self):
00297         """writes the elements in a sorted order"""
00298         msg = []
00299         if self.elements:
00300             msg = ['$ELEMENTS\n']
00301             for (eid, element) in sorted(self.elements.iteritems()):
00302                 try:
00303                     msg.append(str(element))
00304                 except:
00305                     print('failed printing element...'
00306                           'type=%s eid=%s' %(element.type,eid))
00307                     raise
00308                 ###
00309         return ''.join(msg)
00310 
00311     def write_rigid_elements(self):
00312         """writes the rigid elements in a sorted order"""
00313         msg = []
00314         if self.rigidElements:
00315             msg += '$RIGID ELEMENTS\n'
00316             for (eid, element) in sorted(self.rigidElements.iteritems()):
00317                 try:
00318                     msg.append(str(element))
00319                 except:
00320                     print('failed printing element...'
00321                           'type=%s eid=%s' %(element.type,eid))
00322                     raise
00323                 ###
00324         return ''.join(msg)
00325 
00326     def write_properties(self):
00327         """writes the properties in a sorted order"""
00328         msg = ''
00329         if self.properties:
00330             msg += '$PROPERTIES\n'
00331             for (pid, prop) in sorted(self.properties.iteritems()):
00332                 msg += str(prop)
00333         return msg
00334 
00335     def write_elements_properties(self):
00336         """writes the elements and properties in and interspersed order"""
00337         msg = []
00338         missingProperties = []
00339         if self.properties:
00340             msg = ['$ELEMENTS_WITH_PROPERTIES\n']
00341 
00342         eidsWritten = []
00343         for (pid, prop) in sorted(self.properties.iteritems()):
00344             eids = self.getElementIDsWithPID(pid)
00345 
00346             if eids:
00347                 msg.append(str(prop))
00348                 eids.sort()
00349                 for eid in eids:
00350                     element = self.Element(eid)
00351                     try:
00352                         msg.append(str(element))
00353                     except:
00354                         print('failed printing element...'
00355                               'type=%s eid=%s' %(element.type,eid))
00356                         raise
00357                 ###
00358                 eidsWritten += eids
00359             else:
00360                 missingProperties.append(str(prop))
00361             ###
00362         ###
00363 
00364         eidsMissing = set(self.elements.keys()).difference(set(eidsWritten))
00365         if eidsMissing:
00366             msg.append('$ELEMENTS_WITH_NO_PROPERTIES '
00367                        '(PID=0 and unanalyzed properties)\n')
00368             for eid in sorted(eidsMissing):
00369                 element = self.Element(eid)
00370                 try:
00371                     msg.append(str(element))
00372                 except:
00373                     print('failed printing element...'
00374                           'type=%s eid=%s' %(element.type, eid))
00375                     raise
00376                 ###
00377             ###
00378 
00379         if missingProperties:
00380             msg.append('$UNASSOCIATED_PROPERTIES\n')
00381             for missingProperty in missingProperties:
00382                 msg.append(str(missingProperty))
00383         return ''.join(msg)
00384 
00385     def write_materials(self):
00386         """writes the materials in a sorted order"""
00387         msg = ''
00388         if self.materials:
00389             msg += '$MATERIALS\n'
00390             for (mid, material) in sorted(self.materials.iteritems()):
00391                 msg += str(material)
00392             for (mid, material) in sorted(self.creepMaterials.iteritems()):
00393                 msg += str(material)
00394             for (mid, material) in sorted(self.materialDeps.iteritems()):
00395                 msg += str(material)
00396         return msg
00397 
00398     def write_thermal_materials(self):
00399         """writes the thermal materials in a sorted order"""
00400         msg = ''
00401         if self.thermalMaterials:
00402             msg += '$THERMAL MATERIALS\n'
00403             for (mid, material) in sorted(self.thermalMaterials.iteritems()):
00404                 msg += str(material)
00405         return msg
00406 
00407     def write_constraints(self):
00408         """writes the constraint cards sorted by ID"""
00409         msg = ''
00410         if self.suports:
00411             msg += '$CONSTRAINTS\n'
00412             for suport in self.suports:
00413                 msg += str(suport)
00414             ###
00415 
00416         if self.spcs or self.spcadds:
00417             msg += '$SPCs\n'
00418             strSPC = str(self.spcObject2)
00419             if strSPC:
00420                 msg += strSPC
00421             else:
00422                 for (spcID, spcadd) in sorted(self.spcadds.iteritems()):
00423                     msg += str(spcadd)
00424                 for (spcID, spcs) in sorted(self.spcs.iteritems()):
00425                     for spc in spcs:
00426                         msg += str(spc)
00427                     ###
00428                 ###
00429             ###
00430         ###
00431         
00432         if self.mpcs or self.mpcadds:
00433             msg += '$MPCs\n'
00434             strMPC = str(self.mpcObject2)
00435             if strMPC:
00436                 msg += strMPC
00437             else:
00438                 for (mpcID, mpcadd) in sorted(self.mpcadds.iteritems()):
00439                     msg += str(mpcadd)
00440                 for (mpcID, mpcs) in sorted(self.mpcs.iteritems()):
00441                     for mpc in mpcs:
00442                         msg += str(mpc)
00443         return msg
00444 
00445     def write_loads(self):
00446         """writes the load cards sorted by ID"""
00447         msg = ''
00448         if self.loads:
00449             msg += '$LOADS\n'
00450             for (key, loadcase) in sorted(self.loads.iteritems()):
00451                 for load in loadcase:
00452                     try:
00453                         msg += str(load)
00454                     except:
00455                         print('failed printing load...type=%s key=%s'
00456                             %(load.type, key))
00457                         raise
00458         return msg
00459 
00460     def write_optimization(self):
00461         """writes the optimization cards sorted by ID"""
00462         msg = ''
00463         if (self.dconstrs or self.desvars or self.ddvals or self.dresps 
00464           or self.dvprels or self.dvmrels or self.doptprm or self.dlinks):
00465             msg += '$OPTIMIZATION\n'
00466             for (ID, dconstr) in sorted(self.dconstrs.iteritems()):
00467                 msg += str(dconstr)
00468             for (ID, desvar) in sorted(self.desvars.iteritems()):
00469                 msg += str(desvar)
00470             for (ID, ddval) in sorted(self.ddvals.iteritems()):
00471                 msg += str(ddval)
00472             for (ID, dlink) in sorted(self.dlinks.iteritems()):
00473                 msg += str(dlink)
00474             for (ID, dresp) in sorted(self.dresps.iteritems()):
00475                 msg += str(dresp)
00476             for (ID, dvmrel) in sorted(self.dvmrels.iteritems()):
00477                 msg += str(dvmrel)
00478             for (ID, dvprel) in sorted(self.dvprels.iteritems()):
00479                 msg += str(dvprel)
00480             for (ID, equation) in sorted(self.dequations.iteritems()):
00481                 msg += str(equation)
00482             if self.doptprm is not None:
00483                 msg += str(self.doptprm)
00484         return msg
00485 
00486     def write_tables(self):
00487         """writes the TABLEx cards sorted by ID"""
00488         msg = ''
00489         if self.tables:
00490             msg += '$TABLES\n'
00491             for (ID, table) in sorted(self.tables.iteritems()):
00492                 msg += str(table)
00493         if self.randomTables:
00494             msg += '$RANDOM TABLES\n'
00495             for (ID, table) in sorted(self.randomTables.iteritems()):
00496                 msg += str(table)
00497         return msg
00498 
00499     def write_sets(self):
00500         """writes the SETx cards sorted by ID"""
00501         msg = ''
00502         if (self.sets or self.setsSuper or self.asets or self.bsets or
00503             self.csets or self.qsets):
00504             msg += '$SETS\n'
00505             for (ID, setObj) in sorted(self.sets.iteritems()):  # dict
00506                 msg += str(setObj)
00507             for setObj in self.asets:  # list
00508                 msg += str(setObj)
00509             for setObj in self.bsets:  # list
00510                 msg += str(setObj)
00511             for setObj in self.csets:  # list
00512                 msg += str(setObj)
00513             for setObj in self.qsets:  # list
00514                 msg += str(setObj)
00515             for (ID, setObj) in sorted(self.setsSuper.iteritems()):  # dict
00516                 msg += str(setObj)
00517         return msg
00518 
00519     def write_dynamic(self):
00520         """writes the dynamic cards sorted by ID"""
00521         msg = ''
00522         if (self.dareas or self.nlparms or self.frequencies or self.methods or
00523             self.cMethods or self.tsteps or self.tstepnls):
00524             msg += '$DYNAMIC\n'
00525             for (ID, method) in sorted(self.methods.iteritems()):
00526                 msg += str(method)
00527             for (ID, cMethod) in sorted(self.cMethods.iteritems()):
00528                 msg += str(cMethod)
00529             for (ID, darea) in sorted(self.dareas.iteritems()):
00530                 msg += str(darea)
00531             for (ID, nlparm) in sorted(self.nlparms.iteritems()):
00532                 msg += str(nlparm)
00533             for (ID, tstep) in sorted(self.tsteps.iteritems()):
00534                 msg += str(tstep)
00535             for (ID, tstepnl) in sorted(self.tstepnls.iteritems()):
00536                 msg += str(tstepnl)
00537             for (ID, freq) in sorted(self.frequencies.iteritems()):
00538                 msg += str(freq)
00539         return msg
00540         
00541     def write_aero(self):
00542         """writes the aero cards"""
00543         msg = ''
00544         if (self.aero or self.aeros or self.gusts or self.caeros 
00545         or self.paeros or self.trims):
00546             msg = '$AERO\n'
00547             for (ID, caero) in sorted(self.caeros.iteritems()):
00548                 msg += str(caero)
00549             for (ID, paero) in sorted(self.paeros.iteritems()):
00550                 msg += str(paero)
00551             for (ID, spline) in sorted(self.splines.iteritems()):
00552                 msg += str(spline)
00553             for (ID, trim) in sorted(self.trims.iteritems()):
00554                 msg += str(trim)
00555 
00556             for (ID, aero) in sorted(self.aero.iteritems()):
00557                 msg += str(aero)
00558             for (ID, aero) in sorted(self.aeros.iteritems()):
00559                 msg += str(aero)
00560 
00561             for (ID, gust) in sorted(self.gusts.iteritems()):
00562                 msg += str(gust)
00563         return msg
00564 
00565     def write_aero_control(self):
00566         """writes the aero control surface cards"""
00567         msg = ''
00568         if (self.aefacts or self.aeparams or self.aelinks or self.aelists or
00569             self.aestats or self.aesurfs):
00570             msg = '$AERO CONTROL SURFACES\n'
00571             for (ID, aelinks) in sorted(self.aelinks.iteritems()):
00572                 for aelink in aelinks:
00573                     msg += str(aelink)
00574             for (ID, aeparam) in sorted(self.aeparams.iteritems()):
00575                 msg += str(aeparam)
00576             for (ID, aestat) in sorted(self.aestats.iteritems()):
00577                 msg += str(aestat)
00578 
00579             for (ID, aelist) in sorted(self.aelists.iteritems()):
00580                 msg += str(aelist)
00581             for (ID, aesurf) in sorted(self.aesurfs.iteritems()):
00582                 msg += str(aesurf)
00583             for (ID, aefact) in sorted(self.aefacts.iteritems()):
00584                 msg += str(aefact)
00585         return msg
00586 
00587     def write_flutter(self):
00588         """writes the flutter cards"""
00589         msg = []
00590         if (self.flfacts or self.flutters or self.mkaeros):
00591             msg = ['$FLUTTER\n']
00592             for (ID, flfact) in sorted(self.flfacts.iteritems()):
00593                 #if ID!=0:
00594                 msg.append(str(flfact))
00595             for (ID, flutter) in sorted(self.flutters.iteritems()):
00596                 msg.append(str(flutter))
00597             for mkaero in self.mkaeros:
00598                 msg.append(str(mkaero))
00599         return ''.join(msg)
00600 
00601     def write_thermal(self):
00602         """writes the thermal cards"""
00603         msg = ''
00604         # PHBDY
00605         
00606         if self.phbdys or self.convectionProperties or self.bcs:
00607             # self.thermalProperties or
00608             msg = '$THERMAL\n'
00609 
00610             for (key, phbdy) in sorted(self.phbdys.iteritems()):
00611                 msg += str(phbdy)
00612 
00613             #for key,prop in sorted(self.thermalProperties.iteritems()):
00614             #    msg += str(prop)
00615             for (key, prop) in sorted(self.convectionProperties.iteritems()):
00616                 msg += str(prop)
00617 
00618             # BCs
00619             for (key, bcs) in sorted(self.bcs.iteritems()):
00620                 for bc in bcs: # list
00621                     msg += str(bc)
00622                 ###
00623             ###
00624         return msg
00625 
00626     def write_coords(self):
00627         """writes the coordinate cards in a sorted order"""
00628         msg = ''
00629         if len(self.coords) > 1:
00630             msg += '$COORDS\n'
00631         for (ID, coord) in sorted(self.coords.iteritems()):
00632             if ID != 0:
00633                 msg += str(coord)
00634         return msg
00635 
00636     def write_rejects(self):
00637         """
00638         writes the rejected (processed) cards and the rejected unprocessed
00639         cardLines
00640         """
00641         msg = ''
00642         if self.reject_cards:
00643             msg += '$REJECTS\n'
00644             for reject_card in self.reject_cards:
00645                 try:
00646                     msg += printCard(reject_card)
00647                 except RuntimeError:
00648                     for field in reject_card:
00649                         if field is not None and '=' in field:
00650                             raise SyntaxError('cannot reject equal signed '
00651                                           'cards\ncard=%s\n' %(reject_card))
00652                     raise
00653 
00654         if self.rejects:
00655             msg += '$REJECT_LINES\n'
00656         for reject_lines in self.rejects:
00657             if reject_lines[0][0] == ' ':
00658                 continue
00659             else:
00660                 for reject in reject_lines:
00661                     reject2 = reject.rstrip()
00662                     if reject2:
00663                         msg += str(reject2)+'\n'
00664         return msg
00665 
 All Classes Namespaces Files Functions Variables