DUNE-FUNCTIONS (unstable)

cubichermitebasis.hh
Go to the documentation of this file.
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#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
7#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
8
9#include <algorithm>
10#include <array>
11#include <numeric>
12#include <type_traits>
13#include <vector>
14
15#include <dune/common/exceptions.hh>
16#include <dune/common/fmatrix.hh>
17#include <dune/common/fvector.hh>
18#include <dune/common/rangeutilities.hh>
19
20#include <dune/grid/common/mcmgmapper.hh>
21
22#include <dune/localfunctions/common/localbasis.hh>
23#include <dune/localfunctions/common/localfiniteelementtraits.hh>
24#include <dune/localfunctions/common/localkey.hh>
25
26#include <dune/functions/common/mapperutilities.hh>
27#include <dune/functions/common/squeezetensor.hh>
28#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
29#include <dune/functions/functionspacebases/functionaldescriptor.hh>
30#include <dune/functions/functionspacebases/leafprebasismappermixin.hh>
31#include <dune/functions/functionspacebases/nodes.hh>
32#include <dune/functions/functionspacebases/transformedfiniteelementmixin.hh>
33
34
35
36#include <dune/functions/analyticfunctions/monomialset.hh>
37
53namespace Dune::Functions
54{
55
56 template<class GV, class R, bool reduced>
57 class CubicHermitePreBasis;
58
78 template<class GV,bool reduced = false, class R = double>
80
81 template<class DF, int n, class D, class RF, int m, class R, class J, class H>
82 struct H2LocalBasisTraits
83 : public LocalBasisTraits<DF, n, D, RF, m, R, J>
84 {
90 using HessianType = H;
91 };
92
93 namespace Impl
94 {
95
96 // *****************************************************************************
97 // * Some helper functions for building polynomial bases from monomials
98 // *****************************************************************************
99
109 template<class KCoeff, int sizePolynom, int sizeMonom, class In, class Out>
110 void multiplyWithCoefficentMatrix(Dune::FieldMatrix<KCoeff, sizePolynom, sizeMonom> const& coefficients,
111 In const& monomialValues,
112 Out& polynomialValues)
113 {
114 for (int i = 0; i < sizePolynom; ++i)
115 {
116 squeezeTensor(polynomialValues[i]) = 0;
117 for (int j = 0; j < sizeMonom; ++j)
118 squeezeTensor(polynomialValues[i]) += coefficients[i][j]*monomialValues[j];
119 }
120 }
121
127 template<int dim, bool reduced>
128 class CubicHermiteLocalCoefficients
129 {
130 public:
131 using size_type = std::size_t;
132
133 CubicHermiteLocalCoefficients()
134 : localKeys_(size())
135 {
136 static_assert((dim > 0) and (dim <= 3), "CubicHermiteLocalCoefficients only implemented for dim=1,2,3");
137 static_assert((not reduced) or (dim == 2), "Reduced version of CubicHermiteLocalCoefficients only implemented for dim=2");
138 for (size_type i = 0; i < (dim +1); ++i)
139 {
140 // dim derivatives + 1 evaluation dofs per vertex
141 for (size_type k = 0; k < (dim +1); ++k)
142 localKeys_[(dim +1) * i + k] = LocalKey(i, dim, k);
143 }
144 if constexpr (not reduced)
145 {
146 // 1 evaluation per element (2d) / facets (3d)
147 for (size_type i = 0; i < (dim - 1) * (dim - 1); ++i)
148 localKeys_[(dim +1) * (dim +1) + i] = LocalKey(i, (dim == 2) ? 0 : 1, 0); // inner dofs
149 }
150 }
151
154 static constexpr size_type size()
155 {
156 if constexpr (dim==1)
157 return 4;
158 if constexpr ((dim==2) and (reduced))
159 return 9;
160 if constexpr ((dim==2) and (not reduced))
161 return 10;
162 if constexpr (dim==3)
163 return 20;
164 return 0;
165 }
166
169 LocalKey const &localKey(size_type i) const
170 {
171 return localKeys_[i];
172 }
173
174 private:
175 std::vector<LocalKey> localKeys_;
176 };
177
178
184 template<class D, class R, int dim, bool reduced>
185 class CubicHermiteReferenceLocalBasis
186 {
187 public:
188 using Traits = H2LocalBasisTraits<D, dim, FieldVector<D, dim>, R, 1, FieldVector<R, 1>,
189 FieldMatrix<R, 1, dim>, FieldMatrix<R, dim, dim>>;
190
191 private:
192
205 static constexpr auto getCubicHermiteCoefficients()
206 {
207 if constexpr (dim == 1)
208 return Dune::FieldMatrix<D, 4, 4>({{1, 0, -3, 2}, {0, 1, -2, 1}, {0, 0, 3, -2}, {0, 0, -1, 1}});
209 else if constexpr (dim == 2)
210 {
211 if constexpr (reduced) {
212 auto w = std::array<D, 9>{1. / 3, 1. / 18, 1. / 18, 1. / 3, -1. / 9,
213 1. / 18, 1. / 3, 1. / 18, -1. / 9};
214 return Dune::FieldMatrix<D, 9, 10>({
215 {1, 0, 0, -3, -13 + w[0] * 27, -3, 2, 13 - w[0] * 27, 13 - w[0] * 27, 2},
216 {0, 1, 0, -2, -3 + w[1] * 27, 0, 1, 3 - w[1] * 27, 2 - w[1] * 27, 0},
217 {0, 0, 1, 0, -3 + w[2] * 27, -2, 0, 2 - w[2] * 27, 3 - w[2] * 27, 1},
218 {0, 0, 0, 3, -7 + w[3] * 27, 0, -2, 7 - w[3] * 27, 7 - w[3] * 27, 0},
219 {0, 0, 0, -1, 2 + w[4] * 27, 0, 1, -2 - w[4] * 27, -2 - w[4] * 27, 0},
220 {0, 0, 0, 0, -1 + w[5] * 27, 0, 0, 2 - w[5] * 27, 1 - w[5] * 27, 0},
221 {0, 0, 0, 0, -7 + w[6] * 27, 3, 0, 7 - w[6] * 27, 7 - w[6] * 27, -2},
222 {0, 0, 0, 0, -1 + w[7] * 27, 0, 0, 1 - w[7] * 27, 2 - w[7] * 27, 0},
223 {0, 0, 0, 0, 2 + w[8] * 27, -1, 0, -2 - w[8] * 27, -2 - w[8] * 27, 1},
224 });
225 }
226 else
227 return Dune::FieldMatrix<D, 10,10>({
228 {1, 0, 0, -3, -13, -3, 2, 13, 13, 2},
229 {0, 1, 0, -2, -3, 0, 1, 3, 2, 0},
230 {0, 0, 1, 0, -3, -2, 0, 2, 3, 1}, // l_2
231 {0, 0, 0, 3, -7, 0, -2, 7, 7, 0},
232 {0, 0, 0, -1, 2, 0, 1, -2, -2, 0},
233 {0, 0, 0, 0, -1, 0, 0, 2, 1, 0},
234 {0, 0, 0, 0, -7, 3, 0, 7, 7, -2}, // l_6
235 {0, 0, 0, 0, -1, 0, 0, 1, 2, 0},
236 {0, 0, 0, 0, 2, -1, 0, -2, -2, 1},
237 {0, 0, 0, 0, 27, 0, 0, -27, -27, 0}}); // l_9, inner dof
238 }
239 else if constexpr (dim == 3)
240 {
241 return Dune::FieldMatrix<D, 20,20>({{1, 0, 0, 0, -3, -13, -3, -13, -13, -3, // deg 0 to 2
242 2, 13, 13, 2, 13, 33, 13, 13, 13, 2}, // deg 3
243 {0, 1, 0, 0,/*xx*/ -2, /*xy*/-3,/*yy*/ 0,/*xz*/ -3,/*yz*/ 0,/*zz*/ 0, 1, 3, 2, 0, 3, 4, 0, 2, 0, 0},
244 {0, 0, 1, 0, 0, -3, -2, 0, -3, 0, 0, 2, 3, 1, 0, 4, 3, 0, 2, 0},
245 {0, 0, 0, 1, 0, 0, 0, -3, -3, -2, 0, 0, 0, 0, 2, 4, 2, 3, 3, 1},
246 {0, 0, 0, 0, 3, -7, 0, -7, 0, 0, // l_4
247 -2, 7, 7, 0, 7, 7, 0, 7, 0, 0},
248 {0, 0, 0, 0, -1, 2, 0, 2, 0, 0, 1, -2, -2, 0, -2, -2, 0, -2, 0, 0},
249 {0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0},
250 {0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0},
251 {0, 0, 0, 0, 0, -7, 3, 0, -7, 0, // l_8
252 0, 7, 7, -2, 0, 7, 7, 0, 7, 0},
253 {0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0},
254 {0, 0, 0, 0, 0, 2, -1, 0, 2, 0, 0, -2, -2, 1, 0, -2, -2, 0, -2, 0},
255 {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0},
256 {0, 0, 0, 0, 0, 0, 0, -7, -7, 3, // l_12
257 0, 0, 0, 0, 7, 7, 7, 7, 7, -2},
258 {0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0},
259 {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0},
260 {0, 0, 0, 0, 0, 0, 0, 2, 2, -1, 0, 0, 0, 0, -2, -2, -2, -2, -2, 1},
261 // l_16, from here on inner dofs
262 {0, 0, 0, 0, 0, 27, 0, 0, 0, 0, // bottom
263 0, -27, -27, 0, 0, -27, 0, 0, 0, 0},
264 {0, 0, 0, 0, 0, 0, 0, 27, 0, 0, // front
265 0, 0, 0, 0, -27, -27, 0, -27, 0, 0},
266 {0, 0, 0, 0, 0, 0, 0, 0, 27, 0, // left
267 0, 0, 0, 0, 0, -27, -27, 0, -27, 0},
268 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // right
269 0, 0, 0, 0, 0, 27, 0, 0, 0, 0}});
270 }
271 }
272
273 static constexpr auto referenceBasisCoefficients = getCubicHermiteCoefficients();
274 static constexpr MonomialSet<typename Traits::RangeFieldType, dim, 3> monomials = {};
275
276 public:
277
278 CubicHermiteReferenceLocalBasis()
279 {
280 static_assert((dim > 0) and (dim <= 3), "CubicHermiteReferenceLocalBasis only implemented for dim=1,2,3");
281 static_assert((not reduced) or (dim == 2), "Reduced version of CubicHermiteReferenceLocalBasis only implemented for dim=2");
282 }
283
286 static constexpr unsigned int size()
287 {
288 return CubicHermiteLocalCoefficients<dim,reduced>::size();
289 }
290
293 unsigned int order() const
294 {
295 return 3;
296 }
297
303 void evaluateFunction(const typename Traits::DomainType &in,
304 std::vector<typename Traits::RangeType> &out) const
305 {
306 out.resize(size());
307 auto monomialValues = monomials(in);
308 multiplyWithCoefficentMatrix(referenceBasisCoefficients, monomialValues, out);
309 }
310
316 void evaluateJacobian(const typename Traits::DomainType &in,
317 std::vector<typename Traits::JacobianType> &out) const
318 {
319 out.resize(size());
320 auto monomialValues = derivative(monomials)(in);
321 multiplyWithCoefficentMatrix(referenceBasisCoefficients, monomialValues, out);
322 }
323
329 void evaluateHessian(const typename Traits::DomainType &in,
330 std::vector<typename Traits::HessianType> &out) const
331 {
332 out.resize(size());
333 auto monomialValues = derivative(derivative(monomials))(in);
334 multiplyWithCoefficentMatrix(referenceBasisCoefficients, monomialValues, out);
335 }
336
343 void partial(std::array<unsigned int, dim> order, const typename Traits::DomainType &in,
344 std::vector<typename Traits::RangeType> &out) const
345 {
346 out.resize(size());
347 auto totalOrder = std::accumulate(order.begin(), order.end(), 0);
348 if (totalOrder == 0)
349 evaluateFunction(in, out);
350 else if (totalOrder == 1)
351 {
352 evaluateJacobian(in,jacobiansBuffer_);
353 std::size_t which = std::max_element(order.begin(), order.end()) - order.begin();
354 for (auto i : Dune::range(size()))
355 out[i] = jacobiansBuffer_[i][0][which];
356 }
357 else if (totalOrder == 2)
358 {
359 evaluateHessian(in, hessianBuffer_);
360 std::size_t first, second;
361 first = std::max_element(order.begin(), order.end()) - order.begin();
362 if (order[first] == 2)
363 second = first;
364 else
365 {
366 order[first] = 0;
367 second = std::max_element(order.begin(), order.end()) - order.begin();
368 }
369 for (auto i : Dune::range(size()))
370 out[i] = hessianBuffer_[i][first][second];
371 }
372 else
373 DUNE_THROW(RangeError, "partial() not implemented for given order");
374 }
375
376 private:
377 mutable std::vector<typename Traits::JacobianType> jacobiansBuffer_;
378 mutable std::vector<typename Traits::HessianType> hessianBuffer_;
379 };
380
381
387 template<class D, int dim, bool reduced = false>
388 class CubicHermiteLocalInterpolation
389 {
390 using size_type = std::size_t;
391
392 static constexpr unsigned int size()
393 {
394 return CubicHermiteLocalCoefficients<dim,reduced>::size();
395 }
396
397 using FunctionalDescriptor = Dune::Functions::Impl::FunctionalDescriptor<dim>;
398
399 public:
400
401 CubicHermiteLocalInterpolation()
402 {
403 static_assert((dim > 0) and (dim <= 3), "CubicHermiteLocalInterpolation only implemented for dim=1,2,3");
404 static_assert((not reduced) or (dim == 2), "Reduced version of CubicHermiteLocalInterpolation only implemented for dim=2");
405 if constexpr (dim==1)
406 {
407 descriptors_[0] = FunctionalDescriptor();
408 descriptors_[1] = FunctionalDescriptor({1});
409 descriptors_[2] = FunctionalDescriptor();
410 descriptors_[3] = FunctionalDescriptor({1});
411 }
412 if constexpr (dim==2)
413 {
414 descriptors_[0] = FunctionalDescriptor();
415 descriptors_[1] = FunctionalDescriptor({1,0});
416 descriptors_[2] = FunctionalDescriptor({0,1});
417 descriptors_[3] = FunctionalDescriptor();
418 descriptors_[4] = FunctionalDescriptor({1,0});
419 descriptors_[5] = FunctionalDescriptor({0,1});
420 descriptors_[6] = FunctionalDescriptor();
421 descriptors_[7] = FunctionalDescriptor({1,0});
422 descriptors_[8] = FunctionalDescriptor({0,1});
423 if (not reduced)
424 descriptors_[9] = FunctionalDescriptor();
425 }
426 if constexpr (dim==3)
427 {
428 descriptors_[0] = FunctionalDescriptor();
429 descriptors_[1] = FunctionalDescriptor({1,0,0});
430 descriptors_[2] = FunctionalDescriptor({0,1,0});
431 descriptors_[3] = FunctionalDescriptor({0,0,1});
432 descriptors_[4] = FunctionalDescriptor();
433 descriptors_[5] = FunctionalDescriptor({1,0,0});
434 descriptors_[6] = FunctionalDescriptor({0,1,0});
435 descriptors_[7] = FunctionalDescriptor({0,0,1});
436 descriptors_[8] = FunctionalDescriptor();
437 descriptors_[9] = FunctionalDescriptor({1,0,0});
438 descriptors_[10] = FunctionalDescriptor({0,1,0});
439 descriptors_[11] = FunctionalDescriptor({0,0,1});
440 descriptors_[12] = FunctionalDescriptor();
441 descriptors_[13] = FunctionalDescriptor({1,0,0});
442 descriptors_[14] = FunctionalDescriptor({0,1,0});
443 descriptors_[15] = FunctionalDescriptor({0,0,1});
444 descriptors_[16] = FunctionalDescriptor();
445 descriptors_[17] = FunctionalDescriptor();
446 descriptors_[18] = FunctionalDescriptor();
447 descriptors_[19] = FunctionalDescriptor();
448 }
449 }
450
453 template<class Element>
454 void bind( Element const &element, std::array<D, dim+1>const& averageVertexMeshSize)
455 {
456 averageVertexMeshSize_ = &averageVertexMeshSize;
457 }
458
466 template<class F, class C>
467 void interpolate(const F &f, std::vector<C> &out) const
468 {
469 out.resize(size());
470 auto df = derivative(f);
471 auto const &refElement = Dune::ReferenceElements<D, dim>::simplex();
472
473 // Iterate over vertices, dim derivative +1 evaluation dofs per vertex
474 for (int i = 0; i < (dim+1); ++i)
475 {
476 auto x = refElement.position(i, dim);
477 auto&& derivativeValue = df(x);
478 out[i * (dim +1)] = f(x);
479 for (int d = 0; d < dim; ++d)
480 out[i * (dim+1) + d + 1] = squeezeTensor(derivativeValue)[d] * (*averageVertexMeshSize_)[i];
481 }
482
483 if constexpr (not reduced)
484 {
485 for (size_type i = 0; i < (dim - 1) * (dim - 1); ++i)
486 out[(dim +1) * (dim +1) + i] = f(refElement.position(i, (dim == 2) ? 0 : 1));
487 }
488 }
489
493 const FunctionalDescriptor& functionalDescriptor(size_type i) const
494 {
495 return descriptors_[i];
496 }
497
498 protected:
499 std::array<D, dim+1> const* averageVertexMeshSize_;
500 std::array<FunctionalDescriptor, size()> descriptors_;
501 };
502
503 template<class D, class R, int dim , bool reduced>
504 struct CubicHermiteLocalBasisTraits
505 : public H2LocalBasisTraits<D, dim, Dune::FieldVector<D,dim>, R, 1,
506 Dune::FieldVector<R,1>, Dune::FieldMatrix<R,1,dim>, Dune::FieldMatrix<R,dim,dim>>
507 {};
508
517 template<class D, class R, int dim, bool reduced = false>
518 class CubicHermiteLocalFiniteElement
519 : public Impl::TransformedFiniteElementMixin<CubicHermiteLocalFiniteElement<D,R,dim,reduced>, CubicHermiteLocalBasisTraits<D, R, dim, reduced>>
520 {
521 using Base = Impl::TransformedFiniteElementMixin< CubicHermiteLocalFiniteElement<D,R,dim,reduced>, CubicHermiteLocalBasisTraits<D, R, dim, reduced>>;
522 friend class Impl::TransformedLocalBasis<CubicHermiteLocalFiniteElement<D,R,dim,reduced>, CubicHermiteLocalBasisTraits<D, R, dim, reduced>>;
523
524 public:
525
526 CubicHermiteLocalFiniteElement()
527 : Base()
528 {
529 static_assert((dim > 0) and (dim <= 3), "CubicHermiteLocalFiniteElement only implemented for dim=1,2,3");
530 static_assert((not reduced) or (dim == 2), "Reduced version of CubicHermiteLocalFiniteElement only implemented for dim=2");
531 }
532
535 using size_type = std::size_t;
536 using Traits = LocalFiniteElementTraits<
537 Impl::TransformedLocalBasis<CubicHermiteLocalFiniteElement<D,R,dim,reduced>, CubicHermiteLocalBasisTraits<D, R, dim, reduced>>,
538 Impl::CubicHermiteLocalCoefficients<dim, reduced>,
539 Impl::CubicHermiteLocalInterpolation<D, dim, reduced>>;
540
544 const typename Traits::LocalCoefficientsType &localCoefficients() const
545 {
546 return coefficients_;
547 }
548
551 const typename Traits::LocalInterpolationType &localInterpolation() const
552 {
553 return interpolation_;
554 }
555
558 static constexpr GeometryType type()
559 {
560 return GeometryTypes::simplex(dim);
561 }
562
565 static constexpr size_type size()
566 {
567 return Impl::CubicHermiteLocalCoefficients<dim,reduced>::size();
568 }
569
572 template<class Mapper, class Element>
573 void bind(Mapper const& vertexMapper, std::vector<D> const& globalAverageVertexMeshSize, Element const &e)
574 {
575 // Cache average mesh size for each vertex
576 for (auto i : range(dim+1))
577 averageVertexMeshSize_[i] = globalAverageVertexMeshSize[vertexMapper.subIndex(e, i, dim)];
578
579 // Bind LocalInterpolation to updated local state
580 interpolation_.bind(e, averageVertexMeshSize_);
581
582 // Compute local transformation matrices for each vertex
583 const auto& geometry = e.geometry();
584 const auto& refElement = Dune::ReferenceElements<typename Element::Geometry::ctype, dim>::simplex();
585 for (auto i : range(dim+1))
586 {
587 scaledVertexJacobians_[i] = geometry.jacobian(refElement.position(i, dim));
588 scaledVertexJacobians_[i] /= averageVertexMeshSize_[i];
589 }
590 }
591
592 protected:
593
596 Impl::CubicHermiteReferenceLocalBasis<D, R, dim, reduced> const& referenceLocalBasis() const
597 {
598 return basis_;
599 }
600
605 template<class InputValues, class OutputValues>
606 void transform(InputValues const &inValues, OutputValues &outValues) const
607 {
608 assert(inValues.size() == size());
609 assert(outValues.size() == inValues.size());
610 auto inIt = inValues.begin();
611 auto outIt = outValues.begin();
612
613 for (auto vertex : Dune::range((dim +1)))
614 {
615 *outIt = *inIt; // value dof is not transformed
616 outIt++, inIt++;
617 // transform the gradient dofs together
618 for (auto &&[row_i, i] : sparseRange(scaledVertexJacobians_[vertex]))
619 {
620 outIt[i] = 0.;
621 for (auto &&[val_i_j, j] : sparseRange(row_i))
622 outIt[i] += val_i_j * inIt[j];
623 }
624 // increase pointer by size of gradient = dim
625 outIt += dim, inIt += dim;
626 }
627
628 // For the non-reduced case: Copy all remaining inner dofs
629 if constexpr (dim > 1 and (not reduced))
630 std::copy(inIt, inValues.end(), outIt);
631 }
632
633 private:
634
635 typename Impl::CubicHermiteReferenceLocalBasis<D, R, dim, reduced> basis_;
636 typename Traits::LocalCoefficientsType coefficients_;
637 typename Traits::LocalInterpolationType interpolation_;
638 // the transformation to correct the lack of affine equivalence boils down to
639 // one transformation matrix per vertex
640 std::array<Dune::FieldMatrix<R, dim, dim>, dim+1> scaledVertexJacobians_;
641 // the local state, i.e. a collection of global information restricted to this element
642 std::array<D, dim+1> averageVertexMeshSize_;
643
644 };
645
646 } // end namespace Impl
647
648
649
650 // *****************************************************************************
651 // This is the reusable part of the basis. It contains
652 //
653 // CubicHermitePreBasis
654 // CubicHermiteNode
655 //
656 // The pre-basis allows to create the others and is the owner of possible shared
657 // state. These components do _not_ depend on the global basis and local view
658 // and can be used without a global basis.
659 // *****************************************************************************
660
661 template<class GV, class R, bool reduced>
662 class CubicHermiteNode
663 : public LeafBasisNode
664 {
665 using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
666
667 public:
668 using size_type = std::size_t;
669 using Element = typename GV::template Codim<0>::Entity;
670 using FiniteElement = typename Impl::CubicHermiteLocalFiniteElement<typename GV::ctype, R, GV::dimension, reduced>;
671
672 CubicHermiteNode(Mapper const& m, std::vector<typename GV::ctype> const& averageVertexMeshSize)
673 : element_(nullptr)
674 , vertexMapper_(&m)
675 , averageVertexMeshSize_(&averageVertexMeshSize)
676 {}
677
679 Element const &element() const
680 {
681 return *element_;
682 }
683
689 FiniteElement const &finiteElement() const
690 {
691 return finiteElement_;
692 }
693
695 void bind(Element const &e)
696 {
697 element_ = &e;
698 finiteElement_.bind(*vertexMapper_, *averageVertexMeshSize_, *element_);
699 this->setSize(finiteElement_.size());
700 }
701
703 unsigned int order() const { return finiteElement_.localBasis().order(); }
704
705 protected:
706 FiniteElement finiteElement_;
707 Element const* element_;
708 Mapper const* vertexMapper_;
709 std::vector<typename GV::ctype> const* averageVertexMeshSize_;
710 };
711
712
722 template<class GV, class R, bool reduced = false>
724 : public LeafPreBasisMapperMixin<GV>
725 {
727 using SubEntityMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GV>;
728 using Element = typename GV::template Codim<0>::Entity;
729 using D = typename GV::ctype;
730 static const std::size_t dim = GV::dimension;
731
732 // helper methods to assign each subentity the number of dofs. Used by the LeafPreBasisMapperMixin.
733 static constexpr auto cubicHermiteMapperLayout(Dune::GeometryType type, int gridDim)
734 {
735 if (type.isVertex())
736 return 1 + gridDim; // one evaluation dof and gridDim derivative dofs per vertex
737 if (gridDim == 1) // in 1d there are no other dofs
738 return 0;
739 // in 2d we have one inner dof (i.e. on the triangle) or non for the reduced case
740 // and in 3d we have one dof on each face (i.e. on each triangle)
741 if ((type.isTriangle()) and (not reduced))
742 return 1;
743 else
744 return 0; // this case is only entered for the interior of the 3d element. There are no dofs.
745 }
746
747 public:
749 using GridView = GV;
750
752 using size_type = std::size_t;
753
755 using Node = CubicHermiteNode<GridView, R,reduced>;
756
757 public:
758
761 : Base(gv, cubicHermiteMapperLayout)
762 , vertexMapper_({gv, mcmgVertexLayout()})
763 {
764 static_assert((dim > 0) and (dim <= 3), "CubicHermitePreBasis only implemented for dim=1,2,3");
765 static_assert((not reduced) or (dim == 2), "Reduced version of CubicHermitePreBasis only implemented for dim=2");
766 averageVertexMeshSize_ = Impl::computeAverageSubEntityMeshSize<D>(vertexMapper_);
767 }
768
770 void update(GridView const &gv)
771 {
772 Base::update(gv);
773 vertexMapper_.update(this->gridView());
774 averageVertexMeshSize_ = Impl::computeAverageSubEntityMeshSize<D>(vertexMapper_);
775 }
776
781 {
782 return Node{vertexMapper_, averageVertexMeshSize_};
783 }
784
785 protected:
786
787 SubEntityMapper vertexMapper_;
788 std::vector<D> averageVertexMeshSize_;
789
790 }; // class CubicHermitePreBasis
791
792 namespace BasisFactory
793 {
794
802 template<class R = double>
803 auto cubicHermite()
804 {
805 return [=](auto const &gridView) {
806 return CubicHermitePreBasis<std::decay_t<decltype(gridView)>, R>(gridView);
807 };
808 }
809
817 template<class R = double>
818 auto reducedCubicHermite()
819 {
820 return [=](auto const &gridView) {
821 return CubicHermitePreBasis<std::decay_t<decltype(gridView)>, R, true>(gridView);
822 };
823 }
824
825 } // end namespace BasisFactory
826
827
828} // end namespace Dune::Functions
829
830#endif
A pre-basis for a Hermitebasis.
Definition: cubichermitebasis.hh:725
Node makeNode() const
Create tree node.
Definition: cubichermitebasis.hh:780
CubicHermiteNode< GridView, R, reduced > Node
Template mapping root tree path to type of created tree node.
Definition: cubichermitebasis.hh:755
GV GridView
The grid view that the FE basis is defined on.
Definition: cubichermitebasis.hh:749
std::size_t size_type
Type used for indices and size information.
Definition: cubichermitebasis.hh:752
void update(GridView const &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: cubichermitebasis.hh:770
CubicHermitePreBasis(const GV &gv)
Constructor for a given grid view object.
Definition: cubichermitebasis.hh:760
Global basis for given pre-basis.
Definition: defaultglobalbasis.hh:53
A generic MixIn class for PreBasis with flat indices computed from a mapper.
Definition: leafprebasismappermixin.hh:62
const GridView & gridView() const
Export the stored GridView.
Definition: leafprebasismappermixin.hh:95
void update(const GridView &gv)
Update the stored GridView.
Definition: leafprebasismappermixin.hh:101
TrigonometricFunction< K, -cosFactor, sinFactor > derivative(const TrigonometricFunction< K, sinFactor, cosFactor > &f)
Obtain derivative of TrigonometricFunction function.
Definition: trigonometricfunction.hh:43
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jan 9, 23:34, 2026)