GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/discretization/porenetwork/gridgeometry.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 137 191 71.7%
Functions: 23 38 60.5%
Branches: 381 768 49.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 PoreNetworkDiscretization
10 * \brief Base class for the finite volume geometry for porenetwork models
11 */
12 #ifndef DUMUX_DISCRETIZATION_PNM_GRID_GEOMETRY_HH
13 #define DUMUX_DISCRETIZATION_PNM_GRID_GEOMETRY_HH
14
15 #include <string>
16 #include <utility>
17 #include <unordered_map>
18 #include <functional>
19
20 #include <dune/common/exceptions.hh>
21 #include <dune/localfunctions/lagrange/lagrangelfecache.hh>
22
23 #include <dumux/discretization/method.hh>
24 #include <dumux/common/indextraits.hh>
25 #include <dumux/common/defaultmappertraits.hh>
26 #include <dumux/common/parameters.hh>
27
28 #include <dumux/discretization/basegridgeometry.hh>
29 #include <dumux/discretization/porenetwork/fvelementgeometry.hh>
30 #include <dumux/discretization/porenetwork/subcontrolvolume.hh>
31 #include <dumux/discretization/porenetwork/subcontrolvolumeface.hh>
32 #include <dumux/porenetwork/common/throatproperties.hh>
33 #include <dumux/porenetwork/common/poreproperties.hh>
34 #include <dumux/discretization/extrusion.hh>
35
36 namespace Dumux::PoreNetwork {
37
38 /*!
39 * \ingroup PoreNetworkDiscretization
40 * \brief Base class for geometry data extraction from the grid data format
41 */
42 template<class Scalar, class GridView>
43 class DefaultPNMData
44 {
45 using GridIndex = typename IndexTraits<GridView>::GridIndex;
46 using SmallLocalIndex = typename IndexTraits<GridView>::SmallLocalIndex;
47 using Label = std::int_least8_t;
48 using Vertex = typename GridView::template Codim<GridView::dimension>::Entity;
49 using Element = typename GridView::template Codim<0>::Entity;
50
51 static const int dim = GridView::dimension;
52
53 public:
54
55 template<class GridData>
56 24 void update(const GridView& gridView, const GridData& gridData)
57 {
58
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 coordinationNumber_ = gridData.getCoordinationNumbers();
59
60 24 const auto numThroats = gridView.size(0);
61 24 throatInscribedRadius_.resize(numThroats);
62 24 throatLength_.resize(numThroats);
63 24 throatLabel_.resize(numThroats);
64 24 throatCrossSectionalArea_.resize(numThroats);
65 24 throatShapeFactor_.resize(numThroats);
66
67 24 useSameGeometryForAllPores_ = true;
68 24 useSameShapeForAllThroats_ = true;
69 24 overwriteGridDataWithShapeSpecificValues_ = false;
70
71 // first check if the same geometry shall be used for all entities ...
72
9/16
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 24 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 20 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 20 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
120 if (hasParamInGroup(gridData.paramGroup(), "Grid.ThroatCrossSectionShape"))
73 {
74 41 const auto throatGeometryInput = getParamFromGroup<std::string>(gridData.paramGroup(), "Grid.ThroatCrossSectionShape");
75
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 const auto throatGeometry = Throat::shapeFromString(throatGeometryInput);
76
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 throatGeometry_.resize(1);
77 20 throatGeometry_[0] = throatGeometry;
78
2/7
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
21 overwriteGridDataWithShapeSpecificValues_ = getParamFromGroup<bool>(gridData.paramGroup(), "Grid.OverwriteGridDataWithShapeSpecificValues", true);
79
80
3/6
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 20 times.
60 std::cout << "Using '" << throatGeometryInput << "' as cross-sectional shape for all throats." << std::endl;
81 }
82 else // .. otherwise, get the corresponding parameter index from the grid data and resize the respective vector
83 {
84 8 std::cout << "Reading shape factors for throats from grid data." << std::endl;
85 4 useSameShapeForAllThroats_ = false;
86 4 throatGeometry_.resize(numThroats);
87 }
88
89 // get the vertex parameters
90 24 const auto numPores = gridView.size(dim);
91 24 poreInscribedRadius_.resize(numPores);
92 24 poreLabel_.resize(numPores);
93 24 poreVolume_.resize(numPores);
94
95 // first check if the same geometry shall be used for all entities ...
96
10/17
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 19 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 19 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 19 times.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
120 if (hasParamInGroup(gridData.paramGroup(), "Grid.PoreGeometry"))
97 {
98
0/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
53 const auto poreGeometryInput = getParamFromGroup<std::string>(gridData.paramGroup(), "Grid.PoreGeometry");
99
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 poreGeometry_.resize(1);
100
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 poreGeometry_[0] = Pore::shapeFromString(poreGeometryInput);;
101
102
3/6
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 24 times.
72 std::cout << "Using '" << poreGeometryInput << "' as geometry for all pores." << std::endl;
103 }
104 else // .. otherwise, get the corresponding parameter index from the grid data and resize the respective vector
105 {
106 std::cout << "Reading pore shapes from grid data." << std::endl;
107 useSameGeometryForAllPores_ = false;
108 poreGeometry_.resize(numPores);
109 }
110
111
112
6/6
✓ Branch 1 taken 18847 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 18847 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 18826 times.
37718 for (const auto& vertex : vertices(gridView))
113 {
114
7/14
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 18826 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 21 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
18889 static const auto poreInscribedRadiusIdx = gridData.parameterIndex("PoreInscribedRadius");
115
7/14
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 18826 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 21 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
18847 static const auto poreLabelIdx = gridData.parameterIndex("PoreLabel");
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18847 times.
18847 const auto vIdx = gridView.indexSet().index(vertex);
117 18847 const auto& params = gridData.parameters(vertex);
118
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18847 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18847 times.
37694 poreInscribedRadius_[vIdx] = params[poreInscribedRadiusIdx];
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18847 times.
18847 assert(poreInscribedRadius_[vIdx] > 0.0);
120
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18847 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18847 times.
37694 poreLabel_[vIdx] = params[poreLabelIdx];
121
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18847 times.
18847 if (!useSameGeometryForAllPores())
123 poreGeometry_[vIdx] = getPoreGeometry_(gridData, vertex);
124
125 18847 poreVolume_[vIdx] = getPoreVolume_(gridData, vertex, vIdx);
126 }
127
128
5/6
✓ Branch 1 taken 42153 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 42153 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42153 times.
42177 for (const auto& element : elements(gridView))
129 {
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42153 times.
42153 const int eIdx = gridView.indexSet().index(element);
131 42153 const auto& params = gridData.parameters(element);
132
7/14
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 21 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
42195 static const auto throatInscribedRadiusIdx = gridData.parameterIndex("ThroatInscribedRadius");
133
7/14
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 21 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
42153 static const auto throatLengthIdx = gridData.parameterIndex("ThroatLength");
134
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 42132 times.
84306 throatInscribedRadius_[eIdx] = params[throatInscribedRadiusIdx];
135
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 42132 times.
84306 throatLength_[eIdx] = params[throatLengthIdx];
136
137 // use a default value if no throat label is given by the grid
138
6/10
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 21 times.
42153 static const bool gridHasThroatLabel = gridData.gridHasElementParameter("ThroatLabel");
139
1/2
✓ Branch 0 taken 42153 times.
✗ Branch 1 not taken.
42153 if (gridHasThroatLabel)
140 {
141
7/14
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 21 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 21 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
42153 static const auto throatLabelIdx = gridData.parameterIndex("ThroatLabel");
142 126459 throatLabel_[eIdx] = params[throatLabelIdx];
143 }
144 else
145 {
146 const auto vIdx0 = gridView.indexSet().subIndex(element, 0, dim);
147 const auto vIdx1 = gridView.indexSet().subIndex(element, 1, dim);
148
149 const auto poreLabel0 = poreLabel(vIdx0);
150 const auto poreLabel1 = poreLabel(vIdx1);
151
152 if (poreLabel0 >= 0 && poreLabel1 >= 0)
153 {
154 std::cout << "\n Warning: Throat "
155 << eIdx << " connects two boundary pores with different pore labels. Using the greater pore label as throat label.\n"
156 << "Set the throat labels explicitly in your grid file, if needed." << std::endl;
157 }
158
159 using std::max;
160 throatLabel_[eIdx] = max(poreLabel0, poreLabel1);
161 }
162
163
2/2
✓ Branch 0 taken 6382 times.
✓ Branch 1 taken 35771 times.
42153 if (!useSameShapeForAllThroats())
164 {
165
7/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6381 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
6384 static const auto throatShapeFactorIdx = gridData.parameterIndex("ThroatShapeFactor");
166
7/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6381 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
6384 static const auto throatAreaIdx = gridData.parameterIndex("ThroatCrossSectionalArea");
167
4/4
✓ Branch 0 taken 4122 times.
✓ Branch 1 taken 2260 times.
✓ Branch 2 taken 4122 times.
✓ Branch 3 taken 2260 times.
12764 throatShapeFactor_[eIdx] = params[throatShapeFactorIdx];
168
2/2
✓ Branch 0 taken 4122 times.
✓ Branch 1 taken 2260 times.
10504 throatGeometry_[eIdx] = Throat::shape(throatShapeFactor_[eIdx]);
169 19146 throatCrossSectionalArea_[eIdx] = params[throatAreaIdx];
170 }
171 else
172 {
173 35771 throatCrossSectionalArea_[eIdx] = getThroatCrossSectionalArea_(gridData, element, eIdx);
174 35771 throatShapeFactor_[eIdx] = getThroatShapeFactor_(gridData, element, eIdx);
175 }
176
177
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42153 times.
84306 assert(throatInscribedRadius_[eIdx] > 0.0);
178
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42153 times.
84306 assert(throatLength_[eIdx] > 0.0);
179
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42153 times.
84306 assert(throatCrossSectionalArea_[eIdx] > 0.0);
180
181
5/8
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 42132 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
42153 static const bool addThroatVolumeToPoreVolume = getParamFromGroup<bool>(gridData.paramGroup(), "Grid.AddThroatVolumeToPoreVolume", false);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42153 times.
42153 if (addThroatVolumeToPoreVolume)
183 {
184 for (int vIdxLocal = 0; vIdxLocal < 2; ++vIdxLocal)
185 {
186 const auto vIdx = gridView.indexSet().subIndex(element, vIdxLocal, dim);
187 poreVolume_[vIdx] += 0.5 * throatCrossSectionalArea_[eIdx] * throatLength_[eIdx];
188 }
189 }
190 }
191
192 24 maybeResizeContainers_();
193 24 }
194
195 //! Returns the pore label (e.g. used for setting BCs)
196 Label poreLabel(const GridIndex dofIdxGlobal) const
197
59/68
✓ Branch 0 taken 49599 times.
✓ Branch 1 taken 1460415 times.
✓ Branch 2 taken 49599 times.
✓ Branch 3 taken 1460415 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1316 times.
✓ Branch 6 taken 17037 times.
✓ Branch 7 taken 62929 times.
✓ Branch 8 taken 18353 times.
✓ Branch 9 taken 61613 times.
✓ Branch 10 taken 265812 times.
✓ Branch 11 taken 2758432 times.
✓ Branch 12 taken 265495 times.
✓ Branch 13 taken 2758115 times.
✓ Branch 14 taken 7377 times.
✓ Branch 15 taken 5356 times.
✓ Branch 16 taken 7986 times.
✓ Branch 17 taken 5666 times.
✓ Branch 18 taken 21515 times.
✓ Branch 19 taken 20869 times.
✓ Branch 20 taken 27465 times.
✓ Branch 21 taken 123769 times.
✓ Branch 22 taken 65157 times.
✓ Branch 23 taken 742879 times.
✓ Branch 24 taken 117514 times.
✓ Branch 25 taken 829614 times.
✓ Branch 26 taken 87561 times.
✓ Branch 27 taken 551575 times.
✓ Branch 28 taken 27280 times.
✓ Branch 29 taken 354760 times.
✓ Branch 30 taken 7323 times.
✓ Branch 31 taken 28251 times.
✓ Branch 32 taken 4472 times.
✓ Branch 33 taken 19699 times.
✓ Branch 34 taken 44251 times.
✓ Branch 35 taken 382748 times.
✓ Branch 36 taken 44250 times.
✓ Branch 37 taken 382744 times.
✓ Branch 38 taken 1407 times.
✓ Branch 39 taken 5383 times.
✓ Branch 40 taken 1407 times.
✓ Branch 41 taken 5383 times.
✓ Branch 42 taken 1365 times.
✓ Branch 43 taken 4018 times.
✓ Branch 44 taken 805 times.
✓ Branch 45 taken 3213 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 6790 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 6790 times.
✓ Branch 50 taken 1732252 times.
✓ Branch 51 taken 2101022 times.
✓ Branch 52 taken 1732252 times.
✓ Branch 53 taken 2101022 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✓ Branch 64 taken 82760 times.
✓ Branch 65 taken 715720 times.
✓ Branch 66 taken 82760 times.
✓ Branch 67 taken 715720 times.
✓ Branch 68 taken 195 times.
✓ Branch 69 taken 1819 times.
✓ Branch 70 taken 195 times.
✓ Branch 71 taken 1819 times.
24654985 { return poreLabel_[dofIdxGlobal]; }
198
199 //! Returns the vector of pore labels
200 const std::vector<Label>& poreLabel() const
201
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
20 { return poreLabel_; }
202
203 //! Returns the inscribed radius of the pore
204 Scalar poreInscribedRadius(const GridIndex dofIdxGlobal) const
205
13/24
✓ Branch 0 taken 2522976 times.
✓ Branch 1 taken 41563 times.
✓ Branch 2 taken 2522976 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2564539 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2522976 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2522976 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2522976 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1092264 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1092264 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1092264 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1092264 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1092264 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1092264 times.
✗ Branch 23 not taken.
42478828 { return poreInscribedRadius_[dofIdxGlobal]; }
206
207 //! Returns the vector of inscribed pore radii
208 const std::vector<Scalar>& poreInscribedRadius() const
209 { return poreInscribedRadius_; }
210
211 //! Returns the volume of the pore
212 Scalar poreVolume(const GridIndex dofIdxGlobal) const
213 15824760 { return poreVolume_[dofIdxGlobal]; }
214
215 //! Returns the vector of pore volumes
216 const std::vector<Scalar>& poreVolume() const
217
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
3 { return poreVolume_; }
218
219 //! Returns the inscribed radius of the throat
220 Scalar throatInscribedRadius(const GridIndex eIdx) const
221
2/4
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
84730822 { return throatInscribedRadius_[eIdx]; }
222
223 //! Returns the vector of inscribed throat radii
224 const std::vector<Scalar>& throatInscribedRadius() const
225 { return throatInscribedRadius_; }
226
227 //! Returns the length of the throat
228 Scalar throatLength(const GridIndex eIdx) const
229 80928576 { return throatLength_[eIdx]; }
230
231 //! Returns the vector of throat lengths
232 const std::vector<Scalar>& throatLength() const
233 { return throatLength_; }
234
235 //! Returns an index indicating if a throat is touching the domain boundary
236 Label throatLabel(const GridIndex eIdx) const
237 1444 { return throatLabel_[eIdx]; }
238
239 //! Returns the vector of throat labels
240 const std::vector<Label>& throatLabel() const
241
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
20 { return throatLabel_; }
242
243 //! Returns the number of throats connected to a pore (coordination number)
244 SmallLocalIndex coordinationNumber(const GridIndex dofIdxGlobal) const
245 15813316 { return coordinationNumber_[dofIdxGlobal]; }
246
247 //! Returns the vector of coordination numbers
248 const std::vector<SmallLocalIndex>& coordinationNumber() const
249
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
1368799 { return coordinationNumber_; }
250
251 //! the geometry of the pore
252 Pore::Shape poreGeometry(const GridIndex vIdx) const
253
2/4
✓ Branch 0 taken 83320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2979476 times.
✗ Branch 3 not taken.
3063616 { return useSameGeometryForAllPores() ? poreGeometry_[0] : poreGeometry_[vIdx]; }
254
255 //! Returns the vector of pore geometries
256 3062796 const std::vector<Pore::Shape>& poreGeometry() const
257 {
258
1/2
✓ Branch 0 taken 3062796 times.
✗ Branch 1 not taken.
3062796 if (useSameGeometryForAllPores())
259 {
260 // if a vector of pore geometries is requested (e.g., for vtk output),
261 // resize the container and fill it with the same value everywhere
262 3062796 const auto poreGeo = poreGeometry_[0];
263 6125592 poreGeometry_.resize(poreInscribedRadius_.size(), poreGeo);
264 }
265
266 3062796 return poreGeometry_;
267 }
268
269 //! Returns the throat's cross-sectional shape
270 Throat::Shape throatCrossSectionShape(const GridIndex eIdx) const
271
6/10
✓ Branch 0 taken 2910328 times.
✓ Branch 1 taken 35427936 times.
✓ Branch 2 taken 1092264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92457 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 959946 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 959820 times.
✗ Branch 9 not taken.
41514293 { return useSameShapeForAllThroats() ? throatGeometry_[0] : throatGeometry_[eIdx]; }
272
273 //! Returns the vector of cross-sectional shapes
274 const std::vector<Throat::Shape>& throatCrossSectionShape() const
275 {
276 if (useSameShapeForAllThroats())
277 {
278 // if a vector of throat cross section shapes is requested (e.g., for vtk output),
279 // resize the container and fill it with the same value everywhere
280 const auto throatShape = throatGeometry_[0];
281 throatGeometry_.resize(throatInscribedRadius_.size(), throatShape);
282 }
283
284 return throatGeometry_;
285 }
286
287 //! Returns the throat's cross-sectional area
288 Scalar throatCrossSectionalArea(const GridIndex eIdx) const
289
4/4
✓ Branch 0 taken 153993 times.
✓ Branch 1 taken 867363 times.
✓ Branch 2 taken 153993 times.
✓ Branch 3 taken 867363 times.
89019842 { return throatCrossSectionalArea_[eIdx]; }
290
291 //! Returns the vector of throat cross-sectional areas
292 const std::vector<Scalar>& throatCrossSectionalArea() const
293
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
3 { return throatCrossSectionalArea_; }
294
295 //! Returns the throat's shape factor
296 Scalar throatShapeFactor(const GridIndex eIdx) const
297
4/6
✓ Branch 0 taken 1409717 times.
✓ Branch 1 taken 35427936 times.
✓ Branch 2 taken 3482796 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1092264 times.
✗ Branch 5 not taken.
41412713 { return useSameShapeForAllThroats() ? throatShapeFactor_[0] : throatShapeFactor_[eIdx]; }
298
299 //! Returns the vector of throat shape factors
300 2 const std::vector<Scalar>& throatShapeFactor() const
301 {
302
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (useSameShapeForAllThroats())
303 {
304 // if a vector of throat shape factors is requested (e.g., for vtk output),
305 // resize the container and fill it with the same value everywhere
306 2 const auto shapeFactor = throatShapeFactor_[0];
307 4 throatShapeFactor_.resize(throatInscribedRadius_.size(), shapeFactor);
308 }
309
310 2 return throatShapeFactor_;
311 }
312
313 //! Returns whether all pores feature the same shape
314 bool useSameGeometryForAllPores() const
315 { return useSameGeometryForAllPores_; }
316
317 //! Returns whether all throats feature the same cross-sectional shape
318 bool useSameShapeForAllThroats() const
319 { return useSameShapeForAllThroats_; }
320
321 private:
322
323 //! determine the pore geometry provided as scalar value by the grid file
324 template<class GridData>
325 Pore::Shape getPoreGeometry_(const GridData& gridData, const Vertex& vertex) const
326 {
327 static const auto poreGeometryIdx = gridData.parameterIndex("PoreGeometry");
328 using T = std::underlying_type_t<Pore::Shape>;
329 const auto poreGeometryValue = static_cast<T>(gridData.parameters(vertex)[poreGeometryIdx]);
330 return static_cast<Pore::Shape>(poreGeometryValue);
331 }
332
333 //! automatically determine the pore volume if not provided by the grid file
334 template<class GridData>
335 18847 Scalar getPoreVolume_(const GridData& gridData, const Vertex& vertex, const std::size_t vIdx) const
336 {
337
6/10
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 18826 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 21 times.
18847 static const bool gridHasPoreVolume = gridData.gridHasVertexParameter("PoreVolume");
338
339
2/2
✓ Branch 0 taken 18027 times.
✓ Branch 1 taken 820 times.
18847 if (gridHasPoreVolume)
340 {
341
7/14
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 18017 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
18027 static const auto poreVolumeIdx = gridData.parameterIndex("PoreVolume");
342 18027 return gridData.parameters(vertex)[poreVolumeIdx];
343 }
344 else
345 {
346
2/4
✓ Branch 0 taken 820 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 820 times.
1640 if (poreGeometry(vIdx) == Pore::Shape::cylinder)
347 {
348 static const Scalar fixedHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.PoreHeight", -1.0);
349 const Scalar h = fixedHeight > 0.0 ? fixedHeight : gridData.getParameter(vertex, "PoreHeight");
350 return Pore::volume(Pore::Shape::cylinder, poreInscribedRadius(vIdx), h);
351 }
352 else
353 1640 return Pore::volume(poreGeometry(vIdx), poreInscribedRadius(vIdx));
354 }
355 }
356
357 //! automatically determine throat cross-sectional area if not provided by the grid file
358 template<class GridData>
359 35771 Scalar getThroatCrossSectionalArea_(const GridData& gridData, const Element& element, const std::size_t eIdx) const
360 {
361
6/10
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 35751 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
35811 static const bool gridHasThroatCrossSectionalArea = gridData.gridHasElementParameter("ThroatCrossSectionalArea");
362
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 35771 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
35771 if (gridHasThroatCrossSectionalArea && !overwriteGridDataWithShapeSpecificValues_)
363 {
364 static const auto throatAreaIdx = gridData.parameterIndex("ThroatCrossSectionalArea");
365 return gridData.parameters(element)[throatAreaIdx];
366 }
367 else
368 {
369
2/4
✓ Branch 0 taken 35771 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35771 times.
71542 if (const auto shape = throatCrossSectionShape(eIdx); shape == Throat::Shape::rectangle)
370 {
371 static const auto throatHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatHeight");
372 return Throat::totalCrossSectionalAreaForRectangle(throatInscribedRadius_[eIdx], throatHeight);
373 }
374 else
375 71542 return Throat::totalCrossSectionalArea(shape, throatInscribedRadius_[eIdx]);
376 }
377 }
378
379 //! automatically determine throat shape factor if not provided by the grid file
380 template<class GridData>
381 35771 Scalar getThroatShapeFactor_(const GridData& gridData, const Element& element, const std::size_t eIdx) const
382 {
383
6/10
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 35751 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
35811 static const bool gridHasThroatShapeFactor = gridData.gridHasElementParameter("ThroatShapeFactor");
384
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 35771 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
35771 if (gridHasThroatShapeFactor && !overwriteGridDataWithShapeSpecificValues_)
385 {
386 static const auto throatShapeFactorIdx = gridData.parameterIndex("ThroatShapeFactor");
387 return gridData.parameters(element)[throatShapeFactorIdx];
388 }
389 else
390 {
391
2/4
✓ Branch 0 taken 35771 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35771 times.
71542 if (const auto shape = throatCrossSectionShape(eIdx); shape == Throat::Shape::rectangle)
392 {
393 static const auto throatHeight = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatHeight");
394 return Throat::shapeFactorRectangle(throatInscribedRadius_[eIdx], throatHeight);
395 }
396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35771 times.
35771 else if (shape == Throat::Shape::polygon || shape == Throat::Shape::scaleneTriangle)
397 {
398 static const auto shapeFactor = getParamFromGroup<Scalar>(gridData.paramGroup(), "Grid.ThroatShapeFactor");
399 return shapeFactor;
400 }
401 else
402 71542 return Throat::shapeFactor<Scalar>(shape, throatInscribedRadius_[eIdx]);
403 }
404 }
405
406 24 void maybeResizeContainers_()
407 {
408 // check if all throat might have the same shape in order to save some memory
409
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
24 if (!useSameShapeForAllThroats() &&
410
6/12
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
24 std::adjacent_find(throatGeometry_.begin(), throatGeometry_.end(), std::not_equal_to<Throat::Shape>() ) == throatGeometry_.end())
411 {
412 std::cout << "All throats feature the same shape, resizing containers" << std::endl;
413 useSameShapeForAllThroats_ = true;
414 const Scalar shapeFactor = throatShapeFactor_[0];
415 const auto throatGeometry = throatGeometry_[0];
416 throatShapeFactor_.resize(1);
417 throatGeometry_.resize(1);
418 throatShapeFactor_[0] = shapeFactor;
419 throatGeometry_[0] = throatGeometry;
420 }
421
422 // check if all throat might have the same shape in order to save some memory
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!useSameGeometryForAllPores() &&
424 std::adjacent_find(poreGeometry_.begin(), poreGeometry_.end(), std::not_equal_to<Pore::Shape>() ) == poreGeometry_.end())
425 {
426 std::cout << "All pores feature the same shape, resizing containers" << std::endl;
427 useSameGeometryForAllPores_ = true;
428 const auto poreGeometry = poreGeometry_[0];
429 poreGeometry_.resize(1);
430 poreGeometry_[0] = poreGeometry;
431 }
432 24 }
433
434 mutable std::vector<Pore::Shape> poreGeometry_;
435 std::vector<Scalar> poreInscribedRadius_;
436 std::vector<Scalar> poreVolume_;
437 std::vector<Label> poreLabel_; // 0:no, 1:general, 2:coupling1, 3:coupling2, 4:inlet, 5:outlet
438 std::vector<SmallLocalIndex> coordinationNumber_;
439 mutable std::vector<Throat::Shape> throatGeometry_;
440 mutable std::vector<Scalar> throatShapeFactor_;
441 std::vector<Scalar> throatInscribedRadius_;
442 std::vector<Scalar> throatLength_;
443 std::vector<Label> throatLabel_; // 0:no, 1:general, 2:coupling1, 3:coupling2, 4:inlet, 5:outlet
444 std::vector<Scalar> throatCrossSectionalArea_;
445 bool useSameGeometryForAllPores_;
446 bool useSameShapeForAllThroats_;
447 bool overwriteGridDataWithShapeSpecificValues_;
448 };
449
450 /*!
451 * \ingroup PoreNetworkDiscretization
452 * \brief The default traits
453 * \tparam the grid view type
454 */
455 template<class GridView, class MapperTraits = DefaultMapperTraits<GridView>>
456 struct PNMDefaultGridGeometryTraits
457 : public MapperTraits
458 {
459 using SubControlVolume = PNMSubControlVolume<GridView>;
460 using SubControlVolumeFace = PNMSubControlVolumeFace<GridView>;
461
462 template<class GridGeometry, bool enableCache>
463 using LocalView = PNMFVElementGeometry<GridGeometry, enableCache>;
464
465 using PNMData = DefaultPNMData<typename SubControlVolume::Traits::Scalar, GridView>;
466 };
467
468 /*!
469 * \ingroup PoreNetworkDiscretization
470 * \brief Base class for the finite volume geometry for porenetwork models
471 * \note This class is specialized for versions with and without caching the fv geometries on the grid view
472 */
473 template<class Scalar,
474 class GridView,
475 bool enableGridGeometryCache = false,
476 class Traits = PNMDefaultGridGeometryTraits<GridView> >
477 class GridGeometry;
478
479 /*!
480 * \ingroup PoreNetworkDiscretization
481 * \brief Base class for the finite volume geometry for porenetwork models
482 * \note For caching enabled we store the fv geometries for the whole grid view which is memory intensive but faster
483 */
484 template<class Scalar, class GV, class Traits>
485 class GridGeometry<Scalar, GV, true, Traits>
486 : public BaseGridGeometry<GV, Traits>
487 , public Traits::PNMData
488 {
489 using ThisType = GridGeometry<Scalar, GV, true, Traits>;
490 using ParentType = BaseGridGeometry<GV, Traits>;
491 using GridIndexType = typename IndexTraits<GV>::GridIndex;
492 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
493 using PNMData = typename Traits::PNMData;
494
495 using Element = typename GV::template Codim<0>::Entity;
496 using CoordScalar = typename GV::ctype;
497 static const int dim = GV::dimension;
498 static const int dimWorld = GV::dimensionworld;
499
500 public:
501 //! export the discretization method this geometry belongs to
502 using DiscretizationMethod = DiscretizationMethods::Box;
503 static constexpr DiscretizationMethod discMethod{};
504
505 //! export the type of the fv element geometry (the local view type)
506 using LocalView = typename Traits::template LocalView<ThisType, true>;
507 //! export the type of sub control volume
508 using SubControlVolume = typename Traits::SubControlVolume;
509 //! export the type of sub control volume
510 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
511 //! export the type of extrusion
512 using Extrusion = Extrusion_t<Traits>;
513 //! export dof mapper type
514 using DofMapper = typename Traits::VertexMapper;
515 //! export the finite element cache type
516 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
517 //! export the grid view type
518 using GridView = GV;
519
520 //! Constructor
521 template<class GridData>
522 GridGeometry(const GridView& gridView, const GridData& gridData)
523 : ParentType(gridView)
524 {
525 static_assert(GridView::dimension == 1, "Porenetwork model only allow GridView::dimension == 1!");
526 update_(gridData);
527 }
528
529 //! the vertex mapper is the dofMapper
530 //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa...
531 const DofMapper& dofMapper() const
532 { return this->vertexMapper(); }
533
534 //! The total number of sub control volumes
535 std::size_t numScv() const
536 { return numScv_; }
537
538 //! The total number of sun control volume faces
539 std::size_t numScvf() const
540 { return numScvf_; }
541
542 //! The total number of boundary sub control volume faces
543 //! For compatibility reasons with cc methods
544 std::size_t numBoundaryScvf() const
545 { return 0; }
546
547 //! The total number of degrees of freedom
548 std::size_t numDofs() const
549 { return this->vertexMapper().size(); }
550
551 //! update all fvElementGeometries (call this after grid adaption)
552 template<class GridData>
553 void update(const GridView& gridView, const GridData& gridData)
554 {
555 ParentType::update(gridView);
556 update_(gridData);
557 }
558
559 //! update all fvElementGeometries (call this after grid adaption)
560 template<class GridData>
561 void update(GridView&& gridView, const GridData& gridData)
562 {
563 ParentType::update(std::move(gridView));
564 update_(gridData);
565 }
566
567 //! The finite element cache for creating local FE bases
568 const FeCache& feCache() const
569 { return feCache_; }
570
571 //! Get the local scvs for an element
572 const std::array<SubControlVolume, 2>& scvs(GridIndexType eIdx) const
573 { return scvs_[eIdx]; }
574
575 //! Get the local scvfs for an element
576 const std::array<SubControlVolumeFace, 1>& scvfs(GridIndexType eIdx) const
577 { return scvfs_[eIdx]; }
578
579 //! If a vertex / d.o.f. is on the boundary
580 bool dofOnBoundary(GridIndexType dofIdx) const
581 { return boundaryDofIndices_[dofIdx]; }
582
583 //! If a vertex / d.o.f. is on a periodic boundary (not implemented)
584 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
585 { return false; }
586
587 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
588 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
589 { DUNE_THROW(Dune::NotImplemented, "Periodic boundaries"); }
590
591 //! Returns the map between dofs across periodic boundaries
592 [[deprecated("Will be removed after release 3.9. Implement periodicDofMap() if periodic bcs are supported.")]]
593 std::unordered_map<GridIndexType, GridIndexType> periodicVertexMap() const
594 { return std::unordered_map<GridIndexType, GridIndexType>{}; }
595
596 //! Returns whether one of the geometry's scvfs lies on a boundary
597 bool hasBoundaryScvf(GridIndexType eIdx) const
598 { return hasBoundaryScvf_[eIdx]; }
599
600 private:
601
602 template<class GridData>
603 void update_(const GridData& gridData)
604 {
605 PNMData::update(this->gridView(), gridData);
606
607 scvs_.clear();
608 scvfs_.clear();
609
610 auto numElements = this->gridView().size(0);
611 scvs_.resize(numElements);
612 scvfs_.resize(numElements);
613 hasBoundaryScvf_.resize(numElements, false);
614
615 boundaryDofIndices_.assign(numDofs(), false);
616
617 numScvf_ = numElements;
618 numScv_ = 2*numElements;
619
620 // Build the SCV and SCV faces
621 for (const auto& element : elements(this->gridView()))
622 {
623 // get the element geometry
624 auto eIdx = this->elementMapper().index(element);
625 auto elementGeometry = element.geometry();
626
627 // construct the sub control volumes
628 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < elementGeometry.corners(); ++scvLocalIdx)
629 {
630 const auto dofIdxGlobal = this->vertexMapper().subIndex(element, scvLocalIdx, dim);
631
632 // get the corners
633 auto corners = std::array{elementGeometry.corner(scvLocalIdx), elementGeometry.center()};
634
635 // get the fractional volume associated with the scv
636 const auto volume = this->poreVolume(dofIdxGlobal) / this->coordinationNumber(dofIdxGlobal);
637
638 scvs_[eIdx][scvLocalIdx] = SubControlVolume(dofIdxGlobal,
639 scvLocalIdx,
640 eIdx,
641 std::move(corners),
642 volume);
643
644 if (this->poreLabel(dofIdxGlobal) > 0)
645 {
646 if (boundaryDofIndices_[dofIdxGlobal])
647 continue;
648
649 boundaryDofIndices_[dofIdxGlobal] = true;
650 hasBoundaryScvf_[eIdx] = true;
651 }
652 }
653
654 // construct the inner sub control volume face
655 auto unitOuterNormal = elementGeometry.corner(1)-elementGeometry.corner(0);
656 unitOuterNormal /= unitOuterNormal.two_norm();
657 LocalIndexType scvfLocalIdx = 0;
658 scvfs_[eIdx][0] = SubControlVolumeFace(elementGeometry.center(),
659 std::move(unitOuterNormal),
660 this->throatCrossSectionalArea(this->elementMapper().index(element)),
661 scvfLocalIdx++,
662 std::array<LocalIndexType, 2>({0, 1}));
663 }
664 }
665
666 const FeCache feCache_;
667
668 std::vector<std::array<SubControlVolume, 2>> scvs_;
669 std::vector<std::array<SubControlVolumeFace, 1>> scvfs_;
670
671 std::size_t numScv_;
672 std::size_t numScvf_;
673
674 // vertices on the boundary
675 std::vector<bool> boundaryDofIndices_;
676 std::vector<bool> hasBoundaryScvf_;
677 };
678
679 /*!
680 * \ingroup PoreNetworkDiscretization
681 * \brief Base class for the finite volume geometry for porenetwork models
682 * \note For caching disabled we store only some essential index maps to build up local systems on-demand in
683 * the corresponding FVElementGeometry
684 */
685 template<class Scalar, class GV, class Traits>
686 class GridGeometry<Scalar, GV, false, Traits>
687 : public BaseGridGeometry<GV, Traits>
688 , public Traits::PNMData
689 {
690 using ThisType = GridGeometry<Scalar, GV, false, Traits>;
691 using ParentType = BaseGridGeometry<GV, Traits>;
692 using GridIndexType = typename IndexTraits<GV>::GridIndex;
693 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
694 using PNMData = typename Traits::PNMData;
695
696 static const int dim = GV::dimension;
697 static const int dimWorld = GV::dimensionworld;
698
699 using Element = typename GV::template Codim<0>::Entity;
700 using CoordScalar = typename GV::ctype;
701
702 public:
703 //! export the discretization method this geometry belongs to
704 using DiscretizationMethod = DiscretizationMethods::Box;
705 static constexpr DiscretizationMethod discMethod{};
706
707 //! export the type of the fv element geometry (the local view type)
708 using LocalView = typename Traits::template LocalView<ThisType, false>;
709 //! export the type of sub control volume
710 using SubControlVolume = typename Traits::SubControlVolume;
711 //! export the type of sub control volume
712 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
713 //! export the type of extrusion
714 using Extrusion = Extrusion_t<Traits>;
715 //! export dof mapper type
716 using DofMapper = typename Traits::VertexMapper;
717 //! export the finite element cache type
718 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
719 //! export the grid view type
720 using GridView = GV;
721
722 //! Constructor
723 template<class GridData>
724 22 GridGeometry(const GridView& gridView, const GridData& gridData)
725
2/6
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
22 : ParentType(gridView)
726 {
727 static_assert(GridView::dimension == 1, "Porenetwork model only allow GridView::dimension == 1!");
728
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 update_(gridData);
729 22 }
730
731
732 //! the vertex mapper is the dofMapper
733 //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa...
734 const DofMapper& dofMapper() const
735
9/32
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 501 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 501 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4880 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4880 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 5 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 6 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 6 times.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
21720024 { return this->vertexMapper(); }
736
737 //! The total number of sub control volumes
738 std::size_t numScv() const
739 { return numScv_; }
740
741 //! The total number of sun control volume faces
742 std::size_t numScvf() const
743 { return numScvf_; }
744
745 //! The total number of boundary sub control volume faces
746 //! For compatibility reasons with cc methods
747 std::size_t numBoundaryScvf() const
748 { return 0; }
749
750 //! The total number of degrees of freedom
751 std::size_t numDofs() const
752
55/99
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✓ Branch 17 taken 7 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 5 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✓ Branch 29 taken 2 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✓ Branch 35 taken 140 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 140 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 140 times.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 3 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 4 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 4 times.
✗ Branch 57 not taken.
✓ Branch 59 taken 4 times.
✗ Branch 60 not taken.
✓ Branch 62 taken 4 times.
✗ Branch 63 not taken.
✓ Branch 65 taken 4 times.
✗ Branch 66 not taken.
✓ Branch 68 taken 2 times.
✗ Branch 69 not taken.
✓ Branch 71 taken 2 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 2 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 1 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 1 times.
✗ Branch 81 not taken.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
✓ Branch 86 taken 1 times.
✗ Branch 87 not taken.
✓ Branch 89 taken 1 times.
✗ Branch 90 not taken.
✓ Branch 92 taken 1 times.
✗ Branch 93 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✓ Branch 98 taken 1 times.
✗ Branch 99 not taken.
✓ Branch 101 taken 1 times.
✗ Branch 102 not taken.
✓ Branch 104 taken 1 times.
✗ Branch 105 not taken.
✓ Branch 107 taken 1 times.
✗ Branch 108 not taken.
✓ Branch 110 taken 1 times.
✗ Branch 111 not taken.
✓ Branch 113 taken 1 times.
✗ Branch 114 not taken.
✓ Branch 116 taken 1 times.
✗ Branch 117 not taken.
✓ Branch 119 taken 1 times.
✗ Branch 120 not taken.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✓ Branch 125 taken 1 times.
✗ Branch 126 not taken.
✓ Branch 128 taken 1 times.
✗ Branch 129 not taken.
✓ Branch 131 taken 1 times.
✗ Branch 132 not taken.
708 { return this->vertexMapper().size(); }
753
754 //! update all fvElementGeometries (call this after grid adaption)
755 template<class GridData>
756 void update(const GridView& gridView, const GridData& gridData)
757 {
758
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 ParentType::update(gridView);
759
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 update_(gridData);
760 }
761
762 //! update all fvElementGeometries (call this after grid adaption)
763 template<class GridData>
764 void update(GridView&& gridView, const GridData& gridData)
765 {
766 ParentType::update(std::move(gridView));
767 update_(gridData);
768 }
769
770 //! The finite element cache for creating local FE bases
771 const FeCache& feCache() const
772 5427310 { return feCache_; }
773
774 //! If a vertex / d.o.f. is on the boundary
775 bool dofOnBoundary(GridIndexType dofIdx) const
776
12/12
✓ Branch 0 taken 222602 times.
✓ Branch 1 taken 2132830 times.
✓ Branch 2 taken 222602 times.
✓ Branch 3 taken 2132830 times.
✓ Branch 4 taken 85052 times.
✓ Branch 5 taken 855798 times.
✓ Branch 6 taken 85052 times.
✓ Branch 7 taken 855798 times.
✓ Branch 8 taken 496 times.
✓ Branch 9 taken 480 times.
✓ Branch 10 taken 496 times.
✓ Branch 11 taken 480 times.
6594516 { return boundaryDofIndices_[dofIdx]; }
777
778 //! If a vertex / d.o.f. is on a periodic boundary (not implemented)
779 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
780 { return false; }
781
782 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
783 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
784 { DUNE_THROW(Dune::NotImplemented, "Periodic boundaries"); }
785
786 //! Returns the map between dofs across periodic boundaries
787 [[deprecated("Will be removed after release 3.9. Implement periodicDofMap() if periodic bcs are supported.")]]
788 std::unordered_map<GridIndexType, GridIndexType> periodicVertexMap() const
789 { return std::unordered_map<GridIndexType, GridIndexType>{}; }
790
791 private:
792
793 template<class GridData>
794 24 void update_(const GridData& gridData)
795 {
796 48 PNMData::update(this->gridView(), gridData);
797
798 48 boundaryDofIndices_.assign(numDofs(), false);
799
800 // save global data on the grid's scvs and scvfs
801 48 numScvf_ = this->gridView().size(0);
802 24 numScv_ = 2*numScvf_;
803
804
4/4
✓ Branch 2 taken 42153 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 42153 times.
✓ Branch 5 taken 24 times.
42201 for (const auto& element : elements(this->gridView()))
805 {
806 // treat boundaries
807
2/2
✓ Branch 0 taken 84306 times.
✓ Branch 1 taken 42153 times.
126459 for (LocalIndexType vIdxLocal = 0; vIdxLocal < 2; ++vIdxLocal)
808 {
809 168612 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdxLocal, dim);
810
4/4
✓ Branch 0 taken 14154 times.
✓ Branch 1 taken 70152 times.
✓ Branch 2 taken 14154 times.
✓ Branch 3 taken 70152 times.
168612 if (this->poreLabel(vIdxGlobal) > 0)
811 {
812
6/6
✓ Branch 0 taken 4762 times.
✓ Branch 1 taken 9392 times.
✓ Branch 2 taken 4762 times.
✓ Branch 3 taken 9392 times.
✓ Branch 4 taken 4762 times.
✓ Branch 5 taken 9392 times.
42462 if (boundaryDofIndices_[vIdxGlobal])
813 continue;
814
815 14286 boundaryDofIndices_[vIdxGlobal] = true;
816 }
817 }
818 }
819 24 }
820
821 const FeCache feCache_;
822
823 // Information on the global number of geometries
824 std::size_t numScv_;
825 std::size_t numScvf_;
826
827 // vertices on the boundary
828 std::vector<bool> boundaryDofIndices_;
829 };
830
831 } // end namespace Dumux::PoreNetwork
832
833 #endif
834