ngtoucd.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 """
00004 ngtoucd - converts Netgen neutral finite element mesh files
00005           into unstructured cell data format
00006 
00007 Copyright (c) 2002-2005 Richard Boardman, Hans Fangohr
00008 
00009 ngtoucd is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 2
00012 
00013 ngtoucd is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with magpar; if not, write to the Free Software Foundation,
00020 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00021 
00022 This program was designed for magpar, so results may
00023 vary when used with other programs accepting AVS/UCD
00024 as an input file format
00025 
00026 """
00027 
00028 VERSION="0.2"
00029 
00030 import os, string, sys, time
00031 
00032 def readmesh(filename):
00033     """This will read the NETGEN neutral mesh 'filename' and return
00034     points, tetrahedra and triangles"""
00035     
00036     f = open(filename, 'r')
00037 
00038     #################################################################
00039     #
00040     # read the first line to get the number of points
00041     #
00042     #################################################################
00043 
00044     thisline         = f.readline()
00045     number_of_points = int(thisline)
00046 
00047     #################################################################
00048     #
00049     # read the points
00050     #
00051     #################################################################
00052 
00053     points = []
00054 
00055     for i in range(number_of_points):
00056         thisline  = f.readline()
00057         segments  = string.split(thisline[:-1])
00058         thispoint = list(map(lambda p: float(p), segments))
00059         points.append(thispoint)
00060 
00061     #################################################################
00062     #
00063     # now read all the volume elements
00064     # first, ascertain the number of volume elements
00065     #
00066     #################################################################
00067 
00068     thisline             = f.readline()
00069     number_of_tetrahedra = int(thisline)
00070 
00071     #################################################################
00072     #
00073     # then read and populate, keeping track
00074     # of the tetrahedra subdomain
00075     #
00076     #################################################################
00077     
00078     tetrahedra           = []
00079     tetrahedra_subdomain = []
00080 
00081     for i in range(number_of_tetrahedra):
00082         thisline = f.readline()
00083         segments = string.split(thisline[:-1])
00084         if len(segments) != 5:
00085             print "Found", len(segments), "elements, but expected 5"
00086             print segments
00087             raise "Oops", "File format error"
00088 
00089         tetrahedra_subdomain.append(int(segments[0])-1)
00090 
00091         # rpb, 17th March 2006 - updated to handle materials (note:
00092         # in netgen these are top-level objects [tlos])
00093         # original mapping was [a, b, c, d] (where a-d are points)
00094         # new mapping is [[a,b,c,d],m] (where m is a material ID)
00095         tetrahedron = [list(map(lambda t : int(t)-1, segments[1:5])), int(segments[0])]
00096 
00097         # netgen counts from 1 rather than from 0, hence int(t)-1
00098 
00099         tetrahedra.append(tetrahedron)
00100 
00101     #################################################################
00102     #
00103     # now for the surface elements
00104     # ascertain the number of surface elements
00105     #
00106     #################################################################
00107 
00108     thisline            = f.readline()
00109     number_of_triangles = int(thisline)
00110     triangles           = []
00111     triangles_subdomain = []
00112     for i in range(number_of_triangles):
00113         thisline = f.readline()
00114         segments = string.split(thisline[:-1])
00115         if len(segments) != 4:
00116             print "Found", len(segments), "elements, but expected 4"
00117             print segments
00118             raise "Oops", "File format error"
00119 
00120         triangles_subdomain.append(int(segments[0])-1)
00121         # similar adjustment for materials as with tetrahedra
00122         triangle = [list(map(lambda t : int(t)-1, segments[1:4])), int(segments[0])]
00123         triangles.append(triangle)
00124 
00125     #################################################################
00126     #
00127     # send back the read mesh
00128     #
00129     #################################################################
00130     
00131     return (points, tetrahedra, triangles, tetrahedra_subdomain, triangles_subdomain)
00132 
00133 def bail(message="Sorry, I don't understand. Bailing out..."):
00134     """A 'get-out' clause"""
00135     print message
00136     sys.exit(1)
00137 
00138 def initialise_file(file):
00139     """Attempt to remove the file first to avoid append issues"""
00140     try:
00141         os.remove(file)
00142     except:
00143         # no problem
00144         pass
00145 
00146 def writeln(line, file):
00147     """One-shot file line append; this keeps the code terse"""
00148     f = open(file, 'a')
00149     f.write(line + '\n')
00150     f.close()
00151 
00152 def stamp():
00153     """Format a time and a date for stdout feedback"""
00154     thistime = time.localtime()
00155     return "[%04d/%02d/%02d %02d:%02d:%02d] " % (thistime[0],
00156                                                  thistime[1],
00157                                                  thistime[2],
00158                                                  thistime[3],
00159                                                  thistime[4],
00160                                                  thistime[5])
00161 
00162 
00163 def info():
00164     """Output GPL details"""
00165     print """ngtoucd, copyright (c) 2002-2005 Richard Boardman, Hans Fangohr
00166 ngtoucd comes with ABSOLUTELY NO WARRANTY; for details see the file COPYING"""
00167 
00168 def writeucd():
00169     """Call readmesh to read the NETGEN mesh, then convert and write the UCD mesh"""
00170     info()
00171     al = len(sys.argv)
00172     if al < 2 or al > 3 or sys.argv[1] == '--help' or sys.argv[1] == '-h':
00173         bail("Usage: " + sys.argv[0] + " neutral.msh [ucdmesh.inp]")
00174 
00175     inputfile = sys.argv[1]
00176 
00177     if len(sys.argv) == 3:
00178         outputfile = sys.argv[2]
00179     else:
00180         outputfile = os.path.splitext(inputfile)[0] + ".inp"
00181 
00182     print
00183     print "About to read, check and process the neutral mesh", inputfile
00184     print "and then create the AVS/UCD mesh", outputfile
00185     print
00186 
00187     print stamp() + "Initialising file" + outputfile
00188     initialise_file(outputfile)
00189     print stamp() + "File " + outputfile + " initialised"
00190 
00191     print stamp() + "Attemping read of input " + inputfile
00192     (points, tetrahedra, triangles, tetrasub, trisub) = readmesh(inputfile)
00193     print stamp() + "Input file successfully read"
00194 
00195     print stamp() + "Points:     %d" % len(points)
00196     print stamp() + "Tetrahedra: %d [%d in subdomain]" % (len(tetrahedra), len(tetrasub))
00197     print stamp() + "Triangles:  %d [%d in subdomain]" % (len(triangles),  len(trisub))
00198 
00199     #################################################################
00200     #
00201     # the first line of a UCD file reads:
00202     # a b c d e
00203     #
00204     # where a is the number of nodes
00205     #       b is the number of cells
00206     #       c is the length of vector data associated with the nodes
00207     #       d is the length of vector data associated with the cells
00208     #       e is the length of vector data associated with the model
00209     #
00210     # example: 12 2 1 0 0
00211     #
00212     #################################################################
00213 
00214     # n.b. here the third integer indicates the number of placeholders
00215     
00216     print stamp() + "Creating descriptor [UCD]"
00217     writeln(str(len(points)) + " " + str(len(tetrahedra)) + " 3 0 0", outputfile)
00218     print stamp() + "UCD descriptor created"
00219     
00220     #################################################################
00221     #
00222     # then we have nodes in threespace, one line per node
00223     # n x y z
00224     # where n is the node ID -- integer (not necessarily sequential)
00225     #       x,y,z are the x, y and z coordinates
00226     #
00227     #################################################################
00228 
00229     print stamp() + "Now converting nodes"
00230     for i in range(len(points)):
00231         x, y, z = points[i][0], points[i][1], points[i][2]
00232         writeln(str(i+1) + " " + str(x) + " " + str(y) + " " + str(z), outputfile)
00233     print stamp() + "Nodes converted"
00234 
00235     #################################################################
00236     #
00237     # now the cells, one line/cell:
00238     #
00239     # c m t n1 n2 ... nn
00240     #
00241     # where c is the cell ID
00242     #       m is the material type (int, leave as 1 if we don't care)
00243     #       t is the cell type (prism|hex|pyr|tet|quad|tri|line|pt)
00244     #       n1...nn is a node ID list corresponding to cell vertices
00245     #
00246     #################################################################
00247 
00248     cellctr = 0
00249 
00250     print stamp() + "Converting tetrahedra"
00251 
00252     ### here we need to take extra care of the tetrahedra point write
00253     ### order to avoid "negative" volume issues
00254 
00255     for tetra in tetrahedra:
00256         tet = tetra[0] # just the tetrahedron; tetra[1] is the material
00257         tetorder  = [0, 2, 1, 3]
00258         tetstring =  " " + str(tet[tetorder[0]]+1)
00259         tetstring += " " + str(tet[tetorder[1]]+1)
00260         tetstring += " " + str(tet[tetorder[2]]+1)
00261         tetstring += " " + str(tet[tetorder[3]]+1)
00262         writeln(str(cellctr+1) + " " + str(tetra[1]) + " tet" + tetstring, outputfile)
00263         cellctr   += 1
00264 
00265     print stamp() + "Tetrahedra converted"
00266 
00267     #################################################################
00268     #
00269     # uncomment the following section to convert triangles as well
00270     # - since magpar will ignore these, leave away for the time being
00271     #
00272     # print stamp() + "Converting triangles"
00273     #
00274     # cellctr = 0
00275     # for triang in triangles:
00276     #     tri = triang[0] # just the triangle; triang[1] is the material
00277     #     tristring = ""
00278     #     for node in tri:
00279     #         tristring += " " + str(node+1)
00280     #     writeln(str(cellctr+1) + " " + str(triang[1]) + " tri" + ts, outputfile)
00281     #
00282     # print stamp() + "Triangles converted"
00283     #
00284     #################################################################
00285 
00286     #################################################################
00287     #
00288     # for the data vector associated with the nodes:
00289     #
00290     # first line tells us into which components the vector is divided
00291     #
00292     #   example: vector of 5 floats could be 3 3 1 1
00293     #            node scalar could be 1 1
00294     #
00295     # next lines, for each data component, use a cs label/unit pair
00296     #
00297     #   example: temperature, kelvin
00298     #
00299     # subsequent lines, for each node, the vector of associated data
00300     # in this order
00301     #
00302     #   example: 1 10\n2 15\n3 12.4\n4 9
00303     #
00304     #################################################################
00305 
00306     print stamp() + "Initialising placeholders"
00307 
00308     writeln("3 1 1 1", outputfile)
00309     writeln("M_x, none", outputfile)
00310     writeln("M_y, none", outputfile)
00311     writeln("M_z, none", outputfile)
00312     
00313     #################################################################
00314     #
00315     # create some initial scalar values; here, generally
00316     # +x=1.0 +y=+z=0.01*x (everything else)="\epsilon"
00317     #
00318     #################################################################
00319 
00320     scalarstring =  " 1.0 0.0 0.0"
00321 
00322     for i in range(len(points)):
00323         writeln(str(i+1) + scalarstring, outputfile)
00324 
00325     print stamp() + "Placeholders inserted"
00326 
00327     # all done
00328 
00329     print stamp() + "All finished"
00330 
00331 
00332     
00333 if __name__=="__main__":
00334     writeucd()

magpar - Parallel Finite Element Micromagnetics Package
Copyright (C) 2002-2009 Werner Scholz