GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/porousmediumflow/boxdfm/fvgridgeometry.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 51 52 98.1%
Functions: 15 15 100.0%
Branches: 62 129 48.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 BoxDFMModel
10 * \brief Base class for the finite volume geometry vector for box schemes that consider
11 * extra connectivity between grid vertices on marked codim one entities.
12 *
13 * On these, an additional scvf is created accounting for the additional exchange fluxes
14 * between these degrees of freedom.
15 */
16
17 #ifndef DUMUX_POROUSMEDIUMFLOW_BOXDFM_GRID_FVGEOMETRY_HH
18 #define DUMUX_POROUSMEDIUMFLOW_BOXDFM_GRID_FVGEOMETRY_HH
19
20 #include <utility>
21 #include <unordered_map>
22
23 #include <dune/localfunctions/lagrange/lagrangelfecache.hh>
24 #include <dune/geometry/multilineargeometry.hh>
25 #include <dune/grid/common/mcmgmapper.hh>
26
27 #include <dumux/discretization/method.hh>
28 #include <dumux/common/defaultmappertraits.hh>
29 #include <dumux/discretization/basegridgeometry.hh>
30 #include <dumux/discretization/box/boxgeometryhelper.hh>
31 #include <dumux/discretization/extrusion.hh>
32
33 #include "fvelementgeometry.hh"
34 #include "geometryhelper.hh"
35 #include "subcontrolvolume.hh"
36 #include "subcontrolvolumeface.hh"
37
38 namespace Dumux {
39
40 namespace Detail {
41 template<class GV, class T>
42 using BoxDfmGeometryHelper_t = Dune::Std::detected_or_t<
43 Dumux::BoxDfmGeometryHelper<GV, GV::dimension, typename T::SubControlVolume, typename T::SubControlVolumeFace>,
44 SpecifiesGeometryHelper,
45 T
46 >;
47 } // end namespace Detail
48
49 /*!
50 * \ingroup BoxDFMModel
51 * \brief The default traits for the box finite volume grid geometry
52 *
53 * Defines the scv and scvf types and the mapper types.
54 *
55 * \tparam the grid view type
56 */
57 template<class GridView, class MapperTraits = DefaultMapperTraits<GridView>>
58 struct BoxDfmDefaultGridGeometryTraits
59 : public MapperTraits
60 {
61 using SubControlVolume = BoxDfmSubControlVolume<GridView>;
62 using SubControlVolumeFace = BoxDfmSubControlVolumeFace<GridView>;
63
64 template<class GridGeometry, bool enableCache>
65 using LocalView = BoxDfmFVElementGeometry<GridGeometry, enableCache>;
66
67 // Mapper type for mapping edges
68 using FacetMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
69 };
70
71 /*!
72 * \ingroup BoxDFMModel
73 * \brief Base class for the finite volume geometry vector for box schemes
74 *
75 * This builds up the sub control volumes and sub control volume faces
76 *
77 * \note This class is specialized for versions with and without caching the fv geometries on the grid view
78 */
79 template<class Scalar,
80 class GridView,
81 bool enableGridGeometryCache = false,
82 class Traits = BoxDfmDefaultGridGeometryTraits<GridView> >
83 class BoxDfmFVGridGeometry;
84
85 /*!
86 * \ingroup BoxDFMModel
87 * \brief Base class for the finite volume geometry vector for box schemes that consider
88 * extra connectivity between grid vertices on marked codim one entities.
89 *
90 * On these, an additional scvf is created accounting for the additional exchange fluxes
91 * between these degrees of freedom.
92 *
93 * \note For caching enabled we store the fv geometries for the whole grid view which is memory intensive but faster
94 */
95 template<class Scalar, class GV, class Traits>
96 class BoxDfmFVGridGeometry<Scalar, GV, true, Traits>
97 : public BaseGridGeometry<GV, Traits>
98 {
99 using ThisType = BoxDfmFVGridGeometry<Scalar, GV, true, Traits>;
100 using ParentType = BaseGridGeometry<GV, Traits>;
101 using GridIndexType = typename GV::IndexSet::IndexType;
102
103 using Element = typename GV::template Codim<0>::Entity;
104 using CoordScalar = typename GV::ctype;
105 static const int dim = GV::dimension;
106 static const int dimWorld = GV::dimensionworld;
107 static_assert(dim == 2 || dim == 3, "The box-dfm GridGeometry is only implemented in 2 or 3 dimensions.");
108
109 public:
110 //! export the discretization method this geometry belongs to
111 using DiscretizationMethod = DiscretizationMethods::Box;
112 static constexpr DiscretizationMethod discMethod{};
113
114 //! Export the type of the fv element geometry (the local view type)
115 using LocalView = typename Traits::template LocalView<ThisType, true>;
116 //! Export the type of sub control volume
117 using SubControlVolume = typename Traits::SubControlVolume;
118 //! Export the type of sub control volume
119 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
120 //! Export the extrusion type
121 using Extrusion = Extrusion_t<Traits>;
122 //! Export dof mapper type
123 using DofMapper = typename Traits::VertexMapper;
124 //! Export the finite element cache type
125 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
126 //! Export the grid view type
127 using GridView = GV;
128 //! export the geometry helper type
129 using GeometryHelper = Detail::BoxDfmGeometryHelper_t<GV, Traits>;
130
131 //! Constructor
132 template< class FractureGridAdapter >
133 BoxDfmFVGridGeometry(const GridView gridView, const FractureGridAdapter& fractureGridAdapter)
134 : ParentType(gridView)
135 {
136 update_(fractureGridAdapter);
137 }
138
139 //! The vertex mapper is the dofMapper
140 //! This is convenience to have better chance to have the same main files for box/tpfa/mpfa...
141 const DofMapper& dofMapper() const
142 { return this->vertexMapper(); }
143
144 //! The total number of sub control volumes
145 std::size_t numScv() const
146 { return numScv_; }
147
148 //! The total number of sun control volume faces
149 std::size_t numScvf() const
150 { return numScvf_; }
151
152 //! The total number of boundary sub control volume faces
153 //! For compatibility reasons with cc methods
154 std::size_t numBoundaryScvf() const
155 { return numBoundaryScvf_; }
156
157 //! The total number of degrees of freedom
158 std::size_t numDofs() const
159 { return this->gridView().size(dim); }
160
161 //! update all fvElementGeometries (call this after grid adaption)
162 template< class FractureGridAdapter >
163 void update(const GridView& gridView, const FractureGridAdapter& fractureGridAdapter)
164 {
165 ParentType::update(gridView);
166 update_(fractureGridAdapter);
167 }
168
169 //! update all fvElementGeometries (call this after grid adaption)
170 template< class FractureGridAdapter >
171 void update(GridView&& gridView, const FractureGridAdapter& fractureGridAdapter)
172 {
173 ParentType::update(std::move(gridView));
174 update_(fractureGridAdapter);
175 }
176
177 //! The finite element cache for creating local FE bases
178 const FeCache& feCache() const { return feCache_; }
179 //! Get the local scvs for an element
180 const std::vector<SubControlVolume>& scvs(GridIndexType eIdx) const { return scvs_[eIdx]; }
181 //! Get the local scvfs for an element
182 const std::vector<SubControlVolumeFace>& scvfs(GridIndexType eIdx) const { return scvfs_[eIdx]; }
183 //! If a vertex / d.o.f. is on the boundary
184 bool dofOnBoundary(unsigned int dofIdx) const { return boundaryDofIndices_[dofIdx]; }
185 //! If a vertex / d.o.f. is on a fracture
186 bool dofOnFracture(unsigned int dofIdx) const { return fractureDofIndices_[dofIdx]; }
187 //! Periodic boundaries are not supported for the box-dfm scheme
188 bool dofOnPeriodicBoundary(std::size_t dofIdx) const { return false; }
189
190 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
191 std::size_t periodicallyMappedDof(std::size_t dofIdx) const
192 { DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme"); }
193
194 private:
195
196 template< class FractureGridAdapter >
197 void update_(const FractureGridAdapter& fractureGridAdapter)
198 {
199 scvs_.clear();
200 scvfs_.clear();
201
202 auto numElements = this->gridView().size(0);
203 scvs_.resize(numElements);
204 scvfs_.resize(numElements);
205
206 boundaryDofIndices_.assign(numDofs(), false);
207 fractureDofIndices_.assign(this->gridView.size(dim), false);
208
209 numScv_ = 0;
210 numScvf_ = 0;
211 numBoundaryScvf_ = 0;
212 // Build the SCV and SCV faces
213 for (const auto& element : elements(this->gridView()))
214 {
215 // fill the element map with seeds
216 auto eIdx = this->elementMapper().index(element);
217
218 // count
219 numScv_ += element.subEntities(dim);
220 numScvf_ += element.subEntities(dim-1);
221
222 // get the element geometry
223 auto elementGeometry = element.geometry();
224 const auto refElement = referenceElement(elementGeometry);
225
226 // instantiate the geometry helper
227 GeometryHelper geometryHelper(elementGeometry);
228
229 // construct the sub control volumes
230 scvs_[eIdx].resize(elementGeometry.corners());
231 using LocalIndexType = typename SubControlVolumeFace::Traits::LocalIndexType;
232 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < elementGeometry.corners(); ++scvLocalIdx)
233 {
234 const auto dofIdxGlobal = this->vertexMapper().subIndex(element, scvLocalIdx, dim);
235
236 scvs_[eIdx][scvLocalIdx] = SubControlVolume(geometryHelper,
237 scvLocalIdx,
238 eIdx,
239 dofIdxGlobal);
240 }
241
242 // construct the sub control volume faces
243 LocalIndexType scvfLocalIdx = 0;
244 scvfs_[eIdx].resize(element.subEntities(dim-1));
245 for (; scvfLocalIdx < element.subEntities(dim-1); ++scvfLocalIdx)
246 {
247 // find the global and local scv indices this scvf is belonging to
248 std::vector<LocalIndexType> localScvIndices({static_cast<LocalIndexType>(refElement.subEntity(scvfLocalIdx, dim-1, 0, dim)),
249 static_cast<LocalIndexType>(refElement.subEntity(scvfLocalIdx, dim-1, 1, dim))});
250
251 scvfs_[eIdx][scvfLocalIdx] = SubControlVolumeFace(geometryHelper,
252 element,
253 elementGeometry,
254 scvfLocalIdx,
255 std::move(localScvIndices));
256 }
257
258 // construct the ...
259 // ... sub-control volume faces on the domain boundary
260 // ... sub-control volumes on fracture facets
261 // ... sub-control volume faces on fracture facets
262 // NOTE We do not construct fracture scvfs on boundaries here!
263 // That means specifying Neumann fluxes on only the fractures is not possible
264 // However, it is difficult to interpret this here as a fracture ending on the boundary
265 // could also be connected to a facet which is both boundary and fracture at the same time!
266 // In that case, the fracture boundary scvf wouldn't make sense. In order to do it properly
267 // we would have to find only those fractures that are at the boundary and aren't connected
268 // to a fracture which is a boundary.
269 LocalIndexType scvLocalIdx = element.subEntities(dim);
270 for (const auto& intersection : intersections(this->gridView(), element))
271 {
272 // first, obtain all vertex indices on this intersection
273 const auto& isGeometry = intersection.geometry();
274 const auto numCorners = isGeometry.corners();
275 const auto idxInInside = intersection.indexInInside();
276
277 std::vector<GridIndexType> isVertexIndices(numCorners);
278 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
279 isVertexIndices[vIdxLocal] = this->vertexMapper().subIndex(element,
280 refElement.subEntity(idxInInside, 1, vIdxLocal, dim),
281 dim);
282 // maybe add boundary scvf
283 if (intersection.boundary() && !intersection.neighbor())
284 {
285 numScvf_ += isGeometry.corners();
286 numBoundaryScvf_ += isGeometry.corners();
287
288 for (unsigned int isScvfLocalIdx = 0; isScvfLocalIdx < numCorners; ++isScvfLocalIdx)
289 {
290 // find the scvs this scvf is belonging to
291 const LocalIndexType insideScvIdx = static_cast<LocalIndexType>(refElement.subEntity(idxInInside, 1, isScvfLocalIdx, dim));
292 std::vector<LocalIndexType> localScvIndices = {insideScvIdx, insideScvIdx};
293 scvfs_[eIdx].emplace_back(geometryHelper,
294 intersection,
295 isGeometry,
296 isScvfLocalIdx,
297 scvfLocalIdx++,
298 std::move(localScvIndices));
299 }
300
301 // add all vertices on the intersection to the set of
302 // boundary vertices
303 const auto numFaceVerts = refElement.size(idxInInside, 1, dim);
304 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
305 {
306 const auto vIdx = refElement.subEntity(idxInInside, 1, localVIdx, dim);
307 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdx, dim);
308 boundaryDofIndices_[vIdxGlobal] = true;
309 }
310 }
311 // make sure we have no periodic boundaries
312 else if (intersection.boundary() && intersection.neighbor())
313 DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme");
314
315 // maybe add fracture scvs & scvfs
316 if (fractureGridAdapter.composeFacetElement(isVertexIndices))
317 {
318 for (auto vIdx : isVertexIndices)
319 fractureDofIndices_[vIdx] = true;
320
321 // add fracture scv for each vertex of intersection
322 numScv_ += numCorners;
323 const auto curNumScvs = scvs_[eIdx].size();
324 scvs_[eIdx].reserve(curNumScvs+numCorners);
325 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
326 scvs_[eIdx].emplace_back(geometryHelper,
327 intersection,
328 isGeometry,
329 vIdxLocal,
330 static_cast<LocalIndexType>(refElement.subEntity(idxInInside, 1, vIdxLocal, dim)),
331 scvLocalIdx++,
332 idxInInside,
333 eIdx,
334 isVertexIndices[vIdxLocal]);
335
336 // add fracture scvf for each edge of the intersection in 3d
337 if (dim == 3)
338 {
339 const auto& faceRefElement = referenceElement(isGeometry);
340 for (unsigned int edgeIdx = 0; edgeIdx < faceRefElement.size(1); ++edgeIdx)
341 {
342 // inside/outside scv indices in face local node numbering
343 std::vector<LocalIndexType> localScvIndices({static_cast<LocalIndexType>(faceRefElement.subEntity(edgeIdx, 1, 0, dim-1)),
344 static_cast<LocalIndexType>(faceRefElement.subEntity(edgeIdx, 1, 1, dim-1))});
345
346 // add offset to get the right scv indices
347 std::for_each( localScvIndices.begin(),
348 localScvIndices.end(),
349 [curNumScvs] (auto& elemLocalIdx) { elemLocalIdx += curNumScvs; } );
350
351 // add scvf
352 numScvf_++;
353 scvfs_[eIdx].emplace_back(geometryHelper,
354 intersection,
355 isGeometry,
356 edgeIdx,
357 scvfLocalIdx++,
358 std::move(localScvIndices),
359 intersection.boundary());
360 }
361 }
362
363 // dim == 2, intersection is an edge, make 1 scvf
364 else
365 {
366 // inside/outside scv indices in face local node numbering
367 std::vector<LocalIndexType> localScvIndices({0, 1});
368
369 // add offset such that the fracture scvs above are addressed
370 std::for_each( localScvIndices.begin(),
371 localScvIndices.end(),
372 [curNumScvs] (auto& elemLocalIdx) { elemLocalIdx += curNumScvs; } );
373
374 // add scvf
375 numScvf_++;
376 scvfs_[eIdx].emplace_back(geometryHelper,
377 intersection,
378 isGeometry,
379 /*idxOnIntersection*/0,
380 scvfLocalIdx++,
381 std::move(localScvIndices),
382 intersection.boundary());
383 }
384 }
385 }
386 }
387 }
388
389 const FeCache feCache_;
390
391 std::vector<std::vector<SubControlVolume>> scvs_;
392 std::vector<std::vector<SubControlVolumeFace>> scvfs_;
393
394 // TODO do we need those?
395 std::size_t numScv_;
396 std::size_t numScvf_;
397 std::size_t numBoundaryScvf_;
398
399 // vertices on the boundary & fracture facets
400 std::vector<bool> boundaryDofIndices_;
401 std::vector<bool> fractureDofIndices_;
402 };
403
404 /*!
405 * \ingroup BoxDFMModel
406 * \brief Base class for the finite volume geometry vector for box schemes
407 * This builds up the sub control volumes and sub control volume faces
408 * \note For caching disabled we store only some essential index maps to build up local systems on-demand in
409 * the corresponding FVElementGeometry
410 */
411 template<class Scalar, class GV, class Traits>
412 class BoxDfmFVGridGeometry<Scalar, GV, false, Traits>
413 : public BaseGridGeometry<GV, Traits>
414 {
415 using ThisType = BoxDfmFVGridGeometry<Scalar, GV, false, Traits>;
416 using ParentType = BaseGridGeometry<GV, Traits>;
417 using GridIndexType = typename GV::IndexSet::IndexType;
418
419 static const int dim = GV::dimension;
420 static const int dimWorld = GV::dimensionworld;
421
422 using Element = typename GV::template Codim<0>::Entity;
423 using Intersection = typename GV::Intersection;
424 using CoordScalar = typename GV::ctype;
425
426 public:
427 //! export the discretization method this geometry belongs to
428 using DiscretizationMethod = DiscretizationMethods::Box;
429 static constexpr DiscretizationMethod discMethod{};
430
431 //! export the type of the fv element geometry (the local view type)
432 using LocalView = typename Traits::template LocalView<ThisType, false>;
433 //! export the type of sub control volume
434 using SubControlVolume = typename Traits::SubControlVolume;
435 //! export the type of sub control volume
436 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
437 //! Export the extrusion type
438 using Extrusion = Extrusion_t<Traits>;
439 //! export dof mapper type
440 using DofMapper = typename Traits::VertexMapper;
441 //! export the finite element cache type
442 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
443 //! export the grid view type
444 using GridView = GV;
445 //! export the geometry helper type
446 using GeometryHelper = Detail::BoxDfmGeometryHelper_t<GV, Traits>;
447
448 //! Constructor
449 template< class FractureGridAdapter >
450 6 BoxDfmFVGridGeometry(const GridView gridView, const FractureGridAdapter& fractureGridAdapter)
451 : ParentType(gridView)
452
3/6
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
12 , facetMapper_(gridView, Dune::mcmgLayout(Dune::template Codim<1>()))
453 {
454
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 update_(fractureGridAdapter);
455 6 }
456
457 //! the vertex mapper is the dofMapper
458 //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa...
459 20749014 const DofMapper& dofMapper() const
460
4/16
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
20749014 { return this->vertexMapper(); }
461
462 //! The total number of sub control volumes
463 std::size_t numScv() const
464 { return numScv_; }
465
466 //! The total number of sun control volume faces
467 std::size_t numScvf() const
468 { return numScvf_; }
469
470 //! The total number of boundary sub control volume faces
471 //! For compatibility reasons with cc methods
472 std::size_t numBoundaryScvf() const
473 { return numBoundaryScvf_; }
474
475 //! The total number of degrees of freedom
476 48 std::size_t numDofs() const
477
2/4
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
30 { return this->gridView().size(dim); }
478
479 //! update all fvElementGeometries (call this after grid adaption)
480 template< class FractureGridAdapter >
481 void update(const GridView& gridView, const FractureGridAdapter& fractureGridAdapter)
482 {
483 ParentType::update(gridView);
484 updateFacetMapper_();
485 update_(fractureGridAdapter);
486 }
487
488 //! update all fvElementGeometries (call this after grid adaption)
489 template< class FractureGridAdapter >
490 void update(GridView&& gridView, const FractureGridAdapter& fractureGridAdapter)
491 {
492 ParentType::update(std::move(gridView));
493 updateFacetMapper_();
494 update_(fractureGridAdapter);
495 }
496
497 //! The finite element cache for creating local FE bases
498
2/3
✓ Branch 4 taken 3079314 times.
✓ Branch 5 taken 758298 times.
✗ Branch 6 not taken.
14299800 const FeCache& feCache() const { return feCache_; }
499 //! If a vertex / d.o.f. is on the boundary
500
2/2
✓ Branch 0 taken 643678 times.
✓ Branch 1 taken 6432546 times.
7076224 bool dofOnBoundary(unsigned int dofIdx) const { return boundaryDofIndices_[dofIdx]; }
501 //! If a vertex / d.o.f. is on a fracture
502
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 3520 times.
3880 bool dofOnFracture(unsigned int dofIdx) const { return fractureDofIndices_[dofIdx]; }
503 //! Periodic boundaries are not supported for the box-dfm scheme
504 bool dofOnPeriodicBoundary(std::size_t dofIdx) const { return false; }
505
506 //! Returns true if an intersection coincides with a fracture element
507 7535184 bool isOnFracture(const Element& element, const Intersection& intersection) const
508 7535184 { return facetOnFracture_[facetMapper_.subIndex(element, intersection.indexInInside(), 1)]; }
509
510 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
511 std::size_t periodicallyMappedDof(std::size_t dofIdx) const
512 { DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme"); }
513
514 private:
515
516 void updateFacetMapper_()
517 {
518 facetMapper_.update(this->gridView());
519 }
520
521 template< class FractureGridAdapter >
522 6 void update_(const FractureGridAdapter& fractureGridAdapter)
523 {
524 6 boundaryDofIndices_.assign(numDofs(), false);
525 6 fractureDofIndices_.assign(numDofs(), false);
526 6 facetOnFracture_.assign(this->gridView().size(1), false);
527
528 // save global data on the grid's scvs and scvfs
529 // TODO do we need those information?
530 6 numScv_ = 0;
531 6 numScvf_ = 0;
532 6 numBoundaryScvf_ = 0;
533
7/10
✓ Branch 2 taken 4429 times.
✓ Branch 3 taken 3 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4426 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 4426 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4426 times.
✓ Branch 14 taken 3 times.
17719 for (const auto& element : elements(this->gridView()))
534 {
535
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 numScv_ += element.subEntities(dim);
536
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 numScvf_ += element.subEntities(dim-1);
537
538
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 const auto elementGeometry = element.geometry();
539 8852 const auto refElement = referenceElement(elementGeometry);
540
541 // store the sub control volume face indices on the domain boundary
542
11/16
✓ Branch 2 taken 4426 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4426 times.
✓ Branch 6 taken 15776 times.
✓ Branch 8 taken 7080 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 22856 times.
✓ Branch 12 taken 10870 times.
✓ Branch 13 taken 29534 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 7080 times.
✗ Branch 17 not taken.
✓ Branch 1 taken 4426 times.
✗ Branch 7 not taken.
✓ Branch 15 taken 8696 times.
✓ Branch 10 taken 8696 times.
141570 for (const auto& intersection : intersections(this->gridView(), element))
543 {
544 // first, obtain all vertex indices on this intersection
545
1/2
✓ Branch 1 taken 15776 times.
✗ Branch 2 not taken.
31552 const auto& isGeometry = intersection.geometry();
546
1/2
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
31552 const auto numCorners = isGeometry.corners();
547
1/2
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
31552 const auto idxInInside = intersection.indexInInside();
548
549
1/4
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
31552 std::vector<GridIndexType> isVertexIndices(numCorners);
550
2/2
✓ Branch 0 taken 80496 times.
✓ Branch 1 taken 31552 times.
112048 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
551
1/2
✓ Branch 2 taken 80496 times.
✗ Branch 3 not taken.
80496 isVertexIndices[vIdxLocal] = this->vertexMapper().subIndex(element,
552 refElement.subEntity(idxInInside, 1, vIdxLocal, dim),
553 dim);
554
555
4/4
✓ Branch 0 taken 950 times.
✓ Branch 1 taken 15776 times.
✓ Branch 2 taken 3436 times.
✓ Branch 3 taken 12340 times.
32502 if (intersection.boundary() && !intersection.neighbor())
556 {
557 1900 numScvf_ += numCorners;
558
1/2
✓ Branch 1 taken 950 times.
✗ Branch 2 not taken.
1900 numBoundaryScvf_ += numCorners;
559
560 // add all vertices on the intersection to the set of
561 // boundary vertices
562 1900 const auto fIdx = intersection.indexInInside();
563 1900 const auto numFaceVerts = refElement.size(fIdx, 1, dim);
564
2/2
✓ Branch 1 taken 5420 times.
✓ Branch 2 taken 1900 times.
7320 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
565 {
566 5420 const auto vIdx = refElement.subEntity(fIdx, 1, localVIdx, dim);
567
1/2
✓ Branch 1 taken 5420 times.
✗ Branch 2 not taken.
5420 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdx, dim);
568 5420 boundaryDofIndices_[vIdxGlobal] = true;
569 }
570 }
571
572 // make sure we have no periodic boundaries
573
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14826 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14826 else if (intersection.boundary() && intersection.neighbor())
574 DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme");
575
576 // maybe add fracture scvs & scvfs
577
3/4
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 876 times.
✓ Branch 4 taken 30676 times.
31552 if (fractureGridAdapter.composeFacetElement(isVertexIndices))
578 {
579
1/2
✓ Branch 1 taken 876 times.
✗ Branch 2 not taken.
876 facetOnFracture_[facetMapper_.subIndex(element, idxInInside, 1)] = true;
580
2/2
✓ Branch 0 taken 2192 times.
✓ Branch 1 taken 876 times.
3068 for (auto vIdx : isVertexIndices)
581 2192 fractureDofIndices_[vIdx] = true;
582
583
1/2
✓ Branch 1 taken 220 times.
✗ Branch 2 not taken.
876 const auto isGeometry = intersection.geometry();
584
1/2
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
876 numScv_ += isGeometry.corners();
585
1/2
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
876 numScvf_ += dim == 3 ? referenceElement(isGeometry).size(1) : 1;
586 876 }
587 }
588 }
589 6 }
590
591 const FeCache feCache_;
592
593 // Information on the global number of geometries
594 // TODO do we need those information?
595 std::size_t numScv_;
596 std::size_t numScvf_;
597 std::size_t numBoundaryScvf_;
598
599 // vertices on the boundary & fracture facets
600 std::vector<bool> boundaryDofIndices_;
601 std::vector<bool> fractureDofIndices_;
602
603 // facet mapper and markers which facets lie on interior boundaries
604 typename Traits::FacetMapper facetMapper_;
605 std::vector<bool> facetOnFracture_;
606 };
607
608 } // end namespace Dumux
609
610 #endif
611