KASKADE 7 development version
hierarchicshapefunctions.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2020 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef HIERARCHICSHAPEFUNCTIONS_HH
14#define HIERARCHICSHAPEFUNCTIONS_HH
15
23#include "fem/barycentric.hh"
28
29#include <dune/common/fvector.hh>
30#include <dune/geometry/referenceelements.hh>
31
32#include <algorithm>
33#include <cmath>
34#include <functional>
35#include <map>
36#include <memory>
37#include <numeric>
38#include <tuple>
39
40//---------------------------------------------------------------------
41namespace Kaskade
42{
43 // forward declarations
44 template <class,int,class> class HierarchicSimplexShapeFunctionSet;
45 template <class,int,class> class HierarchicExtensionSimplexShapeFunctionSet;
46
50 namespace HierarchicDetail {
51
58 int nSubentities(int d, int c);
59
60
66 int cdimSize(int d, int p, int c);
67
68
73 int size(int d, int p);
74
75
81 std::pair<int,int> codim(int d, int p, int k);
82
83
93 std::tuple<int,int,int> tupleIndex(int d, int p, int k);
94
95
104 double shapeFunction(int d, int p, int k, double const b[]);
105
106
116 void dShapeFunction(int d, int p, int k, double const b[], double* grad);
117
118
123 int actualOrder(int d, int p, int k);
124
125
136 int entityPermutation(int d, int c, int e, int const vGlobal[]);
137
138
152 std::tuple<int,int> sfPermutation(int d, int p, int c, int e, int k, int const vGlobal[]);
153
154
155 template <class ctype, int dimension, class Scalar, bool restricted>
156 struct ChooseShapeFunctionSet
157 {
158 typedef HierarchicSimplexShapeFunctionSet<ctype,dimension,Scalar> type;
159 };
160
161 template <class ctype, int dimension, class Scalar>
162 struct ChooseShapeFunctionSet<ctype,dimension,Scalar,true>
163 {
164 typedef RestrictedShapeFunctionSet<HierarchicSimplexShapeFunctionSet<ctype,dimension,Scalar> > type;
165 };
166
167 template <class ctype, int dimension, class Scalar, bool restricted>
168 struct ChooseExtensionShapeFunctionSet
169 {
170 typedef HierarchicExtensionSimplexShapeFunctionSet<ctype,dimension,Scalar> type;
171 };
172
173 template <class ctype, int dimension, class Scalar>
174 struct ChooseExtensionShapeFunctionSet<ctype,dimension,Scalar,true>
175 {
176 typedef RestrictedShapeFunctionSet<HierarchicExtensionSimplexShapeFunctionSet<ctype,dimension,Scalar> > type;
177 };
178
179 } // End of namespace HierarchicDetail
180
185 //---------------------------------------------------------------------
186
254 template <class ctype, int dimension, class Scalar>
255 class HierarchicSimplexShapeFunction: public ShapeFunction<ctype,dimension,Scalar>
256 {
257 public:
258 static int const dim = dimension;
259 static int const comps = 1;
260
261 typedef ctype CoordType;
262 typedef Scalar ResultType;
263
270
275 order_(order), number_(k)
276 {
277 assert(order>=0);
278 assert(0<=k && k<HierarchicDetail::size(dim,order));
279 std::tie(codim_,entity_,entityIndex_) = HierarchicDetail::tupleIndex(dim,order,k);
280 actualOrder = HierarchicDetail::actualOrder(dim,order_,k);
281 }
282
284 : actualOrder(other.actualOrder), order_(other.order_), number_(other.number_),
285 codim_(other.codim_), entity_(other.entity_), entityIndex_(other.entityIndex_)
286 {}
287
295 {
297 return HierarchicDetail::shapeFunction(dim,order_,number_,&zeta[0]);
298 }
299
308 {
311 HierarchicDetail::dShapeFunction(dim,order_,number_,&zeta[0],&bgrad[0]);
312
314 for (int i=0; i<dim; ++i)
315 grad[0][i] = bgrad[i]-bgrad[dim];
316
317
318 // for (int i=0; i<dim; ++i) {
319 // double h = 1e-5;
320 // Dune::FieldVector<CoordType,dim> yl(x), yr(x);
321 // yl[i] -= h;
322 // yr[i] += h;
323 // double diff = (evaluateFunction(yr)-evaluateFunction(yl))/(2*h);
324 //
325 // if (std::abs(diff-grad[0][i]) > 1e-4) {
326 // std::cout << "i=" << i << ": numdiff=" << diff << " bdiff=" << grad[0][i] << '\n';
327 // }
328 // grad[0][i] = diff;
329 // }
330
331
332 return grad;
333 }
334
343 {
344 static bool visited = false;
345 if (!visited)
346 {
347 visited = true;
348 std::cerr << "Not implemented: Hierarchic shape function 2nd derivative at " << __FILE__ << ":" << __LINE__ << "\n";
349 }
350 return 0;
351 }
352
364 virtual std::tuple<int,int,int,int> location() const
365 {
366 return std::make_tuple(order_,codim_,entity_,entityIndex_);
367 }
368
374 int order() const { return actualOrder; }
375
376
377 private:
378 int actualOrder;
379
380 int order_;
381 int number_;
382 int codim_;
383 int entity_;
384 int entityIndex_;
385 };
386
387
388 //---------------------------------------------------------------------
389
397 template <class ctype, int dimension, class Scalar>
398 class HierarchicSimplexShapeFunctionSet : public ShapeFunctionSet<ctype,dimension,Scalar>
399 {
400 public:
403
411 : ShapeFunctionSet<ctype,dimension,Scalar>(Dune::GeometryType(Dune::GeometryType::simplex,dimension))
412 {
413 this->order_ = -1;
414
415 // Empty dummy set.
416 if (ord<0) {
417 this->size_ = 0;
418 return;
419 }
420
421 for (int o=0; o<=ord; ++o) {
422 int n = HierarchicDetail::size(dimension,o);
423 for (int i=0; i<n; ++i) {
424 sf.push_back(value_type(o,i));
425 this->order_ = std::max(this->order_,sf.back().order());
426 }
427 }
428
429 // Use equidistant "interpolation" nodes. Note that we may have
430 // more shape functions than nodes with the same order. To enable
431 // a faithful reconstruction during grid transfer, we use
432 // interpolation nodes for the maximal ACTUAL order of the shape
433 // functions and a least squares "interpolation" approach.
434 //
435 // TODO: Evaluate the alternative of using interpolation nodes for
436 // the maximal *NOMINAL* order of the shape functions and a least
437 // coefficient l2-norm interpolation. This does not allow a
438 // faithful reconstruction (except for the lower dimensional
439 // subspace of nominal order), but is faster due to the lower
440 // number of interpolation points. Note that for some applications
441 // the exact reproduction is necessary.
442 int n = binomial(dimension+this->order_,dimension);
443 this->iNodes.insert(this->iNodes.end(),n,Dune::FieldVector<ctype,dimension>());
445 for (int i=0; i<n; ++i) {
446 for (int j=0; j<dimension; ++j)
447 this->iNodes[i][j] = static_cast<ctype>(b[j])/this->order_;
448 next_multiindex(b.begin(),b.end(),this->order_);
449 }
450
451 // Compute the pseudoinverse for use in interpolation.
452 computePseudoInverse();
453
454 this->size_ = sf.size();
455 }
456
461
466
468
469 virtual value_type const& operator[](int i) const{ return sf[i]; }
470
471 virtual Dune::GeometryType type() const { return Dune::GeometryType(Dune::GeometryType::simplex,dimension); }
472
474 Matrix& IA) const
475 {
476 // TODO: implement without temporaries
477 IA = pinv * A;
478 }
479
480 void removeShapeFunction(size_t index)
481 {
482 assert(index>=0 && index < sf.size());
483 sf.erase(sf.begin()+index);
484 this->size_ = sf.size();
485 computePseudoInverse();
486 }
487
488 protected:
489 std::vector<value_type> sf;
491
492 private:
493 void computePseudoInverse()
494 {
495 pinv.resize(sf.size(),this->iNodes.size());
496 DynamicMatrix<Scalar> A(this->iNodes.size(),sf.size());
497 for (int j=0; j<sf.size(); ++j)
498 for (int i=0; i<this->iNodes.size(); ++i)
499 A[i][j] = sf[j].evaluateFunction(this->iNodes[i]);
500
501 pinv = pseudoinverse(A);
502 }
503 };
504
505 //---------------------------------------------------------------------
506 //---------------------------------------------------------------------
507 //---------------------------------------------------------------------
508
509
510 template <class ctype, int dimension, class Scalar, bool restricted = false>
512 {
513 public:
515
516 private:
517 typedef std::map<std::pair<Dune::GeometryType,int>,value_type const*> Container;
518 typedef typename HierarchicDetail::ChooseShapeFunctionSet<ctype,dimension,Scalar,restricted>::type ShapeFunctionType;
519
520 public:
521
523 {
524 // Fill the container with shape function sets. This is not done
525 // on demand in operator(), since then operator() is not easily
526 // and efficiently made thread-safe.
527 //
528 // Currently only shape functions for simplices are defined.
529 Dune::GeometryType simplex(Dune::GeometryType::simplex,dimension);
530
531 value_type* sfsPrevious = 0;
532
533 for (int i=-1; i<=maxOrder; ++i) {
534 value_type* sfs = new ShapeFunctionType(i);
535 sfs->initHierarchicalProjection(sfsPrevious);
536 container.insert(typename Container::value_type(std::make_pair(simplex,i),sfs));
537 sfsPrevious = sfs;
538 }
539 }
540
542 {
543 for (typename Container::iterator i=container.begin(); i!=container.end(); ++i)
544 delete i->second;
545 }
546
547 virtual value_type const& operator()(Dune::GeometryType type, int order) const
548 {
549 typename Container::const_iterator i = container.find(std::make_pair(type,order));
550 assert(i!=container.end()); // should throw, not assert!
551 return *i->second;
552 }
553
554 private:
555 // A map storing Hierarchic shape function sets associated with
556 // (reference element type, order). Due to runtime polymorphism,
557 // pointers are stored in the map. This class owns the shape
558 // function sets pointed to, and has to delete them in the
559 // destructor.
560 Container container;
561 };
562
563
568 template <class ctype, int dimension, class Scalar>
570 hierarchicShapeFunctionSet(Dune::GeometryType type, int order)
571 {
572 // This static variable will be destructed on program shutdown,
573 // causing its contents to be deleted properly from the heap by
574 // the destructor. No memory leaks should be induced.
576
577 return container(type,order);
578 }
579
580 //---------------------------------------------------------------------
581 //---------------------------------------------------------------------
582
583
593 template <class ctype, int dimension, class Scalar>
595 {
596 public:
599
601 : ShapeFunctionSet<ctype,dimension,Scalar>(Dune::GeometryType(Dune::GeometryType::simplex,
602 dimension))
603 {
604 this->order_ = -1;
605
606 // Empty dummy set.
607 if (ord<0) {
608 this->size_ = 0;
609 return;
610 }
611
612 int n = HierarchicDetail::size(dimension,ord);
613 if (n==0) {
614 this->size_ = 0;
615 return;
616 }
617
618 for (int i=0; i<n; ++i) {
619 sf.push_back(value_type(ord,i));
620 this->order_ = std::max(this->order_,sf.back().order());
621 }
622
623 // Use equidistant "interpolation" nodes. To enable a faithful
624 // reconstruction during grid transfer, we use interpolation nodes
625 // for the maximal ACTUAL order of the shape functions and a least
626 // squares "interpolation" approach.
627 //
628 // TODO: Since this is only an *extension*, we usually have fewer
629 // shape functions. Check whether this can be exploited by using
630 // fewer interpolation nodes.
631 int m = binomial(dimension+this->order_,dimension);
632 this->iNodes.resize(m);
634 for (int i=0; i<m; ++i) {
635 for (int j=0; j<dimension; ++j)
636 this->iNodes[i][j] = static_cast<ctype>(b[j])/this->order_;
637 next_multiindex(b.begin(),b.end(),this->order_);
638 }
639
640 // Compute the pseudoinverse for use in interpolation.
641 computePseudoInverse();
642
643 this->size_ = sf.size();
644 }
645
647
649
650 virtual value_type const& operator[](int i) const{ return sf[i]; }
651
652 virtual Dune::GeometryType type() const
653 {
654 return Dune::GeometryType(Dune::GeometryType::simplex,dimension);
655 }
656
658 Matrix& IA) const
659 {
660 // TODO: implement without temporaries
661 IA = pinv * A;
662 }
663
664 void removeShapeFunction(size_t index)
665 {
666 assert(index>=0 && index < sf.size());
667 sf.erase(sf.begin()+index);
668 this->size_ = sf.size();
669 computePseudoInverse();
670 }
671
672 protected:
673 std::vector<value_type> sf;
675
676 private:
677 void computePseudoInverse()
678 {
679 DynamicMatrix<Scalar> A(this->iNodes.size(),sf.size());
680 for (int j=0; j<sf.size(); ++j)
681 for (int i=0; i<this->iNodes.size(); ++i)
682 A[i][j] = sf[j].evaluateFunction(this->iNodes[i]);
683
684 pinv = pseudoinverse(A);
685 }
686 };
687
688 //---------------------------------------------------------------------
689
690 template <class ctype, int dimension, class Scalar, bool restricted = false>
692 {
693 public:
695
696 private:
697 typedef std::map<std::pair<Dune::GeometryType,int>,value_type const*> Container;
698 typedef typename HierarchicDetail::ChooseExtensionShapeFunctionSet<ctype,dimension,Scalar,restricted>::type ShapeFunctionType;
699
700 public:
701
703 {
704 // Fill the container with shape function sets. This is not done
705 // on demand in operator(), since then operator() is not easily
706 // and efficiently made thread-safe.
707 //
708 // Currently only shape functions for simplices are defined.
709 Dune::GeometryType simplex(Dune::GeometryType::simplex,dimension);
710
711 value_type* sfsPrevious = 0;
712
713 for (int i=-1; i<=maxOrder; ++i) {
714 value_type* sfs = new ShapeFunctionType(i);
715 sfs->initHierarchicalProjection(sfsPrevious);
716 container.insert(typename Container::value_type(std::make_pair(simplex,i),sfs));
717 sfsPrevious = sfs;
718 }
719 }
720
722 {
723 for (typename Container::iterator i=container.begin(); i!=container.end(); ++i)
724 delete i->second;
725 }
726
727 virtual value_type const& operator()(Dune::GeometryType type, int order) const
728 {
729 typename Container::const_iterator i = container.find(std::make_pair(type,order));
730 assert(i!=container.end()); // should throw, not assert!
731 return *i->second;
732 }
733
734 private:
735 // A map storing Hierarchic shape function sets associated with
736 // (reference element type, order). Due to runtime polymorphism,
737 // pointers are stored in the map. This class owns the shape
738 // function sets pointed to, and has to delete them in the
739 // destructor.
740 Container container;
741 };
742
743
748 template <class ctype, int dimension, class Scalar>
750 hierarchicExtensionShapeFunctionSet(Dune::GeometryType type, int order)
751 {
752 // This static variable will be destructed on program shutdown,
753 // causing its contents to be deleted properly from the heap by
754 // the destructor. No memory leaks should be induced.
756
757 return container(type,order);
758 }
759
760} // End of namespace Kaskade
761
762#endif
A LAPACK-compatible dense matrix class with shape specified at runtime.
void resize(size_type r, size_type c)
Resizes the matrix to r x c, leaving the entries in an undefined state.
ShapeFunctionSet< ctype, dimension, Scalar > value_type
virtual value_type const & operator()(Dune::GeometryType type, int order) const
access a shape function via type and order
A container of hierarchic shape functions of nominal order Ord on the unit simplex of grid dimension....
HierarchicExtensionSimplexShapeFunctionSet(HierarchicExtensionSimplexShapeFunctionSet const &other)=default
HierarchicSimplexShapeFunction< ctype, dimension, Scalar > value_type
HierarchicExtensionSimplexShapeFunctionSet(HierarchicExtensionSimplexShapeFunctionSet &&other)=default
virtual void interpolate(typename ShapeFunctionSet< ctype, dimension, Scalar >::SfValueArray const &A, Matrix &IA) const
DynamicMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > pinv
virtual value_type const & operator[](int i) const
Random access to a shape function.
ShapeFunctionSet< ctype, dimension, Scalar >::Matrix Matrix
ShapeFunctionSet< ctype, dimension, Scalar > value_type
virtual value_type const & operator()(Dune::GeometryType type, int order) const
access a shape function via type and order
Scalar hierarchic shape functions on the unit simplex.
virtual Dune::FieldVector< ResultType, comps > evaluateFunction(Dune::FieldVector< CoordType, dim > const &x) const
int order() const
The actual polynomial order of the shape function.
HierarchicSimplexShapeFunction(int order, int k)
Creates the k-th shape function of given order.
virtual Tensor< Scalar, 1, dim, dim > evaluate2ndDerivative(Dune::FieldVector< CoordType, dim > const &x) const
Evaluates the second derivative of the shape function.
HierarchicSimplexShapeFunction(HierarchicSimplexShapeFunction const &other)
virtual std::tuple< int, int, int, int > location() const
Information about the association of the shape function to subentities of the simplex.
virtual Dune::FieldMatrix< Scalar, 1, dim > evaluateDerivative(Dune::FieldVector< CoordType, dim > const &x) const
Evaluates the derivative of the shape function.
A container of hierarchic shape functions (see HierarchicSimplexShapeFunction) up to a given nominal ...
virtual void interpolate(typename ShapeFunctionSet< ctype, dimension, Scalar >::SfValueArray const &A, Matrix &IA) const
ShapeFunctionSet< ctype, dimension, Scalar >::Matrix Matrix
HierarchicSimplexShapeFunctionSet(int ord)
Constructs a hierarchic shape function set.
HierarchicSimplexShapeFunction< ctype, dimension, Scalar > value_type
DynamicMatrix< Dune::FieldMatrix< Scalar, 1, 1 > > pinv
virtual value_type const & operator[](int i) const
Random access to a shape function.
HierarchicSimplexShapeFunctionSet(HierarchicSimplexShapeFunctionSet &&other)=default
Move constructor.
HierarchicSimplexShapeFunctionSet(HierarchicSimplexShapeFunctionSet const &other)=default
Copy constructor.
Base class for sets of shape function containers.
A set of shape functions.
void initHierarchicalProjection(ShapeFunctionSet< ctype, dimension, T, comp > const *sfl)
Initialize the hierarchical projection matrix based on the given lower order shape function set.
int maxOrder(Evaluators const &evals)
Computes the maximum ansatz order used in a collection of evaluators.
Dune::FieldVector< CoordType, dim+1 > barycentric(Dune::FieldVector< CoordType, dim > const &x)
Computes the barycentric coordinates of a point in the unit simplex.
Definition: barycentric.hh:32
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Definition: fixdune.hh:110
constexpr int binomial(int n, int k)
Computes the binomial coefficient .
void next_multiindex(It first, It last, int const m)
Computes the next nonnegative multiindex of order m.
HierarchicShapeFunctionSetContainer< ctype, dimension, Scalar >::value_type const & hierarchicShapeFunctionSet(Dune::GeometryType type, int order)
Returns a Hierarchic shape function set for given reference element type and given polynomial order....
void pseudoinverse(SLAPMatrix< Scalar > A, SLAPMatrix< Scalar > &Ainv)
HierarchicExtensionShapeFunctionSetContainer< ctype, dimension, Scalar >::value_type const & hierarchicExtensionShapeFunctionSet(Dune::GeometryType type, int order)