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