Merge lp:~kahosato93/fluidity/firedrake-mesh into lp:fluidity/firedrake

Proposed by Kaho Sato
Status: Merged
Merged at revision: 4304
Proposed branch: lp:~kahosato93/fluidity/firedrake-mesh
Merge into: lp:fluidity/firedrake
Diff against target: 187 lines (+81/-52)
1 file modified
python/firedrake/mesh.py (+81/-52)
To merge this branch: bzr merge lp:~kahosato93/fluidity/firedrake-mesh
Reviewer Review Type Date Requested Status
Florian Rathgeber Approve
Review via email: mp+184811@code.launchpad.net

Description of the change

Mesh files created along the creation of a mesh instance are now cached.

To post a comment you must log in.
4328. By Kaho Sato <email address hidden>

Now mesh class uses cached mesh file if it exists

Revision history for this message
Florian Rathgeber (florian-rathgeber) wrote :

Excellent! No objections, merging...

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'python/firedrake/mesh.py'
2--- python/firedrake/mesh.py 2013-09-09 16:01:01 +0000
3+++ python/firedrake/mesh.py 2013-09-10 15:49:10 +0000
4@@ -7,57 +7,80 @@
5 import firedrake
6
7
8-class _get_msh_file(object):
9-
10- """Class that can be used as a context manager of .geo and .msh files,
11- that removes these files as soon as they are no longer useful.
12- Given a source code and dimension of the mesh,
13- returns the object representing the temporary .msh file.
14+_cachedir = os.path.join(tempfile.gettempdir(),
15+ 'firedrake-mesh-cache-uid%d' % os.getuid())
16+if not os.path.exists(_cachedir):
17+ os.makedirs(_cachedir)
18+
19+_exts = [".node", ".ele", ".face"]
20+_pexts = _exts + [".halo"]
21+
22+
23+def _get_msh_file(source, name, dimension):
24+
25+ """Given a source code, name and dimension of the mesh,
26+ returns the name of the file that contains necessary information to build
27+ a mesh class. The mesh class would call _from_file method on this file
28+ to contruct itself.
29 """
30
31- def __init__(self, source, dimension):
32- self._source = source
33- self._dimension = dimension
34-
35- def __enter__(self):
36- if MPI.comm.rank == 0:
37- self._input = tempfile.NamedTemporaryFile('w+r', suffix='.geo')
38- self._input.write(self._source)
39- self._input.flush()
40- self._input.seek(0)
41- self._output = tempfile.NamedTemporaryFile('w+r', suffix='.msh')
42- result = self._output.name
43- subprocess.call(['gmsh', self._input.name,
44- "-"+str(self._dimension), '-o', self._output.name])
45+ if MPI.comm.rank == 0:
46+ input = os.path.join(_cachedir, name+'.geo')
47+ if not os.path.exists(input):
48+ with open(input, 'w') as f:
49+ f.write(source)
50+
51+ output = os.path.join(_cachedir, name)
52+
53+ if not os.path.exists(output+'.msh'):
54+
55+ #Writing of the output file.
56 if MPI.parallel:
57 from mpi4py import MPI as _MPI
58- _MPI.COMM_SELF.Spawn('gmsh', args=[self._input.name,
59- "-"+str(self._dimension), '-o', self._output.name])
60+ _MPI.COMM_SELF.Spawn('gmsh', args=[input,
61+ "-" + str(dimension), '-o', output+'.msh'])
62+ else:
63+ subprocess.call(['gmsh', input, "-"+str(dimension),
64+ '-o', output+'.msh'])
65+
66+ if MPI.parallel:
67+ if not _triangled(output, _exts):
68 gmsh2triangle = os.path.split(firedrake.__file__)[0] +\
69 "/../../bin/gmsh2triangle"
70- subprocess.call([gmsh2triangle, self._output.name])
71- result = os.path.splitext(self._output.name)[0][5:]
72+ subprocess.call([gmsh2triangle, output+'.msh'], cwd=_cachedir)
73+
74+ basename = output + "_" + str(MPI.comm.size)
75+ #Deal with decomposition.
76+ #fldecomp would always name the decomposed triangle files
77+ #in a same way.(meshname_rank.node, rather than
78+ #meshname_size_rank.node).
79+ #To go around this without creating triangle files everytime,
80+ #we can make a simlink meshname_size.node which points to
81+ #the file meshname.node.
82+ for ext in _exts:
83+ if not os.path.lexists(basename + ext):
84+ os.symlink(output+ext, basename+ext)
85+ if not all([_triangled(basename + '_' + str(r), _pexts)
86+ for r in xrange(MPI.comm.size)]):
87 fldecomp = os.path.split(firedrake.__file__)[0] +\
88 "/../../bin/fldecomp"
89 subprocess.call([fldecomp, '-n', str(MPI.comm.size), '-m',
90- 'triangle', result])
91- result += ".node"
92- MPI.comm.bcast(result, root=0)
93-
94- else:
95- result = MPI.comm.bcast(None, root=0)
96- return result
97-
98- def __exit__(self, type, value, traceback):
99- if MPI.comm.rank == 0:
100- if MPI.parallel:
101- import glob
102- files = glob.glob(os.path.splitext(self._output.name)[0][5:] +
103- '*')
104- for file in files:
105- os.remove(file)
106- self._input.close()
107- self._output.close()
108+ 'triangle', basename])
109+
110+ output = basename + ".node"
111+ MPI.comm.bcast(output, root=0)
112+
113+ #Not processor-0
114+ else:
115+ output = MPI.comm.bcast(None, root=0)
116+
117+ return output if MPI.parallel else output + '.msh'
118+
119+
120+def _triangled(basename, exts):
121+ """ Checks if the mesh of the given basename has already been decomposed.
122+ """
123+ return all(map(lambda ext: os.path.exists(basename + ext), exts))
124
125
126 class UnitSquareMesh(Mesh):
127@@ -82,9 +105,10 @@
128 Line{1}; Layers{%d};
129 }
130 """ % (nx, ny)
131+ name = "unitsquare_%d_%d" % (nx, ny)
132
133- with _get_msh_file(source, 2) as output:
134- super(UnitSquareMesh, self).__init__(output)
135+ output = _get_msh_file(source, name, 2)
136+ super(UnitSquareMesh, self).__init__(output)
137
138
139 class UnitCubeMesh(Mesh):
140@@ -112,9 +136,10 @@
141 Surface{5}; Layers{%d};
142 }
143 """ % (nx, ny, nz)
144+ name = "unitcube_%d_%d_%d" % (nx, ny, nz)
145
146- with _get_msh_file(source, 3) as output:
147- super(UnitCubeMesh, self).__init__(output)
148+ output = _get_msh_file(source, name, 3)
149+ super(UnitCubeMesh, self).__init__(output)
150
151
152 class UnitCircleMesh(Mesh):
153@@ -135,9 +160,10 @@
154 Line{1};Layers{%d};
155 }
156 """ % (2*resolution, resolution * 4)
157+ name = "unitcircle_%d" % resolution
158
159- with _get_msh_file(source, 2) as output:
160- super(UnitCircleMesh, self).__init__(output)
161+ output = _get_msh_file(source, name, 2)
162+ super(UnitCircleMesh, self).__init__(output)
163
164
165 class UnitIntervalMesh(Mesh):
166@@ -178,8 +204,10 @@
167 Surface Loop(16) = {12, 14, 10, 8};
168 Volume(16) = {16};
169 """
170- with _get_msh_file(source, 3) as output:
171- super(UnitTetrahedronMesh, self).__init__(output)
172+ name = "unittetra"
173+
174+ output = _get_msh_file(source, name, 3)
175+ super(UnitTetrahedronMesh, self).__init__(output)
176
177
178 class UnitTriangleMesh(Mesh):
179@@ -196,5 +224,6 @@
180 Line Loop(5) = {1, 2, 3};
181 Plane Surface(5) = {5};
182 """
183- with _get_msh_file(source, 2) as output:
184- super(UnitTriangleMesh, self).__init__(output)
185+ name = "unittri"
186+ output = _get_msh_file(source, name, 2)
187+ super(UnitTriangleMesh, self).__init__(output)

Subscribers

People subscribed via source and target branches

to all changes: