KASKADE 7 development version
lagrangespace.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-2023 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 LAGRANGESPACE_HH
14#define LAGRANGESPACE_HH
15
16#include <cmath>
17#include <numeric>
18#include <tuple>
19
20#include "boost/multi_array.hpp"
21
22#include "dune/grid/common/capabilities.hh"
23
24#include "fem/converter.hh"
25#include "fem/fixdune.hh"
27#include "fem/functionspace.hh"
29#include "fem/scalarspace.hh"
30
38namespace Kaskade
39{
49 template <class ScalarType, class GV, bool restricted=false>
51 {
52 public:
54
55 typedef GV GridView;
56 typedef typename GridView::Grid Grid;
57 typedef typename GridView::IndexSet IndexSet;
59
60 using ctype = typename Grid::ctype;
61
62 static int const dim = Grid::dimension;
63
65
72 void update()
73 {}
74
75
79 IndexSet const& indexSet() const { return gv.indexSet(); }
80
87 size_t size(Dune::GeometryType gt) const
88 {
89 return indexSet().size(gt);
90 }
91
97 bool inSupport(Cell const& cell) const
98 {
99 return true;
100 }
101
105 typename IndexSet::IndexType subIndex(Cell const& cell, int subentity, int codim) const
106 {
107 return indexSet().subIndex(cell,subentity,codim);
108 }
109
110
111 GridView const& gridView() const { return gv; }
112
117 LagrangeMapperImplementation(GridView const& gridView_, int order_)
118 : ord(order_)
119 , gv(gridView_)
120 {
121 simplexSFS = &lagrangeShapeFunctionSet<ctype,dim,Scalar,restricted>(
122 Dune::GeometryType(Dune::GeometryType::simplex,dim),ord);
123
124 // Cube shape functions are not yet defined for arbitrary order, thus obtaining them may throw.
125 // Ignore this, as the grid may not contain any cubes...
126 try
127 {
128 cubeSFS = &lagrangeShapeFunctionSet<ctype,dim,Scalar,restricted>(Dune::GeometryType(Dune::GeometryType::cube,dim),ord);
129 }
130 catch(...)
131 {
132 cubeSFS = nullptr;
133 };
134 }
135
136 ShapeFunctionSet const& shapeFunctions(Cell const& cell) const
137 {
138 if (cell.type().isSimplex())
139 return *simplexSFS;
140 if (cell.type().isCube())
141 if (cubeSFS)
142 return *cubeSFS;
143 else
144 throw LookupException("No Lagrangian shape functions on cubes defined.\n",__FILE__,__LINE__);
145 else
146 throw LookupException("Not supported geometry type.\n",__FILE__,__LINE__);
147 }
148
149 ShapeFunctionSet const& lowerShapeFunctions(Cell const& cell) const
150 {
151 return lagrangeShapeFunctionSet<ctype,dim,Scalar,restricted>(cell.type(),ord-1);
152 }
153
155 {
157 return empty;
158 }
159
160 int order() const { return ord; }
161
162
164
175 {
176 public:
177 template <class GlobalIndices>
178 Combiner(GlobalIndices const& globalIndices, ShapeFunctionSet const& sfs)
179 : m(globalIndices.size())
180 , n(sfs.size())
181 {
182 // We support Lagrange spaces where cells either have full support (i.e., shape
183 // functions correspond one-to-one to ansatz functions, n==m) or no support (i.e.,
184 // there are no dofs at all, m==0, though shape functions may be defined, n>0).
185 assert(m==0 || n==m);
186 }
187
192 template <class Matrix>
193 void rightTransform(Matrix& A) const
194 {
195 assert(A.M()==n);
196 if (m==0)
197 A.resize(A.N(),0);
198 }
199
201 template <int d, int k>
202 void rightTransform(std::vector<VariationalArg<Scalar,d,k>>& v) const
203 {
204 assert(v.size()==n);
205 if (m==0)
206 v.clear();
207 }
208
210 template <class Matrix>
211 void leftPseudoInverse(Matrix& A) const
212 {
213 assert(A.N()==n);
214 if (m==0)
215 A.resize(0,A.M());
216 }
217
220 operator Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1>>() const
221 {
222 Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1>> K(m,m,Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1> >::random);
223 for (int i=0; i<m; ++i)
224 K.incrementrowsize(i);
225 K.endrowsizes();
226 for (int i=0; i<m; ++i)
227 K.addindex(i,i);
228 K.endindices();
229 for (int i=0; i<m; ++i)
230 *K[i].begin() = 1;
231 return K;
232 }
233
234 private:
235 int m; // the number of ansatz functions (dofs) on the current cell
236 int n; // the number of shape functions on the current cell
237 };
238
239 private:
240 int ord;
241 GridView gv;
242 ShapeFunctionSet const* simplexSFS;
243 ShapeFunctionSet const* cubeSFS;
244 };
245
246
247 //---------------------------------------------------------------------
248 //---------------------------------------------------------------------
249
250
251 template <class ScalarType, class GV>
253 {
255 typedef typename Base::Cell Cell;
256
257 public:
260 {}
261
262 // Returns the number of degrees of freedom (global ansatz
263 // functions) uniquely associated to the given subentity type.
264 int dofOnEntity(Dune::GeometryType gt) const
265 {
266 int const ord = this->order();
267 int const dim = GV::Grid::dimension;
268
269
270 if (gt.dim() == dim) // dofs live only on codim 0 entities (cells).
271 {
272 if ( gt.isSimplex() )
273 {
274 if (dim==1) return ord+1;
275 if (dim==2) return (ord+1)*(ord+2)/2;
276 if (dim==3) return (ord+1)*(ord+2)*(ord+3)/6;
277 assert("Unknown dimension"==0);
278 }
279 if ( gt.isCube() ) return pow(ord+1,dim);
280 if ( gt.isPyramid() || gt.isPrism() || gt.isNone() ) assert( "Not implemented"==0);
281 }
282
283 // subentities with codim > 0 do not carry local degrees of freedom
284 return 0;
285 }
286
287 // Returns the geometry type, subentity number in cell and subentity
288 // codimension for the subentity to which the dof is
289 // associated. Here we have a discontinuous discretization, where
290 // all dofs are associated to the cells.
291 template <class ShapeFunction, class Dummy>
292 void entityIndex(Cell const& cell, ShapeFunction const& sf, int n,
293 Dune::GeometryType& gt, int& subentity, int& codim, int& indexInSubentity, Dummy&) const
294 {
295 gt = cell.type();
296 subentity = 0;
297 codim = 0;
298 indexInSubentity = n;
299 }
300 };
301
302
310 template <class ScalarType, class GV>
312 public UniformScalarMapper<DiscontinuousLagrangeMapperImplementation<ScalarType,GV> >
313 {
317
318 public:
319 typedef GV GridView;
321 static int const continuity = -1;
322
329 template <int m>
331
332 template <int m>
333 struct [[deprecated]] Element
334 {
336 };
337
338
341 {}
342 };
343
344 template <class ScalarType, class GV>
346 public UniformScalarMapper<DiscontinuousLagrangeMapperImplementation<ScalarType,GV> >
347 {
351
352 public:
353 typedef GV GridView;
355 static int const continuity = -1;
356
363 template <int m>
365
366 template <int m>
367 struct [[deprecated]] Element
368 {
370 };
371
372
375 {}
376 };
377
378 //---------------------------------------------------------------------
379
380 template <class ScalarType, class GV, class ShapeFunctionFilter=ScalarSpaceDetail::AllShapeFunctions>
382 : public LagrangeMapperImplementation<ScalarType,GV,std::is_same<ShapeFunctionFilter,ScalarSpaceDetail::RestrictToBoundary>::value>,
383 public ShapeFunctionFilter
384 {
386
387 public:
388 typedef typename GV::IndexSet IndexSet;
390 typedef GV GridView;
391 using Cell = typename Base::Cell;
392
393 ContinuousLagrangeMapperImplementation(GV const& gridView, int order, ShapeFunctionFilter shapeFunctionFilter=ShapeFunctionFilter())
394 : Base(gridView,order), ShapeFunctionFilter(shapeFunctionFilter)
395 {
396 }
397
398
403 int dofOnEntity(Dune::GeometryType gt) const
404 {
405 int const ord = this->order();
406
407 if(gt.isSimplex())
408 {
409 if (gt.dim()==0) return 1;
410 if (gt.dim()==1) return ord-1;
411 if (gt.dim()==2) return std::max(0,(ord-2)*(ord-1)/2);
412 if (gt.dim()==3) return std::max(0,(ord-3)*(ord-2)*(ord-1)/6);
413 assert("Unknown dimension"==0);
414 }
415 if(gt.isCube()) return std::max(0.0,pow(ord-1,gt.dim()));
416 if(gt.isPyramid() || gt.isPrism()) assert("Not implemented"==0);
417
418 assert("Unknown geometry type"==0);
419
420 return -1;
421 }
422
436 template <class ShapeFunction, class Data>
437 void entityIndex(Cell const& cell, ShapeFunction const& sf, int n,
438 Dune::GeometryType& gt, int& subentity, int& codim, int& indexInSubentity, Data& data) const
439 {
440 int const dim = Cell::dimension;
441 int const ord = this->order();
442 IndexSet const& is = this->indexSet();
443
444 int dummy;
445 std::tie(dummy,codim,subentity,indexInSubentity) = sf.location();
446
447 // Obtain geometry type of the subentity on which the shape function lives.
448 // As we assume that all cells are either simplices or hexahedra, there is only
449 // one geometry type per codimension.
450 gt = is.types(codim)[0]; // limited to just one geometry type....
451
452 // implementation below assumes simplicial cells
453 assert(gt.isSimplex());
454
455 // local index is globally unique in the interior of the cell and
456 // on the vertices. Otherwise we need to compute a globally unique
457 // numbering based on the global numbering of incident vertices.
458 if (codim>0 && codim<dim && ord>2)
459 {
460 // Obtain the local barycentric index of the shape function.
461 std::array<int,dim+1> xi = barycentric(SimplexLagrangeDetail::tupleIndex<dim>(ord,n),ord);
462
463 int nVertices = dim+1-codim;
464
465 // Obtain a globally unique sorting of the barycentric coordinates, and extract
466 // the corresponding permutation and selection of the barycentric coordinates
467 // in our subentity.
469 int pi[nVertices];
470 gbp.barycentricSubsetPermutation(subentity,codim,pi);
471
472 // Since here the node is not located on a lower dimensional
473 // subentity, we know that all barycentric indices are at least 1. Therefore we
474 // may restrict ourselves to the interior nodes by subtracting 1
475 // from all barycentric indices. Note that the "order" associated
476 // with these interior nodes shrinks by 1+dimension(our subentity),
477 // i.e. dim+1-codim !
478 int idx[nVertices];
479 for (int i=0; i<nVertices; ++i)
480 idx[i] = xi[pi[i]]-1;
481
482 // Finally we compute the local index of this permuted node within the
483 // interior of our subentity.
484 indexInSubentity = SimplexLagrangeDetail::local(idx,dim-codim,ord-nVertices);
485 }
486
487 // consider restrictions to the boundary here
488 this->treatBoundary(data,this->gridView(),cell,codim,subentity);
489 }
490
491 };
492
500 template <class ScalarType, class GV>
502 : public UniformScalarMapper<ContinuousLagrangeMapperImplementation<ScalarType,GV> >
503 {
506
507 public:
509 typedef GV GridView;
512 static int const continuity = 0;
513
520 template <int m>
522
523 template <int m>
524 struct [[deprecated]] Element
525 {
527 };
528
536 {
537 assert(order >= 1);
538 }
539 };
540
541 // --------------------------------------------------------------------------------------------
542 // --------------------------------------------------------------------------------------------
543
544 template <class GV, class SupportOracle, class ScalarType=double>
546 : public ContinuousLagrangeMapperImplementation<ScalarType,GV>
547 {
549 using Index = typename GV::IndexSet::IndexType;
550
551 public:
552 using GridView = GV;
553
555 SupportOracle&& supportOracle_)
557 , supportOracle(std::move(supportOracle_))
558 {}
559
560 void update()
561 {
562 auto const& gv = this->gridView();
563 auto const& is = gv.indexSet();
564 int const dim = GV::dimension;
565
566 // For each entity in the grid, create a char, which we can use to
567 // flag whether this has already been seen or not.
568 support.clear();
569
570 for (int codim=0; codim<=dim; ++codim) // For each entity codimension...
571 for(auto const& geoType: is.types(codim)) // ... and each geometry type of that codimension...
572 {
573 auto& idx = support[geoType]; // create the flag vector ...
574 idx.resize(is.size(geoType),-1); // ... with as many flags as there are entities of
575 } // this type in the index set, and initialize them to -1.
576
577
578 // Now step through all entities in the support. This is the closure of the cells within the support.
579 // Thus, we step through all the cells and flag them as well as all their subentities.
580 Dune::GeometryType cellGeometryType;
581 for (auto const& cell : elements(gv))
582 {
583 cellGeometryType = cell.type();
584 size_t const cellIndex = is.index(cell);
585
586 if (supportOracle(cell))
587 {
588 support[cellGeometryType][cellIndex] = 0;
589 auto refElem = referenceElement(cell.geometry());
590
591 // Now step through all subentities (as we have processed the cell itself already, we
592 // start with codimension 1). For all the subentities we obtain their geometry type
593 // and index and flag them with 1 as within the support.
594 for (int codim=1; codim<=dim; ++codim)
595 for (int i=0; i<refElem.size(codim); ++i)
596 support[refElem.type(i,codim)][is.subIndex(cell,i,codim)] = 0;
597 }
598 }
599
600 // Now count how many entities of a given geometry type are within our support.
601 supportSize.clear();
602 for (auto& p: support)
603 {
604 // Assign global indices to subentities in the support by incrementing a counter.
605 long idx = 0;
606 for (size_t i=0; i<p.second.size(); ++i)
607 if (p.second[i] >= 0)
608 p.second[i] = idx++;
609
610 // ... which in the end also yields the total number of entities of a given type.
611 supportSize[p.first] = idx;
612 }
613 }
614
618 size_t size(Dune::GeometryType gt) const
619 {
620 return supportSize.find(gt)->second;
621 }
622
628 bool inSupport(typename Base::Cell const& cell) const
629 {
630 auto it = support.find(cell.type());
631 if (it==support.end())
632 return false;
633 return it->second[this->indexSet().index(cell)] >= 0;
634 }
635
636 Index subIndex(typename Base::Cell const& cell, int subentity, int codim) const
637 {
638 auto subentityGeometryType = referenceElement(cell).type(subentity,codim);
639 auto it = support.find(subentityGeometryType);
640
641 if (it==support.end())
642 throw LookupException("Geometry type of provided cell not contained in the index set.",__FILE__,__LINE__);
643
644 auto const& s = it->second;
645 return s[this->indexSet().subIndex(cell,subentity,codim)];
646 }
647
648 private:
649 SupportOracle supportOracle;
650 std::map<Dune::GeometryType,size_t> supportSize;
651 std::map<Dune::GeometryType,std::vector<long>> support;
652 };
653
654
673 template <class GV, class SupportOracle, class ScalarType=double>
675 : public UniformScalarMapper<ContinuousLagrangeMapperSubdomainImplementation<GV,SupportOracle,ScalarType>>
676 {
679
680 public:
682 typedef GV GridView;
685
692 static int const continuity = -1;
693
700 template <int m>
702
703 template <int m>
704 struct [[deprecated]] Element
705 {
707 };
708
715 ContinuousLagrangeMapperSubdomain(GridView const& gridView, int order, SupportOracle&& supportOracle)
716 : Base(Implementation(gridView,order,std::move(supportOracle)))
717 {
718 assert(order >= 1);
719 }
720 };
721
722
723
724}
725
726#endif
A degrees of freedom manager for globally continuous FEFunctionSpace s of piecewise polynomials.
ContinuousLagrangeMapper(GridView const &gridView, int order)
Constructor.
Base::ShapeFunctionSet ShapeFunctionSet
int dofOnEntity(Dune::GeometryType gt) const
Returns the number of degrees of freedom (global ansatz functions) uniquely associated to the given s...
ContinuousLagrangeMapperImplementation(GV const &gridView, int order, ShapeFunctionFilter shapeFunctionFilter=ShapeFunctionFilter())
void entityIndex(Cell const &cell, ShapeFunction const &sf, int n, Dune::GeometryType &gt, int &subentity, int &codim, int &indexInSubentity, Data &data) const
Returns the geometry type, subentity number in cell and subentity codimension for the subentity to wh...
A local-to-global mapper for continuous finite elements on a subdomain.
static int const continuity
Continuity of the functions in this space. If the support is restricted to a proper subdomain,...
ContinuousLagrangeMapperSubdomain(GridView const &gridView, int order, SupportOracle &&supportOracle)
Constructor.
ContinuousLagrangeMapperSubdomainImplementation(GridView const &gridView, int order, SupportOracle &&supportOracle_)
bool inSupport(typename Base::Cell const &cell) const
Tells whether the given cell is contained in the support.
Index subIndex(typename Base::Cell const &cell, int subentity, int codim) const
size_t size(Dune::GeometryType gt) const
Returns the number of entities of given geometry type in our support.
A degrees of freedom manager for FEFunctionSpace s of piecewise polynomials of order Order.
DiscontinuousLagrangeMapper(GridView const &gridView, int order)
int dofOnEntity(Dune::GeometryType gt) const
void entityIndex(Cell const &cell, ShapeFunction const &sf, int n, Dune::GeometryType &gt, int &subentity, int &codim, int &indexInSubentity, Dummy &) const
DiscontinuousLagrangeMapperImplementation(GV const &gridView, int order)
DiscontinuousLagrangeMapperSubdomain(GridView const &gridView, int order)
A class for representing finite element functions.
A class for computing permutations of local vertex numbers of simplex subentities to a globally uniqu...
std::array< int, dimension+1-codim > barycentricSubsetPermutation(int e) const
Computes a permutation of barycentric coordinates to globally unique ordering.
A class implementing a matrix mapping a subset of global degrees of freedom (those given by globalI...
Combiner(GlobalIndices const &globalIndices, ShapeFunctionSet const &sfs)
void rightTransform(Matrix &A) const
In-place computation of . Since is the identity, this is a no-op.
void rightTransform(std::vector< VariationalArg< Scalar, d, k > > &v) const
In-place computation of row vectors .
void leftPseudoInverse(Matrix &A) const
In-place computation of .
A local to global mapper for scalar Lagrange bases.
typename LagrangeShapeFunctionSetContainer< ctype, dim, Scalar, restricted >::value_type ShapeFunctionSet
bool inSupport(Cell const &cell) const
Tells whether the given cell is contained in the support.
IndexSet::IndexType subIndex(Cell const &cell, int subentity, int codim) const
Returns the index of the specified subentity.
ShapeFunctionSet const & shapeFunctions(Cell const &cell) const
ShapeFunctionSet const & lowerShapeFunctions(Cell const &cell) const
ShapeFunctionSet const & emptyShapeFunctionSet() const
void update()
This is called on grid modifications and can be overwritten if internal data needs to be recomputed o...
size_t size(Dune::GeometryType gt) const
The number of entities of given geometry type in our support.
GridView const & gridView() const
Kaskade::Cell< GridView > Cell
ScalarConverter< Cell, Scalar > Converter
LagrangeMapperImplementation(GridView const &gridView_, int order_)
IndexSet const & indexSet() const
The index set obtained from gridView().
An exception that can be thrown whenever a key lookup fails.
A Converter for scalar shape functions that do not change their value under transformation from refer...
Definition: converter.hh:62
virtual std::tuple< int, int, int, int > location() const =0
Returns a tuple (nominalOrder,codim,entity,index) giving detailed information about the location of t...
A set of shape functions.
Base class for uniform scalar local to global mappers.
Definition: scalarspace.hh:205
Implementation::ShapeFunctionSet ShapeFunctionSet
Definition: scalarspace.hh:209
This file contains various utility functions that augment the basic functionality of Dune.
FEFunctionSpace and FunctionSpaceElement and the like.
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Definition: gridBasics.hh:35
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
define Lagrange type shape functions for simplicial elements of arbitrary dimension and order
typename GetScalar< Type >::type ScalarType
Extracts the scalar field type from linear algebra data types.
FunctionSpaceElement< FEFunctionSpace< ContinuousLagrangeMapper >, m > type
FunctionSpaceElement< FEFunctionSpace< ContinuousLagrangeMapperSubdomain >, m > type
FunctionSpaceElement< FEFunctionSpace< Self >, m > type
FunctionSpaceElement< FEFunctionSpace< Self >, m > type
void treatBoundary(Data &, GridView const &, Cell const &, int, int) const
Definition: scalarspace.hh:162
A class that stores values, gradients, and Hessians of evaluated shape functions.