<commit_before>/*----------------------------   fe.h     ---------------------------*/
/*      $Id$                 */
/*      Copyright <NAME>, University of Heidelberg, 1998 */
#ifndef __fe_H
#define __fe_H
/*----------------------------   fe.h     ---------------------------*/

#include <base/exceptions.h>
#include <base/subscriptor.h>
#include <base/point.h>
#include <base/tensor.h>
#include <grid/dof.h>
#include <grid/geometry_info.h>
#include <lac/dfmatrix.h>



template <int dim> class Boundary;
template <int dim> struct FiniteElementData;



/**
 * Dimension dependent data for finite elements. See the #FiniteElementBase#
 * class for more information.
 */
struct FiniteElementData<1> {
				     /**
				      * Number of degrees of freedom on
				      * a vertex.
				      */
    const unsigned int dofs_per_vertex;

				     /** Number of degrees of freedom
				      *  on a line.
				      */
    const unsigned int dofs_per_line;

				     /**
				      * Number of degrees of freedom on a
				      * face. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int dofs_per_face;
    
				     /**
				      * Total number of degrees of freedom
				      * on a cell. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int total_dofs;

				     /**
				      * Number of basis functions used for the
				      * transformation from unit cell to real
				      * cell. For a linear mapping, this number
				      * equals the number of vertices.
				      */
    const unsigned int n_transform_functions;
    
    				     /**
				      * Default constructor. Constructs an element
				      * which is not so useful. Checking
				      * #total_dofs# is therefore a good way to
				      * check if something went wrong.
				      */
    FiniteElementData ();

				     /**
				      * A more useful version to construct
				      * an object of this type.
				      */
    FiniteElementData (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int n_transform_functions) :
		    dofs_per_vertex(dofs_per_vertex),
		    dofs_per_line(dofs_per_line),
		    dofs_per_face(dofs_per_vertex),
		    total_dofs (2*dofs_per_vertex+dofs_per_line),
		    n_transform_functions(n_transform_functions) {};

				     /**
				      * Comparison operator. It is not clear to
				      * me why we have to declare and implement
				      * this one explicitely.
				      */
    bool operator == (const FiniteElementData<1> &) const;

				     /**
				      * Exception
				      */
    DeclException0 (ExcInternalError);
};




/**
 * Dimension dependent data for finite elements. See the #FiniteElementBase#
 * class for more information.
 */
struct FiniteElementData<2> {
				     /**
				      * Number of degrees of freedom on
				      * a vertex.
				      */
    const unsigned int dofs_per_vertex;

				     /** Number of degrees of freedom
				      *  on a line.
				      */
    const unsigned int dofs_per_line;

				     /** Number of degrees of freedom
				      *  on a quad.
				      */
    const unsigned int dofs_per_quad;

				     /**
				      * Number of degrees of freedom on a
				      * face. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int dofs_per_face;
    
				     /**
				      * Total number of degrees of freedom
				      * on a cell. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int total_dofs;

				     /**
				      * Number of basis functions used for the
				      * transformation from unit cell to real
				      * cell. For a linear mapping, this number
				      * equals the number of vertices.
				      */
    const unsigned int n_transform_functions;

    				     /**
				      * Default constructor. Constructs an element
				      * which is not so useful. Checking
				      * #total_dofs# is therefore a good way to
				      * check if something went wrong.
				      */
    FiniteElementData ();

				     /**
				      * A more useful version to construct
				      * an object of this type.
				      */
    FiniteElementData (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int dofs_per_quad,
		       const unsigned int n_transform_functions) :
		    dofs_per_vertex(dofs_per_vertex),
		    dofs_per_line(dofs_per_line),
		    dofs_per_quad(dofs_per_quad),
		    dofs_per_face(2*dofs_per_vertex+
				  dofs_per_line),
		    total_dofs (4*dofs_per_vertex+
				4*dofs_per_line+
				dofs_per_quad),
		    n_transform_functions (n_transform_functions) {};

				     /**
				      * Comparison operator. It is not clear to
				      * me why we have to declare and implement
				      * this one explicitely.
				      */
    bool operator == (const FiniteElementData<2> &) const;

				     /**
				      * Exception
				      */
    DeclException0 (ExcInternalError);
};

    



/**
 * Base class for finite elements in arbitrary dimensions. This class provides
 * several fields which describe a specific finite element and which are filled
 * by derived classes. It more or less only offers the fields and access
 * functions which makes it possible to copy finite elements without knowledge
 * of the actual type (linear, quadratic, etc).
 *
 * The implementation of this base class is split into two parts: those fields
 * which are not common to all dimensions (#dofs_per_quad# for example are only
 * useful for #dim>=2#) are put into the #FiniteElementData<dim># class which
 * is explicitely specialized for all used dimensions, while those fields which
 * may be formulated in a dimension-independent way are put into the present
 * class.
 *
 * The different matrices are initialized with the correct size, such that in
 * the derived (concrete) finite element classes, their entries must only be
 * filled in; no resizing is needed.
 *
 * @author <NAME>, 1998
 */
template <int dim>
struct FiniteElementBase :
  public Subscriptor,
  public FiniteElementData<dim>

{
  public:
				     /**
				      * Construct an object of this type.
				      * You have to set the
				      * matrices explicitely after calling
				      * this base class' constructor. For
				      * #dim==1#, #dofs_per_quad# must be
				      * zero.
				      */
    FiniteElementBase (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int dofs_per_quad,
		       const unsigned int n_transform_functions);
    
				     /**
				      * Return a readonly reference to the
				      * matrix which describes the transfer of a
				      * child with the given number to the
				      * mother cell. See the #restriction# array
				      * for more information.
				      */
    const dFMatrix & restrict (const unsigned int child) const;

				     /**
				      * Return a readonly reference to the
				      * matrix which describes the transfer of a
				      * mother cell to the child with the given
				      * number.
				      */
    const dFMatrix & prolongate (const unsigned int child) const;

				     /**
				      * Return a readonly reference to the
				      * matrix which describes the constraints
				      * at the interface between a refined and
				      * an unrefined cell.
				      *
				      * The matrix is obviously empty in only
				      * one space dimension, since there are no
				      * constraints then.
				      */
    const dFMatrix & constraints () const;

				     /**
				      * Comparison operator. We also check for
				      * equality of the constraint matrix,
				      * which is quite an expensive operation.
				      * Do therefore
				      * use this function with care, if possible
				      * only for debugging purposes.
				      *
				      * Since this function is not that important,
				      * we avoid an implementational question
				      * about comparing arrays and do not compare
				      * the matrix arrays #restriction# and
				      * #prolongation#.
				      */
    bool operator == (const FiniteElementBase<dim> &) const;

				     /**
				      * Exception
				      */
    DeclException1 (ExcInvalidIndex,
		    int,
		    << "Invalid index " << arg1);
				     /**
				      * Exception
				      */
    DeclException2 (ExcWrongFieldDimension,
		    int, int,
		    << "The field has not the assumed dimension " << arg2
		    << ", but has " << arg1 << " elements.");
    DeclException2 (ExcWrongInterfaceMatrixSize,
		    int, int,
		    << "The interface matrix has a size of " << arg1
		    << "x" << arg2
		    << ", which is not reasonable in the present dimension.");
    
  protected:
				     /**
				      * Have #N=2^dim# matrices keeping the
				      * restriction constants for the transfer
				      * of the #i#th child to the mother cell.
				      * The numbering conventions for the
				      * degree of freedom indices are descibed
				      * in the derived classes.
				      * In this matrix, the row indices belong
				      * to the destination cell, i.e. the
				      * unrefined one, while the column indices
				      * are for the refined cell's degrees of
				      * freedom. The application of this matrix
				      * is therefore usually its being
				      * multiplied by the vector of nodal values
				      * on the child.
				      *
				      * In essence, using the matrices from the
				      * children to the mother cell amounts to
				      * computing the interpolation of the
				      * function on the refined to the coarse
				      * mesh. To get the vector of nodal values
				      * of the interpolant on the mother cell,
				      * you have to multiply the nodal value
				      * vectors of each of the child cell with
				      * the respective restriction matrix and
				      * clobber these contributions together.
				      * However, you must take care not to
				      * #add# these together, since nodes which
				      * belong to more than one child would then
				      * be counted more than once; rather, you
				      * have to overwrite the nonzero
				      * contributions of each child into the
				      * nodal value vector of the mother cell.
				      *
				      * While we could avoid this and rather add
				      * up the contributions of each child for
				      * nodes that are interior of the mother
				      * cell, we can't for nodes on the boundary
				      * of the mother cell. The reason for this
				      * is that we know how many children may
				      * contribute to the interpolated nodal
				      * value of an interior degree of freedom.
				      * However, we don't know for dofs on the
				      * boundary, for which we only know how many
				      * children from each side of the face
				      * contribute, but we would have to look out
				      * of the cell to know how many neighbors
				      * there are and then, still, we would have
				      * to have two different interpolation
				      * routines for local interpolation and for
				      * the contribution of a cell to a global
				      * interpolation if we wanted to compute
				      * that by adding up local contributions.
				      *
				      * Because of this problem, we chose to
				      * write rather than add the contributions
				      * of each cell to the interpolation onto
				      * the mother cell. However, there now is
				      * another problem which appears when using
				      * discontinuous finite elements. The
				      * process of 'writing' assumed that we
				      * get the same result for each degree of
				      * freedom from each of the children, such
				      * that 'over'writing would not destroy
				      * information; when using discontinuous
				      * elements, this assumption is violated.
				      *
				      * SOLUTION? NOT YET MADE UP!
				      *
				      * To compute the interpolation of a
				      * finite element field to a cell, you
				      * may use the #get_interpolated_dof_values#
				      * function of the #DoFCellAccessor# class.
				      * See there for more information.
				      *
				      * Upon assembling the transfer matrix
				      * between cells using this matrix array,
				      * zero elements in the restriction
				      * matrix are discarded and will not fill
				      * up the transfer matrix.
				      */
    dFMatrix restriction[GeometryInfo<dim>::children_per_cell];

    				     /**
				      * Have #N=2^dim# matrices keeping the
				      * prolongation constants for the transfer
				      * of the mother cell to the #i#th child.
				      * The numbering conventions for the
				      * degree of freedom indices are descibed
				      * in the derived classes.
				      * In this matrix, the row indices belong
				      * to the destination cell, i.e. the
				      * refined one, while the column indices
				      * are for the unrefined cell's degrees of
				      * freedom. Thus, if #u0# is the vector<commit_msg>Doc update.<commit_after>/*----------------------------   fe.h     ---------------------------*/
/*      $Id$                 */
/*      Copyright <NAME>, University of Heidelberg, 1998 */
#ifndef __fe_H
#define __fe_H
/*----------------------------   fe.h     ---------------------------*/

#include <base/exceptions.h>
#include <base/subscriptor.h>
#include <base/point.h>
#include <base/tensor.h>
#include <grid/dof.h>
#include <grid/geometry_info.h>
#include <lac/dfmatrix.h>



template <int dim> class Boundary;
template <int dim> struct FiniteElementData;



/**
 * Dimension dependent data for finite elements. See the #FiniteElementBase#
 * class for more information.
 */
struct FiniteElementData<1> {
				     /**
				      * Number of degrees of freedom on
				      * a vertex.
				      */
    const unsigned int dofs_per_vertex;

				     /** Number of degrees of freedom
				      *  on a line.
				      */
    const unsigned int dofs_per_line;

				     /**
				      * Number of degrees of freedom on a
				      * face. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int dofs_per_face;
    
				     /**
				      * Total number of degrees of freedom
				      * on a cell. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int total_dofs;

				     /**
				      * Number of basis functions used for the
				      * transformation from unit cell to real
				      * cell. For a linear mapping, this number
				      * equals the number of vertices.
				      */
    const unsigned int n_transform_functions;
    
    				     /**
				      * Default constructor. Constructs an element
				      * which is not so useful. Checking
				      * #total_dofs# is therefore a good way to
				      * check if something went wrong.
				      */
    FiniteElementData ();

				     /**
				      * A more useful version to construct
				      * an object of this type.
				      */
    FiniteElementData (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int n_transform_functions) :
		    dofs_per_vertex(dofs_per_vertex),
		    dofs_per_line(dofs_per_line),
		    dofs_per_face(dofs_per_vertex),
		    total_dofs (2*dofs_per_vertex+dofs_per_line),
		    n_transform_functions(n_transform_functions) {};

				     /**
				      * Comparison operator. It is not clear to
				      * me why we have to declare and implement
				      * this one explicitely.
				      */
    bool operator == (const FiniteElementData<1> &) const;

				     /**
				      * Exception
				      */
    DeclException0 (ExcInternalError);
};




/**
 * Dimension dependent data for finite elements. See the #FiniteElementBase#
 * class for more information.
 */
struct FiniteElementData<2> {
				     /**
				      * Number of degrees of freedom on
				      * a vertex.
				      */
    const unsigned int dofs_per_vertex;

				     /** Number of degrees of freedom
				      *  on a line.
				      */
    const unsigned int dofs_per_line;

				     /** Number of degrees of freedom
				      *  on a quad.
				      */
    const unsigned int dofs_per_quad;

				     /**
				      * Number of degrees of freedom on a
				      * face. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int dofs_per_face;
    
				     /**
				      * Total number of degrees of freedom
				      * on a cell. This information is
				      * redundant to some fields in the
				      * derived classes but makes
				      * writing dimension independant
				      * programs easier.
				      */
    const unsigned int total_dofs;

				     /**
				      * Number of basis functions used for the
				      * transformation from unit cell to real
				      * cell. For a linear mapping, this number
				      * equals the number of vertices.
				      */
    const unsigned int n_transform_functions;

    				     /**
				      * Default constructor. Constructs an element
				      * which is not so useful. Checking
				      * #total_dofs# is therefore a good way to
				      * check if something went wrong.
				      */
    FiniteElementData ();

				     /**
				      * A more useful version to construct
				      * an object of this type.
				      */
    FiniteElementData (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int dofs_per_quad,
		       const unsigned int n_transform_functions) :
		    dofs_per_vertex(dofs_per_vertex),
		    dofs_per_line(dofs_per_line),
		    dofs_per_quad(dofs_per_quad),
		    dofs_per_face(2*dofs_per_vertex+
				  dofs_per_line),
		    total_dofs (4*dofs_per_vertex+
				4*dofs_per_line+
				dofs_per_quad),
		    n_transform_functions (n_transform_functions) {};

				     /**
				      * Comparison operator. It is not clear to
				      * me why we have to declare and implement
				      * this one explicitely.
				      */
    bool operator == (const FiniteElementData<2> &) const;

				     /**
				      * Exception
				      */
    DeclException0 (ExcInternalError);
};

    



/**
 * Base class for finite elements in arbitrary dimensions. This class provides
 * several fields which describe a specific finite element and which are filled
 * by derived classes. It more or less only offers the fields and access
 * functions which makes it possible to copy finite elements without knowledge
 * of the actual type (linear, quadratic, etc).
 *
 * The implementation of this base class is split into two parts: those fields
 * which are not common to all dimensions (#dofs_per_quad# for example are only
 * useful for #dim>=2#) are put into the #FiniteElementData<dim># class which
 * is explicitely specialized for all used dimensions, while those fields which
 * may be formulated in a dimension-independent way are put into the present
 * class.
 *
 * The different matrices are initialized with the correct size, such that in
 * the derived (concrete) finite element classes, their entries must only be
 * filled in; no resizing is needed.
 *
 * @author <NAME>, 1998
 */
template <int dim>
struct FiniteElementBase :
  public Subscriptor,
  public FiniteElementData<dim>

{
  public:
				     /**
				      * Construct an object of this type.
				      * You have to set the
				      * matrices explicitely after calling
				      * this base class' constructor. For
				      * #dim==1#, #dofs_per_quad# must be
				      * zero.
				      */
    FiniteElementBase (const unsigned int dofs_per_vertex,
		       const unsigned int dofs_per_line,
		       const unsigned int dofs_per_quad,
		       const unsigned int n_transform_functions);
    
				     /**
				      * Return a readonly reference to the
				      * matrix which describes the transfer of a
				      * child with the given number to the
				      * mother cell. See the #restriction# array
				      * for more information.
				      */
    const dFMatrix & restrict (const unsigned int child) const;

				     /**
				      * Return a readonly reference to the
				      * matrix which describes the transfer of a
				      * mother cell to the child with the given
				      * number.
				      */
    const dFMatrix & prolongate (const unsigned int child) const;

				     /**
				      * Return a readonly reference to the
				      * matrix which describes the constraints
				      * at the interface between a refined and
				      * an unrefined cell.
				      *
				      * The matrix is obviously empty in only
				      * one space dimension, since there are no
				      * constraints then.
				      */
    const dFMatrix & constraints () const;

				     /**
				      * Comparison operator. We also check for
				      * equality of the constraint matrix,
				      * which is quite an expensive operation.
				      * Do therefore
				      * use this function with care, if possible
				      * only for debugging purposes.
				      *
				      * Since this function is not that important,
				      * we avoid an implementational question
				      * about comparing arrays and do not compare
				      * the matrix arrays #restriction# and
				      * #prolongation#.
				      */
    bool operator == (const FiniteElementBase<dim> &) const;

				     /**
				      * Exception
				      */
    DeclException1 (ExcInvalidIndex,
		    int,
		    << "Invalid index " << arg1);
				     /**
				      * Exception
				      */
    DeclException2 (ExcWrongFieldDimension,
		    int, int,
		    << "The field has not the assumed dimension " << arg2
		    << ", but has " << arg1 << " elements.");
    DeclException2 (ExcWrongInterfaceMatrixSize,
		    int, int,
		    << "The interface matrix has a size of " << arg1
		    << "x" << arg2
		    << ", which is not reasonable in the present dimension.");
    
  protected:
				     /**
				      * Have #N=2^dim# matrices keeping the
				      * restriction constants for the transfer
				      * of the #i#th child to the mother cell.
				      * The numbering conventions for the
				      * degree of freedom indices are descibed
				      * in the derived classes.
				      * In this matrix, the row indices belong
				      * to the destination cell, i.e. the
				      * unrefined one, while the column indices
				      * are for the refined cell's degrees of
				      * freedom. The application of this matrix
				      * is therefore usually its being
				      * multiplied by the vector of nodal values
				      * on the child.
				      *
				      * In essence, using the matrices from the
				      * children to the mother cell amounts to
				      * computing the interpolation of the
				      * function on the refined to the coarse
				      * mesh. To get the vector of nodal values
				      * of the interpolant on the mother cell,
				      * you have to multiply the nodal value
				      * vectors of each of the child cell with
				      * the respective restriction matrix and
				      * clobber these contributions together.
				      * However, you must take care not to
				      * #add# these together, since nodes which
				      * belong to more than one child would then
				      * be counted more than once; rather, you
				      * have to overwrite the nonzero
				      * contributions of each child into the
				      * nodal value vector of the mother cell.
				      *
				      * While we could avoid this and rather add
				      * up the contributions of each child for
				      * nodes that are interior of the mother
				      * cell, we can't for nodes on the boundary
				      * of the mother cell. The reason for this
				      * is that we know how many children may
				      * contribute to the interpolated nodal
				      * value of an interior degree of freedom.
				      * However, we don't know for dofs on the
				      * boundary, for which we only know how many
				      * children from each side of the face
				      * contribute, but we would have to look out
				      * of the cell to know how many neighbors
				      * there are and then, still, we would have
				      * to have two different interpolation
				      * routines for local interpolation and for
				      * the contribution of a cell to a global
				      * interpolation if we wanted to compute
				      * that by adding up local contributions.
				      *
				      * Because of this problem, we chose to
				      * write rather than add the contributions
				      * of each cell to the interpolation onto
				      * the mother cell. However, there now is
				      * another problem which appears when using
				      * discontinuous finite elements. The
				      * process of 'writing' assumed that we
				      * get the same result for each degree of
				      * freedom from each of the children, such
				      * that 'over'writing would not destroy
				      * information; when using discontinuous
				      * elements, this assumption is violated.
				      *
				      * One way to get the whole thing working
				      * nonetheless would be to use a flag which
				      * tells us when the 'write' and when to
				      * 'add'. Adding is possible when we have
				      * only interior degrees of freedom, i.e.
				      * dofs that are not shared between cells.
				      * This is certainly the way to go for the
				      * DG(r) elements. However, this scheme
				      * does not work for discontinuous elements
				      * with degrees of freedom on the faces,
				      * such as the rotated bilinear
				      * (Rannacher-Turek) element or elements
				      * like the Crouzeix-Raviart one. The latter
				      * have degrees of freedom on the faces,
				      * e.g. mean values on a face, and these
				      * values are the same from both sides of
				      * the face, but the solutions are
				      * discontinuous there nevertheless, such
				      * that interpolation is not possible here.
				      *
				      * FINAL SOLUTION? NOT YET MADE UP!
				      *
				      * To compute the interpolation of a
				      * finite element field to a cell, you
				      * may use the #get_interpolated_dof_values#
				      * function of the #DoFCellAccessor# class.
				      * See there for more information.
				      *
				      * Upon assembling the transfer matrix
				      * between cells using this matrix array,
				      * zero elements in the restriction
				      * matrix are discarded and will not fill
				      * up the transfer matrix.
				      */
    dFMatrix restriction[GeometryInfo<dim>::children_per_cell];

    				     /**
				      * Have #N=2^dim# matrices keeping the
				      * prolongation constants for the transfer
				      * of the mother cell to the #i#th child.
				      * The numbering conventions for the
				      * degree of freedom indices are descibed
				      * in the derived classes.
				      * In this matrix, the row indices belong
				      * to the destination cell, i.e. the
				      * refined one, while the column indices
				      * are for the unrefined cell's degrees of
				      * freedom. Thus, if #u0# is the vector
{'fraction_non_alphanumeric': 0.0681720890410959, 'fraction_numerical': 0.00221175799086758, 'mean_word_length': 1.7849195310947745, 'pattern_counts': {'":': 0, '<': 91, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '947883', 'n_tokens_mistral': 9046, 'n_tokens_neox': 6711, 'n_words': 2956}