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// squared Euclidean norm, real-valued also for complex-valued entries
85template<class T>
86auto squaredNorm(const T& t)
87{
88 if constexpr (Dune::IsNumber<T>::value)
89 {
90 using std::abs;
91 const auto a = abs(t);
92 return a*a;
93 }
94 else
95 return t.two_norm2();
96}
97
98} // end namespace Detail
99#endif
100
107template<class GridGeometry, class SolutionVector,
108 typename std::enable_if_t<!Detail::hasLocalFunction<SolutionVector>(), int> = 0>
109auto integrateGridFunction(const GridGeometry& gg,
110 const SolutionVector& sol,
111 std::size_t order)
112{
113 using GridView = typename GridGeometry::GridView;
114 using Scalar = typename Detail::FieldType< std::decay_t<decltype(sol[0])> >;
115
116 Scalar integral(0.0);
117 for (const auto& element : elements(gg.gridView()))
118 {
119 const auto elemSol = elementSolution(element, sol, gg);
120 const auto geometry = element.geometry();
121 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
122 for (auto&& qp : quad)
123 {
124 auto value = evalSolution(element, geometry, gg, elemSol, geometry.global(qp.position()));
125 value *= qp.weight()*geometry.integrationElement(qp.position());
126 integral += value;
127 }
128 }
129 return integral;
130}
131
140template<class GridGeometry, class Sol1, class Sol2,
141 typename std::enable_if_t<!Detail::hasLocalFunction<Sol1>(), int> = 0>
142auto integrateL2Error(const GridGeometry& gg,
143 const Sol1& sol1,
144 const Sol2& sol2,
145 std::size_t order)
146{
147 using GridView = typename GridGeometry::GridView;
148 using Scalar = typename Dune::FieldTraits<Detail::FieldType< std::decay_t<decltype(sol1[0])> >>::real_type;
149
150 Scalar l2norm(0.0);
151 for (const auto& element : elements(gg.gridView()))
152 {
153 const auto elemSol1 = elementSolution(element, sol1, gg);
154 const auto elemSol2 = elementSolution(element, sol2, gg);
155
156 const auto geometry = element.geometry();
157 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
158 for (auto&& qp : quad)
159 {
160 const auto& globalPos = geometry.global(qp.position());
161 const auto value1 = evalSolution(element, geometry, gg, elemSol1, globalPos);
162 const auto value2 = evalSolution(element, geometry, gg, elemSol2, globalPos);
163 const auto error = (value1 - value2);
164 l2norm += Detail::squaredNorm(error)*qp.weight()*geometry.integrationElement(qp.position());
165 }
166 }
167
168 using std::sqrt;
169 return sqrt(l2norm);
170}
171
172#if HAVE_DUNE_FUNCTIONS
173
181template<class GridView, class F,
182 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
183auto integrateGridFunction(const GridView& gv,
184 const F& f,
185 std::size_t order)
186{
187 auto fLocal = localFunction(f);
188
189 using Element = typename GridView::template Codim<0>::Entity;
190 using LocalPosition = typename Element::Geometry::LocalCoordinate;
191 using Scalar = typename Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >;
192
193 Scalar integral(0.0);
194 for (const auto& element : elements(gv))
195 {
196 fLocal.bind(element);
197
198 const auto geometry = element.geometry();
199 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
200 for (auto&& qp : quad)
201 {
202 auto value = fLocal(qp.position());
203 value *= qp.weight()*geometry.integrationElement(qp.position());
204 integral += value;
205 }
206
207 fLocal.unbind();
208 }
209 return integral;
210}
211
221template<class GridView, class F, class G,
222 typename std::enable_if_t<Detail::hasLocalFunction<F>(), int> = 0>
223auto integrateL2Error(const GridView& gv,
224 const F& f,
225 const G& g,
226 std::size_t order)
227{
228 auto fLocal = localFunction(f);
229 auto gLocal = localFunction(g);
230
231 using Element = typename GridView::template Codim<0>::Entity;
232 using LocalPosition = typename Element::Geometry::LocalCoordinate;
233 using Scalar = typename Dune::FieldTraits<Detail::FieldType< std::decay_t<decltype(fLocal(std::declval<LocalPosition>()))> >>::real_type;
234
235 Scalar l2norm(0.0);
236 for (const auto& element : elements(gv))
237 {
238 fLocal.bind(element);
239 gLocal.bind(element);
240
241 const auto geometry = element.geometry();
242 const auto& quad = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>::rule(geometry.type(), order);
243 for (auto&& qp : quad)
244 {
245 const auto error = fLocal(qp.position()) - gLocal(qp.position());
246 l2norm += Detail::squaredNorm(error)*qp.weight()*geometry.integrationElement(qp.position());
247 }
248
249 gLocal.unbind();
250 fLocal.unbind();
251 }
252
253 using std::sqrt;
254 return sqrt(l2norm);
255}
256#endif
257
266template<class Scalar, class Function,
267 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
268Scalar integrateScalarFunction(const Function& f,
269 const Scalar lowerBound,
270 const Scalar upperBound,
271 const Scalar targetAbsoluteError = 1e-13)
272{
273 return DoubleExponentialIntegrator<Scalar>::integrate(f, lowerBound, upperBound, targetAbsoluteError);
274}
275
276} // end namespace Dumux
277
278#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:268
auto integrateGridFunction(const GridGeometry &gg, const SolutionVector &sol, std::size_t order)
Integrate a grid function over a grid view.
Definition integrate.hh:109
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:142