]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Rename fe_base.h to fe_data.h 13908/head
authorPeter Munch <peterrmuench@gmail.com>
Sun, 5 Jun 2022 21:59:00 +0000 (23:59 +0200)
committerPeter Munch <peterrmuench@gmail.com>
Sun, 5 Jun 2022 22:01:48 +0000 (00:01 +0200)
include/deal.II/fe/fe.h
include/deal.II/fe/fe_base.h
include/deal.II/fe/fe_data.h [new file with mode: 0644]
include/deal.II/fe/fe_rannacher_turek.h
tests/bits/anna_1.cc
tests/bits/anna_2.cc
tests/bits/anna_3.cc
tests/fe/fe_conformity_test.h

index 3bd303c1f5d70f3bf856ea103a57475052ff7c33..9af212e80aa70b8d3dcdd0eb044e0cae458bbcff 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <deal.II/fe/block_mask.h>
 #include <deal.II/fe/component_mask.h>
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_update_flags.h>
 #include <deal.II/fe/fe_values_extractors.h>
 #include <deal.II/fe/mapping.h>
index 519f2045ef6c89a67a158c88a7f1aafa2581e82e..662d4012bb768e2ecc15cc8ebd8f38bc352a8c14 100644 (file)
 
 #include <deal.II/base/config.h>
 
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/grid/reference_cell.h>
-
-#include <deal.II/lac/block_indices.h>
-
-#include <vector>
-
-DEAL_II_NAMESPACE_OPEN
-
-// Forward declarations:
-#ifndef DOXYGEN
-template <int dim>
-class FiniteElementData;
-#endif
-
-/**
- * A namespace solely for the purpose of defining the Domination enum as well
- * as associated operators.
- */
-namespace FiniteElementDomination
-{
-  /**
-   * An enum that describes the outcome of comparing two elements for mutual
-   * domination. If one element dominates another, then the restriction of the
-   * space described by the dominated element to a face of the cell is
-   * strictly larger than that of the dominating element. For example, in 2-d
-   * Q(2) elements dominate Q(4) elements, because the traces of Q(4) elements
-   * are quartic polynomials which is a space strictly larger than the
-   * quadratic polynomials (the restriction of the Q(2) element). Similar
-   * reasonings apply for vertices and cells as well. In general, Q(k) dominates
-   * Q(k') if $k\le k'$.
-   *
-   * This enum is used in the FiniteElement::compare_for_domination() function
-   * that is used in the context of hp-finite element methods when determining
-   * what to do at faces where two different finite elements meet (see the
-   * @ref hp_paper "hp-paper"
-   * for a more detailed description of the following). In that case, the
-   * degrees of freedom of one side need to be constrained to those on the
-   * other side. The determination which side is which is based on the outcome
-   * of a comparison for mutual domination: the dominated side is constrained
-   * to the dominating one.
-   *
-   * Note that there are situations where neither side dominates. The
-   * @ref hp_paper "hp-paper"
-   * lists two case, with the simpler one being that a $Q_2\times Q_1$ vector-
-   * valued element (i.e. a <code>FESystem(FE_Q(2),1,FE_Q(1),1)</code>) meets
-   * a $Q_1\times Q_2$ element: here, for each of the two vector-components,
-   * we can define a domination relationship, but it is different for the two
-   * components.
-   *
-   * It is clear that the concept of domination doesn't matter for
-   * discontinuous elements. However, discontinuous elements may be part of
-   * vector-valued elements and may therefore be compared against each other
-   * for domination. They should return
-   * <code>either_element_can_dominate</code> in that case. Likewise, when
-   * comparing two identical finite elements, they should return this code;
-   * the reason is that we can not decide which element will dominate at the
-   * time we look at the first component of, for example, two $Q_2\times Q_1$
-   * and $Q_2\times Q_2$ elements, and have to keep our options open until we
-   * get to the second base element.
-   *
-   * Finally, the code no_requirements exists for cases where elements impose
-   * no continuity requirements. The case is primarily meant for FE_Nothing
-   * which is an element that has no degrees of freedom in a subdomain. It
-   * could also be used by discontinuous elements, for example.
-   *
-   * More details on domination can be found in the
-   * @ref hp_paper "hp-paper".
-   */
-  enum Domination
-  {
-    /**
-     * The current element dominates.
-     */
-    this_element_dominates,
-    /**
-     * The other element dominates.
-     */
-    other_element_dominates,
-    /**
-     * Neither element dominates.
-     */
-    neither_element_dominates,
-    /**
-     * Either element may dominate.
-     */
-    either_element_can_dominate,
-    /**
-     * There are no requirements.
-     */
-    no_requirements
-  };
-
-
-  /**
-   * A generalization of the binary <code>and</code> operator to a comparison
-   * relationship. The way this works is pretty much as when you would want to
-   * define a comparison relationship for vectors: either all elements of the
-   * first vector are smaller, equal, or larger than those of the second
-   * vector, or some are and some are not.
-   *
-   * This operator is pretty much the same: if both arguments are
-   * <code>this_element_dominates</code> or
-   * <code>other_element_dominates</code>, then the returned value is that
-   * value. On the other hand, if one of the values is
-   * <code>either_element_can_dominate</code>, then the returned value is that
-   * of the other argument. If either argument is
-   * <code>neither_element_dominates</code>, or if the two arguments are
-   * <code>this_element_dominates</code> and
-   * <code>other_element_dominates</code>, then the returned value is
-   * <code>neither_element_dominates</code>.
-   */
-  inline Domination
-  operator&(const Domination d1, const Domination d2);
-} // namespace FiniteElementDomination
-
-namespace internal
-{
-  /**
-   * Internal data structure for setting up FiniteElementData. It stores for
-   * each object the (inclusive/exclusive) number of degrees of freedoms, as
-   * well as, the index of its first degree of freedom within a cell and the
-   * index of the first d-dimensional object within each face.
-   *
-   * The information is saved as a vector of vectors. One can query the
-   * inclusive number of dofs of the i-th d-dimensional object via:
-   * dofs_per_object_inclusive[d][i].
-   *
-   * As an example, the data is shown for a quadratic wedge. Which consists of
-   * 6 vertices, 9 lines, and 5 faces (two triangles and three quadrilaterals).
-   * @code
-   *            vertices            lines                  faces      cell
-   * dpo_excl  1 1 1 1 1 1 | 1 1 1 1  1  1  1  1  1 |  0  0  1  1  1 |  0
-   * dpo_incl  1 1 1 1 1 1 | 3 3 3 3  3  3  3  3  3 |  6  6  9  9  9 | 18
-   * obj_index 0 1 2 3 4 5 | 6 7 8 9 10 11 12 13 14 | 15 15 15 16 17 | 18
-   * @endcode
-   *
-   * Since the above table looks as follows for:
-   *
-   * - a triangle:
-   * @code
-   * dpo_excl  1  1  1 | 1  1  1 |  0
-   * obj_index 0  1  2 | 3  4  5 |  6
-   * @endcode
-   *
-   * - quadrilateral:
-   * @code
-   * dpo_excl  1  1  1  1 | 1  1  1  1 |  1
-   * obj_index 0  1  2  3 | 4  5  6  7 |  8
-   * @endcode
-   *
-   * The index of the first d-dimensional object within each face results as:
-   * @code
-   *                         vertices      lines       face
-   * first_obj_index_on_face 0 0 0 0 0 | 3 3 4 4 4 | 6 6 8 8 8
-   * @endcode
-   *
-   */
-  struct GenericDoFsPerObject
-  {
-    /**
-     * Exclusive number of degrees of freedom per object.
-     */
-    std::vector<std::vector<unsigned int>> dofs_per_object_exclusive;
-
-    /**
-     * Inclusive number of degrees of freedom per object.
-     */
-    std::vector<std::vector<unsigned int>> dofs_per_object_inclusive;
-
-    /**
-     * First index of an object.
-     */
-    std::vector<std::vector<unsigned int>> object_index;
-
-    /**
-     * First index of an object within a face.
-     */
-    std::vector<std::vector<unsigned int>> first_object_index_on_face;
-
-    /**
-     * Function that fills the fields based on a provided finite element.
-     */
-    template <int dim>
-    static GenericDoFsPerObject
-    generate(const FiniteElementData<dim> &fe);
-  };
-} // namespace internal
-
-/**
- * A class that declares a number of scalar constant variables that describe
- * basic properties of a finite element implementation. This includes, for
- * example, the number of degrees of freedom per vertex, line, or cell; the
- * number of vector components; etc.
- *
- * The kind of information stored here is computed during initialization of a
- * finite element object and is passed down to this class via its constructor.
- * The data stored by this class is part of the public interface of the
- * FiniteElement class (which derives from the current class). See there for
- * more information.
- *
- * @ingroup febase
- */
-template <int dim>
-class FiniteElementData
-{
-public:
-  /**
-   * Enumerator for the different types of continuity a finite element may
-   * have. Continuity is measured by the Sobolev space containing the
-   * constructed finite element space and is also called this way.
-   *
-   * Note that certain continuities may imply others. For instance, a function
-   * in <i>H<sup>1</sup></i> is in <i>H<sup>curl</sup></i> and
-   * <i>H<sup>div</sup></i> as well.
-   *
-   * If you are interested in continuity in the classical sense, then the
-   * following relations hold:
-   *
-   * <ol>
-   *
-   * <li> <i>H<sup>1</sup></i> implies that the function is continuous over
-   * cell boundaries.
-   *
-   * <li> <i>H<sup>2</sup></i> implies that the function is continuously
-   * differentiable over cell boundaries.
-   *
-   * <li> <i>L<sup>2</sup></i> indicates that the element is discontinuous.
-   * Since discontinuous elements have no topological couplings between grid
-   * cells and code may actually depend on this property, <i>L<sup>2</sup></i>
-   * conformity is handled in a special way in the sense that it is <b>not</b>
-   * implied by any higher conformity.
-   * </ol>
-   *
-   * In order to test if a finite element conforms to a certain space, use
-   * FiniteElementData<dim>::conforms().
-   */
-  enum Conformity
-  {
-    /**
-     * Indicates incompatible continuities of a system.
-     */
-    unknown = 0x00,
-
-    /**
-     * Discontinuous elements. See above!
-     */
-    L2 = 0x01,
-
-    /**
-     * Conformity with the space <i>H<sup>curl</sup></i> (continuous
-     * tangential component of a vector field)
-     */
-    Hcurl = 0x02,
-
-    /**
-     * Conformity with the space <i>H<sup>div</sup></i> (continuous normal
-     * component of a vector field)
-     */
-    Hdiv = 0x04,
-
-    /**
-     * Conformity with the space <i>H<sup>1</sup></i> (continuous)
-     */
-    H1 = Hcurl | Hdiv,
-
-    /**
-     * Conformity with the space <i>H<sup>2</sup></i> (continuously
-     * differentiable)
-     */
-    H2 = 0x0e
-  };
-
-  /**
-   * The dimension of the finite element, which is the template parameter
-   * <tt>dim</tt>
-   */
-  static constexpr unsigned int dimension = dim;
-
-private:
-  /**
-   * Reference cell type.
-   */
-  const ReferenceCell reference_cell_kind;
-
-  /**
-   * Number of unique quads. If all quads have the same type, the value is
-   * one; else it equals the number of quads.
-   */
-  const unsigned int number_unique_quads;
-
-  /**
-   * Number of unique faces. If all faces have the same type, the value is
-   * one; else it equals the number of faces.
-   */
-  const unsigned int number_unique_faces;
-
-public:
-  /**
-   * Number of degrees of freedom on a vertex.
-   */
-  const unsigned int dofs_per_vertex;
-
-  /**
-   * Number of degrees of freedom in a line; not including the degrees of
-   * freedom on the vertices of the line.
-   */
-  const unsigned int dofs_per_line;
-
-private:
-  /**
-   * Number of degrees of freedom on quads. If all quads have the same
-   * number of degrees freedoms the values equal dofs_per_quad.
-   */
-  const std::vector<unsigned int> n_dofs_on_quad;
-
-public:
-  /**
-   * Number of degrees of freedom in a quadrilateral; not including the
-   * degrees of freedom on the lines and vertices of the quadrilateral.
-   */
-  const unsigned int dofs_per_quad;
-
-private:
-  /**
-   * Maximum number of degrees of freedom on any quad.
-   */
-  const unsigned int dofs_per_quad_max;
-
-public:
-  /**
-   * Number of degrees of freedom in a hexahedron; not including the degrees
-   * of freedom on the quadrilaterals, lines and vertices of the hexahedron.
-   */
-  const unsigned int dofs_per_hex;
-
-  /**
-   * First index of dof on a line.
-   */
-  const unsigned int first_line_index;
-
-private:
-  /**
-   * First index of a quad. If all quads have the same number of degrees of
-   * freedom, only the first index of the first quad is stored since the
-   * indices of the others can be simply recomputed.
-   */
-  const std::vector<unsigned int> first_index_of_quads;
-
-public:
-  /**
-   * First index of dof on a quad.
-   */
-  const unsigned int first_quad_index;
-
-  /**
-   * First index of dof on a hexahedron.
-   */
-  const unsigned int first_hex_index;
-
-private:
-  /**
-   * Index of the first line of all faces.
-   */
-  const std::vector<unsigned int> first_line_index_of_faces;
-
-public:
-  /**
-   * First index of dof on a line for face data.
-   */
-  const unsigned int first_face_line_index;
-
-private:
-  /**
-   * Index of the first quad of all faces.
-   */
-  const std::vector<unsigned int> first_quad_index_of_faces;
-
-public:
-  /**
-   * First index of dof on a quad for face data.
-   */
-  const unsigned int first_face_quad_index;
-
-private:
-  /**
-   * Number of degrees of freedom on faces. If all faces have the same
-   * number of degrees freedoms the values equal dofs_per_quad.
-   */
-  const std::vector<unsigned int> n_dofs_on_face;
-
-public:
-  /**
-   * Number of degrees of freedom on a face. This is the accumulated number of
-   * degrees of freedom on all the objects of dimension up to <tt>dim-1</tt>
-   * constituting a face.
-   */
-  const unsigned int dofs_per_face;
-
-private:
-  /**
-   * Maximum number of degrees of freedom on any face.
-   */
-  const unsigned int dofs_per_face_max;
-
-public:
-  /**
-   * Total number of degrees of freedom on a cell. This is the accumulated
-   * number of degrees of freedom on all the objects of dimension up to
-   * <tt>dim</tt> constituting a cell.
-   */
-  const unsigned int dofs_per_cell;
-
-  /**
-   * Number of vector components of this finite element, and dimension of the
-   * image space. For vector-valued finite elements (i.e. when this number is
-   * greater than one), the number of vector components is in many cases equal
-   * to the number of base elements glued together with the help of the
-   * FESystem class. However, for elements like the Nedelec element, the
-   * number is greater than one even though we only have one base element.
-   */
-  const unsigned int components;
-
-  /**
-   * Maximal polynomial degree of a shape function in a single coordinate
-   * direction.
-   */
-  const unsigned int degree;
-
-  /**
-   * Indicate the space this element conforms to.
-   */
-  const Conformity conforming_space;
-
-  /**
-   * Storage for an object describing the sizes of each block of a compound
-   * element. For an element which is not an FESystem, this contains only a
-   * single block with length #dofs_per_cell.
-   */
-  const BlockIndices block_indices_data;
-
-  /**
-   * Constructor, computing all necessary values from the distribution of dofs
-   * to geometrical objects.
-   *
-   * @param[in] dofs_per_object A vector that describes the number of degrees
-   * of freedom on geometrical objects for each dimension. This vector must
-   * have size dim+1, and entry 0 describes the number of degrees of freedom
-   * per vertex, entry 1 the number of degrees of freedom per line, etc. As an
-   * example, for the common $Q_1$ Lagrange element in 2d, this vector would
-   * have elements <code>(1,0,0)</code>. On the other hand, for a $Q_3$
-   * element in 3d, it would have entries <code>(1,2,4,8)</code>.
-   *
-   * @param[in] n_components Number of vector components of the element.
-   *
-   * @param[in] degree The maximal polynomial degree of any of the shape
-   * functions of this element in any variable on the reference element. For
-   * example, for the $Q_1$ element (in any space dimension), this would be
-   * one; this is so despite the fact that the element has a shape function of
-   * the form $\hat x\hat y$ (in 2d) and $\hat x\hat y\hat z$ (in 3d), which,
-   * although quadratic and cubic polynomials, are still only linear in each
-   * reference variable separately. The information provided by this variable
-   * is typically used in determining what an appropriate quadrature formula
-   * is.
-   *
-   * @param[in] conformity A variable describing which Sobolev space this
-   * element conforms to. For example, the $Q_p$ Lagrange elements
-   * (implemented by the FE_Q class) are $H^1$ conforming, whereas the
-   * Raviart-Thomas element (implemented by the FE_RaviartThomas class) is
-   * $H_\text{div}$ conforming; finally, completely discontinuous elements
-   * (implemented by the FE_DGQ class) are only $L_2$ conforming.
-   *
-   * @param[in] block_indices An argument that describes how the base elements
-   * of a finite element are grouped. The default value constructs a single
-   * block that consists of all @p dofs_per_cell degrees of freedom. This is
-   * appropriate for all "atomic" elements (including non-primitive ones) and
-   * these can therefore omit this argument. On the other hand, composed
-   * elements such as FESystem will want to pass a different value here.
-   */
-  FiniteElementData(const std::vector<unsigned int> &dofs_per_object,
-                    const unsigned int               n_components,
-                    const unsigned int               degree,
-                    const Conformity                 conformity = unknown,
-                    const BlockIndices &block_indices = BlockIndices());
-
-  /**
-   * The same as above but with the difference that also the type of the
-   * underlying geometric entity can be specified.
-   */
-  FiniteElementData(const std::vector<unsigned int> &dofs_per_object,
-                    const ReferenceCell              reference_cell,
-                    const unsigned int               n_components,
-                    const unsigned int               degree,
-                    const Conformity                 conformity = unknown,
-                    const BlockIndices &block_indices = BlockIndices());
-
-  /**
-   * The same as above but instead of passing a vector containing the degrees
-   * of freedoms per object a struct of type GenericDoFsPerObject. This allows
-   * that 2D objects might have different number of degrees of freedoms, which
-   * is particular useful for cells with triangles and quadrilaterals as faces.
-   */
-  FiniteElementData(const internal::GenericDoFsPerObject &data,
-                    const ReferenceCell                   reference_cell,
-                    const unsigned int                    n_components,
-                    const unsigned int                    degree,
-                    const Conformity                      conformity = unknown,
-                    const BlockIndices &block_indices = BlockIndices());
-
-  /**
-   * Return the kind of reference cell this element is defined on: For
-   * example, whether the element's reference cell is a square or
-   * triangle, or similar choices in higher dimensions.
-   */
-  ReferenceCell
-  reference_cell() const;
-
-  /**
-   * Number of unique quads. If all quads have the same type, the value is
-   * one; else it equals the number of quads.
-   */
-  unsigned int
-  n_unique_quads() const;
-
-  /**
-   * Number of unique faces. If all faces have the same type, the value is
-   * one; else it equals the number of faces.
-   */
-  unsigned int
-  n_unique_faces() const;
-
-  /**
-   * Number of dofs per vertex.
-   */
-  unsigned int
-  n_dofs_per_vertex() const;
-
-  /**
-   * Number of dofs per line. Not including dofs on lower dimensional objects.
-   */
-  unsigned int
-  n_dofs_per_line() const;
-
-  /**
-   * Number of dofs per quad. Not including dofs on lower dimensional objects.
-   */
-  unsigned int
-  n_dofs_per_quad(unsigned int face_no = 0) const;
-
-  /**
-   * Maximum number of dofs per quad. Not including dofs on lower dimensional
-   * objects.
-   */
-  unsigned int
-  max_dofs_per_quad() const;
-
-  /**
-   * Number of dofs per hex. Not including dofs on lower dimensional objects.
-   */
-  unsigned int
-  n_dofs_per_hex() const;
-
-  /**
-   * Number of dofs per face, accumulating degrees of freedom of all lower
-   * dimensional objects.
-   */
-  unsigned int
-  n_dofs_per_face(unsigned int face_no = 0, unsigned int child = 0) const;
-
-  /**
-   * Maximum number of dofs per face, accumulating degrees of freedom of all
-   * lower dimensional objects.
-   */
-  unsigned int
-  max_dofs_per_face() const;
-
-  /**
-   * Number of dofs per cell, accumulating degrees of freedom of all lower
-   * dimensional objects.
-   */
-  unsigned int
-  n_dofs_per_cell() const;
-
-  /**
-   * Return the number of degrees per structdim-dimensional object. For
-   * structdim==0, the function therefore returns dofs_per_vertex, for
-   * structdim==1 dofs_per_line, etc. This function is mostly used to allow
-   * some template trickery for functions that should work on all sorts of
-   * objects without wanting to use the different names (vertex, line, ...)
-   * associated with these objects.
-   */
-  template <int structdim>
-  unsigned int
-  n_dofs_per_object(const unsigned int i = 0) const;
-
-  /**
-   * Number of components. See
-   * @ref GlossComponent "the glossary"
-   * for more information.
-   */
-  unsigned int
-  n_components() const;
-
-  /**
-   * Number of blocks. See
-   * @ref GlossBlock "the glossary"
-   * for more information.
-   */
-  unsigned int
-  n_blocks() const;
-
-  /**
-   * Detailed information on block sizes.
-   */
-  const BlockIndices &
-  block_indices() const;
-
-  /**
-   * Maximal polynomial degree of a shape function in a single coordinate
-   * direction.
-   *
-   * This function can be used to determine the optimal quadrature rule.
-   */
-  unsigned int
-  tensor_degree() const;
-
-  /**
-   * Test whether a finite element space conforms to a certain Sobolev space.
-   *
-   * @note This function will return a true value even if the finite element
-   * space has higher regularity than asked for.
-   */
-  bool
-  conforms(const Conformity) const;
-
-  /**
-   * Comparison operator.
-   */
-  bool
-  operator==(const FiniteElementData &) const;
-
-  /**
-   * Return first index of dof on a line.
-   */
-  unsigned int
-  get_first_line_index() const;
-
-  /**
-   * Return first index of dof on a quad.
-   */
-  unsigned int
-  get_first_quad_index(const unsigned int quad_no = 0) const;
-
-  /**
-   * Return first index of dof on a hexahedron.
-   */
-  unsigned int
-  get_first_hex_index() const;
-
-  /**
-   * Return first index of dof on a line for face data.
-   */
-  unsigned int
-  get_first_face_line_index(const unsigned int face_no = 0) const;
-
-  /**
-   * Return first index of dof on a quad for face data.
-   */
-  unsigned int
-  get_first_face_quad_index(const unsigned int face_no = 0) const;
-};
-
-namespace internal
-{
-  /**
-   * Utility function to convert "dofs per object" information
-   * of a @p dim dimensional reference cell @p reference_cell.
-   */
-  internal::GenericDoFsPerObject
-  expand(const unsigned int               dim,
-         const std::vector<unsigned int> &dofs_per_object,
-         const dealii::ReferenceCell      reference_cell);
-} // namespace internal
-
-
-
-// --------- inline and template functions ---------------
-
-
-#ifndef DOXYGEN
-
-namespace FiniteElementDomination
-{
-  inline Domination
-  operator&(const Domination d1, const Domination d2)
-  {
-    // go through the entire list of possibilities. note that if we were into
-    // speed, obfuscation and cared enough, we could implement this operator
-    // by doing a bitwise & (and) if we gave these values to the enum values:
-    // neither_element_dominates=0, this_element_dominates=1,
-    // other_element_dominates=2, either_element_can_dominate=3
-    // =this_element_dominates|other_element_dominates
-    switch (d1)
-      {
-        case this_element_dominates:
-          if ((d2 == this_element_dominates) ||
-              (d2 == either_element_can_dominate) || (d2 == no_requirements))
-            return this_element_dominates;
-          else
-            return neither_element_dominates;
-
-        case other_element_dominates:
-          if ((d2 == other_element_dominates) ||
-              (d2 == either_element_can_dominate) || (d2 == no_requirements))
-            return other_element_dominates;
-          else
-            return neither_element_dominates;
-
-        case neither_element_dominates:
-          return neither_element_dominates;
-
-        case either_element_can_dominate:
-          if (d2 == no_requirements)
-            return either_element_can_dominate;
-          else
-            return d2;
-
-        case no_requirements:
-          return d2;
-
-        default:
-          // shouldn't get here
-          Assert(false, ExcInternalError());
-      }
-
-    return neither_element_dominates;
-  }
-} // namespace FiniteElementDomination
-
-
-template <int dim>
-inline ReferenceCell
-FiniteElementData<dim>::reference_cell() const
-{
-  return reference_cell_kind;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_unique_quads() const
-{
-  return number_unique_quads;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_unique_faces() const
-{
-  return number_unique_faces;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_vertex() const
-{
-  return dofs_per_vertex;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_line() const
-{
-  return dofs_per_line;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_quad(unsigned int face_no) const
-{
-  return n_dofs_on_quad[n_dofs_on_quad.size() == 1 ? 0 : face_no];
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::max_dofs_per_quad() const
-{
-  return dofs_per_quad_max;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_hex() const
-{
-  return dofs_per_hex;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_face(unsigned int face_no,
-                                        unsigned int child_no) const
-{
-  (void)child_no;
-
-  return n_dofs_on_face[n_dofs_on_face.size() == 1 ? 0 : face_no];
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::max_dofs_per_face() const
-{
-  return dofs_per_face_max;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_cell() const
-{
-  return dofs_per_cell;
-}
-
-
-
-template <int dim>
-template <int structdim>
-inline unsigned int
-FiniteElementData<dim>::n_dofs_per_object(const unsigned int i) const
-{
-  switch (structdim)
-    {
-      case 0:
-        return n_dofs_per_vertex();
-      case 1:
-        return n_dofs_per_line();
-      case 2:
-        return n_dofs_per_quad((structdim == 2 && dim == 3) ? i : 0);
-      case 3:
-        return n_dofs_per_hex();
-      default:
-        Assert(false, ExcInternalError());
-    }
-  return numbers::invalid_unsigned_int;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_components() const
-{
-  return components;
-}
-
-
-
-template <int dim>
-inline const BlockIndices &
-FiniteElementData<dim>::block_indices() const
-{
-  return block_indices_data;
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::n_blocks() const
-{
-  return block_indices_data.size();
-}
-
-
-
-template <int dim>
-inline unsigned int
-FiniteElementData<dim>::tensor_degree() const
-{
-  return degree;
-}
-
-
-template <int dim>
-inline bool
-FiniteElementData<dim>::conforms(const Conformity space) const
-{
-  return ((space & conforming_space) == space);
-}
-
-
-
-template <int dim>
-unsigned int
-FiniteElementData<dim>::get_first_line_index() const
-{
-  return first_line_index;
-}
-
-template <int dim>
-unsigned int
-FiniteElementData<dim>::get_first_quad_index(const unsigned int quad_no) const
-{
-  if (first_index_of_quads.size() == 1)
-    return first_index_of_quads[0] + quad_no * n_dofs_per_quad(0);
-  else
-    return first_index_of_quads[quad_no];
-}
-
-template <int dim>
-unsigned int
-FiniteElementData<dim>::get_first_hex_index() const
-{
-  return first_hex_index;
-}
-
-template <int dim>
-unsigned int
-FiniteElementData<dim>::get_first_face_line_index(
-  const unsigned int face_no) const
-{
-  return first_line_index_of_faces[first_line_index_of_faces.size() == 1 ?
-                                     0 :
-                                     face_no];
-}
-
-template <int dim>
-unsigned int
-FiniteElementData<dim>::get_first_face_quad_index(
-  const unsigned int face_no) const
-{
-  return first_quad_index_of_faces[first_quad_index_of_faces.size() == 1 ?
-                                     0 :
-                                     face_no];
-}
-
-template <int dim>
-internal::GenericDoFsPerObject
-internal::GenericDoFsPerObject::generate(const FiniteElementData<dim> &fe)
-{
-  const auto reference_cell = fe.reference_cell();
-
-  internal::GenericDoFsPerObject result;
-
-  result.dofs_per_object_exclusive.resize(4);
-  result.dofs_per_object_inclusive.resize(4);
-  result.object_index.resize(4);
-
-  unsigned int counter = 0;
-
-  for (unsigned int v : reference_cell.vertex_indices())
-    {
-      const auto c = fe.template n_dofs_per_object<0>(v);
-
-      result.dofs_per_object_exclusive[0].emplace_back(c);
-      result.dofs_per_object_inclusive[0].emplace_back(c);
-      result.object_index[0].emplace_back(counter);
-
-      counter += c;
-    }
-
-  if (dim >= 2)
-    for (unsigned int l : reference_cell.line_indices())
-      {
-        const auto c = fe.template n_dofs_per_object<1>(l);
-
-        result.dofs_per_object_exclusive[1].emplace_back(c);
-        result.dofs_per_object_inclusive[1].emplace_back(
-          c + 2 * fe.template n_dofs_per_object<0>());
-        result.object_index[1].emplace_back(counter);
-
-        counter += c;
-      }
-
-  if (dim == 3)
-    for (unsigned int f : reference_cell.face_indices())
-      {
-        const auto c = fe.template n_dofs_per_object<2>(f);
-
-        result.dofs_per_object_exclusive[2].emplace_back(c);
-        result.dofs_per_object_inclusive[2].emplace_back(fe.n_dofs_per_face(f));
-        result.object_index[2].emplace_back(counter);
-
-        counter += c;
-      }
-
-  {
-    const auto c = fe.template n_dofs_per_object<dim>();
-
-    result.dofs_per_object_exclusive[dim].emplace_back(c);
-    result.dofs_per_object_inclusive[dim].emplace_back(fe.n_dofs_per_cell());
-    result.object_index[dim].emplace_back(counter);
-
-    counter += c;
-  }
-
-  for (unsigned int d = dim + 1; d <= 3; ++d)
-    {
-      result.dofs_per_object_exclusive[d].emplace_back(0);
-      result.dofs_per_object_inclusive[d].emplace_back(0);
-      result.object_index[d].emplace_back(counter);
-    }
-
-  result.first_object_index_on_face.resize(3);
-  for (unsigned int face_no : reference_cell.face_indices())
-    {
-      result.first_object_index_on_face[0].emplace_back(0);
-
-      result.first_object_index_on_face[1].emplace_back(
-        fe.get_first_face_line_index(face_no));
-
-      result.first_object_index_on_face[2].emplace_back(
-        fe.get_first_face_quad_index(face_no));
-    }
-
-  return result;
-}
-
-
-#endif // DOXYGEN
-
-
-DEAL_II_NAMESPACE_CLOSE
+DEAL_II_WARNING("This file is deprecated. Simply use <deal.II/fe/fe_data.h>.")
 
 #endif
diff --git a/include/deal.II/fe/fe_data.h b/include/deal.II/fe/fe_data.h
new file mode 100644 (file)
index 0000000..7d47986
--- /dev/null
@@ -0,0 +1,1063 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2000 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii_fe_data_h
+#define dealii_fe_data_h
+
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/exceptions.h>
+
+#include <deal.II/grid/reference_cell.h>
+
+#include <deal.II/lac/block_indices.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+// Forward declarations:
+#ifndef DOXYGEN
+template <int dim>
+class FiniteElementData;
+#endif
+
+/**
+ * A namespace solely for the purpose of defining the Domination enum as well
+ * as associated operators.
+ */
+namespace FiniteElementDomination
+{
+  /**
+   * An enum that describes the outcome of comparing two elements for mutual
+   * domination. If one element dominates another, then the restriction of the
+   * space described by the dominated element to a face of the cell is
+   * strictly larger than that of the dominating element. For example, in 2-d
+   * Q(2) elements dominate Q(4) elements, because the traces of Q(4) elements
+   * are quartic polynomials which is a space strictly larger than the
+   * quadratic polynomials (the restriction of the Q(2) element). Similar
+   * reasonings apply for vertices and cells as well. In general, Q(k) dominates
+   * Q(k') if $k\le k'$.
+   *
+   * This enum is used in the FiniteElement::compare_for_domination() function
+   * that is used in the context of hp-finite element methods when determining
+   * what to do at faces where two different finite elements meet (see the
+   * @ref hp_paper "hp-paper"
+   * for a more detailed description of the following). In that case, the
+   * degrees of freedom of one side need to be constrained to those on the
+   * other side. The determination which side is which is based on the outcome
+   * of a comparison for mutual domination: the dominated side is constrained
+   * to the dominating one.
+   *
+   * Note that there are situations where neither side dominates. The
+   * @ref hp_paper "hp-paper"
+   * lists two case, with the simpler one being that a $Q_2\times Q_1$ vector-
+   * valued element (i.e. a <code>FESystem(FE_Q(2),1,FE_Q(1),1)</code>) meets
+   * a $Q_1\times Q_2$ element: here, for each of the two vector-components,
+   * we can define a domination relationship, but it is different for the two
+   * components.
+   *
+   * It is clear that the concept of domination doesn't matter for
+   * discontinuous elements. However, discontinuous elements may be part of
+   * vector-valued elements and may therefore be compared against each other
+   * for domination. They should return
+   * <code>either_element_can_dominate</code> in that case. Likewise, when
+   * comparing two identical finite elements, they should return this code;
+   * the reason is that we can not decide which element will dominate at the
+   * time we look at the first component of, for example, two $Q_2\times Q_1$
+   * and $Q_2\times Q_2$ elements, and have to keep our options open until we
+   * get to the second base element.
+   *
+   * Finally, the code no_requirements exists for cases where elements impose
+   * no continuity requirements. The case is primarily meant for FE_Nothing
+   * which is an element that has no degrees of freedom in a subdomain. It
+   * could also be used by discontinuous elements, for example.
+   *
+   * More details on domination can be found in the
+   * @ref hp_paper "hp-paper".
+   */
+  enum Domination
+  {
+    /**
+     * The current element dominates.
+     */
+    this_element_dominates,
+    /**
+     * The other element dominates.
+     */
+    other_element_dominates,
+    /**
+     * Neither element dominates.
+     */
+    neither_element_dominates,
+    /**
+     * Either element may dominate.
+     */
+    either_element_can_dominate,
+    /**
+     * There are no requirements.
+     */
+    no_requirements
+  };
+
+
+  /**
+   * A generalization of the binary <code>and</code> operator to a comparison
+   * relationship. The way this works is pretty much as when you would want to
+   * define a comparison relationship for vectors: either all elements of the
+   * first vector are smaller, equal, or larger than those of the second
+   * vector, or some are and some are not.
+   *
+   * This operator is pretty much the same: if both arguments are
+   * <code>this_element_dominates</code> or
+   * <code>other_element_dominates</code>, then the returned value is that
+   * value. On the other hand, if one of the values is
+   * <code>either_element_can_dominate</code>, then the returned value is that
+   * of the other argument. If either argument is
+   * <code>neither_element_dominates</code>, or if the two arguments are
+   * <code>this_element_dominates</code> and
+   * <code>other_element_dominates</code>, then the returned value is
+   * <code>neither_element_dominates</code>.
+   */
+  inline Domination
+  operator&(const Domination d1, const Domination d2);
+} // namespace FiniteElementDomination
+
+namespace internal
+{
+  /**
+   * Internal data structure for setting up FiniteElementData. It stores for
+   * each object the (inclusive/exclusive) number of degrees of freedoms, as
+   * well as, the index of its first degree of freedom within a cell and the
+   * index of the first d-dimensional object within each face.
+   *
+   * The information is saved as a vector of vectors. One can query the
+   * inclusive number of dofs of the i-th d-dimensional object via:
+   * dofs_per_object_inclusive[d][i].
+   *
+   * As an example, the data is shown for a quadratic wedge. Which consists of
+   * 6 vertices, 9 lines, and 5 faces (two triangles and three quadrilaterals).
+   * @code
+   *            vertices            lines                  faces      cell
+   * dpo_excl  1 1 1 1 1 1 | 1 1 1 1  1  1  1  1  1 |  0  0  1  1  1 |  0
+   * dpo_incl  1 1 1 1 1 1 | 3 3 3 3  3  3  3  3  3 |  6  6  9  9  9 | 18
+   * obj_index 0 1 2 3 4 5 | 6 7 8 9 10 11 12 13 14 | 15 15 15 16 17 | 18
+   * @endcode
+   *
+   * Since the above table looks as follows for:
+   *
+   * - a triangle:
+   * @code
+   * dpo_excl  1  1  1 | 1  1  1 |  0
+   * obj_index 0  1  2 | 3  4  5 |  6
+   * @endcode
+   *
+   * - quadrilateral:
+   * @code
+   * dpo_excl  1  1  1  1 | 1  1  1  1 |  1
+   * obj_index 0  1  2  3 | 4  5  6  7 |  8
+   * @endcode
+   *
+   * The index of the first d-dimensional object within each face results as:
+   * @code
+   *                         vertices      lines       face
+   * first_obj_index_on_face 0 0 0 0 0 | 3 3 4 4 4 | 6 6 8 8 8
+   * @endcode
+   *
+   */
+  struct GenericDoFsPerObject
+  {
+    /**
+     * Exclusive number of degrees of freedom per object.
+     */
+    std::vector<std::vector<unsigned int>> dofs_per_object_exclusive;
+
+    /**
+     * Inclusive number of degrees of freedom per object.
+     */
+    std::vector<std::vector<unsigned int>> dofs_per_object_inclusive;
+
+    /**
+     * First index of an object.
+     */
+    std::vector<std::vector<unsigned int>> object_index;
+
+    /**
+     * First index of an object within a face.
+     */
+    std::vector<std::vector<unsigned int>> first_object_index_on_face;
+
+    /**
+     * Function that fills the fields based on a provided finite element.
+     */
+    template <int dim>
+    static GenericDoFsPerObject
+    generate(const FiniteElementData<dim> &fe);
+  };
+} // namespace internal
+
+/**
+ * A class that declares a number of scalar constant variables that describe
+ * basic properties of a finite element implementation. This includes, for
+ * example, the number of degrees of freedom per vertex, line, or cell; the
+ * number of vector components; etc.
+ *
+ * The kind of information stored here is computed during initialization of a
+ * finite element object and is passed down to this class via its constructor.
+ * The data stored by this class is part of the public interface of the
+ * FiniteElement class (which derives from the current class). See there for
+ * more information.
+ *
+ * @ingroup febase
+ */
+template <int dim>
+class FiniteElementData
+{
+public:
+  /**
+   * Enumerator for the different types of continuity a finite element may
+   * have. Continuity is measured by the Sobolev space containing the
+   * constructed finite element space and is also called this way.
+   *
+   * Note that certain continuities may imply others. For instance, a function
+   * in <i>H<sup>1</sup></i> is in <i>H<sup>curl</sup></i> and
+   * <i>H<sup>div</sup></i> as well.
+   *
+   * If you are interested in continuity in the classical sense, then the
+   * following relations hold:
+   *
+   * <ol>
+   *
+   * <li> <i>H<sup>1</sup></i> implies that the function is continuous over
+   * cell boundaries.
+   *
+   * <li> <i>H<sup>2</sup></i> implies that the function is continuously
+   * differentiable over cell boundaries.
+   *
+   * <li> <i>L<sup>2</sup></i> indicates that the element is discontinuous.
+   * Since discontinuous elements have no topological couplings between grid
+   * cells and code may actually depend on this property, <i>L<sup>2</sup></i>
+   * conformity is handled in a special way in the sense that it is <b>not</b>
+   * implied by any higher conformity.
+   * </ol>
+   *
+   * In order to test if a finite element conforms to a certain space, use
+   * FiniteElementData<dim>::conforms().
+   */
+  enum Conformity
+  {
+    /**
+     * Indicates incompatible continuities of a system.
+     */
+    unknown = 0x00,
+
+    /**
+     * Discontinuous elements. See above!
+     */
+    L2 = 0x01,
+
+    /**
+     * Conformity with the space <i>H<sup>curl</sup></i> (continuous
+     * tangential component of a vector field)
+     */
+    Hcurl = 0x02,
+
+    /**
+     * Conformity with the space <i>H<sup>div</sup></i> (continuous normal
+     * component of a vector field)
+     */
+    Hdiv = 0x04,
+
+    /**
+     * Conformity with the space <i>H<sup>1</sup></i> (continuous)
+     */
+    H1 = Hcurl | Hdiv,
+
+    /**
+     * Conformity with the space <i>H<sup>2</sup></i> (continuously
+     * differentiable)
+     */
+    H2 = 0x0e
+  };
+
+  /**
+   * The dimension of the finite element, which is the template parameter
+   * <tt>dim</tt>
+   */
+  static constexpr unsigned int dimension = dim;
+
+private:
+  /**
+   * Reference cell type.
+   */
+  const ReferenceCell reference_cell_kind;
+
+  /**
+   * Number of unique quads. If all quads have the same type, the value is
+   * one; else it equals the number of quads.
+   */
+  const unsigned int number_unique_quads;
+
+  /**
+   * Number of unique faces. If all faces have the same type, the value is
+   * one; else it equals the number of faces.
+   */
+  const unsigned int number_unique_faces;
+
+public:
+  /**
+   * Number of degrees of freedom on a vertex.
+   */
+  const unsigned int dofs_per_vertex;
+
+  /**
+   * Number of degrees of freedom in a line; not including the degrees of
+   * freedom on the vertices of the line.
+   */
+  const unsigned int dofs_per_line;
+
+private:
+  /**
+   * Number of degrees of freedom on quads. If all quads have the same
+   * number of degrees freedoms the values equal dofs_per_quad.
+   */
+  const std::vector<unsigned int> n_dofs_on_quad;
+
+public:
+  /**
+   * Number of degrees of freedom in a quadrilateral; not including the
+   * degrees of freedom on the lines and vertices of the quadrilateral.
+   */
+  const unsigned int dofs_per_quad;
+
+private:
+  /**
+   * Maximum number of degrees of freedom on any quad.
+   */
+  const unsigned int dofs_per_quad_max;
+
+public:
+  /**
+   * Number of degrees of freedom in a hexahedron; not including the degrees
+   * of freedom on the quadrilaterals, lines and vertices of the hexahedron.
+   */
+  const unsigned int dofs_per_hex;
+
+  /**
+   * First index of dof on a line.
+   */
+  const unsigned int first_line_index;
+
+private:
+  /**
+   * First index of a quad. If all quads have the same number of degrees of
+   * freedom, only the first index of the first quad is stored since the
+   * indices of the others can be simply recomputed.
+   */
+  const std::vector<unsigned int> first_index_of_quads;
+
+public:
+  /**
+   * First index of dof on a quad.
+   */
+  const unsigned int first_quad_index;
+
+  /**
+   * First index of dof on a hexahedron.
+   */
+  const unsigned int first_hex_index;
+
+private:
+  /**
+   * Index of the first line of all faces.
+   */
+  const std::vector<unsigned int> first_line_index_of_faces;
+
+public:
+  /**
+   * First index of dof on a line for face data.
+   */
+  const unsigned int first_face_line_index;
+
+private:
+  /**
+   * Index of the first quad of all faces.
+   */
+  const std::vector<unsigned int> first_quad_index_of_faces;
+
+public:
+  /**
+   * First index of dof on a quad for face data.
+   */
+  const unsigned int first_face_quad_index;
+
+private:
+  /**
+   * Number of degrees of freedom on faces. If all faces have the same
+   * number of degrees freedoms the values equal dofs_per_quad.
+   */
+  const std::vector<unsigned int> n_dofs_on_face;
+
+public:
+  /**
+   * Number of degrees of freedom on a face. This is the accumulated number of
+   * degrees of freedom on all the objects of dimension up to <tt>dim-1</tt>
+   * constituting a face.
+   */
+  const unsigned int dofs_per_face;
+
+private:
+  /**
+   * Maximum number of degrees of freedom on any face.
+   */
+  const unsigned int dofs_per_face_max;
+
+public:
+  /**
+   * Total number of degrees of freedom on a cell. This is the accumulated
+   * number of degrees of freedom on all the objects of dimension up to
+   * <tt>dim</tt> constituting a cell.
+   */
+  const unsigned int dofs_per_cell;
+
+  /**
+   * Number of vector components of this finite element, and dimension of the
+   * image space. For vector-valued finite elements (i.e. when this number is
+   * greater than one), the number of vector components is in many cases equal
+   * to the number of base elements glued together with the help of the
+   * FESystem class. However, for elements like the Nedelec element, the
+   * number is greater than one even though we only have one base element.
+   */
+  const unsigned int components;
+
+  /**
+   * Maximal polynomial degree of a shape function in a single coordinate
+   * direction.
+   */
+  const unsigned int degree;
+
+  /**
+   * Indicate the space this element conforms to.
+   */
+  const Conformity conforming_space;
+
+  /**
+   * Storage for an object describing the sizes of each block of a compound
+   * element. For an element which is not an FESystem, this contains only a
+   * single block with length #dofs_per_cell.
+   */
+  const BlockIndices block_indices_data;
+
+  /**
+   * Constructor, computing all necessary values from the distribution of dofs
+   * to geometrical objects.
+   *
+   * @param[in] dofs_per_object A vector that describes the number of degrees
+   * of freedom on geometrical objects for each dimension. This vector must
+   * have size dim+1, and entry 0 describes the number of degrees of freedom
+   * per vertex, entry 1 the number of degrees of freedom per line, etc. As an
+   * example, for the common $Q_1$ Lagrange element in 2d, this vector would
+   * have elements <code>(1,0,0)</code>. On the other hand, for a $Q_3$
+   * element in 3d, it would have entries <code>(1,2,4,8)</code>.
+   *
+   * @param[in] n_components Number of vector components of the element.
+   *
+   * @param[in] degree The maximal polynomial degree of any of the shape
+   * functions of this element in any variable on the reference element. For
+   * example, for the $Q_1$ element (in any space dimension), this would be
+   * one; this is so despite the fact that the element has a shape function of
+   * the form $\hat x\hat y$ (in 2d) and $\hat x\hat y\hat z$ (in 3d), which,
+   * although quadratic and cubic polynomials, are still only linear in each
+   * reference variable separately. The information provided by this variable
+   * is typically used in determining what an appropriate quadrature formula
+   * is.
+   *
+   * @param[in] conformity A variable describing which Sobolev space this
+   * element conforms to. For example, the $Q_p$ Lagrange elements
+   * (implemented by the FE_Q class) are $H^1$ conforming, whereas the
+   * Raviart-Thomas element (implemented by the FE_RaviartThomas class) is
+   * $H_\text{div}$ conforming; finally, completely discontinuous elements
+   * (implemented by the FE_DGQ class) are only $L_2$ conforming.
+   *
+   * @param[in] block_indices An argument that describes how the base elements
+   * of a finite element are grouped. The default value constructs a single
+   * block that consists of all @p dofs_per_cell degrees of freedom. This is
+   * appropriate for all "atomic" elements (including non-primitive ones) and
+   * these can therefore omit this argument. On the other hand, composed
+   * elements such as FESystem will want to pass a different value here.
+   */
+  FiniteElementData(const std::vector<unsigned int> &dofs_per_object,
+                    const unsigned int               n_components,
+                    const unsigned int               degree,
+                    const Conformity                 conformity = unknown,
+                    const BlockIndices &block_indices = BlockIndices());
+
+  /**
+   * The same as above but with the difference that also the type of the
+   * underlying geometric entity can be specified.
+   */
+  FiniteElementData(const std::vector<unsigned int> &dofs_per_object,
+                    const ReferenceCell              reference_cell,
+                    const unsigned int               n_components,
+                    const unsigned int               degree,
+                    const Conformity                 conformity = unknown,
+                    const BlockIndices &block_indices = BlockIndices());
+
+  /**
+   * The same as above but instead of passing a vector containing the degrees
+   * of freedoms per object a struct of type GenericDoFsPerObject. This allows
+   * that 2D objects might have different number of degrees of freedoms, which
+   * is particular useful for cells with triangles and quadrilaterals as faces.
+   */
+  FiniteElementData(const internal::GenericDoFsPerObject &data,
+                    const ReferenceCell                   reference_cell,
+                    const unsigned int                    n_components,
+                    const unsigned int                    degree,
+                    const Conformity                      conformity = unknown,
+                    const BlockIndices &block_indices = BlockIndices());
+
+  /**
+   * Return the kind of reference cell this element is defined on: For
+   * example, whether the element's reference cell is a square or
+   * triangle, or similar choices in higher dimensions.
+   */
+  ReferenceCell
+  reference_cell() const;
+
+  /**
+   * Number of unique quads. If all quads have the same type, the value is
+   * one; else it equals the number of quads.
+   */
+  unsigned int
+  n_unique_quads() const;
+
+  /**
+   * Number of unique faces. If all faces have the same type, the value is
+   * one; else it equals the number of faces.
+   */
+  unsigned int
+  n_unique_faces() const;
+
+  /**
+   * Number of dofs per vertex.
+   */
+  unsigned int
+  n_dofs_per_vertex() const;
+
+  /**
+   * Number of dofs per line. Not including dofs on lower dimensional objects.
+   */
+  unsigned int
+  n_dofs_per_line() const;
+
+  /**
+   * Number of dofs per quad. Not including dofs on lower dimensional objects.
+   */
+  unsigned int
+  n_dofs_per_quad(unsigned int face_no = 0) const;
+
+  /**
+   * Maximum number of dofs per quad. Not including dofs on lower dimensional
+   * objects.
+   */
+  unsigned int
+  max_dofs_per_quad() const;
+
+  /**
+   * Number of dofs per hex. Not including dofs on lower dimensional objects.
+   */
+  unsigned int
+  n_dofs_per_hex() const;
+
+  /**
+   * Number of dofs per face, accumulating degrees of freedom of all lower
+   * dimensional objects.
+   */
+  unsigned int
+  n_dofs_per_face(unsigned int face_no = 0, unsigned int child = 0) const;
+
+  /**
+   * Maximum number of dofs per face, accumulating degrees of freedom of all
+   * lower dimensional objects.
+   */
+  unsigned int
+  max_dofs_per_face() const;
+
+  /**
+   * Number of dofs per cell, accumulating degrees of freedom of all lower
+   * dimensional objects.
+   */
+  unsigned int
+  n_dofs_per_cell() const;
+
+  /**
+   * Return the number of degrees per structdim-dimensional object. For
+   * structdim==0, the function therefore returns dofs_per_vertex, for
+   * structdim==1 dofs_per_line, etc. This function is mostly used to allow
+   * some template trickery for functions that should work on all sorts of
+   * objects without wanting to use the different names (vertex, line, ...)
+   * associated with these objects.
+   */
+  template <int structdim>
+  unsigned int
+  n_dofs_per_object(const unsigned int i = 0) const;
+
+  /**
+   * Number of components. See
+   * @ref GlossComponent "the glossary"
+   * for more information.
+   */
+  unsigned int
+  n_components() const;
+
+  /**
+   * Number of blocks. See
+   * @ref GlossBlock "the glossary"
+   * for more information.
+   */
+  unsigned int
+  n_blocks() const;
+
+  /**
+   * Detailed information on block sizes.
+   */
+  const BlockIndices &
+  block_indices() const;
+
+  /**
+   * Maximal polynomial degree of a shape function in a single coordinate
+   * direction.
+   *
+   * This function can be used to determine the optimal quadrature rule.
+   */
+  unsigned int
+  tensor_degree() const;
+
+  /**
+   * Test whether a finite element space conforms to a certain Sobolev space.
+   *
+   * @note This function will return a true value even if the finite element
+   * space has higher regularity than asked for.
+   */
+  bool
+  conforms(const Conformity) const;
+
+  /**
+   * Comparison operator.
+   */
+  bool
+  operator==(const FiniteElementData &) const;
+
+  /**
+   * Return first index of dof on a line.
+   */
+  unsigned int
+  get_first_line_index() const;
+
+  /**
+   * Return first index of dof on a quad.
+   */
+  unsigned int
+  get_first_quad_index(const unsigned int quad_no = 0) const;
+
+  /**
+   * Return first index of dof on a hexahedron.
+   */
+  unsigned int
+  get_first_hex_index() const;
+
+  /**
+   * Return first index of dof on a line for face data.
+   */
+  unsigned int
+  get_first_face_line_index(const unsigned int face_no = 0) const;
+
+  /**
+   * Return first index of dof on a quad for face data.
+   */
+  unsigned int
+  get_first_face_quad_index(const unsigned int face_no = 0) const;
+};
+
+namespace internal
+{
+  /**
+   * Utility function to convert "dofs per object" information
+   * of a @p dim dimensional reference cell @p reference_cell.
+   */
+  internal::GenericDoFsPerObject
+  expand(const unsigned int               dim,
+         const std::vector<unsigned int> &dofs_per_object,
+         const dealii::ReferenceCell      reference_cell);
+} // namespace internal
+
+
+
+// --------- inline and template functions ---------------
+
+
+#ifndef DOXYGEN
+
+namespace FiniteElementDomination
+{
+  inline Domination
+  operator&(const Domination d1, const Domination d2)
+  {
+    // go through the entire list of possibilities. note that if we were into
+    // speed, obfuscation and cared enough, we could implement this operator
+    // by doing a bitwise & (and) if we gave these values to the enum values:
+    // neither_element_dominates=0, this_element_dominates=1,
+    // other_element_dominates=2, either_element_can_dominate=3
+    // =this_element_dominates|other_element_dominates
+    switch (d1)
+      {
+        case this_element_dominates:
+          if ((d2 == this_element_dominates) ||
+              (d2 == either_element_can_dominate) || (d2 == no_requirements))
+            return this_element_dominates;
+          else
+            return neither_element_dominates;
+
+        case other_element_dominates:
+          if ((d2 == other_element_dominates) ||
+              (d2 == either_element_can_dominate) || (d2 == no_requirements))
+            return other_element_dominates;
+          else
+            return neither_element_dominates;
+
+        case neither_element_dominates:
+          return neither_element_dominates;
+
+        case either_element_can_dominate:
+          if (d2 == no_requirements)
+            return either_element_can_dominate;
+          else
+            return d2;
+
+        case no_requirements:
+          return d2;
+
+        default:
+          // shouldn't get here
+          Assert(false, ExcInternalError());
+      }
+
+    return neither_element_dominates;
+  }
+} // namespace FiniteElementDomination
+
+
+template <int dim>
+inline ReferenceCell
+FiniteElementData<dim>::reference_cell() const
+{
+  return reference_cell_kind;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_unique_quads() const
+{
+  return number_unique_quads;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_unique_faces() const
+{
+  return number_unique_faces;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_vertex() const
+{
+  return dofs_per_vertex;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_line() const
+{
+  return dofs_per_line;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_quad(unsigned int face_no) const
+{
+  return n_dofs_on_quad[n_dofs_on_quad.size() == 1 ? 0 : face_no];
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::max_dofs_per_quad() const
+{
+  return dofs_per_quad_max;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_hex() const
+{
+  return dofs_per_hex;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_face(unsigned int face_no,
+                                        unsigned int child_no) const
+{
+  (void)child_no;
+
+  return n_dofs_on_face[n_dofs_on_face.size() == 1 ? 0 : face_no];
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::max_dofs_per_face() const
+{
+  return dofs_per_face_max;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_cell() const
+{
+  return dofs_per_cell;
+}
+
+
+
+template <int dim>
+template <int structdim>
+inline unsigned int
+FiniteElementData<dim>::n_dofs_per_object(const unsigned int i) const
+{
+  switch (structdim)
+    {
+      case 0:
+        return n_dofs_per_vertex();
+      case 1:
+        return n_dofs_per_line();
+      case 2:
+        return n_dofs_per_quad((structdim == 2 && dim == 3) ? i : 0);
+      case 3:
+        return n_dofs_per_hex();
+      default:
+        Assert(false, ExcInternalError());
+    }
+  return numbers::invalid_unsigned_int;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_components() const
+{
+  return components;
+}
+
+
+
+template <int dim>
+inline const BlockIndices &
+FiniteElementData<dim>::block_indices() const
+{
+  return block_indices_data;
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::n_blocks() const
+{
+  return block_indices_data.size();
+}
+
+
+
+template <int dim>
+inline unsigned int
+FiniteElementData<dim>::tensor_degree() const
+{
+  return degree;
+}
+
+
+template <int dim>
+inline bool
+FiniteElementData<dim>::conforms(const Conformity space) const
+{
+  return ((space & conforming_space) == space);
+}
+
+
+
+template <int dim>
+unsigned int
+FiniteElementData<dim>::get_first_line_index() const
+{
+  return first_line_index;
+}
+
+template <int dim>
+unsigned int
+FiniteElementData<dim>::get_first_quad_index(const unsigned int quad_no) const
+{
+  if (first_index_of_quads.size() == 1)
+    return first_index_of_quads[0] + quad_no * n_dofs_per_quad(0);
+  else
+    return first_index_of_quads[quad_no];
+}
+
+template <int dim>
+unsigned int
+FiniteElementData<dim>::get_first_hex_index() const
+{
+  return first_hex_index;
+}
+
+template <int dim>
+unsigned int
+FiniteElementData<dim>::get_first_face_line_index(
+  const unsigned int face_no) const
+{
+  return first_line_index_of_faces[first_line_index_of_faces.size() == 1 ?
+                                     0 :
+                                     face_no];
+}
+
+template <int dim>
+unsigned int
+FiniteElementData<dim>::get_first_face_quad_index(
+  const unsigned int face_no) const
+{
+  return first_quad_index_of_faces[first_quad_index_of_faces.size() == 1 ?
+                                     0 :
+                                     face_no];
+}
+
+template <int dim>
+internal::GenericDoFsPerObject
+internal::GenericDoFsPerObject::generate(const FiniteElementData<dim> &fe)
+{
+  const auto reference_cell = fe.reference_cell();
+
+  internal::GenericDoFsPerObject result;
+
+  result.dofs_per_object_exclusive.resize(4);
+  result.dofs_per_object_inclusive.resize(4);
+  result.object_index.resize(4);
+
+  unsigned int counter = 0;
+
+  for (unsigned int v : reference_cell.vertex_indices())
+    {
+      const auto c = fe.template n_dofs_per_object<0>(v);
+
+      result.dofs_per_object_exclusive[0].emplace_back(c);
+      result.dofs_per_object_inclusive[0].emplace_back(c);
+      result.object_index[0].emplace_back(counter);
+
+      counter += c;
+    }
+
+  if (dim >= 2)
+    for (unsigned int l : reference_cell.line_indices())
+      {
+        const auto c = fe.template n_dofs_per_object<1>(l);
+
+        result.dofs_per_object_exclusive[1].emplace_back(c);
+        result.dofs_per_object_inclusive[1].emplace_back(
+          c + 2 * fe.template n_dofs_per_object<0>());
+        result.object_index[1].emplace_back(counter);
+
+        counter += c;
+      }
+
+  if (dim == 3)
+    for (unsigned int f : reference_cell.face_indices())
+      {
+        const auto c = fe.template n_dofs_per_object<2>(f);
+
+        result.dofs_per_object_exclusive[2].emplace_back(c);
+        result.dofs_per_object_inclusive[2].emplace_back(fe.n_dofs_per_face(f));
+        result.object_index[2].emplace_back(counter);
+
+        counter += c;
+      }
+
+  {
+    const auto c = fe.template n_dofs_per_object<dim>();
+
+    result.dofs_per_object_exclusive[dim].emplace_back(c);
+    result.dofs_per_object_inclusive[dim].emplace_back(fe.n_dofs_per_cell());
+    result.object_index[dim].emplace_back(counter);
+
+    counter += c;
+  }
+
+  for (unsigned int d = dim + 1; d <= 3; ++d)
+    {
+      result.dofs_per_object_exclusive[d].emplace_back(0);
+      result.dofs_per_object_inclusive[d].emplace_back(0);
+      result.object_index[d].emplace_back(counter);
+    }
+
+  result.first_object_index_on_face.resize(3);
+  for (unsigned int face_no : reference_cell.face_indices())
+    {
+      result.first_object_index_on_face[0].emplace_back(0);
+
+      result.first_object_index_on_face[1].emplace_back(
+        fe.get_first_face_line_index(face_no));
+
+      result.first_object_index_on_face[2].emplace_back(
+        fe.get_first_face_quad_index(face_no));
+    }
+
+  return result;
+}
+
+
+#endif // DOXYGEN
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
index 89d0c690b7984e63528d9a7a8465da5e1499d5da..bf8632abdae9b3ebc1c7d5c6458b1ad8e31f46ec 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <deal.II/base/polynomials_rannacher_turek.h>
 
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_poly.h>
 
 #include <string>
index 448a5eba2e3b0bf039c833f8703e36f6031f02ba..b3d059d088ffe4238bbf059988fb5bc6a19ec86e 100644 (file)
@@ -29,7 +29,7 @@
 #include <deal.II/dofs/dof_renumbering.h>
 #include <deal.II/dofs/dof_tools.h>
 
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_nedelec.h>
 #include <deal.II/fe/fe_q.h>
 #include <deal.II/fe/fe_system.h>
index f9d9cf893f4e810656edffbeb82a044357971029..8682a9a80464cab41beaf04482f8fd98008cc15b 100644 (file)
@@ -33,7 +33,7 @@
 #include <deal.II/dofs/dof_renumbering.h>
 #include <deal.II/dofs/dof_tools.h>
 
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_nedelec.h>
 #include <deal.II/fe/fe_q.h>
 #include <deal.II/fe/fe_system.h>
index 9d98007dbc1ebc65e21d00711121a6fdda7bce8f..65cc6f405f2af2bd8d08b17aea507079961c342d 100644 (file)
@@ -27,7 +27,7 @@
 #include <deal.II/dofs/dof_renumbering.h>
 #include <deal.II/dofs/dof_tools.h>
 
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_nedelec.h>
 #include <deal.II/fe/fe_q.h>
 #include <deal.II/fe/fe_system.h>
index fe6bdf5493f86999efd98ee8bbafa428494a9b88..8ca10995a2032f69787a3fedceb69bf53ff29b81 100644 (file)
@@ -24,7 +24,7 @@
 #include <deal.II/dofs/dof_tools.h>
 
 #include <deal.II/fe/fe.h>
-#include <deal.II/fe/fe_base.h>
+#include <deal.II/fe/fe_data.h>
 #include <deal.II/fe/fe_interface_values.h>
 #include <deal.II/fe/fe_tools.h>
 #include <deal.II/fe/fe_values.h>

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.