GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/porousmediumflow/boxdfm/geometryhelper.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 40 51 78.4%
Functions: 11 12 91.7%
Branches: 18 112 16.1%

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 BoxDFMModel
10 * \brief Helper class constructing the dual grid finite volume geometries
11 * for the box discrete fracture model.
12 */
13 #ifndef DUMUX_POROUSMEDIUMFLOW_BOXDFM_GEOMETRY_HELPER_HH
14 #define DUMUX_POROUSMEDIUMFLOW_BOXDFM_GEOMETRY_HELPER_HH
15
16 #include <dune/common/fvector.hh>
17 #include <dune/common/reservedvector.hh>
18 #include <dune/geometry/multilineargeometry.hh>
19
20 #include <dumux/discretization/box/boxgeometryhelper.hh>
21
22 namespace Dumux {
23
24 template <class ct>
25 struct BoxDfmMLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
26 {
27 // we use static vectors to store the corners as we know
28 // the number of corners in advance (2^(mydim) corners (1<<(mydim))
29 // However, on fracture scvs the number might be smaller (use ReservedVector)
30 template< int mydim, int cdim >
31 struct CornerStorage
32 {
33 using Type = Dune::ReservedVector< Dune::FieldVector< ct, cdim >, (1<<(mydim)) >;
34 };
35
36 // we know all scvfs will have the same geometry type
37 template< int mydim >
38 struct hasSingleGeometryType
39 {
40 static const bool v = true;
41 static const unsigned int topologyId = Dune::GeometryTypes::cube(mydim).id();
42 };
43 };
44
45 //! Create sub control volumes and sub control volume face geometries
46 template<class GridView, int dim, class ScvType, class ScvfType>
47 class BoxDfmGeometryHelper;
48
49 //! A class to create sub control volume and sub control volume face geometries per element
50 template <class GridView, class ScvType, class ScvfType>
51 class BoxDfmGeometryHelper<GridView, 2, ScvType, ScvfType> : public BoxGeometryHelper<GridView, 2, ScvType, ScvfType>
52 {
53 using ParentType = BoxGeometryHelper<GridView, 2, ScvType, ScvfType>;
54
55 using Intersection = typename GridView::Intersection;
56 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
57
58 static constexpr auto dim = GridView::dimension;
59 using Scalar = typename GridView::ctype;
60
61 public:
62
63 //! Pull up constructor of base class
64
2/4
✓ Branch 1 taken 1264764 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1264764 times.
✗ Branch 5 not taken.
5059056 using ParentType::ParentType;
65
66 //! Get the corners of the (d-1)-dimensional fracture scvf
67 129342 ScvfCornerStorage getFractureScvfCorners(unsigned int localFacetIndex,
68 unsigned int) const
69 {
70 129342 const auto& geo = this->elementGeometry();
71
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
129342 const auto ref = referenceElement(geo);
72
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
258684 return ScvfCornerStorage({ geo.global(ref.position(localFacetIndex, 1)) });
73 }
74
75 //! get fracture scvf normal vector (simply the unit vector of the edge)
76 //! The third argument is for compatibility reasons with the 3d case!
77 typename ScvfType::Traits::GlobalPosition
78 258684 fractureNormal(const ScvfCornerStorage& p,
79 const Intersection& is,
80 unsigned int edgeIndexInIntersection) const
81 {
82 258684 const auto& geo = this->elementGeometry();
83 258684 const auto ref = referenceElement(geo);
84
2/2
✓ Branch 0 taken 2142 times.
✓ Branch 1 taken 127200 times.
388026 const auto v0 = ref.subEntity(is.indexInInside(), 1, 0, dim);
85
2/2
✓ Branch 0 taken 2142 times.
✓ Branch 1 taken 127200 times.
388026 const auto v1 = ref.subEntity(is.indexInInside(), 1, 1, dim);
86 258684 auto normal = geo.corner(v1) - geo.corner(v0);
87 517368 normal /= normal.two_norm();
88 258684 return normal;
89 }
90 };
91
92 //! A class to create sub control volume and sub control volume face geometries per element
93 template <class GridView, class ScvType, class ScvfType>
94 class BoxDfmGeometryHelper<GridView, 3, ScvType, ScvfType> : public BoxGeometryHelper<GridView, 3, ScvType, ScvfType>
95 {
96 using ParentType = BoxGeometryHelper<GridView, 3, ScvType, ScvfType>;
97
98 using Intersection = typename GridView::Intersection;
99 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
100
101 static constexpr auto dim = GridView::dimension;
102 static constexpr auto dimWorld = GridView::dimensionworld;
103 using Scalar = typename GridView::ctype;
104
105 public:
106
107 //! Pull up constructor of base class
108
2/4
✓ Branch 1 taken 136962 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 136962 times.
✗ Branch 5 not taken.
547848 using ParentType::ParentType;
109
110 //! Create the sub control volume face geometries on an intersection marked as fracture
111 83160 ScvfCornerStorage getFractureScvfCorners(unsigned int localFacetIndex,
112 unsigned int indexInFacet) const
113 {
114 83160 constexpr int facetCodim = 1;
115
116 // we have to use the corresponding facet geometry as the intersection geometry
117 // might be rotated or flipped. This makes sure that the corners (dof location)
118 // and corresponding scvfs are sorted in the same way
119 using Dune::referenceElement;
120 83160 const auto& geo = this->elementGeometry();
121 83160 const auto type = referenceElement(geo).type(localFacetIndex, facetCodim);
122
1/2
✓ Branch 0 taken 83160 times.
✗ Branch 1 not taken.
83160 if (type == Dune::GeometryTypes::triangle)
123 {
124 using Corners = Detail::Box::ScvfCorners<Dune::GeometryTypes::triangle>;
125 166320 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(geo, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
126 }
127 else if (type == Dune::GeometryTypes::quadrilateral)
128 {
129 using Corners = Detail::Box::ScvfCorners<Dune::GeometryTypes::quadrilateral>;
130 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(geo, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
131 }
132 else
133 DUNE_THROW(Dune::NotImplemented, "Box fracture scvf geometries for dim=" << dim
134 << " dimWorld=" << dimWorld
135 << " type=" << type);
136 }
137
138 //! get fracture scvf normal vector
139 typename ScvfType::Traits::GlobalPosition
140 83160 fractureNormal(const ScvfCornerStorage& scvfCorners,
141 const Intersection& is,
142 unsigned int edgeIndexInIntersection) const
143 {
144 83160 const auto& geo = this->elementGeometry();
145 83160 const auto refElement = referenceElement(geo);
146
147 // first get the intersection corners (maximum "4" is for quadrilateral face)
148 83160 typename ScvfType::Traits::GlobalPosition c[4];
149
150 124740 const auto corners = refElement.size(is.indexInInside(), 1, dim);
151
2/2
✓ Branch 0 taken 249480 times.
✓ Branch 1 taken 83160 times.
332640 for (int i = 0; i < corners; ++i)
152 {
153 374220 const auto vIdxLocal = refElement.subEntity(is.indexInInside(), 1, i, dim);
154 249480 c[i] = geo.corner(vIdxLocal);
155 }
156
157 // compute edge vector depending on number of corners
158 83160 const auto gridEdge = [&] ()
159 {
160 // triangles
161
1/2
✓ Branch 0 taken 83160 times.
✗ Branch 1 not taken.
83160 if (corners == 3)
162 {
163 27720 if (edgeIndexInIntersection == 0) return c[1]-c[0];
164
2/2
✓ Branch 0 taken 27720 times.
✓ Branch 1 taken 27720 times.
55440 else if (edgeIndexInIntersection == 1) return c[2]-c[0];
165
1/2
✓ Branch 0 taken 27720 times.
✗ Branch 1 not taken.
27720 else if (edgeIndexInIntersection == 2) return c[2]-c[1];
166 else DUNE_THROW(Dune::InvalidStateException, "Invalid edge index");
167 }
168 else if (corners == 4)
169 {
170 if (edgeIndexInIntersection == 0) return c[2]-c[0];
171 else if (edgeIndexInIntersection == 1) return c[3]-c[1];
172 else if (edgeIndexInIntersection == 2) return c[1]-c[0];
173 else if (edgeIndexInIntersection == 3) return c[3]-c[2];
174 else DUNE_THROW(Dune::InvalidStateException, "Invalid edge index");
175 }
176 else
177 DUNE_THROW(Dune::InvalidStateException, "Invalid face geometry");
178
2/4
✓ Branch 1 taken 27720 times.
✓ Branch 2 taken 55440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
166320 } ();
179
180 // compute lower edge of the scvf
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83160 times.
83160 assert(scvfCorners.size() == 2);
182 249480 const auto scvfEdge = scvfCorners[1]-scvfCorners[0];
183
184 // compute scvf normal via 2 cross products
185 83160 const auto faceN = crossProduct(gridEdge, scvfEdge);
186 83160 auto n = crossProduct(scvfEdge, faceN);
187 166320 n /= n.two_norm();
188 83160 return n;
189 }
190 };
191
192 } // end namespace Dumux
193
194 #endif
195