Fixes a conditional statement in FE_Nedelec::convert_...to_dof_values. Adds a new test function in tests/fe/interpolation_common.h for use in tests/fe/interpolation_nedelec.cc as the previous test case indicated (incorrectly) that the function returned correct DoF values.
--- /dev/null
+Bugfix: FE_Nedelec<2>::convert_generalized_support_point_values_to_dof_values()
+now works correctly for every degree.
+<br>
+(Jake Harmon, 2021/04/22)
{
// Let us begin with the
// interpolation part.
- const QGauss<dim - 1> reference_edge_quadrature(this->degree);
+ const QGauss<1> reference_edge_quadrature(this->degree);
const unsigned int n_edge_points = reference_edge_quadrature.size();
for (unsigned int i = 0; i < 2; ++i)
nodal_values[(i + 2 * j) * this->degree] = 0.0;
}
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof support_point_values
- // are obtained by solving
+ // If the Nedelec element degree is greater
+ // than 0 (i.e., the polynomial degree is greater than 1),
+ // then we have still some higher order edge
+ // shape functions to consider.
+ // Note that this->degree returns the polynomial
+ // degree.
+ // Here the projection part starts.
+ // The dof support_point_values are obtained by solving
// a linear system of
// equations.
- if (this->degree - 1 > 1)
+ if (this->degree > 1)
{
// We start with projection
// on the higher order edge
#include <deal.II/base/function.h>
+#include <deal.II/base/function_lib.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/fe/fe.h>
}
}
};
+
+
+// Local implementation of an alternative test function
+
+
+template <int dim, int degree, int COMP = 1>
+class PolynomialFunction : public Function<dim>
+{
+public:
+ PolynomialFunction()
+ : Function<dim>(COMP)
+ {
+ Table<2, double> exponents(degree, dim);
+ for (unsigned int i = 0; i < degree; ++i)
+ for (unsigned int d = 0; d < dim; ++d)
+ exponents[i][d] = i + d;
+ std::vector<double> coeffs(degree);
+ for (unsigned int i = 0; i < degree; ++i)
+ coeffs[i] = std::pow(-1.0, static_cast<double>(i)) * (i + 1);
+ poly = std::make_unique<Functions::Polynomial<dim>>(
+ Functions::Polynomial<dim>(exponents, coeffs));
+ }
+
+ double
+ value(const Point<dim> &p, const unsigned int c) const
+ {
+ return poly->value(p, 0) + c;
+ }
+
+ void
+ value_list(const std::vector<Point<dim>> &points,
+ std::vector<double> & values,
+ const unsigned int c) const
+ {
+ Assert(values.size() == points.size(),
+ ExcDimensionMismatch(values.size(), points.size()));
+
+ for (unsigned int i = 0; i < points.size(); ++i)
+ {
+ const Point<dim> &p = points[i];
+
+ values[i] = poly->value(p, 0) + c;
+ }
+ }
+
+ void
+ vector_value_list(const std::vector<Point<dim>> &points,
+ std::vector<Vector<double>> & values) const
+ {
+ Assert(values.size() == points.size(),
+ ExcDimensionMismatch(values.size(), points.size()));
+ Assert(values[0].size() == this->n_components,
+ ExcDimensionMismatch(values.size(), this->n_components));
+
+ for (unsigned int i = 0; i < points.size(); ++i)
+ {
+ const Point<dim> &p = points[i];
+ for (unsigned int c = 0; c < COMP; ++c)
+ values[i](c) = poly->value(p, 0);
+ }
+ }
+
+private:
+ std::unique_ptr<Functions::Polynomial<dim>> poly;
+};
#include "interpolate_common.h"
-
// FE_Nedelec<dim>::interpolate(...)
template <int dim>
Vector<double>(dim));
f.vector_value_list(fe.get_generalized_support_points(), values);
fe.convert_generalized_support_point_values_to_dof_values(values, dofs);
+
deallog << " vector " << vector_difference(fe, dofs, f, 0) << std::endl;
}
check1(w22, 2);
Q1WedgeFunction<2, 3, 2> w23;
check1(w23, 3);
+
+ PolynomialFunction<2, 1, 2> p21;
+ check1(p21, 1);
+ PolynomialFunction<2, 2, 2> p22;
+ check1(p22, 2);
+ PolynomialFunction<2, 3, 2> p23;
+ check1(p23, 3);
}
{
Q1WedgeFunction<3, 1, 3> w21;
check1(w21, 1);
check1(w21, 2);
+
+
+
// FIXME - higher order interpolation is currently broken
+ // PolynomialFunction<3, 1, 3> p21;
+ // check1(p21, 1);
// Q1WedgeFunction<3, 2, 3> w22;
// check1(w22, 2);
// Q1WedgeFunction<3, 3, 3> w23;
// check1(w23, 3);
+ // PolynomialFunction<3, 2, 3> p22;
+ // check1(p22, 2);
+ // PolynomialFunction<3, 3, 3> p23;
+ // check1(p23, 3);
}
}
-DEAL::FE_Nedelec<2>(0) 4 vector 0.00000
-DEAL::FE_Nedelec<2>(1) 12 vector 0.00000
+DEAL::FE_Nedelec<2>(0) 4 vector 2.77556e-17
+DEAL::FE_Nedelec<2>(1) 12 vector 1.38778e-17
DEAL::FE_Nedelec<2>(2) 21 vector 5.55112e-17
DEAL::FE_Nedelec<2>(2) 21 vector 1.11022e-16
-DEAL::FE_Nedelec<2>(2) 21 vector 1.58727e-16
-DEAL::FE_Nedelec<2>(3) 32 vector 1.17788e-15
-DEAL::FE_Nedelec<3>(1) 56 vector 5.55112e-17
-DEAL::FE_Nedelec<3>(2) 117 vector 1.11022e-16
+DEAL::FE_Nedelec<2>(2) 21 vector 2.81025e-16
+DEAL::FE_Nedelec<2>(3) 32 vector 7.56830e-16
+DEAL::FE_Nedelec<2>(1) 12 vector 5.55112e-17
+DEAL::FE_Nedelec<2>(2) 21 vector 4.44089e-16
+DEAL::FE_Nedelec<2>(3) 32 vector 1.60288e-15
+DEAL::FE_Nedelec<3>(1) 56 vector 2.77556e-17
+DEAL::FE_Nedelec<3>(2) 117 vector 1.66533e-16