GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/discretization/evalsolution.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 30 48 62.5%
Functions: 27 84 32.1%
Branches: 39 90 43.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 Discretization
10 * \brief free functions for the evaluation of primary variables inside elements.
11 */
12 #ifndef DUMUX_DISCRETIZATION_EVAL_SOLUTION_HH
13 #define DUMUX_DISCRETIZATION_EVAL_SOLUTION_HH
14
15 #include <iterator>
16 #include <algorithm>
17 #include <type_traits>
18 #include <memory>
19
20 #include <dune/localfunctions/lagrange/pqkfactory.hh>
21
22 #include <dumux/common/typetraits/state.hh>
23 #include <dumux/common/typetraits/isvalid.hh>
24 #include <dumux/discretization/method.hh>
25 #include <dumux/discretization/cvfe/elementsolution.hh>
26 #include <dumux/discretization/cellcentered/elementsolution.hh>
27
28 namespace Dumux {
29
30 // some implementation details
31 namespace Detail {
32
33 //! returns true if all states in an element solution are the same
34 template<class ElementSolution>
35 bool allStatesEqual(const ElementSolution& elemSol, std::true_type hasState)
36 {
37 // determine if all states are the same at all vertices
38 auto firstState = elemSol[0].state();
39 for (std::size_t i = 1; i < elemSol.size(); ++i)
40 if (elemSol[i].state() != firstState)
41 return false;
42
43 return true;
44 }
45
46 //! overload if the solution is stateless
47 template<class ElementSolution>
48 bool allStatesEqual(const ElementSolution& elemSol, std::false_type hasState)
49 {
50 return true;
51 }
52
53 //! return the solution at the closest dof
54 template<class Geometry, class ElementSolution>
55 auto minDistVertexSol(const Geometry& geometry, const typename Geometry::GlobalCoordinate& globalPos,
56 const ElementSolution& elemSol)
57 {
58 // calculate the distances from the evaluation point to the vertices
59 std::vector<typename Geometry::ctype> distances(geometry.corners());
60 for (int i = 0; i < geometry.corners(); ++i)
61 distances[i] = (geometry.corner(i) - globalPos).two_norm2();
62
63 // determine the minimum distance and corresponding vertex
64 auto minDistanceIt = std::min_element(distances.begin(), distances.end());
65 return elemSol[std::distance(distances.begin(), minDistanceIt)];
66 }
67
68 /*!
69 * \brief Interpolates a given control-volume finite element solution at a given global position.
70 * Uses the finite element cache of the grid geometry.
71 * \ingroup Discretization
72 *
73 * \return the interpolated primary variables
74 * \param element The element
75 * \param geometry The element geometry
76 * \param gridGeometry The finite volume grid geometry
77 * \param elemSol The primary variables at the dofs of the element
78 * \param globalPos The global position
79 * \param ignoreState If true, the state of primary variables is ignored
80 */
81 template<class Element, class GridGeometry, class CVFEElemSol>
82 typename CVFEElemSol::PrimaryVariables
83 57747412 evalCVFESolution(const Element& element,
84 const typename Element::Geometry& geometry,
85 const GridGeometry& gridGeometry,
86 const CVFEElemSol& elemSol,
87 const typename Element::Geometry::GlobalCoordinate& globalPos,
88 bool ignoreState = false)
89 {
90 // determine if all states are the same at all vertices
91 using HasState = decltype(isValid(Detail::hasState())(elemSol[0]));
92 57747412 bool allStatesEqual = ignoreState || Detail::allStatesEqual(elemSol, HasState{});
93
94 if (allStatesEqual)
95 {
96 using Scalar = typename CVFEElemSol::PrimaryVariables::value_type;
97
98 // interpolate the solution
99
1/2
✓ Branch 4 taken 29200 times.
✗ Branch 5 not taken.
117121157 const auto& localBasis = gridGeometry.feCache().get(geometry.type()).localBasis();
100
101 // evaluate the shape functions at the scv center
102
1/2
✓ Branch 1 taken 29200 times.
✗ Branch 2 not taken.
57747412 const auto localPos = geometry.local(globalPos);
103
1/4
✓ Branch 1 taken 30533121 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
115494824 std::vector< Dune::FieldVector<Scalar, 1> > shapeValues;
104
1/2
✓ Branch 1 taken 30533121 times.
✗ Branch 2 not taken.
57747412 localBasis.evaluateFunction(localPos, shapeValues);
105
106 31200208 typename CVFEElemSol::PrimaryVariables result(0.0);
107
4/4
✓ Branch 0 taken 105539458 times.
✓ Branch 1 taken 30533121 times.
✓ Branch 2 taken 105539458 times.
✓ Branch 3 taken 30533121 times.
485609317 for (int i = 0; i < shapeValues.size(); ++i)
108 {
109 200512768 auto value = elemSol[i];
110 601538304 value *= shapeValues[i][0];
111 200512768 result += value;
112 }
113
114 // set an arbitrary state if the model requires a state (models constexpr if)
115 if constexpr (HasState{})
116 if (!ignoreState)
117 result.setState(elemSol[0].state());
118
119
1/2
✓ Branch 0 taken 30533121 times.
✗ Branch 1 not taken.
57747412 return result;
120 }
121 else
122 {
123 static bool warnedAboutUsingMinDist = false;
124 if (!warnedAboutUsingMinDist)
125 {
126 std::cout << "Warning: Using nearest-neighbor interpolation in evalSolution"
127 << "\nbecause not all states are equal and ignoreState is false!"
128 << std::endl;
129 warnedAboutUsingMinDist = true;
130 }
131
132 return Detail::minDistVertexSol(geometry, globalPos, elemSol);
133 }
134 }
135
136 } // end namespace Detail
137
138 /*!
139 * \brief Interpolates a given box element solution at a given global position.
140 * Uses the finite element cache of the grid geometry.
141 * \ingroup Discretization
142 *
143 * \return the interpolated primary variables
144 * \param element The element
145 * \param geometry The element geometry
146 * \param gridGeometry The finite volume grid geometry
147 * \param elemSol The primary variables at the dofs of the element
148 * \param globalPos The global position
149 * \param ignoreState If true, the state of primary variables is ignored
150 */
151 template<class Element, class FVElementGeometry, class PrimaryVariables>
152 PrimaryVariables evalSolution(const Element& element,
153 const typename Element::Geometry& geometry,
154 const typename FVElementGeometry::GridGeometry& gridGeometry,
155 const CVFEElementSolution<FVElementGeometry, PrimaryVariables>& elemSol,
156 const typename Element::Geometry::GlobalCoordinate& globalPos,
157 bool ignoreState = false)
158 {
159
4/5
✓ Branch 1 taken 1604474 times.
✓ Branch 2 taken 12279 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 15000 times.
✗ Branch 5 not taken.
30518121 return Detail::evalCVFESolution(element, geometry, gridGeometry, elemSol, globalPos, ignoreState);
160 }
161
162 /*!
163 * \ingroup Discretization
164 * \brief Interpolates a given box element solution at a given global position.
165 *
166 * Overload of the above evalSolution() function without a given gridGeometry.
167 * The local basis is computed on the fly.
168 *
169 * \return the interpolated primary variables
170 * \param element The element
171 * \param geometry The element geometry
172 * \param elemSol The primary variables at the dofs of the element
173 * \param globalPos The global position
174 * \param ignoreState If true, the state of primary variables is ignored
175 */
176 template<class Element, class FVElementGeometry, class PrimaryVariables>
177 4311148 PrimaryVariables evalSolution(const Element& element,
178 const typename Element::Geometry& geometry,
179 const CVFEElementSolution<FVElementGeometry, PrimaryVariables>& elemSol,
180 const typename Element::Geometry::GlobalCoordinate& globalPos,
181 bool ignoreState = false)
182 {
183 static_assert(FVElementGeometry::GridGeometry::discMethod == DiscretizationMethods::box, "Only implemented for the Box method");
184
185 // determine if all states are the same at all vertices
186 using HasState = decltype(isValid(Detail::hasState())(elemSol[0]));
187
3/4
✓ Branch 0 taken 2595772 times.
✓ Branch 1 taken 1660451 times.
✓ Branch 3 taken 2595772 times.
✗ Branch 4 not taken.
4311148 bool allStatesEqual = ignoreState || Detail::allStatesEqual(elemSol, HasState{});
188
189 if (allStatesEqual)
190 {
191 using Scalar = typename PrimaryVariables::value_type;
192 using CoordScalar = typename Element::Geometry::GlobalCoordinate::value_type;
193 static constexpr int dim = Element::Geometry::mydimension;
194
195 // The box scheme always uses linear Ansatz functions
196 using FEFactory = Dune::PQkLocalFiniteElementFactory<CoordScalar, Scalar, dim, 1>;
197 using FiniteElement = typename FEFactory::FiniteElementType;
198
1/2
✓ Branch 3 taken 4272098 times.
✗ Branch 4 not taken.
12917019 std::unique_ptr<FiniteElement> fe(FEFactory::create(geometry.type()));
199
2/4
✓ Branch 1 taken 4272098 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4272098 times.
✗ Branch 5 not taken.
8622296 const auto& localBasis = fe->localBasis();
200
201 // evaluate the shape functions at the scv center
202
1/2
✓ Branch 1 taken 2611647 times.
✗ Branch 2 not taken.
4311148 const auto localPos = geometry.local(globalPos);
203 using ShapeValue = typename FiniteElement::Traits::LocalBasisType::Traits::RangeType;
204
1/4
✓ Branch 1 taken 4272098 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8622296 std::vector< ShapeValue > shapeValues;
205
1/2
✓ Branch 1 taken 4272098 times.
✗ Branch 2 not taken.
4311148 localBasis.evaluateFunction(localPos, shapeValues);
206
207 4272098 PrimaryVariables result(0.0);
208
4/4
✓ Branch 0 taken 11896848 times.
✓ Branch 1 taken 4272098 times.
✓ Branch 2 taken 11896848 times.
✓ Branch 3 taken 4272098 times.
28469969 for (int i = 0; i < geometry.corners(); ++i)
209 {
210 12051948 auto value = elemSol[i];
211 36155844 value *= shapeValues[i][0];
212 12051948 result += value;
213 }
214
215 // set an arbitrary state if the model requires a state (models constexpr if)
216 if constexpr (HasState{})
217
2/2
✓ Branch 0 taken 2595772 times.
✓ Branch 1 taken 1660451 times.
4256223 if (!ignoreState)
218
2/4
✓ Branch 1 taken 2595772 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2595772 times.
✗ Branch 5 not taken.
5191544 result.setState(elemSol[0].state());
219
220
1/2
✓ Branch 0 taken 4272098 times.
✗ Branch 1 not taken.
4311148 return result;
221 }
222 else
223 {
224 static bool warnedAboutUsingMinDist = false;
225 if (!warnedAboutUsingMinDist)
226 {
227 std::cout << "Warning: Using nearest-neighbor interpolation in evalSolution"
228 << "\nbecause not all states are equal and ignoreState is false!"
229 << std::endl;
230 warnedAboutUsingMinDist = true;
231 }
232
233 return Detail::minDistVertexSol(geometry, globalPos, elemSol);
234 }
235 }
236
237 /*!
238 * \ingroup Discretization
239 * \brief Interpolates a given cell-centered element solution at a given global position.
240 *
241 * \return the primary variables (constant over the element)
242 * \param element The element
243 * \param geometry The element geometry
244 * \param gridGeometry The finite volume grid geometry
245 * \param elemSol The primary variables at the dofs of the element
246 * \param globalPos The global position
247 * \param ignoreState If true, the state of primary variables is ignored
248 */
249 template<class Element, class FVElementGeometry, class PrimaryVariables>
250 PrimaryVariables evalSolution(const Element& element,
251 const typename Element::Geometry& geometry,
252 const typename FVElementGeometry::GridGeometry& gridGeometry,
253 const CCElementSolution<FVElementGeometry, PrimaryVariables>& elemSol,
254 const typename Element::Geometry::GlobalCoordinate& globalPos,
255 bool ignoreState = false)
256 {
257
4/4
✓ Branch 0 taken 31834 times.
✓ Branch 1 taken 21245 times.
✓ Branch 2 taken 21216 times.
✓ Branch 3 taken 84697 times.
3120299 return elemSol[0];
258 }
259
260 /*!
261 * \brief Interpolates a given cell-centered element solution at a given global position.
262 * Overload of the above evalSolution() function without a given gridGeometry.
263 * For compatibility reasons with the box scheme.
264 * \ingroup Discretization
265 *
266 * \return the primary variables (constant over the element)
267 * \param element The element
268 * \param geometry The element geometry
269 * \param elemSol The primary variables at the dofs of the element
270 * \param globalPos The global position
271 * \param ignoreState If true, the state of primary variables is ignored
272 */
273 template< class Element, class FVElementGeometry, class PrimaryVariables>
274 PrimaryVariables evalSolution(const Element& element,
275 const typename Element::Geometry& geometry,
276 const CCElementSolution<FVElementGeometry, PrimaryVariables>& elemSol,
277 const typename Element::Geometry::GlobalCoordinate& globalPos,
278 bool ignoreState = false)
279 {
280
4/4
✓ Branch 0 taken 643586 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 38225 times.
✓ Branch 3 taken 275 times.
684144 return elemSol[0];
281 }
282
283 } // namespace Dumux
284
285 #endif
286