GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/discretization/pq1bubble/pq1bubblelocalfiniteelement.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 51 65 78.5%
Functions: 13 24 54.2%
Branches: 16 52 30.8%

Line Branch Exec Source
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 //
7 /*!
8 * \file
9 * \ingroup PQ1BubbleDiscretization
10 * \brief Evaluate P1/Q1 basis with bubble function
11 */
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
24 #include <dune/geometry/type.hh>
25 #include <dune/geometry/referenceelements.hh>
26
27 #include <dune/localfunctions/common/localbasis.hh>
28 #include <dune/localfunctions/common/localfiniteelementtraits.hh>
29 #include <dune/localfunctions/common/localkey.hh>
30
31 #include <dune/localfunctions/lagrange/lagrangesimplex.hh>
32 #include <dune/localfunctions/lagrange/lagrangecube.hh>
33
34 namespace Dumux::Detail {
35
36 /*!
37 * \brief P1/Q1 + Bubble on the reference element
38 *
39 * \tparam D Type to represent the field in the domain
40 * \tparam R Type to represent the field in the range
41 * \tparam dim Dimension of the domain element
42 * \tparam typeId The geometry type
43 */
44 template<class D, class R, unsigned int dim, Dune::GeometryType::Id typeId>
45 class PQ1BubbleLocalBasis
46 {
47 using PQ1FiniteElement = std::conditional_t<
48 Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim),
49 Dune::LagrangeCubeLocalFiniteElement<D, R, dim, 1>,
50 Dune::LagrangeSimplexLocalFiniteElement<D, R, dim, 1>
51 >;
52 static constexpr std::size_t numDofs
53 = Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim) ? (1<<dim)+1 : (dim+1)+1;
54 public:
55 using Traits = Dune::LocalBasisTraits<
56 D, dim, Dune::FieldVector<D, dim>,
57 R, 1, Dune::FieldVector<R, 1>,
58 Dune::FieldMatrix<R, 1, dim>
59 >;
60
61 56 PQ1BubbleLocalBasis()
62
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
56 : pq1FiniteElement_{}
63 {
64 // precompute center values for normalization
65
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 const auto& p1Basis = pq1FiniteElement_.localBasis();
66
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
56 const auto refElement = Dune::referenceElement<typename Traits::DomainFieldType, dim>(type());
67 56 const auto& center = refElement.position(0, 0);
68
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 p1Basis.evaluateFunction(center, pq1AtCenter_);
69 56 }
70
71 /*!
72 * \brief Number of shape functions (one for each vertex and one in the element)
73 */
74 static constexpr unsigned int size()
75 { return numDofs; }
76
77 /*!
78 * \brief Evaluate all shape functions
79 */
80 37431036 void evaluateFunction(const typename Traits::DomainType& x,
81 std::vector<typename Traits::RangeType>& out) const
82 {
83 37431036 out.reserve(size());
84 37431036 const auto& p1Basis = pq1FiniteElement_.localBasis();
85 37431036 p1Basis.evaluateFunction(x, out);
86 37431036 const auto bubble = evaluateBubble_(x);
87 37431036 out.resize(size());
88 37431036 out.back() = bubble;
89
2/2
✓ Branch 0 taken 64603880 times.
✓ Branch 1 taken 18715518 times.
166638796 for (int i = 0; i < numDofs-1; ++i)
90 129207760 out[i] -= pq1AtCenter_[i]*out.back();
91 37431036 }
92
93 /*!
94 * \brief Evaluate the Jacobians of all shape functions
95 */
96 2105276 void evaluateJacobian(const typename Traits::DomainType& x,
97 std::vector<typename Traits::JacobianType>& out) const
98 {
99 2105276 out.reserve(size());
100 2105276 const auto& p1Basis = pq1FiniteElement_.localBasis();
101 2105276 p1Basis.evaluateJacobian(x, out);
102
103 2105276 std::vector<typename Traits::RangeType> shapeValues;
104
1/2
✓ Branch 1 taken 1052638 times.
✗ Branch 2 not taken.
2105276 p1Basis.evaluateFunction(x, shapeValues);
105
106 2105276 const auto bubbleJacobian = evaluateBubbleJacobian_(x);
107
108
2/2
✓ Branch 1 taken 3792408 times.
✓ Branch 2 taken 1052638 times.
9690092 for (int i = 0; i < numDofs-1; ++i)
109
2/2
✓ Branch 0 taken 7791464 times.
✓ Branch 1 taken 3792408 times.
23167744 for (int k = 0; k < dim; ++k)
110 15582928 out[i][0][k] -= pq1AtCenter_[i]*bubbleJacobian[0][k];
111
112
1/2
✓ Branch 1 taken 1052638 times.
✗ Branch 2 not taken.
2105276 out.resize(size());
113
1/2
✓ Branch 0 taken 1052638 times.
✗ Branch 1 not taken.
2105276 out.back() = bubbleJacobian;
114 2105276 }
115
116 /** \brief Evaluate partial derivatives of any order of all shape functions
117 *
118 * \param order Order of the partial derivatives, in the classic multi-index notation
119 * \param in Position where to evaluate the derivatives
120 * \param[out] out The desired partial derivatives
121 */
122 void partial(const std::array<unsigned int, dim>& order,
123 const typename Traits::DomainType& in,
124 std::vector<typename Traits::RangeType>& out) const
125 {
126 DUNE_THROW(Dune::NotImplemented, "Partial derivatives");
127 }
128
129 /*!
130 * \brief Evaluate the Jacobians of all shape functions
131 * we are actually cubic/quartic but cannot represent all cubic/quartic polynomials
132 */
133 static constexpr unsigned int order()
134 {
135 return 1;
136 }
137
138 /*!
139 * \brief The reference element type
140 */
141 static constexpr Dune::GeometryType type()
142 {
143 return { typeId };
144 }
145 private:
146 // evaluate bubble function at x
147 18715518 typename Traits::RangeType evaluateBubble_(const typename Traits::DomainType& x) const
148 {
149 if constexpr (type() == Dune::GeometryTypes::simplex(dim))
150 {
151 if constexpr (dim == 2)
152 10258192 return 27*x[0]*x[1]*(1-x[0]-x[1]);
153 else if constexpr (dim == 3)
154 754062 return 256*x[0]*x[1]*x[2]*(1-x[0]-x[1]-x[2]);
155 }
156 else if constexpr (type() == Dune::GeometryTypes::cube(dim))
157 {
158 if constexpr (dim == 2)
159 7703264 return 16*x[0]*x[1]*(1-x[0])*(1-x[1]);
160 else if constexpr (dim == 3)
161 return 64*x[0]*x[1]*x[2]*(1-x[0])*(1-x[1])*(1-x[2]);
162 }
163 else
164 DUNE_THROW(Dune::NotImplemented, "Bubble function for " << type());
165 }
166
167 // evaluate bubble function at x
168 2105276 typename Traits::JacobianType evaluateBubbleJacobian_(const typename Traits::DomainType& x) const
169 {
170 if constexpr (type() == Dune::GeometryTypes::simplex(dim))
171 {
172 if constexpr (dim == 2)
173 836288 return {{27*(x[1]*(1-x[0]-x[1]) - x[0]*x[1]),
174 836288 27*(x[0]*(1-x[0]-x[1]) - x[0]*x[1])}};
175 else if constexpr (dim == 3)
176 103324 return {{256*(x[1]*x[2]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2]),
177 103324 256*(x[0]*x[2]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2]),
178 103324 256*(x[0]*x[1]*(1-x[0]-x[1]-x[2]) - x[0]*x[1]*x[2])}};
179 }
180 else if constexpr (type() == Dune::GeometryTypes::cube(dim))
181 {
182 if constexpr (dim == 2)
183 1165664 return {{16*(x[1]*(1-x[0])*(1-x[1]) - x[0]*x[1]*(1-x[1])),
184 1165664 16*(x[0]*(1-x[0])*(1-x[1]) - x[0]*x[1]*(1-x[0]))}};
185 else if constexpr (dim == 3)
186 return {{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]),
187 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]),
188 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])}};
189 }
190 else
191 DUNE_THROW(Dune::NotImplemented, "Bubble function for " << type() << " dim = " << dim);
192 }
193
194 PQ1FiniteElement pq1FiniteElement_;
195 std::vector<typename Traits::RangeType> pq1AtCenter_;
196 };
197
198 /*!
199 * \brief Associations of the P1/Q1 + Bubble degrees of freedom to the facets of the reference element
200 * \tparam dim Dimension of the reference element
201 * \tparam typeId The geometry type
202 */
203 template<int dim, Dune::GeometryType::Id typeId>
204 class PQ1BubbleLocalCoefficients
205 {
206 static constexpr std::size_t numDofs
207 = Dune::GeometryType{ typeId } == Dune::GeometryTypes::cube(dim) ? (1<<dim)+1 : (dim+1)+1;
208 public:
209
210 PQ1BubbleLocalCoefficients()
211 {
212 // Dune::LocalKey is constructed with
213 // - the local index with respect to the subentity type
214 // - the codim of the subentity the dof is attached to
215 // - the local number of the function to evaluate
216
217 // vertex dofs
218 for (std::size_t i=0; i<size()-1; i++)
219 localKeys_[i] = Dune::LocalKey(i, dim, 0);
220
221 // cell dof
222 localKeys_.back() = Dune::LocalKey(0, 0, 0);
223 }
224
225 //! Number of coefficients
226 static constexpr std::size_t size ()
227 { return numDofs; }
228
229 //! Get i-th local key
230 4714080 const Dune::LocalKey& localKey (std::size_t i) const
231 4714080 { return localKeys_[i]; }
232
233 private:
234 std::array<Dune::LocalKey, numDofs> localKeys_;
235 };
236
237 /*!
238 * \brief Evaluate the degrees of freedom of a P1 + Bubble basis
239 *
240 * \tparam LocalBasis The corresponding set of shape functions
241 */
242 template<class LocalBasis>
243 class PQ1BubbleLocalInterpolation
244 {
245 public:
246 /*!
247 * \brief Evaluate a given function at the vertices and the cell midpoint
248 *
249 * \tparam F Type of function to evaluate
250 * \tparam C Type used for the values of the function
251 * \param[in] f Function to evaluate (call operator that gets a local position)
252 * \param[out] out Array of function values
253 */
254 template<typename F, typename C>
255 void interpolate (const F& f, std::vector<C>& out) const
256 {
257 constexpr auto dim = LocalBasis::Traits::dimDomain;
258
259 out.resize(LocalBasis::size());
260
261 const auto refElement = Dune::referenceElement<typename LocalBasis::Traits::DomainFieldType,dim>(LocalBasis::type());
262
263 // Evaluate at the vertices and at the center
264 for (int i = 0; i < refElement.size(dim); ++i)
265 out[i] = f(refElement.position(i, dim));
266 out.back() = f(refElement.position(0, 0));
267 }
268 };
269
270 } // end namespace Dumux::Detail
271
272 namespace Dumux {
273
274 /*!
275 * \brief P1/Q1 + Bubble finite element
276 *
277 * \tparam D type used for domain coordinates
278 * \tparam R type used for function values
279 * \tparam dim dimension of the reference element
280 * \tparam typeId The geometry type
281 */
282 template<class D, class R, int dim, Dune::GeometryType::Id typeId>
283
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
84 class PQ1BubbleLocalFiniteElement
284 {
285 using Basis = Detail::PQ1BubbleLocalBasis<D, R, dim, typeId>;
286 using Coefficients = Detail::PQ1BubbleLocalCoefficients<dim, typeId>;
287 using Interpolation = Detail::PQ1BubbleLocalInterpolation<Basis>;
288
289 static constexpr Dune::GeometryType gt = Dune::GeometryType{ typeId };
290 static_assert(
291 gt == Dune::GeometryTypes::cube(dim) || gt == Dune::GeometryTypes::simplex(dim),
292 "Only implemented for cubes and simplices"
293 );
294
295 public:
296 using Traits = Dune::LocalFiniteElementTraits<Basis, Coefficients, Interpolation>;
297
298 /*!
299 * \brief Returns the local basis, i.e., the set of shape functions
300 */
301 28 const typename Traits::LocalBasisType& localBasis() const
302 {
303 28 return basis_;
304 }
305
306 /*!
307 * \brief Returns the assignment of the degrees of freedom to the element subentities
308 */
309 28 const typename Traits::LocalCoefficientsType& localCoefficients() const
310 {
311 28 return coefficients_;
312 }
313
314 /*!
315 * \brief Returns object that evaluates degrees of freedom
316 */
317 28 const typename Traits::LocalInterpolationType& localInterpolation() const
318 {
319 28 return interpolation_;
320 }
321
322 /*!
323 * \brief The number of coefficients in the basis
324 */
325 static constexpr std::size_t size()
326 {
327 return Basis::size();
328 }
329
330 /*!
331 * \brief The reference element type that the local finite element is defined on
332 */
333 static constexpr Dune::GeometryType type()
334 {
335 return Traits::LocalBasisType::type();
336 }
337
338 private:
339 Basis basis_;
340 Coefficients coefficients_;
341 Interpolation interpolation_;
342 };
343
344 } // end namespace Dumux
345
346 #endif
347