1
# Copyright (C) 2006 Anders Logg
2
# Licensed under the GNU LGPL Version 2.1
4
# Modified by Garth N. Wells (gmsh function)
5
# Modified by Alexander H. Jarosch (gmsh fix)
6
# Modified by Angelo Simone (Gmsh and Medit fix)
7
# Modified by Andy R. Terrel (gmsh fix and triangle function)
8
# Modified by Magnus Vikstrom (metis and scotch function)
9
# Modified by Bartosz Sawicki (diffpack function)
10
# Modified by Gideon Simpson (Exodus II function)
11
# Modified by Arve Knudsen (make into module, abaqus support)
12
# Modified by Kent-Andre Mardal (Star-CD function)
13
# Modified by Nuno Lopes (fix for emc2 mesh format (medit version 0))
14
""" Module for converting various mesh formats.
19
from dolfin_utils.commands import getoutput
24
def format_from_suffix(suffix):
25
"Return format for given suffix"
28
elif suffix == "mesh":
30
elif suffix == "gmsh":
38
elif suffix == "grid":
42
elif suffix == "ncdf":
48
elif suffix == "vrt" or suffix == "cel":
51
_error("Sorry, unknown suffix %s." % suffix)
53
def mesh2xml(ifilename, ofilename):
54
"""Convert between .mesh and .xml, parser implemented as a
60
3 = read number of vertices
62
5 = read 'Triangles' or 'Tetrahedra'
63
6 = read number of cells
69
print "Converting from Medit format (.mesh) to DOLFIN XML format"
72
ifile = open(ifilename, "r")
73
ofile = open(ofilename, "w")
75
# Scan file for cell type
81
line = ifile.readline()
89
if line == "Dimension" or line == " Dimension":
90
line = ifile.readline()
93
cell_type = "triangle"
96
cell_type = "tetrahedron"
100
# Check that we got the cell type
101
if cell_type == None:
102
_error("Unable to find cell type.")
104
# Step to beginning of file
108
write_header_mesh(ofile, cell_type, dim)
114
num_vertices_read = 0
120
line = ifile.readline()
132
if line == "Dimension" or line == " Dimension":
138
if line == "Vertices" or line == " Vertices":
141
num_vertices = int(line)
142
write_header_vertices(ofile, num_vertices)
146
(x, y, tmp) = line.split()
151
(x, y, z, tmp) = line.split()
155
write_vertex(ofile, num_vertices_read, x, y, z)
156
num_vertices_read +=1
157
if num_vertices == num_vertices_read:
158
write_footer_vertices(ofile)
161
if (line == "Triangles" or line == " Triangles") and num_dims == 2:
163
if line == "Tetrahedra" and num_dims == 3:
166
num_cells = int(line)
167
write_header_cells(ofile, num_cells)
171
(n0, n1, n2, tmp) = line.split()
175
write_cell_triangle(ofile, num_cells_read, n0, n1, n2)
177
(n0, n1, n2, n3, tmp) = line.split()
182
write_cell_tetrahedron(ofile, num_cells_read, n0, n1, n2, n3)
184
if num_cells == num_cells_read:
185
write_footer_cells(ofile)
190
# Check that we got all data
192
print "Conversion done"
194
_error("Missing data, unable to convert")
197
write_footer_mesh(ofile)
203
def gmsh2xml(ifilename, ofilename):
204
"""Convert between .gmsh v2.0 format (http://www.geuz.org/gmsh/) and .xml,
205
parser implemented as a state machine:
207
0 = read 'MeshFormat'
208
1 = read mesh format data
209
2 = read 'EndMeshFormat'
211
4 = read number of vertices
215
8 = read number of cells
221
print "Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format"
224
ifile = open(ifilename, "r")
225
ofile = open(ofilename, "w")
227
# Scan file for cell type
230
line = ifile.readline()
238
if line.find("$Elements") == 0:
240
line = ifile.readline()
241
num_cells = int(line)
242
num_cells_counted = 0
244
_error("No cells found in gmsh file.")
245
line = ifile.readline()
247
# Now iterate through elements to find largest dimension. Gmsh
248
# format might include elements of lower dimensions in the element list.
249
# We also need to count number of elements of correct dimensions.
250
# Also determine which vertices are not used.
255
while line.find("$EndElements") == -1:
256
element = line.split()
257
elem_type = int(element[1])
258
num_tags = int(element[2])
261
cell_type = "triangle"
263
node_num_list = [int(node) for node in element[3 + num_tags:]]
264
vertices_2_used.extend(node_num_list)
268
cell_type = "tetrahedron"
270
vertices_2_used = None
271
node_num_list = [int(node) for node in element[3 + num_tags:]]
272
vertices_3_used.extend(node_num_list)
274
line = ifile.readline()
277
line = ifile.readline()
279
# Check that we got the cell type and set num_cells_counted
280
if cell_type == None:
281
_error("Unable to find cell type.")
283
num_cells_counted = dim_3_count
284
vertex_set = set(vertices_3_used)
285
vertices_3_used = None
287
num_cells_counted = dim_2_count
288
vertex_set = set(vertices_2_used)
289
vertices_2_used = None
292
for n,v in enumerate(vertex_set):
295
# Step to beginning of file
299
write_header_mesh(ofile, cell_type, dim)
301
# Initialise node list (gmsh does not export all vertexes in order)
308
num_vertices_read = 0
314
line = ifile.readline()
326
if line == "$MeshFormat":
329
(version, file_type, data_size) = line.split()
332
if line == "$EndMeshFormat":
338
#num_vertices = int(line)
339
num_vertices = len(vertex_dict)
340
write_header_vertices(ofile, num_vertices)
343
(node_no, x, y, z) = line.split()
344
if vertex_dict.has_key(int(node_no)):
345
node_no = vertex_dict[int(node_no)]
348
nodelist[int(node_no)] = num_vertices_read
349
write_vertex(ofile, num_vertices_read, x, y, z)
350
num_vertices_read +=1
352
if num_vertices == num_vertices_read:
353
write_footer_vertices(ofile)
356
if line == "$EndNodes":
359
if line == "$Elements":
362
write_header_cells(ofile, num_cells_counted)
365
element = line.split()
366
elem_type = int(element[1])
367
num_tags = int(element[2])
368
if elem_type == 2 and dim == 2:
369
node_num_list = [vertex_dict[int(node)] for node in element[3 + num_tags:]]
370
for node in node_num_list:
371
if not node in nodelist:
372
_error("Vertex %d of triangle %d not previously defined." %
373
(node, num_cells_read))
374
n0 = nodelist[node_num_list[0]]
375
n1 = nodelist[node_num_list[1]]
376
n2 = nodelist[node_num_list[2]]
377
write_cell_triangle(ofile, num_cells_read, n0, n1, n2)
379
elif elem_type == 4 and dim == 3:
380
node_num_list = [vertex_dict[int(node)] for node in element[3 + num_tags:]]
381
for node in node_num_list:
382
if not node in nodelist:
383
_error("Vertex %d of tetrahedron %d not previously defined." %
384
(node, num_cells_read))
385
n0 = nodelist[node_num_list[0]]
386
n1 = nodelist[node_num_list[1]]
387
n2 = nodelist[node_num_list[2]]
388
n3 = nodelist[node_num_list[3]]
389
write_cell_tetrahedron(ofile, num_cells_read, n0, n1, n2, n3)
392
if num_cells_counted == num_cells_read:
393
write_footer_cells(ofile)
398
# Check that we got all data
400
print "Conversion done"
402
_error("Missing data, unable to convert \n\ Did you use version 2.0 of the gmsh file format?")
405
write_footer_mesh(ofile)
411
def triangle2xml(ifilename, ofilename):
412
"""Convert between triangle format (http://www.cs.cmu.edu/~quake/triangle.html) and .xml. The
413
given ifilename should be the prefix for the corresponding .node, and .ele files.
416
def get_next_line (fp):
417
"""Helper function for skipping comments and blank lines"""
420
_error("Hit end of file prematurely.")
422
if not (line.startswith('#') or line == ''):
424
return get_next_line(fp)
427
print "Converting from Triangle format {.node, .ele} to DOLFIN XML format"
430
node_file = open(ifilename+".node", "r")
431
ele_file = open(ifilename+".ele", "r")
432
ofile = open(ofilename, "w")
436
num_nodes, dim, attr, bound = map(int, get_next_line(node_file).split())
437
while len(nodes) < num_nodes:
438
node, x, y = get_next_line(node_file).split()[:3]
439
nodes[int(node)] = (float(x), float(y))
441
# Read all the triangles
443
num_tris, n_per_tri, attrs = map(int, get_next_line(ele_file).split())
444
while len(tris) < num_tris:
445
tri, n1, n2, n3 = map(int, get_next_line(ele_file).split()[:4])
446
tris[tri] = (n1, n2, n3)
448
# Write everything out
449
write_header_mesh(ofile, "triangle", 2)
450
write_header_vertices(ofile, num_nodes)
451
node_off = 0 if nodes.has_key(0) else -1
452
for node, node_t in nodes.iteritems():
453
write_vertex(ofile, node+node_off, node_t[0], node_t[1], 0.0)
454
write_footer_vertices(ofile)
455
write_header_cells(ofile, num_tris)
456
tri_off = 0 if tris.has_key(0) else -1
457
for tri, tri_t in tris.iteritems():
458
write_cell_triangle(ofile, tri+tri_off, tri_t[0] + node_off,
459
tri_t[1] + node_off, tri_t[2] + node_off)
460
write_footer_cells(ofile)
461
write_footer_mesh(ofile)
469
def xml_old2xml(ifilename, ofilename):
470
"Convert from old DOLFIN XML format to new."
472
print "Converting from old (pre DOLFIN 0.6.2) to new DOLFIN XML format..."
475
ifile = open(ifilename, "r")
476
ofile = open(ofilename, "w")
478
# Scan file for cell type (assuming there is just one)
484
line = ifile.readline()
488
if "<triangle" in line:
489
cell_type = "triangle"
492
elif "<tetrahedron" in line:
493
cell_type = "tetrahedron"
497
# Step to beginning of file
500
# Read lines and make changes
504
line = ifile.readline()
509
line = "<dolfin xmlns:dolfin=\"http://www.fenicsproject.org\">\n"
511
line = " <mesh celltype=\"%s\" dim=\"%d\">\n" % (cell_type, dim)
512
if dim == 2 and " z=\"0.0\"" in line:
513
line = line.replace(" z=\"0.0\"", "")
515
line = line.replace(" name=", " index=")
516
if " name =" in line:
517
line = line.replace(" name =", " index=")
519
line = line.replace("n0", "v0")
521
line = line.replace("n1", "v1")
523
line = line.replace("n2", "v2")
525
line = line.replace("n3", "v3")
533
print "Conversion done"
535
def metis_graph2graph_xml(ifilename, ofilename):
536
"Convert from Metis graph format to DOLFIN Graph XML."
538
print "Converting from Metis graph format to DOLFIN Graph XML."
541
ifile = open(ifilename, "r")
542
ofile = open(ofilename, "w")
544
# Read number of vertices and edges
545
line = ifile.readline()
549
(num_vertices, num_edges) = line.split()
551
write_header_graph(ofile, "directed")
552
write_header_vertices(ofile, int(num_vertices))
554
for i in range(int(num_vertices)):
555
line = ifile.readline()
557
write_graph_vertex(ofile, i, len(edges))
559
write_footer_vertices(ofile)
560
write_header_edges(ofile, 2*int(num_edges))
562
# Step to beginning of file and skip header info
565
for i in range(int(num_vertices)):
567
line = ifile.readline()
570
write_graph_edge(ofile, i, int(e))
572
write_footer_edges(ofile)
573
write_footer_graph(ofile)
579
def scotch_graph2graph_xml(ifilename, ofilename):
580
"Convert from Scotch graph format to DOLFIN Graph XML."
582
print "Converting from Scotch graph format to DOLFIN Graph XML."
585
ifile = open(ifilename, "r")
586
ofile = open(ofilename, "w")
588
# Skip graph file version number
591
# Read number of vertices and edges
592
line = ifile.readline()
596
(num_vertices, num_edges) = line.split()
598
# Read start index and numeric flag
599
# Start index is 0 or 1 (C/Fortran)
600
# Numeric flag is 3 bits where bit 1 enables vertex labels
601
# bit 2 enables edge weights and bit 3 enables vertex weights
603
line = ifile.readline()
604
(start_index, numeric_flag) = line.split()
606
# Handling not implented
607
if not numeric_flag == "000":
608
_error("Handling of scotch vertex labels, edge- and vertex weights not implemented")
610
write_header_graph(ofile, "undirected")
611
write_header_vertices(ofile, int(num_vertices))
613
# Read vertices and edges, first number gives number of edges from this vertex (not used)
614
for i in range(int(num_vertices)):
615
line = ifile.readline()
617
write_graph_vertex(ofile, i, len(edges)-1)
619
write_footer_vertices(ofile)
620
write_header_edges(ofile, int(num_edges))
623
# Step to beginning of file and skip header info
628
for i in range(int(num_vertices)):
629
line = ifile.readline()
632
for j in range(1, len(edges)):
633
write_graph_edge(ofile, i, int(edges[j]))
635
write_footer_edges(ofile)
636
write_footer_graph(ofile)
642
def write_header_meshfunction(ofile, dimensions, size):
643
header = """<?xml version="1.0" encoding="UTF-8"?>
644
<dolfin xmlns:dolfin="http://www.fenics.org/dolfin/">
645
<meshfunction type="uint" dim="%d" size="%d">
646
""" % (dimensions, size)
649
def write_entity_meshfunction(ofile, index, value):
650
ofile.write(""" <entity index=\"%d\" value=\"%d\"/>
651
""" % (index, value))
653
def write_footer_meshfunction(ofile):
654
ofile.write(""" </meshfunction>
657
def diffpack2xml(ifilename, ofilename):
658
"Convert from Diffpack tetrahedral grid format to DOLFIN XML."
660
print diffpack2xml.__doc__
662
# Format strings for MeshFunction XML files
663
meshfunction_header = """\
664
<?xml version="1.0" encoding="UTF-8"?>\n
665
<dolfin xmlns:dolfin="http://www.fenics.org/dolfin/">
666
<meshfunction type="uint" dim="%d" size="%d">\n"""
667
meshfunction_entity = " <entity index=\"%d\" value=\"%d\"/>\n"
668
meshfunction_footer = " </meshfunction>\n</dolfin>"
671
ifile = open(ifilename, "r")
672
ofile = open(ofilename, "w")
673
ofile_mat = open(ofilename.split(".")[0]+"_mat.xml", "w")
674
ofile_bi = open(ofilename.split(".")[0]+"_bi.xml", "w")
676
# Read and analyze header
678
line = ifile.readline()
683
if re.search(r"Number of elements", line):
684
num_cells = int(re.match(r".*\s(\d+).*", line).group(1))
685
if re.search(r"Number of nodes", line):
686
num_vertices = int(re.match(r".*\s(\d+).*", line).group(1))
688
write_header_mesh(ofile, "tetrahedron", 3)
689
write_header_vertices(ofile, num_vertices)
690
ofile_bi.write(meshfunction_header % (0, num_vertices))
691
ofile_mat.write(meshfunction_header % (3, num_cells))
693
# Read & write vertices
694
# Note that only first boundary indicator is rewriten into XML
695
for i in range(num_vertices):
696
line = ifile.readline()
697
m = re.match(r"^.*\(\s*(.*)\s*\).*\](.*)$", line)
698
x = re.split("[\s,]+", m.group(1))
699
write_vertex(ofile, i, x[0], x[1], x[2])
700
tmp = m.group(2).split()
705
ofile_bi.write(meshfunction_entity % (i, bi))
707
write_footer_vertices(ofile)
708
write_header_cells(ofile, num_cells)
710
# Ignore comment lines
712
line = ifile.readline()
719
for i in range(int(num_cells)):
720
line = ifile.readline()
722
if v[1] != "ElmT4n3D":
723
_error("Only tetrahedral elements (ElmT4n3D) are implemented.")
724
write_cell_tetrahedron(ofile, i, int(v[3])-1, int(v[4])-1, int(v[5])-1, int(v[6])-1)
725
ofile_mat.write(meshfunction_entity % (i, int(v[2])))
727
write_footer_cells(ofile)
728
write_footer_mesh(ofile)
729
ofile_bi.write(meshfunction_footer)
730
ofile_mat.write(meshfunction_footer)
738
class ParseError(Exception):
739
""" Error encountered in source file.
742
class DataHandler(object):
743
""" Baseclass for handlers of mesh data.
745
The actual handling of mesh data encountered in the source file is
746
delegated to a polymorfic object. Typically, the delegate will write the
748
@ivar _state: the state which the handler is in, one of State_*.
749
@ivar _cell_type: cell type in mesh. One of CellType_*.
750
@ivar _dim: mesh dimensions.
752
State_Invalid, State_Init, State_Vertices, State_Cells, State_MeshFunction = range(5)
753
CellType_Tetrahedron, CellType_Triangle = range(2)
756
self._state = self.State_Invalid
758
def set_mesh_type(self, cell_type, dim):
759
assert self._state == self.State_Invalid
760
self._state = self.State_Init
761
if cell_type == "tetrahedron":
762
self._cell_type = self.CellType_Tetrahedron
763
elif cell_type == "triangle":
764
self._cell_type = self.CellType_Triangle
767
def start_vertices(self, num_vertices):
768
assert self._state == self.State_Init
769
self._state = self.State_Vertices
771
def add_vertex(self, vertex, coords):
772
assert self._state == self.State_Vertices
774
def end_vertices(self):
775
assert self._state == self.State_Vertices
776
self._state = self.State_Init
778
def start_cells(self, num_cells):
779
assert self._state == self.State_Init
780
self._state = self.State_Cells
782
def add_cell(self, cell, nodes):
783
assert self._state == self.State_Cells
786
assert self._state == self.State_Cells
787
self._state = self.State_Init
789
def start_meshfunction(self, name, dim, size):
790
assert self._state == self.State_Init
791
self._state = self.State_MeshFunction
793
def add_entity_meshfunction(self, index, value):
794
assert self._state == self.State_MeshFunction
796
def end_meshfunction(self):
797
assert self._state == self.State_MeshFunction
798
self._state = self.State_Init
801
""" Issue warning during parse.
805
def error(self, msg):
806
""" Raise error during parse.
808
This method is expected to raise ParseError.
810
raise ParseError(msg)
813
self._state = self.State_Invalid
815
class XmlHandler(DataHandler):
816
""" Data handler class which writes to Dolfin XML.
818
def __init__(self, ofilename):
819
DataHandler.__init__(self)
820
self._ofilename = ofilename
821
self.__ofile = file(ofilename, "wb")
822
self.__ofile_meshfunc = None
824
def set_mesh_type(self, cell_type, dim):
825
DataHandler.set_mesh_type(self, cell_type, dim)
826
write_header_mesh(self.__ofile, cell_type, dim)
828
def start_vertices(self, num_vertices):
829
DataHandler.start_vertices(self, num_vertices)
830
write_header_vertices(self.__ofile, num_vertices)
832
def add_vertex(self, vertex, coords):
833
DataHandler.add_vertex(self, vertex, coords)
834
write_vertex(self.__ofile, vertex, *coords)
836
def end_vertices(self):
837
DataHandler.end_vertices(self)
838
write_footer_vertices(self.__ofile)
840
def start_cells(self, num_cells):
841
DataHandler.start_cells(self, num_cells)
842
write_header_cells(self.__ofile, num_cells)
844
def add_cell(self, cell, nodes):
845
DataHandler.add_cell(self, cell, nodes)
846
if self._cell_type == self.CellType_Tetrahedron:
847
func = write_cell_tetrahedron
848
func(self.__ofile, cell, *nodes)
851
DataHandler.end_cells(self)
852
write_footer_cells(self.__ofile)
854
def start_meshfunction(self, name, dim, size):
855
DataHandler.start_meshfunction(self, name, dim, size)
856
fname = os.path.splitext(self.__ofile.name)[0]
857
self.__ofile_meshfunc = file("%s_%s.xml" % (fname, name), "wb")
858
write_header_meshfunction(self.__ofile_meshfunc, dim, size)
860
def add_entity_meshfunction(self, index, value):
861
DataHandler.add_entity_meshfunction(self, index, value)
862
write_entity_meshfunction(self.__ofile_meshfunc, index, value)
864
def end_meshfunction(self):
865
DataHandler.end_meshfunction(self)
866
write_footer_meshfunction(self.__ofile_meshfunc)
867
self.__ofile_meshfunc.close()
868
self.__ofile_meshfunc = None
871
DataHandler.close(self)
872
if self.__ofile.closed:
874
write_footer_mesh(self.__ofile)
876
if self.__ofile_meshfunc is not None:
877
self.__ofile_meshfunc.close()
879
def _abaqus(ifilename, handler):
880
""" Convert from Abaqus.
882
The Abaqus format first defines a node block, then there should be a number
883
of elements containing these nodes.
886
ifile = file(ifilename, "rb")
887
handler.set_mesh_type("tetrahedron", 3)
891
def read_params(params_spec, pnames, lineno):
893
for p in params_spec:
894
m = re.match(r"(.+)=(.+)", p)
896
pname, val = m.groups()
898
handler.warn("Invalid parameter syntax on line %d: %s" % (lineno, p))
910
material2elsetids = {}
912
re_sect = re.compile(r"\*([^,]+)(?:,(.*))?")
913
re_node = re.compile(r"(\d+),\s*(.+),\s*(.+),\s*(.+)")
914
re_tetra = re.compile(r"(\d+),\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)")
916
for lineno, l in enumerate(ifile):
917
l = l.strip().lower()
920
sect, params_str = m.groups()
921
params_spec = ([s.strip() for s in params_str.split(",")] if params_str
924
if sect == "element":
925
pnames = ("type", "elset")
926
params = read_params(params_spec, pnames, lineno)
927
if "type" not in params:
928
handler.error("Element on line %d doesn't declare TYPE" %
930
tp, elset = params["type"], params.get("elset")
931
if tp not in ("c3d4", "dc3d4"):
932
handler.warn("Unsupported element type '%s' on line %d" % (tp, lineno))
933
supported_elem = False
935
supported_elem = True
936
elif sect == "solid section":
937
pnames = ("material", "elset")
938
params = read_params(params_spec, pnames, lineno)
940
if pname not in params:
941
handler.error("Solid section on line %d doesn't "
942
"declare %s" % (lineno, pname.upper()))
943
matname = params["material"]
944
material2elsetids.setdefault(matname, []).append(params["elset"])
945
elif sect == "material":
946
name = read_params(params_spec, ["name"], lineno)["name"]
947
materials.append(name)
948
# We've read the section's heading, continue to next line
954
# Read node definition
957
handler.warn("Node on line %d is on unsupported format" % (lineno,))
959
idx, c0, c1, c2 = m.groups()
960
try: coords = [float(c) for c in (c0, c1, c2)]
962
handler.warn("Node on line %d contains non-numeric coordinates"
965
nodes[int(idx)] = coords
966
elif sect == "element":
967
if not supported_elem:
969
m = re_tetra.match(l)
971
handler.error("Node on line %d badly specified (expected 3 "
972
"coordinates)" % (lineno,))
973
idx, n0, n1, n2, n3 = [int(x) for x in m.groups()]
974
elems[idx] = (tp, n0, n1, n2, n3)
975
eid2elset.setdefault(elset, set()).add(idx)
979
# Note that vertices/cells must be consecutively numbered, which isn't
980
# necessarily the case in Abaqus. Therefore we enumerate and translate
981
# original IDs to sequence indexes.
983
handler.start_vertices(len(nodes))
984
nodeids = nodes.keys()
986
for idx, nid in enumerate(nodeids):
987
handler.add_vertex(idx, nodes[nid])
988
handler.end_vertices()
990
handler.start_cells(len(elems))
991
elemids = elems.keys()
993
for idx, eid in enumerate(elemids):
998
try: elemnodes.append(nodeids.index(nid))
1000
handler.error("Element %s references non-existent node %s" % (eid, nid))
1001
handler.add_cell(idx, elemnodes)
1004
# Define the material function for the cells
1007
for matname, elsetids in material2elsetids.items():
1008
if matname not in materials:
1009
handler.error("Unknown material %s referred to for element sets %s" %
1010
(matname, ", ".join(elsetids)))
1011
num_entities += len(elsetids)
1012
handler.start_meshfunction("material", 3, num_entities)
1013
# Each material is associated with a number of element sets
1014
for i, matname in enumerate(materials):
1015
try: elsetids = material2elsetids[matname]
1017
# No elements for this material
1019
# For each element set associated with this material
1021
for eid in elsetids:
1022
try: elsets.append(eid2elset[eid])
1024
handler.error("Material '%s' is assigned to undefined element "
1025
"set '%s'" % (matname, eid))
1026
for elset in elsets:
1027
for elemid in elset:
1028
handler.add_entity_meshfunction(elemids.index(elemid), i)
1029
handler.end_meshfunction()
1031
def netcdf2xml(ifilename,ofilename):
1032
"Convert from NetCDF format to DOLFIN XML."
1034
print "Converting from NetCDF format (.ncdf) to DOLFIN XML format"
1037
ifile = open(ifilename, "r")
1038
ofile = open(ofilename, "w")
1044
# Scan file for dimension, number of nodes, number of elements
1046
line = ifile.readline()
1049
if re.search(r"num_dim.*=", line):
1050
dim = int(re.match(".*\s=\s(\d+)\s;",line).group(1))
1051
if re.search(r"num_nodes.*=", line):
1052
num_vertices = int(re.match(".*\s=\s(\d+)\s;",line).group(1))
1053
if re.search(r"num_elem.*=", line):
1054
num_cells = int(re.match(".*\s=\s(\d+)\s;",line).group(1))
1055
if re.search(r"connect1 =",line):
1062
cell_type ="triangle"
1064
cell_type ="tetrahedron"
1066
# Check that we got the cell type
1067
if cell_type == None:
1068
error("Unable to find cell type.")
1071
write_header_mesh(ofile, cell_type, dim)
1072
write_header_cells(ofile, num_cells)
1075
# Read and write cells
1078
line = ifile.readline()
1081
connect=re.split("[,;]",line)
1083
n0 = int(connect[0])-1
1084
n1 = int(connect[1])-1
1085
n2 = int(connect[2])-1
1086
write_cell_triangle(ofile, num_cells_read, n0, n1, n2)
1088
n0 = int(connect[0])-1
1089
n1 = int(connect[1])-1
1090
n2 = int(connect[2])-1
1091
n3 = int(connect[3])-1
1092
write_cell_tetrahedron(ofile, num_cells_read, n0, n1, n2, n3)
1094
if num_cells == num_cells_read:
1095
write_footer_cells(ofile)
1096
write_header_vertices(ofile, num_vertices)
1099
num_vertices_read = 0
1104
line = ifile.readline()
1106
error("Missing data")
1107
if re.search(r"coord =",line):
1112
line = ifile.readline()
1116
if re.search(r"\A\s\s\S+,",line):
1119
print "Found x_"+str(coord)+" coordinates"
1120
coords[coord] += line.split()
1121
if re.search(r";",line):
1125
for i in range(num_vertices):
1127
x = float(re.split(",",coords[0].pop(0))[0])
1128
y = float(re.split(",",coords[1].pop(0))[0])
1131
x = float(re.split(",",coords[0].pop(0))[0])
1132
y = float(re.split(",",coords[1].pop(0))[0])
1133
z = float(re.split(",",coords[2].pop(0))[0])
1134
write_vertex(ofile, i, x, y, z)
1138
write_footer_vertices(ofile)
1139
write_footer_mesh(ofile)
1145
def exodus2xml(ifilename,ofilename):
1146
"Convert from Exodus II format to DOLFIN XML."
1148
print "Converting from Exodus II format to NetCDF format"
1150
name = ifilename.split(".")[0]
1151
netcdffilename = name +".ncdf"
1152
os.system('ncdump '+ifilename + ' > '+netcdffilename)
1153
netcdf2xml(netcdffilename,ofilename)
1156
def write_header_mesh(ofile, cell_type, dim):
1158
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1160
<dolfin xmlns:dolfin=\"http://www.fenics.org/dolfin/\">
1161
<mesh celltype="%s" dim="%d">
1162
""" % (cell_type, dim))
1164
# Write graph header
1165
def write_header_graph(ofile, graph_type):
1167
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1169
<dolfin xmlns:dolfin=\"http://www.fenics.org/dolfin/\">
1174
def write_footer_mesh(ofile):
1180
# Write graph footer
1181
def write_footer_graph(ofile):
1187
def write_header_vertices(ofile, num_vertices):
1188
"Write vertices header"
1189
print "Expecting %d vertices" % num_vertices
1190
ofile.write(" <vertices size=\"%d\">\n" % num_vertices)
1192
def write_footer_vertices(ofile):
1193
"Write vertices footer"
1194
ofile.write(" </vertices>\n")
1195
print "Found all vertices"
1197
def write_header_edges(ofile, num_edges):
1198
"Write edges header"
1199
print "Expecting %d edges" % num_edges
1200
ofile.write(" <edges size=\"%d\">\n" % num_edges)
1202
def write_footer_edges(ofile):
1203
"Write edges footer"
1204
ofile.write(" </edges>\n")
1205
print "Found all edges"
1207
def write_vertex(ofile, vertex, x, y, z):
1209
ofile.write(" <vertex index=\"%d\" x=\"%s\" y=\"%s\" z=\"%s\"/>\n" % \
1212
def write_graph_vertex(ofile, vertex, num_edges, weight = 1):
1213
"Write graph vertex"
1214
ofile.write(" <vertex index=\"%d\" num_edges=\"%d\" weight=\"%d\"/>\n" % \
1215
(vertex, num_edges, weight))
1217
def write_graph_edge(ofile, v1, v2, weight = 1):
1219
ofile.write(" <edge v1=\"%d\" v2=\"%d\" weight=\"%d\"/>\n" % \
1222
def write_header_cells(ofile, num_cells):
1223
"Write cells header"
1224
ofile.write(" <cells size=\"%d\">\n" % num_cells)
1225
print "Expecting %d cells" % num_cells
1227
def write_footer_cells(ofile):
1228
"Write cells footer"
1229
ofile.write(" </cells>\n")
1230
print "Found all cells"
1232
def write_cell_triangle(ofile, cell, n0, n1, n2):
1233
"Write cell (triangle)"
1234
ofile.write(" <triangle index=\"%d\" v0=\"%d\" v1=\"%d\" v2=\"%d\"/>\n" % \
1237
def write_cell_tetrahedron(ofile, cell, n0, n1, n2, n3):
1238
"Write cell (tetrahedron)"
1239
ofile.write(" <tetrahedron index=\"%d\" v0=\"%d\" v1=\"%d\" v2=\"%d\" v3=\"%d\"/>\n" % \
1240
(cell, n0, n1, n2, n3))
1242
def _error(message):
1243
"Write an error message"
1244
for line in message.split("\n"):
1245
print "*** %s" % line
1248
def convert2xml(ifilename, ofilename, iformat=None):
1249
""" Convert a file to the DOLFIN XML format.
1251
convert(ifilename, XmlHandler(ofilename), iformat=iformat)
1253
def convert(ifilename, handler, iformat=None):
1254
""" Convert a file using a provided data handler.
1256
Note that handler.close is called when this function finishes.
1257
@param ifilename: Name of input file.
1258
@param handler: The data handler (instance of L{DataHandler}).
1259
@param iformat: Format of input file.
1262
iformat = format_from_suffix(os.path.splitext(ifilename)[1][1:])
1263
# XXX: Backwards-compat
1264
if hasattr(handler, "_ofilename"):
1265
ofilename = handler._ofilename
1267
if iformat == "mesh":
1268
# Convert from mesh to xml format
1269
mesh2xml(ifilename, ofilename)
1270
elif iformat == "gmsh":
1271
# Convert from gmsh to xml format
1272
gmsh2xml(ifilename, ofilename)
1273
elif iformat == "Triangle":
1274
# Convert from Triangle to xml format
1275
triangle2xml(ifilename, ofilename)
1276
elif iformat == "xml-old":
1277
# Convert from old to new xml format
1278
xml_old2xml(ifilename, ofilename)
1279
elif iformat == "metis":
1280
# Convert from metis graph to dolfin graph xml format
1281
metis_graph2graph_xml(ifilename, ofilename)
1282
elif iformat == "scotch":
1283
# Convert from scotch graph to dolfin graph xml format
1284
scotch_graph2graph_xml(ifilename, ofilename)
1285
elif iformat == "diffpack":
1286
# Convert from Diffpack tetrahedral grid format to xml format
1287
diffpack2xml(ifilename, ofilename)
1288
elif iformat == "abaqus":
1289
# Convert from abaqus to xml format
1290
_abaqus(ifilename, handler)
1291
elif iformat == "NetCDF":
1292
# Convert from NetCDF generated from ExodusII format to xml format
1293
netcdf2xml(ifilename, ofilename)
1294
elif iformat =="ExodusII":
1295
# Convert from ExodusII format to xml format via NetCDF
1296
exodus2xml(ifilename, ofilename)
1297
elif iformat == "StarCD":
1298
# Convert from Star-CD tetrahedral grid format to xml format
1299
starcd2xml(ifilename, ofilename)
1301
_error("Sorry, cannot convert between %s and DOLFIN xml file formats." % iformat)
1303
# XXX: handler.close messes things for other input formats than abaqus
1304
if iformat == "abaqus":
1307
def starcd2xml(ifilename, ofilename):
1308
"Convert from Star-CD tetrahedral grid format to DOLFIN XML."
1310
print starcd2xml.__doc__
1312
if not os.path.isfile(ifilename[:-3] + "vrt") or not os.path.isfile(ifilename[:-3] + "cel"):
1313
print "StarCD format requires one .vrt file and one .cel file"
1318
ofile = open(ofilename, "w")
1320
# Open file, the vertices are in a .vrt file
1321
ifile = open(ifilename[:-3] + "vrt", "r")
1323
write_header_mesh(ofile, "tetrahedron", 3)
1326
# Read & write vertices
1328
# first, read all lines (need to sweep to times through the file)
1329
lines = ifile.readlines()
1331
# second, find the number of vertices
1334
# nodenr_map is needed because starcd support node numbering like 1,2,4 (ie 3 is missing)
1337
nodenr = int(line[0:15])
1338
nodenr_map[nodenr] = counter
1340
num_vertices = counter
1342
# third, run over all vertices
1343
write_header_vertices(ofile, num_vertices)
1345
nodenr = int(line[0:15])
1346
vertex0 = float(line[15:31])
1347
vertex1 = float(line[31:47])
1348
vertex2 = float(line[47:63])
1349
write_vertex(ofile, nodenr_map[nodenr], float(vertex0), float(vertex1), float(vertex2))
1350
write_footer_vertices(ofile)
1352
# Open file, the cells are in a .cel file
1353
ifile = open(ifilename[:-3] + "cel", "r")
1355
# Read & write cells
1357
# first, read all lines (need to sweep to times through the file)
1358
lines = ifile.readlines()
1360
# second, find the number of cells
1364
l = [int(a) for a in line.split()]
1365
cellnr, node0, node1, node2, node3, node4, node5, node6, node7, tmp1, tmp2 = l
1367
if node2 == node3 and node4 == node5 and node5 == node6 and node6 == node7: # these nodes should be equal
1370
print "The file does contain cells that are not tetraheders. The cell number is ", cellnr, " the line read was ", line
1372
# triangles on the surface
1373
# print "The file does contain cells that are not tetraheders node4==0. The cell number is ", cellnr, " the line read was ", line
1379
# third, run over all cells
1380
write_header_cells(ofile, num_cells)
1383
l = [int(a) for a in line.split()]
1384
cellnr, node0, node1, node2, node3, node4, node5, node6, node7, tmp1, tmp2 = l
1386
if node2 == node3 and node4 == node5 and node5 == node6 and node6 == node7: # these nodes should be equal
1388
write_cell_tetrahedron(ofile, counter, nodenr_map[node0], nodenr_map[node1], nodenr_map[node2], nodenr_map[node4])
1392
write_footer_cells(ofile)
1393
write_footer_mesh(ofile)