GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/common/integrate.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 43 44 97.7%
Functions: 4 6 66.7%
Branches: 23 67 34.3%

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-FileCopyrightInfo: 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 Core
10 * \brief Define helper functions for integration
11 */
12 #ifndef DUMUX_COMMON_INTEGRATE_HH
13 #define DUMUX_COMMON_INTEGRATE_HH
14
15 #include <cmath>
16 #include <type_traits>
17
18 #include <dune/common/typetraits.hh>
19 #include <dune/geometry/quadraturerules.hh>
20 #include <dune/common/concept.hh>
21
22 #if HAVE_DUNE_FUNCTIONS
23 #include <dune/functions/gridfunctions/gridfunction.hh>
24 #endif
25
26 #include <dumux/common/doubleexpintegrator.hh>
27 #include <dumux/discretization/evalsolution.hh>
28 #include <dumux/discretization/elementsolution.hh>
29
30 namespace Dumux {
31
32 // implementation details of the integrate functions
33 #ifndef DOXYGEN
34 namespace Detail {
35
36 struct HasLocalFunction
37 {
38 template<class F>
39 auto require(F&& f) -> decltype(
40 localFunction(f),
41 localFunction(f).unbind()
42 );
43 };
44
45 template<class F>
46 static constexpr bool hasLocalFunction()
47 { return Dune::models<HasLocalFunction, F>(); }
48
49 template<class Error,
50 typename std::enable_if_t<Dune::IsIndexable<Error>::value, int> = 0>
51 Error sqrtNorm(const Error& error)
52 {
53 using std::sqrt;
54 auto e = error;
55 for (int i = 0; i < error.size(); ++i)
56 e[i] = sqrt(error[i]);
57 return e;
58 }
59
60 template<class Error,
61 typename std::enable_if_t<!Dune::IsIndexable<Error>::value, int> = 0>
62 Error sqrtNorm(const Error& error)
63 {
64 using std::sqrt;
65 return sqrt(error);
66 }
67
68 template<class T, typename = int>
69 struct FieldTypeImpl
70 {
71 using type = T;
72 };
73
74 template<class T>
75 struct FieldTypeImpl<T, typename std::enable_if<(sizeof(std::declval<T>()[0]) > 0), int>::type>
76 {
77 using type = typename FieldTypeImpl<std::decay_t<decltype(std::declval<T>()[0])>>::type;
78 };
79
80 template<class T>
81 using FieldType = typename FieldTypeImpl<T>::type;
82
83 } // end namespace Detail
84 #endif
85
86 /*!
87 * \brief Integrate a grid function over a grid view
88 * \param gg the grid geometry
89 * \param sol the solution vector
90 * \param order the order of the quadrature rule
91 */
92 template<class GridGeometry, class SolutionVector,
93 typename std::enable_if_t<!Detail::hasLocalFunction<SolutionVector>(), int> = 0>
94 auto integrateGridFunction(const GridGeometry& gg,
95 const SolutionVector& sol,
96 std::size_t order)
97 {
98 using GridView = typename GridGeometry::GridView;
99 using Scalar = typename Detail::FieldType< std::decay_t<decltype(sol[0])> >;
100
101 Scalar integral(0.0);
102 for (const auto& element : elements(gg.gridView()))
103 {
104 const auto elemSol = elementSolution(element, sol, gg);
105 const auto geometry = element.geometry();
106 const auto& quad = Dune::QuadratureRules<Scalar, GridView::dimension>::rule(geometry.type(), order);
107 for (auto&& qp : quad)
108 {
109 auto value = evalSolution(element, geometry, gg, elemSol, geometry.global(qp.position()));
110 value *= qp.weight()*geometry.integrationElement(qp.position());
111 integral += value;
112 }
113 }
114 return integral;
115 }
116
117 /*!
118 * \brief Integrate a function over a grid view
119 * \param gg the grid geometry
120 * \param sol1 the first function
121 * \param sol2 the second function
122 * \param order the order of the quadrature rule
123 * \note dune functions currently doesn't support composing two functions
124 */
125 template<class GridGeometry, class Sol1, class Sol2,
126 typename std::enable_if_t<!Detail::hasLocalFunction<Sol1>(), int> = 0>
127 12 auto integrateL2Error(const GridGeometry& gg,
128 const Sol1& sol1,
129 const Sol2& sol2,
130 std::size_t order)
131 {
132 using GridView = typename GridGeometry::GridView;
133 using Scalar = typename Detail::FieldType< std::decay_t<decltype(sol1[0])> >;
134
135 12 Scalar l2norm(0.0);
136
1/2
✓ Branch 2 taken 7412 times.
✗ Branch 3 not taken.
14824 for (const auto& element : elements(gg.gridView()))
137 {
138 7400 const auto elemSol1 = elementSolution(element, sol1, gg);
139 7400 const auto elemSol2 = elementSolution(element, sol2, gg);
140
141 7400 const auto geometry = element.geometry();
142 14800 const auto& quad = Dune::QuadratureRules<Scalar, GridView::dimension>::rule(geometry.type(), order);
143
4/4
✓ Branch 0 taken 15000 times.
✓ Branch 1 taken 7400 times.
✓ Branch 2 taken 15000 times.
✓ Branch 3 taken 7400 times.
52200 for (auto&& qp : quad)
144 {
145
2/4
✓ Branch 1 taken 14600 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14600 times.
✗ Branch 5 not taken.
30000 const auto& globalPos = geometry.global(qp.position());
146
1/2
✓ Branch 1 taken 15000 times.
✗ Branch 2 not taken.
15000 const auto value1 = evalSolution(element, geometry, gg, elemSol1, globalPos);
147
1/2
✓ Branch 1 taken 15000 times.
✗ Branch 2 not taken.
15000 const auto value2 = evalSolution(element, geometry, gg, elemSol2, globalPos);
148 15000 const auto error = (value1 - value2);
149 60000 l2norm += (error*error)*qp.weight()*geometry.integrationElement(qp.position());
150 }
151 }
152
153 using std::sqrt;
154 12 return sqrt(l2norm);
155 }
156
157 #if HAVE_DUNE_FUNCTIONS
158
159 /*!
160 * \brief Integrate a grid function over a grid view
161 * \param gv the grid view
162 * \param f the grid function
163 * \param order the order of the quadrature rule
164 * \note overload for a Dune::Functions::GridFunction
165 */
166 template<class GridView, class F,
167 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
168 1 auto integrateGridFunction(const GridView& gv,
169 const F& f,
170 std::size_t order)
171 {
172 1 auto fLocal = localFunction(f);
173
174 using Element = typename GridView::template Codim<0>::Entity;
175 using LocalPosition = typename Element::Geometry::LocalCoordinate;
176 using Scalar = typename Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >;
177
178 1 Scalar integral(0.0);
179
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1090 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1089 times.
✗ Branch 8 not taken.
2180 for (const auto& element : elements(gv))
180 {
181
1/2
✓ Branch 1 taken 1089 times.
✗ Branch 2 not taken.
1089 fLocal.bind(element);
182
183 1089 const auto geometry = element.geometry();
184 2178 const auto& quad = Dune::QuadratureRules<Scalar, GridView::dimension>::rule(geometry.type(), order);
185
4/4
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 1089 times.
✓ Branch 2 taken 1089 times.
✓ Branch 3 taken 1089 times.
5445 for (auto&& qp : quad)
186 {
187
2/4
✓ Branch 1 taken 1089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1089 times.
✗ Branch 5 not taken.
2178 auto value = fLocal(qp.position());
188 2178 value *= qp.weight()*geometry.integrationElement(qp.position());
189 1089 integral += value;
190 }
191
192
1/2
✓ Branch 0 taken 1089 times.
✗ Branch 1 not taken.
2178 fLocal.unbind();
193 }
194 1 return integral;
195 }
196
197 /*!
198 * \brief Integrate a function over a grid view
199 * \param gv the grid view
200 * \param f the first function
201 * \param g the second function
202 * \param order the order of the quadrature rule
203 * \note overload for a Dune::Functions::GridFunction
204 * \note dune functions currently doesn't support composing two functions
205 */
206 template<class GridView, class F, class G,
207 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
208 29 auto integrateL2Error(const GridView& gv,
209 const F& f,
210 const G& g,
211 std::size_t order)
212 {
213
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
42 auto fLocal = localFunction(f);
214
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
29 auto gLocal = localFunction(g);
215
216 using Element = typename GridView::template Codim<0>::Entity;
217 using LocalPosition = typename Element::Geometry::LocalCoordinate;
218 using Scalar = typename Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >;
219
220 29 Scalar l2norm(0.0);
221
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
221829 for (const auto& element : elements(gv))
222 {
223
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
110900 fLocal.bind(element);
224
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
110900 gLocal.bind(element);
225
226
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
110900 const auto geometry = element.geometry();
227 221800 const auto& quad = Dune::QuadratureRules<Scalar, GridView::dimension>::rule(geometry.type(), order);
228
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1219900 for (auto&& qp : quad)
229 {
230
0/5
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
887200 const auto error = fLocal(qp.position()) - gLocal(qp.position());
231 1330800 l2norm += (error*error)*qp.weight()*geometry.integrationElement(qp.position());
232 }
233
234
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
110900 gLocal.unbind();
235
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
221800 fLocal.unbind();
236 }
237
238 using std::sqrt;
239 42 return sqrt(l2norm);
240 }
241 #endif
242
243 /*!
244 * \brief Integrate a scalar function
245 * \param f the integrand (invocable with a single scalar)
246 * \param lowerBound lower integral bound
247 * \param upperBound upper integral bound
248 * \param targetAbsoluteError desired absolute error in the result
249 * \return The value of the integral
250 */
251 template<class Scalar, class Function,
252 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
253 Scalar integrateScalarFunction(const Function& f,
254 const Scalar lowerBound,
255 const Scalar upperBound,
256 const Scalar targetAbsoluteError = 1e-13)
257 {
258
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 50 times.
✗ Branch 12 not taken.
2149664 return DoubleExponentialIntegrator<Scalar>::integrate(f, lowerBound, upperBound, targetAbsoluteError);
259 }
260
261 } // end namespace Dumux
262
263 #endif
264