* This class implements the <i>H<sup>div</sup></i>-conforming,
* Raviart-Thomas polynomials as described in the book by Brezzi and Fortin.
* Most of the functionality comes from the vector-valued anisotropic
- * polynomials class .
+ * polynomials class PolynomialsVectorAnisotropic.
*
* The Raviart-Thomas polynomials are constructed such that the divergence is
* in the tensor product polynomial space <i>Q<sub>k</sub></i>. Therefore, the
class PolynomialsRaviartThomas : public PolynomialsVectorAnisotropic<dim>
{
public:
- /**
- * Constructor. Creates all basis functions for Raviart-Thomas polynomials
- * of given degree in normal and tangential directions. The usual
- * FE_RaviartThomas and FE_RaviartThomasNodal classes will use `degree + 1`
- * and `degree` in the two directions, respectively.
- */
- PolynomialsRaviartThomas(const unsigned int degree_normal,
- const unsigned int degree_tangential);
-
/**
* Constructor, using the common Raviart-Thomas space of degree `k + 1` in
* normal direction and `k` in the tangential directions.
*/
PolynomialsRaviartThomas(const unsigned int k);
- /**
- * Copy constructor.
- */
- PolynomialsRaviartThomas(const PolynomialsRaviartThomas &other) = default;
-
- /**
- * Return the number of polynomials in the space without requiring to
- * build an object of PolynomialsRaviartThomas. This is required by the
- * FiniteElement classes.
- */
- static unsigned int
- n_polynomials(const unsigned int normal_degree,
- const unsigned int tangential_degree);
-
/**
* Variant of the n_polynomials() function taking only a single argument
* `degree`, assuming `degree + 1` in the normal direction and `degree` in
static unsigned int
n_polynomials(const unsigned int degree);
+ // Make respective two-argument method from base class available
+ using PolynomialsVectorAnisotropic<dim>::n_polynomials;
+
/**
* Compute the lexicographic to hierarchic numbering underlying this class,
* computed as a free function.
*/
static std::vector<unsigned int>
- get_lexicographic_numbering(const unsigned int normal_degree,
- const unsigned int tangential_degree);
+ get_lexicographic_numbering(const unsigned int degree);
/**
* @copydoc TensorPolynomialsBase::clone()
lexicographic_numbering =
PolynomialsRaviartThomas<dim>::get_lexicographic_numbering(
- fe_in.degree, fe_in.degree - 1);
+ fe_in.degree - 1);
// To get the right shape_values of the RT element
std::vector<unsigned int> lex_normal, lex_tangent;
-template <int dim>
-PolynomialsRaviartThomas<dim>::PolynomialsRaviartThomas(
- const unsigned int normal_degree,
- const unsigned int tangential_degree)
- : PolynomialsVectorAnisotropic<dim>(
- normal_degree,
- tangential_degree,
- get_lexicographic_numbering(normal_degree, tangential_degree))
-{}
-
-
-
template <int dim>
PolynomialsRaviartThomas<dim>::PolynomialsRaviartThomas(const unsigned int k)
- : PolynomialsRaviartThomas(k + 1, k)
+ : PolynomialsVectorAnisotropic<dim>(k + 1, k, get_lexicographic_numbering(k))
{}
-template <int dim>
-unsigned int
-PolynomialsRaviartThomas<dim>::n_polynomials(
- const unsigned int normal_degree,
- const unsigned int tangential_degree)
-{
- return PolynomialsVectorAnisotropic<dim>::n_polynomials(normal_degree,
- tangential_degree);
-}
-
-
-
template <int dim>
unsigned int
PolynomialsRaviartThomas<dim>::n_polynomials(const unsigned int degree)
template <int dim>
std::vector<unsigned int>
PolynomialsRaviartThomas<dim>::get_lexicographic_numbering(
- const unsigned int normal_degree,
- const unsigned int tangential_degree)
+ const unsigned int degree)
{
- const unsigned int n_dofs_face =
- Utilities::pow(tangential_degree + 1, dim - 1);
+ const unsigned int n_dofs_face = Utilities::pow(degree + 1, dim - 1);
std::vector<unsigned int> lexicographic_numbering;
+
// component 1
for (unsigned int j = 0; j < n_dofs_face; ++j)
{
lexicographic_numbering.push_back(j);
- if (normal_degree > 1)
- for (unsigned int i = n_dofs_face * 2 * dim;
- i < n_dofs_face * 2 * dim + normal_degree - 1;
- ++i)
- lexicographic_numbering.push_back(i + j * (normal_degree - 1));
+ for (unsigned int i = n_dofs_face * 2 * dim;
+ i < n_dofs_face * 2 * dim + degree;
+ ++i)
+ lexicographic_numbering.push_back(i + j * degree);
lexicographic_numbering.push_back(n_dofs_face + j);
}
// component 2
- unsigned int layers = (dim == 3) ? tangential_degree + 1 : 1;
+ unsigned int layers = (dim == 3) ? degree + 1 : 1;
for (unsigned int k = 0; k < layers; ++k)
{
- unsigned int k_add = k * (tangential_degree + 1);
- for (unsigned int j = n_dofs_face * 2;
- j < n_dofs_face * 2 + tangential_degree + 1;
+ unsigned int k_add = k * (degree + 1);
+ for (unsigned int j = n_dofs_face * 2; j < n_dofs_face * 2 + degree + 1;
++j)
lexicographic_numbering.push_back(j + k_add);
- if (normal_degree > 1)
- for (unsigned int i = n_dofs_face * (2 * dim + (normal_degree - 1));
- i < n_dofs_face * (2 * dim + (normal_degree - 1)) +
- (normal_degree - 1) * (tangential_degree + 1);
- ++i)
- {
- lexicographic_numbering.push_back(i + k_add * tangential_degree);
- }
- for (unsigned int j = n_dofs_face * 3;
- j < n_dofs_face * 3 + tangential_degree + 1;
+ for (unsigned int i = n_dofs_face * (2 * dim + degree);
+ i < n_dofs_face * (2 * dim + degree) + degree * (degree + 1);
+ ++i)
+ lexicographic_numbering.push_back(i + k_add * degree);
+ for (unsigned int j = n_dofs_face * 3; j < n_dofs_face * 3 + degree + 1;
++j)
lexicographic_numbering.push_back(j + k_add);
}
{
for (unsigned int i = 4 * n_dofs_face; i < 5 * n_dofs_face; ++i)
lexicographic_numbering.push_back(i);
- if (normal_degree > 1)
- for (unsigned int i =
- 6 * n_dofs_face + n_dofs_face * 2 * (normal_degree - 1);
- i < 6 * n_dofs_face + n_dofs_face * 3 * (normal_degree - 1);
- ++i)
- lexicographic_numbering.push_back(i);
+ for (unsigned int i = 6 * n_dofs_face + n_dofs_face * 2 * degree;
+ i < 6 * n_dofs_face + n_dofs_face * 3 * degree;
+ ++i)
+ lexicographic_numbering.push_back(i);
for (unsigned int i = 5 * n_dofs_face; i < 6 * n_dofs_face; ++i)
lexicographic_numbering.push_back(i);
}
template <int dim>
FE_RaviartThomas<dim>::FE_RaviartThomas(const unsigned int deg)
: FE_PolyTensor<dim>(
- PolynomialsRaviartThomas<dim>(deg + 1, deg),
+ PolynomialsRaviartThomas<dim>(deg),
FiniteElementData<dim>(get_dpo_vector(deg),
dim,
deg + 1,
FiniteElementData<dim>::Hdiv),
- std::vector<bool>(PolynomialsRaviartThomas<dim>::n_polynomials(deg + 1,
- deg),
+ std::vector<bool>(PolynomialsRaviartThomas<dim>::n_polynomials(deg),
true),
- std::vector<ComponentMask>(
- PolynomialsRaviartThomas<dim>::n_polynomials(deg + 1, deg),
- ComponentMask(std::vector<bool>(dim, true))))
+ std::vector<ComponentMask>(PolynomialsRaviartThomas<dim>::n_polynomials(
+ deg),
+ ComponentMask(std::vector<bool>(dim, true))))
{
Assert(dim >= 2, ExcImpossibleInDim(dim));
const unsigned int n_dofs = this->n_dofs_per_cell();
template <int dim>
FE_RaviartThomasNodal<dim>::FE_RaviartThomasNodal(const unsigned int degree)
- : FE_PolyTensor<dim>(
- PolynomialsRaviartThomas<dim>(degree + 1, degree),
- FiniteElementData<dim>(get_rt_dpo_vector(dim, degree),
- dim,
- degree + 1,
- FiniteElementData<dim>::Hdiv),
- std::vector<bool>(1, false),
- std::vector<ComponentMask>(
- PolynomialsRaviartThomas<dim>::n_polynomials(degree + 1, degree),
- ComponentMask(std::vector<bool>(dim, true))))
+ : FE_PolyTensor<dim>(PolynomialsRaviartThomas<dim>(degree),
+ FiniteElementData<dim>(get_rt_dpo_vector(dim, degree),
+ dim,
+ degree + 1,
+ FiniteElementData<dim>::Hdiv),
+ std::vector<bool>(1, false),
+ std::vector<ComponentMask>(
+ PolynomialsRaviartThomas<dim>::n_polynomials(degree),
+ ComponentMask(std::vector<bool>(dim, true))))
{
Assert(dim >= 2, ExcImpossibleInDim(dim));
// First, initialize the generalized support points and quadrature weights,
// since they are required for interpolation.
this->generalized_support_points =
- PolynomialsRaviartThomas<dim>(degree + 1, degree)
- .get_polynomial_support_points();
+ PolynomialsRaviartThomas<dim>(degree).get_polynomial_support_points();
AssertDimension(this->generalized_support_points.size(),
this->n_dofs_per_cell());