GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/discretization/facecentered/diamond/geometryhelper.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 69 77 89.6%
Functions: 41 95 43.2%
Branches: 87 196 44.4%

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 DiamondDiscretization
10 * \copydoc Dumux::DiamondGeometryHelper
11 */
12 #ifndef DUMUX_DISCRETIZATION_FACECENTERED_DIAMOND_GEOMETRY_HELPER_HH
13 #define DUMUX_DISCRETIZATION_FACECENTERED_DIAMOND_GEOMETRY_HELPER_HH
14
15 #include <array>
16
17 #include <dune/common/reservedvector.hh>
18 #include <dune/common/fvector.hh>
19 #include <dune/geometry/multilineargeometry.hh>
20 #include <dune/geometry/type.hh>
21
22 #include <dumux/common/math.hh>
23
24 namespace Dumux {
25
26 //! Traits for an efficient corner storage for fc diamond method
27 template <class ct>
28 struct FCDiamondMLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
29 {
30 // we use static vectors to store the corners as we know
31 // the maximum number of corners in advance (2^dim)
32 template< int mydim, int cdim >
33 struct CornerStorage
34 {
35 using Type = Dune::ReservedVector< Dune::FieldVector< ct, cdim >, (1<<mydim)>;
36 };
37 };
38
39 namespace Detail::FCDiamond {
40
41 template<Dune::GeometryType::Id gt>
42 struct ScvCorners;
43
44 template<>
45 struct ScvCorners<Dune::GeometryTypes::triangle>
46 {
47 static constexpr Dune::GeometryType type()
48 { return Dune::GeometryTypes::triangle; }
49
50 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
51 static constexpr std::array<std::array<Key, 3>, 3> keys = {{
52 { Key{0, 2}, Key{1, 2}, Key{0, 0} },
53 { Key{2, 2}, Key{0, 2}, Key{0, 0} },
54 { Key{1, 2}, Key{2, 2}, Key{0, 0} }
55 }};
56 };
57
58 template<>
59 struct ScvCorners<Dune::GeometryTypes::quadrilateral>
60 {
61 static constexpr Dune::GeometryType type()
62 { return Dune::GeometryTypes::triangle; }
63
64 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
65 static constexpr std::array<std::array<Key, 3>, 4> keys = {{
66 { Key{2, 2}, Key{0, 2}, Key{0, 0} },
67 { Key{1, 2}, Key{3, 2}, Key{0, 0} },
68 { Key{0, 2}, Key{1, 2}, Key{0, 0} },
69 { Key{3, 2}, Key{2, 2}, Key{0, 0} }
70 }};
71 };
72
73 template<>
74 struct ScvCorners<Dune::GeometryTypes::tetrahedron>
75 {
76 static constexpr Dune::GeometryType type()
77 { return Dune::GeometryTypes::tetrahedron; }
78
79 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
80 static constexpr std::array<std::array<Key, 4>, 4> keys = {{
81 { Key{0, 3}, Key{1, 3}, Key{2, 3}, Key{0, 0} },
82 { Key{1, 3}, Key{0, 3}, Key{3, 3}, Key{0, 0} },
83 { Key{0, 3}, Key{2, 3}, Key{3, 3}, Key{0, 0} },
84 { Key{2, 3}, Key{1, 3}, Key{3, 3}, Key{0, 0} }
85 }};
86 };
87
88 template<>
89 struct ScvCorners<Dune::GeometryTypes::hexahedron>
90 {
91 static constexpr Dune::GeometryType type()
92 { return Dune::GeometryTypes::pyramid; }
93
94 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
95 static constexpr std::array<std::array<Key, 5>, 6> keys = {{
96 { Key{4, 3}, Key{0, 3}, Key{6, 3}, Key{2, 3}, Key{0, 0} },
97 { Key{1, 3}, Key{5, 3}, Key{3, 3}, Key{7, 3}, Key{0, 0} },
98 { Key{4, 3}, Key{5, 3}, Key{0, 3}, Key{1, 3}, Key{0, 0} },
99 { Key{2, 3}, Key{3, 3}, Key{6, 3}, Key{7, 3}, Key{0, 0} },
100 { Key{0, 3}, Key{1, 3}, Key{2, 3}, Key{3, 3}, Key{0, 0} },
101 { Key{6, 3}, Key{7, 3}, Key{4, 3}, Key{5, 3}, Key{0, 0} }
102 }};
103 };
104
105 template<Dune::GeometryType::Id gt>
106 struct ScvfCorners;
107
108 template<>
109 struct ScvfCorners<Dune::GeometryTypes::triangle>
110 {
111 static constexpr Dune::GeometryType type()
112 { return Dune::GeometryTypes::line; }
113
114 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
115 static constexpr std::array<std::array<Key, 2>, 3> keys = {{
116 { Key{0, 2}, Key{0, 0} },
117 { Key{1, 2}, Key{0, 0} },
118 { Key{2, 2}, Key{0, 0} }
119 }};
120 };
121
122 template<>
123 struct ScvfCorners<Dune::GeometryTypes::quadrilateral>
124 {
125 static constexpr Dune::GeometryType type()
126 { return Dune::GeometryTypes::line; }
127
128 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
129 static constexpr std::array<std::array<Key, 2>, 4> keys = {{
130 { Key{0, 2}, Key{0, 0} },
131 { Key{1, 2}, Key{0, 0} },
132 { Key{2, 2}, Key{0, 0} },
133 { Key{3, 2}, Key{0, 0} }
134 }};
135 };
136
137 template<>
138 struct ScvfCorners<Dune::GeometryTypes::tetrahedron>
139 {
140 static constexpr Dune::GeometryType type()
141 { return Dune::GeometryTypes::triangle; }
142
143 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
144 static constexpr std::array<std::array<Key, 3>, 6> keys = {{
145 { Key{0, 3}, Key{1, 3}, Key{0, 0} },
146 { Key{2, 3}, Key{0, 3}, Key{0, 0} },
147 { Key{1, 3}, Key{2, 3}, Key{0, 0} },
148 { Key{0, 3}, Key{3, 3}, Key{0, 0} },
149 { Key{1, 3}, Key{3, 3}, Key{0, 0} },
150 { Key{2, 3}, Key{3, 3}, Key{0, 0} }
151 }};
152 };
153
154 template<>
155 struct ScvfCorners<Dune::GeometryTypes::hexahedron>
156 {
157 static constexpr Dune::GeometryType type()
158 { return Dune::GeometryTypes::triangle; }
159
160 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
161 static constexpr std::array<std::array<Key, 3>, 12> keys = {{
162 { Key{0, 3}, Key{4, 3}, Key{0, 0} },
163 { Key{1, 3}, Key{5, 3}, Key{0, 0} },
164 { Key{2, 3}, Key{6, 3}, Key{0, 0} },
165 { Key{3, 3}, Key{7, 3}, Key{0, 0} },
166 { Key{0, 3}, Key{2, 3}, Key{0, 0} },
167 { Key{1, 3}, Key{3, 3}, Key{0, 0} },
168 { Key{0, 3}, Key{1, 3}, Key{0, 0} },
169 { Key{2, 3}, Key{3, 3}, Key{0, 0} },
170 { Key{4, 3}, Key{6, 3}, Key{0, 0} },
171 { Key{5, 3}, Key{7, 3}, Key{0, 0} },
172 { Key{4, 3}, Key{5, 3}, Key{0, 0} },
173 { Key{6, 3}, Key{7, 3}, Key{0, 0} }
174 }};
175 };
176
177 // convert key array to global corner storage
178 template<class S, class Geo, class KeyArray, std::size_t... I>
179 1920588 S keyToCornerStorageImpl(const Geo& geo, const KeyArray& key, std::index_sequence<I...>)
180 {
181 using Dune::referenceElement;
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
1920588 const auto ref = referenceElement(geo);
183 // key is a pair of a local sub-entity index (first) and the sub-entity's codim (second)
184
23/34
✗ Branch 0 not taken.
✓ Branch 1 taken 960294 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 960294 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 960294 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 168836 times.
✓ Branch 8 taken 791458 times.
✓ Branch 9 taken 168836 times.
✓ Branch 10 taken 791458 times.
✓ Branch 11 taken 168836 times.
✓ Branch 12 taken 791458 times.
✓ Branch 13 taken 84436 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 556924 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 556924 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 472500 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 12 times.
✓ Branch 22 taken 54118 times.
✓ Branch 23 taken 12 times.
✓ Branch 24 taken 54118 times.
✓ Branch 25 taken 12 times.
✓ Branch 26 taken 54118 times.
✓ Branch 27 taken 12 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 36474 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 36462 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 36462 times.
7619212 return { geo.global(ref.position(key[I].first, key[I].second))... };
185 }
186
187 // convert key array to global corner storage
188 template<class S, class Geo, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
189 S keyToCornerStorage(const Geo& geo, const std::array<T, N>& key)
190 {
191 960294 return keyToCornerStorageImpl<S>(geo, key, Indices{});
192 }
193
194 // boundary corners for the i-th facet
195 template<class S, class Geo, std::size_t... ii>
196 332 S boundaryCornerStorageImpl(const Geo& geo, unsigned int i, std::index_sequence<ii...>)
197 {
198 using Dune::referenceElement;
199 332 const auto ref = referenceElement(geo);
200 // simply the vertices of the facet i
201 380 return { geo.global(ref.position(ref.subEntity(i, 1, ii, Geo::mydimension), Geo::mydimension))... };
202 }
203
204 // boundary corners for the i-th facet
205 template<class S, std::size_t numCorners, class Geo>
206 S boundaryCornerStorage(const Geo& geo, unsigned int i)
207 {
208 166 return boundaryCornerStorageImpl<S>(geo, i, std::make_index_sequence<numCorners>{});
209 }
210
211 template<class IndexType, Dune::GeometryType::Id gt>
212 struct InsideOutsideScv;
213
214 template<class IndexType>
215 struct InsideOutsideScv<IndexType, Dune::GeometryTypes::triangle>
216 {
217 static constexpr std::array<std::array<IndexType, 2>, 3> pairs = {{
218 {0, 1}, {0, 2}, {1, 2}
219 }};
220 };
221
222 template<class IndexType>
223 struct InsideOutsideScv<IndexType, Dune::GeometryTypes::quadrilateral>
224 {
225 static constexpr std::array<std::array<IndexType, 2>, 4> pairs = {{
226 {0, 2}, {1, 2}, {0, 3}, {1, 3}
227 }};
228 };
229
230 template<class IndexType>
231 struct InsideOutsideScv<IndexType, Dune::GeometryTypes::tetrahedron>
232 {
233 static constexpr std::array<std::array<IndexType, 2>, 6> pairs = {{
234 {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
235 }};
236 };
237
238 template<class IndexType>
239 struct InsideOutsideScv<IndexType, Dune::GeometryTypes::hexahedron>
240 {
241 static constexpr std::array<std::array<IndexType, 2>, 12> pairs = {{
242 {0, 2}, {1, 2}, {0, 3}, {1, 3}, {0, 4}, {1, 4},
243 {2, 4}, {3, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}
244 }};
245 };
246
247 } // end namespace Detail::FCDiamond
248
249 /*!
250 * \ingroup DiamondDiscretization
251 * \brief Helper class to construct SCVs and SCVFs for the diamond scheme
252 */
253 template <class GridView, class ScvType, class ScvfType>
254 class DiamondGeometryHelper
255 {
256 using Element = typename GridView::template Codim<0>::Entity;
257
258 static constexpr auto dim = GridView::dimension;
259 static constexpr auto dimWorld = GridView::dimensionworld;
260
261 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
262 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
263 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
264
265 // for the normal
266 using ctype = typename GridView::ctype;
267 using GlobalPosition = typename Dune::FieldVector<ctype, GridView::dimensionworld>;
268
269 public:
270 127686 DiamondGeometryHelper(const typename Element::Geometry& geo)
271
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10278 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
127686 : geo_(geo)
272 {}
273
274 //! Create a corner storage with the scv corners for a given face (codim-1) index
275 338890 ScvCornerStorage getScvCorners(unsigned int localFacetIndex) const
276 {
277
1/2
✓ Branch 1 taken 34274 times.
✗ Branch 2 not taken.
457576 const auto type = geo_.type();
278
2/3
✓ Branch 0 taken 338814 times.
✓ Branch 1 taken 34302 times.
✗ Branch 2 not taken.
457576 if (type == Dune::GeometryTypes::triangle)
279 {
280 using Corners = Detail::FCDiamond::ScvCorners<Dune::GeometryTypes::triangle>;
281
2/4
✓ Branch 1 taken 20514 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20514 times.
✗ Branch 5 not taken.
388452 return Detail::FCDiamond::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localFacetIndex]);
282 }
283
2/3
✓ Branch 0 taken 165130 times.
✓ Branch 1 taken 13772 times.
✗ Branch 2 not taken.
263350 else if (type == Dune::GeometryTypes::quadrilateral)
284 {
285 using Corners = Detail::FCDiamond::ScvCorners<Dune::GeometryTypes::quadrilateral>;
286
2/4
✓ Branch 1 taken 13760 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13760 times.
✗ Branch 5 not taken.
418400 return Detail::FCDiamond::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localFacetIndex]);
287 }
288
2/2
✓ Branch 0 taken 54106 times.
✓ Branch 1 taken 12 times.
54150 else if (type == Dune::GeometryTypes::tetrahedron)
289 {
290 using Corners = Detail::FCDiamond::ScvCorners<Dune::GeometryTypes::tetrahedron>;
291 35328 return Detail::FCDiamond::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localFacetIndex]);
292 }
293
2/2
✓ Branch 0 taken 36450 times.
✓ Branch 1 taken 12 times.
36486 else if (type == Dune::GeometryTypes::hexahedron)
294 {
295 using Corners = Detail::FCDiamond::ScvCorners<Dune::GeometryTypes::hexahedron>;
296 72972 return Detail::FCDiamond::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localFacetIndex]);
297 }
298 else
299 DUNE_THROW(Dune::NotImplemented, "Scv geometries for type " << type);
300 }
301
302 //! Create a corner storage with the scvf corners for a given edge (codim-2) index
303 384068 ScvfCornerStorage getScvfCorners(unsigned int localEdgeIndex) const
304 {
305
1/2
✓ Branch 1 taken 34274 times.
✗ Branch 2 not taken.
502766 const auto type = geo_.type();
306
2/3
✓ Branch 0 taken 384068 times.
✓ Branch 1 taken 34274 times.
✗ Branch 2 not taken.
502766 if (type == Dune::GeometryTypes::triangle)
307 {
308 using Corners = Detail::FCDiamond::ScvfCorners<Dune::GeometryTypes::triangle>;
309
2/4
✓ Branch 1 taken 20514 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20514 times.
✗ Branch 5 not taken.
388404 return Detail::FCDiamond::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localEdgeIndex]);
310 }
311
2/3
✓ Branch 0 taken 210380 times.
✓ Branch 1 taken 13760 times.
✗ Branch 2 not taken.
308564 else if (type == Dune::GeometryTypes::quadrilateral)
312 {
313 using Corners = Detail::FCDiamond::ScvfCorners<Dune::GeometryTypes::quadrilateral>;
314
2/4
✓ Branch 1 taken 13760 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13760 times.
✗ Branch 5 not taken.
418336 return Detail::FCDiamond::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localEdgeIndex]);
315 }
316
1/2
✓ Branch 0 taken 99372 times.
✗ Branch 1 not taken.
99396 else if (type == Dune::GeometryTypes::tetrahedron)
317 {
318 using Corners = Detail::FCDiamond::ScvfCorners<Dune::GeometryTypes::tetrahedron>;
319 52944 return Detail::FCDiamond::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localEdgeIndex]);
320 }
321
1/2
✓ Branch 0 taken 72900 times.
✗ Branch 1 not taken.
72924 else if (type == Dune::GeometryTypes::hexahedron)
322 {
323 using Corners = Detail::FCDiamond::ScvfCorners<Dune::GeometryTypes::hexahedron>;
324 145848 return Detail::FCDiamond::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localEdgeIndex]);
325 }
326 else
327 DUNE_THROW(Dune::NotImplemented, "Scvf geometries for type " << type);
328 }
329
330 //! Create the sub control volume face geometries on the boundary for a given face index
331 160 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex) const
332 {
333 166 const auto type = geo_.type();
334
1/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
172 if (type == Dune::GeometryTypes::triangle || type == Dune::GeometryTypes::quadrilateral)
335 160 return Detail::FCDiamond::boundaryCornerStorage<ScvfCornerStorage, 2>(geo_, localFacetIndex);
336
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
6 else if (type == Dune::GeometryTypes::tetrahedron)
337 return Detail::FCDiamond::boundaryCornerStorage<ScvfCornerStorage, 3>(geo_, localFacetIndex);
338
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
6 else if (type == Dune::GeometryTypes::hexahedron)
339 6 return Detail::FCDiamond::boundaryCornerStorage<ScvfCornerStorage, 4>(geo_, localFacetIndex);
340 else
341 DUNE_THROW(Dune::NotImplemented, "Boundary scvf geometries for type " << type);
342 }
343
344 84406 GlobalPosition facetCenter(unsigned int localFacetIndex) const
345 {
346
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
84406 return geo_.global(referenceElement(geo_).position(localFacetIndex, 1));
347 }
348
349 384068 std::array<LocalIndexType, 2> getInsideOutsideScvForScvf(unsigned int localEdgeIndex)
350 {
351 502754 const auto type = geo_.type();
352
1/2
✓ Branch 0 taken 384068 times.
✗ Branch 1 not taken.
502754 if (type == Dune::GeometryTypes::triangle)
353 388404 return Detail::FCDiamond::InsideOutsideScv<LocalIndexType, Dune::GeometryTypes::triangle>::pairs[localEdgeIndex];
354
1/2
✓ Branch 0 taken 210380 times.
✗ Branch 1 not taken.
308552 else if (type == Dune::GeometryTypes::quadrilateral)
355 418336 return Detail::FCDiamond::InsideOutsideScv<LocalIndexType, Dune::GeometryTypes::quadrilateral>::pairs[localEdgeIndex];
356
1/2
✓ Branch 0 taken 99372 times.
✗ Branch 1 not taken.
99384 else if (type == Dune::GeometryTypes::tetrahedron)
357 52944 return Detail::FCDiamond::InsideOutsideScv<LocalIndexType, Dune::GeometryTypes::tetrahedron>::pairs[localEdgeIndex];
358
1/2
✓ Branch 0 taken 72900 times.
✗ Branch 1 not taken.
72912 else if (type == Dune::GeometryTypes::hexahedron)
359 145824 return Detail::FCDiamond::InsideOutsideScv<LocalIndexType, Dune::GeometryTypes::hexahedron>::pairs[localEdgeIndex];
360 else
361 DUNE_THROW(Dune::NotImplemented, "Inside outside scv pairs for type " << type);
362 }
363
364 //! number of interior sub control volume faces (number of codim-2 entities)
365 std::size_t numInteriorScvf()
366 {
367
4/4
✓ Branch 6 taken 384068 times.
✓ Branch 7 taken 96135 times.
✓ Branch 8 taken 384068 times.
✓ Branch 9 taken 96135 times.
480203 return referenceElement(geo_).size(2);
368 }
369
370 //! number of sub control volumes (number of codim-1 entities)
371 std::size_t numScv()
372 {
373
18/18
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 338808 times.
✓ Branch 7 taken 96139 times.
✓ Branch 8 taken 338808 times.
✓ Branch 9 taken 96139 times.
✓ Branch 10 taken 14 times.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 14 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 14 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 14 times.
✓ Branch 17 taken 4 times.
435109 return referenceElement(geo_).size(1);
374 }
375
376 template<int d = dimWorld, std::enable_if_t<(d==3), int> = 0>
377 99384 GlobalPosition normal(const ScvfCornerStorage& p, const std::array<LocalIndexType, 2>& scvPair)
378 {
379 695688 auto normal = Dumux::crossProduct(p[1]-p[0], p[2]-p[0]);
380 198768 normal /= normal.two_norm();
381
382 99384 const auto ref = referenceElement(geo_);
383 99384 const auto v = facetCenter_(scvPair[1], ref) - facetCenter_(scvPair[0], ref);
384
385 99384 const auto s = v*normal;
386
4/4
✓ Branch 0 taken 40868 times.
✓ Branch 1 taken 58516 times.
✓ Branch 2 taken 40868 times.
✓ Branch 3 taken 58516 times.
198768 if (std::signbit(s))
387 normal *= -1;
388
389 99384 return normal;
390 }
391
392 template<int d = dimWorld, std::enable_if_t<(d==2), int> = 0>
393 403370 GlobalPosition normal(const ScvfCornerStorage& p, const std::array<LocalIndexType, 2>& scvPair)
394 {
395 //! obtain normal vector by 90° counter-clockwise rotation of t
396 1210110 const auto t = p[1] - p[0];
397 1210110 GlobalPosition normal({-t[1], t[0]});
398 806740 normal /= normal.two_norm();
399
400 403370 const auto ref = referenceElement(geo_);
401 403370 const auto v = facetCenter_(scvPair[1], ref) - facetCenter_(scvPair[0], ref);
402
403 403370 const auto s = v*normal;
404
4/4
✓ Branch 0 taken 176156 times.
✓ Branch 1 taken 227214 times.
✓ Branch 2 taken 176156 times.
✓ Branch 3 taken 227214 times.
806740 if (std::signbit(s))
405 normal *= -1;
406
407 403370 return normal;
408 }
409
410 const typename Element::Geometry& elementGeometry() const
411 { return geo_; }
412
413 private:
414 template<class RefElement>
415 GlobalPosition facetCenter_(unsigned int localFacetIndex, const RefElement& ref) const
416 {
417 1343156 return geo_.global(ref.position(localFacetIndex, 1));
418 }
419
420 const typename Element::Geometry& geo_; //!< Reference to the element geometry
421 };
422
423 } // end namespace Dumux
424
425 #endif
426