GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/porousmediumflow/boxdfm/fvgridgeometry.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 48 52 92.3%
Functions: 15 25 60.0%
Branches: 95 215 44.2%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup BoxDFMModel
10 * \brief 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 //! Returns the map between dofs across periodic boundaries
195 [[deprecated("Will be removed after release 3.9. Implement periodicDofMap() if periodic bcs are supported.")]]
196 std::unordered_map<std::size_t, std::size_t> periodicVertexMap() const
197 { return std::unordered_map<std::size_t, std::size_t>(); }
198
199 private:
200
201 template< class FractureGridAdapter >
202 void update_(const FractureGridAdapter& fractureGridAdapter)
203 {
204 scvs_.clear();
205 scvfs_.clear();
206
207 auto numElements = this->gridView().size(0);
208 scvs_.resize(numElements);
209 scvfs_.resize(numElements);
210
211 boundaryDofIndices_.assign(numDofs(), false);
212 fractureDofIndices_.assign(this->gridView.size(dim), false);
213
214 numScv_ = 0;
215 numScvf_ = 0;
216 numBoundaryScvf_ = 0;
217 // Build the SCV and SCV faces
218 for (const auto& element : elements(this->gridView()))
219 {
220 // fill the element map with seeds
221 auto eIdx = this->elementMapper().index(element);
222
223 // count
224 numScv_ += element.subEntities(dim);
225 numScvf_ += element.subEntities(dim-1);
226
227 // get the element geometry
228 auto elementGeometry = element.geometry();
229 const auto refElement = referenceElement(elementGeometry);
230
231 // instantiate the geometry helper
232 GeometryHelper geometryHelper(elementGeometry);
233
234 // construct the sub control volumes
235 scvs_[eIdx].resize(elementGeometry.corners());
236 using LocalIndexType = typename SubControlVolumeFace::Traits::LocalIndexType;
237 for (LocalIndexType scvLocalIdx = 0; scvLocalIdx < elementGeometry.corners(); ++scvLocalIdx)
238 {
239 const auto dofIdxGlobal = this->vertexMapper().subIndex(element, scvLocalIdx, dim);
240
241 scvs_[eIdx][scvLocalIdx] = SubControlVolume(geometryHelper,
242 scvLocalIdx,
243 eIdx,
244 dofIdxGlobal);
245 }
246
247 // construct the sub control volume faces
248 LocalIndexType scvfLocalIdx = 0;
249 scvfs_[eIdx].resize(element.subEntities(dim-1));
250 for (; scvfLocalIdx < element.subEntities(dim-1); ++scvfLocalIdx)
251 {
252 // find the global and local scv indices this scvf is belonging to
253 std::vector<LocalIndexType> localScvIndices({static_cast<LocalIndexType>(refElement.subEntity(scvfLocalIdx, dim-1, 0, dim)),
254 static_cast<LocalIndexType>(refElement.subEntity(scvfLocalIdx, dim-1, 1, dim))});
255
256 scvfs_[eIdx][scvfLocalIdx] = SubControlVolumeFace(geometryHelper,
257 element,
258 elementGeometry,
259 scvfLocalIdx,
260 std::move(localScvIndices));
261 }
262
263 // construct the ...
264 // ... sub-control volume faces on the domain boundary
265 // ... sub-control volumes on fracture facets
266 // ... sub-control volume faces on fracture facets
267 // NOTE We do not construct fracture scvfs on boundaries here!
268 // That means specifying Neumann fluxes on only the fractures is not possible
269 // However, it is difficult to interpret this here as a fracture ending on the boundary
270 // could also be connected to a facet which is both boundary and fracture at the same time!
271 // In that case, the fracture boundary scvf wouldn't make sense. In order to do it properly
272 // we would have to find only those fractures that are at the boundary and aren't connected
273 // to a fracture which is a boundary.
274 LocalIndexType scvLocalIdx = element.subEntities(dim);
275 for (const auto& intersection : intersections(this->gridView(), element))
276 {
277 // first, obtain all vertex indices on this intersection
278 const auto& isGeometry = intersection.geometry();
279 const auto numCorners = isGeometry.corners();
280 const auto idxInInside = intersection.indexInInside();
281
282 std::vector<GridIndexType> isVertexIndices(numCorners);
283 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
284 isVertexIndices[vIdxLocal] = this->vertexMapper().subIndex(element,
285 refElement.subEntity(idxInInside, 1, vIdxLocal, dim),
286 dim);
287 // maybe add boundary scvf
288 if (intersection.boundary() && !intersection.neighbor())
289 {
290 numScvf_ += isGeometry.corners();
291 numBoundaryScvf_ += isGeometry.corners();
292
293 for (unsigned int isScvfLocalIdx = 0; isScvfLocalIdx < numCorners; ++isScvfLocalIdx)
294 {
295 // find the scvs this scvf is belonging to
296 const LocalIndexType insideScvIdx = static_cast<LocalIndexType>(refElement.subEntity(idxInInside, 1, isScvfLocalIdx, dim));
297 std::vector<LocalIndexType> localScvIndices = {insideScvIdx, insideScvIdx};
298 scvfs_[eIdx].emplace_back(geometryHelper,
299 intersection,
300 isGeometry,
301 isScvfLocalIdx,
302 scvfLocalIdx++,
303 std::move(localScvIndices));
304 }
305
306 // add all vertices on the intersection to the set of
307 // boundary vertices
308 const auto numFaceVerts = refElement.size(idxInInside, 1, dim);
309 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
310 {
311 const auto vIdx = refElement.subEntity(idxInInside, 1, localVIdx, dim);
312 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdx, dim);
313 boundaryDofIndices_[vIdxGlobal] = true;
314 }
315 }
316 // make sure we have no periodic boundaries
317 else if (intersection.boundary() && intersection.neighbor())
318 DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme");
319
320 // maybe add fracture scvs & scvfs
321 if (fractureGridAdapter.composeFacetElement(isVertexIndices))
322 {
323 for (auto vIdx : isVertexIndices)
324 fractureDofIndices_[vIdx] = true;
325
326 // add fracture scv for each vertex of intersection
327 numScv_ += numCorners;
328 const auto curNumScvs = scvs_[eIdx].size();
329 scvs_[eIdx].reserve(curNumScvs+numCorners);
330 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
331 scvs_[eIdx].emplace_back(geometryHelper,
332 intersection,
333 isGeometry,
334 vIdxLocal,
335 static_cast<LocalIndexType>(refElement.subEntity(idxInInside, 1, vIdxLocal, dim)),
336 scvLocalIdx++,
337 idxInInside,
338 eIdx,
339 isVertexIndices[vIdxLocal]);
340
341 // add fracture scvf for each edge of the intersection in 3d
342 if (dim == 3)
343 {
344 const auto& faceRefElement = referenceElement(isGeometry);
345 for (unsigned int edgeIdx = 0; edgeIdx < faceRefElement.size(1); ++edgeIdx)
346 {
347 // inside/outside scv indices in face local node numbering
348 std::vector<LocalIndexType> localScvIndices({static_cast<LocalIndexType>(faceRefElement.subEntity(edgeIdx, 1, 0, dim-1)),
349 static_cast<LocalIndexType>(faceRefElement.subEntity(edgeIdx, 1, 1, dim-1))});
350
351 // add offset to get the right scv indices
352 std::for_each( localScvIndices.begin(),
353 localScvIndices.end(),
354 [curNumScvs] (auto& elemLocalIdx) { elemLocalIdx += curNumScvs; } );
355
356 // add scvf
357 numScvf_++;
358 scvfs_[eIdx].emplace_back(geometryHelper,
359 intersection,
360 isGeometry,
361 edgeIdx,
362 scvfLocalIdx++,
363 std::move(localScvIndices),
364 intersection.boundary());
365 }
366 }
367
368 // dim == 2, intersection is an edge, make 1 scvf
369 else
370 {
371 // inside/outside scv indices in face local node numbering
372 std::vector<LocalIndexType> localScvIndices({0, 1});
373
374 // add offset such that the fracture scvs above are addressed
375 std::for_each( localScvIndices.begin(),
376 localScvIndices.end(),
377 [curNumScvs] (auto& elemLocalIdx) { elemLocalIdx += curNumScvs; } );
378
379 // add scvf
380 numScvf_++;
381 scvfs_[eIdx].emplace_back(geometryHelper,
382 intersection,
383 isGeometry,
384 /*idxOnIntersection*/0,
385 scvfLocalIdx++,
386 std::move(localScvIndices),
387 intersection.boundary());
388 }
389 }
390 }
391 }
392 }
393
394 const FeCache feCache_;
395
396 std::vector<std::vector<SubControlVolume>> scvs_;
397 std::vector<std::vector<SubControlVolumeFace>> scvfs_;
398
399 // TODO do we need those?
400 std::size_t numScv_;
401 std::size_t numScvf_;
402 std::size_t numBoundaryScvf_;
403
404 // vertices on the boundary & fracture facets
405 std::vector<bool> boundaryDofIndices_;
406 std::vector<bool> fractureDofIndices_;
407 };
408
409 /*!
410 * \ingroup BoxDFMModel
411 * \brief Base class for the finite volume geometry vector for box schemes
412 * This builds up the sub control volumes and sub control volume faces
413 * \note For caching disabled we store only some essential index maps to build up local systems on-demand in
414 * the corresponding FVElementGeometry
415 */
416 template<class Scalar, class GV, class Traits>
417 class BoxDfmFVGridGeometry<Scalar, GV, false, Traits>
418 : public BaseGridGeometry<GV, Traits>
419 {
420 using ThisType = BoxDfmFVGridGeometry<Scalar, GV, false, Traits>;
421 using ParentType = BaseGridGeometry<GV, Traits>;
422 using GridIndexType = typename GV::IndexSet::IndexType;
423
424 static const int dim = GV::dimension;
425 static const int dimWorld = GV::dimensionworld;
426
427 using Element = typename GV::template Codim<0>::Entity;
428 using Intersection = typename GV::Intersection;
429 using CoordScalar = typename GV::ctype;
430
431 public:
432 //! export the discretization method this geometry belongs to
433 using DiscretizationMethod = DiscretizationMethods::Box;
434 static constexpr DiscretizationMethod discMethod{};
435
436 //! export the type of the fv element geometry (the local view type)
437 using LocalView = typename Traits::template LocalView<ThisType, false>;
438 //! export the type of sub control volume
439 using SubControlVolume = typename Traits::SubControlVolume;
440 //! export the type of sub control volume
441 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
442 //! Export the extrusion type
443 using Extrusion = Extrusion_t<Traits>;
444 //! export dof mapper type
445 using DofMapper = typename Traits::VertexMapper;
446 //! export the finite element cache type
447 using FeCache = Dune::LagrangeLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
448 //! export the grid view type
449 using GridView = GV;
450 //! export the geometry helper type
451 using GeometryHelper = Detail::BoxDfmGeometryHelper_t<GV, Traits>;
452
453 //! Constructor
454 template< class FractureGridAdapter >
455 6 BoxDfmFVGridGeometry(const GridView gridView, const FractureGridAdapter& fractureGridAdapter)
456 : ParentType(gridView)
457
7/18
✓ 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.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
12 , facetMapper_(gridView, Dune::mcmgLayout(Dune::template Codim<1>()))
458 {
459
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 update_(fractureGridAdapter);
460 6 }
461
462 //! the vertex mapper is the dofMapper
463 //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa...
464 const DofMapper& dofMapper() const
465
8/33
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✓ Branch 30 taken 2 times.
✓ Branch 31 taken 2 times.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
48022380 { return this->vertexMapper(); }
466
467 //! The total number of sub control volumes
468 std::size_t numScv() const
469 { return numScv_; }
470
471 //! The total number of sun control volume faces
472 std::size_t numScvf() const
473 { return numScvf_; }
474
475 //! The total number of boundary sub control volume faces
476 //! For compatibility reasons with cc methods
477 std::size_t numBoundaryScvf() const
478 { return numBoundaryScvf_; }
479
480 //! The total number of degrees of freedom
481 std::size_t numDofs() const
482
4/7
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 3 times.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
72 { return this->gridView().size(dim); }
483
484 //! update all fvElementGeometries (call this after grid adaption)
485 template< class FractureGridAdapter >
486 void update(const GridView& gridView, const FractureGridAdapter& fractureGridAdapter)
487 {
488 ParentType::update(gridView);
489 updateFacetMapper_();
490 update_(fractureGridAdapter);
491 }
492
493 //! update all fvElementGeometries (call this after grid adaption)
494 template< class FractureGridAdapter >
495 void update(GridView&& gridView, const FractureGridAdapter& fractureGridAdapter)
496 {
497 ParentType::update(std::move(gridView));
498 updateFacetMapper_();
499 update_(fractureGridAdapter);
500 }
501
502 //! The finite element cache for creating local FE bases
503
2/3
✓ Branch 4 taken 3617874 times.
✓ Branch 5 taken 758298 times.
✗ Branch 6 not taken.
16464312 const FeCache& feCache() const { return feCache_; }
504 //! If a vertex / d.o.f. is on the boundary
505
4/4
✓ Branch 0 taken 683278 times.
✓ Branch 1 taken 7481330 times.
✓ Branch 2 taken 683278 times.
✓ Branch 3 taken 7481330 times.
16329216 bool dofOnBoundary(unsigned int dofIdx) const { return boundaryDofIndices_[dofIdx]; }
506 //! If a vertex / d.o.f. is on a fracture
507
4/4
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 3520 times.
✓ Branch 2 taken 360 times.
✓ Branch 3 taken 3520 times.
7760 bool dofOnFracture(unsigned int dofIdx) const { return fractureDofIndices_[dofIdx]; }
508 //! Periodic boundaries are not supported for the box-dfm scheme
509 bool dofOnPeriodicBoundary(std::size_t dofIdx) const { return false; }
510
511 //! Returns true if an intersection coincides with a fracture element
512 8761392 bool isOnFracture(const Element& element, const Intersection& intersection) const
513
2/2
✓ Branch 0 taken 154224 times.
✓ Branch 1 taken 3678624 times.
13142088 { return facetOnFracture_[facetMapper_.subIndex(element, intersection.indexInInside(), 1)]; }
514
515 //! The index of the vertex / d.o.f. on the other side of the periodic boundary
516 std::size_t periodicallyMappedDof(std::size_t dofIdx) const
517 { DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme"); }
518
519 //! Returns the map between dofs across periodic boundaries
520 [[deprecated("Will be removed after release 3.9. Implement periodicDofMap() if periodic bcs are supported.")]]
521 std::unordered_map<std::size_t, std::size_t> periodicVertexMap() const
522 { return std::unordered_map<std::size_t, std::size_t>(); }
523
524 private:
525
526 void updateFacetMapper_()
527 {
528 facetMapper_.update(this->gridView());
529 }
530
531 template< class FractureGridAdapter >
532 6 void update_(const FractureGridAdapter& fractureGridAdapter)
533 {
534 6 boundaryDofIndices_.assign(numDofs(), false);
535 6 fractureDofIndices_.assign(numDofs(), false);
536 12 facetOnFracture_.assign(this->gridView().size(1), false);
537
538 // save global data on the grid's scvs and scvfs
539 // TODO do we need those information?
540 6 numScv_ = 0;
541 6 numScvf_ = 0;
542 6 numBoundaryScvf_ = 0;
543
10/12
✓ Branch 2 taken 4426 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 4426 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4426 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 4426 times.
✓ Branch 11 taken 3 times.
✓ Branch 13 taken 4426 times.
✗ Branch 14 not taken.
17716 for (const auto& element : elements(this->gridView()))
544 {
545
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 numScv_ += element.subEntities(dim);
546
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 numScvf_ += element.subEntities(dim-1);
547
548
2/4
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4426 times.
✗ Branch 5 not taken.
13278 const auto elementGeometry = element.geometry();
549
1/2
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
8852 const auto refElement = referenceElement(elementGeometry);
550
551 // store the sub control volume face indices on the domain boundary
552
7/15
✓ Branch 1 taken 4426 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4426 times.
✓ Branch 4 taken 4426 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4426 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 40404 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 13 taken 15776 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 15776 times.
✗ Branch 16 not taken.
98512 for (const auto& intersection : intersections(this->gridView(), element))
553 {
554 // first, obtain all vertex indices on this intersection
555
2/4
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31552 times.
✗ Branch 5 not taken.
63104 const auto& isGeometry = intersection.geometry();
556
2/3
✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 30256 times.
✗ Branch 2 not taken.
31552 const auto numCorners = isGeometry.corners();
557
2/3
✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 30256 times.
✗ Branch 2 not taken.
31552 const auto idxInInside = intersection.indexInInside();
558
559
4/12
✓ Branch 1 taken 31552 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31552 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31552 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15776 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
126208 std::vector<GridIndexType> isVertexIndices(numCorners);
560
2/2
✓ Branch 0 taken 80496 times.
✓ Branch 1 taken 31552 times.
112048 for (unsigned int vIdxLocal = 0; vIdxLocal < numCorners; ++vIdxLocal)
561
1/2
✓ Branch 3 taken 80496 times.
✗ Branch 4 not taken.
160992 isVertexIndices[vIdxLocal] = this->vertexMapper().subIndex(element,
562 refElement.subEntity(idxInInside, 1, vIdxLocal, dim),
563 dim);
564
565
5/6
✓ Branch 0 taken 3436 times.
✓ Branch 1 taken 13290 times.
✓ Branch 2 taken 14826 times.
✓ Branch 3 taken 950 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1900 times.
33452 if (intersection.boundary() && !intersection.neighbor())
566 {
567 1900 numScvf_ += numCorners;
568 1900 numBoundaryScvf_ += numCorners;
569
570 // add all vertices on the intersection to the set of
571 // boundary vertices
572
2/3
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1018 times.
✗ Branch 2 not taken.
1900 const auto fIdx = intersection.indexInInside();
573 1900 const auto numFaceVerts = refElement.size(fIdx, 1, dim);
574
2/2
✓ Branch 1 taken 5420 times.
✓ Branch 2 taken 1900 times.
7320 for (int localVIdx = 0; localVIdx < numFaceVerts; ++localVIdx)
575 {
576 5420 const auto vIdx = refElement.subEntity(fIdx, 1, localVIdx, dim);
577
2/4
✓ Branch 1 taken 5420 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5420 times.
✗ Branch 5 not taken.
10840 const auto vIdxGlobal = this->vertexMapper().subIndex(element, vIdx, dim);
578 16260 boundaryDofIndices_[vIdxGlobal] = true;
579 }
580 }
581
582 // make sure we have no periodic boundaries
583
2/6
✓ Branch 0 taken 2486 times.
✓ Branch 1 taken 27166 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
29652 else if (intersection.boundary() && intersection.neighbor())
584 DUNE_THROW(Dune::InvalidStateException, "Periodic boundaries are not supported by the box-dfm scheme");
585
586 // maybe add fracture scvs & scvfs
587
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))
588 {
589
1/2
✓ Branch 1 taken 876 times.
✗ Branch 2 not taken.
876 facetOnFracture_[facetMapper_.subIndex(element, idxInInside, 1)] = true;
590
4/4
✓ Branch 0 taken 2192 times.
✓ Branch 1 taken 876 times.
✓ Branch 2 taken 2192 times.
✓ Branch 3 taken 876 times.
7012 for (auto vIdx : isVertexIndices)
591 6576 fractureDofIndices_[vIdx] = true;
592
593
1/4
✓ Branch 1 taken 876 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1752 const auto isGeometry = intersection.geometry();
594
2/3
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
876 numScv_ += isGeometry.corners();
595
4/7
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 220 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 220 times.
✗ Branch 6 not taken.
876 numScvf_ += dim == 3 ? referenceElement(isGeometry).size(1) : 1;
596 }
597 }
598 }
599 6 }
600
601 const FeCache feCache_;
602
603 // Information on the global number of geometries
604 // TODO do we need those information?
605 std::size_t numScv_;
606 std::size_t numScvf_;
607 std::size_t numBoundaryScvf_;
608
609 // vertices on the boundary & fracture facets
610 std::vector<bool> boundaryDofIndices_;
611 std::vector<bool> fractureDofIndices_;
612
613 // facet mapper and markers which facets lie on interior boundaries
614 typename Traits::FacetMapper facetMapper_;
615 std::vector<bool> facetOnFracture_;
616 };
617
618 } // end namespace Dumux
619
620 #endif
621