File: submesh-impl.tex

package info (click to toggle)
alberta 3.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 19,176 kB
  • sloc: ansic: 135,836; cpp: 6,601; makefile: 2,801; sh: 333; fortran: 180; lisp: 177; xml: 30
file content (418 lines) | stat: -rw-r--r-- 21,392 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
\section{Implementation of submeshes}%
\label{S:submesh_implementation}%
\label{S:tracemesh_implementation}%
\idx{submeshes!implementation}
\idx{tracemeshes!implementation}

The concepts and motivations behind submeshes in \ALBERTA were already
introduced in \secref{book:S:Submeshes}. Shortly, a submesh or slave
mesh (maybe better ``trace-mesh'') of a given $d$-dimensional master
mesh is a collection of certain $d-1$-dimensional subsimplices that
should be refined and coarsened in a conforming way to the master
mesh. For parametric master meshes, all submeshes should also be
parametric.

The philosophy of submeshes is that their use should not involve major
changes of data structures nor excessive overhead in memory or CPU
time as a price for their features. We first describe how to allocate
and use submeshes. The ideas of how refining and coarsening work for
submeshes is described later.

\subsection{Allocating submeshes}%
\label{S:alloc_submesh}%
\idx{submeshes!allocation}

Submeshes are \ALBERTA \code{MESH} objects with some special properties.
The user defines a submesh by selecting certain subsimplices of 
macro elements. The mechanism uses a callback method similar to the case 
of node projections, refer \secref{S:node_projections}. 
\fdx{get_submesh()@{\code{get\_submesh()}}}
\bv\begin{verbatim}
MESH *get_submesh(MESH *, const char *,
                  int (*)(MESH *, MACRO_EL *, int, void *), void *);
\end{verbatim}\ev
\code{get\_submesh(master, name, binding\_method, data)} allocates a submesh 
with the identifier \code{name} of the given \code{master}. The binding method
is a callback function which is called by \ALBERTA for each macro element and 
each vertex/edge/face in 1d/2d/3d.

Given the \code{master} mesh,
a macro element \code{mel}, a vertex/edge/face \code{face}, and arbitrary 
user \code{data}, this function should return \true if the subface is 
to be part of the submesh and \false otherwise. An example is shown below.
The argument \code{data} is passed to the callback and may contain arbitrary
user data.

Calling this function will return the complete submesh. More than one
submesh may be defined. If the master mesh is already refined, then
the submesh will automatically be refined to maintain the conformity
property \mathref{book:E:conforming_submesh} on page
\pageref{book:E:conforming_submesh}. If the master mesh used projection of
nodes, then the node projection is inherited by the slave mesh and
automatically initialized in such a way that all submesh vertices
undergo the same projection as the master vertices.

If the master 
mesh is a parametric mesh (or is later defined to be one), then the parametric
structure is inherited in a straight forward manner to the submesh, a 
mechanism which is only implemented for \code{use\_lagrange\_parametric}. This 
implies that the submesh elements will also be described by element 
transformations of the same polynomial degree as for the master mesh, and that 
the shape of submesh elements matches the shape of curved master mash 
subsimplices.

The numbering of vertices on the macro triangulation of the submesh is done 
in such a way as to always guarantee matching refinement edges of submesh
and master mesh. Furthermore, the orientation of the submesh elements for 
2d submeshes follows a right hand rule for the outward pointing unit normal 
of the master macro element, see Figure \figref{F:submesh_numbering_3d}.

\begin{figure}[htbp]
\centering
\includegraphics{EPS/submesh_numbering_3d}
\caption[Trace-meshes, numbering of subsimplices]{Local vertex
  numbering of the 2d subsimplices of a 3d element of type 0 and
  positive orientation. The 2d submesh numbering depends on type and
  orientation of the master elements.}
\label{F:submesh_numbering_3d}
\end{figure}

The connection of submesh and master mesh is described internally using two
special \code{DOF\_PTR\_VEC}s. One of these, called \code{master\_binding},
is based on the submesh and contains pointers from slave elements into 
master elements. To be precise, each \code{CENTER} DOF of this vector
is a pointer to the master \code{EL} structure describing the element along 
which the submesh element lies. 

The second vector, called \code{slave\_binding}, is based on the
master mesh and points in the opposite direction. It maps
\code{VERTEX}/\code{EDGE}/\code{FACE} DOFs of the master element to
the \code{EL} structures of the slaves. If no slave element lies along
the \code{VERTEX}/\code{EDGE}/\code{FACE} then the pointer is
\nil. Figure \figref{F:slave_binding} illustrates this.

\begin{figure}[htbp]
\centering
\includegraphics[scale=0.75]{EPS/sm_dpv_2d}
\caption[Trace-meshes, 1d slave-elements]{2d master triangle with
  submesh intervals on all sides. Left: vector \code{slave\_binding}
  connecting \code{EDGE} DOFs to slave elements.  Right: vector
  \code{master\_binding} connecting \code{CENTER} DOFs to master
  elements.}
\label{F:slave_binding}
\end{figure}

Both vectors have their \code{refine\_interpol} and \code{coarse\_restrict} 
entries set to special internal routines. These routines automatically 
take care of updating the submesh during refinement and coarsening, which 
is useful since mesh changes are most easily done simultaneously on 
refinement or coarsening patches. This is described in more detail below.

Submeshes can be disconnected from the master mesh using the function
\fdx{unchain_submesh()@{\code{unchain\_submesh()}}}
\bv\begin{verbatim}
void unchain_submesh(MESH *slave);
\end{verbatim}\ev
This function deletes the connection between master mesh and submesh. It does 
\emph{not} delete the submesh. After doing this, the submesh and master mesh 
are entirely independent and separate \code{MESH} objects for \ALBERTA and 
may be refined and coarsened independently.

\subsection{Routines for submeshes}%
\label{S:tools_submesh}%
\idx{submeshes!tools}

The following tools are available for submeshes:
\fdx{read_submesh()@{\code{read\_submesh()}}}
\fdx{read_submesh_xdr()@{\code{read\_submesh\_xdr()}}}
\fdx{get_bndry_submesh()@{\code{get\_bndry\_submesh()}}}
\fdx{get_bndry_submesh_by_type()@{\code{get\_bndry\_submesh\_by\_type()}}}
\fdx{get_bndry_submesh_by_segment()@{\code{get\_bndry\_submesh\_by\_segment()}}}
\fdx{read_bndry_submesh()@{\code{read\_bndry\_submesh()}}}
\fdx{read_bndry_submesh_xdr()@{\code{read\_bndry\_submesh\_xdr()}}}
\fdx{read_bndry_submesh_by_type()@{\code{read\_bndry\_submesh\_by\_type()}}}
\fdx{read_bndry_submesh_by_type_xdr()@{\code{read\_bndry\_submesh\_by\_type\_xdr()}}}
\fdx{read_bndry_submesh_by_segment()@{\code{read\_bndry\_submesh\_by\_segment()}}}
\fdx{read_bndry_submesh_by_segment_xdr()@{\code{read\_bndry\_submesh\_by\_segment\_xdr()}}}
\fdx{trace_dof_real_vec()@{\code{trace\_dof\_real\_vec()}}}
\fdx{trace_dof_real_d_vec()@{\code{trace\_dof\_real\_d\_vec()}}}
\fdx{get_slave_dof_mapping()@{\code{get\_slave\_dof\_mapping()}}}
\fdx{get_master()@{\code{get\_master()}}}
\fdx{get_slave_el()@{\code{get\_slave\_el()}}}
\fdx{fill_slave_el_info()@{\code{get\_slave\_el\_info()}}}
\fdx{fill_master_el_info()@{\code{get\_master\_el\_info()}}}
\fdx{trace_to_bulk_coords()@{\code{trace\_to\_bulk\_coords()}}}
\fdx{trace_to_bulk_coords_dim()@{\code{trace\_to\_bulk\_coords\_dim()}}}
\fdx{trace_to_bulk_coords_0d()@{\code{trace\_to\_bulk\_coords\_0d()}}}
\fdx{trace_to_bulk_coords_1d()@{\code{trace\_to\_bulk\_coords\_1d()}}}
\fdx{trace_to_bulk_coords_2d()@{\code{trace\_to\_bulk\_coords\_2d()}}}
\fdx{bulk_to_trace_coords()@{\code{bulk\_to\_trace\_coords()}}}
\fdx{bulk_to_trace_coords_dim()@{\code{bulk\_to\_trace\_coords\_dim()}}}
\fdx{bulk_to_trace_coords_0d()@{\code{bulk\_to\_trace\_coords\_0d()}}}
\fdx{bulk_to_trace_coords_1d()@{\code{bulk\_to\_trace\_coords\_1d()}}}
\fdx{bulk_to_trace_coords_2d()@{\code{bulk\_to\_trace\_coords\_2d()}}}
\fdx{get_master_dof_indices()@{\code{get\_master\_dof\_indices()}}}
\fdx{get_master_bound()@{\code{get\_master\_bound()}}}
\fdx{trace_dof_real_vec()@{\code{trace\_dof\_real\_vec()}}}
\fdx{trace_dof_real_d_vec()@{\code{trace\_dof\_real\_d\_vec()}}}
\fdx{trace_dof_int_vec()@{\code{trace\_dof\_int\_vec()}}}
\fdx{trace_dof_dof_vec()@{\code{trace\_dof\_dof\_vec()}}}
\fdx{trace_int_dof_vec()@{\code{trace\_int\_dof\_vec()}}}
\fdx{trace_dof_uchar_vec()@{\code{trace\_dof\_uchar\_vec()}}}
\fdx{trace_dof_schar_vec()@{\code{trace\_dof\_schar\_vec()}}}
\fdx{trace_dof_ptr_vec()@{\code{trace\_dof\_ptr\_vec()}}}
\fdx{update_master_matrix()@{\code{update\_master\_matrix()}}}
\fdx{update_master_real_vec()@{\code{update\_master\_real\_vec()}}}
\fdx{update_master_real_d_vec()@{\code{update\_master\_real\_d\_vec()}}}
\bv\begin{verbatim}
MESH *read_submesh(MESH *master,
                   const char *slave_filename,
                   int (*binding_method)(MESH *master, MACRO_EL *el,
                                         int face, void *data),
                   NODE_PROJECTION *(*)(MESH *, MACRO_EL *, int),
                   void *data);
MESH *read_submesh_xdr(MESH *master,
                       const char *slave_filename,
                       int (*binding_method)(MESH *master, MACRO_EL *el,
                                             int face, void *data),
                       NODE_PROJECTION *(*)(MESH *, MACRO_EL *, int),
                       void *data);
MESH *get_bndry_submesh(MESH *master, const char *name);
MESH *get_bndry_submesh_by_type(MESH *master, const char *name,
                                BNDRY_TYPE type);
MESH *get_bndry_submesh_by_segment(MESH *master, const char *name,
                                   BNDRY_FLAGS segment);
MESH *read_bndry_submesh(MESH *master, const char *slave_filename);
MESH *read_bndry_submesh_xdr(MESH *master, const char *slave_filename);
MESH *read_bndry_submesh_by_type(MESH *master,
				 const char *slave_filename, BNDRY_TYPE type);
MESH *read_bndry_submesh_by_type_xdr(MESH *master,
				     const char *slave_filename,
                                     BNDRY_TYPE type);
MESH *read_bndry_submesh_by_segment(MESH *master,
				    const char *slave_filename,
                                    BNDRY_FLAGS segment);
MESH *read_bndry_submesh_by_segment_xdr(MESH *master,
				       const char *slave_filename,
                                       BNDRY_FLAGS segment);

void get_slave_dof_mapping(const FE_SPACE *m_fe_space, DOF_INT_VEC *s_map);
MESH *get_master(MESH *slave);
const DOF *get_master_dof_indices(const EL_INFO *s_el_info,
				  const FE_SPACE *m_fe_space,
				  DOF *result);
void trace_dof_real_vec(DOF_REAL_VEC *svec, const DOF_REAL_VEC *mvec);
void trace_dof_real_d_vec(DOF_REAL_D_VEC *svec, const DOF_REAL_D_VEC *mvec);
void trace_dof_int_vec(DOF_INT_VEC *svec, const DOF_INT_VEC *mvec);
void trace_dof_dof_vec(DOF_DOF_VEC *svec, const DOF_DOF_VEC *mvec);
void trace_int_dof_vec(DOF_DOF_VEC *svec, const DOF_DOF_VEC *mvec);
void trace_dof_uchar_vec(DOF_UCHAR_VEC *svec, const DOF_UCHAR_VEC *mvec);
void trace_dof_schar_vec(DOF_SCHAR_VEC *svec, const DOF_UCHAR_VEC *mvec);
void trace_dof_ptr_vec(DOF_PTR_VEC *svec, const DOF_PTR_VEC *mvec);
void update_master_matrix(DOF_MATRIX *m_dof_matrix,
			  const EL_MATRIX_INFO *s_minfo);
void update_master_real_vec(DOF_REAL_VEC *m_drv,
                            const EL_VEC_INFO *s_vec_info);
void update_master_real_d_vec(DOF_REAL_D_VEC *m_drdv,
			      const EL_VEC_D_INFO *s_vec_info);
\end{verbatim}\ev
%%
\begin{compatibility}
  \label{compat:get_master_el}
  The functionality of the function \code{get\_master\_el()} has been
  shifted to the \hyperref[T:EL_INFO]{\code{EL\_INFO}} structure;
  information about the "master"-element is computed during
  mesh-traversal if requested by the \code{FILL\_MASTER\_INFO} and
  \code{FILL\_MASTER\_NEIGH} fill-flags (see also
  \secref{S:traverse}).
\end{compatibility}
%%
Description of the individual functions:
\begin{descr}
  \kitem{read\_submesh(master,filename,binding\_method,init\_node\_proj,data)}
  This function must be used to read a submesh from disk which was
  previously saved by \code{write\_mesh()}, see
  \secref{S:file_formats}. Note that a \code{write\_mesh()} call using
  the master mesh does \emph{not} store submeshes as well. After this
  call the submesh is again connected with the master mesh. The
  \code{init\_node\_proj} must be the same function as originally
  passed to the master mesh. The \code{binding\_method} must also be
  the same function as used to define the submesh originally. The
  reason for passing these pointers again is that there is no way to
  store the C code describing these functions in a file.

  \kitem{read\_submesh\_xdr()} Analogous function for submeshes stored
  by \code{write\_mesh\_xdr()}.

  \kitem{get\_bndry\_submesh(master, name)} A convenience function, internally
  \code{get\_submesh()} is called with an appropriate
  \code{binding\_method} which turns all boundary simplices into a sub-mesh.

  \kitem{get\_bndry\_submesh\_by\_type(master, name, type)}  Like  the
  function above, but allows for the specification of a boundary type.
  See Section \ref{S:boundary}.

  \kitem{get\_bndry\_submesh\_by\_segment(master, name, segment)} Like
    the function above, but allows for the specification of a boundary
    type bit-mask.  See Section \ref{S:boundary}.

  \kitem{read\_bndry\_submesh(master, filename)}
  \kitem{read\_bndry\_submesh\_xdr(master, filename)}
  \kitem{read\_bndry\_submesh\_by\_type(master, filename, type)}
  \kitem{read\_bndry\_submesh\_by\_type\_xdr(master, filename, type)}
  \kitem{read\_bndry\_submesh\_by\_segment(master, filename, segment)}
  \kitem{read\_bndry\_submesh\_by\_segment\_xdr(master, filename, segment)}~\\
  Counterparts to \code{read\_submesh()} and
  \code{read\_submesh\_xdr()} to read back sub-meshes generated by
  \code{get\_bndry\_submesh()} and
  \code{get\_bndry\_submesh\_by\_type()}, respectively.

  \kitem{get\_slave\_dof\_mapping(m\_fe\_space, s\_map)} Fills the
  vector \code{s\_map} on the submesh with the corresponding DOF
  indices of the finite element space \code{m\_fe\_space} on the
  master mesh. This only works if \code{m\_fe\_space} and
  \code{s\_map->fe\_space} are Lagrange type spaces of equal degree.
  The master DOF indices are not updated during mesh changes, hence
  the use of a \code{DOF\_INT\_VEC}, see \secref{S:DOF_VEC}.

  \kitem{get\_master(slave)} returns the master mesh of \code{slave}.
  
 \kitem{fill\_slave\_el\_info(slv\_el\_info, el\_info, face, slave\_mesh)}
  Fills a \code{EL\_INFO} element descriptor refering to the slave mesh.

 \kitem{fill\_master\_el\_info(mst\_el\_info, el\_info, face, fill\_flags)}
  Fills a \code{EL\_INFO} element descriptor refering to the slave mesh.
  \code{fill\_flags} determines what kind of information is provided.

 \kitem{trace\_to\_bulk\_coords(result, lambda, el\_info)}
 \kitem{bulk\_to\_trace\_coords(result, lambda, el\_info)}
  Given local coordinates on either the master or the trace mesh
  construct the matching local coordinates for the
  peer-element. \code{el\_info} always refers to the lower-dimensional slave-mesh.

 \kitem{get\_master\_dof\_indices(result, s\_el\_info, m\_fe\_space)}
  Find the \code{DOF}s of \code{m\_fe\_space} -- a finite element
  space belonging to a master mesh -- belonging to the
  \code{s\_el\_info} -- an element descriptor for an element of the
  slave mesh. If \code{result} is not \nil, then it is used as storage
  for the \code{DOF}-indices and its address is returned. Otherwise
  the address of a static storage area is returned which holds the
  results until it is overwritten on the call to
  \code{get\_master\_dof\_indices()}.

 \kitem{get\_master\_bound(result, s\_el\_info, m\_fe\_space)}
  Same for the boundary classification.

  \kitem{trace\_<TYPE>\_vec(slave\_vec, master\_vec)} Implement
  discrete trace operators. The vector \code{slave\_vec} must be based
  on a submesh of the mesh defining \code{master\_vec}. The entries of
  \code{slave\_vec} are overwritten with values of \code{master\_vec}
  along the interface. The finite element spaces of \code{slace\_vec}
  and \code{master\_vec} must be compatible, i.e.
  \code{slave\_vec->fe\_space->bas\_fcts} must be the trace space
  \code{master\_vec->fe\_space->bas\_fcts->trace\_bas\_fcts}.
  \code{<TYPE>} is one of \{\code{dof\_real}, \code{dof\_real\_d},
  \code{dof\_int}, \code{dof\_dof}, \code{int\_dof},
  \code{dof\_schar}, \code{dof\_uchar}, \code{dof\_ptr}\}, i.e. there
  is a trace operation for all \code{DOF}-vector types.
%  These routines use interpolation and therefore
%  work for any finite element spaces.  If both vectors are contained
%  in Lagrange type spaces of equal degree then the values will be
%  exactly the same at the DOFs that coincide spatially.


%  \kitem{get\_master\_binding(slave)} returns the \code{DOF\_PTR\_VEC}
%  \code{master\_binding} described above.

%  \kitem{get\_slave\_binding(slave)} returns the \code{DOF\_PTR\_VEC}
%  \code{slave\_binding} described above.
  \kitem{update\_master\_matrix(m\_dof\_matrix, s\_minfo)}
  \kitem{update\_master\_real\_vec(m\_drv, s\_vec\_info)}
  \kitem{update\_master\_real\_d\_vec(m\_drdv, s\_vec\_info)}~\\
  These functions take element-matrix descriptors \code{s\_minfo}
  designed for the slave-mesh and update a matrix for the master-mesh.
  This can, e.g., be used to assemble Robin boundary conditions and
  the like.
\end{descr}

\subsection{Refinement and coarsening of submeshes}%
\label{S:rc_submeshes}%
\idx{submeshes!refinement}%
\idx{submeshes!coarsening}

As explained above, submeshes and master meshes are automatically refined
and coarsened simultaneously to maintain matching nodes and edges. To 
guarantee this property we need to be careful in choosing the enumeration 
of vertices of the submesh. In the most complicated case of a 2d submesh of 
a 3d master mesh, the numbering of a slave element tied to a given face 
of a master tetrahedron depends on the master tetrahedron's 
orientation, type, and the face index. Figure \figref{F:submesh_numbering_3d}
demonstrates one given case. The 2d submesh triangles possess the property
that they are oriented in a right hand rule with the thumb pointing away
from the master element.

Any mesh, whether master mesh or submesh may be refined or coarsened by 
a call to the routines \code{refine()} or \code{coarsen}, see Sections
\ref{S:refinement_routines} and \ref{S:coarsening_routines} respectively.
As mentioned before, an entire hierarchy of submeshes from 3d down to 1d 
is possible. 

If a top-level master mesh is to be refined, then
the refinement algorithm is carried out as usual. The vector 
\code{slave\_binding} based on the top-level master mesh has an entry 
\code{refine\_interpol} set to a special internal routine. This routine
is called for each master refinement patch. It creates a corresponding 
submesh refinement patch for the submesh elements adjoining the master 
patch. The submesh patch is then refined (in the process calling in turn 
any \code{refine\_interpol}s of the submesh).

If a submesh is to be refined, \ALBERTA first transfers the refinement
markers of the submesh elements to the corresponding master elements
using \code{master\_binding}. Then \code{refine()} is called
recursively for the master mesh. Once we reach the top-level master
mesh we proceed as in the prior paragraph.  The submesh refinement
markers are reset during the refinement of the master meshes. The
diagram of \figref{F:submesh_refinement} describes this process.

\begin{figure}[htbp]
\centering
\includegraphics[scale=0.75]{EPS/submesh_refinement}
\caption{Modified refinement algorithm.}\label{F:submesh_refinement}
\end{figure}

Coarsening of master and submeshes works in much the same way. Note
that coarsening marks must be transferred to the master mesh to enable
any change --- this will overwrite refinement marks on the master mesh
elements along the interface! Furthermore, the master mesh receives
the same value of the coarsening mark as the slave mesh, which may not
be enough to guarantee the coarsening if the current refinement edge
of a master element does not lie along the interface with the submesh.

Another caveat is that the user should be careful when using other refinement 
interpolation or coarsening interpolation/restriction routines on the 
master mesh that perform certain operations using submeshes. The state of 
the submesh is undefined at the time of calling these routines.

To conclude, submeshes offer advantages in many calculations where
information based on surfaces or interfaces is necessary. The price of
using a submesh is the additional overhead of one \code{MESH}
structure plus the memory needed to store two \code{DOF\_PTR\_VEC}s
(and their respective DOF administration). The vector
\code{slave\_binding} is based on the master mesh, while the vector
\code{master\_binding} is based on the submesh. Both vector require
the feature \code{preserve\_coarse\_dofs}, see
\secref{S:basic_steps_rc} for details. Allocating submeshes once
the master mesh is strongly refined is to be avoided, since a DOF 
administration for new element nodes may have to be set up on the fly. This
can be expensive in terms of CPU time. The user should code the macro
triangulations in a way that the interface defining the submesh is 
easily accessible.





%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "alberta-man"
%%% End: