1#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_TEST_ENABLEDIFFERENTIABILITYCHECK_HH
2#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_TEST_ENABLEDIFFERENTIABILITYCHECK_HH
8#include <dune/common/test/testsuite.hh>
9#include <dune/common/transpose.hh>
13#include <dune/typetree/traversal.hh>
15template <
class Element,
class Gr
idView>
16std::string elementStr(
const Element &element,
const GridView &gridView);
24struct EnableDifferentiabilityCheck
26 std::size_t order_ = 5;
28 std::string checkLocation =
"across";
30 template <
class JumpEvaluator,
class QuadRuleFactoryMethod>
31 auto localJumpDifferentiabilityCheck(
const JumpEvaluator &jumpEvaluator,
32 const QuadRuleFactoryMethod &quadRuleFactoryMethod,
33 std::size_t order,
double tol)
const
35 return [=](
const auto &intersection,
const auto &
treePath,
const auto &insideNode,
36 const auto &outsideNode,
const auto &insideToOutside)
39 using Node = std::decay_t<
decltype(insideNode)>;
41 std::vector<int> isDifferentiable(insideNode.size(),
true);
42 const auto &quadRule = quadRuleFactoryMethod(intersection, order);
46 typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;
47 std::vector<std::vector<JacobiRange>> insideValues;
48 std::vector<std::vector<JacobiRange>> outsideValues;
51 insideValues.resize(quadRule.size());
52 outsideValues.resize(quadRule.size());
54 std::size_t insideNodeSize = insideNode.finiteElement().localBasis().size();
55 std::size_t outsideNodeSize = outsideNode.finiteElement().localBasis().size();
57 for (std::size_t k = 0; k < quadRule.size(); ++k)
59 std::vector<JacobiRange> insideLocalJacobians, outsideLocalJacobians;
61 insideLocalJacobians.resize(insideNodeSize);
62 outsideLocalJacobians.resize(outsideNodeSize);
63 insideValues[k].resize(insideNodeSize);
64 outsideValues[k].resize(outsideNodeSize);
66 auto insidePoint = intersection.geometryInInside().global(quadRule[k].position());
67 auto outsidePoint = intersection.geometryInOutside().global(quadRule[k].position());
68 insideNode.finiteElement().localBasis().evaluateJacobian(insidePoint,
69 insideLocalJacobians);
70 outsideNode.finiteElement().localBasis().evaluateJacobian(outsidePoint,
71 outsideLocalJacobians);
72 auto insideJacobiInverseTransposed
73 = intersection.inside().geometry().jacobianInverseTransposed(insidePoint);
74 auto outsideJacobiInverseTransposed
75 = intersection.outside().geometry().jacobianInverseTransposed(outsidePoint);
76 for (std::size_t i = 0; i < insideNodeSize; ++i)
79 insideValues[k][i] = insideLocalJacobians[i] *
transpose(insideJacobiInverseTransposed);
80 if (i < outsideNodeSize)
82 = outsideLocalJacobians[i] *
transpose(outsideJacobiInverseTransposed);
87 for (std::size_t i = 0; i < insideNode.size(); ++i)
89 for (std::size_t k = 0; k < quadRule.size(); ++k)
91 auto jump = insideValues[k][i];
92 if (insideToOutside[i].has_value())
93 jump -= outsideValues[k][insideToOutside[i].value()];
94 isDifferentiable[i] = isDifferentiable[i]
95 and (jumpEvaluator(jump, intersection, quadRule[k].position()) < tol);
98 for (std::size_t k = 0; k < quadRule.size(); ++k)
100 insideValues[k].clear();
101 outsideValues[k].clear();
103 return isDifferentiable;
107 auto localDifferentiabilityCheck()
const
109 auto jumpNorm = [](
auto &&jump,
auto &&intersection,
auto &&x) ->
double
110 {
return jump.infinity_norm(); };
112 auto quadRuleProvider = [](
auto &&intersection,
auto &&order)
114 return Dune::QuadratureRules<double, std::decay_t<
decltype(intersection)>::mydimension>::rule(intersection.type(),
118 return localJumpDifferentiabilityCheck(jumpNorm, quadRuleProvider, order_, tol_);
122struct EnableVertexDifferentiabilityCheck:
public EnableDifferentiabilityCheck
124 std::size_t order_ = 5;
126 std::string checkLocation =
"at vertices of";
128 auto localDifferentiabilityCheck()
const
130 auto jumpNorm = [](
auto &&jump,
auto &&intersection,
auto &&x) ->
double
131 {
return jump.infinity_norm(); };
133 auto quadRuleProvider = [](
auto &&intersection,
auto &&order)
136 std::vector<Pt> quadRule;
137 for (
int i = 0; i < intersection.geometry().corners(); ++i)
139 Pt{intersection.geometry().local(intersection.geometry().corner(i)), 1.});
143 return localJumpDifferentiabilityCheck(jumpNorm, quadRuleProvider, order_, tol_);
147struct EnableNormalDifferentiabilityAtMidpointsCheck:
public EnableDifferentiabilityCheck
149 std::size_t order_ = 5;
151 std::string checkLocation =
"at edge midpoint of";
153 auto localDifferentiabilityCheck()
const
155 auto jumpNorm = [](
auto &&jump,
auto &&intersection,
auto &&x) ->
double
158 jump.mv(intersection.unitOuterNormal(x), res);
162 auto quadRuleProvider = [](
auto &&intersection,
auto &&order)
165 std::vector<Pt> quadRule;
167 quadRule.push_back(Pt{intersection.geometry().local(intersection.geometry().center()), 1.});
171 return localJumpDifferentiabilityCheck(jumpNorm, quadRuleProvider, order_, tol_);
186template <
class Basis,
class Flag>
187Dune::TestSuite checkBasisDifferentiability(
const Basis &basis,
const Flag &flag)
189 Dune::TestSuite test(
"Global differentiability check of basis functions");
191 auto const &localCheck = flag.localDifferentiabilityCheck();
193 auto localView = basis.localView();
194 auto neighborLocalView = basis.localView();
196 for (
const auto &e :
elements(basis.gridView()))
199 for (
const auto &intersection :
intersections(basis.gridView(), e))
201 if (intersection.neighbor())
203 neighborLocalView.bind(intersection.outside());
207 [&](
const auto &insideNode,
auto &&
treePath)
209 const auto &outsideNode = Dune::TypeTree::child(neighborLocalView.tree(), treePath);
211 std::vector<std::optional<int>> insideToOutside;
212 insideToOutside.resize(insideNode.size());
215 for (std::size_t i = 0; i < insideNode.size(); ++i)
217 for (std::size_t j = 0; j < outsideNode.size(); ++j)
219 if (localView.index(insideNode.localIndex(i))
220 == neighborLocalView.index(outsideNode.localIndex(j)))
223 test.check(not insideToOutside[i].has_value())
224 <<
"Basis function " << localView.index(insideNode.localIndex(i))
225 <<
" appears twice in element "
226 << elementStr(neighborLocalView.element(), basis.gridView());
227 insideToOutside[i] = j;
234 auto isDifferentiable
235 = localCheck(intersection,
treePath, insideNode, outsideNode, insideToOutside);
237 for (std::size_t i = 0; i < insideNode.size(); ++i)
239 test.check(isDifferentiable[i])
240 <<
"Basis function " << localView.index(insideNode.localIndex(i))
241 <<
" is not differentiable " << flag.checkLocation
242 <<
" intersection of elements "
243 << elementStr(localView.element(), basis.gridView()) <<
" and "
244 << elementStr(neighborLocalView.element(), basis.gridView());
FieldTraits< vt >::real_type infinity_norm() const
infinity norm (maximum of absolute values of entries)
Definition: densevector.hh:661
vector space out of a tensor product of fields.
Definition: fvector.hh:91
Single evaluation point in a quadrature rule.
Definition: quadraturerules.hh:66
A container for all quadrature rules of dimension dim
Definition: quadraturerules.hh:260
A Simple helper class to organize your test suite.
Definition: testsuite.hh:31
IteratorRange<... > intersections(const GV &gv, const Entity &e)
Iterates over all Intersections of an Entity with respect to the given GridView.
IteratorRange<... > elements(const GV &gv)
Iterates over all elements / cells (entities with codimension 0) of a GridView.
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:326
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: traversal.hh:269
auto transpose(const Matrix &matrix)
Return the transposed of the given matrix.
Definition: transpose.hh:183