version 3.10.0
Loading...
Searching...
No Matches
discretization/cellcentered/tpfa/fvgridgeometry.hh
Go to the documentation of this file.
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//
14#ifndef DUMUX_DISCRETIZATION_CCTPFA_FV_GRID_GEOMETRY_HH
15#define DUMUX_DISCRETIZATION_CCTPFA_FV_GRID_GEOMETRY_HH
16
17#include <utility>
18#include <algorithm>
19
22
31
33
34namespace Dumux {
35
42template<class GridView, class MapperTraits = DefaultMapperTraits<GridView>>
44: public MapperTraits
45{
48
49 template<class GridGeometry>
51
52 template<class GridGeometry, bool enableCache>
54
59 static constexpr int maxNumScvfNeighbors = int(GridView::dimension)<int(GridView::dimensionworld) ? 8 : 1<<(GridView::dimension-1);
60};
61
68template<class GridView,
69 bool enableGridGeometryCache = false,
72
79template<class GV, class Traits>
80class CCTpfaFVGridGeometry<GV, true, Traits>
81: public BaseGridGeometry<GV, Traits>
82{
84 using ParentType = BaseGridGeometry<GV, Traits>;
85 using ConnectivityMap = typename Traits::template ConnectivityMap<ThisType>;
86 using GridIndexType = typename IndexTraits<GV>::GridIndex;
87 using Element = typename GV::template Codim<0>::Entity;
88
89 static const int dim = GV::dimension;
90 static const int dimWorld = GV::dimensionworld;
91
92public:
96 using LocalView = typename Traits::template LocalView<ThisType, true>;
98 using SubControlVolume = typename Traits::SubControlVolume;
100 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
104 using DofMapper = typename Traits::ElementMapper;
107
109 using DiscretizationMethod = DiscretizationMethods::CCTpfa;
110 static constexpr DiscretizationMethod discMethod{};
111
113 static constexpr int maxElementStencilSize = LocalView::maxNumElementScvfs*Traits::maxNumScvfNeighbors + 1;
114
116 using GridView = GV;
117
119 CCTpfaFVGridGeometry(std::shared_ptr<BasicGridGeometry> gg)
120 : ParentType(std::move(gg))
121 , periodicGridTraits_(this->gridView().grid())
122 {
123 // Check if the overlap size is what we expect
125 DUNE_THROW(Dune::InvalidStateException, "The cctpfa discretization method needs at least an overlap of 1 for parallel computations. "
126 << " Set the parameter \"Grid.Overlap\" in the input file.");
127
128 update_();
129 }
130
132 CCTpfaFVGridGeometry(const GridView& gridView)
133 : CCTpfaFVGridGeometry(std::make_shared<BasicGridGeometry>(gridView))
134 {}
135
138 const DofMapper& dofMapper() const
139 { return this->elementMapper(); }
140
142 std::size_t numScv() const
143 {
144 return scvs_.size();
145 }
146
148 std::size_t numScvf() const
149 {
150 return scvfs_.size();
151 }
152
154 std::size_t numBoundaryScvf() const
155 {
156 return numBoundaryScvf_;
157 }
158
160 std::size_t numDofs() const
161 { return this->gridView().size(0); }
162
163
165 void update(const GridView& gridView)
166 {
167 ParentType::update(gridView);
168 update_();
169 }
170
172 void update(GridView&& gridView)
173 {
174 ParentType::update(std::move(gridView));
175 update_();
176 }
177
179 const SubControlVolume& scv(GridIndexType scvIdx) const
180 {
181 return scvs_[scvIdx];
182 }
183
185 const SubControlVolumeFace& scvf(GridIndexType scvfIdx) const
186 {
187 return scvfs_[scvfIdx];
188 }
189
192 const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, unsigned int outsideScvfIdx = 0) const
193 {
194 return scvfs_[flipScvfIndices_[scvfIdx][outsideScvfIdx]];
195 }
196
198 const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx) const
199 {
200 return scvfIndicesOfScv_[scvIdx];
201 }
202
207 const ConnectivityMap &connectivityMap() const
208 { return connectivityMap_; }
209
211 bool hasBoundaryScvf(GridIndexType eIdx) const
212 { return hasBoundaryScvf_[eIdx]; }
213
214private:
215
216 void update_()
217 {
218 // clear containers (necessary after grid refinement)
219 scvs_.clear();
220 scvfs_.clear();
221 scvfIndicesOfScv_.clear();
222 flipScvfIndices_.clear();
223
224 // determine size of containers
225 std::size_t numScvs = numDofs();
226 std::size_t numScvf = 0;
227 for (const auto& element : elements(this->gridView()))
228 numScvf += element.subEntities(1);
229
230 // reserve memory
231 scvs_.resize(numScvs);
232 scvfs_.reserve(numScvf);
233 scvfIndicesOfScv_.resize(numScvs);
234 hasBoundaryScvf_.assign(numScvs, false);
235
236 // Build the scvs and scv faces
237 GridIndexType scvfIdx = 0;
238 numBoundaryScvf_ = 0;
239 for (const auto& element : elements(this->gridView()))
240 {
241 const auto eIdx = this->elementMapper().index(element);
242 scvs_[eIdx] = SubControlVolume(element.geometry(), eIdx);
243
244 // the element-wise index sets for finite volume geometry
245 std::vector<GridIndexType> scvfsIndexSet;
246 scvfsIndexSet.reserve(element.subEntities(1));
247
248 // for network grids there might be multiple intersection with the same geometryInInside
249 // we identify those by the indexInInside for now (assumes conforming grids at branching facets)
250 using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage;
251 std::vector<ScvfGridIndexStorage> outsideIndices;
252 if (dim < dimWorld)
253 {
255 outsideIndices.resize(element.subEntities(1));
256 std::for_each(outsideIndices.begin(), outsideIndices.end(), [eIdx] (auto& nIndices) { nIndices.push_back(eIdx); });
257
258 // second, insert neighbors
259 for (const auto& intersection : intersections(this->gridView(), element))
260 {
261 if (intersection.neighbor())
262 {
263 const auto nIdx = this->elementMapper().index( intersection.outside() );
264 outsideIndices[intersection.indexInInside()].push_back(nIdx);
265 }
266 }
267 }
268
269 for (const auto& intersection : intersections(this->gridView(), element))
270 {
271 // inner sub control volume faces (includes periodic boundaries)
272 if (intersection.neighbor())
273 {
274 // update the grid geometry if we have periodic boundaries
275 if (periodicGridTraits_.isPeriodic(intersection))
276 this->setPeriodic();
277
278 if (dim == dimWorld)
279 {
280 const auto nIdx = this->elementMapper().index(intersection.outside());
281 scvfs_.emplace_back(intersection,
282 intersection.geometry(),
283 scvfIdx,
284 ScvfGridIndexStorage({eIdx, nIdx}),
285 false);
286 scvfsIndexSet.push_back(scvfIdx++);
287 }
288 // this is for network grids
289 // (will be optimized away of dim == dimWorld)
290 else
291 {
292 auto indexInInside = intersection.indexInInside();
293 // check if we already handled this facet
294 if (outsideIndices[indexInInside].empty())
295 continue;
296 else
297 {
298 scvfs_.emplace_back(intersection,
299 intersection.geometry(),
300 scvfIdx,
301 outsideIndices[indexInInside],
302 false);
303 scvfsIndexSet.push_back(scvfIdx++);
304 outsideIndices[indexInInside].clear();
305 }
306 }
307 }
308 // boundary sub control volume faces
309 else if (intersection.boundary())
310 {
311 scvfs_.emplace_back(intersection,
312 intersection.geometry(),
313 scvfIdx,
314 ScvfGridIndexStorage({eIdx, static_cast<GridIndexType>(this->gridView().size(0) + numBoundaryScvf_++)}),
315 true);
316 scvfsIndexSet.push_back(scvfIdx++);
317
318 hasBoundaryScvf_[eIdx] = true;
319 }
320 }
321
322 // Save the scvf indices belonging to this scv to build up fv element geometries fast
323 scvfIndicesOfScv_[eIdx] = scvfsIndexSet;
324 }
325
326 // Make the flip index set for network, surface, and periodic grids
327 if (dim < dimWorld || this->isPeriodic())
328 {
329 flipScvfIndices_.resize(scvfs_.size());
330 for (auto&& scvf : scvfs_)
331 {
332 if (scvf.boundary())
333 continue;
334
335 flipScvfIndices_[scvf.index()].resize(scvf.numOutsideScvs());
336 const auto insideScvIdx = scvf.insideScvIdx();
337 // check which outside scvf has the insideScvIdx index in its outsideScvIndices
338 for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
339 flipScvfIndices_[scvf.index()][i] = findFlippedScvfIndex_(insideScvIdx, scvf.outsideScvIdx(i));
340 }
341 }
342
343 // build the connectivity map for an efficient assembly
344 connectivityMap_.update(*this);
345 }
346
347 // find the scvf that has insideScvIdx in its outsideScvIdx list and outsideScvIdx as its insideScvIdx
348 GridIndexType findFlippedScvfIndex_(GridIndexType insideScvIdx, GridIndexType outsideScvIdx)
349 {
350 // go over all potential scvfs of the outside scv
351 for (auto outsideScvfIndex : scvfIndicesOfScv_[outsideScvIdx])
352 {
353 const auto& outsideScvf = this->scvf(outsideScvfIndex);
354 for (unsigned int j = 0; j < outsideScvf.numOutsideScvs(); ++j)
355 if (outsideScvf.outsideScvIdx(j) == insideScvIdx)
356 return outsideScvf.index();
357 }
358
359 DUNE_THROW(Dune::InvalidStateException, "No flipped version of this scvf found!");
360 }
361
363 ConnectivityMap connectivityMap_;
364
366 std::vector<SubControlVolume> scvs_;
367 std::vector<SubControlVolumeFace> scvfs_;
368 std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_;
369 std::size_t numBoundaryScvf_;
370 std::vector<bool> hasBoundaryScvf_;
371
373 std::vector<std::vector<GridIndexType>> flipScvfIndices_;
374
375 PeriodicGridTraits<typename GridView::Grid> periodicGridTraits_;
376};
377
385template<class GV, class Traits>
386class CCTpfaFVGridGeometry<GV, false, Traits>
387: public BaseGridGeometry<GV, Traits>
388{
389 using ThisType = CCTpfaFVGridGeometry<GV, false, Traits>;
390 using ParentType = BaseGridGeometry<GV, Traits>;
391 using ConnectivityMap = typename Traits::template ConnectivityMap<ThisType>;
392
393 using GridIndexType = typename IndexTraits<GV>::GridIndex;
394 using Element = typename GV::template Codim<0>::Entity;
395
396 static const int dim = GV::dimension;
397 static const int dimWorld = GV::dimensionworld;
398
399 using ScvfGridIndexStorage = typename Traits::SubControlVolumeFace::Traits::GridIndexStorage;
400 using NeighborVolVarIndices = typename std::conditional_t< (dim<dimWorld),
401 ScvfGridIndexStorage,
402 Dune::ReservedVector<GridIndexType, 1> >;
403
404public:
406 using BasicGridGeometry = BasicGridGeometry_t<GV, Traits>;
408 using LocalView = typename Traits::template LocalView<ThisType, false>;
410 using SubControlVolume = typename Traits::SubControlVolume;
412 using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
414 using Extrusion = Extrusion_t<Traits>;
416 using DofMapper = typename Traits::ElementMapper;
418 using SupportsPeriodicity = typename PeriodicGridTraits<typename GV::Grid>::SupportsPeriodicity;
419
421 using DiscretizationMethod = DiscretizationMethods::CCTpfa;
422 static constexpr DiscretizationMethod discMethod{};
423
425 static constexpr int maxElementStencilSize = LocalView::maxNumElementScvfs*Traits::maxNumScvfNeighbors + 1;
426
428 using GridView = GV;
429
431 CCTpfaFVGridGeometry(std::shared_ptr<BasicGridGeometry> gg)
432 : ParentType(std::move(gg))
433 , periodicGridTraits_(this->gridView().grid())
434 {
435 // Check if the overlap size is what we expect
437 DUNE_THROW(Dune::InvalidStateException, "The cctpfa discretization method needs at least an overlap of 1 for parallel computations. "
438 << " Set the parameter \"Grid.Overlap\" in the input file.");
439
440 update_();
441 }
442
444 CCTpfaFVGridGeometry(const GridView& gridView)
445 : CCTpfaFVGridGeometry(std::make_shared<BasicGridGeometry>(gridView))
446 {}
447
450 const DofMapper& dofMapper() const
451 { return this->elementMapper(); }
452
454 std::size_t numScv() const
455 {
456 return numScvs_;
457 }
458
460 std::size_t numScvf() const
461 {
462 return numScvf_;
463 }
464
466 std::size_t numBoundaryScvf() const
467 {
468 return numBoundaryScvf_;
469 }
470
472 std::size_t numDofs() const
473 { return this->gridView().size(0); }
474
476 void update(const GridView& gridView)
477 {
478 ParentType::update(gridView);
479 update_();
480 }
481
483 void update(GridView&& gridView)
484 {
485 ParentType::update(std::move(gridView));
486 update_();
487 }
488
489 const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx) const
490 { return scvfIndicesOfScv_[scvIdx]; }
491
493 const std::vector<NeighborVolVarIndices>& neighborVolVarIndices(GridIndexType scvIdx) const
494 { return neighborVolVarIndices_[scvIdx]; }
495
500 const ConnectivityMap &connectivityMap() const
501 { return connectivityMap_; }
502
503private:
504
505 void update_()
506 {
507 // clear local data
508 scvfIndicesOfScv_.clear();
509 neighborVolVarIndices_.clear();
510
511 // reserve memory or resize the containers
512 numScvs_ = numDofs();
513 numScvf_ = 0;
514 numBoundaryScvf_ = 0;
515 scvfIndicesOfScv_.resize(numScvs_);
516 neighborVolVarIndices_.resize(numScvs_);
517
518 // Build the SCV and SCV face
519 for (const auto& element : elements(this->gridView()))
520 {
521 const auto eIdx = this->elementMapper().index(element);
522
523 // the element-wise index sets for finite volume geometry
524 auto numLocalFaces = element.subEntities(1);
525 std::vector<GridIndexType> scvfsIndexSet;
526 std::vector<NeighborVolVarIndices> neighborVolVarIndexSet;
527 scvfsIndexSet.reserve(numLocalFaces);
528 neighborVolVarIndexSet.reserve(numLocalFaces);
529
530 // for network grids there might be multiple intersection with the same geometryInInside
531 // we identify those by the indexInInside for now (assumes conforming grids at branching facets)
532 std::vector<NeighborVolVarIndices> outsideIndices;
533 if (dim < dimWorld)
534 {
535 outsideIndices.resize(numLocalFaces);
536 for (const auto& intersection : intersections(this->gridView(), element))
537 {
538 if (intersection.neighbor())
539 {
540 const auto nIdx = this->elementMapper().index(intersection.outside());
541 outsideIndices[intersection.indexInInside()].push_back(nIdx);
542 }
543 }
544 }
545
546 for (const auto& intersection : intersections(this->gridView(), element))
547 {
548 // inner sub control volume faces (includes periodic boundaries)
549 if (intersection.neighbor())
550 {
551 // update the grid geometry if we have periodic boundaries
552 if (periodicGridTraits_.isPeriodic(intersection))
553 this->setPeriodic();
554
555 if (dim == dimWorld)
556 {
557 scvfsIndexSet.push_back(numScvf_++);
558 const auto nIdx = this->elementMapper().index(intersection.outside());
559 neighborVolVarIndexSet.emplace_back(NeighborVolVarIndices({nIdx}));
560 }
561 // this is for network grids
562 // (will be optimized away of dim == dimWorld)
563 else
564 {
565 auto indexInInside = intersection.indexInInside();
566 // check if we already handled this facet
567 if (outsideIndices[indexInInside].empty())
568 continue;
569 else
570 {
571 scvfsIndexSet.push_back(numScvf_++);
572 neighborVolVarIndexSet.emplace_back(std::move(outsideIndices[indexInInside]));
573 outsideIndices[indexInInside].clear();
574 }
575 }
576 }
577 // boundary sub control volume faces
578 else if (intersection.boundary())
579 {
580 scvfsIndexSet.push_back(numScvf_++);
581 neighborVolVarIndexSet.emplace_back(NeighborVolVarIndices({static_cast<GridIndexType>(numScvs_ + numBoundaryScvf_++)}));
582 }
583 }
584
585 // store the sets of indices in the data container
586 scvfIndicesOfScv_[eIdx] = scvfsIndexSet;
587 neighborVolVarIndices_[eIdx] = neighborVolVarIndexSet;
588 }
589
590 // build the connectivity map for an efficient assembly
591 connectivityMap_.update(*this);
592 }
593
595 std::size_t numScvs_;
596 std::size_t numScvf_;
597 std::size_t numBoundaryScvf_;
598
600 ConnectivityMap connectivityMap_;
601
603 std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_;
604 std::vector<std::vector<NeighborVolVarIndices>> neighborVolVarIndices_;
605
606 PeriodicGridTraits<typename GridView::Grid> periodicGridTraits_;
607};
608
609} // end namespace Dumux
610
611#endif
Base class for grid geometries.
Stores the face indices corresponding to the neighbors of an element that contribute to the derivativ...
Check the overlap size for different discretization methods.
Base class for all grid geometries.
Definition basegridgeometry.hh:52
An implementation of a grid geometry with some basic features.
Definition basicgridgeometry.hh:37
A simple version of the connectivity map for cellcentered schemes. This implementation works for sche...
Definition cellcentered/connectivitymap.hh:41
Sub control volumes for cell-centered discretization schemes.
Definition discretization/cellcentered/subcontrolvolume.hh:47
Stencil-local finite volume geometry (scvs and scvfs) for cell-centered TPFA models This builds up th...
Definition discretization/cellcentered/tpfa/fvelementgeometry.hh:53
The finite volume geometry (scvs and scvfs) for cell-centered TPFA models on a grid view This builds ...
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:71
The sub control volume face.
Definition discretization/cellcentered/tpfa/subcontrolvolumeface.hh:78
Traits extracting the public Extrusion type from T Defaults to NoExtrusion if no such type is found.
Definition extrusion.hh:155
Definition periodicgridtraits.hh:121
Defines the default element and vertex mapper types.
Sub control volumes for cell-centered discretization schemes.
Stencil-local finite volume geometry (scvs and scvfs) for cell-centered TPFA models This builds up th...
The sub control volume face.
Helper classes to compute the integration elements.
Dune::Std::detected_or_t< Dumux::BasicGridGeometry< GV, typename T::ElementMapper, typename T::VertexMapper >, Detail::SpecifiesBaseGridGeometry, T > BasicGridGeometry_t
Type of the basic grid geometry implementation used as backend.
Definition basegridgeometry.hh:38
@ element
Definition fieldtype.hh:23
Defines the index types used for grid and local indices.
The available discretization methods in Dumux.
Definition adapt.hh:17
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:166
Grid properties related to periodicity.
The default traits for the tpfa finite volume grid geometry Defines the scv and scvf types and the ma...
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:45
CCTpfaFVElementGeometry< GridGeometry, enableCache > LocalView
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:53
CCTpfaSubControlVolumeFace< GridView > SubControlVolumeFace
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:47
CCSimpleConnectivityMap< GridGeometry > ConnectivityMap
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:50
CCSubControlVolume< GridView > SubControlVolume
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:46
static constexpr int maxNumScvfNeighbors
Definition discretization/cellcentered/tpfa/fvgridgeometry.hh:59
static bool isValid(const GridView &gridView) noexcept
Definition checkoverlapsize.hh:30
typename GridView::IndexSet::IndexType GridIndex
Definition indextraits.hh:27
Definition periodicgridtraits.hh:34