DUNE-FUNCTIONS (unstable)

cubichermitebasis.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_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
5 
6 #include <dune/common/exceptions.hh>
7 #include <dune/common/tuplevector.hh>
8 
9 #include <dune/grid/common/capabilities.hh>
10 #include <dune/grid/common/mcmgmapper.hh>
11 #include <dune/grid/common/rangegenerators.hh>
12 
13 #include <dune/localfunctions/common/localfiniteelementvariant.hh>
14 #include <dune/localfunctions/rannacherturek.hh>
15 #include <dune/localfunctions/crouzeixraviart.hh>
16 
17 #include <dune/functions/functionspacebases/nodes.hh>
18 #include <dune/functions/functionspacebases/defaultglobalbasis.hh>
19 #include <dune/functions/functionspacebases/leafprebasismappermixin.hh>
20 
21 
22 namespace Dune {
23 namespace Functions {
24 
25 namespace Impl {
26 
27  // Helper function returning an unordered range
28  // of global indices associated to the element.
29  // This could be implemented cheaper internally in
30  // the MCMGMapper by storing a precomputed
31  // container of all subsentities addressed by the layout.
32  template<class GridView>
33  auto subIndexSet(const Dune::MultipleCodimMultipleGeomTypeMapper<GridView>& mapper, const typename GridView::template Codim<0>::Entity& element)
34  {
35  using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
36  using Index = typename Mapper::Index;
37  constexpr auto dimension = GridView::dimension;
38  auto subIndices = std::vector<Index>();
39  auto referenceElement = Dune::referenceElement<double, dimension>(element.type());
40  for(auto codim : Dune::range(dimension+1))
41  {
42  for(auto subEntity : Dune::range(referenceElement.size(codim)))
43  {
44  std::size_t c = mapper.layout()(referenceElement.type(subEntity, codim), dimension);
45  if (c>0)
46  {
47  std::size_t firstIndex = mapper.subIndex(element, subEntity, codim);
48  for(auto j : Dune::range(firstIndex, firstIndex+c))
49  {
50  subIndices.push_back(j);
51  }
52  }
53  }
54  }
55  return subIndices;
56  }
57 
58  // Helper function computing an average mesh size per subentity
59  // by averaging over the adjacent elements. This only considers
60  // the subentities handled by the given mapper and returns a
61  // vector of mesh sizes indixed according to the mapper.
62  template<class Mapper>
63  auto computeAverageSubEntityMeshSize(const Mapper& mapper)
64  {
65  constexpr auto dimension = Mapper::GridView::dimension;
66 
67  std::vector<unsigned int> adjacentElements(mapper.size(), 0);
68  std::vector<double> subEntityMeshSize(mapper.size(), 0.0);
69  for(const auto& element : Dune::elements(mapper.gridView()))
70  {
71  auto A = element.geometry().volume();
72  for(auto i : Impl::subIndexSet(mapper, element))
73  {
74  subEntityMeshSize[i] += A;
75  ++(adjacentElements[i]);
76  }
77  }
78  for(auto i : Dune::range(mapper.size()))
79  subEntityMeshSize[i] = std::pow(subEntityMeshSize[i]/adjacentElements[i], 1./dimension);
80  return subEntityMeshSize;
81  }
82 
83 
84 
85 // *****************************************************************************
86 // * Some helper functions for building polynomial bases from monomials
87 // *****************************************************************************
88 
89 // Evaluation of 1d monomial values
90 template<class K>
91 static constexpr auto evaluateMonomialValues(const Dune::FieldVector<K,1>& x)
92 {
93  using Range = Dune::FieldVector<K,1>;
94  constexpr std::size_t maxOrder=3;
95  constexpr std::size_t size = (maxOrder+1);
96  auto xPowers = std::array<double,maxOrder+1>{};
97  xPowers[0] = 1.0;
98  for(auto k: Dune::range(maxOrder))
99  xPowers[k+1] = xPowers[k]*x[0];
100  auto y = Dune::FieldVector<Range,size>{};
101  for(auto order : Dune::range(maxOrder+1))
102  y[order] = xPowers[order];
103  return y;
104 }
105 
106 // Evaluation of 1d monomial jacobians
107 template<class K>
108 static constexpr auto evaluateMonomialJacobians(const Dune::FieldVector<K,1>& x)
109 {
110  using Jacobian = Dune::FieldMatrix<K,1,1>;
111  constexpr std::size_t maxOrder=3;
112  constexpr std::size_t size = (maxOrder+1);
113  auto xPowers = std::array<double,maxOrder+1>{};
114  xPowers[0] = 1.0;
115  for(auto k: Dune::range(maxOrder))
116  xPowers[k+1] = xPowers[k]*x[0];
117  auto y = Dune::FieldVector<Jacobian,size>{};
118  for(auto order : Dune::range(std::size_t(1), maxOrder+1))
119  y[order][0][2] = order*xPowers[order-1];
120  return y;
121 }
122 
123 // Evaluation of 2d monomial values
124 template<class K>
125 static constexpr auto evaluateMonomialValues(const Dune::FieldVector<K,2>& x)
126 {
127  using Range = Dune::FieldVector<K,1>;
128  constexpr std::size_t maxOrder=3;
129  constexpr std::size_t dim=2;
130  constexpr std::size_t size = (maxOrder+1)*(maxOrder+2)/2;
131  auto xPowers = std::array<std::array<double,maxOrder+1>,dim>{};
132  for(auto j: Dune::range(dim))
133  {
134  xPowers[j][0] = 1.0;
135  for(auto k: Dune::range(maxOrder))
136  xPowers[j][k+1] = xPowers[j][k]*x[j];
137  }
138  auto y = Dune::FieldVector<Range,size>{};
139  std::size_t index=0;
140  for(auto order : Dune::range(maxOrder+1))
141  {
142  for(auto k : Dune::range(order+1))
143  {
144  y[index] = xPowers[0][order-k]*xPowers[1][k];
145  ++index;
146  }
147  }
148  return y;
149 }
150 
151 // Evaluation of 2d monomial jacobians
152 template<class K>
153 static constexpr auto evaluateMonomialJacobians(const Dune::FieldVector<K,2>& x)
154 {
155  using Jacobian = Dune::FieldMatrix<K,1,2>;
156  constexpr std::size_t maxOrder=3;
157  constexpr std::size_t dim=2;
158  constexpr std::size_t size = (maxOrder+1)*(maxOrder+2)/2;
159  auto xPowers = std::array<std::array<double,maxOrder+1>,dim>{};
160  for(auto j: Dune::range(dim))
161  {
162  xPowers[j][0] = 1.0;
163  for(auto k: Dune::range(maxOrder))
164  xPowers[j][k+1] = xPowers[j][k]*x[j];
165  }
166  auto y = Dune::FieldVector<Jacobian,size>{};
167  std::size_t index=0;
168  for(auto order : Dune::range(maxOrder+1))
169  {
170  for(auto k : Dune::range(order+1))
171  {
172  if (order-k>0)
173  y[index][0][0] = (order-k)*xPowers[0][order-k-1]*xPowers[1][k];
174  if (k>0)
175  y[index][0][1] = k*xPowers[0][order-k]*xPowers[1][k-1];
176  ++index;
177  }
178  }
179  return y;
180 }
181 
182 
183 
184 // *****************************************************************************
185 // * CubicHermiteLocalFiniteElement
186 // *****************************************************************************
187 
188 
189 
190 template<class DF, class RF, unsigned int dim, bool reduced>
191 class CubicHermiteLocalBasis
192 {
193 
194  static constexpr auto makeReferenceBasisCoefficients() {
195  if constexpr (dim==1)
196  return Dune::FieldMatrix<int,4,4>{
197  { 1, 0, -3, 2},
198  { 0, 1, -2, 1},
199  { 0, 0, 3, -2},
200  { 0, 0, -1, 1}
201  };
202  if constexpr ((dim==2) and (not reduced))
203  return Dune::FieldMatrix<int,10,10>{
204  { 1, 0, 0, -3, -13, -3, 2, 13, 13, 2},
205  { 0, 1, 0, -2, -3, 0, 1, 3, 2, 0},
206  { 0, 0, 1, 0, -3, -2, 0, 2, 3, 1},
207  { 0, 0, 0, 3, -7, 0, -2, 7, 7, 0},
208  { 0, 0, 0, -1, 2, 0, 1, -2, -2, 0},
209  { 0, 0, 0, 0, -1, 0, 0, 2, 1, 0},
210  { 0, 0, 0, 0, -7, 3, 0, 7, 7, -2},
211  { 0, 0, 0, 0, -1, 0, 0, 1, 2, 0},
212  { 0, 0, 0, 0, 2, -1, 0, -2, -2, 1},
213  { 0, 0, 0, 0, 27, 0, 0, -27, -27, 0}
214  };
215  if constexpr ((dim==2) and (reduced))
216  {
217  auto w = std::array{1./3, 1./18, 1./18, 1./3, -1./9, 1./18, 1./3, 1./18, -1./9};
218  return Dune::FieldMatrix<double,9,10>{
219  { 1, 0, 0, -3, -13 + w[0]*27, -3, 2, 13 - w[0]*27, 13 - w[0]*27, 2},
220  { 0, 1, 0, -2, -3 + w[1]*27, 0, 1, 3 - w[1]*27, 2 - w[1]*27, 0},
221  { 0, 0, 1, 0, -3 + w[2]*27, -2, 0, 2 - w[2]*27, 3 - w[2]*27, 1},
222  { 0, 0, 0, 3, -7 + w[3]*27, 0, -2, 7 - w[3]*27, 7 - w[3]*27, 0},
223  { 0, 0, 0, -1, 2 + w[4]*27, 0, 1, -2 - w[4]*27, -2 - w[4]*27, 0},
224  { 0, 0, 0, 0, -1 + w[5]*27, 0, 0, 2 - w[5]*27, 1 - w[5]*27, 0},
225  { 0, 0, 0, 0, -7 + w[6]*27, 3, 0, 7 - w[6]*27, 7 - w[6]*27, -2},
226  { 0, 0, 0, 0, -1 + w[7]*27, 0, 0, 1 - w[7]*27, 2 - w[7]*27, 0},
227  { 0, 0, 0, 0, 2 + w[8]*27, -1, 0, -2 - w[8]*27, -2 - w[8]*27, 1},
228  };
229  }
230  }
231 
232  // These are the coefficients of the cubic Hermite basis functions
233  // on the reference element wrt. the monomials. These have been computed
234  // by solving with the corresponiding Vandermonde-matrix for the reference
235  // element in advance.
236  // The basis functions can be evaluated by first evaluating the monomials
237  // and then transforming their values with these coefficients using
238  //
239  // referenceBasisCoefficients.mv(evaluateMonomialValues(x), values);
240  //
241  // Surprisingly, storing them as static constexpr member is slightly faster
242  // than using the static constexpr function directly.
243  static constexpr auto referenceBasisCoefficients = makeReferenceBasisCoefficients();
244 
245  // This transforms the function or derivative values from the basis
246  // functions on the reference element to those on the grid element.
247  // Since Hermite elements do not form an affine family, the transformation
248  // of derivative DOFs involves the Jacobian of the grid element transformation.
249  // To avoid blowup of condition numbers due to h-dependend basis functions,
250  // an h-dependent rescaling is applied.
251  template<class LambdaRefValues, class Entry>
252  void transformToElementBasis(const LambdaRefValues& refValues, std::vector<Entry>& out) const
253  {
254  if constexpr (dim==1)
255  {
256  const auto& J = elementJacobian_;
257  out.resize(refValues.size());
258  out[0] = refValues[0];
259  out[1] = J*refValues[1] / (*localSubEntityMeshSize_)[1];
260  out[2] = refValues[2];
261  out[3] = J*refValues[3] / (*localSubEntityMeshSize_)[1];;
262  }
263  if constexpr (dim==2)
264  {
265  const auto& J = elementJacobian_;
266  out.resize(refValues.size());
267  out[0] = refValues[0];
268  out[1] = (J[0][0]*refValues[1] + J[0][1]*refValues[2]) / (*localSubEntityMeshSize_)[1];
269  out[2] = (J[1][0]*refValues[1] + J[1][1]*refValues[2]) / (*localSubEntityMeshSize_)[2];
270  out[3] = refValues[3];
271  out[4] = (J[0][0]*refValues[4] + J[0][1]*refValues[5]) / (*localSubEntityMeshSize_)[4];
272  out[5] = (J[1][0]*refValues[4] + J[1][1]*refValues[5]) / (*localSubEntityMeshSize_)[5];
273  out[6] = refValues[6];
274  out[7] = (J[0][0]*refValues[7] + J[0][1]*refValues[8]) / (*localSubEntityMeshSize_)[7];
275  out[8] = (J[1][0]*refValues[7] + J[1][1]*refValues[8]) / (*localSubEntityMeshSize_)[8];
276  if constexpr (not reduced)
277  out[9] = refValues[9];
278  }
279  }
280 
281  using ElementJacobian = Dune::FieldMatrix<DF, dim,dim>;
282 
283  using LocalSubEntityMeshSize = std::vector<double>;
284 
285 public:
286 
287  using Domain = Dune::FieldVector<DF, dim>;
288  using Range = Dune::FieldVector<RF, 1>;
289  using Jacobian = Dune::FieldMatrix<RF, 1, dim>;
290  using Traits = Dune::LocalBasisTraits<DF, dim, Domain, RF, 1, Range, Jacobian>;
291  using OrderArray = std::array<unsigned int, dim>;
292 
293  static constexpr unsigned int size()
294  {
295  return decltype(referenceBasisCoefficients)::rows;
296  }
297 
298  inline void evaluateFunction(const Domain& x, std::vector<Range>& values) const
299  {
300  auto monomialValues = evaluateMonomialValues(x);
301  auto referenceValues = Dune::FieldVector<Range, size()>{};
302  referenceBasisCoefficients.mv(monomialValues, referenceValues);
303  transformToElementBasis(referenceValues, values);
304  }
305 
306  inline void evaluateJacobian(const Domain& x, std::vector<Jacobian>& jacobians) const
307  {
308  auto monomialJacobians = evaluateMonomialJacobians(x);
309  auto referenceJacobians = Dune::FieldVector<Jacobian, size()>{};
310  referenceBasisCoefficients.mv(monomialJacobians, referenceJacobians);
311  transformToElementBasis(referenceJacobians, jacobians);
312  }
313 
314  void partial(const OrderArray& order, const Domain& x, std::vector<Range>& out) const
315  {
316  auto totalOrder = std::accumulate(order.begin(), order.end(), 0);
317  if (totalOrder == 0)
318  evaluateFunction(x, out);
319  DUNE_THROW(RangeError, "partial() not implemented for given order");
320  }
321 
322  unsigned int order() const
323  {
324  return 3;
325  }
326 
327  template<class Element>
328  void bind(const Element& element, const LocalSubEntityMeshSize& localSubEntityMeshSize) {
329  localSubEntityMeshSize_ = &localSubEntityMeshSize;
330  auto center = Dune::ReferenceElements<DF, dim>::simplex().position(0, 0);
331  elementJacobian_ = element.geometry().jacobian(center);
332  }
333 
334 private:
335  ElementJacobian elementJacobian_;
336  const LocalSubEntityMeshSize* localSubEntityMeshSize_;
337 };
338 
339 
340 
341 template<unsigned int dim, bool reduced>
342 struct CubicHermiteLocalCoefficients
343 {
344 
345  static constexpr auto makeLocalKeys() {
346  if constexpr (dim==1)
347  return std::array{
348  LocalKey(0, 1, 0),
349  LocalKey(0, 1, 1),
350  LocalKey(1, 1, 0),
351  LocalKey(1, 1, 1)
352  };
353  if constexpr ((dim==2) and (not reduced))
354  return std::array{
355  LocalKey(0, 2, 0),
356  LocalKey(0, 2, 1),
357  LocalKey(0, 2, 2),
358  LocalKey(1, 2, 0),
359  LocalKey(1, 2, 1),
360  LocalKey(1, 2, 2),
361  LocalKey(2, 2, 0),
362  LocalKey(2, 2, 1),
363  LocalKey(2, 2, 2),
364  LocalKey(0, 0, 0)
365  };
366  if constexpr ((dim==2) and (reduced))
367  return std::array{
368  LocalKey(0, 2, 0),
369  LocalKey(0, 2, 1),
370  LocalKey(0, 2, 2),
371  LocalKey(1, 2, 0),
372  LocalKey(1, 2, 1),
373  LocalKey(1, 2, 2),
374  LocalKey(2, 2, 0),
375  LocalKey(2, 2, 1),
376  LocalKey(2, 2, 2)
377  };
378  }
379 
380  using LocalKeys = std::decay_t<decltype(makeLocalKeys())>;
381 
382 public:
383 
384  std::size_t size() const
385  {
386  return localKeys_.size();
387  }
388 
389  const LocalKey& localKey(std::size_t i) const
390  {
391  assert( i < localKeys_.size() );
392  return localKeys_[i];
393  }
394 private:
395  LocalKeys localKeys_ = makeLocalKeys();
396 };
397 
398 
399 
400 template<class DF, class RF, unsigned int dim, bool reduced>
401 class CubicHermiteLocalInterpolation
402 {
403  using ElementJacobianInverse = Dune::FieldMatrix<DF, dim,dim>;
404  using LocalSubEntityMeshSize = std::vector<double>;
405 
406 public:
407 
408  template<class Element>
409  void bind(const Element& element, const LocalSubEntityMeshSize& localSubEntityMeshSize) {
410  localSubEntityMeshSize_ = &localSubEntityMeshSize;
411  }
412 
413  template<class F, class C>
414  void interpolate(const F& f, std::vector<C>& out) const
415  {
416  using Domain = Dune::FieldVector<DF, dim>;
417  auto&& df = derivative(f);
418  if constexpr (dim==1)
419  {
420  out.resize(4);
421  out[0] = f(0);
422  out[1] = df(0) * (*localSubEntityMeshSize_)[1];
423  out[2] = f(1);
424  out[3] = df(1) * (*localSubEntityMeshSize_)[3];
425  }
426  if constexpr (dim==2)
427  {
428  if constexpr (not reduced)
429  {
430  out.resize(10);
431  out[9] = f(Domain({1.0/3.0,1.0/3.0}));
432  }
433  if constexpr (reduced)
434  out.resize(9);
435  auto J0 = df(Domain({0,0}));
436  auto J1 = df(Domain({1,0}));
437  auto J2 = df(Domain({0,1}));
438  out[0] = f(Domain({0,0}));
439  out[1] = J0[0][0] * (*localSubEntityMeshSize_)[1];
440  out[2] = J0[0][1] * (*localSubEntityMeshSize_)[2];
441  out[3] = f(Domain({1,0}));
442  out[4] = J1[0][0] * (*localSubEntityMeshSize_)[4];
443  out[5] = J1[0][1] * (*localSubEntityMeshSize_)[5];
444  out[6] = f(Domain({0,1}));
445  out[7] = J2[0][0] * (*localSubEntityMeshSize_)[7];
446  out[8] = J2[0][1] * (*localSubEntityMeshSize_)[8];
447  }
448  }
449 private:
450  const LocalSubEntityMeshSize* localSubEntityMeshSize_;
451 };
452 
453 
454 
462 template<class DF, class RF, unsigned int dim, bool reduced>
463 class CubicHermiteLocalFiniteElement
464 {
465  using LocalBasis = CubicHermiteLocalBasis<DF, RF, dim, reduced>;
466  using LocalCoefficients = CubicHermiteLocalCoefficients<dim, reduced>;
467  using LocalInterpolation = CubicHermiteLocalInterpolation<DF, RF, dim, reduced>;
468  using LocalSubEntityMeshSize = std::vector<double>;
469 
470 public:
471 
472  using Traits = LocalFiniteElementTraits<LocalBasis, LocalCoefficients, LocalInterpolation>;
473 
474  const LocalBasis& localBasis() const {
475  return localBasis_;
476  }
477 
478  const LocalCoefficients& localCoefficients() const {
479  return localCoefficients_;
480  }
481 
482  const LocalInterpolation& localInterpolation() const {
483  return localInterpolation_;
484  }
485 
486  unsigned int size() const {
487  return localBasis_.size();
488  }
489 
490  GeometryType type() const {
491  return type_;
492  }
493 
494  template<class Element, class Mapper, class MeshSizeContainer>
495  void bind(const Element& element, const Mapper& mapper, const MeshSizeContainer& subEntityMeshSize) {
496  // Update local mesh size cache
497  localSubEntityMeshSize_.resize(localCoefficients_.size());
498  for(auto i : Dune::range(size()))
499  {
500  auto localKey = localCoefficients_.localKey(i);
501  auto subEntityIndex = mapper.subIndex(element, localKey.subEntity(), localKey.codim());
502  localSubEntityMeshSize_[i] = subEntityMeshSize[subEntityIndex];
503  }
504 
505  localBasis_.bind(element, localSubEntityMeshSize_);
506  localInterpolation_.bind(element, localSubEntityMeshSize_);
507  type_ = element.type();
508  }
509 
510 private:
511  LocalSubEntityMeshSize localSubEntityMeshSize_;
512  LocalBasis localBasis_;
513  LocalCoefficients localCoefficients_;
514  LocalInterpolation localInterpolation_;
515  GeometryType type_;
516 };
517 
518 
519 
520 
521 } // namespace Impl in Dune::Functions::
522 
523 
524 
525 // *****************************************************************************
526 // This is the reusable part of the basis. It contains
527 //
528 // CubicHermitePreBasis
529 // CubicHermiteNode
530 //
531 // The pre-basis allows to create the others and is the owner of possible shared
532 // state. These components do _not_ depend on the global basis and local view
533 // and can be used without a global basis.
534 // *****************************************************************************
535 
536 template<typename GV, bool reduced>
537 class CubicHermiteNode :
538  public LeafBasisNode
539 {
540  static const int gridDim = GV::dimension;
541 
542  using CubeFiniteElement = Impl::CubicHermiteLocalFiniteElement<typename GV::ctype, double, gridDim, reduced>;
543  using SubEntityMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
544  using Base = LeafBasisNode;
545 
546 public:
547 
548  using size_type = std::size_t;
549  using Element = typename GV::template Codim<0>::Entity;
550  using FiniteElement = CubeFiniteElement;
551  using Base::size;
552 
553  CubicHermiteNode(const SubEntityMapper& subEntityMapper, const std::vector<double>& subEntityMeshSize) :
554  finiteElement_(),
555  element_(nullptr),
556  subEntityMapper_(&subEntityMapper),
557  subEntityMeshSize_(&subEntityMeshSize)
558  {}
559 
561  const Element& element() const
562  {
563  return *element_;
564  }
565 
570  const FiniteElement& finiteElement() const
571  {
572  return finiteElement_;
573  }
574 
576  void bind(const Element& e)
577  {
578  element_ = &e;
579  finiteElement_.bind(*element_, *subEntityMapper_, *subEntityMeshSize_);
580  this->setSize(finiteElement_.size());
581  }
582 
583 protected:
584 
585  FiniteElement finiteElement_;
586  const Element* element_;
587  const SubEntityMapper* subEntityMapper_;
588  const std::vector<double>* subEntityMeshSize_;
589 };
590 
591 
592 
600 template<typename GV, bool reduced = false>
602 {
604  using Base::mapper_;
605  using SubEntityMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
606 
607  static constexpr auto cubicHermiteMapperLayout(Dune::GeometryType type, int gridDim) {
608  if (type.isVertex())
609  return 1 + gridDim;
610  if ((type.isTriangle()) and (not reduced))
611  return 1;
612  else
613  return 0;
614  }
615 
616  static constexpr auto subEntityLayout(Dune::GeometryType type, int gridDim) {
617  return (cubicHermiteMapperLayout(type, gridDim) > 0);
618  }
619 
620 public:
621 
622  using GridView = typename Base::GridView;
623  using Node = CubicHermiteNode<GridView, reduced>;
624 
625  CubicHermitePreBasis(const GridView& gv) :
626  Base(gv, cubicHermiteMapperLayout),
627  subEntityMapper_(gv, subEntityLayout)
628  {
629  static_assert(GridView::dimension<=2, "CubicHermitePreBasis is only implemented for dim<=2");
630  subEntityMeshSize_ = Impl::computeAverageSubEntityMeshSize(subEntityMapper_);
631  }
632 
633  void update(const GridView& gv)
634  {
635  Base::update(gv);
636  subEntityMapper_.update(gv);
637  subEntityMeshSize_ = Impl::computeAverageSubEntityMeshSize(subEntityMapper_);
638  }
639 
640  Node makeNode() const
641  {
642  return Node{subEntityMapper_, subEntityMeshSize_};
643  }
644 
645 private:
646  std::vector<double> subEntityMeshSize_;
647  SubEntityMapper subEntityMapper_;
648 };
649 
650 
651 
652 namespace BasisFactory {
653 
659 template<class Dummy=void>
661 {
662  return [](const auto& gridView) {
663  return CubicHermitePreBasis<std::decay_t<decltype(gridView)>>(gridView);
664  };
665 }
666 
672 template<class Dummy=void>
674 {
675  return [](const auto& gridView) {
676  return CubicHermitePreBasis<std::decay_t<decltype(gridView)>, true>(gridView);
677  };
678 }
679 
680 } // end namespace BasisFactory
681 
682 
683 
684 
691 template<typename GV>
693 
694 
695 
702 template<typename GV>
704 
705 
706 
707 } // end namespace Functions
708 } // end namespace Dune
709 
710 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
Pre-basis for a CubicHermite basis.
Definition: cubichermitebasis.hh:602
Global basis for given pre-basis.
Definition: defaultglobalbasis.hh:46
A generic MixIn class for PreBasis with flat indices computed from a mapper.
Definition: leafprebasismappermixin.hh:58
void update(const GridView &gv)
Update the stored GridView.
Definition: leafprebasismappermixin.hh:97
GV GridView
Type of the associated GridView.
Definition: leafprebasismappermixin.hh:64
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:39
auto cubicHermite()
Create a pre-basis factory that can create a CubicHermite pre-basis.
Definition: cubichermitebasis.hh:660
auto reducedCubicHermite()
Create a pre-basis factory that can create a CubicHermite pre-basis.
Definition: cubichermitebasis.hh:673
Definition: polynomial.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)