GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/discretization/pq1bubble/fvgridgeometry.hh
Date: 2025-06-28 19:18:10
Exec Total Coverage
Lines: 110 113 97.3%
Functions: 32 32 100.0%
Branches: 127 239 53.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-FileCopyrightText: 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 PQ1BubbleDiscretization
10 * \brief Base class for the finite volume geometry vector for the pq1bubble method
11 * This builds up the sub control volumes and sub control volume faces
12 * for each element of the grid partition.
13 */
14 #ifndef DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH
15 #define DUMUX_DISCRETIZATION_PQ1BUBBLE_GRID_GEOMETRY_HH
16
17 #include <utility>
18 #include <unordered_map>
19 #include <type_traits>
20
21 #include <dune/grid/common/mcmgmapper.hh>
22
23 #include <dumux/discretization/method.hh>
24
25 #include <dumux/common/indextraits.hh>
26 #include <dumux/common/defaultmappertraits.hh>
27
28 #include <dumux/geometry/center.hh>
29 #include <dumux/geometry/volume.hh>
30
31 #include <dumux/discretization/basegridgeometry.hh>
32 #include <dumux/discretization/pq1bubble/geometryhelper.hh>
33 #include <dumux/discretization/pq1bubble/fvelementgeometry.hh>
34 #include <dumux/discretization/pq1bubble/subcontrolvolume.hh>
35 #include <dumux/discretization/pq1bubble/subcontrolvolumeface.hh>
36 #include <dumux/discretization/pq1bubble/pq1bubblefecache.hh>
37 #include <dumux/discretization/extrusion.hh>
38
39 #include <dumux/io/grid/periodicgridtraits.hh>
40
41 namespace Dumux {
42
43 namespace Detail {
44 template<class T>
45 using EnableHybridCVFE
46 = typename T::EnableHybridCVFE;
47
48 template<class T>
49 static constexpr bool enablesHybridCVFE
50 = Dune::Std::detected_or_t<std::false_type, EnableHybridCVFE, T>{};
51
52 template<class GV, class T>
53 using PQ1BubbleGeometryHelper_t = Dune::Std::detected_or_t<
54 std::conditional_t<enablesHybridCVFE<T>,
55 Dumux::HybridPQ1BubbleGeometryHelper<GV, typename T::SubControlVolume, typename T::SubControlVolumeFace>,
56 Dumux::PQ1BubbleGeometryHelper<GV, typename T::SubControlVolume, typename T::SubControlVolumeFace>
57 >,
58 SpecifiesGeometryHelper,
59 T
60 >;
61 } // end namespace Detail
62
63 template <class GridView>
64 struct PQ1BubbleMapperTraits :public DefaultMapperTraits<GridView>
65 {
66 using DofMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
67
68 /**
69 * \brief layout for elements and vertices
70 *
71 */
72 14 static Dune::MCMGLayout layout()
73 {
74
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 28 times.
88 return [](Dune::GeometryType gt, int dimgrid) {
75
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 32 times.
88 return (gt.dim() == dimgrid) || (gt.dim() == 0);
76
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 };
77 }
78 };
79
80 /*!
81 * \ingroup PQ1BubbleDiscretization
82 * \brief The default traits for the pq1bubble finite volume grid geometry
83 * Defines the scv and scvf types and the mapper types
84 * \tparam the grid view type
85 */
86 template<class GridView, class MapperTraits = PQ1BubbleMapperTraits<GridView>>
87 struct PQ1BubbleDefaultGridGeometryTraits
88 : public MapperTraits
89 {
90 using SubControlVolume = PQ1BubbleSubControlVolume<GridView>;
91 using SubControlVolumeFace = PQ1BubbleSubControlVolumeFace<GridView>;
92
93 template<class GridGeometry, bool enableCache>
94 using LocalView = PQ1BubbleFVElementGeometry<GridGeometry, enableCache>;
95 };
96
97 /*!
98 * \ingroup PQ1BubbleDiscretization
99 * \brief The default traits for the hybrid pq1bubble finite volume grid geometry
100 * Defines the scv and scvf types and the mapper types
101 * \tparam the grid view type
102 */
103 template<class BaseTraits>
104 struct HybridPQ1BubbleCVFEGridGeometryTraits
105 : public BaseTraits
106 { using EnableHybridCVFE = std::true_type; };
107
108 /*!
109 * \ingroup PQ1BubbleDiscretization
110 * \brief Base class for the finite volume geometry vector for pq1bubble schemes
111 * This builds up the sub control volumes and sub control volume faces
112 * \note For caching enabled we store the fv geometries for the whole grid view which is memory intensive but faster
113 */
114 template<class Scalar,
115 class GV,
116 bool enableCaching = true,
117 class Traits = PQ1BubbleDefaultGridGeometryTraits<GV>>
118 class PQ1BubbleFVGridGeometry
119 : public BaseGridGeometry<GV, Traits>
120 {
121 using ThisType = PQ1BubbleFVGridGeometry<Scalar, GV, enableCaching, Traits>;
122 using ParentType = BaseGridGeometry<GV, Traits>;
123 using GridIndexType = typename IndexTraits<GV>::GridIndex;
124 using LocalIndexType = typename IndexTraits<GV>::LocalIndex;
125
126 using Element = typename GV::template Codim<0>::Entity;
127 using CoordScalar = typename GV::ctype;
128 static const int dim = GV::dimension;
129 static const int dimWorld = GV::dimensionworld;
130
131 static_assert(dim > 1, "Only implemented for dim > 1");
132
133 public:
134 //! export the discretization method this geometry belongs to
135 using DiscretizationMethod = DiscretizationMethods::PQ1Bubble;
136 static constexpr DiscretizationMethod discMethod{};
137
138 static constexpr bool enableHybridCVFE = Detail::enablesHybridCVFE<Traits>;
139
140 //! export basic grid geometry type for the alternative constructor
141 using BasicGridGeometry = BasicGridGeometry_t<GV, Traits>;
142 //! export the type of the fv element geometry (the local view type)
143 using LocalView = typename Traits::template LocalView<ThisType, true>;
144 //! export the type of sub control volume
145 using SubControlVolume = typename Traits::SubControlVolume;
146 //! export the type of sub control volume
147 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
148 //! export the type of extrusion
149 using Extrusion = Extrusion_t<Traits>;
150 //! export dof mapper type
151 using DofMapper = typename Traits::DofMapper;
152 //! export the finite element cache type
153 using FeCache = Dumux::PQ1BubbleFECache<CoordScalar, Scalar, dim>;
154 //! export the grid view type
155 using GridView = GV;
156 //! export whether the grid(geometry) supports periodicity
157 using SupportsPeriodicity = typename PeriodicGridTraits<typename GV::Grid>::SupportsPeriodicity;
158
159 //! Constructor with basic grid geometry used to share state with another grid geometry on the same grid view
160 14 PQ1BubbleFVGridGeometry(std::shared_ptr<BasicGridGeometry> gg)
161 : ParentType(std::move(gg))
162
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 , dofMapper_(this->gridView(), Traits::layout())
163 14 , cache_(*this)
164
4/8
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 9 taken 14 times.
✗ Branch 10 not taken.
28 , periodicGridTraits_(this->gridView().grid())
165 {
166
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 update_();
167 14 }
168
169 //! Constructor
170 14 PQ1BubbleFVGridGeometry(const GridView& gridView)
171
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 : PQ1BubbleFVGridGeometry(std::make_shared<BasicGridGeometry>(gridView))
172 14 {}
173
174 //! The dofMapper
175 112070269 const DofMapper& dofMapper() const
176
7/12
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
4714113 { return dofMapper_; }
177
178 //! The total number of sub control volumes
179 std::size_t numScv() const
180 { return numScv_; }
181
182 //! The total number of sub control volume faces
183 std::size_t numScvf() const
184 { return numScvf_; }
185
186 //! The total number of boundary sub control volume faces
187 2 std::size_t numBoundaryScvf() const
188
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 { return numBoundaryScvf_; }
189
190 //! The total number of degrees of freedom
191 86 std::size_t numDofs() const
192
6/13
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 8 not taken.
73 { return this->dofMapper().size(); }
193
194 //! update all geometries (call this after grid adaption)
195 void update(const GridView& gridView)
196 {
197 ParentType::update(gridView);
198 update_();
199 }
200
201 //! update all geometries (call this after grid adaption)
202 void update(GridView&& gridView)
203 {
204 ParentType::update(std::move(gridView));
205 update_();
206 }
207
208 //! The finite element cache for creating local FE bases
209 19787966 const FeCache& feCache() const
210 19787966 { return feCache_; }
211
212 //! If a vertex / d.o.f. is on the boundary
213 2692076 bool dofOnBoundary(GridIndexType dofIdx) const
214
4/4
✓ Branch 0 taken 74970 times.
✓ Branch 1 taken 2501314 times.
✓ Branch 2 taken 2047 times.
✓ Branch 3 taken 113745 times.
2692076 { return boundaryDofIndices_[dofIdx]; }
215
216 //! If a vertex / d.o.f. is on a periodic boundary
217 72336 bool dofOnPeriodicBoundary(GridIndexType dofIdx) const
218
0/4
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
144672 { return periodicDofMap_.count(dofIdx); }
219
220 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
221 GridIndexType periodicallyMappedDof(GridIndexType dofIdx) const
222 { return periodicDofMap_.at(dofIdx); }
223
224 //! Returns the map between dofs across periodic boundaries
225 const std::unordered_map<GridIndexType, GridIndexType>& periodicDofMap() const
226 25 { return periodicDofMap_; }
227
228 //! local view of this object (constructed with the internal cache)
229 1363076 friend inline LocalView localView(const PQ1BubbleFVGridGeometry& gg)
230
13/17
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 6 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1 times.
✓ Branch 8 taken 4801 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 21601 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 21604 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 42002 times.
✓ Branch 7 taken 903 times.
✓ Branch 10 taken 4 times.
✓ Branch 13 taken 2 times.
840964 { return { gg.cache_ }; }
231
232 private:
233 class PQ1BubbleGridGeometryCache
234 {
235 friend class PQ1BubbleFVGridGeometry;
236 public:
237 //! export the geometry helper type
238 using GeometryHelper = Detail::PQ1BubbleGeometryHelper_t<GV, Traits>;
239
240 14 explicit PQ1BubbleGridGeometryCache(const PQ1BubbleFVGridGeometry& gg)
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 : gridGeometry_(&gg)
242 {}
243
244 135326286 const PQ1BubbleFVGridGeometry& gridGeometry() const
245
12/16
✓ Branch 1 taken 66114 times.
✓ Branch 2 taken 100622 times.
✓ Branch 12 taken 4412 times.
✓ Branch 13 taken 9600 times.
✓ Branch 15 taken 5052 times.
✗ Branch 16 not taken.
✓ Branch 10 taken 7200 times.
✗ Branch 11 not taken.
✓ Branch 3 taken 203864 times.
✓ Branch 0 taken 1580 times.
✓ Branch 9 taken 4800 times.
✗ Branch 14 not taken.
✓ Branch 4 taken 41160 times.
✓ Branch 5 taken 2177904 times.
✓ Branch 18 taken 1920 times.
✗ Branch 19 not taken.
132465762 { return *gridGeometry_; }
246
247 //! Get the global sub control volume indices of an element
248 114378189 const std::vector<SubControlVolume>& scvs(GridIndexType eIdx) const
249
4/5
✓ Branch 1 taken 7406 times.
✓ Branch 2 taken 921130 times.
✓ Branch 3 taken 56830 times.
✓ Branch 4 taken 231314 times.
✗ Branch 5 not taken.
113789177 { return scvs_[eIdx]; }
250
251 //! Get the global sub control volume face indices of an element
252 5645311 const std::vector<SubControlVolumeFace>& scvfs(GridIndexType eIdx) const
253
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 12000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 2 not taken.
5500451 { return scvfs_[eIdx]; }
254
255 //! Returns whether one of the geometry's scvfs lies on a boundary
256 42775 bool hasBoundaryScvf(GridIndexType eIdx) const
257
2/4
✓ Branch 0 taken 1362 times.
✓ Branch 1 taken 41413 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
42775 { return hasBoundaryScvf_[eIdx]; }
258
259 //! Local mappings necessary to construct geometries of scvfs
260 664 const std::vector<std::array<LocalIndexType, 2>>& scvfBoundaryGeometryKeys(GridIndexType eIdx) const
261 664 { return scvfBoundaryGeometryKeys_.at(eIdx); }
262
263 private:
264 14 void clear_()
265 {
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 scvs_.clear();
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 scvfs_.clear();
268 14 hasBoundaryScvf_.clear();
269 14 scvfBoundaryGeometryKeys_.clear();
270 14 }
271
272 std::vector<std::vector<SubControlVolume>> scvs_;
273 std::vector<std::vector<SubControlVolumeFace>> scvfs_;
274 std::vector<bool> hasBoundaryScvf_;
275 std::unordered_map<GridIndexType, std::vector<std::array<LocalIndexType, 2>>> scvfBoundaryGeometryKeys_;
276
277 const PQ1BubbleFVGridGeometry* gridGeometry_;
278 };
279
280 public:
281 //! the cache type (only the caching implementation has this)
282 //! this alias should only be used by the local view implementation
283 using Cache = PQ1BubbleGridGeometryCache;
284
285 private:
286 using GeometryHelper = typename Cache::GeometryHelper;
287
288 14 void update_()
289 {
290 14 cache_.clear_();
291 14 dofMapper_.update(this->gridView());
292
293 14 auto numElements = this->gridView().size(0);
294 14 cache_.scvs_.resize(numElements);
295 14 cache_.scvfs_.resize(numElements);
296 14 cache_.hasBoundaryScvf_.resize(numElements, false);
297
298 14 boundaryDofIndices_.assign(numDofs(), false);
299
300 14 numScv_ = 0;
301 14 numScvf_ = 0;
302 14 numBoundaryScvf_ = 0;
303
304 // Build the scvs and scv faces
305
6/9
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 12000 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12000 times.
✓ Branch 11 taken 3 times.
✓ Branch 1 taken 111266 times.
156385 for (const auto& element : elements(this->gridView()))
306 {
307
2/4
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
123261 auto eIdx = this->elementMapper().index(element);
308
309 // get the element geometry
310
1/2
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
123261 auto elementGeometry = element.geometry();
311
1/2
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
123261 const auto refElement = referenceElement(elementGeometry);
312
313 // instantiate the geometry helper
314
1/2
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
123261 GeometryHelper geometryHelper(elementGeometry);
315
316 123261 numScv_ += geometryHelper.numScv();
317 // construct the sub control volumes
318
2/4
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
123261 cache_.scvs_[eIdx].resize(geometryHelper.numScv());
319
320 // Scvs related to control volumes
321
4/4
✓ Branch 1 taken 559813 times.
✓ Branch 2 taken 111261 times.
✓ Branch 3 taken 49600 times.
✓ Branch 4 taken 12000 times.
671074 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < geometryHelper.numScv(); ++scvLocalIdx)
322 {
323
1/2
✓ Branch 1 taken 49600 times.
✗ Branch 2 not taken.
547813 auto corners = geometryHelper.getScvCorners(scvLocalIdx);
324 547813 cache_.scvs_[eIdx][scvLocalIdx] = SubControlVolume(
325
1/2
✓ Branch 1 taken 22069 times.
✗ Branch 2 not taken.
547813 geometryHelper.scvVolume(scvLocalIdx, corners),
326 1095626 geometryHelper.dofPosition(scvLocalIdx),
327
1/2
✓ Branch 1 taken 547813 times.
✗ Branch 2 not taken.
1095626 Dumux::center(corners),
328 scvLocalIdx,
329 eIdx,
330 547813 GeometryHelper::dofIndex(this->dofMapper(), element, scvLocalIdx),
331
1/2
✓ Branch 1 taken 49600 times.
✗ Branch 2 not taken.
547813 geometryHelper.isOverlappingScv(scvLocalIdx)
332 );
333 }
334
335 // construct the sub control volume faces
336
1/2
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
123261 const auto numInteriorScvfs = GeometryHelper::numInteriorScvf(elementGeometry.type());
337 123261 numScvf_ += numInteriorScvfs;
338
1/2
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
123261 cache_.scvfs_[eIdx].resize(numInteriorScvfs);
339 123261 LocalIndexType scvfLocalIdx = 0;
340
2/2
✓ Branch 0 taken 857932 times.
✓ Branch 1 taken 123261 times.
981193 for (; scvfLocalIdx < numInteriorScvfs; ++scvfLocalIdx)
341 {
342
1/2
✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
857932 const auto scvPair = geometryHelper.getScvPairForScvf(scvfLocalIdx);
343
1/2
✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
857932 const auto corners = geometryHelper.getScvfCorners(scvfLocalIdx);
344 857932 const auto area = Dumux::convexPolytopeVolume<dim-1>(
345 geometryHelper.getInteriorScvfGeometryType(scvfLocalIdx),
346
1/2
✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
1760004 [&](unsigned int i){ return corners[i]; }
347 );
348
349 857932 cache_.scvfs_[eIdx][scvfLocalIdx] = SubControlVolumeFace(
350 857932 Dumux::center(corners),
351 area,
352 857932 geometryHelper.normal(corners, scvPair),
353 std::move(scvPair),
354 scvfLocalIdx,
355
2/4
✓ Branch 1 taken 75200 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75200 times.
✗ Branch 5 not taken.
1715864 geometryHelper.isOverlappingScvf(scvfLocalIdx)
356 );
357 }
358
359 // construct the sub control volume faces on the domain boundary
360
7/9
✓ Branch 2 taken 174566 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 91746 times.
✓ Branch 6 taken 132420 times.
✓ Branch 7 taken 392704 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18358 times.
✓ Branch 10 taken 284186 times.
✓ Branch 1 taken 33101 times.
1305696 for (const auto& intersection : intersections(this->gridView(), element))
361 {
362
3/4
✓ Branch 0 taken 7452 times.
✓ Branch 1 taken 119840 times.
✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
127872 if (intersection.boundary() && !intersection.neighbor())
363 {
364
1/2
✓ Branch 1 taken 5866 times.
✗ Branch 2 not taken.
7452 cache_.hasBoundaryScvf_[eIdx] = true;
365
366 7452 const auto localFacetIndex = intersection.indexInInside();
367
2/4
✓ Branch 1 taken 5866 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5286 times.
✗ Branch 5 not taken.
7452 const auto numBoundaryScvf = GeometryHelper::numBoundaryScvf(elementGeometry.type(), localFacetIndex);
368 7452 numScvf_ += numBoundaryScvf;
369 7452 numBoundaryScvf_ += numBoundaryScvf;
370
371
2/2
✓ Branch 0 taken 17430 times.
✓ Branch 1 taken 7452 times.
24882 for (unsigned int isScvfLocalIdx = 0; isScvfLocalIdx < numBoundaryScvf; ++isScvfLocalIdx)
372 {
373 // find the scvs this scvf is belonging to
374
1/2
✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
17430 const auto scvPair = geometryHelper.getScvPairForBoundaryScvf(localFacetIndex, isScvfLocalIdx);
375
1/2
✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
17430 const auto corners = geometryHelper.getBoundaryScvfCorners(localFacetIndex, isScvfLocalIdx);
376 17430 const auto area = Dumux::convexPolytopeVolume<dim-1>(
377 geometryHelper.getBoundaryScvfGeometryType(isScvfLocalIdx),
378 42426 [&](unsigned int i){ return corners[i]; }
379 );
380
3/5
✓ Branch 1 taken 14678 times.
✓ Branch 2 taken 2752 times.
✓ Branch 4 taken 5544 times.
✗ Branch 5 not taken.
✗ Branch 3 not taken.
17430 cache_.scvfs_[eIdx].emplace_back(
381 34860 Dumux::center(corners),
382 area,
383
1/2
✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
17430 intersection.centerUnitOuterNormal(),
384 std::move(scvPair),
385 scvfLocalIdx,
386 typename SubControlVolumeFace::Traits::BoundaryFlag{ intersection },
387
1/2
✓ Branch 1 taken 13086 times.
✗ Branch 2 not taken.
17430 geometryHelper.isOverlappingBoundaryScvf(localFacetIndex)
388 );
389
390 // store look-up map to construct boundary scvf geometries
391
2/4
✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14246 times.
✗ Branch 5 not taken.
17430 cache_.scvfBoundaryGeometryKeys_[eIdx].emplace_back(std::array<LocalIndexType, 2>{{
392 static_cast<LocalIndexType>(localFacetIndex),
393 static_cast<LocalIndexType>(isScvfLocalIdx)
394 }});
395
396 // increment local counter
397 17430 scvfLocalIdx++;
398 }
399
400 // TODO also move this to helper class
401 // add all vertices on the intersection to the set of boundary vertices
402
2/2
✓ Branch 0 taken 17430 times.
✓ Branch 1 taken 7452 times.
24882 for (int localVIdx = 0; localVIdx < numBoundaryScvf; ++localVIdx)
403 {
404 17430 const auto vIdx = refElement.subEntity(localFacetIndex, 1, localVIdx, dim);
405
1/2
✓ Branch 1 taken 14246 times.
✗ Branch 2 not taken.
17430 const auto vIdxGlobal = this->dofMapper().subIndex(element, vIdx, dim);
406 17430 boundaryDofIndices_[vIdxGlobal] = true;
407 }
408 }
409
410 // inform the grid geometry if we have periodic boundaries
411
1/2
✓ Branch 1 taken 340144 times.
✗ Branch 2 not taken.
424550 else if (periodicGridTraits_.isPeriodic(intersection))
412 {
413 this->setPeriodic();
414
415 // find the mapped periodic vertex of all vertices on periodic boundaries
416 const auto fIdx = intersection.indexInInside();
417 const auto numFaceVerts = refElement.size(fIdx, 1, dim);
418 const auto eps = 1e-7*(elementGeometry.corner(1) - elementGeometry.corner(0)).two_norm();
419 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
420 {
421 const auto vIdx = refElement.subEntity(fIdx, 1, localVIdx, dim);
422 const auto vIdxGlobal = this->dofMapper().subIndex(element, vIdx, dim);
423 const auto vPos = elementGeometry.corner(vIdx);
424
425 const auto& outside = intersection.outside();
426 const auto outsideGeometry = outside.geometry();
427 for (const auto& isOutside : intersections(this->gridView(), outside))
428 {
429 // only check periodic vertices of the periodic neighbor
430 if (periodicGridTraits_.isPeriodic(isOutside))
431 {
432 const auto fIdxOutside = isOutside.indexInInside();
433 const auto numFaceVertsOutside = refElement.size(fIdxOutside, 1, dim);
434 for (int localVIdxOutside = 0; localVIdxOutside < numFaceVertsOutside; ++localVIdxOutside)
435 {
436 const auto vIdxOutside = refElement.subEntity(fIdxOutside, 1, localVIdxOutside, dim);
437 const auto vPosOutside = outsideGeometry.corner(vIdxOutside);
438 const auto shift = std::abs((this->bBoxMax()-this->bBoxMin())*intersection.centerUnitOuterNormal());
439 if (std::abs((vPosOutside-vPos).two_norm() - shift) < eps)
440 periodicDofMap_[vIdxGlobal] = this->dofMapper().subIndex(outside, vIdxOutside, dim);
441 }
442 }
443 }
444 }
445 }
446 }
447 }
448
449 // error check: periodic boundaries currently don't work for pq1bubble in parallel
450
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
14 if (this->isPeriodic() && this->gridView().comm().size() > 1)
451 DUNE_THROW(Dune::NotImplemented, "Periodic boundaries for pq1bubble method for parallel simulations!");
452 14 }
453
454 DofMapper dofMapper_;
455
456 const FeCache feCache_;
457
458 std::size_t numScv_;
459 std::size_t numScvf_;
460 std::size_t numBoundaryScvf_;
461
462 // vertices on the boundary
463 std::vector<bool> boundaryDofIndices_;
464
465 // a map for periodic boundary vertices
466 std::unordered_map<GridIndexType, GridIndexType> periodicDofMap_;
467
468 Cache cache_;
469
470 PeriodicGridTraits<typename GridView::Grid> periodicGridTraits_;
471 };
472
473 } // end namespace Dumux
474
475 #endif
476