KASKADE 7 development version
nedelecshapefunctions.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-2016 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 NEDELECSHAPEFUNCTIONS_HH
14#define NEDELECSHAPEFUNCTIONS_HH
15
16#include <map>
17
18#include <dune/common/fvector.hh>
19#include <dune/geometry/referenceelements.hh>
20#include <dune/geometry/type.hh>
21
22#include "fem/barycentric.hh"
25
27
28namespace Kaskade
29{
44 template <class ctype, int dimension, class T>
45 class NedelecSimplexShapeFunction: public ShapeFunction<ctype,dimension,T,dimension>
46 {
47 public:
48 static int const dim = dimension;
49 static int const comps = dim;
50 static int const order = 1;
51
52 typedef ctype CoordType;
53 typedef T ResultType;
54
61 {
63 }
64
71 {
72 // compute index local in element
73 entity_ = e;
74
75 // Compute barycentric dimensions of edge end points. Note that the origin, which
76 // has barycentric index dim, has the subentity number 0. Hence we need to shift and
77 // wrap the subentity indices to obtain the barycentric indices.
78 Dune::ReferenceElement<CoordType,dim> const &simplex = Dune::ReferenceElements<CoordType,dim>::simplex();
79 int p0Id = simplex.subEntity(e,dim-1,0,dim);
80 p0_ = p0Id==0? dim: p0Id-1;
81 int p1Id = simplex.subEntity(e,dim-1,1,dim);
82 p1_ = p1Id==0? dim: p1Id-1;
83
84 // compute gradients of barycentric coordinate functions
85 if (p0_==dim) dp0_ = -1;
86 else { dp0_ = 0; dp0_[p0_] = 1; }
87 if (p1_==dim) dp1_ = -1;
88 else { dp1_ = 0; dp1_[p1_] = 1; }
89
90 // compute position and direction of edge
91 pos_ = simplex.position(e,dim-1);
92 edge_ = simplex.position(p1Id,dim) - simplex.position(p0Id,dim);
93 }
94
103 {
105 return bc[p0_]*dp1_ - bc[p1_]*dp0_;
106 }
107
116 {
117 // derivative of bc[p0]*dp1 - bc[p1]*dp0 is dp1 * bc[p0]' - dp0 * bc[p1]', where the products are *outer products*
118 // resulting in the proper matrices. Start with derivatives of the barycentric coordinates \lambda_i and \lambda_j
119 Dune::FieldVector<T,dim> dbc0(0.0), dbc1(0.0);
120 for (int dir=0; dir<dim; ++dir)
121 {
122 if (p0_ == dir) dbc0 = -1.0;
123 else dbc0[p0_] = 1.0;
124 if (p1_ == dir) dbc1 = -1.0;
125 else dbc1[p1_] = 1.0;
126 }
127
128 return outerProduct(dp1_,dbc0) - outerProduct(dp0_,dbc1);
129
130 // old code, should be equivlaent...
131// // TODO: faster implementation needed
132// Dune::FieldMatrix<ResultType,dim,dim> d;
133// for (int c=0; c<dim; ++c)
134// for (int dir=0; dir<dim; ++dir) {
135// ResultType dbcp0_ddir=0, dbcp1_ddir=0;
136// if (p0_==dir) dbcp0_ddir = 1;
137// if (p0_==dim) dbcp0_ddir = -1;
138// if (p1_==dir) dbcp1_ddir = 1;
139// if (p1_==dim) dbcp1_ddir = -1;
140//
141// d[c][dir] = dbcp0_ddir*dp1_[c] - dbcp1_ddir*dp0_[c];
142// }
143//
144// return d;
145 }
146
157 {
158 // Nedelec shape functions are linear -- the second derivative vanishes.
160 }
161
162 virtual std::tuple<int,int,int,int> location() const
163 {
164 return std::make_tuple(1,dim-1,entity_,0);
165 }
166
171
175 Dune::FieldVector<CoordType,dim> edge() const { return edge_; }
176
177 private:
178 int entity_;
179 // p0_ and p1_ contain the barycentric coordinate into which the
180 // "from" and "to" points of the edge lie, respectively.
181 int p0_, p1_;
184 };
185
186 //--------------------------------------------------
187
188 template <class ctype, int dimension, class T>
189 class NedelecSimplexShapeFunctionSet: public ShapeFunctionSet<ctype,dimension,T,dimension>
190 {
191 static int const dim = dimension;
192 static int const noEdges = dim*(dim+1)/2; // number of edges
193
194
195 public:
197
199 ShapeFunctionSet<ctype,dim,T,dim>(Dune::GeometryType(Dune::GeometryType::simplex,dim))
200 {
201 auto const& simplex = Dune::ReferenceElements<ctype,dim>::simplex();
202 assert(noEdges == simplex.size(dim-1));
203
204 sf.reserve(noEdges);
205 for (int i=0; i<noEdges; ++i)
206 sf.push_back(value_type(i));
207
208 // The interpolation uses the fact that for any edge vector e_i of
209 // the reference simplex and any shape function phi_j evaluated on
210 // this edge it holds that <e_i,phi_j>=0 if i!=j. Thus we first
211 // store the tangential component <e_i,phi_i> for all shape
212 // functions.
213 this->iNodes.reserve(noEdges);
214 tangentialComponents.reserve(noEdges);
215 for (size_t i=0; i<noEdges; ++i) {
216 this->iNodes.push_back(sf[i].position());
217 tangentialComponents.push_back(sf[i].edge()*sf[i].evaluateFunction(sf[i].position()));
218 }
219
220 this->order_ = 1;
221 this->size_ = sf.size();
222 }
223
224 virtual value_type const& operator[](int i) const{ return sf[i]; }
225 virtual Dune::GeometryType type() const { return Dune::GeometryType(Dune::GeometryType::simplex,dim); }
226
240 {
241 assert(A.N()==noEdges);
242
243 IA.setSize(noEdges,A.M());
244 for (int i=0; i<noEdges; ++i)
245 for (int j=0; j<A.M(); ++j)
246 IA[i][j] = sf[i].edge()*asVector(A[i][j])/tangentialComponents[i];
247 }
248
249
250 private:
251 std::vector<value_type> sf;
252 std::vector<T> tangentialComponents;
253 };
254
255 //---------------------------------------------------------------------
256 //---------------------------------------------------------------------
257
258 template <class ctype, int dimension, class T>
259 class NedelecShapeFunctionSetContainer: public ShapeFunctionSetContainer<ctype,dimension,T,dimension>
260 {
261 public:
263
264 private:
265 typedef std::map<std::pair<Dune::GeometryType,int>,value_type const*> Container;
266
267 public:
268
270 {
271 // Fill the container with shape function sets. This is not done
272 // on demand in operator(), since then operator() is not easily
273 // and efficiently made thread-safe.
274 //
275 // Currently only shape functions for simplices are defined.
276 Dune::GeometryType simplex(Dune::GeometryType::simplex,dimension);
277 container.insert(typename Container::value_type(std::make_pair(simplex,1),new NedelecSimplexShapeFunctionSet<ctype,dimension,T>));
278 }
279
280
282 {
283 for (typename Container::iterator i=container.begin(); i!=container.end(); ++i)
284 delete i->second;
285 }
286
287 virtual value_type const& operator()(Dune::GeometryType type, int order) const
288 {
289 typename Container::const_iterator i = container.find(std::make_pair(type,order));
290 assert(i!=container.end()); // should throw, not assert!
291 return *i->second;
292 }
293
294 private:
295 // A map storing Nedelec shape function sets associated with
296 // (reference element type, order). Due to runtime polymorphism,
297 // pointers are stored in the map. This class owns the shape
298 // function sets pointed to, and has to delete them in the
299 // destructor.
300 Container container;
301 };
302
303
308 template <class ctype, int dimension, class T>
310 {
311 // This static variable will be destructed on program shutdown,
312 // causing its contents to be deleted properly from the heap by
313 // the destructor. No memory leaks should be induced.
315 return container(type,order);
316 }
317
318 //-------------------------------------------------------------------------------
319 //-------------------------------------------------------------------------------
320
332 template <class ctype, int dimension, class T>
333 class HdivSimplexShapeFunction: public ShapeFunction<ctype,dimension,T,dimension>
334 {
335 public:
336 static int const dim = dimension;
337 static int const comps = dim;
338 static int const order = 1;
339
340 typedef ctype CoordType;
341
348
356 template <class Coefficients>
357 explicit HdivSimplexShapeFunction(Coefficients const& coeff_, std::tuple<int,int,int,int> loc_)
358 : coeff(coeff_), loc(loc_), lsfs(lagrangeShapeFunctionSet<ctype,dimension>(Dune::GeometryType(Dune::GeometryType::simplex,dim),std::get<0>(loc)))
359 {
360 assert(coeff.size() == lsfs.size());
361 }
362
363 virtual std::unique_ptr<ShapeFunction<ctype,dim,T,dim>> clone() const
364 {
365 return std::unique_ptr<ShapeFunction<ctype,dim,T,dim>>(new HdivSimplexShapeFunction(*this));
366 }
367
376 {
378 for (int i=0; i<coeff.size(); ++i)
379 phi += lsfs[i].evaluateFunction(xi)[0] * coeff[i];
380 return phi;
381 }
382
390 {
392 for (int i=0; i<coeff.size(); ++i)
393 {
394 auto lsf = lsfs[i].evaluateDerivative(xi)[0]; // has only one component
395 for (int j=0; j<dim; ++j)
396 dphi[j] += coeff[i][j] * lsf;
397 }
398 return dphi;
399 }
400
410 {
411 Tensor<T,dim,dim,dim> ddphi(0);
412 for (int i=0; i<coeff.size(); ++i)
413 {
414 auto lsf = lsfs[i].evaluate2ndDerivative(xi)[0];// has only one component
415 for (int j=0; j<dim; ++j)
416 ddphi[j] += coeff[i][j] * lsf;
417 }
418 return ddphi;
419 }
420
421 virtual std::tuple<int,int,int,int> location() const
422 {
423 return loc;
424 }
425
426 private:
427 std::vector<Dune::FieldVector<T,comps>> coeff; // coefficients of Lagrangian shape functions.
428 std::tuple<int,int,int,int> loc; // location information
429 ShapeFunctionSet<ctype,dim,T> const& lsfs; // Lagrangian shape function set
430 };
431
432 //--------------------------------------------------
433
445 template <class ctype, int dimension, class T=double>
446 class HdivSimplexShapeFunctionSet: public ShapeFunctionSet<ctype,dimension,T,dimension>
447 {
448 static int const dim = dimension;
449
450
451 public:
453
459
460 virtual value_type const& operator[](int i) const{ return sf[i]; }
461
462 virtual Dune::GeometryType type() const { return Dune::GeometryType(Dune::GeometryType::simplex,dim); }
463
477 {
478 std::cerr << "not implemented\n";
479 abort(); // to be implemented
480 }
481
482
483 private:
484 std::vector<value_type> sf;
485 };
486
487 //---------------------------------------------------------------------
488 //---------------------------------------------------------------------
489
490 template <class ctype, int dimension, class T>
491 class HdivShapeFunctionSetContainer: public ShapeFunctionSetContainer<ctype,dimension,T,dimension>
492 {
493 public:
495
496 private:
497 typedef std::map<std::pair<Dune::GeometryType,int>,value_type const*> Container;
498
499 public:
500
502 {
503 // Fill the container with shape function sets. This is not done
504 // on demand in operator(), since then operator() is not easily
505 // and efficiently made thread-safe.
506 //
507 // Currently only shape functions for simplices are defined.
508 Dune::GeometryType simplex(Dune::GeometryType::simplex,dimension);
509 for (int order=1; order<6; ++order)
510 container.insert(typename Container::value_type(std::make_pair(simplex,order),new HdivSimplexShapeFunctionSet<ctype,dimension,T>(order)));
511 }
512
513
515 {
516 for (typename Container::iterator i=container.begin(); i!=container.end(); ++i)
517 delete i->second;
518 }
519
520 virtual value_type const& operator()(Dune::GeometryType type, int order) const
521 {
522 typename Container::const_iterator i = container.find(std::make_pair(type,order));
523 assert(i!=container.end()); // should throw, not assert!
524 return *i->second;
525 }
526
527 private:
528 // A map storing Hdiv shape function sets associated with
529 // (reference element type, order). Due to runtime polymorphism,
530 // pointers are stored in the map. This class owns the shape
531 // function sets pointed to, and has to delete them in the
532 // destructor.
533 Container container;
534 };
535
536
541 template <class ctype, int dimension, class T=double>
543 {
544 // This static variable will be destructed on program shutdown,
545 // causing its contents to be deleted properly from the heap by
546 // the destructor. No memory leaks should be induced.
548 return container(type,order);
549 }
550
551} // end of namespace Kaskade
552
553
554#endif
A LAPACK-compatible dense matrix class with shape specified at runtime.
virtual value_type const & operator()(Dune::GeometryType type, int order) const
access a shape function via type and order
ShapeFunctionSet< ctype, dimension, T, dimension > value_type
Vectorial conforming shape functions on the unit simplex.
virtual Dune::FieldMatrix< T, dim, dim > evaluateDerivative(Dune::FieldVector< CoordType, dim > const &xi) const
Evaluates the derivative of the shape function.
virtual Tensor< T, dim, dim, dim > evaluate2ndDerivative(Dune::FieldVector< CoordType, dim > const &xi) const
Evaluates the second derivative of the shape function.
virtual Dune::FieldVector< T, dim > evaluateFunction(Dune::FieldVector< ctype, dim > const &xi) const
Evaluates the shape function at point xi.
HdivSimplexShapeFunction(Coefficients const &coeff_, std::tuple< int, int, int, int > loc_)
Creates a shape function as a linear combination of Lagrangian shape functions.
virtual std::unique_ptr< ShapeFunction< ctype, dim, T, dim > > clone() const
virtual std::tuple< int, int, int, int > location() const
Returns a tuple (nominalOrder,codim,entity,index) giving detailed information about the location of t...
HdivSimplexShapeFunction()=default
Default constructor. Constructs a vanishing "shape function". Not particularly useful,...
A shape function set of conforming functions.
virtual Dune::GeometryType type() const
virtual value_type const & operator[](int i) const
Random access to a shape function.
HdivSimplexShapeFunctionSet(int order)
Constructs a conforming shape function set of given polynomial order.
virtual void interpolate(typename ShapeFunctionSet< ctype, dim, T, dim >::SfValueArray const &A, DynamicMatrix< Dune::FieldMatrix< T, 1, 1 > > &IA) const
Left-multiplies the provided matrix with the interpolation matrix of the shape function set.
HdivSimplexShapeFunction< ctype, dim, T > value_type
ShapeFunctionSet< ctype, dimension, T, dimension > value_type
virtual value_type const & operator()(Dune::GeometryType type, int order) const
access a shape function via type and order
Vectorial Nedelec shape functions on the unit simplex.
virtual Dune::FieldMatrix< ResultType, dim, dim > evaluateDerivative(Dune::FieldVector< CoordType, dim > const &x) const
Evaluates the derivative of the shape function.
Dune::FieldVector< CoordType, dim > position() const
Returns the element-local position of the node associated to the shape function.
virtual std::tuple< int, int, int, int > location() const
Returns a tuple (nominalOrder,codim,entity,index) giving detailed information about the location of t...
Dune::FieldVector< CoordType, dim > edge() const
Returns the edge vector of the edge associated to this shape function.
virtual Tensor< ResultType, 1, dim, dim > evaluate2ndDerivative(Dune::FieldVector< CoordType, dim > const &x) const
Evaluates the second derivative of the shape function.
virtual Dune::FieldVector< T, dim > evaluateFunction(Dune::FieldVector< ctype, dim > const &x) const
Evaluates the shape function at point x.
virtual Dune::GeometryType type() const
virtual value_type const & operator[](int i) const
Random access to a shape function.
virtual void interpolate(typename ShapeFunctionSet< ctype, dim, T, dim >::SfValueArray const &A, DynamicMatrix< Dune::FieldMatrix< T, 1, 1 > > &IA) const
Left-multiplies the provided matrix with the interpolation matrix of the shape function set.
NedelecSimplexShapeFunction< ctype, dim, T > value_type
Base class for sets of shape function containers.
A set of shape functions.
virtual int size() const
Number of shape functions in the set.
int order() const
Maximal polynomial order of shape functions.
A class for representing tensors of arbitrary static rank and extents.
Definition: tensor.hh:86
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::FieldMatrix< T, n, m > outerProduct(Dune::FieldVector< T, n > const &x, Dune::FieldVector< T, m > const &y)
outer vector product .
Definition: fixdune.hh:164
Dune::FieldVector< T, n *m > asVector(Dune::FieldMatrix< T, n, m > const &x)
Converts a matrix of size n x m to a vector of size n*m by concatenating all the columns.
Definition: fixdune.hh:135
define Lagrange type shape functions for simplicial elements of arbitrary dimension and order
NedelecShapeFunctionSetContainer< ctype, dimension, T >::value_type const & nedelecShapeFunctionSet(Dune::GeometryType type, int order)
LagrangeShapeFunctionSetContainer< ctype, dimension, Scalar, restricted >::value_type const & lagrangeShapeFunctionSet(Dune::GeometryType type, int order)
Returns a Lagrange shape function set for given reference element type and given polynomial order....
HdivShapeFunctionSetContainer< ctype, dimension, T >::value_type const & hdivShapeFunctionSet(Dune::GeometryType type, int order)
Returns a Hdiv shape function set for given reference element type and given polynomial order....