7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CUBICHERMITEBASIS_HH
15#include <dune/grid/common/rangegenerators.hh>
17#include <dune/localfunctions/common/localfiniteelementvariant.hh>
19#include <dune/localfunctions/crouzeixraviart.hh>
21#include <dune/functions/functionspacebases/nodes.hh>
22#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
23#include <dune/functions/functionspacebases/leafprebasismappermixin.hh>
36 template<
class Gr
idView>
42 auto subIndices = std::vector<Index>();
43 auto referenceElement = Dune::referenceElement<double, dimension>(element.type());
44 for(
auto codim : Dune::range(dimension+1))
48 std::size_t c = mapper.layout()(
referenceElement.type(subEntity, codim), dimension);
51 std::size_t firstIndex = mapper.
subIndex(element, subEntity, codim);
52 for(
auto j : Dune::range(firstIndex, firstIndex+c))
54 subIndices.push_back(j);
66 template<
class Mapper>
67 auto computeAverageSubEntityMeshSize(
const Mapper& mapper)
69 constexpr auto dimension = Mapper::GridView::dimension;
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()))
75 auto A = element.geometry().volume();
76 for(
auto i : Impl::subIndexSet(mapper, element))
78 subEntityMeshSize[i] += A;
79 ++(adjacentElements[i]);
82 for(
auto i : Dune::range(mapper.size()))
83 subEntityMeshSize[i] = std::pow(subEntityMeshSize[i]/adjacentElements[i], 1./dimension);
84 return subEntityMeshSize;
98 constexpr std::size_t maxOrder=3;
99 constexpr std::size_t
size = (maxOrder+1);
100 auto xPowers = std::array<double,maxOrder+1>{};
102 for(
auto k: Dune::range(maxOrder))
103 xPowers[k+1] = xPowers[k]*x[0];
105 for(
auto order : Dune::range(maxOrder+1))
106 y[order] = xPowers[order];
115 constexpr std::size_t maxOrder=3;
116 constexpr std::size_t
size = (maxOrder+1);
117 auto xPowers = std::array<double,maxOrder+1>{};
119 for(
auto k: Dune::range(maxOrder))
120 xPowers[k+1] = xPowers[k]*x[0];
122 for(
auto order : Dune::range(std::size_t(1), maxOrder+1))
123 y[order][0][2] = order*xPowers[order-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))
139 for(
auto k: Dune::range(maxOrder))
140 xPowers[j][k+1] = xPowers[j][k]*x[j];
144 for(
auto order : Dune::range(maxOrder+1))
146 for(
auto k : Dune::range(order+1))
148 y[index] = xPowers[0][order-k]*xPowers[1][k];
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))
167 for(
auto k: Dune::range(maxOrder))
168 xPowers[j][k+1] = xPowers[j][k]*x[j];
172 for(
auto order : Dune::range(maxOrder+1))
174 for(
auto k : Dune::range(order+1))
177 y[index][0][0] = (order-k)*xPowers[0][order-k-1]*xPowers[1][k];
179 y[index][0][1] = k*xPowers[0][order-k]*xPowers[1][k-1];
194template<
class DF,
class RF,
unsigned int dim,
bool reduced>
195class CubicHermiteLocalBasis
198 static constexpr auto makeReferenceBasisCoefficients() {
199 if constexpr (dim==1)
206 if constexpr ((dim==2) and (not reduced))
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}
219 if constexpr ((dim==2) and (reduced))
221 auto w = std::array{1./3, 1./18, 1./18, 1./3, -1./9, 1./18, 1./3, 1./18, -1./9};
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},
247 static constexpr auto referenceBasisCoefficients = makeReferenceBasisCoefficients();
255 template<
class LambdaRefValues,
class Entry>
256 void transformToElementBasis(
const LambdaRefValues& refValues, std::vector<Entry>& out)
const
258 if constexpr (dim==1)
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];;
267 if constexpr (dim==2)
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];
287 using LocalSubEntityMeshSize = std::vector<double>;
295 using OrderArray = std::array<unsigned int, dim>;
297 static constexpr unsigned int size()
299 return decltype(referenceBasisCoefficients)::rows;
302 inline void evaluateFunction(
const Domain& x, std::vector<Range>& values)
const
304 auto monomialValues = evaluateMonomialValues(x);
306 referenceBasisCoefficients.mv(monomialValues, referenceValues);
307 transformToElementBasis(referenceValues, values);
310 inline void evaluateJacobian(
const Domain& x, std::vector<Jacobian>& jacobians)
const
312 auto monomialJacobians = evaluateMonomialJacobians(x);
314 referenceBasisCoefficients.mv(monomialJacobians, referenceJacobians);
315 transformToElementBasis(referenceJacobians, jacobians);
318 void partial(
const OrderArray& order,
const Domain& x, std::vector<Range>& out)
const
322 evaluateFunction(x, out);
323 DUNE_THROW(RangeError,
"partial() not implemented for given order");
326 unsigned int order()
const
331 template<
class Element>
332 void bind(
const Element& element,
const LocalSubEntityMeshSize& localSubEntityMeshSize) {
333 localSubEntityMeshSize_ = &localSubEntityMeshSize;
335 elementJacobian_ = element.geometry().jacobian(center);
339 ElementJacobian elementJacobian_;
340 const LocalSubEntityMeshSize* localSubEntityMeshSize_;
345template<
unsigned int dim,
bool reduced>
346struct CubicHermiteLocalCoefficients
349 static constexpr auto makeLocalKeys() {
350 if constexpr (dim==1)
357 if constexpr ((dim==2) and (not reduced))
370 if constexpr ((dim==2) and (reduced))
384 using LocalKeys = std::decay_t<
decltype(makeLocalKeys())>;
388 std::size_t
size()
const
390 return localKeys_.size();
393 const LocalKey& localKey(std::size_t i)
const
395 assert( i < localKeys_.size() );
396 return localKeys_[i];
399 LocalKeys localKeys_ = makeLocalKeys();
404template<
class DF,
class RF,
unsigned int dim,
bool reduced>
405class CubicHermiteLocalInterpolation
408 using LocalSubEntityMeshSize = std::vector<double>;
412 template<
class Element>
413 void bind(
const Element& element,
const LocalSubEntityMeshSize& localSubEntityMeshSize) {
414 localSubEntityMeshSize_ = &localSubEntityMeshSize;
417 template<
class F,
class C>
418 void interpolate(
const F& f, std::vector<C>& out)
const
422 if constexpr (dim==1)
426 out[1] = df(0) * (*localSubEntityMeshSize_)[1];
428 out[3] = df(1) * (*localSubEntityMeshSize_)[3];
430 if constexpr (dim==2)
432 if constexpr (not reduced)
435 out[9] = f(Domain({1.0/3.0,1.0/3.0}));
437 if constexpr (reduced)
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];
454 const LocalSubEntityMeshSize* localSubEntityMeshSize_;
466template<
class DF,
class RF,
unsigned int dim,
bool reduced>
467class CubicHermiteLocalFiniteElement
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>;
476 using Traits = LocalFiniteElementTraits<LocalBasis, LocalCoefficients, LocalInterpolation>;
478 const LocalBasis& localBasis()
const {
482 const LocalCoefficients& localCoefficients()
const {
483 return localCoefficients_;
486 const LocalInterpolation& localInterpolation()
const {
487 return localInterpolation_;
490 unsigned int size()
const {
491 return localBasis_.size();
498 template<
class Element,
class Mapper,
class MeshSizeContainer>
499 void bind(
const Element& element,
const Mapper& mapper,
const MeshSizeContainer& subEntityMeshSize) {
501 localSubEntityMeshSize_.resize(localCoefficients_.size());
502 for(
auto i : Dune::range(
size()))
504 auto localKey = localCoefficients_.localKey(i);
505 auto subEntityIndex = mapper.subIndex(element, localKey.subEntity(), localKey.codim());
506 localSubEntityMeshSize_[i] = subEntityMeshSize[subEntityIndex];
509 localBasis_.bind(element, localSubEntityMeshSize_);
510 localInterpolation_.bind(element, localSubEntityMeshSize_);
511 type_ = element.type();
515 LocalSubEntityMeshSize localSubEntityMeshSize_;
516 LocalBasis localBasis_;
517 LocalCoefficients localCoefficients_;
518 LocalInterpolation localInterpolation_;
540template<
typename GV,
bool reduced>
541class CubicHermiteNode :
544 static const int gridDim = GV::dimension;
546 using CubeFiniteElement = Impl::CubicHermiteLocalFiniteElement<typename GV::ctype, double, gridDim, reduced>;
548 using Base = LeafBasisNode;
552 using size_type = std::size_t;
553 using Element =
typename GV::template Codim<0>::Entity;
554 using FiniteElement = CubeFiniteElement;
557 CubicHermiteNode(
const SubEntityMapper& subEntityMapper,
const std::vector<double>& subEntityMeshSize) :
560 subEntityMapper_(&subEntityMapper),
561 subEntityMeshSize_(&subEntityMeshSize)
565 const Element& element()
const
574 const FiniteElement& finiteElement()
const
576 return finiteElement_;
580 void bind(
const Element& e)
583 finiteElement_.bind(*element_, *subEntityMapper_, *subEntityMeshSize_);
584 this->setSize(finiteElement_.size());
589 FiniteElement finiteElement_;
590 const Element* element_;
591 const SubEntityMapper* subEntityMapper_;
592 const std::vector<double>* subEntityMeshSize_;
604template<
typename GV,
bool reduced = false>
611 static constexpr auto cubicHermiteMapperLayout(
Dune::GeometryType type,
int gridDim) {
621 return (cubicHermiteMapperLayout(type, gridDim) > 0);
627 using Node = CubicHermiteNode<GridView, reduced>;
630 Base(gv, cubicHermiteMapperLayout),
631 subEntityMapper_(gv, subEntityLayout)
633 static_assert(
GridView::dimension<=2,
"CubicHermitePreBasis is only implemented for dim<=2");
634 subEntityMeshSize_ = Impl::computeAverageSubEntityMeshSize(subEntityMapper_);
640 subEntityMapper_.
update(gv);
641 subEntityMeshSize_ = Impl::computeAverageSubEntityMeshSize(subEntityMapper_);
644 Node makeNode()
const
646 return Node{subEntityMapper_, subEntityMeshSize_};
650 std::vector<double> subEntityMeshSize_;
656namespace BasisFactory {
663template<
class Dummy=
void>
666 return [](
const auto& gridView) {
676template<
class Dummy=
void>
679 return [](
const auto& gridView) {
A dense n x m matrix.
Definition: fmatrix.hh:117
vector space out of a tensor product of fields.
Definition: fvector.hh:91
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
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
constexpr bool isVertex() const
Return true if entity is a vertex.
Definition: type.hh:279
constexpr bool isTriangle() const
Return true if entity is a triangle.
Definition: type.hh:289
IndexType Index
Number type used for indices.
Definition: mapper.hh:114
Index subIndex(const typename GV::template Codim< 0 >::Entity &e, int i, unsigned int codim) const
Map subentity of codim 0 entity to starting index in array for dof block.
Definition: mcmgmapper.hh:185
void update(const GV &gridView)
Recalculates indices after grid adaptation.
Definition: mcmgmapper.hh:308
A set of traits classes to store static information about grid implementation.
A few common exception classes.
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
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
static constexpr int dimension
The dimension of the grid.
Definition: gridview.hh:134
unspecified value type referenceElement(T &&... t)
Returns a reference element for the objects t....
constexpr T accumulate(Range &&range, T value, F &&f)
Accumulate values.
Definition: hybridutilities.hh:279
Mapper for multiple codim and multiple geometry types.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Convenience header that includes all available Rannacher-Turek LocalFiniteElements.
static const ReferenceElement & simplex()
get simplex reference elements
Definition: referenceelements.hh:162
Type traits for LocalBasisVirtualInterface.
Definition: localbasis.hh:35
Provides the TupleVector class that augments std::tuple by operator[].