{\it TERRY}

\subsection{Mesh Entities}
\label{sec:entities}

{\it TERRY}

\subsubsection{Nodes}
\label{sec:nodes}

{\it TERRY}

\subsubsection{Elements}
\label{sec:elements}

{\it TERRY}

\subsubsection{Sparse Elements}
\label{sec:sparse}

{\it TERRY}

\subsubsection{Mesh Entity Operations}

{\it TERRY}

\subsubsection{Mesh Entity Queries}

{\it TERRY}

\subsubsection{Advanced Mesh Entity Operations}

{\it TERRY}

\subsection{Meshes}
\label{sec:meshes}

{\it TERRY}

\subsubsection{Basic Mesh Operations}

{\it TERRY}

\subsubsection{Mesh Utilities}

{\it TERRY}

\subsubsection{Advanced Mesh Operations}

{\it TERRY}

\subsection{Mesh Communication: Ghost Layers}
\label{sec:ghost}

{\it SAYANTAN}

\subsubsection{Ghost Numbering}

{\it SAYANTAN}

\subsubsection{Ghost Layer Creation\label{SectionGhostLayerCreation}}

{\it SAYANTAN}

\subsubsection{Symmetries and Ghosts: Geometric Layer}

{\it SAYANTAN}

\subsubsection{Advanced Symmetries and Ghosts: Lower Layer}

{\it SAYANTAN}

\subsection{Older Mesh Operations}

{\it SAYANTAN}

\subsubsection{Mesh Data Operations}

{\it SAYANTAN}

\subsubsection{Ghost Numbering}

{\it SAYANTAN}

\subsubsection{Backward Compatability}

{\it SAYANTAN}

\subsubsection{Sparse Data}

{\it SAYANTAN}

\subsection{Mesh Modification}

{\it AARON}

\subsection{Topological Mesh Data}

A ParFUM application can request that the ParFUM framework compute topological adjacencies. All ParFUM applications initially specify the mesh as a set of elements, each element defined by a fixed number of nodes. ParFUM can compute and maintain other sets of adjacencies such as which elements are adjacent to a given node, or which nodes are adjacent(they are both associated with a single element), or which elements share an edge/face with another element. Currently only a single element type is supported, and that element must be \texttt{FEM\_ELEM+0}. To generate the structures storing the other types of adjacencies, each process in the ParFUM application should call the following subroutines:

\begin{list}{-}{}
\item \texttt{FEM\_Add\_elem2face\_tuples(int mesh, 0, nodesPerFace, numFacesPerElement, faces);} specifies the topology of an element, specifically the configuration of its faces(if 3D) or edges(if 2D). Two elements are adjacent if they share a common face. The parameter faces is an integer array of length $nodesPerFace \cdot numFacesPerElement$. The description is the same as used for determining ghost layers in section \ref{SectionGhostLayerCreation}.
\item \texttt{FEM\_Mesh\_allocate\_valid\_attr(int mesh, int entity\_type);}
\item \texttt{FEM\_Mesh\_create\_node\_elem\_adjacency(int mesh);}
\item \texttt{FEM\_Mesh\_create\_node\_node\_adjacency(int mesh);}
\item \texttt{FEM\_Mesh\_create\_elem\_elem\_adjacency(int mesh);}
\end{list}

These subroutines can be called in \texttt{init} on a sequential mesh, or after partitioning in \texttt{driver}. The adjacencies will contain references to ghost elements if the subroutines were called in \texttt{driver} when ghosts are used. The indexes to ghosts are negative integers which can easily be converted to positive indices by using the function \texttt{FEM\_To\_ghost\_index(id)}. The C header \texttt{ParFUM\_internals.h} is required to be included by the ParFUM application to access the adjacencies. The functions to access the adjacencies are in sections \ref{adjacencies-e2e},\ref{adjacencies-n2e}, and \ref{adjacencies-n2n}.

The internal data structures representing the adjacencies are maintained correctly when the adaptivity operations described in section \ref{Subsection-Mesh-Adaptivity} are used.

\subsubsection{Accessing Element to Element Adjacencies\label{adjacencies-e2e}}

\begin{list}{-}{}
\item \texttt{void e2e\_getAll(int e, int *neighbors);} places all of element e's adjacent element ids in neighbors; assumes \texttt{neighbors} is already allocated to correct size
\item \texttt{int e2e\_getNbr(int e, short idx);} returns the id of the idx-th adjacent element
\end{list}


\subsubsection{Accessing Node to Element Adjacencies\label{adjacencies-n2e}}

\begin{list}{-}{}
\item \texttt{n2e\_getLength(int n)} returns the number of elements adjacent to the given node \texttt{n}.
\item \texttt{n2e\_getAll(int n, int *\&adjelements, int \&sz)} for node \texttt{n} place all the ids for adjacent elements into \texttt{adjelements}. You can ignore sz if you correctly determine the length beforehand.
\end{list}


\subsubsection{Accessing Node to Node Adjacencies\label{adjacencies-n2n}}

\begin{list}{-}{}
\item \texttt{n2n\_getLength(int n)} returns the number of nodes adjacent to the given node \texttt{n}.
\item \texttt{n2n\_getAll(int n, int *\&adjnodes, int \&sz)} for node \texttt{n} place all the ids for adjacent nodes into \texttt{adjnodes}. You can ignore sz if you correctly determine the length beforehand.
\end{list}




\subsection{Mesh Adaptivity\label{Subsection-Mesh-Adaptivity}}


\subsubsection{Initialization}
If a ParFUM application wants to use parallel mesh adaptivity,
the first task is to call the initialization routine from the 
{\it driver} function. This creates the node and element 
adjacency information that is essential for the adaptivity 
operations. It also initializes all the mesh adaptivity related
internal objects in the framework.

\function{void FEM\_ADAPT\_Init(int meshID)}
\index{femAdaptInit}
\desc{Initializes the mesh defined by {\it meshID} for the mesh
adaptivity operations.}

\subsubsection{Preparing the Mesh}
For every element entity in the mesh, there is a desired size entry 
for each element. This entry is called meshSizing. This meshSizing entry 
contains a metric that determines element quality. The default metric is
the average of the length of the three edges of an element. ParFUM provides 
various mechanisms to set this field. Some of the adaptive operations
use these metrics to maintain quality. In addition, there is another metric
which is computed for each element and maintained during mesh adaptivity. This metric 
is the ratio of the longest side to the shortest altitude, and this value 
is not allowed to go beyond a certain limit in order to maintain element quality.

\function{void FEM\_ADAPT\_SetElementSizeField(int meshID, int elem, double size);}
\index{femAdaptSetElementSizeField1}
\desc{For the mesh specified by {\it meshID}, for the element {\it elem},
we set the desired size for each element to be {\it size}.}

\function{void FEM\_ADAPT\_SetElementSizeField(int meshID, double *sizes);}
\index{femAdaptSetElementSizeField2}
\desc{For the mesh specified by {\it meshID}, for the element {\it elem},
we set the desired size for each element from the corresonponding entry in
the {\it sizes} array.}

\function{void FEM\_ADAPT\_SetReferenceMesh(int meshID);}
\index{femAdaptSetReferenceMesh}
\desc{For each element int this mesh defined by {\it meshID} 
set its size to the average edge length of the corresponding element.}

\function{void FEM\_ADAPT\_GradateMesh(int meshID, double smoothness);}
\index{femAdaptGradateMesh}
\desc{Resize mesh elements to avoid jumps in element size.
That is, avoid discontinuities in the desired sizes for elements of a mesh
by smoothing them out. Algorithm based on h-shock correction, described in
Mesh Gradation Control, Borouchaki et al.}


\subsubsection{Modifying the Mesh}
Once the elements in the mesh have been prepared by specifying their desired
sizes, we are ready to use the actual adaptivity operations. Currently we
provide delaunay flip operations, edge bisect operations and edge coarsen 
operations, all of which are implemented in parallel. We provide several higher level 
functions which use these basic operations to 
generate a mesh with higher quality elements while achieving the
desired sizing.

\function{void FEM\_ADAPT\_Refine(int meshID, int qm, int method, double factor,double *sizes);}
\index{femAdaptRefine}
\desc{Perform refinements on the mesh specified by {\it meshId}.
Tries to maintain/improve element quality by refining the mesh
as specified by a quality measure {\it qm}.
If {\it method} = 0, refine areas with size larger than {\it factor} down to {\it factor}
If {\it method} = 1, refine elements down to sizes specified in the {\it sizes} array.
In this array each entry corresponds to the corresponding element.
Negative entries in sizes array indicate no refinement. }

\function{void FEM\_ADAPT\_Coarsen(int meshID, int qm, int method, double factor,double *sizes);}
\index{femAdaptCoarsen}
\desc{Perform refinements on the mesh specified by {\it meshId}.
Tries to maintain/improve element quality by coarsening the mesh
as specified by a quality measure {\it qm}.
If {\it method} = 0, coarsen areas with size smaller than {\it factor} down to {\it factor}
If {\it method} = 1, coarsen elements up to sizes specified in the {\it sizes} array.
In this array each entry corresponds to the corresponding element.
Negative entries in sizes array indicate no coarsening. }

\function{void FEM\_ADAPT\_AdaptMesh(int meshID, int qm, int method, double factor,double *sizes);}
\index{femAdaptAdaptMesh}
\desc{This function has the same set of arguments as required by the previous two operations,
namely refine and coarsen. This function keeps using the above two functions until
we have all elements in the mesh with as close to the desired quality. Apart from
using the above two operations, it also performs a mesh repair operation which
gets rid of some bad quality elements by delaunay flip or coarsening as the
geometry in the area demands.}

\function{int FEM\_ADAPT\_SimpleRefineMesh(int meshID, double targetA, double xmin, double ymin, double xmax, double ymax);}
\index{femAdaptSimpleRefineMesh}
\desc{A region is defined by ({\it xmax, xmin, ymax, ymin}) 
and the target area to be achieved for all elements in this region
in the mesh specified by {\it meshID} is given by {\it targetA}.
This function only performs a series of refinements on the elements in this region.
If the area is larger, then no coarsening is done.}

\function{int FEM\_ADAPT\_SimpleCoarsenMesh(int meshID, double targetA, double xmin, double ymin, double xmax, double ymax);}
\index{femAdaptSimpleCoarsenMesh}
\desc{A region is defined by ({\it xmax, xmin, ymax, ymin}) 
and the target area to be achieved for all elements in this region
in the mesh specified by {\it meshID} is given by {\it targetA}.
This function only performs a series of coarsenings on the elements in this region.
If the area is smaller, then no refinement is done.}


\subsection{Verifying correctness}
We provide a checking function that can be used for debugging purposes to identify corrupted meshes or low quality elements.

\function{void FEM\_ADAPT\_TestMesh(int meshID);}
\index{femAdaptTestMesh}
\desc{This provides a series of tests to determine the consistency of the
mesh specified by {\it meshID}.}
