version 3.11-dev
Loading...
Searching...
No Matches
pq1bubblelocalfiniteelement.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_DISCRETIZATION_PQ1BUBBLE_LOCAL_FINITE_ELEMENT_HH
13#define DUMUX_DISCRETIZATION_PQ1BUBBLE_LOCAL_FINITE_ELEMENT_HH
14
15#include <array>
16#include <vector>
17#include <numeric>
18#include <algorithm>
19
20#include <dune/common/fmatrix.hh>
21#include <dune/common/fvector.hh>
22#include <dune/common/exceptions.hh>
23#include <dune/common/typetraits.hh>
24
25#include <dune/geometry/type.hh>
26#include <dune/geometry/referenceelements.hh>
27
28#include <dune/localfunctions/common/localbasis.hh>
29#include <dune/localfunctions/common/localfiniteelementtraits.hh>
30#include <dune/localfunctions/common/localkey.hh>
31
32#include <dune/localfunctions/lagrange/lagrangesimplex.hh>
33#include <dune/localfunctions/lagrange/lagrangecube.hh>
34
35namespace Dumux::Detail {
36
46template<class D, class R, unsigned int dim, Dune::GeometryType::Id typeId, std::size_t numCubeBubbleDofs>
48{
49 using PQ1FiniteElement = std::conditional_t<
50 Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim),
51 Dune::LagrangeCubeLocalFiniteElement<D, R, dim, 1>,
52 Dune::LagrangeSimplexLocalFiniteElement<D, R, dim, 1>
53 >;
54 static constexpr bool isCube = Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim);
55 static constexpr std::size_t numVertexDofs = isCube ? (1<<dim) : (dim+1);
56 static constexpr std::size_t numBubbleDofs = isCube ? numCubeBubbleDofs : 1;
57 static constexpr std::size_t numDofs = numVertexDofs + numBubbleDofs;
58public:
59 using Traits = Dune::LocalBasisTraits<
60 D, dim, Dune::FieldVector<D, dim>,
61 R, 1, Dune::FieldVector<R, 1>,
62 Dune::FieldMatrix<R, 1, dim>
63 >;
64
66 : pq1FiniteElement_{}
67 {
68 // precompute center values for normalization
69 const auto& p1Basis = pq1FiniteElement_.localBasis();
70 const auto refElement = Dune::referenceElement<typename Traits::DomainFieldType, dim>(type());
71 const auto& center = refElement.position(0, 0);
72 p1Basis.evaluateFunction(center, pq1AtCenter_);
73 }
74
78 static constexpr unsigned int size()
79 { return numDofs; }
80
84 void evaluateFunction(const typename Traits::DomainType& x,
85 std::vector<typename Traits::RangeType>& out) const
86 {
87 out.reserve(size());
88 const auto& p1Basis = pq1FiniteElement_.localBasis();
89 p1Basis.evaluateFunction(x, out);
90 const auto bubble = evaluateBubble_(x);
91
92 out.resize(size());
93 out[numVertexDofs] = bubble;
94
95 if constexpr (numBubbleDofs == 2)
96 out[numVertexDofs+1] = scaling_(x)*bubble;
97
98 for (std::size_t i = 0; i < numVertexDofs; ++i)
99 out[i] -= pq1AtCenter_[i]*out[numVertexDofs];
100 }
101
105 void evaluateJacobian(const typename Traits::DomainType& x,
106 std::vector<typename Traits::JacobianType>& out) const
107 {
108 out.reserve(size());
109 const auto& p1Basis = pq1FiniteElement_.localBasis();
110 p1Basis.evaluateJacobian(x, out);
111
112 std::vector<typename Traits::RangeType> shapeValues;
113 p1Basis.evaluateFunction(x, shapeValues);
114
115 const auto bubble = evaluateBubble_(x);
116 const auto bubbleJacobian = evaluateBubbleJacobian_(x);
117
118 for (std::size_t i = 0; i < numVertexDofs; ++i)
119 for (int k = 0; k < dim; ++k)
120 out[i][0][k] -= pq1AtCenter_[i][0]*bubbleJacobian[0][k];
121
122 out.resize(size());
123 out[numVertexDofs] = bubbleJacobian;
124 if constexpr (numBubbleDofs == 2)
125 out[numVertexDofs+1] = scaling_(x)*bubbleJacobian + bubble[0]*scalingJacobian_(x);
126 }
127
134 void partial(const std::array<unsigned int, dim>& order,
135 const typename Traits::DomainType& in,
136 std::vector<typename Traits::RangeType>& out) const
137 {
138 DUNE_THROW(Dune::NotImplemented, "Partial derivatives");
139 }
140
145 static constexpr unsigned int order()
146 {
147 return dim;
148 }
149
153 static constexpr Dune::GeometryType type()
154 {
155 return { typeId };
156 }
157private:
158 // evaluate bubble function at x
159 typename Traits::RangeType evaluateBubble_(const typename Traits::DomainType& x) const
160 {
161 if constexpr (type() == Dune::GeometryTypes::simplex(dim))
162 {
163 if constexpr (dim == 2)
164 return 27*x[0]*x[1]*(1-x[0]-x[1]);
165 else if constexpr (dim == 3)
166 return 256*x[0]*x[1]*x[2]*(1-x[0]-x[1]-x[2]);
167 }
168 else if constexpr (type() == Dune::GeometryTypes::cube(dim))
169 {
170 if constexpr (dim == 2)
171 return 16*x[0]*x[1]*(1-x[0])*(1-x[1]);
172 else if constexpr (dim == 3)
173 return 64*x[0]*x[1]*x[2]*(1-x[0])*(1-x[1])*(1-x[2]);
174 }
175 else
176 DUNE_THROW(Dune::NotImplemented, "Bubble function for " << type());
177 }
178
179 // evaluate bubble function at x
180 typename Traits::JacobianType evaluateBubbleJacobian_(const typename Traits::DomainType& x) const
181 {
182 if constexpr (type() == Dune::GeometryTypes::simplex(dim))
183 {
184 if constexpr (dim == 2)
185 return {{27*(x[1]*(1-x[0]-x[1]) - x[0]*x[1]),
186 27*(x[0]*(1-x[0]-x[1]) - x[0]*x[1])}};
187 else if constexpr (dim == 3)
188 return {{256*(x[1]*x[2]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2]),
189 256*(x[0]*x[2]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2]),
190 256*(x[0]*x[1]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2])}};
191 }
192 else if constexpr (type() == Dune::GeometryTypes::cube(dim))
193 {
194 if constexpr (dim == 2)
195 return {{16*(x[1]*(1-x[0])*(1-x[1]) - x[0]*x[1]*(1-x[1])),
196 16*(x[0]*(1-x[0])*(1-x[1]) - x[0]*x[1]*(1-x[0]))}};
197 else if constexpr (dim == 3)
198 // by the product rule,
199 // 64*(x[1]*x[2]*(1-x[0])*(1-x[1])*(1-x[2]) - x[0]*x[1]*x[2]*(1-x[1])*(1-x[2]))
200 // 64*(x[0]*x[2]*(1-x[0])*(1-x[1])*(1-x[2]) - x[0]*x[1]*x[2]*(1-x[0])*(1-x[2]))
201 // 64*(x[0]*x[1]*(1-x[0])*(1-x[1])*(1-x[2]) - x[0]*x[1]*x[2]*(1-x[0])*(1-x[1]))
202 // which simplifies to:
203 return {{64*x[1]*x[2]*(1-x[1])*(1-x[2])*(1-2*x[0]),
204 64*x[0]*x[2]*(1-x[0])*(1-x[2])*(1-2*x[1]),
205 64*x[0]*x[1]*(1-x[0])*(1-x[1])*(1-2*x[2])}};
206 }
207 else
208 DUNE_THROW(Dune::NotImplemented, "Bubble function for " << type() << " dim = " << dim);
209 }
210
211 auto scaling_(const typename Traits::DomainType& x) const
212 {
213 if constexpr (dim == 2)
214 return (x[0]-0.5) + (x[1]-0.5);
215 else if constexpr (dim == 3)
216 return (x[0]-0.5) + (x[1]-0.5) + (x[2]-0.5);
217 else
218 DUNE_THROW(Dune::NotImplemented, "Bubble function function for dim = " << dim);
219 }
220
221 typename Traits::JacobianType scalingJacobian_(const typename Traits::DomainType& x) const
222 {
223 if constexpr (dim == 2)
224 return {{1.0, 1.0}};
225 else if constexpr (dim == 3)
226 return {{1.0, 1.0, 1.0}};
227 else
228 DUNE_THROW(Dune::NotImplemented, "Bubble function function for dim = " << dim);
229 }
230
231 PQ1FiniteElement pq1FiniteElement_;
232 std::vector<typename Traits::RangeType> pq1AtCenter_;
233};
234
241template<int dim, Dune::GeometryType::Id typeId, std::size_t numCubeBubbleDofs>
243{
244 static constexpr bool isCube = Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim);
245 static constexpr std::size_t numVertexDofs = isCube ? (1<<dim) : (dim+1);
246 static constexpr std::size_t numBubbleDofs = isCube ? numCubeBubbleDofs : 1;
247 static constexpr std::size_t numDofs = numVertexDofs + numBubbleDofs;
248public:
249
251 {
252 // Dune::LocalKey is constructed with
253 // - the local index with respect to the subentity type
254 // - the codim of the subentity the dof is attached to
255 // - the local number of the function to evaluate
256
257 // vertex dofs
258 for (std::size_t i = 0; i < numVertexDofs; ++i)
259 localKeys_[i] = Dune::LocalKey(i, dim, 0);
260
261 // cell dof(s)
262 for (std::size_t i = 0; i < numBubbleDofs; ++i)
263 localKeys_[numVertexDofs + i] = Dune::LocalKey(0, 0, i);
264 }
265
267 static constexpr std::size_t size ()
268 { return numDofs; }
269
271 const Dune::LocalKey& localKey (std::size_t i) const
272 { return localKeys_[i]; }
273
274private:
275 std::array<Dune::LocalKey, numDofs> localKeys_;
276};
277
283template<class LocalBasis>
285{
286public:
295 template<typename F, typename C>
296 void interpolate (const F& f, std::vector<C>& out) const
297 {
298 constexpr auto dim = LocalBasis::Traits::dimDomain;
299 if constexpr (LocalBasis::type() == Dune::GeometryTypes::cube(dim))
300 DUNE_THROW(Dune::NotImplemented, "Interpolation for Q1 bubble not implemented yet");
301
302 out.resize(LocalBasis::size());
303
304 const auto refElement = Dune::referenceElement<typename LocalBasis::Traits::DomainFieldType,dim>(LocalBasis::type());
305
306 // f may return a scalar or a vector with a single entry
307 const auto coefficient = [](const auto& value) -> C
308 {
309 if constexpr (Dune::IsNumber<std::decay_t<decltype(value)>>::value)
310 return value;
311 else
312 return value[0];
313 };
314
315 // Evaluate at the vertices and at the center
316 for (int i = 0; i < refElement.size(dim); ++i)
317 out[i] = coefficient(f(refElement.position(i, dim)));
318 out.back() = coefficient(f(refElement.position(0, 0)));
319 }
320};
321
322} // end namespace Dumux::Detail
323
324namespace Dumux {
325
335template<class D, class R, int dim, Dune::GeometryType::Id typeId, std::size_t numCubeBubbleDofs = 1>
337{
338 static_assert(numCubeBubbleDofs == 1 || numCubeBubbleDofs == 2,
339 "P1/Q1 bubble FE supports numCubeBubbleDofs = 1 or 2");
342 using Interpolation = Detail::PQ1BubbleLocalInterpolation<Basis>;
343
344 static constexpr Dune::GeometryType gt = Dune::GeometryType{ typeId };
345 static_assert(
346 gt == Dune::GeometryTypes::cube(dim) || gt == Dune::GeometryTypes::simplex(dim),
347 "Only implemented for cubes and simplices"
348 );
349
350public:
351 using Traits = Dune::LocalFiniteElementTraits<Basis, Coefficients, Interpolation>;
352
356 const typename Traits::LocalBasisType& localBasis() const
357 {
358 return basis_;
359 }
360
364 const typename Traits::LocalCoefficientsType& localCoefficients() const
365 {
366 return coefficients_;
367 }
368
372 const typename Traits::LocalInterpolationType& localInterpolation() const
373 {
374 return interpolation_;
375 }
376
380 static constexpr std::size_t size()
381 {
382 return Basis::size();
383 }
384
388 static constexpr Dune::GeometryType type()
389 {
390 return Traits::LocalBasisType::type();
391 }
392
393private:
394 Basis basis_;
395 Coefficients coefficients_;
396 Interpolation interpolation_;
397};
398
399} // end namespace Dumux
400
401#endif
P1/Q1 + Bubble functions on the reference element.
Definition pq1bubblelocalfiniteelement.hh:48
void partial(const std::array< unsigned int, dim > &order, const typename Traits::DomainType &in, std::vector< typename Traits::RangeType > &out) const
Evaluate partial derivatives of any order of all shape functions.
Definition pq1bubblelocalfiniteelement.hh:134
static constexpr unsigned int order()
Evaluate the Jacobians of all shape functions we are actually cubic/quartic but cannot represent all ...
Definition pq1bubblelocalfiniteelement.hh:145
Dune::LocalBasisTraits< D, dim, Dune::FieldVector< D, dim >, R, 1, Dune::FieldVector< R, 1 >, Dune::FieldMatrix< R, 1, dim > > Traits
Definition pq1bubblelocalfiniteelement.hh:59
void evaluateJacobian(const typename Traits::DomainType &x, std::vector< typename Traits::JacobianType > &out) const
Evaluate the Jacobians of all shape functions.
Definition pq1bubblelocalfiniteelement.hh:105
static constexpr Dune::GeometryType type()
The reference element type.
Definition pq1bubblelocalfiniteelement.hh:153
static constexpr unsigned int size()
Number of shape functions (one for each vertex and one in the element).
Definition pq1bubblelocalfiniteelement.hh:78
void evaluateFunction(const typename Traits::DomainType &x, std::vector< typename Traits::RangeType > &out) const
Evaluate all shape functions.
Definition pq1bubblelocalfiniteelement.hh:84
PQ1BubbleLocalBasis()
Definition pq1bubblelocalfiniteelement.hh:65
Associations of the P1/Q1 + Bubble degrees of freedom to the facets of the reference element.
Definition pq1bubblelocalfiniteelement.hh:243
const Dune::LocalKey & localKey(std::size_t i) const
Get i-th local key.
Definition pq1bubblelocalfiniteelement.hh:271
PQ1BubbleLocalCoefficients()
Definition pq1bubblelocalfiniteelement.hh:250
static constexpr std::size_t size()
Number of coefficients.
Definition pq1bubblelocalfiniteelement.hh:267
Evaluate the degrees of freedom of a P1 + Bubble basis.
Definition pq1bubblelocalfiniteelement.hh:285
void interpolate(const F &f, std::vector< C > &out) const
Evaluate a given function at the vertices and the cell midpoint.
Definition pq1bubblelocalfiniteelement.hh:296
P1/Q1 + Bubble finite element.
Definition pq1bubblelocalfiniteelement.hh:337
const Traits::LocalInterpolationType & localInterpolation() const
Returns object that evaluates degrees of freedom.
Definition pq1bubblelocalfiniteelement.hh:372
static constexpr std::size_t size()
The number of coefficients in the basis.
Definition pq1bubblelocalfiniteelement.hh:380
const Traits::LocalBasisType & localBasis() const
Returns the local basis, i.e., the set of shape functions.
Definition pq1bubblelocalfiniteelement.hh:356
static constexpr Dune::GeometryType type()
The reference element type that the local finite element is defined on.
Definition pq1bubblelocalfiniteelement.hh:388
Dune::LocalFiniteElementTraits< Basis, Coefficients, Interpolation > Traits
Definition pq1bubblelocalfiniteelement.hh:351
const Traits::LocalCoefficientsType & localCoefficients() const
Returns the assignment of the degrees of freedom to the element subentities.
Definition pq1bubblelocalfiniteelement.hh:364
Corners::value_type center(const Corners &corners)
The center of a given list of corners.
Definition center.hh:24
Definition cvfelocalresidual.hh:25
Definition adapt.hh:17