*
* @author Wolfgang Bangerth, Guido Kanschat, 1998, 1999, 2000, 2001, 2003, 2005
*/
-template<int dim>
+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 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.
+ *
+ * The value <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.
+ *
+ * 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 = 0x06,
+/// Conformity with the space <i>H<sup>2</sup></i> (continuously differentiable)
+ H2 = 0x0e
+ };
+
/**
* Number of degrees of freedom on
* a vertex.
* coordinate direction.
*/
const unsigned int degree;
+
+ /**
+ * Indicate the space this element conforms to.
+ */
+ const Conformity conforming_space;
/**
* Default
*/
FiniteElementData (const std::vector<unsigned int> &dofs_per_object,
const unsigned int n_components,
- const unsigned int degree = deal_II_numbers::invalid_unsigned_int);
+ const unsigned int degree = deal_II_numbers::invalid_unsigned_int,
+ const Conformity conformity = unknown);
/**
* Number of dofs per vertex.
* 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<dim> &) const;
+ bool operator == (const FiniteElementData &) const;
};
}
+template <int dim>
+inline
+bool
+FiniteElementData<dim>::conforms (Conformity space) const
+{
+ return ((space & conforming_space) != 0);
+}
+
+//----------------------------------------------------------------------//
template <int dim>
inline
#include <fe/fe.h>
-template <int dim>
+template<int dim>
FiniteElementData<dim>::FiniteElementData ()
:
dofs_per_vertex(0),
dofs_per_face(0),
dofs_per_cell (0),
components(0),
- degree(0)
+ degree(0),
+ conforming_space(unknown)
{}
FiniteElementData<dim>::
FiniteElementData (const std::vector<unsigned int> &dofs_per_object,
const unsigned int n_components,
- const unsigned int degree)
+ const unsigned int degree,
+ const Conformity conformity)
:
dofs_per_vertex(dofs_per_object[0]),
dofs_per_line(dofs_per_object[1]),
GeometryInfo<dim>::quads_per_cell * dofs_per_quad +
GeometryInfo<dim>::hexes_per_cell * dofs_per_hex),
components(n_components),
- degree(degree)
+ degree(degree),
+ conforming_space(conformity)
{
Assert(dofs_per_object.size()==dim+1, ExcDimensionMismatch(dofs_per_object.size()-1,dim));
}
(dofs_per_line == f.dofs_per_line) &&
(dofs_per_quad == f.dofs_per_quad) &&
(dofs_per_hex == f.dofs_per_hex) &&
- (components == f.components));
+ (components == f.components) &&
+ (degree == f.degree) &&
+ (conforming_space == f.conforming_space));
}
:
FE_Poly<PolynomialSpace<dim>, dim> (
PolynomialSpace<dim>(Polynomials::Legendre::generate_complete_basis(degree)),
- FiniteElementData<dim>(get_dpo_vector(degree), 1, degree),
+ FiniteElementData<dim>(get_dpo_vector(degree), 1, degree, FiniteElementData<dim>::L2),
std::vector<bool>(FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,true),
std::vector<std::vector<bool> >(FiniteElementData<dim>(
get_dpo_vector(degree), 1, degree).dofs_per_cell, std::vector<bool>(1,true)))
:
FE_Poly<PolynomialsP<dim>, dim> (
PolynomialsP<dim>(degree),
- FiniteElementData<dim>(get_dpo_vector(degree), 1, degree),
+ FiniteElementData<dim>(get_dpo_vector(degree), 1, degree, FiniteElementData<dim>::L2),
std::vector<bool>(FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,true),
std::vector<std::vector<bool> >(FiniteElementData<dim>(
get_dpo_vector(degree), 1, degree).dofs_per_cell, std::vector<bool>(1,true)))
template <int dim>
FE_DGPNonparametric<dim>::FE_DGPNonparametric (const unsigned int degree)
:
- FiniteElement<dim> (FiniteElementData<dim>(get_dpo_vector(degree),1),
+ FiniteElement<dim> (FiniteElementData<dim>(get_dpo_vector(degree),1, FiniteElementData<dim>::L2),
std::vector<bool>(FiniteElementData<dim>(get_dpo_vector(degree),1).dofs_per_cell,true),
std::vector<std::vector<bool> >(FiniteElementData<dim>(get_dpo_vector(degree),1).dofs_per_cell,
std::vector<bool>(1,true))),
:
FE_Poly<TensorProductPolynomials<dim>, dim> (
TensorProductPolynomials<dim>(Polynomials::LagrangeEquidistant::generate_complete_basis(degree)),
- FiniteElementData<dim>(get_dpo_vector(degree), 1, degree),
+ FiniteElementData<dim>(get_dpo_vector(degree), 1, degree, FiniteElementData<dim>::L2),
std::vector<bool>(FiniteElementData<dim>(get_dpo_vector(degree),1, degree).dofs_per_cell, true),
std::vector<std::vector<bool> >(FiniteElementData<dim>(
get_dpo_vector(degree),1, degree).dofs_per_cell, std::vector<bool>(1,true)))
#endif
+
+//TODO: Remove doubled degrees
template <int dim>
FE_Nedelec<dim>::FE_Nedelec (const unsigned int degree)
:
- FiniteElement<dim> (FiniteElementData<dim>(get_dpo_vector(degree),
- dim),
+ FiniteElement<dim> (FiniteElementData<dim>(get_dpo_vector(degree), dim, degree+1, FiniteElementData<dim>::Hcurl),
std::vector<bool> (FiniteElementData<dim>(get_dpo_vector(degree),dim).dofs_per_cell,false),
std::vector<std::vector<bool> >(FiniteElementData<dim>(get_dpo_vector(degree),dim).dofs_per_cell,
std::vector<bool>(dim,true))),
:
FE_Poly<TensorProductPolynomials<dim>, dim> (
TensorProductPolynomials<dim>(Polynomials::LagrangeEquidistant::generate_complete_basis(degree)),
- FiniteElementData<dim>(get_dpo_vector(degree),1, degree),
+ FiniteElementData<dim>(get_dpo_vector(degree),1, degree, FiniteElementData<dim>::H1),
std::vector<bool> (FiniteElementData<dim>(
get_dpo_vector(degree),1, degree).dofs_per_cell, false),
std::vector<std::vector<bool> >(FiniteElementData<dim>(
:
FE_Poly<TensorProductPolynomials<dim>, dim> (
Polynomials::Hierarchical::generate_complete_basis(degree),
- FiniteElementData<dim>(get_dpo_vector(degree),1, degree),
+ FiniteElementData<dim>(get_dpo_vector(degree),1, degree, FiniteElementData<dim>::H1),
std::vector<bool> (FiniteElementData<dim>(
get_dpo_vector(degree),1, degree).dofs_per_cell, false),
std::vector<std::vector<bool> >(FiniteElementData<dim>(
FE_RaviartThomas<dim>::FE_RaviartThomas (const unsigned int rt_order)
:
FiniteElement<dim> (FiniteElementData<dim>(get_dpo_vector(rt_order),
- dim, rt_order+1),
+ dim, rt_order+1, FiniteElementData<dim>::Hdiv),
get_ria_vector (rt_order),
std::vector<std::vector<bool> >(FiniteElementData<dim>(get_dpo_vector(rt_order),dim,rt_order+1).dofs_per_cell,
std::vector<bool>(dim,true))),
FE_PolyTensor<PolynomialsRaviartThomas<dim>, dim> (
deg,
FiniteElementData<dim>(get_dpo_vector(deg),
- dim, deg+1),
+ dim, deg+1, FiniteElementData<dim>::Hdiv),
get_ria_vector (deg),
std::vector<std::vector<bool> >(
FiniteElementData<dim>(get_dpo_vector(deg),
N(current,i) = this->shape_value_component(
i, this->unit_support_points[current],
GeometryInfo< dim >::unit_normal_direction[face]);
-// * GeometryInfo< dim >::unit_normal_orientation[face];
++current;
}
// Interior degrees of freedom in each direction
if (dim>1) dpo.push_back(fe_data.dofs_per_quad * N);
if (dim>2) dpo.push_back(fe_data.dofs_per_hex * N);
- return FiniteElementData<dim> (dpo, fe_data.n_components() * N, fe_data.tensor_degree());
+ return FiniteElementData<dim> (dpo, fe_data.n_components() * N, fe_data.tensor_degree(),
+ fe_data.conforming_space);
}
return FiniteElementData<dim> (dpo,
fe1.n_components() * N1 +
fe2.n_components() * N2,
- degree);
+ degree,
+ FiniteElementData<dim>::Conformity(fe1.conforming_space
+ & fe2.conforming_space));
}
return FiniteElementData<dim> (dpo,
fe1.n_components() * N1 +
fe2.n_components() * N2 +
- fe3.n_components() * N3, degree);
+ fe3.n_components() * N3, degree,
+ FiniteElementData<dim>::Conformity(fe1.conforming_space
+ & fe2.conforming_space
+ & fe3.conforming_space));
}