GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/discretization/cellcentered/mpfa/helper.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 93 124 75.0%
Functions: 99 113 87.6%
Branches: 84 240 35.0%

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 CCMpfaDiscretization
10 * \brief Helper class to get data required for mpfa scheme.
11 */
12 #ifndef DUMUX_DISCRETIZATION_CC_MPFA_HELPER_HH
13 #define DUMUX_DISCRETIZATION_CC_MPFA_HELPER_HH
14
15 #include <dune/common/exceptions.hh>
16 #include <dune/common/fvector.hh>
17 #include <dune/common/fmatrix.hh>
18 #include <dune/common/parallel/mpihelper.hh>
19 #include <dune/geometry/type.hh>
20
21 #include <dumux/common/math.hh>
22
23 namespace Dumux {
24
25 /*!
26 * \ingroup CCMpfaDiscretization
27 * \brief Dimension-specific helper class to get data required for mpfa scheme.
28 */
29 template<class GridGeometry, int dim, int dimWorld>
30 class MpfaDimensionHelper;
31
32 /*!
33 * \ingroup CCMpfaDiscretization
34 * \brief Dimension-specific mpfa helper class for dim == 2 & dimWorld == 2
35 */
36 template<class GridGeometry>
37 class MpfaDimensionHelper<GridGeometry, /*dim*/2, /*dimWorld*/2>
38 {
39 using GridView = typename GridGeometry::GridView;
40 using CoordScalar = typename GridView::ctype;
41 using Element = typename GridView::template Codim<0>::Entity;
42
43 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
44
45 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
46 using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage;
47
48 // Container to store the positions of intersections required for scvf
49 // corner computation. In 2d, these are the center plus the two corners
50 using ScvfPositionsOnIntersection = std::array<GlobalPosition, 3>;
51
52 public:
53 /*!
54 * \brief Calculates the inner normal vectors to a given scv basis.
55 * \param scvBasis The basis of an scv
56 */
57 template< class ScvBasis >
58 34663321 static ScvBasis calculateInnerNormals(const ScvBasis& scvBasis)
59 {
60
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 34663283 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 1 times.
34663321 static const Dune::FieldMatrix<CoordScalar, 2, 2> R = {{0.0, 1.0}, {-1.0, 0.0}};
61
62 34663321 ScvBasis innerNormals;
63 103989963 R.mv(scvBasis[1], innerNormals[0]);
64 34663321 R.mv(scvBasis[0], innerNormals[1]);
65
66 // adjust sign depending on basis being a RHS
67 69326642 if (!isRightHandSystem(scvBasis))
68 innerNormals[0] *= -1.0;
69 else
70 innerNormals[1] *= -1.0;
71
72 34663321 return innerNormals;
73 }
74
75 /*!
76 * \brief Calculates the determinant of an scv basis.
77 * This is equal to the cross product for dim = dimWorld = 2
78 * \param scvBasis The basis of an scv
79 */
80 template< class ScvBasis >
81 static CoordScalar calculateDetX(const ScvBasis& scvBasis)
82 {
83 using std::abs;
84 173316605 return abs(crossProduct<CoordScalar>(scvBasis[0], scvBasis[1]));
85 }
86
87 /*!
88 * \brief Returns the global number of scvfs in the grid. Assumes the grid to be made up of only
89 * basic geometry types. Overlad this function if you want to use different geometry types.
90 * \param gridView The grid view to be checked
91 */
92 17 static std::size_t getGlobalNumScvf(const GridView& gridView)
93 {
94
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
17 assert(gridView.size(Dune::GeometryTypes::triangle)
95 + gridView.size(Dune::GeometryTypes::quadrilateral) == gridView.size(0));
96
97 return gridView.size(Dune::GeometryTypes::triangle)
98 17 * getNumLocalScvfs(Dune::GeometryTypes::triangle)
99 + gridView.size(Dune::GeometryTypes::quadrilateral)
100 17 * getNumLocalScvfs(Dune::GeometryTypes::quadrilateral);
101 }
102
103 /*!
104 * \brief Checks whether or not a given scv basis forms a right hand system.
105 * \param scvBasis The basis of an scv
106 */
107 template< class ScvBasis >
108 static bool isRightHandSystem(const ScvBasis& scvBasis)
109
20/20
✓ Branch 0 taken 13628205 times.
✓ Branch 1 taken 21035116 times.
✓ Branch 2 taken 13628205 times.
✓ Branch 3 taken 21035116 times.
✓ Branch 4 taken 13628205 times.
✓ Branch 5 taken 21035116 times.
✓ Branch 6 taken 13628205 times.
✓ Branch 7 taken 21035116 times.
✓ Branch 8 taken 13628205 times.
✓ Branch 9 taken 21035116 times.
✓ Branch 10 taken 200 times.
✓ Branch 11 taken 200 times.
✓ Branch 12 taken 200 times.
✓ Branch 13 taken 200 times.
✓ Branch 14 taken 200 times.
✓ Branch 15 taken 200 times.
✓ Branch 16 taken 200 times.
✓ Branch 17 taken 200 times.
✓ Branch 18 taken 200 times.
✓ Branch 19 taken 200 times.
173318605 { return !std::signbit(crossProduct<CoordScalar>(scvBasis[0], scvBasis[1])); }
110
111 /*!
112 * \brief Returns a vector containing the positions on a given intersection
113 * that are relevant for scvf corner computation.
114 * Ordering -> 1: facet center, 2: the two facet corners
115 *
116 * \param eg Geometry of the element the facet is embedded in
117 * \param refElement Reference element of the element the facet is embedded in
118 * \param indexInElement The local index of the facet in the element
119 * \param numCorners The number of corners on the facet
120 */
121 template<class ElementGeometry, class ReferenceElement>
122 55148863 static ScvfPositionsOnIntersection computeScvfCornersOnIntersection(const ElementGeometry& eg,
123 const ReferenceElement& refElement,
124 unsigned int indexInElement,
125 unsigned int numCorners)
126 {
127 55148863 ScvfPositionsOnIntersection p;
128
129 // compute facet center and corners
130 110297726 p[0] = 0.0;
131
2/2
✓ Branch 0 taken 110297726 times.
✓ Branch 1 taken 55148863 times.
165446589 for (unsigned int c = 0; c < numCorners; ++c)
132 {
133 // codim = 1, dim = 2
134 119089698 p[c+1] = eg.global(refElement.position(refElement.subEntity(indexInElement, 1, c, 2), 2));
135 330893178 p[0] += p[c+1];
136 }
137 110297726 p[0] /= numCorners;
138
139 55148863 return p;
140 }
141
142 /*!
143 * \brief Returns the corners of the sub control volume face constructed
144 * in a corner (vertex) of an intersection.
145 *
146 * \param p Container with all scvf corners of the intersection
147 * \param numIntersectionCorners Number of corners of the intersection (required in 3d)
148 * \param cornerIdx Local vertex index on the intersection
149 */
150 static ScvfCornerVector getScvfCorners(const ScvfPositionsOnIntersection& p,
151 unsigned int numIntersectionCorners,
152 unsigned int cornerIdx)
153 {
154 // make sure the given input is admissible
155 assert(cornerIdx < 2 && "provided index exceeds the number of corners of facets in 2d");
156
157 // create & return the scvf corner vector
158 return cornerIdx == 0 ? ScvfCornerVector({p[0], p[1]})
159 : ScvfCornerVector({p[0], p[2]});
160 }
161
162 /*!
163 * \brief Calculates the area of an scvf.
164 * \param scvfCorners Container with the corners of the scvf
165 */
166 51738064 static CoordScalar computeScvfArea(const ScvfCornerVector& scvfCorners)
167 203923908 { return (scvfCorners[1]-scvfCorners[0]).two_norm(); }
168
169 /*!
170 * \brief Calculates the number of scvfs in a given element geometry type.
171 * \param gt The element geometry type
172 */
173 79782 static std::size_t getNumLocalScvfs(const Dune::GeometryType& gt)
174 {
175
1/2
✓ Branch 0 taken 79782 times.
✗ Branch 1 not taken.
79782 if (gt == Dune::GeometryTypes::triangle)
176 return 6;
177
1/2
✓ Branch 0 taken 69915 times.
✗ Branch 1 not taken.
69915 else if (gt == Dune::GeometryTypes::quadrilateral)
178 return 8;
179 else
180 DUNE_THROW(Dune::NotImplemented, "Mpfa for 2d geometry type " << gt);
181 }
182 };
183
184 /*!
185 * \ingroup CCMpfaDiscretization
186 * \brief Dimension-specific mpfa helper class for dim == 2 & dimWorld == 3.
187 * Reuses some functionality of the specialization for dim = dimWorld = 2
188 */
189 template<class GridGeometry>
190 class MpfaDimensionHelper<GridGeometry, /*dim*/2, /*dimWorld*/3>
191 : public MpfaDimensionHelper<GridGeometry, 2, 2>
192 {
193 using GridView = typename GridGeometry::GridView;
194 using CoordScalar = typename GridView::ctype;
195 public:
196
197 /*!
198 * \brief Calculates the inner normal vectors to a given scv basis.
199 * \param scvBasis The basis of an scv
200 */
201 template< class ScvBasis >
202 2707270 static ScvBasis calculateInnerNormals(const ScvBasis& scvBasis)
203 {
204 // compute vector normal to the basis plane
205 5414540 const auto normal = [&scvBasis] ()
206 {
207 21658160 auto n = crossProduct<CoordScalar>(scvBasis[0], scvBasis[1]);
208 10829080 n /= n.two_norm();
209 5414540 return n;
210 13536350 } ();
211
212 // compute inner normals using the normal vector
213 2707270 ScvBasis innerNormals;
214 5414540 innerNormals[0] = crossProduct<CoordScalar>(scvBasis[1], normal);
215 5414540 innerNormals[1] = crossProduct<CoordScalar>(normal, scvBasis[0]);
216
217 2707270 return innerNormals;
218 }
219
220 /*!
221 * \brief Calculates the determinant of an scv basis.
222 * For dim = 2 < dimWorld = 3 this is actually not the determinant of the
223 * basis but it is simply the area of the parallelofram spanned by the
224 * basis vectors.
225 *
226 * \param scvBasis The basis of an scv
227 */
228 template< class ScvBasis >
229 2707270 static CoordScalar calculateDetX(const ScvBasis& scvBasis)
230 {
231 using std::abs;
232 8121810 return abs(crossProduct<CoordScalar>(scvBasis[0], scvBasis[1]).two_norm());
233 }
234
235 /*!
236 * \brief Checks whether or not a given scv basis forms a right hand system.
237 * Note that for dim = 2 < dimWorld = 3 the bases forming a right hand system
238 * are not unique.
239 *
240 * \param scvBasis The basis of an scv
241 */
242 template< class ScvBasis >
243 static constexpr bool isRightHandSystem(const ScvBasis& scvBasis) { return true; }
244 };
245 /*!
246 * \ingroup CCMpfaDiscretization
247 * \brief Dimension-specific mpfa helper class for dim == 3 & dimWorld == 3.
248 *
249 */
250 template<class GridGeometry>
251 class MpfaDimensionHelper<GridGeometry, /*dim*/3, /*dimWorld*/3>
252 {
253 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
254 using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage;
255
256 // Be picky about the dimensions
257 using GridView = typename GridGeometry::GridView;
258 using Element = typename GridView::template Codim<0>::Entity;
259 using CoordScalar = typename GridView::ctype;
260 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
261
262 // container to store the positions of intersections required for
263 // scvf corner computation. Maximum number of points needed is 9
264 // for the supported geometry types (quadrilateral facet)
265 using ScvfPositionsOnIntersection = std::array<GlobalPosition, 9>;
266
267 public:
268
269 /*!
270 * \brief Calculates the inner normal vectors to a given scv basis.
271 *
272 * \param scvBasis The basis of an scv
273 */
274 template< class ScvBasis >
275 static ScvBasis calculateInnerNormals(const ScvBasis& scvBasis)
276 {
277 ScvBasis innerNormals;
278
279 innerNormals[0] = crossProduct<CoordScalar>(scvBasis[1], scvBasis[2]);
280 innerNormals[1] = crossProduct<CoordScalar>(scvBasis[2], scvBasis[0]);
281 innerNormals[2] = crossProduct<CoordScalar>(scvBasis[0], scvBasis[1]);
282
283 if (!isRightHandSystem(scvBasis))
284 std::for_each(innerNormals.begin(), innerNormals.end(), [] (auto& n) { n *= -1.0; });
285
286 return innerNormals;
287 }
288
289 /*!
290 * \brief Calculates the determinant of an scv basis.
291 * This is equal to the cross product for dim = dimWorld = 2
292 *
293 * \param scvBasis The basis of an scv
294 */
295 template< class ScvBasis >
296 static CoordScalar calculateDetX(const ScvBasis& scvBasis)
297 {
298 using std::abs;
299 return abs(tripleProduct<CoordScalar>(scvBasis[0], scvBasis[1], scvBasis[2]));
300 }
301
302 /*!
303 * \brief Returns the global number of scvfs in the grid. Assumes the grid to be made up of only
304 * basic geometry types. Overload this function if you want to use different geometry types.
305 *
306 * \param gridView The grid view to be checked
307 */
308 2 static std::size_t getGlobalNumScvf(const GridView& gridView)
309 {
310
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
2 assert(gridView.size(Dune::GeometryTypes::tetrahedron)
311 + gridView.size(Dune::GeometryTypes::pyramid)
312 + gridView.size(Dune::GeometryTypes::prism)
313 + gridView.size(Dune::GeometryTypes::hexahedron) == gridView.size(0));
314
315 return gridView.size(Dune::GeometryTypes::tetrahedron)
316 2 * getNumLocalScvfs(Dune::GeometryTypes::tetrahedron)
317 2 + gridView.size(Dune::GeometryTypes::pyramid)
318 2 * getNumLocalScvfs(Dune::GeometryTypes::pyramid)
319 + gridView.size(Dune::GeometryTypes::prism)
320 2 * getNumLocalScvfs(Dune::GeometryTypes::prism)
321 2 + gridView.size(Dune::GeometryTypes::hexahedron)
322 2 * getNumLocalScvfs(Dune::GeometryTypes::hexahedron);
323 }
324
325 /*!
326 * \brief Checks whether or not a given scv basis forms a right hand system.
327 * \param scvBasis The basis of an scv
328 */
329 template< class ScvBasis >
330 static bool isRightHandSystem(const ScvBasis& scvBasis)
331 { return !std::signbit(tripleProduct<CoordScalar>(scvBasis[0], scvBasis[1], scvBasis[2])); }
332
333 /*!
334 * \brief Returns a vector containing the positions on a given intersection
335 * that are relevant for scvf corner computation.
336 * Ordering -> 1: facet center, 2: facet corners, 3: edge centers
337 *
338 * \param eg Geometry of the element the facet is embedded in
339 * \param refElement Reference element of the element the facet is embedded in
340 * \param indexInElement The local index of the facet in the element
341 * \param numCorners The number of corners on the facet
342 */
343 template<class ElementGeometry, class ReferenceElement>
344 3928 static ScvfPositionsOnIntersection computeScvfCornersOnIntersection(const ElementGeometry& eg,
345 const ReferenceElement& refElement,
346 unsigned int indexInElement,
347 unsigned int numCorners)
348 {
349 // The size of ScvfPositionsOnIntersection doesn't allow for faces with more than four corners!
350 3928 ScvfPositionsOnIntersection p;
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3928 times.
3928 if (numCorners > 4)
352 DUNE_THROW(Dune::InvalidStateException, "Mpfa implementation cannot handle faces with more than 4 corners");
353
354 // compute facet center and corners
355 p[0] = 0.0;
356
2/2
✓ Branch 0 taken 11784 times.
✓ Branch 1 taken 3928 times.
15712 for (unsigned int c = 0; c < numCorners; ++c)
357 {
358 // codim = 1, dim = 3
359 11784 p[c+1] = eg.global(refElement.position(refElement.subEntity(indexInElement, 1, c, 3), 3));
360 35352 p[0] += p[c+1];
361 }
362 7856 p[0] /= numCorners;
363
364 // proceed according to number of corners
365
1/3
✓ Branch 0 taken 3928 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
3928 switch (numCorners)
366 {
367 3928 case 3: // triangle
368 {
369 // add edge midpoints, there are 3 for triangles
370 15712 p[numCorners+1] = p[2] + p[1];
371 7856 p[numCorners+1] /= 2;
372 15712 p[numCorners+2] = p[3] + p[1];
373 7856 p[numCorners+2] /= 2;
374 15712 p[numCorners+3] = p[3] + p[2];
375 7856 p[numCorners+3] /= 2;
376 return p;
377 }
378 case 4: // quadrilateral
379 {
380 // add edge midpoints, there are 4 for quadrilaterals
381 p[numCorners+1] = p[3] + p[1];
382 p[numCorners+1] /= 2;
383 p[numCorners+2] = p[4] + p[2];
384 p[numCorners+2] /= 2;
385 p[numCorners+3] = p[2] + p[1];
386 p[numCorners+3] /= 2;
387 p[numCorners+4] = p[4] + p[3];
388 p[numCorners+4] /= 2;
389 return p;
390 }
391 default:
392 DUNE_THROW(Dune::NotImplemented,
393 "Mpfa scvf corners for dim = 3, dimWorld = 3, corners = " << numCorners);
394 }
395 }
396
397 /*!
398 * \brief Returns the corners of the sub control volume face constructed
399 * in a corner (vertex) of an intersection.
400 *
401 * \param p Container with all scvf corners of the intersection
402 * \param numIntersectionCorners Number of corners of the intersection
403 * \param cornerIdx Local vertex index on the intersection
404 */
405 11784 static ScvfCornerVector getScvfCorners(const ScvfPositionsOnIntersection& p,
406 unsigned int numIntersectionCorners,
407 unsigned int cornerIdx)
408 {
409 // proceed according to number of corners
410 // we assume the ordering according to the above method computeScvfCornersOnIntersection()
411
1/3
✓ Branch 0 taken 11784 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
11784 switch (numIntersectionCorners)
412 {
413 11784 case 3: // triangle
414 {
415 // Only build the maps the first time we encounter a triangle
416 static const std::uint8_t vo = 1; // vertex offset in point vector p
417 static const std::uint8_t eo = 4; // edge offset in point vector p
418 static const std::uint8_t map[3][4] =
419 {
420 {0, eo+1, eo+0, vo+0},
421 {0, eo+0, eo+2, vo+1},
422 {0, eo+2, eo+1, vo+2}
423 };
424
425 11784 return ScvfCornerVector( {p[map[cornerIdx][0]],
426 23568 p[map[cornerIdx][1]],
427 23568 p[map[cornerIdx][2]],
428 47136 p[map[cornerIdx][3]]} );
429 }
430 case 4: // quadrilateral
431 {
432 // Only build the maps the first time we encounter a quadrilateral
433 static const std::uint8_t vo = 1; // vertex offset in point vector p
434 static const std::uint8_t eo = 5; // face offset in point vector p
435 static const std::uint8_t map[4][4] =
436 {
437 {0, eo+0, eo+2, vo+0},
438 {0, eo+2, eo+1, vo+1},
439 {0, eo+3, eo+0, vo+2},
440 {0, eo+1, eo+3, vo+3}
441 };
442
443 return ScvfCornerVector( {p[map[cornerIdx][0]],
444 p[map[cornerIdx][1]],
445 p[map[cornerIdx][2]],
446 p[map[cornerIdx][3]]} );
447 }
448 default:
449 DUNE_THROW(Dune::NotImplemented,
450 "Mpfa scvf corners for dim = 3, dimWorld = 3, corners = " << numIntersectionCorners);
451 }
452 }
453
454 /*!
455 * \brief Calculates the area of an scvf.
456 * \param scvfCorners Container with the corners of the scvf
457 */
458 11784 static CoordScalar computeScvfArea(const ScvfCornerVector& scvfCorners)
459 {
460 // after Wolfram alpha quadrilateral area
461 82488 return 0.5*Dumux::crossProduct(scvfCorners[3]-scvfCorners[0], scvfCorners[2]-scvfCorners[1]).two_norm();
462 }
463
464 /*!
465 * \brief Calculates the number of scvfs in a given element geometry type.
466 *
467 * \param gt The element geometry type
468 */
469 990 static std::size_t getNumLocalScvfs(const Dune::GeometryType& gt)
470 {
471
1/2
✓ Branch 0 taken 990 times.
✗ Branch 1 not taken.
990 if (gt == Dune::GeometryTypes::tetrahedron)
472 return 12;
473
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if (gt == Dune::GeometryTypes::pyramid)
474 return 16;
475
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (gt == Dune::GeometryTypes::prism)
476 return 18;
477
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (gt == Dune::GeometryTypes::hexahedron)
478 return 24;
479 else
480 DUNE_THROW(Dune::NotImplemented, "Mpfa for 3d geometry type " << gt);
481 }
482 };
483
484 /*!
485 * \ingroup CCMpfaDiscretization
486 * \brief Helper class to get the required information on an interaction volume.
487 *
488 * \tparam GridGeometry The finite volume grid geometry
489 */
490 template<class GridGeometry>
491 class CCMpfaHelper : public MpfaDimensionHelper<GridGeometry,
492 GridGeometry::GridView::dimension,
493 GridGeometry::GridView::dimensionworld>
494 {
495 using PrimaryInteractionVolume = typename GridGeometry::GridIVIndexSets::PrimaryInteractionVolume;
496 using SecondaryInteractionVolume = typename GridGeometry::GridIVIndexSets::SecondaryInteractionVolume;
497
498 using VertexMapper = typename GridGeometry::VertexMapper;
499 using FVElementGeometry = typename GridGeometry::LocalView;
500 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
501 using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage;
502
503 using GridView = typename GridGeometry::GridView;
504 static constexpr int dim = GridView::dimension;
505
506 using Element = typename GridView::template Codim<0>::Entity;
507 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
508 using CoordScalar = typename GridView::ctype;
509
510 public:
511 /*!
512 * \brief Calculates the integration point on an scvf.
513 *
514 * \param scvfCorners Container with the corners of the scvf
515 * \param q Parameterization of the integration point on the scvf
516 */
517 template< class Scalar >
518 51749848 static GlobalPosition getScvfIntegrationPoint(const ScvfCornerVector& scvfCorners, Scalar q)
519 {
520 // ordering -> first corner: facet center, last corner: vertex
521
1/2
✓ Branch 0 taken 51749848 times.
✗ Branch 1 not taken.
51749848 if (q == 0.0)
522 103499696 return scvfCorners[0];
523
524 auto ip = scvfCorners.back() - scvfCorners.front();
525 ip *= q;
526 ip += scvfCorners[0];
527 return ip;
528 }
529
530 /*!
531 * \brief Returns a vector which maps true to each vertex on processor boundaries and false otherwise
532 * \todo TODO: The name of this function is not so good, as these are not ghost vertices according
533 * to the Dune definition of ghost entities. Moreover, it should be tried to make MPFA work
534 * also with ghost entities.
535 */
536 50 static std::vector<bool> findGhostVertices(const GridView& gridView, const VertexMapper& vertexMapper)
537 {
538
4/8
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
100 std::vector<bool> ghostVertices(gridView.size(dim), false);
539
540 // if not run in parallel, skip the rest
541
5/6
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 48 times.
50 if (Dune::MPIHelper::getCommunication().size() == 1)
542 return ghostVertices;
543
544 // mpfa methods cannot yet handle ghost cells
545
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 if (gridView.ghostSize(0) > 0)
546 DUNE_THROW(Dune::InvalidStateException, "Mpfa methods in parallel do not work with ghost cells. Use overlap cells instead.");
547
548 // mpfa methods have to have overlapping cells
549
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (gridView.overlapSize(0) == 0)
550 DUNE_THROW(Dune::InvalidStateException, "Grid no overlapping cells. This is required by mpfa methods in parallel.");
551
552
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 418 times.
✗ Branch 4 not taken.
834 for (const auto& element : elements(gridView))
553 {
554
2/2
✓ Branch 1 taken 416 times.
✓ Branch 2 taken 1664 times.
2496 for (const auto& is : intersections(gridView, element))
555 {
556
3/4
✓ Branch 0 taken 1606 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 116 times.
✗ Branch 3 not taken.
1722 if (!is.neighbor() && !is.boundary())
557 {
558
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 const auto refElement = referenceElement(element);
559
560
4/4
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 32 times.
96 for (int isVertex = 0; isVertex < is.geometry().corners(); ++isVertex)
561 {
562 128 const auto vIdxLocal = refElement.subEntity(is.indexInInside(), 1, isVertex, dim);
563
1/2
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
64 const auto vIdxGlobal = vertexMapper.subIndex(element, vIdxLocal, dim);
564 192 ghostVertices[vIdxGlobal] = true;
565 }
566 }
567 }
568 }
569
570 2 return ghostVertices;
571 }
572
573 //! Returns whether or not secondary interaction volumes have to be considered in the model.
574 //! This is always the case when the specified types for the interaction volumes differ.
575 static constexpr bool considerSecondaryIVs()
576 { return !std::is_same<PrimaryInteractionVolume, SecondaryInteractionVolume>::value; }
577
578 //! returns whether or not a value exists in a vector
579 template<typename V, typename T>
580 static bool vectorContainsValue(const V& vector, const T value)
581
19/24
✓ Branch 0 taken 257944 times.
✓ Branch 1 taken 506292 times.
✓ Branch 2 taken 257944 times.
✓ Branch 3 taken 506292 times.
✓ Branch 4 taken 312520 times.
✓ Branch 5 taken 615376 times.
✓ Branch 6 taken 312520 times.
✓ Branch 7 taken 615376 times.
✓ Branch 8 taken 257944 times.
✓ Branch 9 taken 506292 times.
✓ Branch 12 taken 3406072 times.
✓ Branch 13 taken 2061704 times.
✓ Branch 14 taken 58528302 times.
✓ Branch 15 taken 40137020 times.
✓ Branch 16 taken 55122230 times.
✓ Branch 17 taken 38075316 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 3406072 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 58528302 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 55122230 times.
399137108 { return std::find(vector.begin(), vector.end(), value) != vector.end(); }
582 };
583
584 } // end namespace Dumux
585
586 #endif
587