Dune Core Modules (2.6.0)

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#ifndef DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
4#define DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
5
14#include <iomanip>
15#include <iostream>
16#include <typeinfo>
17
20#include <dune/geometry/referenceelements.hh>
21
22#include <dune/localfunctions/common/virtualinterface.hh>
23#include <dune/localfunctions/common/virtualwrappers.hh>
24
25double TOL = 1e-9;
26// The FD approximation used for checking the Jacobian uses half of the
27// precision -- so we have to be a little bit more tolerant here.
28double jacobianTOL = 1e-5; // sqrt(TOL)
29
30// This class wraps one shape function of a local finite element as a function
31// that can be feed to the LocalInterpolation::interpolate method.
32template<class FE>
33class ShapeFunctionAsFunction :
34 // public Dune::LocalFiniteElementFunctionBase<FE>::type
35 public Dune::LocalFiniteElementFunctionBase<FE>::FunctionBase
36 // public Dune::LocalFiniteElementFunctionBase<FE>::VirtualFunctionBase
37{
38public:
39 typedef typename FE::Traits::LocalBasisType::Traits::DomainType DomainType;
40 typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType;
42
43 typedef typename FE::Traits::LocalBasisType::Traits::RangeFieldType CT;
44
45 ShapeFunctionAsFunction(const FE& fe, int shapeFunction) :
46 fe_(fe),
47 shapeFunction_(shapeFunction)
48 {}
49
50 void evaluate (const DomainType& x, RangeType& y) const
51 {
52 std::vector<RangeType> yy;
53 fe_.localBasis().evaluateFunction(x, yy);
54 y = 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 std::vector<typename ShapeFunctionAsFunction<FE>::CT> coeff;
70 for(size_t i=0; i<fe.size(); ++i)
71 {
72 // The i-th shape function as a function that 'interpolate' can deal with
73 ShapeFunctionAsFunction<FE> f(fe, i);
74
75 // Compute degrees of freedom for that shape function
76 // We expect the result to be the i-th unit vector
77 fe.localInterpolation().interpolate(f, coeff);
78
79 // Check size of weight vector
80 if (coeff.size() != fe.localBasis().size())
81 {
82 std::cout << "Bug in LocalInterpolation for finite element type "
83 << Dune::className(fe) << std::endl;
84 std::cout << " Interpolation produces " << coeff.size() << " degrees of freedom" << std::endl;
85 std::cout << " Basis has size " << fe.localBasis().size() << std::endl;
86 std::cout << std::endl;
87 return false;
88 }
89
90 // Check if interpolation weights are equal to coefficients
91 for(std::size_t j=0; j<coeff.size(); ++j)
92 {
93 if ( std::abs(coeff[j] - (i==j)) > TOL)
94 {
95 std::cout << std::setprecision(16);
96 std::cout << "Bug in LocalInterpolation for finite element type "
97 << Dune::className(fe) << std::endl;
98 std::cout << " Degree of freedom " << j << " applied to shape function " << i
99 << " yields value " << coeff[j] << ", not the expected value " << (i==j) << std::endl;
100 std::cout << std::endl;
101 return false;
102 }
103 }
104 }
105 return true;
106}
107
108
109// check whether Jacobian agrees with FD approximation
110template<class FE>
111bool testJacobian(const FE& fe, unsigned order = 2)
112{
113 typedef typename FE::Traits::LocalBasisType LB;
114
115 bool success = true;
116
117 // ////////////////////////////////////////////////////////////
118 // Check the partial derivatives by comparing them
119 // to finite difference approximations
120 // ////////////////////////////////////////////////////////////
121
122 // A set of test points
125
126 // Loop over all quadrature points
127 for (size_t i=0; i<quad.size(); i++) {
128
129 // Get a test point
131 quad[i].position();
132
133 // Get the shape function derivatives there
134 std::vector<typename LB::Traits::JacobianType> jacobians;
135 fe.localBasis().evaluateJacobian(testPoint, jacobians);
136 if(jacobians.size() != fe.localBasis().size()) {
137 std::cout << "Bug in evaluateJacobianGlobal() for finite element type "
138 << Dune::className(fe) << std::endl;
139 std::cout << " Jacobian vector has size " << jacobians.size()
140 << std::endl;
141 std::cout << " Basis has size " << fe.localBasis().size()
142 << std::endl;
143 std::cout << std::endl;
144 return false;
145 }
146
147 // Loop over all directions
148 for (int k=0; k<LB::Traits::dimDomain; k++) {
149
150 // Compute an approximation to the derivative by finite differences
153
154 upPos[k] += jacobianTOL;
155 downPos[k] -= jacobianTOL;
156
157 std::vector<typename LB::Traits::RangeType> upValues, downValues;
158
159 fe.localBasis().evaluateFunction(upPos, upValues);
160 fe.localBasis().evaluateFunction(downPos, downValues);
161
162 // Loop over all shape functions in this set
163 for (unsigned int j=0; j<fe.localBasis().size(); ++j) {
164 //Loop over all components
165 for(int l=0; l < LB::Traits::dimRange; ++l) {
166
167 // The current partial derivative, just for ease of notation
168 double derivative = jacobians[j][l][k];
169
170 double finiteDiff = (upValues[j][l] - downValues[j][l])
171 / (2*jacobianTOL);
172
173 // Check
174 if ( std::abs(derivative-finiteDiff) >
175 TOL/jacobianTOL*((std::abs(finiteDiff)>1) ? std::abs(finiteDiff) : 1.) )
176 {
177 std::cout << std::setprecision(16);
178 std::cout << "Bug in evaluateJacobian() for finite element type "
179 << Dune::className(fe) << std::endl;
180 std::cout << " Shape function derivative does not agree with "
181 << "FD approximation" << std::endl;
182 std::cout << " Shape function " << j << " component " << l
183 << " at position " << testPoint << ": derivative in "
184 << "direction " << k << " is " << derivative << ", but "
185 << finiteDiff << " is expected." << std::endl;
186 std::cout << std::endl;
187 success = false;
188 }
189 } //Loop over all components
190 } // Loop over all shape functions in this set
191 } // Loop over all directions
192 } // Loop over all quadrature points
193
194 return success;
195}
196
202{
203 template <class FE>
204 static bool test(const FE& fe,
205 double eps, double delta, unsigned int diffOrder, std::size_t order = 2)
206 {
207 bool success = true;
208
209 if (diffOrder > 2)
210 std::cout << "No test for differentiability orders larger than 2!" << std::endl;
211
212 if (diffOrder >= 2)
213 success = success and testOrder2(fe, eps, delta, order);
214
215 if (diffOrder >= 1)
216 success = success and testOrder1(fe, eps, delta, order);
217
218 success = success and testOrder0(fe, eps, delta, order);
219
220 return success;
221 }
222
224 template <class FE>
225 static bool testOrder0(const FE& fe,
226 double eps,
227 double delta,
228 std::size_t order = 2)
229 {
230 typedef typename FE::Traits::LocalBasisType::Traits::RangeType RangeType;
231 constexpr auto dimDomain = FE::Traits::LocalBasisType::Traits::dimDomain;
232
233 bool success = true;
234
236 // Check the partial derivatives by comparing them
237 // to finite difference approximations
239
240 // A set of test points
241 const auto& quad = Dune::QuadratureRules<double, dimDomain>::rule(fe.type(),
242 order);
243
244 // Loop over all quadrature points
245 for (size_t i = 0; i < quad.size(); i++)
246 {
247 // Get a test point
248 const Dune::FieldVector<double, dimDomain>& testPoint = quad[i].position();
249
250 // Get the shape function values there using the 'partial' method
251 std::vector<RangeType> partialValues;
252 std::array<unsigned int, dimDomain> multiIndex;
253 std::fill(multiIndex.begin(), multiIndex.end(), 0);
254
255 fe.localBasis().partial(multiIndex, testPoint, partialValues);
256
257 if (partialValues.size() != fe.localBasis().size())
258 {
259 std::cout << "Bug in partial() for finite element type "
260 << Dune::className(fe) << std::endl;
261 std::cout << " values vector has size "
262 << partialValues.size() << std::endl;
263 std::cout << " Basis has size " << fe.localBasis().size()
264 << std::endl;
265 std::cout << std::endl;
266 return false;
267 }
268
269 // Get reference values
270 std::vector<RangeType> referenceValues;
271 fe.localBasis().evaluateFunction(testPoint, referenceValues);
272
273 // Loop over all shape functions in this set
274 for (unsigned int j = 0; j < fe.localBasis().size(); ++j)
275 {
276 // Loop over all components
277 for (int l = 0; l < FE::Traits::LocalBasisType::Traits::dimRange; ++l)
278 {
279 // Check the 'partial' method
280 if (std::abs(partialValues[j][l] - referenceValues[j][l])
281 > TOL / jacobianTOL
282 * ((std::abs(referenceValues[j][l]) > 1) ? std::abs(referenceValues[j][l]) : 1.))
283 {
284 std::cout << std::setprecision(16);
285 std::cout << "Bug in partial() for finite element type "
286 << Dune::className(fe) << std::endl;
287 std::cout << " Shape function value does not agree with "
288 << "output of method evaluateFunction." << std::endl;
289 std::cout << " Shape function " << j << " component " << l
290 << " at position " << testPoint << ": value is " << partialValues[j][l]
291 << ", but " << referenceValues[j][l] << " is expected." << std::endl;
292 std::cout << std::endl;
293 success = false;
294 }
295
296 } //Loop over all components
297 } // Loop over all shape functions in this set
298 } // Loop over all quadrature points
299
300 return success;
301 }
302
304 template <class FE>
305 static bool testOrder1(const FE& fe,
306 double eps,
307 double delta,
308 std::size_t order = 2)
309 {
310 typedef typename FE::Traits::LocalBasisType LB;
311 typedef typename LB::Traits::RangeFieldType RangeField;
312
313 bool success = true;
314
316 // Check the partial derivatives by comparing them
317 // to finite difference approximations
319
320 // A set of test points
323 order);
324
325 // Loop over all quadrature points
326 for (size_t i = 0; i < quad.size(); i++)
327 {
328 // Get a test point
329 const Dune::FieldVector<double, LB::Traits::dimDomain>& testPoint = quad[i].position();
330
331 // Loop over all directions
332 for (int k = 0; k < LB::Traits::dimDomain; k++)
333 {
334 // Get the shape function derivatives there using the 'partial' method
335 std::vector<typename LB::Traits::RangeType> firstPartialDerivatives;
336 std::array<unsigned int, LB::Traits::dimDomain> multiIndex;
337 std::fill(multiIndex.begin(), multiIndex.end(), 0);
338 multiIndex[k]++;
339 fe.localBasis().partial(multiIndex, testPoint, firstPartialDerivatives);
340 if (firstPartialDerivatives.size() != fe.localBasis().size())
341 {
342 std::cout << "Bug in partial() for finite element type "
343 << Dune::className(fe) << std::endl;
344 std::cout << " firstPartialDerivatives vector has size "
345 << firstPartialDerivatives.size() << std::endl;
346 std::cout << " Basis has size " << fe.localBasis().size()
347 << std::endl;
348 std::cout << std::endl;
349 return false;
350 }
351
352 // Compute an approximation to the derivative by finite differences
355
356 upPos[k] += jacobianTOL;
357 downPos[k] -= jacobianTOL;
358
359 std::vector<typename LB::Traits::RangeType> upValues, downValues;
360
361 fe.localBasis().evaluateFunction(upPos, upValues);
362 fe.localBasis().evaluateFunction(downPos, downValues);
363
364 // Loop over all shape functions in this set
365 for (unsigned int j = 0; j < fe.localBasis().size(); ++j)
366 {
367 // Loop over all components
368 for (int l = 0; l < LB::Traits::dimRange; ++l)
369 {
370 RangeField finiteDiff = (upValues[j][l] - downValues[j][l])
371 / (2 * jacobianTOL);
372
373 // Check the 'partial' method
374 RangeField partialDerivative = firstPartialDerivatives[j][l];
375 if (std::abs(partialDerivative - finiteDiff)
376 > TOL / jacobianTOL
377 * ((std::abs(finiteDiff) > 1) ? std::abs(finiteDiff) : 1.))
378 {
379 std::cout << std::setprecision(16);
380 std::cout << "Bug in partial() for finite element type "
381 << Dune::className(fe) << std::endl;
382 std::cout << " Shape function derivative does not agree with "
383 << "FD approximation" << std::endl;
384 std::cout << " Shape function " << j << " component " << l
385 << " at position " << testPoint << ": derivative in "
386 << "direction " << k << " is " << partialDerivative << ", but "
387 << finiteDiff << " is expected." << std::endl;
388 std::cout << std::endl;
389 success = false;
390 }
391
392 } // Loop over all directions
393 } // Loop over all shape functions in this set
394 } //Loop over all components
395 } // Loop over all quadrature points
396
397 return success;
398 }
399
401 template <class FE>
402 static bool testOrder2(const FE& fe,
403 double eps,
404 double delta,
405 std::size_t order = 2)
406 {
407 typedef typename FE::Traits::LocalBasisType LocalBasis;
408 typedef typename LocalBasis::Traits::DomainFieldType DF;
409 typedef typename LocalBasis::Traits::DomainType Domain;
410 static const int dimDomain = LocalBasis::Traits::dimDomain;
411
412 static const std::size_t dimR = LocalBasis::Traits::dimRange;
413 typedef typename LocalBasis::Traits::RangeType Range;
414 typedef typename LocalBasis::Traits::RangeFieldType RangeField;
415
416 bool success = true;
417
419 // Check the partial derivatives by comparing them
420 // to finite difference approximations
422
423 // A set of test points
426
427 // Loop over all quadrature points
428 for (std::size_t i = 0; i < quad.size(); i++)
429 {
430 // Get a test point
431 const Domain& testPoint = quad[i].position();
432
433 // For testing the 'partial' method
434 std::array<std::vector<Dune::FieldMatrix<RangeField, dimDomain, dimDomain> >, dimR> partialHessians;
435 for (size_t k = 0; k < dimR; k++)
436 partialHessians[k].resize(fe.size());
437
438 //loop over all local directions
439 for (int dir0 = 0; dir0 < dimDomain; dir0++)
440 {
441 for (int dir1 = 0; dir1 < dimDomain; dir1++)
442 {
443 // Get the shape function derivatives there using the 'partial' method
444 std::vector<Range> secondPartialDerivative;
445 std::array<unsigned int,dimDomain> multiIndex;
446 std::fill(multiIndex.begin(), multiIndex.end(), 0);
447 multiIndex[dir0]++;
448 multiIndex[dir1]++;
449 fe.localBasis().partial(multiIndex, testPoint, secondPartialDerivative);
450
451 if (secondPartialDerivative.size() != fe.localBasis().size())
452 {
453 std::cout << "Bug in partial() for finite element type "
454 << Dune::className<FE>() << ":" << std::endl;
455 std::cout << " return vector has size " << secondPartialDerivative.size()
456 << std::endl;
457 std::cout << " Basis has size " << fe.localBasis().size()
458 << std::endl;
459 std::cout << std::endl;
460 return false;
461 }
462
463 //combine to Hesse matrices
464 for (size_t k = 0; k < dimR; k++)
465 for (std::size_t j = 0; j < fe.localBasis().size(); ++j)
466 partialHessians[k][j][dir0][dir1] = secondPartialDerivative[j][k];
467
468 }
469 } //loop over all directions
470
471 // Loop over all local directions
472 for (std::size_t dir0 = 0; dir0 < dimDomain; ++dir0)
473 {
474 for (unsigned int dir1 = 0; dir1 < dimDomain; dir1++)
475 {
476 // Compute an approximation to the derivative by finite differences
477 std::array<Domain,4> neighbourPos;
478 std::fill(neighbourPos.begin(), neighbourPos.end(), testPoint);
479
480 neighbourPos[0][dir0] += delta;
481 neighbourPos[0][dir1] += delta;
482 neighbourPos[1][dir0] -= delta;
483 neighbourPos[1][dir1] += delta;
484 neighbourPos[2][dir0] += delta;
485 neighbourPos[2][dir1] -= delta;
486 neighbourPos[3][dir0] -= delta;
487 neighbourPos[3][dir1] -= delta;
488
489 std::array<std::vector<Range>, 4> neighbourValues;
490 for (int k = 0; k < 4; k++)
491 fe.localBasis().evaluateFunction(neighbourPos[k],
492 neighbourValues[k]);
493
494 // Loop over all shape functions in this set
495 for (std::size_t j = 0; j < fe.localBasis().size(); ++j)
496 {
497 //Loop over all components
498 for (std::size_t k = 0; k < dimR; ++k)
499 {
500 RangeField finiteDiff = (neighbourValues[0][j][k]
501 - neighbourValues[1][j][k] - neighbourValues[2][j][k]
502 + neighbourValues[3][j][k]) / (4 * delta * delta);
503
504 // The current partial derivative, just for ease of notation, evaluated by the 'partial' method
505 RangeField partialDerivative = partialHessians[k][j][dir0][dir1];
506
507 // Check
508 if (std::abs(partialDerivative - finiteDiff)
509 > eps / delta * (std::max(std::abs(finiteDiff), 1.0)))
510 {
511 std::cout << std::setprecision(16);
512 std::cout << "Bug in partial() for finite element type "
513 << Dune::className<FE>() << ":" << std::endl;
514 std::cout << " Second shape function derivative does not agree with "
515 << "FD approximation" << std::endl;
516 std::cout << " Shape function " << j << " component " << k
517 << " at position " << testPoint << ": derivative in "
518 << "local direction (" << dir0 << ", " << dir1 << ") is "
519 << partialDerivative << ", but " << finiteDiff
520 << " is expected." << std::endl;
521 std::cout << std::endl;
522 success = false;
523 }
524
525 } //Loop over all components
526 }
527 } // Loop over all local directions
528 } // Loop over all shape functions in this set
529 } // Loop over all quadrature points
530
531 return success;
532 }
533
534};
535
536// Flags for disabling parts of testFE
537enum {
538 DisableNone = 0,
539 DisableLocalInterpolation = 1,
540 DisableVirtualInterface = 2,
541 DisableJacobian = 4,
542 DisableEvaluate = 8
543};
544
545// call tests for given finite element
546template<class FE>
547bool testFE(const FE& fe, char disabledTests = DisableNone, unsigned int diffOrder = 0)
548{
549 // Order of the quadrature rule used to generate test points
550 unsigned int quadOrder = 2;
551
552 bool success = true;
553
554 if (FE::Traits::LocalBasisType::Traits::dimDomain != fe.type().dim())
555 {
556 std::cout << "Bug in type() for finite element type "
557 << Dune::className(fe) << std::endl;
558 std::cout << " Coordinate dimension is " << FE::Traits::LocalBasisType::Traits::dimDomain << std::endl;
559 std::cout << " but GeometryType is " << fe.type() << " with dimension " << fe.type().dim() << std::endl;
560 success = false;
561 }
562
563 if (fe.size() != fe.localBasis().size())
564 {
565 std::cout << "Bug in finite element type "
566 << Dune::className(fe) << std::endl;
567 std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl;
568 std::cout << " but size reported by LocalBasis is " << fe.localBasis().size() << std::endl;
569 success = false;
570 }
571
572 // Make sure evaluateFunction returns the correct number of values
573 std::vector<typename FE::Traits::LocalBasisType::Traits::RangeType> values;
574 fe.localBasis().evaluateFunction(Dune::ReferenceElements<double,FE::Traits::LocalBasisType::Traits::dimDomain>::general(fe.type()).position(0,0), values);
575
576 if (values.size() != fe.size())
577 {
578 std::cout << "Bug in finite element type "
579 << Dune::className(fe) << std::endl;
580 std::cout << " LocalFiniteElement.size() returns " << fe.size() << "," << std::endl;
581 std::cout << " but LocalBasis::evaluateFunction returns " << values.size() << " values!" << std::endl;
582 success = false;
583 }
584
585 if (fe.size() != fe.localCoefficients().size())
586 {
587 std::cout << "Bug in finite element type "
588 << Dune::className(fe) << std::endl;
589 std::cout << " Size reported by LocalFiniteElement is " << fe.size() << std::endl;
590 std::cout << " but size reported by LocalCoefficients is " << fe.localCoefficients().size() << std::endl;
591 success = false;
592 }
593
594 const auto& lc = fe.localCoefficients();
595 for(size_t i=0; i<lc.size(); i++)
596 {
597 const auto& lk = lc.localKey(i);
598 if (lk.codim() > fe.type().dim())
599 {
600 std::cout << "Bug in finite element type "
601 << Dune::className(fe) << std::endl;
602 std::cout << " Codimension reported by localKey(" << i << ") is " << lk.codim() << std::endl;
603 std::cout << " but geometry is " << fe.type() << " with dimension " << fe.type().dim() << std::endl;
604 success = false;
605 }
606 }
607
608 if (not (disabledTests & DisableLocalInterpolation))
609 {
610 success = testLocalInterpolation<FE>(fe) and success;
611 }
612 if (not (disabledTests & DisableJacobian))
613 {
614 success = testJacobian<FE>(fe, quadOrder) and success;
615 }
616 else
617 {
618 // make sure diffOrder is 0
619 success = (diffOrder == 0) and success;
620 }
621
622 if (not (disabledTests & DisableEvaluate))
623 {
624 success = TestPartial::test(fe, TOL, jacobianTOL, diffOrder, quadOrder) and success;
625 }
626
627 if (not (disabledTests & DisableVirtualInterface))
628 {
629 typedef typename FE::Traits::LocalBasisType::Traits ImplementationLBTraits;
631 typedef typename Dune::LocalFiniteElementVirtualImp<FE> VirtualFEImp;
632
633 const VirtualFEImp virtualFE(fe);
634 if (not (disabledTests & DisableLocalInterpolation))
635 success = testLocalInterpolation<VirtualFEInterface>(virtualFE) and success;
636 if (not (disabledTests & DisableJacobian))
637 {
638 success = testJacobian<VirtualFEInterface>(virtualFE) and success;
639 }
640 else
641 {
642 // make sure diffOrder is 0
643 success = (diffOrder == 0) and success;
644 }
645 }
646
647 return success;
648}
649
650#define TEST_FE(A) { bool b = testFE(A); std::cout << "testFE(" #A ") " << (b?"succeeded\n":"failed\n"); success &= b; }
651#define TEST_FE2(A,B) { bool b = testFE(A, B); std::cout << "testFE(" #A ", " #B ") " << (b?"succeeded\n":"failed\n"); success &= b; }
652#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; }
653
654#endif // DUNE_LOCALFUNCTIONS_TEST_TEST_LOCALFE_HH
vector space out of a tensor product of fields.
Definition: fvector.hh:93
void evaluate(const typename Traits::DomainType &x, typename Traits::RangeType &y) const
Function evaluation.
Return a proper base class for functions to use with LocalInterpolation.
Definition: virtualinterface.hh:35
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:266
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:97
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:225
A free function to provide the demangled class name of a given object or type as a string.
std::string className()
Provide the demangled class name of a type T as a string.
Definition: classname.hh:26
Class providing access to the singletons of the reference elements.
Definition: referenceelements.hh:168
Helper class to test the 'partial' method.
Definition: test-localfe.hh:202
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:225
static bool testOrder2(const FE &fe, double eps, double delta, std::size_t order=2)
Test second-order partial derivatives.
Definition: test-localfe.hh:402
static bool testOrder1(const FE &fe, double eps, double delta, std::size_t order=2)
Test the 'partial' method for first-order partial derivatives.
Definition: test-localfe.hh:305
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 24, 23:30, 2024)