version 3.11-dev
Loading...
Searching...
No Matches
integrate.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_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/common/ftraits.hh>
20#include <dune/geometry/quadraturerules.hh>
21#include <dune/common/concept.hh>
22
23#if HAVE_DUNE_FUNCTIONS
24#include <dune/functions/gridfunctions/gridfunction.hh>
25#endif
26
30
31namespace Dumux {
32
33// implementation details of the integrate functions
34#ifndef DOXYGEN
35namespace Detail {
36
37struct HasLocalFunction
38{
39 template<class F>
40 auto require(F&& f) -> decltype(
41 localFunction(f),
42 localFunction(f).unbind()
43 );
44};
45
46template<class F>
47static constexpr bool hasLocalFunction()
48{ return Dune::models<HasLocalFunction, F>(); }
49
50template<class Error,
51 typename std::enable_if_t<Dune::IsIndexable<Error>::value, int> = 0>
52Error sqrtNorm(const Error& error)
53{
54 using std::sqrt;
55 auto e = error;
56 for (int i = 0; i < error.size(); ++i)
57 e[i] = sqrt(error[i]);
58 return e;
59}
60
61template<class Error,
62 typename std::enable_if_t<!Dune::IsIndexable<Error>::value, int> = 0>
63Error sqrtNorm(const Error& error)
64{
65 using std::sqrt;
66 return sqrt(error);
67}
68
69template<class T, typename = int>
70struct FieldTypeImpl
71{
72 using type = T;
73};
74
75template<class T>
76struct FieldTypeImpl<T, typename std::enable_if<(sizeof(std::declval<T>()[0]) > 0), int>::type>
77{
78 using type = typename FieldTypeImpl<std::decay_t<decltype(std::declval<T>()[0])>>::type;
79};
80
81template<class T>
82using FieldType = typename FieldTypeImpl<T>::type;
83
84// a scalar integrand, which may be given as a vector with a single entry
85template<class T>
86auto scalarIntegrand(const T& t)
87{
88 if constexpr (Dune::IsNumber<T>::value)
89 return t;
90 else
91 {
92 static_assert(T::size() == 1, "The integrand has to be a scalar or a vector with a single entry");
93 return t[0];
94 }
95}
96
97// squared Euclidean norm, real-valued also for complex-valued entries
98template<class T>
99auto squaredNorm(const T& t)
100{
101 if constexpr (Dune::IsNumber<T>::value)
102 {
103 using std::abs;
104 const auto a = abs(t);
105 return a*a;
106 }
107 else
108 return t.two_norm2();
109}
110
111} // end namespace Detail
112#endif
113
120template<class GridGeometry, class SolutionVector,
121 typename std::enable_if_t<!Detail::hasLocalFunction<SolutionVector>(), int> = 0>
122auto integrateGridFunction(const GridGeometry& gg,
123 const SolutionVector& sol,
124 std::size_t order)
125{
126 using GridView = typename GridGeometry::GridView;
127 using Scalar = typename Detail::FieldType< std::decay_t<decltype(sol[0])> >;
128
129 Scalar integral(0.0);
130 for (const auto& element : elements(gg.gridView()))
131 {
132 const auto elemSol = elementSolution(element, sol, gg);
133 const auto geometry = element.geometry();
134 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
135 for (auto&& qp : quad)
136 {
137 auto value = evalSolution(element, geometry, gg, elemSol, geometry.global(qp.position()));
138 value *= qp.weight()*geometry.integrationElement(qp.position());
139 integral += Detail::scalarIntegrand(value);
140 }
141 }
142 return integral;
143}
144
153template<class GridGeometry, class Sol1, class Sol2,
154 typename std::enable_if_t<!Detail::hasLocalFunction<Sol1>(), int> = 0>
155auto integrateL2Error(const GridGeometry& gg,
156 const Sol1& sol1,
157 const Sol2& sol2,
158 std::size_t order)
159{
160 using GridView = typename GridGeometry::GridView;
161 using Scalar = typename Dune::FieldTraits<Detail::FieldType< std::decay_t<decltype(sol1[0])> >>::real_type;
162
163 Scalar l2norm(0.0);
164 for (const auto& element : elements(gg.gridView()))
165 {
166 const auto elemSol1 = elementSolution(element, sol1, gg);
167 const auto elemSol2 = elementSolution(element, sol2, gg);
168
169 const auto geometry = element.geometry();
170 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
171 for (auto&& qp : quad)
172 {
173 const auto& globalPos = geometry.global(qp.position());
174 const auto value1 = evalSolution(element, geometry, gg, elemSol1, globalPos);
175 const auto value2 = evalSolution(element, geometry, gg, elemSol2, globalPos);
176 const auto error = (value1 - value2);
177 l2norm += Detail::squaredNorm(error)*qp.weight()*geometry.integrationElement(qp.position());
178 }
179 }
180
181 using std::sqrt;
182 return sqrt(l2norm);
183}
184
185#if HAVE_DUNE_FUNCTIONS
186
194template<class GridView, class F,
195 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
196auto integrateGridFunction(const GridView& gv,
197 const F& f,
198 std::size_t order)
199{
200 auto fLocal = localFunction(f);
201
202 using Element = typename GridView::template Codim<0>::Entity;
203 using LocalPosition = typename Element::Geometry::LocalCoordinate;
204 using Scalar = typename Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >;
205
206 Scalar integral(0.0);
207 for (const auto& element : elements(gv))
208 {
209 fLocal.bind(element);
210
211 const auto geometry = element.geometry();
212 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
213 for (auto&& qp : quad)
214 {
215 auto value = fLocal(qp.position());
216 value *= qp.weight()*geometry.integrationElement(qp.position());
217 integral += Detail::scalarIntegrand(value);
218 }
219
220 fLocal.unbind();
221 }
222 return integral;
223}
224
234template<class GridView, class F, class G,
235 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
236auto integrateL2Error(const GridView& gv,
237 const F& f,
238 const G& g,
239 std::size_t order)
240{
241 auto fLocal = localFunction(f);
242 auto gLocal = localFunction(g);
243
244 using Element = typename GridView::template Codim<0>::Entity;
245 using LocalPosition = typename Element::Geometry::LocalCoordinate;
246 using Scalar = typename Dune::FieldTraits<Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >>::real_type;
247
248 Scalar l2norm(0.0);
249 for (const auto& element : elements(gv))
250 {
251 fLocal.bind(element);
252 gLocal.bind(element);
253
254 const auto geometry = element.geometry();
255 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
256 for (auto&& qp : quad)
257 {
258 const auto error = fLocal(qp.position()) - gLocal(qp.position());
259 l2norm += Detail::squaredNorm(error)*qp.weight()*geometry.integrationElement(qp.position());
260 }
261
262 gLocal.unbind();
263 fLocal.unbind();
264 }
265
266 using std::sqrt;
267 return sqrt(l2norm);
268}
269#endif
270
279template<class Scalar, class Function,
280 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
281Scalar integrateScalarFunction(const Function& f,
282 const Scalar lowerBound,
283 const Scalar upperBound,
284 const Scalar targetAbsoluteError = 1e-13)
285{
286 return DoubleExponentialIntegrator<Scalar>::integrate(f, lowerBound, upperBound, targetAbsoluteError);
287}
288
289} // end namespace Dumux
290
291#endif
static Scalar integrate(const Function &f, const Scalar a, const Scalar b, const Scalar targetAbsoluteError, int &numFunctionEvaluations, Scalar &errorEstimate)
Integrate an analytic function over a finite interval.
Definition doubleexpintegrator.hh:80
A double exponential integrator.
Element solution classes and factory functions.
free functions for the evaluation of primary variables inside elements.
PrimaryVariables evalSolution(const Element &element, const typename Element::Geometry &geometry, const typename FVElementGeometry::GridGeometry &gridGeometry, const CVFEElementSolution< FVElementGeometry, PrimaryVariables > &elemSol, const typename Element::Geometry::GlobalCoordinate &globalPos, bool ignoreState=false)
Interpolates a given box element solution at a given global position. Uses the finite element cache o...
Definition evalsolution.hh:197
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition cellcentered/elementsolution.hh:101
FieldType
Identifier for vtk field types.
Definition fieldtype.hh:22
@ element
Definition fieldtype.hh:23
Definition cvfelocalresidual.hh:25
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
Definition adapt.hh:17
Scalar integrateScalarFunction(const Function &f, const Scalar lowerBound, const Scalar upperBound, const Scalar targetAbsoluteError=1e-13)
Integrate a scalar function.
Definition integrate.hh:281
auto integrateGridFunction(const GridGeometry &gg, const SolutionVector &sol, std::size_t order)
Integrate a grid function over a grid view.
Definition integrate.hh:122
auto integrateL2Error(const GridGeometry &gg, const Sol1 &sol1, const Sol2 &sol2, std::size_t order)
Integrate a function over a grid view.
Definition integrate.hh:155