238 using GridView =
typename GG::GridView;
242 static const int dim = GridView::dimension;
243 static const int dimWorld = GridView::dimensionworld;
247 using Element =
typename GridView::template Codim<0>::Entity;
255 static constexpr std::size_t maxNumElementScvs = 1;
257 static constexpr std::size_t maxNumElementScvfs = 2*dim;
261 : gridGeometryPtr_(&gridGeometry) {}
267 if (scvIdx == scvIndices_[0])
277 auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
278 if (it != scvfIndices_.end())
279 return scvfs_[std::distance(scvfIndices_.begin(), it)];
288 auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
289 if (it != scvfIndices_.end())
291 const auto localScvfIdx = std::distance(scvfIndices_.begin(), it);
292 return neighborScvfs_[flippedScvfIndices_[localScvfIdx][outsideScvIdx]];
297 const auto localFlippedIndex = flippedNeighborScvfIndices_[localScvfIdx][outsideScvIdx];
298 if (localFlippedIndex < scvfs_.size())
299 return scvfs_[localFlippedIndex];
301 return neighborScvfs_[localFlippedIndex - scvfs_.size()];
310 friend inline Dune::IteratorRange<typename std::array<SubControlVolume, 1>::const_iterator>
313 using IteratorType =
typename std::array<SubControlVolume, 1>::const_iterator;
314 return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
322 friend inline Dune::IteratorRange<typename std::vector<SubControlVolumeFace>::const_iterator>
325 using IteratorType =
typename std::vector<SubControlVolumeFace>::const_iterator;
326 return Dune::IteratorRange<IteratorType>(g.scvfs_.begin(), g.scvfs_.end());
331 {
return scvs_.size(); }
335 {
return scvfs_.size(); }
344 this->bind_(element);
345 return std::move(*
this);
350 this->bind_(element);
360 this->bindElement_(element);
361 return std::move(*
this);
366 this->bindElement_(element);
371 {
return static_cast<bool>(element_); }
375 {
return *element_; }
379 {
return *gridGeometryPtr_; }
383 {
return hasBoundaryScvf_; }
386 {
return gridGeometryPtr_->element(scv.dofIndex()).geometry(); }
390 const auto element = gridGeometryPtr_->element(scvf.insideScvIdx());
391 const auto& scvfIndices = gridGeometryPtr_->scvfIndicesOfScv(scvf.insideScvIdx());
393 LocalIndexType localIdx = 0;
394 for (
const auto& intersection : intersections(gridGeometryPtr_->gridView(), element))
396 if (intersection.neighbor() || intersection.boundary())
398 if (localIdx == localScvfIdx)
399 return intersection.geometry();
405 DUNE_THROW(Dune::InvalidStateException,
"Could not find scvf geometry");
411 void bind_(
const Element& element)
413 bindElement_(element);
415 neighborScvs_.reserve(element.subEntities(1));
416 neighborScvfIndices_.reserve(element.subEntities(1));
417 neighborScvfs_.reserve(element.subEntities(1));
419 std::vector<GridIndexType> handledNeighbors;
420 handledNeighbors.reserve(element.subEntities(1));
422 for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
425 if (intersection.neighbor())
427 const auto outside = intersection.outside();
428 const auto outsideIdx = gridGeometry().elementMapper().index(outside);
431 if ( std::find(handledNeighbors.begin(), handledNeighbors.end(), outsideIdx) == handledNeighbors.end() )
433 makeNeighborGeometries(outside, outsideIdx);
434 handledNeighbors.push_back(outsideIdx);
440 if (dim < dimWorld || gridGeometry().isPeriodic())
442 flippedScvfIndices_.resize(scvfs_.size());
443 for (
unsigned int localScvfIdx = 0; localScvfIdx < scvfs_.size(); ++localScvfIdx)
445 const auto& scvf = scvfs_[localScvfIdx];
449 flippedScvfIndices_[localScvfIdx].resize(scvf.numOutsideScvs());
450 for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < scvf.numOutsideScvs(); ++localOutsideScvIdx)
452 const auto globalOutsideScvIdx = scvf.outsideScvIdx(localOutsideScvIdx);
453 for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
455 if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
457 flippedScvfIndices_[localScvfIdx][localOutsideScvIdx] = localNeighborScvfIdx;
464 flippedNeighborScvfIndices_.resize(neighborScvfs_.size());
465 for (
unsigned int localScvfIdx = 0; localScvfIdx < neighborScvfs_.size(); ++localScvfIdx)
467 const auto& neighborScvf = neighborScvfs_[localScvfIdx];
468 flippedNeighborScvfIndices_[localScvfIdx].resize(neighborScvf.numOutsideScvs());
469 for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < neighborScvf.numOutsideScvs(); ++localOutsideScvIdx)
471 flippedNeighborScvfIndices_[localScvfIdx][localOutsideScvIdx] = findFlippedScvfIndex_(neighborScvf.insideScvIdx(), neighborScvf.outsideScvIdx(localOutsideScvIdx));
478 void bindElement_(
const Element& element)
482 scvfs_.reserve(
element.subEntities(1));
483 scvfIndices_.reserve(
element.subEntities(1));
484 makeElementGeometries(element);
487 GridIndexType findFlippedScvfIndex_(GridIndexType insideScvIdx, GridIndexType globalOutsideScvIdx)
489 for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
491 if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
493 return scvfs_.size() + localNeighborScvfIdx;
498 for (
unsigned int localOutsideScvfIdx = 0; localOutsideScvfIdx < scvfs_.size(); ++localOutsideScvfIdx)
500 const auto& outsideScvf = scvfs_[localOutsideScvfIdx];
501 for (
unsigned int j = 0; j < outsideScvf.numOutsideScvs(); ++j)
503 if (outsideScvf.outsideScvIdx(j) == insideScvIdx)
505 return localOutsideScvfIdx;
510 DUNE_THROW(Dune::InvalidStateException,
"No flipped version of this scvf found!");
514 void makeElementGeometries(
const Element& element)
516 using ScvfGridIndexStorage =
typename SubControlVolumeFace::Traits::GridIndexStorage;
518 const auto eIdx = gridGeometry().elementMapper().index(element);
519 scvs_[0] = SubControlVolume(
element.geometry(), eIdx);
520 scvIndices_[0] = eIdx;
522 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
523 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
528 std::vector<bool> handledScvf;
530 handledScvf.resize(
element.subEntities(1),
false);
533 for (
const auto& intersection : intersections(gridGeometry().gridView(),
element))
536 if (handledScvf[intersection.indexInInside()])
539 const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
540 if (intersection.neighbor() || intersection.boundary())
542 ScvfGridIndexStorage scvIndices;
543 scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
544 scvIndices[0] = eIdx;
545 std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
547 const bool onBoundary = intersection.boundary() && !intersection.neighbor();
548 hasBoundaryScvf_ = (hasBoundaryScvf_ || onBoundary);
550 scvfs_.emplace_back(intersection,
551 intersection.geometry(),
552 scvFaceIndices[scvfCounter],
555 scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
560 handledScvf[intersection.indexInInside()] =
true;
566 void makeNeighborGeometries(
const Element& element,
const GridIndexType eIdx)
568 using ScvfGridIndexStorage =
typename SubControlVolumeFace::Traits::GridIndexStorage;
571 neighborScvs_.emplace_back(
element.geometry(), eIdx);
572 neighborScvIndices_.push_back(eIdx);
574 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
575 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
580 std::vector<bool> handledScvf;
582 handledScvf.resize(
element.subEntities(1),
false);
585 for (
const auto& intersection : intersections(gridGeometry().gridView(),
element))
588 if (handledScvf[intersection.indexInInside()])
591 if (intersection.neighbor())
594 const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
595 if (scvfNeighborVolVarIndices[0] < gridGeometry().gridView().size(0))
600 if (scvfNeighborVolVarIndices[0] == gridGeometry().elementMapper().index(*element_))
602 ScvfGridIndexStorage scvIndices({eIdx, scvfNeighborVolVarIndices[0]});
603 neighborScvfs_.emplace_back(intersection,
604 intersection.geometry(),
605 scvFaceIndices[scvfCounter],
609 neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
618 for (
unsigned outsideScvIdx = 0; outsideScvIdx < scvfNeighborVolVarIndices.size(); ++outsideScvIdx)
620 if (scvfNeighborVolVarIndices[outsideScvIdx] == gridGeometry().elementMapper().index(*element_))
622 ScvfGridIndexStorage scvIndices;
623 scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
624 scvIndices[0] = eIdx;
625 std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
626 neighborScvfs_.emplace_back(intersection,
627 intersection.geometry(),
628 scvFaceIndices[scvfCounter],
632 neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
640 handledScvf[intersection.indexInInside()] =
true;
647 else if (intersection.boundary())
650 handledScvf[intersection.indexInInside()] =
true;
659 scvfIndices_.clear();
661 flippedScvfIndices_.clear();
663 neighborScvIndices_.clear();
664 neighborScvfIndices_.clear();
665 neighborScvs_.clear();
666 neighborScvfs_.clear();
667 flippedNeighborScvfIndices_.clear();
669 hasBoundaryScvf_ =
false;
672 std::optional<Element> element_;
673 const GridGeometry* gridGeometryPtr_;
676 std::array<GridIndexType, 1> scvIndices_;
677 std::array<SubControlVolume, 1> scvs_;
679 std::vector<GridIndexType> scvfIndices_;
680 std::vector<SubControlVolumeFace> scvfs_;
681 std::vector<std::vector<GridIndexType>> flippedScvfIndices_;
683 std::vector<GridIndexType> neighborScvIndices_;
684 std::vector<SubControlVolume> neighborScvs_;
686 std::vector<GridIndexType> neighborScvfIndices_;
687 std::vector<SubControlVolumeFace> neighborScvfs_;
688 std::vector<std::vector<GridIndexType>> flippedNeighborScvfIndices_;
690 bool hasBoundaryScvf_ =
false;