Loading [MathJax]/extensions/tex2jax.js

DUNE PDELab (unstable)

test-localfe.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
6#define DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
7
16#include <iomanip>
17#include <iostream>
18#include <typeinfo>
19
22#include <dune/geometry/referenceelements.hh>
23
24#include <dune/localfunctions/common/virtualinterface.hh>
25#include <dune/localfunctions/common/virtualwrappers.hh>
26#include <dune/localfunctions/common/localfiniteelement.hh>
27
28double TOL = 1e-9;
29// The FD approximation used for checking the Jacobian uses half of the
30// precision -- so we have to be a little bit more tolerant here.
31double jacobianTOL = 1e-5; // sqrt(TOL)
32
33// This class wraps one shape function of a local finite element as a callable
34// that can be fed to the LocalInterpolation::interpolate method.
35template<class FE>
36class ShapeFunctionAsCallable
37{
38 // These types are deliberately private: They are not part of a Callable API
39 typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType;
40 typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType;
41public:
42
43 typedef typename FE::Traits::LocalBasisType::Traits::RangeFieldType CT;
44
45 ShapeFunctionAsCallable(const FE& fe, int shapeFunction) :
46 fe_(fe),
47 shapeFunction_(shapeFunction)
48 {}
49
50 RangeType operator() (DomainType x) const
51 {
52 std::vector<RangeType> yy;
53 fe_.localBasis().evaluateFunction(x, yy);
54 return yy[shapeFunction_];
55 }
56
57private:
58 const FE& fe_;
59 int shapeFunction_;
60};
61
62
63// Check whether the degrees of freedom computed by LocalInterpolation
64// are dual to the shape functions. See Ciarlet, "The Finite Element Method
65// for Elliptic Problems", 1978, for details.
66template<class FE>
67bool testLocalInterpolation(const FE& fe)
68{
69 using std::abs;
70 std::vector<typename ShapeFunctionAsCallable<FE>::CT> coeff;
71 for(size_t i=0; i<fe.size(); ++i)
72 {
74 // Feed the shape functions to the 'interpolate' method in form of a callable.
76
77 // The i-th shape function as a function that 'interpolate' can deal with
78 ShapeFunctionAsCallable<FE> sfAsCallable(fe, i);
79
80 // Compute degrees of freedom for that shape function
81 // We expect the result to be the i-th unit vector
82 fe.localInterpolation().interpolate(sfAsCallable, coeff);
83
84 // Check size of weight vector
85 if (coeff.size() != fe.localBasis().size())
86 {
87 std::cout << "Bug in LocalInterpolation for finite element type "
88 << Dune::className(fe) << std::endl;
89 std::cout << " Interpolation produces " << coeff.size() << " degrees of freedom" << std::endl;
90 std::cout << " Basis has size " << fe.localBasis().size() << std::endl;
91 std::cout << std::endl;
92 return false;
93 }
94
95 // Check if interpolation weights are equal to coefficients
96 for(std::size_t j=0; j<coeff.size(); ++j)
97 {
98 if ( abs(coeff[j] - (i==j)) > TOL)
99 {
100 std::cout << std::setprecision(16);
101 std::cout << "Bug in LocalInterpolation for finite element type "
102 << Dune::className(fe) << std::endl;
103 std::cout << " Degree of freedom " << j << " applied to shape function " << i
104 << " yields value " << coeff[j] << ", not the expected value " << (i==j) << std::endl;
105 std::cout << std::endl;
106 return false;
107 }
108 }
109 }
110 return true;
111}
112
113
114// Check whether the space spanned by the shape functions
115// contains the constant functions
116template<class FE>
117bool testCanRepresentConstants(const FE& fe,
118 unsigned order = 5)
119{
120 typedef typename FE::Traits::LocalBasisType LB;
121 using RangeType = typename LB::Traits::RangeType;
122
123 bool success = true;
124
125 // Construct the constant '1' function
126 auto constantOne = [](const typename LB::Traits::DomainType& xi) { return RangeType(1.0); };
127
128 // Project the constant function onto the FE space
129 std::vector<double> coefficients;
130 fe.localInterpolation().interpolate(constantOne, coefficients);
131
132 // A set of test points
133 const auto& quad = Dune::QuadratureRules<double,LB::Traits::dimDomain>::rule(fe.type(),order);
134
135 // Loop over all quadrature points
136 for (size_t i=0; i<quad.size(); i++) {
137
138 // Get a test point
139 const auto& testPoint = quad[i].position();
140
141 // Compute value of the representation of constantOne at the test point
142 std::vector<RangeType> values;
143 fe.localBasis().evaluateFunction(testPoint, values);
144
145 RangeType sum(0);
146 for (size_t j=0; j<values.size(); j++)
147 sum += coefficients[j] * values[j];
148
149 if ((RangeType(1.0)-sum).two_norm() > TOL)
150 {
151 std::cout << "Finite element type " << Dune::className(fe)
152 << " cannot represent constant functions!" << std::endl;
153 std::cout << " At position: " << testPoint << ","
154 << std::endl;
155 std::cout << " discrete approximation of the '1' function has value " << sum
156 << std::endl;
157 std::cout << std::endl;
158 success = false;
159 }
160
161 } // Loop over all quadrature points
162
163 return success;
164}
165
166// check whether Jacobian agrees with FD approximation
167template<class FE>
168bool testJacobian(const FE& fe,
169 unsigned order = 2,
170 const std::function<bool(const typename FE::Traits::LocalBasisType::Traits::DomainType&)> derivativePointSkip = nullptr)
171{
172 typedef typename FE::Traits::LocalBasisType LB;
173
174 bool success = true;
175
176 // ////////////////////////////////////////////////////////////
177 // Check the partial derivatives by comparing them
178 // to finite difference approximations
179 // ////////////////////////////////////////////////////////////
180
181 // A set of test points
184
185 // Loop over all quadrature points
186 for (size_t i=0; i<quad.size(); i++) {
187
188 // Get a test point
190 quad[i].position();
191
192 // Get the shape function derivatives there
193 std::vector<typename LB::Traits::JacobianType> jacobians;
194 fe.localBasis().evaluateJacobian(testPoint, jacobians);
195 if(jacobians.size() != fe.localBasis().size()) {
196 std::cout << "Bug in evaluateJacobian() for finite element type "
197 << Dune::className(fe) << std::endl;
198 std::cout << " Jacobian vector has size " << jacobians.size()
199 << std::endl;
200 std::cout << " Basis has size " << fe.localBasis().size()
201 << std::endl;
202 std::cout << std::endl;
203 return false;
204 }
205
206 // Skip this test point if we are supposed to
207 if (derivativePointSkip && derivativePointSkip(quad[i].position()))
208 continue;
209
210 // Loop over all directions
211 for (int k=0; k<LB::Traits::dimDomain; k++) {
212
213 // Compute an approximation to the derivative by finite differences
216
217 upPos[k] += jacobianTOL;
218 downPos[k] -= jacobianTOL;
219
220 std::vector<typename LB::Traits::RangeType> upValues, downValues;
221
222 fe.localBasis().evaluateFunction(upPos, upValues);
223 fe.localBasis().evaluateFunction(downPos, downValues);
224
225 // Loop over all shape functions in this set
226 for (unsigned int j=0; j<fe.localBasis().size(); ++j) {
227 //Loop over all components
228 for(int l=0; l < LB::Traits::dimRange; ++l) {
229
230 // The current partial derivative, just for ease of notation
231 double derivative = jacobians[j][l][k];
232
233 double finiteDiff = (upValues[j][l] - downValues[j][l])
234 / (2*jacobianTOL);
235
236 // Check
237 if ( std::abs(derivative-finiteDiff) >
238 TOL/jacobianTOL*((std::abs(finiteDiff)>1) ? std::abs(finiteDiff) : 1.) )
239 {
240 std::cout << std::setprecision(16);
241 std::cout << "Bug in evaluateJacobian() for finite element type "
242 << Dune::className(fe) << std::endl;
243 std::cout << " Shape function derivative does not agree with "
244 << "FD approximation" << std::endl;
245 std::cout << " Shape function " << j << " component " << l
246 << " at position " << testPoint << ": derivative in "
247 << "direction " << k << " is " << derivative << ", but "
248 << finiteDiff << " is expected." << std::endl;
249 std::cout << std::endl;
250 success = false;
251 }
252 } //Loop over all components
253 } // Loop over all shape functions in this set
254 } // Loop over all directions
255 } // Loop over all quadrature points
256
257 return success;
258}
259
265{
266 template <class FE>
267 static bool test(const FE& fe,
268 double eps, double delta, unsigned int diffOrder, std::size_t order = 2,
269 const std::function<bool(const typename FE::Traits::LocalBasisType::Traits::DomainType&)> derivativePointSkip = nullptr)
270 {
271 bool success = true;
272
273 if (diffOrder > 2)
274 std::cout << "No test for differentiability orders larger than 2!" << std::endl;
275
276 if (diffOrder >= 2)
277 success = success and testOrder2(fe, eps, delta, order, derivativePointSkip);
278
279 if (diffOrder >= 1)
280 success = success and testOrder1(fe, eps, delta, order, derivativePointSkip);
281
282 success = success and testOrder0(fe, eps, delta, order);
283
284 return success;
285 }
286
288 template <class FE>
289 static bool testOrder0(const FE& fe,
290 double eps,
291 double delta,
292 std::size_t order = 2)
293 {
294 typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType;
295 constexpr auto dimDomain = FE::Traits::LocalBasisType::Traits::dimDomain;
296
297 bool success = true;
298
300 // Check the partial derivatives by comparing them
301 // to finite difference approximations
303
304 // A set of test points
305 const auto& quad = Dune::QuadratureRules<double, dimDomain>::rule(fe.type(),
306 order);
307
308 // Loop over all quadrature points
309 for (size_t i = 0; i < quad.size(); i++)
310 {
311 // Get a test point
312 const Dune::FieldVector<double, dimDomain>& testPoint = quad[i].position();
313
314 // Get the shape function values there using the 'partial' method
315 std::vector<RangeType> partialValues;
316 std::array<unsigned int, dimDomain> multiIndex;
317 std::fill(multiIndex.begin(), multiIndex.end(), 0);
318
319 fe.localBasis().partial(multiIndex, testPoint, partialValues);
320
321 if (partialValues.size() != fe.localBasis().size())
322 {
323 std::cout << "Bug in partial() for finite element type "
324 << Dune::className(fe) << std::endl;
325 std::cout << " values vector has size "
326 << partialValues.size() << std::endl;
327 std::cout << " Basis has size " << fe.localBasis().size()
328 << std::endl;
329 std::cout << std::endl;
330 return false;
331 }
332
333 // Get reference values
334 std::vector<RangeType> referenceValues;
335 fe.localBasis().evaluateFunction(testPoint, referenceValues);
336
337 // Loop over all shape functions in this set
338 for (unsigned int j = 0; j < fe.localBasis().size(); ++j)
339 {
340 // Loop over all components
341 for (int l = 0; l < FE::Traits::LocalBasisType::Traits::dimRange; ++l)
342 {
343 // Check the 'partial' method
344 if (std::abs(partialValues[j][l] - referenceValues[j][l])
345 > TOL / jacobianTOL
346 * ((std::abs(referenceValues[j][l]) > 1) ? std::abs(referenceValues[j][l]) : 1.))
347 {
348 std::cout << std::setprecision(16);
349 std::cout << "Bug in partial() for finite element type "
350 << Dune::className(fe) << std::endl;
351 std::cout << " Shape function value does not agree with "
352 << "output of method evaluateFunction." << std::endl;
353 std::cout << " Shape function " << j << " component " << l
354 << " at position " << testPoint << ": value is " << partialValues[j][l]
355 << ", but " << referenceValues[j][l] << " is expected." << std::endl;
356 std::cout << std::endl;
357 success = false;
358 }
359
360 } //Loop over all components
361 } // Loop over all shape functions in this set
362 } // Loop over all quadrature points
363
364 return success;
365 }
366
368 template <class FE>
369 static bool testOrder1(const FE& fe,
370 double eps,
371 double delta,
372 std::size_t order = 2,
373 const std::function<bool(const typename FE::Traits::LocalBasisType::Traits::DomainType&)> derivativePointSkip = nullptr)
374 {
375 typedef typename FE::Traits::LocalBasisType LB;
376 typedef typename LB::Traits::RangeFieldType RangeField;
377
378 bool success = true;
379
381 // Check the partial derivatives by comparing them
382 // to finite difference approximations
384
385 // A set of test points
388 order);
389
390 // Loop over all quadrature points
391 for (size_t i = 0; i < quad.size(); i++)
392 {
393 // Get a test point
394 const Dune::FieldVector<double, LB::Traits::dimDomain>& testPoint = quad[i].position();
395
396 // Skip the test points we are supposed to skip
397 if (derivativePointSkip && derivativePointSkip(testPoint))
398 continue;
399
400 // Loop over all directions
401 for (int k = 0; k < LB::Traits::dimDomain; k++)
402 {
403 // Get the shape function derivatives there using the 'partial' method
404 std::vector<typename LB::Traits::RangeType> firstPartialDerivatives;
405 std::array<unsigned int, LB::Traits::dimDomain> multiIndex;
406 std::fill(multiIndex.begin(), multiIndex.end(), 0);
407 multiIndex[k]++;
408 fe.localBasis().partial(multiIndex, testPoint, firstPartialDerivatives);
409 if (firstPartialDerivatives.size() != fe.localBasis().size())
410 {
411 std::cout << "Bug in partial() for finite element type "
412 << Dune::className(fe) << std::endl;
413 std::cout << " firstPartialDerivatives vector has size "
414 << firstPartialDerivatives.size() << std::endl;
415 std::cout << " Basis has size " << fe.localBasis().size()
416 << std::endl;
417 std::cout << std::endl;
418 return false;
419 }
420
421 // Compute an approximation to the derivative by finite differences
424
425 upPos[k] += jacobianTOL;
426 downPos[k] -= jacobianTOL;
427
428 std::vector<typename LB::Traits::RangeType> upValues, downValues;
429
430 fe.localBasis().evaluateFunction(upPos, upValues);
431 fe.localBasis().evaluateFunction(downPos, downValues);
432
433 // Loop over all shape functions in this set
434 for (unsigned int j = 0; j < fe.localBasis().size(); ++j)
435 {
436 // Loop over all components
437 for (int l = 0; l < LB::Traits::dimRange; ++l)
438 {
439 RangeField finiteDiff = (upValues[j][l] - downValues[j][l])
440 / (2 * jacobianTOL);
441
442 // Check the 'partial' method
443 RangeField partialDerivative = firstPartialDerivatives[j][l];
444 if (std::abs(partialDerivative - finiteDiff)
445 > TOL / jacobianTOL
446 * ((std::abs(finiteDiff) > 1) ? std::abs(finiteDiff) : 1.))
447 {
448 std::cout << std::setprecision(16);
449 std::cout << "Bug in partial() for finite element type "
450 << Dune::className(fe) << std::endl;
451 std::cout << " Shape function derivative does not agree with "
452 << "FD approximation" << std::endl;
453 std::cout << " Shape function " << j << " component " << l
454 << " at position " << testPoint << ": derivative in "
455 << "direction " << k << " is " << partialDerivative << ", but "
456 << finiteDiff << " is expected." << std::endl;
457 std::cout << std::endl;
458 success = false;
459 }
460
461 } // Loop over all directions
462 } // Loop over all shape functions in this set
463 } //Loop over all components
464 } // Loop over all quadrature points
465
466 return success;
467 }
468
470 template <class FE>
471 static bool testOrder2(const FE& fe,
472 double eps,
473 double delta,
474 std::size_t order = 2,
475 const std::function<bool(const typename FE::Traits::LocalBasisType::Traits::DomainType&)> derivativePointSkip = nullptr)
476 {
477 typedef typename FE::Traits::LocalBasisType LocalBasis;
478 typedef typename LocalBasis::Traits::DomainFieldType DF;
479 typedef typename LocalBasis::Traits::DomainType Domain;
480 static const int dimDomain = LocalBasis::Traits::dimDomain;
481
482 static const std::size_t dimR = LocalBasis::Traits::dimRange;
483 typedef typename LocalBasis::Traits::RangeType Range;
484 typedef typename LocalBasis::Traits::RangeFieldType RangeField;
485
486 bool success = true;
487
489 // Check the partial derivatives by comparing them
490 // to finite difference approximations
492
493 // A set of test points
496
497 // Loop over all quadrature points
498 for (std::size_t i = 0; i < quad.size(); i++)
499 {
500 // Get a test point
501 const Domain& testPoint = quad[i].position();
502
503 // Skip the test points we are supposed to skip
504 if (derivativePointSkip && derivativePointSkip(testPoint))
505 continue;
506
507 // For testing the 'partial' method
508 std::array<std::vector<Dune::FieldMatrix<RangeField, dimDomain, dimDomain> >, dimR> partialHessians;
509 for (size_t k = 0; k < dimR; k++)
510 partialHessians[k].resize(fe.size());
511
512 //loop over all local directions
513 for (int dir0 = 0; dir0 < dimDomain; dir0++)
514 {
515 for (int dir1 = 0; dir1 < dimDomain; dir1++)
516 {
517 // Get the shape function derivatives there using the 'partial' method
518 std::vector<Range> secondPartialDerivative;
519 std::array<unsigned int,dimDomain> multiIndex;
520 std::fill(multiIndex.begin(), multiIndex.end(), 0);
521 multiIndex[dir0]++;
522 multiIndex[dir1]++;
523 fe.localBasis().partial(multiIndex, testPoint, secondPartialDerivative);
524
525 if (secondPartialDerivative.size() != fe.localBasis().size())
526 {
527 std::cout << "Bug in partial() for finite element type "
528 << Dune::className<FE>() << ":" << std::endl;
529 std::cout << " return vector has size " << secondPartialDerivative.size()
530 << std::endl;
531 std::cout << " Basis has size " << fe.localBasis().size()
532 << std::endl;
533 std::cout << std::endl;
534 return false;
535 }
536
537 //combine to Hesse matrices
538 for (size_t k = 0; k < dimR; k++)
539 for (std::size_t j = 0; j < fe.localBasis().size(); ++j)
540 partialHessians[k][j][dir0][dir1] = secondPartialDerivative[j][k];
541
542 }
543 } //loop over all directions
544
545 // Loop over all local directions
546 for (std::size_t dir0 = 0; dir0 < dimDomain; ++dir0)
547 {
548 for (unsigned int dir1 = 0; dir1 < dimDomain; dir1++)
549 {
550 // Compute an approximation to the derivative by finite differences
551 std::array<Domain,4> neighbourPos;
552 std::fill(neighbourPos.begin(), neighbourPos.end(), testPoint);
553
554 neighbourPos[0][dir0] += delta;
555 neighbourPos[0][dir1] += delta;
556 neighbourPos[1][dir0] -= delta;
557 neighbourPos[1][dir1] += delta;
558 neighbourPos[2][dir0] += delta;
559 neighbourPos[2][dir1] -= delta;
560 neighbourPos[3][dir0] -= delta;
561 neighbourPos[3][dir1] -= delta;
562
563 std::array<std::vector<Range>, 4> neighbourValues;
564 for (int k = 0; k < 4; k++)
565 fe.localBasis().evaluateFunction(neighbourPos[k],
566 neighbourValues[k]);
567
568 // Loop over all shape functions in this set
569 for (std::size_t j = 0; j < fe.localBasis().size(); ++j)
570 {
571 //Loop over all components
572 for (std::size_t k = 0; k < dimR; ++k)
573 {
574 RangeField finiteDiff = (neighbourValues[0][j][k]
575 - neighbourValues[1][j][k] - neighbourValues[2][j][k]
576 + neighbourValues[3][j][k]) / (4 * delta * delta);
577
578 // The current partial derivative, just for ease of notation, evaluated by the 'partial' method
579 RangeField partialDerivative = partialHessians[k][j][dir0][dir1];
580
581 // Check
582 if (std::abs(partialDerivative - finiteDiff)
583 > eps / delta * (std::max(std::abs(finiteDiff), 1.0)))
584 {
585 std::cout << std::setprecision(16);
586 std::cout << "Bug in partial() for finite element type "
587 << Dune::className<FE>() << ":" << std::endl;
588 std::cout << " Second shape function derivative does not agree with "
589 << "FD approximation" << std::endl;
590 std::cout << " Shape function " << j << " component " << k
591 << " at position " << testPoint << ": derivative in "
592 << "local direction (" << dir0 << ", " << dir1 << ") is "
593 << partialDerivative << ", but " << finiteDiff
594 << " is expected." << std::endl;
595 std::cout << std::endl;
596 success = false;
597 }
598
599 } //Loop over all components
600 }
601 } // Loop over all local directions
602 } // Loop over all shape functions in this set
603 } // Loop over all quadrature points
604
605 return success;
606 }
607
608};
609
610// Flags for disabling parts of testFE
611enum {
612 DisableNone = 0,
613 DisableLocalInterpolation = 1,
614 DisableVirtualInterface = 2,
615 DisableJacobian = 4,
616 DisableEvaluate = 8,
617 DisableRepresentConstants = 16
618};
619
630template<class FE>
631bool testFE(const FE& fe,
632 char disabledTests = DisableNone,
633 unsigned int diffOrder = 0,
634 const std::function<bool(const typename FE::Traits::LocalBasisType::Traits::DomainType&)> derivativePointSkip = nullptr)
635{
636 // Order of the quadrature rule used to generate test points
637 unsigned int quadOrder = 2;
638
639 bool success = true;
640
641 if (FE::Traits::LocalBasisType::Traits::dimDomain != fe.type().dim())
642 {
643 std::cout << "Bug in type() for finite element type "
644 << Dune::className(fe) << std::endl;
645 std::cout << " Coordinate dimension is " << FE::Traits::LocalBasisType::Traits::dimDomain << std::endl;
646 std::cout << " but GeometryType is " << fe.type() << " with dimension " << fe.type().dim() << std::endl;
647 success = false;
648 }
649
650 if (fe.size() != fe.localBasis().size())
651 {
652 std::cout << "Bug in finite element type "
653 << Dune::className(fe) << std::endl;
654 std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl;
655 std::cout << " but size reported by LocalBasis is " << fe.localBasis().size() << std::endl;
656 success = false;
657 }
658
659 // Make sure evaluateFunction returns the correct number of values
660 std::vector<typename FE::Traits::LocalBasisType::Traits::RangeType> values;
661 fe.localBasis().evaluateFunction(Dune::ReferenceElements<double,FE::Traits::LocalBasisType::Traits::dimDomain>::general(fe.type()).position(0,0), values);
662
663 if (values.size() != fe.size())
664 {
665 std::cout << "Bug in finite element type "
666 << Dune::className(fe) << std::endl;
667 std::cout << " LocalFiniteElement.size() returns " << fe.size() << "," << std::endl;
668 std::cout << " but LocalBasis::evaluateFunction returns " << values.size() << " values!" << std::endl;
669 success = false;
670 }
671
672 if (fe.size() != fe.localCoefficients().size())
673 {
674 std::cout << "Bug in finite element type "
675 << Dune::className(fe) << std::endl;
676 std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl;
677 std::cout << " but size reported by LocalCoefficients is " << fe.localCoefficients().size() << std::endl;
678 success = false;
679 }
680
681 const auto& lc = fe.localCoefficients();
682 for(size_t i=0; i<lc.size(); i++)
683 {
684 const auto& lk = lc.localKey(i);
685 if (lk.codim() > fe.type().dim())
686 {
687 std::cout << "Bug in finite element type "
688 << Dune::className(fe) << std::endl;
689 std::cout << " Codimension reported by localKey(" << i << ") is " << lk.codim() << std::endl;
690 std::cout << " but geometry is " << fe.type() << " with dimension " << fe.type().dim() << std::endl;
691 success = false;
692 }
693 }
694
695 if (not (disabledTests & DisableLocalInterpolation))
696 {
697 success = testLocalInterpolation<FE>(fe) and success;
698 }
699
700 if (not (disabledTests & DisableRepresentConstants))
701 {
702 success = testCanRepresentConstants<FE>(fe) and success;
703 }
704
705 if (not (disabledTests & DisableJacobian))
706 {
707 success = testJacobian<FE>(fe, quadOrder, derivativePointSkip) and success;
708 }
709 else
710 {
711 // make sure diffOrder is 0
712 success = (diffOrder == 0) and success;
713 }
714
715 if (not (disabledTests & DisableEvaluate))
716 {
717 success = TestPartial::test(fe, TOL, jacobianTOL, diffOrder, quadOrder, derivativePointSkip) and success;
718 }
719
720 if (not (disabledTests & DisableVirtualInterface))
721 {
722 typedef typename FE::Traits::LocalBasisType::Traits ImplementationLBTraits;
724 typedef typename Dune::LocalFiniteElementVirtualImp<FE> VirtualFEImp;
725 typedef typename Dune::LocalFiniteElement<ImplementationLBTraits> TypeErasedLFE;
726
727 const VirtualFEImp virtualFE(fe);
728 if (not (disabledTests & DisableLocalInterpolation))
729 success = testLocalInterpolation<VirtualFEInterface>(virtualFE) and success;
730 if (not (disabledTests & DisableJacobian))
731 {
732 success = testJacobian<VirtualFEInterface>(virtualFE, quadOrder, derivativePointSkip) and success;
733 }
734 else
735 {
736 // make sure diffOrder is 0
737 success = (diffOrder == 0) and success;
738 }
739
740 const TypeErasedLFE typeErasedLFE(fe);
741 if (not (disabledTests & DisableLocalInterpolation))
742 success = testLocalInterpolation<TypeErasedLFE>(typeErasedLFE) and success;
743 if (not (disabledTests & DisableJacobian))
744 success = testJacobian<TypeErasedLFE>(typeErasedLFE, quadOrder, derivativePointSkip) and success;
745
746 // Check for assignment of empty type erased wrapper
747 {
748 TypeErasedLFE typeErasedLFE;
749 typeErasedLFE = fe;
750 typeErasedLFE = fe;
751 }
752
753 }
754
755 return success;
756}
757
758#define TEST_FE(A) { bool b = testFE(A); std::cout << "testFE(" #A ") " << (b?"succeeded\n":"failed\n"); success &= b; }
759#define TEST_FE2(A,B) { bool b = testFE(A, B); std::cout << "testFE(" #A ", " #B ") " << (b?"succeeded\n":"failed\n"); success &= b; }
760#define TEST_FE3(A,B,C) { bool b = testFE(A, B, C); std::cout << "testFE(" #A ", " #B ", " #C ") " << (b?"succeeded\n":"failed\n"); success &= b; }
761#define TEST_FE4(A,B,C,D) { bool b = testFE(A, B, C, D); std::cout << "testFE(" #A ", " #B ", " #C ", " #D ") " << (b?"succeeded\n":"failed\n"); success &= b; }
762
763#endif // DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
vector space out of a tensor product of fields.
Definition: fvector.hh:92
class for wrapping a finite element using the virtual interface
Definition: virtualwrappers.hh:240
virtual base class for local finite elements with functions
Definition: virtualinterface.hh:225
Type erasure class storing a local finite element.
Definition: localfiniteelement.hh:40
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:214
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:326
A free function to provide the demangled class name of a given object or type as a string.
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:43
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:485
std::string className()
Provide the demangled class name of a type T as a string.
Definition: classname.hh:47
Class providing access to the singletons of the reference elements.
Definition: referenceelements.hh:128
Helper class to test the 'partial' method.
Definition: test-localfe.hh:265
static bool testOrder0(const FE &fe, double eps, double delta, std::size_t order=2)
Test the 'partial' method for zero-order partial derivatives, i.e., values.
Definition: test-localfe.hh:289
static bool testOrder1(const FE &fe, double eps, double delta, std::size_t order=2, const std::function< bool(const typename FE::Traits::LocalBasisType::Traits::DomainType &)> derivativePointSkip=nullptr)
Test the 'partial' method for first-order partial derivatives.
Definition: test-localfe.hh:369
static bool testOrder2(const FE &fe, double eps, double delta, std::size_t order=2, const std::function< bool(const typename FE::Traits::LocalBasisType::Traits::DomainType &)> derivativePointSkip=nullptr)
Test second-order partial derivatives.
Definition: test-localfe.hh:471
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 5, 23:02, 2025)