\section{Administration of degrees of freedom}%
\label{S:DOFs2}%
\idx{DOFs!implementation|(}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Degrees of freedom (DOFs) give connection between local and global
finite element functions, compare Sections \ref{book:S:FES} and
\ref{book:S:DOFs1}.  We want to be able to have several finite element
spaces and corresponding sets of DOFs at the same time. One set of
DOFs may be shared between different finite element spaces, when
appropriate.

During adaptive refinement and coarsening of a triangulation, not only
elements of the mesh are created and deleted, but also degrees of
freedom. The geometry is handled dynamically in a
hierarchical binary tree structure, using pointers from parent
elements to their children. For data corresponding to DOFs, which are
usually involved with matrix-vector operations, simpler storage and
access methods are more efficient. For that reason every DOF is
realized just as an integer index, which can easily be used to access
data from a vector or to build matrices that operate on vectors of DOF
data.

During coarsening of the mesh, DOFs are deleted. In general, the
deleted DOF is not the one which corresponds to the largest integer
index. ``Holes'' with unused indices appear in the total range of used
indices. One of the main aspects of the DOF administration is to keep
track of all used and unused indices. One possibility to remove holes
from vectors is the compression of DOFs, i.e.\ the renumbering of all
DOFs such that all unused indices are shifted to the end of the index
range, thus removing holes of unused indices. While the global index
corresponding to a DOF may change, the \emph{relative} order of DOF
indices remains unchanged during compression.

During refinement of the mesh, new DOFs are added, and additional
indices are needed. If a deletion of DOFs created some unused indices
before, some of these can be reused for the new DOFs. Otherwise, the
total range of used indices has to be enlarged, and the new indices
are taken from this new range. At the same time, all vectors and
matrices which are supposed to use these DOF indices have to be
adjusted in size, too.  This is the next major aspect of the DOF
administration. To be able to do this, lists of vectors and matrices
are included in the \verb|DOF_ADMIN| data structure. Entries are added
to or removed from these lists via special subroutines, see Section
\ref{S:DOF_VEC}.

In \ALBERTA, every abstract DOF is realized as an integer index into
vectors:
\ddx{DOF@{\code{DOF}}}
\bv\begin{lstlisting}
typedef signed int   DOF;
\end{lstlisting}\ev
%
These indices are administrated via the \verb|DOF_ADMIN| data
structure (see \ref{S:DOF_ADMIN}) and some subroutines. For each set
of DOFs, one \verb|DOF_ADMIN| structure is created.  Degrees of
freedom are directly connected with the mesh. The \code{MESH} data
structure contains a reference to all sets of DOFs which are used on a
mesh, compare Section \ref{S:mesh_data_structure}.  The
\code{FE\_SPACE} structure describing a finite element space
references the corresponding set of DOFs, compare Sections
\ref{book:S:FES}, \ref{S:basfct_data}. Several \verb|FE_SPACE|s may share the
same set of DOFs, thus reference the same \verb|DOF_ADMIN| structure.
Usually, a \verb|DOF_ADMIN| structure is created during definition of
a finite element space by \code{get\_fe\_space()}, see Section
\ref{S:access_fe_space}.  For special applications, additional DOF
sets, that are not connected to any finite element space may also
be defined (compare Section~\ref{S:access_fe_space}).

In Sections \ref{S:FOR_ALL_DOFS} and \ref{S:dof_access}, we describe
storage and access methods for global DOFs and local DOFs on single
mesh elements.

As already mentioned above, special data types for data vectors and
matrices are defined, see Sections \ref{S:DOF_VEC} and
\ref{S:DOF_MATRIX}. Several BLAS routines are available for such
data, see Section \ref{S:DOF_BLAS}.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{The \code{DOF\_ADMIN} data structure}\label{S:DOF_ADMIN}

The following data structure holds all data about one set of DOFs.  It
includes information about used and unused DOF indices, as well as
linked lists of matrices and vectors of different data types, that are
automatically resized and resorted during mesh changes.  Currently,
only an automatic \emph{enlargement} of vectors is implemented, but no
automatic shrinking.  The actual implementation of used and unused
DOFs is not described here in detail --- it uses only one bit of
storage for every integer index.
%
\ddx{DOF_ADMIN@{\code{DOF\_ADMIN}}}
\ddx{DOF_FREE_UNIT@{\code{DOF\_FREE\_UNIT}}}
\bv\begin{lstlisting}[name=DOF_ADMIN,label=T:DOF_ADMIN]
typedef struct dof_admin  DOF_ADMIN;
typedef unsigned long     DOF_FREE_UNIT;

/* Possible values for DOF_ADMIN->flags */
# define ADM_FLAGS_DFLT           0        /* nothing special */
# define ADM_PRESERVE_COARSE_DOFS (1 << 0) /* preserve non-leaf DOFs */
# define ADM_PERIODIC             (1 << 1) /* periodic ADMIN on a
					    * periodic mesh
					    */
#define ADM_FLAGS_MASK (ADM_PRESERVE_COARSE_DOFS | ADM_PERIODIC)

struct dof_admin
{
  MESH         *mesh;
  const char   *name;

  DOF_FREE_UNIT *dof_free;    /* flag bit vector */
  unsigned int  dof_free_size;/* flag bit vector size */
  unsigned int  first_hole;   /* index of first non-zero dof_free entry */

  FLAGS         flags;

  DOF  size;                 /* allocated size of dof_list vector */
  DOF  used_count;           /* number of used dof indices */
  DOF  hole_count;           /* number of FREED dof indices (NOT size-used)*/
  DOF  size_used;            /* > max. index of a used entry */

  int  n_dof[N_NODE_TYPES];  /* dofs from THIS dof_admin */
  int  n0_dof[N_NODE_TYPES]; /* start of THIS admin's DOFs in the mesh. */
  /****************************************************************************/
  DOF_INT_VEC     *dof_int_vec;           /* linked list of int vectors */
  DOF_DOF_VEC     *dof_dof_vec;           /* linked list of dof vectors */
  DOF_DOF_VEC     *int_dof_vec;           /* linked list of dof vectors */
  DOF_UCHAR_VEC   *dof_uchar_vec;         /* linked list of u_char vectors */
  DOF_SCHAR_VEC   *dof_schar_vec;         /* linked list of s_char vectors */
  DOF_REAL_VEC    *dof_real_vec;          /* linked list of real vectors   */
  DOF_REAL_D_VEC  *dof_real_d_vec;        /* linked list of real_d vectors */
  DOF_PTR_VEC     *dof_ptr_vec;           /* linked list of void * vectors */
  DOF_MATRIX      *dof_matrix;            /* linked list of matrices */

  DBL_LIST_NODE   compress_hooks;         /* linked list of custom compress
					   * handlers.
					   */

/*******************************************************************************
 * pointer for administration; don't touch!
 ******************************************************************************/

  void            *mem_info;
};
\end{lstlisting}\ev
The entries yield following information:
\begin{descr}
\kitem{mesh} this is a \code{dof\_admin} on \code{mesh};
  %% 
\kitem{name} a string holding a textual description of this
  \code{dof\_admin};
\kitem{dof\_free, dof\_free\_size, first\_hole} internally used variables
  for administration of used and free DOF indices;
  % 
\kitem{flags} The bit-wise or of flags controlling the behavior of the
  DOF-administrator:
  \begin{descr}
  \kitem{ADM\_PERIODIC} The DOF-administrator identifies DOFs across
    periodic boundaries, compare \secref{S:periodic}.
    %% 
  \kitem{ADM\_PRESERVE\_COARSE\_DOFS} Do not delete DOFs on the
    coarse-levels of the mesh during mesh-refinement. This must be set
    to implement, e.g., multi-grid methods for higher order elements.
    See also \secref{S:basic_steps_rc}
    and\secref{S:refinement_routines}.
  \end{descr}
  %% 
\kitem{size}    current size of vectors in \verb|dof_*_vec| and
  \verb|dof_matrix| lists;
  %% 
\kitem{used\_count} number of used dof indices;
  %% 
\kitem{hole\_count} number of {\em freed} dof indices 
  ({\em not} \verb|size|$-$\verb|used_count|);
  %% 
\kitem{size\_used}  $\geq$ largest used DOF index;
  %% 
\kitem{n\_dof}   numbers of degrees of freedom defined by this \verb|dof_admin|
  structure; \code{n\_dof[VERTEX]}\cdx{VERTEX@{\code{VERTEX}}},
  \verb|n_dof[EDGE]|\cdx{EDGE@{\code{EDGE}}},
  \verb|n_dof[FACE]|\cdx{FACE@{\code{FACE}}}, and
  \verb|n_dof[CENTER]|\cdx{CENTER@{\code{CENTER}}} are the DOF
  counts at vertices, edges, faces (only in 3d) and
  element interiors, compare Section
  \ref{S:dof_access}.  These values are usually set by
  \verb|get_fe_space()| as a copy from
  \verb|bas_fcts->n_dof| (compare
  Section~\ref{S:basfct_data}).
  %% 
\kitem{n0\_dof}  start indices \verb|n0_dof[VERTEX/CENTER/EDGE/FACE]| of the
  first dofs defined by this \verb|dof_admin| in the
  element's \verb|dof[VERTEX/CENTER/EDGE/FACE]| vectors.
  These are
  the sums of degrees of freedom defined by previous
  \verb|dof_admin| structures that were already added
  to the same mesh; \verb|n0_dof[VERTEX/CENTER/EDGE/FACE]|,
  are all set automatically by \verb|get_fe_space()|.
  See Section \ref{S:dof_access} for details and usage;
  %% 
\kitem{dof\_*\_vec, dof\_matrix} pointers to linked lists of
  \verb|DOF_*_VEC|, \verb|DOF_MATRIX| structures which are associated
  with the DOFs administrated by this \verb|DOF_ADMIN| and whose size
  is automatically adjusted during mesh refinements, compare Section
  \ref{S:DOF_VEC};
  %% 
\kitem{compress\_hooks} Root to a doubly linked list of custom
  handlers executed when \code{dof\_compress()} is called. An
  application may install arbitrarily many custom compress-handlers
  via \code{add\_dof\_compress\_hook()}, and delete them via
  \code{del\_dof\_compress\_hook()}. See further below.
  %% 
\kitem{mem\_info} used internally for memory management.
  %% 
\end{descr}
Deletion of DOFs occurs not only when the mesh is (locally) coarsened, but also
during refinement of a mesh with higher order elements. This is due to the
fact, that during local interpolation operations, both coarse-grid and
fine-grid DOFs must be present, so deletion of coarse-grid DOFs that
are no longer used is done after allocation of new fine-grid DOFs.
Usually, all operations concerning DOFs are done automatically by
routines doing mesh adaption or handling finite element spaces. The
removal of ``holes'' in the range of used DOF indices is not done
automatically. It is actually not \emph{needed} to be done, but may
speed up the access in loops over global DOFs; When there are no
holes, then a simple \verb|for|-loop can be used without checking for
each index, whether it is currently in use or not. The
\verb|FOR_ALL_DOFS()|-macro described in Section \ref{S:FOR_ALL_DOFS}
checks this case. Hole removal is done for all \verb|DOF_ADMIN|s
of a mesh by the function
%%
\fdx{dof_compress()@{\code{dof\_compress()}}}
\fdx{add_dof_compress_hook()@{\code{add\_dof\_compress\_hook()}}}
\fdx{del_dof_compress_hook()@{\code{del\_dof\_compress\_hook()}}}
%%
\bv\begin{lstlisting}
void dof_compress(MESH *);

typedef struct dof_comp_hook DOF_COMP_HOOK;
struct dof_comp_hook
{
  DBL_LIST_NODE node; /* our link to the compress_hooks list */
  void (*handler)(DOF first, DOF last, const DOF *new_dof, void *app_data);
  void *application_data;
};

void add_dof_compress_hook(const DOF_ADMIN *admin, DOF_COMP_HOOK *hook);
void del_dof_compress_hook(DOF_COMP_HOOK *hook);
\end{lstlisting}\ev
Description:
\begin{descr}
\kitem{dof\_compress(mesh)}  remove all holes of
 unused DOF indices by compressing the used range of indices (it does
 \emph{not} resize the vectors). While the global index corresponding
 to a DOF may change, the \emph{relative} order of DOF indices remains
 unchanged during compression.

 This routine is usually called after
 a mesh adaption involving higher order elements or coarsening.
%%
 \kitem{add\_dof\_compress\_hook(admin, hook),
   del\_dof\_compress\_hook(hook)} Add to or delete from the list of
 application defined DOF-compress functions. \code{dof\_compress()}
 will call all installed handlers in turn. The calling convention for
 the \code{handler(first, last, new\_dof[], app\_data)} component in
 the \code{DOF\_COMP\_HOOK}-structure are:
 \begin{descr}
   \kitem{first, last} Bounds for the index range where something has
   changed. The application may assume that all DOFs outside the index
   range \code{first,\dots,last} have not been renumbered.
   %%
   \kitem{new\_dof[]} The index permutation, \code{new\_dof[old\_dof]}
   is the new index assigned to the DOF with the old number
   \code{old\_dof}.
   %%
   \kitem{app\_data} This is the structure-component
   \code{application\_data} stored in the
   \code{DOF\_COMP\_HOOK}-structure.
 \end{descr}
\end{descr}

Usually, the range of DOF indices is enlarged in fixed increments
given by the symbolic constant \verb|SIZE_INCREMENT|, defined in
\verb|dof_admin.c|. If an estimate of the finally needed number of DOFs
is available, then a direct enlargement of the DOF range to that number
can be forced by calling:
\fdx{enlarge_dof_lists()@{\code{enlarge\_dof\_lists()}}}
\bv\begin{lstlisting}
void enlarge_dof_lists(DOF_ADMIN *, int);
\end{lstlisting}\ev
Description:
\begin{descr}
\kitem{enlarge\_dof\_lists(admin, minsize)} enlarges the
 range of the indices of \code{admin} to \code{minsize}.
\end{descr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{Vectors indexed by DOFs: The \code{DOF\_*\_VEC} data structures}%
\label{S:DOF_VEC}

The DOFs described above are just integers that can be used as indices
into vectors and matrices. During refinement and coarsening of the
mesh, the number of used DOFs, the meaning of one integer index, and
even the total range of DOFs change. To be able to handle these
changes automatically for all vectors, which are indexed by the DOFs,
special data structures are used which contain such vector data.
Lists of these structures are kept in the \verb|DOF_ADMIN| structure,
so that all vectors in the lists can be resized together with the
range of DOFs.  During refinement and coarsening of elements, values
can be interpolated automatically to new DOFs, and restricted from old
DOFs, see Section \ref{S:DOF_INTERPOL}.

\ALBERTA\ includes data types for vectors of type \verb|REAL|,
\verb|REAL_D|, \verb|S_CHAR|, \verb|U_CHAR|, \verb|int|, and
\verb|void *|. Below, the
%%
\verb|DOF_REAL_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_REAL_VEC@{\code{DOF\_REAL\_VEC}}},
%%
structure is described in detail. Structures
%%
\verb|DOF_REAL_D_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_REAL_D_VEC@{\code{DOF\_REAL\_D\_VEC}}},
\verb|DOF_SCHAR_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_SCHAR_VEC@{\code{DOF\_SCHAR\_VEC}}},
\verb|DOF_UCHAR_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_UCHAR_VEC@{\code{DOF\_UCHAR\_VEC}}},
\verb|DOF_PTR_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_PTR_VEC@{\code{DOF\_PTR\_VEC}}}, and
\verb|DOF_INT_VEC|\ddx{DOF_VEC@{\DOF-vectors}!DOF_INT_VEC@{\code{DOF\_INT\_VEC}}} are
declared similarly, the only difference between them is the type of
the structure entry \verb|vec|.  The exception is the
\verb|DOF_REAL_VEC_D|\ddx{DOF_VEC@{\DOF-vectors}!DOF_REAL_VEC_D@{\code{DOF\_REAL\_VEC\_D}}}
type, which is used to model vector-valued finite element functions
where the underlying basis functions are either vector- or
scalar-valued.

Although the administration of such vectors is done completely by the
DOF administration which needs \verb|DOF_ADMIN| data, the following
data structures include a reference to a \verb|FE_SPACE|, which
includes additionally the \verb|MESH| and \verb|BAS_FCTS|.  In this
way, complete information about a finite element function given by a
\verb|REAL|- and \verb|REAL_D|-valued vector is directly
accessible.
%
\ddx{DOF_VEC@{\DOF-vectors}!DOF_REAL_VEC@{\code{DOF\_REAL\_VEC}}}
\bv\begin{lstlisting}[label=T:DOF_REAL_VEC,name=DOF_REAL_VEC]
typedef struct dof_real_vec  DOF_REAL_VEC;

struct dof_real_vec
{
  DOF_REAL_VEC   *next;
  const FE_SPACE *fe_space;

  const char     *name;

  DOF            size;
  int            reserved; /* stride for DOF_REAL_VEC_D */

  REAL           *vec;     /* different type in DOF_INT_VEC, ... */

  void  (*refine_interpol)(DOF_REAL_VEC *, RC_LIST_EL *, int n);
  void  (*coarse_restrict)(DOF_REAL_VEC *, RC_LIST_EL *, int n);

  DBL_LIST_NODE    chain;        /* chain link for direct sum of fe-spaces */
  const DOF_REAL_VEC *unchained;

  EL_REAL_VEC_D    *vec_loc;

  void            *mem_info;
};
\end{lstlisting}\ev
\label{T:DOF_REAL_VEC_D}
\label{T:DOF_REAL_D_VEC}
\label{T:DOF_INT_VEC}
\label{T:DOF_UCHAR_VEC}
\label{T:DOF_SCHAR_VEC}

The members yield following information:
\begin{descr}
\kitem{next} linked list of \verb|DOF_REAL_VEC| structures in 
  \verb|fe_space->admin|;
  % 
\kitem{fe\_space} \code{FE\_SPACE} structure with information about DOFs
  and basis functions;
  % 
\kitem{name} string with a textual description of the vector, or \nil;
  % 
\kitem{size} current size of \verb|vec|;
  % 
\hyperitem{DOF_REAL_VEC_D:stride}{stride} the stride of \code{vec}. In
  the context of \code{DIM\_OF\_WORLD}-valued problems the underlying
  basis function may or may not be vector-valued for themselves. If
  they are scalar, \code{stride} is set to \code{DIM\_OF\_WORLD}, if
  the basis functions are vector-valued then \code{stride} is set to
  $1$.
  %
\hyperitem{DOF_REAL_VEC:reserved}{reserved} A place holder in all
  \code{DOF\_XXX\_VEC}-structures to make sure that it is possible to
  cast a \code{DOF\_REAL\_VEC\_D} to a \code{DOF\_REAL\_VEC} or a
  \code{DOF\_REAL\_D\_VEC}. Note that for \code{DOF\_REAL\_VEC}
  structures \code{reserved} will internally be tied to $1$, while it
  is tied to \DOW for \code{DOF\_REAL\_D\_VEC} structures.
  %
\kitem{vec}  pointer to \verb|REAL| vector of size \verb|size|;
  %% 
\kitem{refine\_interpol, coarse\_restrict} interpolation and
  restriction routines, see Section \ref{S:DOF_INTERPOL}. For
  \verb|REAL| and \verb|REAL_D| vectors, these usually point to the
  corresponding routines from \verb|fe_space->bas_fcts|, compare
  Section \ref{S:basfct_data}. While we distinguish there between
  \emph{restriction} and \emph{interpolation} during coarsening, only
  one such operation is appropriate for a given vector, as it either
  represents a finite element function or values of a functional
  applied to basis functions.
  % 
\kitem{chain} If the underlying finite element space has the
  structure of a direct sum, then this list-node component is the link
  to the individual components of that direct sum. See
  \secref{S:chain_impl}.
  %% 
\kitem{unchained} The name is misleading, as explained in
  \secref{S:sub_chains}, the reader should, however, have a look at
  \secref{S:chain_impl} first.
  %% 
\hyperitem{DOF_REAL_VEC:vec_loc}{vec\_loc} an element-vector. This
  element vector is used if the corresponding
  \code{BAS\_FCTS.get\_real\_vec()} hook is called with
  \code{result == NULL}.
  % 
\kitem{mem\_info} private pointer for administration, must not be changed.
\end{descr}

All DOF vectors linked in the corresponding
\verb|dof_admin->dof_*_vec| list are automatically adjusted in size
and reordered during mesh changes. Values are transformed during local
mesh changes, if the \verb|refine_interpol| and/or
\verb|coarse_restrict| entries are not \nil, compare Section
\ref{S:DOF_INTERPOL}.

Integer DOF vectors can be used in several ways: They may either hold
an \verb|int| value for each DOF, or reference a \verb|DOF| value for
each DOF.  In both cases, the vectors should be automatically resized
and rearranged during mesh changes. Additionally, values should be
automatically changed in the second case.  Such vectors are referenced
in the \verb|dof_admin->dof_int_vec| and \verb|dof_admin->dof_dof_vec|
lists.

On the other hand, \verb|DOF_INT_VEC|s provide a way to implement for
special applications a vector of \verb|DOF| values, which is
\emph{not indexed} by DOFs. For such vectors, only the values are
automatically changed during mesh changes, but not the size or
order. The user program is responsible for allocating memory for the
\verb|vec| vector. Such DOF vectors are referenced in the
\verb|dof_admin->int_dof_vec| list.

%% Why would one want such a macro except as a dirty debugging hack?
A macro \code{GET\_DOF\_VEC} is defined to simplify the secure access
to a \code{DOF\_*\_VEC}'s data. It assigns \verb|dof_vec->vec| to
\verb|ptr|, if both \verb|dof_vec| and \verb|dof_vec->vec| are not
\nil, and generates an error in other cases:
\mdx{GET_DOF_VEC()@{\code{GET\_DOF\_VEC()}}}
\bv\begin{lstlisting}
#define GET_DOF_VEC(ptr, dof_vec) TEST_EXIT((dof_vec)&&(ptr = (dof_vec)->vec))\
     ("%s == nil", (dof_vec) ? (dof_vec)->name : #dof_vec)
\end{lstlisting}\ev

The following subroutines are provided to handle DOF vectors.
Allocation of a new \code{DOF\_*\_VEC} and freeing of a \code{DOF\_*\_VEC}
(together with its \verb|vec|) are done with:
\fdx{get_dof_real_vec()@{\code{get\_dof\_real\_vec()}}}%
\fdx{get_dof_real_d_vec()@{\code{get\_dof\_real\_d\_vec()}}}%
\fdx{get_dof_real_vec_d()@{\code{get\_dof\_real\_vec\_d()}}}%
\fdx{get_dof_int_vec()@{\code{get\_dof\_int\_vec()}}}%
\fdx{get_dof_dof_vec()@{\code{get\_dof\_dof\_vec()}}}%
\fdx{get_int_dof_vec()@{\code{get\_int\_dof\_vec()}}}%
\fdx{get_dof_uchar_vec()@{\code{get\_dof\_uchar\_vec()}}}%
\fdx{get_dof_schar_vec()@{\code{get\_dof\_schar\_vec()}}}%
\fdx{get_dof_ptr_vec()@{\code{get\_dof\_ptr\_vec()}}}%
\fdx{free_dof_real_vec()@{\code{free\_dof\_real\_vec()}}}%
\fdx{free_dof_real_d_vec()@{\code{free\_dof\_real\_d\_vec()}}}%
\fdx{free_dof_real_vec_d()@{\code{free\_dof\_real\_vec\_d()}}}%
\fdx{free_dof_int_vec()@{\code{free\_dof\_int\_vec()}}}%
\fdx{free_dof_dof_vec()@{\code{free\_dof\_dof\_vec()}}}%
\fdx{free_int_dof_vec()@{\code{free\_int\_dof\_vec()}}}%
\fdx{free_dof_uchar_vec()@{\code{free\_dof\_uchar\_vec()}}}%
\fdx{free_dof_schar_vec()@{\code{free\_dof\_schar\_vec()}}}%
\fdx{free_dof_ptr_vec()@{\code{free\_dof\_ptr\_vec()}}}%
\bv\begin{lstlisting}
DOF_REAL_VEC    *get_dof_real_vec(const char *name, const FE_SPACE *fesp);
DOF_REAL_D_VEC  *get_dof_real_d_vec(const char *name, const FE_SPACE *fesp);
DOF_REAL_VEC_D  *get_dof_real_vec_d(const char *name, const FE_SPACE *fesp);
DOF_INT_VEC     *get_dof_int_vec(const char *name, const FE_SPACE *fesp);
DOF_INT_VEC     *get_dof_dof_vec(const char *name, const FE_SPACE *fesp);
DOF_INT_VEC     *get_int_dof_vec(const char *name, const FE_SPACE *fesp);
DOF_SCHAR_VEC   *get_dof_schar_vec(const char *name, const FE_SPACE *fesp);
DOF_UCHAR_VEC   *get_dof_uchar_vec(const char *name, const FE_SPACE *fesp);
DOF_PTR_VEC     *get_dof_ptr_vec(const char *name, const FE_SPACE *fesp);
void            free_dof_real_vec(DOF_REAL_VEC *vec);
void            free_dof_real_d_vec(DOF_REAL_D_VEC *vec);
void            free_dof_real_vec_d(DOF_REAL_VEC_D *vec);
void            free_dof_int_vec(DOF_INT_VEC *vec);
void            free_dof_dof_vec(DOF_INT_VEC *vec);
void            free_int_dof_vec(DOF_INT_VEC *vec);
void            free_dof_schar_vec(DOF_SCHAR_VEC *vec);
void            free_dof_uchar_vec(DOF_UCHAR_VEC *vec);
void            free_dof_ptr_vec(DOF_PTR_VEC *vec);
\end{lstlisting}\ev
By specifying a finite element space for a \verb|DOF\_*\_VEC|, the
corresponding set of DOFs is implicitly specified by
\verb|fe_space->admin|.  The DOF\_*\_VEC is linked into
\verb|DOF_ADMIN|'s appropriate \verb|dof_*_vec| list for automatic
handling during mesh changes. The DOF\_*\_VEC structure entries
\verb|next| and \verb|admin| are set during creation and must not be
changed otherwise! The size of the \verb|dof_vec->vec| vector is
automatically adjusted to the range of DOF indices controlled by
\verb|fe_space->admin|. The \code{name} argument is duplicated calling
\code{strdup(3)}.

If no finite element space is specified, then the vector will not be
controlled by any \verb|DOF_ADMIN|. In this case the user is
responsible for setting \verb|size| and allocating memory for
\verb|vec|.  Given these entries \ALBERTA will free such vectors
correctly using \verb|free_dof_*_vec|.
\emph{Allocating a \code{DOF\_REAL\_VEC\_D} without an underlying finite
  element space is not supported.}

\begin{compatibility}
  In contrast to previous \ALBERTA versions the
  \verb|get_dof_..._vec()| routines now make a copy of the finite
  element space, which is in turn deallocated upon the call to
  \verb|free_dof_..._vec()|.
\end{compatibility}

There is a special list for each type of DOF vectors in the
\verb|DOF_ADMIN| structure. All \verb|DOF_REAL_VEC|s,
\verb|DOF_REAL_D_VEC|s, \verb|DOF_UCHAR_VEC|s, \verb|DOF_SCHAR_VEC|s,
and \verb|DOF_PTR_VEC|s are added to the respective lists, whereas a
\verb|DOF_INT_VEC| may be added to one of three lists in
\verb|DOF_ADMIN|: \verb|dof_int_vec|, \verb|dof_dof_vec|, and
\verb|int_dof_vec|. The difference between these three lists is their
handling during a resize or compress of the DOF range. In contrast to
all other cases, for a vector in \verb|admin|'s \verb|int_dof_vec|
list, the \verb|size| is NOT changed with \verb|admin->size|. But the
values \verb|vec[i]|, $\verb|i|=1,\dots,\verb|size|$ are adjusted when
\verb|admin| is compressed, for example. For vectors in the
\verb|dof_dof_vec| list, both adjustments in \verb|size| and
adjustment of values is done.

The \verb|get_*_vec()| routines automatically allocate enough memory for the
data vector \verb|vec| as indicated by \verb|fe_space->admin->size|.
Pointers to the routines \verb|refine_interpol| and
\verb|coarse_restrict| are set to \nil. They must be
set explicitly after the call to \verb|get_*_vec()| for an interpolation
during refinement and/or interpolation/restriction
during coarsening. The \verb|free_*_vec()| routines remove the vector
from a \verb|vec->fe_space->admin->dof_*_vec| list and free the memory
used by \verb|vec->vec| and \verb|*vec|.

A printed output of DOF vector is produced by the routines:%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_int_vec()@{\code{print\_dof\_int\_vec()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_real_vec()@{\code{print\_dof\_real\_vec()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_real_d_vec()@{\code{print\_dof\_real\_d\_vec()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_real_vec_dow()@{\code{print\_dof\_real\_vec\_dow()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_uchar_vec()@{\code{print\_dof\_uchar\_vec()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_schar_vec()@{\code{print\_dof\_schar\_vec()}}}%
\fdx{print_dof_vec@{Printing of \DOF-vectors}!print_dof_ptr_vec()@{\code{print\_dof\_ptr\_vec()}}}%
\bv\begin{lstlisting}
void print_dof_int_vec(const DOF_INT_VEC *vec);
void print_dof_real_vec(const DOF_REAL_VEC *vec);
void print_dof_real_d_vec(const DOF_REAL_D_VEC *vec);
void print_dof_real_vec_dow(const DOF_REAL_VEC_D *vec);
void print_dof_schar_vec(const DOF_SCHAR_VEC *vec);
void print_dof_uchar_vec(const DOF_UCHAR_VEC *vec);
void print_dof_ptr_vec(const DOF_PTR_VEC *vec);
\end{lstlisting}\ev
%
Description:
\begin{descr}
\kitem{print\_dof\_*\_vec(dof\_vec)} prints the elements of the DOF vector
\code{dof\_vec} together with its name to the message stream.
\end{descr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{Interpolation and restriction of DOF vectors during mesh adaptation}%
\label{S:DOF_INTERPOL}%
\idx{interpolation}%
\idx{restriction}

During mesh refinement and coarsening, new DOFs are produced, or old
ones are deleted. In many cases, information stored in \verb|DOF_*_VEC|s
has to be adjusted to the new distribution of DOFs. To do this
automatically during the refinement and coarsening process, each
\verb|DOF_*_VEC| can provide pointers to subroutines \verb|refine_interpol|
and \verb|coarse_restrict|, that implements these operations on
data. During refinement and coarsening of a \verb|mesh|, these
routines are called for all \verb|DOF_*_VEC|s with non-\nil\ pointers in
all \verb|DOF_ADMIN|s in \verb|mesh->dof_admin|.

Before doing the mesh operations, it is checked whether any automatic
interpolations or restrictions during refinement or coarsening are
requested. If yes, then the corresponding operations will be performed
during local mesh changes.

As described in Sections \ref{S:refinement_routines} and
\ref{S:coarsening_routines}, interpolation resp.\ restriction of values 
is done during the mesh refinement and coarsening locally on every
refined resp.\ coarsened patch of elements. Which of the local DOFs
are created new, and which ones are kept from parent/children elements,
is described in these other sections, too.  All necessary
interpolations or restrictions are done by
looping through all \verb|DOF_ADMIN|s in \verb|mesh| and calling the
\verb|DOF_*_VEC|'s routines
\idx{refine_interpol()@{\code{refine\_interpol()}}}
\idx{coarse_restrict()@{\code{coarse\_restrict()}}}
\bv\begin{lstlisting}
struct dof_real_vec
{
  ...

  void  (*refine_interpol)(DOF_REAL_VEC *, RC_LIST_EL *, int);
  void  (*coarse_restrict)(DOF_REAL_VEC *, RC_LIST_EL *, int);
}
\end{lstlisting}\ev
Those implement interpolation and restriction on one patch of mesh
elements for this \verb|DOF_*_VEC|. Only these have to know about the
actual meaning of the DOFs. Here, \verb|RC_LIST_EL| is a vector
holding pointers to all \verb|n| parent elements which build the patch
(and thus have a common refinement edge). Usually, the interpolation
and restriction routines for \code{REAL} or \code{REAL\_D} vectors are
defined in the corresponding \verb|dof_vec->fe_space->bas_fcts|
structures. Interpolation or restriction of non-real values
(\code{int} or \code{CHAR}) is usually application dependent and is
not provided in the \code{BAS\_FCTS} structure.

Examples of these routines are shown in Sections
\ref{S:linear-fe}-\ref{S:quartic-fe}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{The \code{DOF\_MATRIX} data structure}\label{S:DOF_MATRIX}

\begin{compatibility}
  Previous versions of \ALBERTA defined extra-types for vector-valued
  problems, like \code{DOF\_DOWB\_MATRIX}, \code{DOWB\_OPERATOR\_INFO}
  etc. The ``\code{DOWB}'' (``DimOfWorldBlocks'') variants, however,
  already incorporated all the functionality of the ordinary
  scalar-only versions. Therefore the scalar-ony versions of most
  data-structures have been abandoned and were replaced by the
  ``\code{DOWB}'' variants, which in turn were renamed to use the
  scalar-only names. For example, in the current implementation a
  \code{DOF\_MATRIX} is in fact what older versions called a
  \code{DOF\_DOWB\_MATRIX}; and implements the scalar-only case as
  well as the block-matrix case.
\end{compatibility}

Not only vectors indexed by DOFs are available in \ALBERTA, but also
matrices which operate on these \verb|DOF_*_VEC|s. For finite element
calculations, these matrices are usually sparse, and should be stored
in a way that reflects this sparseness. We use a storage method which
is similar to the one used in \cite{NPV:91b}. This is further
explained below on page \pageref{T:MATRIX_ROW}.
%%
A \verb|DOF_MATRIX| structure is usually filled by local operations on
single elements, using the \verb|update_matrix()| routine, compare
Section \ref{S:update}, which automatically generates space for new
matrix entries by adding new \verb|MATRIX_ROW|s, if needed.
%%
In view of problems which involve vector-fields of size
\code{DIM\_OF\_WORLD} \ALBERTA supports block-matrices with entries of
type \code{REAL\_D} and \code{REAL\_DD} (as well, of course, as matrices
with scalar entries).
%%

%An automatic adjustment of matrix entry values during mesh refinement
%and coarsening is not possible in the current implementation.
Similar to DOF vectors, the \verb|DOF_MATRIX| structure contains
pointers to routines for interpolation and restriction during mesh
refinement and coarsening. Providing such routines, an existing
\verb|DOF_MATRIX| can be updated by local operations, and a complete
recalculation is not necessary. For DOF vectors describing finite
element functions, such an interpolation can be necessary even from a
mathematical point of view. For matrices, this is more mandatory. For
implicit discretizations, where a (non-) linear system involving the
\verb|DOF_MATRIX| has to be solved, this solution is usually much more
expensive than a complete new matrix recalculation. Thus, local matrix
updates will not save much time. But for explicit discretizations or for
expensive matrices, such a local matrix update may save a noticeable
amount of computing time.
%
\paragraph{Type definitions}
\ddx{DOF_MATRIX@{\code{DOF\_MATRIX}}}%
\bv\begin{lstlisting}[name=DOF_MATRIX,label=T:DOF_MATRIX]
typedef struct dof_matrix DOF_MATRIX
struct dof_matrix
{
  DOF_MATRIX     *next;
  const FE_SPACE *row_fe_space;
  const FE_SPACE *col_fe_space;
  const char     *name;

  MATRIX_ROW     **matrix_row;  /* lists of matrix entries   */
  DOF            size;          /* size of vector matrix_row */
  MATENT_TYPE    type;          /* type of matrix entries. */
  size_t         n_entries;     /* total number of entries in the matrix */

  BNDRY_FLAGS    dirichlet_bndry; /* bit-mask for Dirichlet b.c. */

  void           (*refine_interpol)(DOF_MATRIX *, RC_LIST_EL *, int n);
  void           (*coarse_restrict)(DOF_MATRIX *, RC_LIST_EL *, int n);

  DBL_LIST_NODE  row_chain;
  DBL_LIST_NODE  col_chain;
  const DOF_MATRIX *unchained;

  void           *mem_info;
};
\end{lstlisting}\ev
%%
Description of the individual structure components:
\begin{descr}
%%
\kitem{next} linked list of \verb|DOF_MATRIX| structures in
\verb|row_fe_space->admin|;
%%
\kitem{row\_fe\_space} \verb|FE_SPACE| structure with information
about corresponding row DOFs and basis functions;
%%
\kitem{col\_fe\_space} \verb|FE_SPACE| structure with information
about corresponding column DOFs and basis functions;
%%
\kitem{name} a textual description for the matrix, or \nil;
%%
\kitem{matrix\_row} vector of pointers to \verb|MATRIX_ROW|s, one for
each row, see below;
%%
\kitem{size} current size of the \verb|matrix_row| vector.
%%
\kitem{type} the type of the element entries, one of
\verb|MATENT_REAL|, \verb|MATENT_REAL_D| or \verb|MATENT_REAL_DD|;
%%
\kitem{dirichlet\_bndry} a bit-mask describing which parts of the
boundary should be treated as Dirichlet-boundary by \code{update\_matrix()};
%%
\kitem{n\_entries} the total number of entries currently stored in the
matrix, updated by \verb|add_element_matrix()| and reset to $0$ by
\verb|clear_dof_matrix()|;
%%
\kitem{refine\_interpol, coarse\_restrict} interpolation and
restriction routines as for \verb|DOF_*_VEC|s.  When implementing
interpolation or restriction routines for matrices it is up to the
user to remove matrix entries corresponding to obsolete DOFs.  This
functionality is not implemented in \ALBERTA at the moment since it
would involve an expensive search over all matrix entries after mesh
changes.
%%
\kitem{row\_chain, col\_chain} List pointers, in the context of direct
sums of finite element spaces a \verb|DOF_MATRIX| is actually a
block-matrix, where the individual blocks are again
\verb|DOF_MATRIX|es, each acting on a summand of the direct sum of
finite element spaces. See section \ref{S:chain_impl}.
%%
\kitem{unchained} Normally only a pointer to \nil,
\verb|dof_matrix_sub_chain()| uses this pointer to form a matrix which
acts only on a part of a direct sum of finite element spaces. See
Section \ref{S:chain_impl}.
%%
\kitem{mem\_info} private pointer for administration, should not be
changed.
\end{descr}
%

Every row of a matrix is realized as a linked list of
\verb|MATRIX_ROW| structures, each holding a maximum of
\verb|ROW_LENGTH| matrix entries from that row.  Each entry consists
of a column DOF index and the corresponding \verb|REAL| matrix entry.
Unused entries in a \verb|MATRIX_ROW| are marked with a negative
column index. The \verb|ROW_LENGTH| is a symbolic preprocessor
constant defined in \code{alberta.h}. For $d=2$ meshes built from
triangles, the refinement by bisection generates usually at most eight
elements meeting at a common vertex, more elements may meet only at
macro vertices. Thus, for piecewise linear (Lagrange) elements on
triangles, up to nine entries are non-zero in most rows of a mass or
stiffness matrix. This motivates the choice \verb|ROW_LENGTH = 9|. For
higher order elements or tetrahedra, there are much more non-zero
entries in each row. Thus, a split of rows into short
\verb|MATRIX_ROW| parts hopefully should not produce too much
overhead.
%%
\cdx{ROW_LENGTH@{\code{ROW\_LENGTH}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!ROW_LENGTH@{\code{ROW\_LENGTH}}}%
\mdx{ENTRY_USED()@{\code{ENTRY\_USED()}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!ENTRY_USED()@{\code{ENTRY\_USED()}}}%
\mdx{ENTRY_NOT_USED()@{\code{ENTRY\_NOT\_USED()}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!ENTRY_NOT_USED()@{\code{ENTRY\_NOT\_USED()}}}%
\cdx{UNUSED_ENTRY@{\code{UNUSED\_ENTRY}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!UNUSED_ENTRY@{\code{UNUSED\_ENTRY}}}%
\cdx{NO_MORE_ENTRIES@{\code{NO\_MORE\_ENTRIES}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!NO_MORE_ENTRIES@{\code{NO\_MORE\_ENTRIES}}}%
\ddx{MATRIX_ROW@{\code{MATRIX\_ROW}}}%
\ddx{MATRIX_ROW@{\code{MATRIX\_ROW}}!MATRIX_ROW_REAL@{\code{MATRIX\_ROW\_REAL}}}%
\ddx{MATRIX_ROW@{\code{MATRIX\_ROW}}!MATRIX_ROW_REAL_D@{\code{MATRIX\_ROW\_REAL\_D}}}%
\ddx{MATRIX_ROW@{\code{MATRIX\_ROW}}!MATRIX_ROW_REAL_DD@{\code{MATRIX\_ROW\_REAL\_DD}}}%
\idx{DOF_MATRIX@{\code{DOF\_MATRIX}}!MATRIX_ROW@{\code{MATRIX\_ROW}}}
\bv\begin{lstlisting}[name=MATRIX_ROW,label=T:MATRIX_ROW]
typedef struct matrix_row          MATRIX_ROW;
typedef struct matrix_row_real     MATRIX_ROW_REAL;
typedef struct matrix_row_real_d   MATRIX_ROW_REAL_D;
typedef struct matrix_row_real_dd  MATRIX_ROW_REAL_DD;

# define ROW_LENGTH 9

/* The actual size of this structure is determined by the type of the
 * matrix entries. The correct length is allocated in
 * get_matrix_row().
 */
# define SIZEOF_MATRIX_ROW(type)					\
  (sizeof(MATRIX_ROW) - sizeof(REAL_DD) + ROW_LENGTH*sizeof(type))

struct matrix_row
{
  MATRIX_ROW  *next;
  MATENT_TYPE type;
  DOF         col[ROW_LENGTH];    /* column indices */
  union {
    REAL    real[1];
    REAL_D  real_d[1];
    REAL_DD real_dd[1];
  } entry;
};

struct matrix_row_real
{
  MATRIX_ROW_REAL *next;
  MATENT_TYPE     type;
  DOF             col[ROW_LENGTH];    /* column indices */
  REAL            entry[ROW_LENGTH];  /* matrix entries */
};

struct matrix_row_real_d
{
  MATRIX_ROW_REAL_D *next;
  MATENT_TYPE       type;
  DOF               col[ROW_LENGTH];    /* column indices */
  REAL_D            entry[ROW_LENGTH];  /* matrix entries */
};

struct matrix_row_real_dd
{
  MATRIX_ROW_REAL_DD *next;
  MATENT_TYPE        type;
  DOF                col[ROW_LENGTH];    /* column indices */
  REAL_DD            entry[ROW_LENGTH];  /* matrix entries */
};

# define UNUSED_ENTRY    -1
# define NO_MORE_ENTRIES -2
# define ENTRY_USED(col)         ((col) >= 0)
# define ENTRY_NOT_USED(col)     ((col) < 0)

\end{lstlisting}\ev
\label{T:MATRIX_ROW_REAL}
\label{T:MATRIX_ROW_REAL_D}
\label{T:MATRIX_ROW_REAL_DD}

\noindent
Descriptions for the individual macros and structure components:
\begin{descr}
  \kitem{ROW\_LENGTH} the maximum number of data-times in one list
  element,
  %%
  \kitem{MATRIX\_ROW} a super-type which combines all
  \verb|MATRIX_ROW| data-types for all block-types. Components and
  their meaning:
  \begin{descr}
    \kitem{next} list node pointer
    %%
    \kitem{type} one of \verb|MATENT_{REAL, REAL_D, REAL_DD}|,
    specifying the block-type of the data entries
    %% 
    \kitem{col} the global \DOF-indices for the entries stored in this
    row-component. Entries can be flagged as unused by setting
    \verb|MATRIX_ROW.col[idx]| to \verb|UNUSED_ENTRY|, if
    \verb|MATRIX_ROW.col[idx] == NO_MORE_ENTRIES|, then this signals
    that the remainder of this row component does not contain any more
    data. The other values following such an entry are undefined.
    %%
    \kitem{entry} A union for the actual data entries, with
    sub-components for each block-type. Note that
    \verb|get_matrix_row()| actually allocates enough space to hold
    \verb|ROW_LENGTH| many entries in each row. The actual size of the
    allocated matrix-row structure can be determined by calling the
    macro \verb|SIZEOF_MATIX_ROW(type)| with type \verb|REAL|,
    \verb|REAL_D| or \verb|REAL_DD|.
  \end{descr}
  %%
  \kitem{SIZEOF\_MATRIX\_ROW(type)} See above.
  %%
  \kitem{MATRIX\_ROW\_\{REAL, REAL\_D, REAL\_DD\}} Data-types for each
  individual block-type. They differ from the super-type
  \verb|MATRIX_ROW| only in replacing the \code{entry} union by a
  simple field which holds \verb|ROW_LENGTH| many entries of the given
  matrix-entry type.
\end{descr}

\paragraph{Support routines}
The following routines are available for DOF-matrices:
\fdx{get_dof_matrix()@{\code{get\_dof\_matrix()}}}%
\fdx{free_dof_matrix()@{\code{free\_dof\_matrix()}}}%
\label{Func:clear_dof_matrix}%
\fdx{clear_dof_matrix()@{\code{clear\_dof\_matrix()}}}%
\fdx{print_dof_matrix()@{\code{print\_dof\_matrix()}}}%
\fdx{get_matrix-row()@{\code{get\_matrix\_row()}}}
\mdx{FOR_ALL_MAT_COLS()@{\code{FOR\_ALL\_MAT\_COLS()}}}%
\bv\begin{lstlisting}[name=DOF_MATRIX_ROUTINES,label=D:dofmatroutines]
DOF_MATRIX *get_dof_matrix(const char *name,
                           const FE_SPACE *row_fe_space,
                           const FE_SPACE *col_fe_space);
void       free_dof_matrix(DOF_MATRIX *matrix);
void       clear_dof_matrix(DOF_MATRIX *matrix);
void       print_dof_matrix(const DOF_MATRIX *matrix);
MATRIX_ROW *get_matrix_row(const FE_SPACE *fe_space, MATENT_TYPE type);
FOR_ALL_MAT_COLS(type, matrow, what)
\end{lstlisting}\ev
%
Description:
\begin{descr}
  %% 
\kitem{get\_dof\_matrix(name, row\_fe\_space, col\_fe\_space)}
  allocates a new \verb|DOF_MATRIX| structure operating between the
  finite element spaces \verb|col_fe_space| and \verb|row_fe_space|.
  If no \verb|col_fe_space| is given, then \verb|col_fe_space| is set
  to \verb|row_fe_space|. \code{name} is a textual description for the
  name of the new matrix, it is duplicated using \code{strdup(3)}.
  The new matrix is automatically linked into the
  \verb|row_fe_space->admin->dof_matrix| list. A \verb|matrix_row|
  vector of length \verb|row_fe_space->admin->size| is allocated and
  all entries are set to \nil.
  %% 
\kitem{free\_dof\_matrix(matrix)} frees the DOF matrix \code{matrix}
  previously accessed by the function \code{get\_dof\_matrix()}.
  First, all \verb|MATRIX_ROW|s in \verb|matrix->matrix_row| are freed, 
  then \verb|matrix->matrix_row|, and finally the structure \verb|*matrix|.
  %% 
\kitem{clear\_dof\_matrix(matrix)} clears all entries of the DOF matrix
  \code{matrix}. This is done by \emph{removing} all entries from the 
  DOF matrix,
  i.\,e. all \verb|MATRIX_ROW|s in \verb|matrix->matrix_row| are freed
  and all entries in \verb|matrix->matrix_row| are set to \nil.
  %% 
\kitem{print\_dof\_matrix(matrix)} prints the elements of the DOF matrix
  \code{matrix} together with its name to the message stream.
  %% 
\kitem{get\_matrix\_row(fe\_space, type)} Allocate a new
  \verb|MATRIX_ROW| for a \verb|DOF_MATRIX| with
  \verb|row_fe_space == fe_space|. The second argument specifies the
  type of the entries and is one of \verb|REAL|, \verb|REAL_D| or
  \verb|REAL_DD|.
  %% 
\kitem{FOR\_ALL\_MAT\_COLS(type, matrow, what)} Because the
  \verb|MATRIX_ROW|-structure is somewhat complicated this defines an
  ``iterator'' over all entries of a matrix-row and hides the dirty
  details from the application program. The meaning of the arguments is
  like follows:
  \begin{descr}\label{D:FOR_ALL_MAT_COLS}
  \kitem{type} One of \verb|REAL|, \verb|REAL_D| or
    \verb|REAL_DD|. \verb|type| must be the same as
    \verb|DOF_MATRIX.type| respectively \verb|MATRIX_ROW.type|, or the
    results will be unpredictable.
  \kitem{\code{matrow}} A pointer to the matrix-row to iterator over.
    \code{row} may be \nil.
  \kitem{\code{what}} A block of statements to execute for each entry of
    the matrix-row. When \code{what} is executed the following variables
    are pre-defined to give access to the data of the current entry:
    \begin{descr}
    \kitem{\code{col\_idx}} The index into \verb|MATRIX_ROW.data|.
    \kitem{\code{col\_dof}} The global \DOF-index of the current entry.
    \end{descr}
  \end{descr}
  Example \ref{ex:matrixvector} contains two examples for the
  iteration over the columns of \verb|MATRIX_ROW|s, one using the
  \verb|FOR_ALL_MAT_COLS| macro, and another one with yields the same
  results without the use of this macro.
\end{descr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{Access to global DOFs: Macros for iterations using DOF indices}
\label{S:FOR_ALL_DOFS}

For loops over all used (or free) DOFs, the following macros are defined:
\idx{DOFs!FOR_ALL_DOFS()@{\code{FOR\_ALL\_DOFS()}}}
\mdx{FOR_ALL_DOFS()@{\code{FOR\_ALL\_DOFS()}}}
\idx{DOFs!FOR_ALL_FREE_DOFS()@{\code{FOR\_ALL\_FREE\_DOFS()}}}
\mdx{FOR_ALL_FREE_DOFS()@{\code{FOR\_ALL\_FREE\_DOFS()}}}
\bv\begin{lstlisting}
 FOR_ALL_DOFS(const DOF_ADMIN *, todo);
 FOR_ALL_FREE_DOFS(const DOF_ADMIN *, todo);
\end{lstlisting}\ev
%
Description:
\begin{descr}
\kitem{FOR\_ALL\_DOFS(admin, todo)} loops over all used DOFs of
\code{admin}; \code{todo} is a list of C-statements which are to be
executed for every used DOF index. During \code{todo}, the local
variable \code{int dof} holds the current index of the used entry; 
it must not be altered by \code{todo};
\kitem{FOR\_ALL\_FREE\_DOFS(admin, todo)} loops over all unused DOFs of
\code{admin}; \code{todo} is a list of C-statements which are to be
executed for every unused DOF index. During \code{todo}, the local
variable \code{int dof} holds the current index of the unused entry;
it must not be altered by \code{todo}.
\end{descr}
%
In the context of direct sums of finite element spaces, there are
other macros called \code{FOREACH\_DOF(fe\_space,\dots)} which wrap
\code{FOR\_ALL[\_FREE]\_DOFS()} into an outer loop over the components
of the direct sum, see \secref{S:chain_loops}.  Two examples
illustrate the usage of the \code{FOR\_ALL[\_FREE]\_DOFS()}:

\begin{example}[Initialization of vectors]
This BLAS-1 routine \code{dset()} initializes all elements of a
vector with a given value; for \code{DOF\_REAL\_VEC}s we have to set
this value for all \emph{used} DOFs. All used entries of the
\code{DOF\_REAL\_VEC *drv} are set to a value \code{alpha} by:
\bv\begin{lstlisting}
FOR_ALL_DOFS(drv->fe_space->admin, drv->vec[dof] = alpha);
\end{lstlisting}\ev
The BLAS-1 routine \code{dof\_set()} is written this way, compare
Section \ref{S:DOF_BLAS}.
\end{example}

\begin{example}[Matrix-vector multiplication]
\label{ex:matrixvector}
As a more complex example we give the main loop from an implementation
of the matrix-vector product in \code{dof\_mv()}, compare Sections
\ref{S:DOF_MATRIX} and \ref{S:DOF_BLAS}, specifically the explanations
for \verb|FOR_ALL_MAT_COLS()| on page \pageref{D:FOR_ALL_MAT_COLS}:
%%
\bv\begin{lstlisting}
    FOR_ALL_DOFS(admin, {
	REAL sum = 0.0;
	FOR_ALL_MAT_COLS(REAL, a->matrix_row[dof], {
	    sum += row->entry[col_idx] * xvec[col_dof];
	  });
	yvec[dof] = sum;
      });
\end{lstlisting}\ev
%%
Without the use of the \verb|FOR_ALL_MAT_COLS()|-macro, the same
example looks like follows:
%%
\bv\begin{lstlisting}
    FOR_ALL_DOFS(admin, {
	REAL sum = 0.0;
        MATRIX_ROW_REAL *row;
	for (row = (MATRIX_ROW_REAL *)a->matrix_row[dof];
             row != NULL;
             row = row->next) {
	  for (j = 0; j < ROW_LENGTH; j++) {
	    jcol = row->col[j];
	    if (ENTRY_USED(jcol)) {
	      sum += row->entry[j] * xvec[jcol];
	    } else if (jcol == NO_MORE_ENTRIES) {
	      break;
	    }
	  }
	}
	yvec[dof] = sum;
      });
\end{lstlisting}\ev
\end{example}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{Access to local DOFs on elements}\label{S:dof_access}

As shown by the examples in Figure \ref{book:F:dof_distribution}, the DOF
administration is able to handle different sets of DOFs, defined by
different \verb|DOF_ADMIN| structures, at the same time.  All
operations with finite element functions, like evaluation or
integration, are done locally on the level of single elements.  Thus,
access on element level to DOFs from a single \verb|DOF_ADMIN| has to
be provided in a way that is independent from all other finite element
spaces which might be defined on the mesh.

As described in Section \ref{S:element}, the \verb|EL| data structure
holds a vector of pointers to DOF vectors, that contain data for
\emph{all} DOFs on the element from all \verb|DOF_ADMIN|s:
\idx{DOFs!entries in the \code{el} structure}
\bv\begin{lstlisting}
struct el
{
  ...
  DOF             **dof;
  ...
};
\end{lstlisting}\ev
The lengths of these vectors are
computed by collecting data from all \verb|DOF_ADMIN|s associated with
the mesh; details are given below. Information about all DOFs
associated with a mesh is collected and accessible in the \verb|MESH|
data structure (compare Section \ref{S:mesh_data_structure}):
\idx{DOFs!entries in the \code{mesh} structure}
\bv\begin{lstlisting}
struct mesh
{
  ...
  DOF_ADMIN **dof_admin;
  int       n_dof_admin;

  int             n_dof_el;
  int             n_dof[N_NODE_TYPES];
  int             n_node_el;
  int             node[N_NODE_TYPES];
  ...
};
\end{lstlisting}\ev
The meaning of these entries is:
\begin{descr}
\kitem{dof\_admin}
 a vector of pointers to all \verb|DOF_ADMIN| structures for the mesh;
\kitem{n\_dof\_admin}
 number of all \verb|DOF_ADMIN| structures for the mesh;
\kitem{n\_dof\_el}
 total number of DOFs on one element from all \verb|DOF_ADMIN| structures;
\kitem{n\_dof}
 total number of \verb|VERTEX|, \verb|CENTER|, \verb|EDGE|, and \verb|FACE|
 DOFs from all \verb|DOF_ADMIN| structures;
\kitem{n\_node\_el}
 number of used nodes on each element (vertices, center, edges, and faces),
 this gives the dimension of \verb|el->dof|;
\kitem{node}
 The entry \verb|node[i]|, $\code{i}\in\{\verb|VERTEX|, \verb|CENTER|, 
 \verb|EDGE|, \verb|FACE|\}$ gives the index of the first \code{i}-node
 in \verb|el->dof|.
\end{descr}
All these variables must not be changed by a user routine -- they are set
during calls of the subroutine \verb|get_fe_space()| 
(compare Section \ref{S:access_fe_space}).

We denote the different locations of DOFs on an element by
\emph{nodes}.  As there are DOFs connected with different-dimensional
(sub-) simplices, there are \emph{vertex}, \emph{center}, \emph{edge}, 
and \emph{face} nodes. Using the macros from Section
\ref{S:mesh_constants}, there may be \verb|N_VERTICES(dim)| vertex nodes,
\verb|N_EDGES(dim)| edge nodes (2d or 3d), \verb|N_FACES(dim)| face nodes (in
3d), and one center node. Depending on the finite element spaces in
use, not all possible nodes must be associated with DOFs, but some
nodes may be associated with DOFs from several different finite
element spaces (and several \verb|DOF_ADMIN|s).  In order to minimize
the memory usage for pointers and DOF vectors, the elements store data
only for such nodes where DOFs are used. Each allocation of a finite 
element space forces \ALBERTA to adjust this information. For this
reason it is advisable to allocate finite element spaces before 
refining a mesh. The total number of nodes is
stored in \verb|mesh->n_node_el|, which will be the length of the
\verb|el->dof| vector for all elements.

In order to access the DOFs for one node, \verb|mesh->node[l]|
contains the index of the first \verb|l|-node in \verb|el->dof|,
where \verb|l| is either \verb|VERTEX|, \verb|CENTER|, \verb|EDGE|, 
or \verb|FACE| (compare Figure~\ref{F:mesh_node}).
So, a pointer to DOFs from the \verb|i|-th edge node
is stored at \verb|el->dof[mesh->node[EDGE]+i]| ($\code{0} \leq
\code{i} < \code{N\_EDGES}$), and these DOFs (and the vector
holding them) are shared by all elements meeting at this edge.

\begin{figure}[htbp]
\centerline{\includegraphics[width=0.8\hsize]{EPS/mesh_node}}
\caption[Local indexing of DOFs]{DOF vector indices in \code{el->dof}
  for DOFs at vertices, vertices and edges, vertices, edges and
  center, and vertices and center (in 2d). Corresponding
  \code{mesh->node} values are \{0,0,0,0\}, \{0,0,3,0\}, \{0,6,3,0\},
  and \{0,3,0,0\}. Note that the indices increase according to the
  sequence \code{VERTEX}/\code{EDGE}/\code{FACE}/\code{CENTER} for
  historical reasons.}
\label{F:mesh_node} \end{figure}

The total number of DOFs at an \verb|l|-node is available in
\verb|mesh->n_dof[l]|. This number is larger than zero, iff the node
is in use. All DOFs from different \verb|DOF_ADMIN|s are stored
together in one vector. In order to access DOFs from a given finite
element space (and its associated \verb|DOF_ADMIN|), the start index
for DOFs from this \verb|DOF_ADMIN| must be known. This start index is
generated during mesh initialization and stored in
\verb|admin->n0_dof[l]|. The number of DOFs from this \verb|DOF_ADMIN|
is given in \verb|admin->n_dof[l]|. Thus, a loop over all DOFs
associated with the \verb|i|-th edge node can be done by:
\bv\begin{lstlisting}
 DOF *dof_ptr = el->dof[mesh->node[EDGE]+i] + admin->n0_dof[EDGE];
 for (j = 0 ; j < admin->n_dof[EDGE]; j++)
 {
   dof = dof_ptr[j];
   ...
 }
\end{lstlisting}\ev

In order to simplify the access to DOFs for a finite element space on
an element, the \code{BAS\_FCTS} structure provides a routine
\idx{DOFs!get_dof_indices()@{\code{DOFs!get\_dof\_indices()}}}
\bv\begin{lstlisting}
  const DOF *(*get_dof_indices)(const EL *, const DOF_ADMIN *, DOF *);
\end{lstlisting}\ev
which returns a vector containing all global DOFs associated with
basis functions, in the correct order: the \code{k}-th DOF is
associated with the \code{k}-th local basis function (compare
\secref{S:basfct_data}).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{BLAS routines for DOF vectors and matrices}
\label{S:DOF_BLAS}

Several basic linear algebra subroutines (BLAS
\cite{LHKK:79,DDCHH:88}) are implemented for DOF vectors and DOF
matrices, see \tableref{T:BLAS}. Note that the table only lists the
functions for DOF-vectors and matrices storing scalar values.

Some non-standard routines are added: \verb|dof_xpay()|
is a variant of \verb|dof_axpy()|, \verb|dof_min()| and
\verb|dof_max()| calculate minimum and maximum values, and
\verb|dof_mv()| is a simplified version of the general
\verb|dof_gemv()| matrix-vector multiplication routine.
%%
The BLAS-2 routines \verb|dof_gemv()| and \verb|dof_mv()| accept a
\code{transpose} argument: \verb|transpose = NoTranspose = 0|
indicates the use of the original matrix, while
\verb|transpose = Transpose = 1| indicates that the transposed matrix
should be used. We use the \verb|C-BLAS| definition,
%%
\cdx{Transpose@{\code{Transpose}}}\cdx{NoTranspose@{\code{NoTranspose}}}%
\ddx{MatrixTranspose@{\code{MatrixTranspose}}}%
\bv\begin{lstlisting}[label=enum:MatrixTranspose]
typedef enum { NoTranspose, Transpose, ConjugateTranspose } MatrixTranspose;
\end{lstlisting}\ev
%%
The \code{mask} argument accepted by the matrix-vector routines is a
flag-vector: if specified, then the matrix operates only on those DOFs
$i$ with \code{mask[i] != DIRICHLET}, clearing all those DOFs in the
result to $0$, compare \secref{S:dirichlet_bound}.

Analogue routines exist for \code{DOF\_REAL\_D\_VEC} and
\code{DOF\_REAL\_VEC\_D} objects, with the convention to attach a
\code{\_d}- respectively a \code{\_dow}-suffix for the variants
dealing with \DOW-valued finite element functions, e.g. for the
\code{nrm2()}-function there exist the calls:
%%
\bv\begin{lstlisting}
REAL dof_nrm2(const DOF_REAL_VEC *arg);
REAL dof_nrm2_d(const DOF_REAL_D_VEC *arg);
REAL dof_nrm2_dow(const DOF_REAL_VEC_D *arg);
\end{lstlisting}\ev
%%
Additionally, the matrix-vector routines are available as versions
pairing vector- and scalar-valued DOF-vectors. Of course, the inner
block-type to the \code{DOF\_MATRIX} must match the requirements of
the arguments in this case. So to multiply a scalar finite element
function with a matrix, resulting in a vector-valued finite element function
there exist the variants
%%
\bv\begin{lstlisting}
void dof_mv_rdr(MatrixTranspose transpose,
		const DOF_MATRIX *a, const DOF_SCHAR_VEC *mask,
		const DOF_REAL_VEC *x, DOF_REAL_D_VEC *y);
void dof_mv_dow_scl(MatrixTranspose transpose,
		    const DOF_MATRIX *A, const DOF_SCHAR_VEC *mask,
		    const DOF_REAL_VEC *x, DOF_REAL_VEC_D *y);
\end{lstlisting}\ev

\begin{table}[htbp]
%%
\fdx{dof_nrm2()@{\code{dof\_nrm2()}}}%
\fdx{dof_asum()@{\code{dof\_asum()}}}%
\fdx{dof_min()@{\code{dof\_min()}}}%
\fdx{dof_max()@{\code{dof\_max()}}}%
\fdx{dof_set()@{\code{dof\_set()}}}%
\fdx{dof_scal()@{\code{dof\_scal()}}}%
\fdx{dof_dot()@{\code{dof\_dot()}}}%
\fdx{dof_copy()@{\code{dof\_copy()}}}%
\fdx{dof_axpy()@{\code{dof\_axpy()}}}%
\fdx{dof_xpay()@{\code{dof\_xpay()}}}%
\fdx{dof_gemv()@{\code{dof\_gemv()}}}%
\fdx{dof_mv()@{\code{dof\_mv()}}}%
%%
\fdx{dof_nrm2_d()@{\code{dof\_nrm2\_d()}}}%
\fdx{dof_asum_d()@{\code{dof\_asum\_d()}}}%
\fdx{dof_min_d()@{\code{dof\_min\_d()}}}%
\fdx{dof_max_d()@{\code{dof\_max\_d()}}}%
\fdx{dof_set_d()@{\code{dof\_set\_d()}}}%
\fdx{dof_scal_d()@{\code{dof\_scal\_d()}}}%
\fdx{dof_dot_d()@{\code{dof\_dot\_d()}}}%
\fdx{dof_copy_d()@{\code{dof\_copy\_d()}}}%
\fdx{dof_axpy_d()@{\code{dof\_axpy\_d()}}}%
\fdx{dof_xpay_d()@{\code{dof\_xpay\_d()}}}%
\fdx{dof_gemv_d()@{\code{dof\_gemv\_d()}}}%
\fdx{dof_gemv_rdr()@{\code{dof\_gemv\_rdr()}}}%
\fdx{dof_gemv_rrd()@{\code{dof\_gemv\_rrd()}}}%
\fdx{dof_mv_d()@{\code{dof\_mv\_d()}}}%
\fdx{dof_mv_rdr()@{\code{dof\_mv\_rdr()}}}%
\fdx{dof_mv_rrd()@{\code{dof\_mv\_rrd()}}}%
%%
\fdx{dof_nrm2_dow()@{\code{dof\_nrm2\_dow()}}}%
\fdx{dof_asum_dow()@{\code{dof\_asum\_dow()}}}%
\fdx{dof_min_dow()@{\code{dof\_min\_dow()}}}%
\fdx{dof_max_dow()@{\code{dof\_max\_dow()}}}%
\fdx{dof_set_dow()@{\code{dof\_set\_dow()}}}%
\fdx{dof_scal_dow()@{\code{dof\_scal\_dow()}}}%
\fdx{dof_dot_dow()@{\code{dof\_dot\_dow()}}}%
\fdx{dof_copy_dow()@{\code{dof\_copy\_dow()}}}%
\fdx{dof_axpy_dow()@{\code{dof\_axpy\_dow()}}}%
\fdx{dof_xpay_dow()@{\code{dof\_xpay\_dow()}}}%
\fdx{dof_gemv_dow()@{\code{dof\_gemv\_dow()}}}%
\fdx{dof_gemv_dow_scl()@{\code{dof\_gemv\_dow\_scl()}}}%
\fdx{dof_gemv_scl_dow()@{\code{dof\_gemv\_scl\_dow()}}}%
\fdx{dof_mv_dow()@{\code{dof\_mv\_dow()}}}%
\fdx{dof_mv_dow_scl()@{\code{dof\_mv\_dow\_scl()}}}%
\fdx{dof_mv_scl_dow()@{\code{dof\_mv\_scl\_dow()}}}%
%%
\begin{center}{\small
\begin{tabular}{|l|l|}
\hline
\Strut\verb|REAL dof_nrm2(const DOF_REAL_VEC *x)| & $ nrm2 = (\sum{X_i^2})^{1/2}$  \\
\hline
\Strut\verb|REAL dof_asum(const DOF_REAL_VEC *x)| & $ asum = \sum{|X_i|}$  \\
\hline
\Strut\verb|REAL dof_min(const DOF_REAL_VEC *x)| &  $ min = \min{X_i}$  \\
\hline
\Strut\verb|REAL dof_max(const DOF_REAL_VEC *x)| &  $ max = \max{X_i}$  \\
\hline
\Strut\verb|void dof_set(REAL alpha, DOF_REAL_VEC *x)|  & $X = (\alpha,\dots,\alpha)$  \\
\hline
\Strut\verb|void dof_scal(REAL alpha, DOF_REAL_VEC *x)| & $X = \alpha * X $  \\
\hline
\Strut\verb|REAL dof_dot(const DOF_REAL_VEC *x,| & $dot = \sum{X_i Y_i}$ \\
\Strut\verb|             const DOF_REAL_VEC *y)| & ~ \\
\hline
\Strut\verb|void dof_copy(const DOF_REAL_VEC *x, DOF_REAL_VEC *y)| &  $Y = X$  \\
\hline
\Strut\verb|void dof_axpy(REAL alpha,| & $Y = \alpha * X + Y$ \\
\Strut\verb|              const DOF_REAL_VEC *x, DOF_REAL_VEC *y)| & ~ \\
\hline
\Strut\verb|void dof_xpay(REAL alpha,| & $Y = X + \alpha * Y$ \\
\Strut\verb|              const DOF_REAL_VEC *x, DOF_REAL_VEC *y)| & ~ \\
\hline
\Strut\verb|void dof_gemv(MatrixTranspose transpose, REAL alpha,|
   & $Y_i = (\alpha*A*X + \beta*Y)_i $ \\
\Strut\verb|              const DOF_MATRIX *a,|
   & ~ or\\
\Strut\verb|              const DOF_SCHAR_VEC *mask,|
   & $Y_i = (\alpha*A^t*X + \beta*Y)_i$ \\
\Strut\verb|              const DOF_REAL_VEC *x,|
   & ~ if \code{mask != \nil} and \\
\Strut\verb|              REAL beta, DOF_REAL_VEC *y)|
   & \code{mask[i]!=DIRICHLET}\\
\hline
\Strut\verb|void dof_mv(MatrixTranspose transpose,|
   & $Y_i = (A*X)_i$ \\
\Strut\verb|            const DOF_MATRIX *a,|
  & ~ or \\
\Strut\verb|            const DOF_SCHAR_VEC *mask|
  & $Y_i = (A^t*X)_i$ \\
\Strut\verb|            const DOF_REAL_VEC *x, DOF_REAL_VEC *y)|
  & ~ if \code{mask != \nil} and \\
  & \code{mask[i]!=DIRICHLET}\\
\hline
\end{tabular}
}\end{center}
\caption[Implemented BLAS routines for DOF vectors and matrices]{Implemented BLAS routines for DOF vectors and matrices. Corresponding routines for \DOW-valued coefficient vectors are, of course, also available, see \secref{S:DOF_BLAS}}
\label{T:BLAS}
\end{table}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection{Reading and writing of meshes and vectors}%
\label{S:file_formats}

Section \ref{S:macro_tria} described the input and output of ASCII
files for macro triangulations. Locally refined triangulations
including the mesh hierarchy and corresponding DOFs are saved in
binary formats. Finite element data is saved (and restored) in binary
format, too, in order to keep the full data precision. As the binary
data and file format usually depends on hardware and operating
system, the interchange of data between different platforms needs a
machine independent format. The XDR\idx{XDR} (External Data Representation)
library provides a widely used interface for such a format. The
\verb|_xdr| routines should be used whenever data must be transfered
between different computer platforms.

\fdx{write_mesh()@{\code{write\_mesh()}}}%
\fdx{read_mesh()@{\code{read\_mesh()}}}%
\bv\begin{lstlisting}
int write_mesh(MESH *mesh, const char *name, REAL time);
MESH *read_mesh(const char *name, REAL *timeptr,
                NODE_PROJECTION *(*init_node_proj)(MESH *, MACRO_EL *, int),
                MESH *master);
\end{lstlisting}\ev

The routine \verb|write_mesh| stores information about the mesh in a
file named \verb|name|. Written data includes the corresponding
\verb|time| (only important for time dependent problems), macro
elements, mesh elements including the parent/child hierarchy
information, DOF administration and element DOFs.  The return value is
1 if an error occurs, otherwise 0. User defined leaf data (see
\secref{S:leaf_data_info}) is not written. If the mesh carries a
parametric structure defined by \code{use\_lagrange\_parametric()}
(see \secref{S:access_param_mesh}), then this structure will be dumped
to disk, read back by the corresponding \code{read\_mesh()} routines.
Geometric face-transformations attached to periodic meshes (compare
\secref{S:periodic}) will also be dumped to disk and restored by
\code{read\_mesh()}. If \code{mesh} is a co-dimension $1$ trace-mesh
of another master-mesh (see \secref{S:tracemesh_implementation}), then
this binding will also be dumped to disk, and can optionally be
restored by a call to \code{read\_mesh()}.

Routine \verb|read_mesh| reads a complete mesh from file \verb|name|,
which was created by \verb|write_mesh|. The corresponding time, if
any, is stored at \verb|timeptr|.  The argument \verb|init_node_proj|
is used in the same way as in \verb|GET_MESH()|, compare Sections
\ref{S:mesh_initialization} and \ref{S:node_projections}. If the
argument \code{master} is non-\nil, then \ALBERTA attempts to bind the
read-back mesh as a co-dimension $1$ trace-mesh to this
``master''-mesh, compare \secref{S:tracemesh_implementation}. This
will only work if \code{master} is just in the state it had when the
trace-mesh was dumped to disk, otherwise the behaviour is undefined
and the application supposedly will crash very quickly; a good example
which works is when both, master- and trace-mesh, are dumped to disk
and restored sequentially:
%%
\bv\begin{lstlisting}
exterrn MESH *master, *trace;

write_mesh(master, "master.mesh", HUGE_VAL);
write_mesh(trace, "trace.mesh", HUGE_VAL);

... /* other stuff, 1.000.000 lines of code later: */

master = read_mesh("master.mesh", NULL, NULL, NULL);
trace  = read_mesh("trace.mesh", NULL, NULL, master);
\end{lstlisting}\ev

\begin{compatibility}
  \code{read\_mesh()} is supposed to be able to read data generated by
  previous versions of \ALBERTA.
\end{compatibility}

For input and output of finite element data, the following routines are
provided which read or write files containing binary DOF vectors:

\fdx{read_dof_real_vec()@{\code{read\_dof\_real\_vec()}}}%
\fdx{read_dof_real_d_vec()@{\code{read\_dof\_real\_d\_vec()}}}%
\fdx{read_dof_real_vec_d()@{\code{read\_dof\_real\_vec\_d()}}}%
\fdx{read_dof_int_vec()@{\code{read\_dof\_int\_vec()}}}%
\fdx{read_dof_schar_vec()@{\code{read\_dof\_schar\_vec()}}}%
\fdx{read_dof_uchar_vec()@{\code{read\_dof\_uchar\_vec()}}}%
\fdx{write_dof_real_vec()@{\code{write\_dof\_real\_vec()}}}%
\fdx{write_dof_real_d_vec()@{\code{write\_dof\_real\_d\_vec()}}}%
\fdx{write_dof_real_vec_d()@{\code{write\_dof\_real\_vec\_d()}}}%
\fdx{write_dof_int_vec()@{\code{write\_dof\_int\_vec()}}}%
\fdx{write_dof_schar_vec()@{\code{write\_dof\_schar\_vec()}}}%
\fdx{write_dof_uchar_vec()@{\code{write\_dof\_uchar\_vec()}}}%
\bv\begin{lstlisting}
int write_dof_int_vec(const DOF_INT_VEC *div, const char *name); 
int write_dof_real_vec(const DOF_REAL_VEC *drv, const char *name);
int write_dof_real_d_vec(const DOF_REAL_D_VEC *drdv, const char *name); 
int write_dof_real_vec_d(const DOF_REAL_VEC_D *drvd, const char *name); 
int write_dof_schar_vec(const DOF_SCHAR_VEC *dsv, const char *name); 
int write_dof_uchar_vec(const DOF_UCHAR_VEC *duv, const char *name);

DOF_INT_VEC    *read_dof_int_vec(const char *name, MESH *, FE_SPACE*); 
DOF_REAL_VEC   *read_dof_real_vec(const char *name, MESH *, FE_SPACE *); 
DOF_REAL_D_VEC *read_dof_real_d_vec(const char *name, MESH *, FE_SPACE *); 
DOF_REAL_VEC_D *read_dof_real_vec_d(const char *name, MESH *, FE_SPACE *); 
DOF_SCHAR_VEC  *read_dof_schar_vec(const char *name, MESH *, FE_SPACE *); 
DOF_UCHAR_VEC  *read_dof_uchar_vec(const char *name, MESH *, FE_SPACE *); 
\end{lstlisting}\ev

For the output and input of machine independent data files, similar
routines are provided. The XDR library is used, and all routine
names end with \verb|_xdr|:

\fdx{write_mesh_xdr()@{\code{write\_mesh\_xdr()}}}%
\fdx{read_mesh_xdr()@{\code{read\_mesh\_xdr()}}}%
\bv\begin{lstlisting}
int write_mesh_xdr(MESH *mesh, const char *name, REAL time);

MESH *read_mesh_xdr(const char *name, REAL *timeptr,
                    NODE_PROJECTION *(*init_node_proj)(MESH *,MACRO_EL *,int));
\end{lstlisting}\ev

\fdx{read_dof_real_vec_xdr()@{\code{read\_dof\_real\_vec\_xdr()}}}%
\fdx{read_dof_real_d_vec_xdr()@{\code{read\_dof\_real\_d\_vec\_xdr()}}}%
\fdx{read_dof_real_vec_d_xdr()@{\code{read\_dof\_real\_vec\_xdr\_d()}}}%
\fdx{read_dof_int_vec_xdr()@{\code{read\_dof\_int\_vec\_xdr()}}}%
\fdx{read_dof_schar_vec_xdr()@{\code{read\_dof\_schar\_vec\_xdr()}}}%
\fdx{read_dof_uchar_vec_xdr()@{\code{read\_dof\_uchar\_vec\_xdr()}}}%
\fdx{write_dof_real_vec_xdr()@{\code{write\_dof\_real\_vec\_xdr()}}}%
\fdx{write_dof_real_d_vec_xdr()@{\code{write\_dof\_real\_d\_vec\_xdr()}}}%
\fdx{write_dof_real_vec_d_xdr()@{\code{write\_dof\_real\_vec\_d\_xdr()}}}%
\fdx{write_dof_int_vec_xdr()@{\code{write\_dof\_int\_vec\_xdr()}}}%
\fdx{write_dof_schar_vec_xdr()@{\code{write\_dof\_schar\_vec\_xdr()}}}%
\fdx{write_dof_uchar_vec_xdr()@{\code{write\_dof\_uchar\_vec\_xdr()}}}%
\bv\begin{lstlisting}
int write_dof_int_vec_xdr(const DOF_INT_VEC *div, const char *name); 
int write_dof_real_vec_xdr(const DOF_REAL_VEC *drv, const char *name);i
int write_dof_real_d_vec_xdr(const DOF_REAL_D_VEC *drdv, const char *name); 
int write_dof_real_vec_d_xdr(const DOF_REAL_VEC_D *drvd, const char *name); 
int write_dof_schar_vec_xdr(const DOF_SCHAR_VEC *dsv, const char *name); 
int write_dof_uchar_vec_xdr(const DOF_UCHAR_VEC *duv, const char *name);

DOF_INT_VEC    *read_dof_int_vec_xdr(const char *name, MESH *, FE_SPACE*); 
DOF_REAL_VEC   *read_dof_real_vec_xdr(const char *name, MESH *, FE_SPACE *); 
DOF_REAL_D_VEC *read_dof_real_d_vec_xdr(const char *name, MESH *, FE_SPACE *); 
DOF_REAL_VEC_D *read_dof_real_vec_d_xdr(const char *name, MESH *, FE_SPACE *); 
DOF_SCHAR_VEC  *read_dof_schar_vec_xdr(const char *name, MESH *, FE_SPACE *); 
DOF_UCHAR_VEC  *read_dof_uchar_vec_xdr(const char *name, MESH *, FE_SPACE *); 
\end{lstlisting}\ev

All flavours of the IO-routines come also with a version which accepts
a \code{stdio-FILE} pointer as argument. These routines are pre-fixed
by the letter ``\code{f}'', in the spirit of \code{fprintf(3)}. For
example, the corresponding proto-type for the
\code{write\_mesh\_xdr()} function is
%%
\fdx{fwrite_mesh()@{\code{fwrite\_mesh()}}}%
\fdx{fread_mesh()@{\code{fread\_mesh()}}}%
\fdx{fread_dof_real_vec()@{\code{fread\_dof\_real\_vec()}}}%
\fdx{fread_dof_real_d_vec()@{\code{fread\_dof\_real\_d\_vec()}}}%
\fdx{fread_dof_real_vec_d()@{\code{fread\_dof\_real\_vec\_d()}}}%
\fdx{fread_dof_int_vec()@{\code{fread\_dof\_int\_vec()}}}%
\fdx{fread_dof_schar_vec()@{\code{fread\_dof\_schar\_vec()}}}%
\fdx{fread_dof_uchar_vec()@{\code{fread\_dof\_uchar\_vec()}}}%
\fdx{fwrite_dof_real_vec()@{\code{fwrite\_dof\_real\_vec()}}}%
\fdx{fwrite_dof_real_d_vec()@{\code{fwrite\_dof\_real\_d\_vec()}}}%
\fdx{fwrite_dof_real_vec_d()@{\code{fwrite\_dof\_real\_vec\_d()}}}%
\fdx{fwrite_dof_int_vec()@{\code{fwrite\_dof\_int\_vec()}}}%
\fdx{fwrite_dof_schar_vec()@{\code{fwrite\_dof\_schar\_vec()}}}%
\fdx{fwrite_dof_uchar_vec()@{\code{fwrite\_dof\_uchar\_vec()}}}%
\fdx{fread_dof_real_vec_xdr()@{\code{fread\_dof\_real\_vec\_xdr()}}}%
\fdx{fread_dof_real_d_vec_xdr()@{\code{fread\_dof\_real\_d\_vec\_xdr()}}}%
\fdx{fread_dof_real_vec_d_xdr()@{\code{fread\_dof\_real\_vec\_xdr\_d()}}}%
\fdx{fread_dof_int_vec_xdr()@{\code{fread\_dof\_int\_vec\_xdr()}}}%
\fdx{fread_dof_schar_vec_xdr()@{\code{fread\_dof\_schar\_vec\_xdr()}}}%
\fdx{fread_dof_uchar_vec_xdr()@{\code{fread\_dof\_uchar\_vec\_xdr()}}}%
\fdx{fwrite_dof_real_vec_xdr()@{\code{fwrite\_dof\_real\_vec\_xdr()}}}%
\fdx{fwrite_dof_real_d_vec_xdr()@{\code{fwrite\_dof\_real\_d\_vec\_xdr()}}}%
\fdx{fwrite_dof_real_vec_d_xdr()@{\code{fwrite\_dof\_real\_vec\_d\_xdr()}}}%
\fdx{fwrite_dof_int_vec_xdr()@{\code{fwrite\_dof\_int\_vec\_xdr()}}}%
\fdx{fwrite_dof_schar_vec_xdr()@{\code{fwrite\_dof\_schar\_vec\_xdr()}}}%
\fdx{fwrite_dof_uchar_vec_xdr()@{\code{fwrite\_dof\_uchar\_vec\_xdr()}}}%
\bv\begin{lstlisting}
bool fwrite_mesh_xdr(MESH *mesh, FILE *fp, REAL time);
\end{lstlisting}\ev
%%
Likewise for all other functions: just replace the file-name argument
by the file-pointer argument. Intentionally, this feature has been
introduced to let the IO-routines act on streaming data. Note that the
compatibility mode of \code{read\_mesh()} with respect to meshes
generated by \ALBERTA-1.2 will not work if the actual file underlying
the file-pointer does not allow for random access (e.g. if it is a
pipe or socket).

\idx{DOFs!implementation|)}

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