9#ifndef DUNE_LOCALFUNCTIONS_TEST_TEST_FE_HH
10#define DUNE_LOCALFUNCTIONS_TEST_TEST_FE_HH
37 using RangeType =
typename FE::Traits::Basis::Traits::Range;
38 using DomainType =
typename FE::Traits::Basis::Traits::DomainLocal;
41 using RangeType =
typename FE::Traits::Basis::Traits::Range;
42 using DomainType =
typename FE::Traits::Basis::Traits::DomainLocal;
45 typedef typename FE::Traits::Basis::Traits::RangeField CT;
47 std::vector<CT> coeff;
49 FEFunction(
const FE& fe_) : fe(fe_) { resetCoefficients(); }
51 void resetCoefficients() {
52 coeff.resize(fe.basis().size());
53 for(std::size_t i=0; i<coeff.size(); ++i)
57 void setRandom(
double max) {
58 coeff.resize(fe.basis().size());
59 for(std::size_t i=0; i<coeff.size(); ++i)
60 coeff[i] = ((1.0*std::rand()) / RAND_MAX - 0.5)*2.0*
max;
63 void evaluate (
const DomainType& x, RangeType& y)
const {
64 std::vector<RangeType> yy;
65 fe.basis().evaluateFunction(x, yy);
67 for (std::size_t i=0; i<yy.size(); ++i)
68 y.axpy(coeff[i], yy[i]);
86bool testInterpolation(
const FE& fe,
double eps,
int n=5)
91 std::vector<typename FEFunction<FE>::CT> coeff;
92 std::vector<typename FEFunction<FE>::CT> coeff2;
93 for(
int i=0; i<n && success; ++i) {
104 fe.interpolation().interpolate(f, coeff);
110 auto callableF = [&](
const auto& x) {
111 using Range =
typename FE::Traits::Basis::Traits::Range;
116 fe.interpolation().interpolate(callableF, coeff2);
117 if (coeff != coeff2) {
118 std::cout <<
"Passing callable and function with evaluate yields different "
119 <<
"interpolation weights for finite element type "
120 << Dune::className<FE>() <<
":" << std::endl;
125 if (coeff.size() != fe.basis().size()) {
126 std::cout <<
"Bug in LocalInterpolation for finite element type "
127 << Dune::className<FE>() <<
":" << std::endl;
128 std::cout <<
" Interpolation vector has size " << coeff.size()
130 std::cout <<
" Basis has size " << fe.basis().size() << std::endl;
131 std::cout << std::endl;
139 for(std::size_t j=0; j<coeff.size() && success; ++j) {
140 if ( std::abs(coeff[j]-f.coeff[j]) >
141 eps*(
std::max(std::abs(f.coeff[j]), 1.0)) )
143 std::cout << std::setprecision(16);
144 std::cout <<
"Bug in LocalInterpolation for finite element type "
145 << Dune::className<FE>() <<
":" << std::endl;
146 std::cout <<
" Interpolation weight " << j <<
" differs by "
147 << std::abs(coeff[j]-f.coeff[j]) <<
" from coefficient of "
148 <<
"linear combination." << std::endl;
149 std::cout << std::endl;
169template<
class Geo,
class FE>
170bool testJacobian(
const Geo &geo,
const FE& fe,
double eps,
double delta,
171 std::size_t order = 2)
173 typedef typename FE::Traits::Basis Basis;
175 typedef typename Basis::Traits::DomainField DF;
176 static const std::size_t dimDLocal = Basis::Traits::dimDomainLocal;
177 typedef typename Basis::Traits::DomainLocal DomainLocal;
178 static const std::size_t dimDGlobal = Basis::Traits::dimDomainGlobal;
180 static const std::size_t dimR = Basis::Traits::dimRange;
181 typedef typename Basis::Traits::Range Range;
183 typedef typename Basis::Traits::Jacobian Jacobian;
197 for (std::size_t i=0; i < quad.size(); i++) {
200 const DomainLocal& testPoint = quad[i].position();
203 std::vector<Jacobian> jacobians;
204 fe.basis().evaluateJacobian(testPoint, jacobians);
205 if(jacobians.size() != fe.basis().size()) {
206 std::cout <<
"Bug in evaluateJacobianGlobal() for finite element type "
207 << Dune::className<FE>() <<
":" << std::endl;
208 std::cout <<
" Jacobian vector has size " << jacobians.size()
210 std::cout <<
" Basis has size " << fe.basis().size() << std::endl;
211 std::cout << std::endl;
216 geo.jacobianTransposed(testPoint);
219 for (std::size_t j=0; j<fe.basis().size(); ++j) {
225 for(std::size_t k = 0; k < dimR; ++k)
226 for(std::size_t l = 0; l < dimDGlobal; ++l)
227 for(std::size_t m = 0; m < dimDLocal; ++m)
228 localJacobian[k][m] += jacobians[j][k][l] * geoJT[m][l];
231 for (std::size_t m = 0; m < dimDLocal; ++m) {
234 DomainLocal upPos = testPoint;
235 DomainLocal downPos = testPoint;
240 std::vector<Range> upValues, downValues;
242 fe.basis().evaluateFunction(upPos, upValues);
243 fe.basis().evaluateFunction(downPos, downValues);
246 for(std::size_t k = 0; k < dimR; ++k) {
251 double finiteDiff = (upValues[j][k] - downValues[j][k]) / (2*delta);
255 eps/delta*(
std::max(std::abs(finiteDiff), 1.0)) )
257 std::cout << std::setprecision(16);
258 std::cout <<
"Bug in evaluateJacobian() for finite element type "
259 << Dune::className<FE>() <<
":" << std::endl;
260 std::cout <<
" Shape function derivative does not agree with "
261 <<
"FD approximation" << std::endl;
262 std::cout <<
" Shape function " << j <<
" component " << k
263 <<
" at position " << testPoint <<
": derivative in "
264 <<
"local direction " << m <<
" is "
265 <<
derivative <<
", but " << finiteDiff <<
" is "
266 <<
"expected." << std::endl;
267 std::cout << std::endl;
279template<
class Geo,
class FE>
280bool testFE(
const Geo &geo,
const FE& fe,
double eps,
double delta,
285 success = testInterpolation(fe, eps) and success;
286 success = testJacobian(geo, fe, eps, delta, order) and success;
A dense n x m matrix.
Definition: fmatrix.hh:69
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:152
static const QuadratureRule & rule(const GeometryType &t, int p, QuadratureType::Enum qt=QuadratureType::GaussLegendre)
select the appropriate QuadratureRule for GeometryType t and order p
Definition: quadraturerules.hh:280
A free function to provide the demangled class name of a given object or type as a string.
Implements a matrix constructed from a given type representing a field and compile-time given number ...
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:39
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79