GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/geometry/volume.hh
Date: 2024-05-04 19:09:25
Exec Total Coverage
Lines: 42 43 97.7%
Functions: 14 17 82.4%
Branches: 15 28 53.6%

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 Geometry
10 * \brief Compute the volume of several common geometry types
11 */
12 #ifndef DUMUX_GEOMETRY_VOLUME_HH
13 #define DUMUX_GEOMETRY_VOLUME_HH
14
15 #include <cmath>
16 #include <limits>
17 #include <type_traits>
18
19 #include <dune/common/exceptions.hh>
20 #include <dune/geometry/type.hh>
21 #include <dune/geometry/quadraturerules.hh>
22
23 #include <dumux/common/math.hh>
24
25 namespace Dumux {
26
27 /*!
28 * \ingroup Geometry
29 * \brief Compute the volume of several common geometry types
30 * \param type the geometry type
31 * \param c a function returning the ith corner (in Dune reference element order)
32 * e.g. `[&](unsigned int i){ return corners[i]; }`, where `corners` is a
33 * random access container storing the corners, and the returned corner is stored
34 * in a container (e.g. Dune::FieldVector) that exports `value_type` and `dimension`.
35 * \tparam dim the dimension of the geometry
36 * \tparam CornerF the function type (is deduced)
37 * \return volume of the geometry or NaN signalling not implemented
38 * \note This is only correct for convex polytopes (flat sides)
39 */
40 template<int dim, class CornerF>
41 43987463 auto convexPolytopeVolume(Dune::GeometryType type, const CornerF& c)
42 {
43 using ctype = typename std::decay_t<decltype(c(0))>::value_type;
44 static constexpr int coordDim = std::decay_t<decltype(c(0))>::dimension;
45 static_assert(coordDim >= dim, "Coordinate dimension has to be larger than geometry dimension");
46
47 // not implemented for coordinate dimension larger than 3
48 if constexpr (coordDim > 3)
49 return std::numeric_limits<ctype>::quiet_NaN();
50
51 if constexpr (dim == 0)
52 return 1.0;
53
54 else if constexpr (dim == 1)
55 25530022 return (c(1)-c(0)).two_norm();
56
57 else if constexpr (dim == 2)
58 {
59
1/2
✓ Branch 0 taken 323786 times.
✗ Branch 1 not taken.
41828845 if (type == Dune::GeometryTypes::triangle)
60 {
61 if constexpr (coordDim == 2)
62 {
63 // make sure we are using positive volumes
64 // the cross product of edge vectors might be negative,
65 // depending on the element orientation
66 using std::abs;
67 4246954 return 0.5*abs(Dumux::crossProduct(c(1)-c(0), c(2)-c(0)));
68 }
69 else // coordDim == 3
70 936448 return 0.5*Dumux::crossProduct(c(1)-c(0), c(2)-c(0)).two_norm();
71
72 }
73
1/2
✓ Branch 0 taken 323754 times.
✗ Branch 1 not taken.
41239875 else if (type == Dune::GeometryTypes::quadrilateral)
74 {
75 if constexpr (coordDim == 2)
76 {
77 // make sure we are using positive volumes
78 // the cross product of diagonals might be negative,
79 // depending on the element orientation
80 using std::abs;
81 340374193 return 0.5*abs(Dumux::crossProduct(c(3)-c(0), c(2)-c(1)));
82 }
83 else // coordDim == 3
84 27363920 return 0.5*Dumux::crossProduct(c(3)-c(0), c(2)-c(1)).two_norm();
85
86 }
87 else
88 return std::numeric_limits<ctype>::quiet_NaN();
89 }
90
91 else if constexpr (dim == 3)
92 {
93
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
1751192 if (type == Dune::GeometryTypes::tetrahedron)
94 {
95 using std::abs;
96 22080 return 1.0/6.0 * abs(
97 220680 Dumux::tripleProduct(c(3)-c(0), c(1)-c(0), c(2)-c(0))
98 22080 );
99 }
100
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
1729112 else if (type == Dune::GeometryTypes::hexahedron)
101 {
102 // after Grandy 1997, Efficient computation of volume of hexahedron
103 5077720 const auto v = c(7)-c(0);
104 using std::abs;
105 return 1.0/6.0 * (
106 13540688 abs(Dumux::tripleProduct(v, c(1)-c(0), c(3)-c(5)))
107 13540688 + abs(Dumux::tripleProduct(v, c(4)-c(0), c(5)-c(6)))
108 13540688 + abs(Dumux::tripleProduct(v, c(2)-c(0), c(6)-c(3)))
109 1692624 );
110 }
111
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
36488 else if (type == Dune::GeometryTypes::pyramid)
112 {
113 // 1/3 * base * height
114 // for base see case Dune::GeometryTypes::quadrilateral above
115 // = 1/3 * (1/2 * norm(ADxBC)) * ((ADxBC)/norm(AD x BC) ⋅ AE)
116 // = 1/6 * (AD x BC) ⋅ AE
117 using std::abs;
118 36484 return 1.0/6.0 * abs(
119 364672 Dumux::tripleProduct(c(3)-c(0), c(2)-c(1), c(4)-c(0))
120 36484 );
121 }
122
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 else if (type == Dune::GeometryTypes::prism)
123 {
124 // compute as sum of a pyramid (0-1-3-4-5) and a tetrahedron (2-0-1-5)
125 using std::abs;
126 return 1.0/6.0 * (
127 20 abs(Dumux::tripleProduct(c(3)-c(1), c(4)-c(0), c(5)-c(0)))
128 20 + abs(Dumux::tripleProduct(c(5)-c(2), c(0)-c(2), c(1)-c(2)))
129 4 );
130 }
131 else
132 return std::numeric_limits<ctype>::quiet_NaN();
133 }
134 else
135 return std::numeric_limits<ctype>::quiet_NaN();
136 }
137
138 /*!
139 * \ingroup Geometry
140 * \brief The volume of a given geometry
141 */
142 template<class Geometry>
143 292 auto convexPolytopeVolume(const Geometry& geo)
144 {
145 292 const auto v = convexPolytopeVolume<Geometry::mydimension>(
146 490 geo.type(), [&](unsigned int i){ return geo.corner(i); }
147 );
148
149 // fall back to the method of the geometry if no specialized
150 // volume function is implemented for the geometry type
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
292 return std::isnan(v) ? geo.volume() : v;
152 }
153
154 /*!
155 * \ingroup Geometry
156 * \brief The volume of a given geometry
157 */
158 template<class Geometry>
159 146 auto volume(const Geometry& geo, unsigned int integrationOrder = 4)
160 {
161 using ctype = typename Geometry::ctype;
162 146 ctype volume = 0.0;
163 292 const auto rule = Dune::QuadratureRules<ctype, Geometry::mydimension>::rule(geo.type(), integrationOrder);
164 4938 for (const auto& qp : rule)
165 4554 volume += geo.integrationElement(qp.position())*qp.weight();
166 292 return volume;
167 }
168
169 /*!
170 * \ingroup Geometry
171 * \brief The volume of a given geometry with an extrusion/transformation policy
172 * \note depending on the transformation this might not be an accurate quadrature rule anymore
173 */
174 template<class Geometry, class Transformation>
175 86517 auto volume(const Geometry& geo, Transformation transformation, unsigned int integrationOrder = 4)
176 {
177 using ctype = typename Geometry::ctype;
178 86517 ctype volume = 0.0;
179
1/4
✓ Branch 3 taken 86517 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
248268 const auto rule = Dune::QuadratureRules<ctype, Geometry::mydimension>::rule(geo.type(), integrationOrder);
180
4/4
✓ Branch 0 taken 778623 times.
✓ Branch 1 taken 86517 times.
✓ Branch 2 taken 778623 times.
✓ Branch 3 taken 86517 times.
1816797 for (const auto& qp : rule)
181
2/4
✓ Branch 1 taken 101517 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 101517 times.
✗ Branch 5 not taken.
1557246 volume += transformation.integrationElement(geo, qp.position())*qp.weight();
182
1/2
✓ Branch 0 taken 86517 times.
✗ Branch 1 not taken.
173034 return volume;
183 }
184
185 } // end namespace Dumux
186
187 #endif
188