213 using GridView =
typename GG::GridView;
217 static const int dim = GridView::dimension;
218 static const int dimWorld = GridView::dimensionworld;
222 using Element =
typename GridView::template Codim<0>::Entity;
242 if (scvIdx == scvIndices_[0])
245 return neighborScvs_[findLocalIndex(scvIdx, neighborScvIndices_)];
252 auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
253 if (it != scvfIndices_.end())
254 return scvfs_[std::distance(scvfIndices_.begin(), it)];
256 return neighborScvfs_[findLocalIndex(scvfIdx, neighborScvfIndices_)];
263 auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
264 if (it != scvfIndices_.end())
266 const auto localScvfIdx = std::distance(scvfIndices_.begin(), it);
267 return neighborScvfs_[flippedScvfIndices_[localScvfIdx][outsideScvIdx]];
271 const auto localScvfIdx = findLocalIndex(scvfIdx, neighborScvfIndices_);
272 const auto localFlippedIndex = flippedNeighborScvfIndices_[localScvfIdx][outsideScvIdx];
273 if (localFlippedIndex < scvfs_.size())
274 return scvfs_[localFlippedIndex];
276 return neighborScvfs_[localFlippedIndex - scvfs_.size()];
285 friend inline Dune::IteratorRange<typename std::array<SubControlVolume, 1>::const_iterator>
288 using IteratorType =
typename std::array<SubControlVolume, 1>::const_iterator;
289 return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
297 friend inline Dune::IteratorRange<typename std::vector<SubControlVolumeFace>::const_iterator>
300 using IteratorType =
typename std::vector<SubControlVolumeFace>::const_iterator;
301 return Dune::IteratorRange<IteratorType>(g.scvfs_.begin(), g.scvfs_.end());
306 {
return scvs_.size(); }
310 {
return scvfs_.size(); }
320 return std::move(*
this);
336 return std::move(*
this);
346 {
return static_cast<bool>(element_); }
350 {
return *element_; }
354 {
return *gridGeometryPtr_; }
358 {
return hasBoundaryScvf_; }
363 void bind_(
const Element& element)
365 bindElement_(element);
367 neighborScvs_.reserve(element.subEntities(1));
368 neighborScvfIndices_.reserve(element.subEntities(1));
369 neighborScvfs_.reserve(element.subEntities(1));
371 std::vector<GridIndexType> handledNeighbors;
372 handledNeighbors.reserve(element.subEntities(1));
374 for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
377 if (intersection.neighbor())
379 const auto outside = intersection.outside();
380 const auto outsideIdx = gridGeometry().elementMapper().index(outside);
383 if ( std::find(handledNeighbors.begin(), handledNeighbors.end(), outsideIdx) == handledNeighbors.end() )
385 makeNeighborGeometries(outside, outsideIdx);
386 handledNeighbors.push_back(outsideIdx);
392 if (dim < dimWorld || gridGeometry().isPeriodic())
394 flippedScvfIndices_.resize(scvfs_.size());
395 for (
unsigned int localScvfIdx = 0; localScvfIdx < scvfs_.size(); ++localScvfIdx)
397 const auto& scvf = scvfs_[localScvfIdx];
401 flippedScvfIndices_[localScvfIdx].resize(scvf.numOutsideScvs());
402 for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < scvf.numOutsideScvs(); ++localOutsideScvIdx)
404 const auto globalOutsideScvIdx = scvf.outsideScvIdx(localOutsideScvIdx);
405 for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
407 if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
409 flippedScvfIndices_[localScvfIdx][localOutsideScvIdx] = localNeighborScvfIdx;
416 flippedNeighborScvfIndices_.resize(neighborScvfs_.size());
417 for (
unsigned int localScvfIdx = 0; localScvfIdx < neighborScvfs_.size(); ++localScvfIdx)
419 const auto& neighborScvf = neighborScvfs_[localScvfIdx];
420 flippedNeighborScvfIndices_[localScvfIdx].resize(neighborScvf.numOutsideScvs());
421 for (
unsigned int localOutsideScvIdx = 0; localOutsideScvIdx < neighborScvf.numOutsideScvs(); ++localOutsideScvIdx)
423 flippedNeighborScvfIndices_[localScvfIdx][localOutsideScvIdx] = findFlippedScvfIndex_(neighborScvf.insideScvIdx(), neighborScvf.outsideScvIdx(localOutsideScvIdx));
430 void bindElement_(
const Element& element)
434 scvfs_.reserve(
element.subEntities(1));
435 scvfIndices_.reserve(
element.subEntities(1));
436 makeElementGeometries(element);
439 GridIndexType findFlippedScvfIndex_(GridIndexType insideScvIdx, GridIndexType globalOutsideScvIdx)
441 for (
unsigned int localNeighborScvfIdx = 0; localNeighborScvfIdx < neighborScvfs_.size(); ++localNeighborScvfIdx)
443 if (neighborScvfs_[localNeighborScvfIdx].insideScvIdx() == globalOutsideScvIdx)
445 return scvfs_.size() + localNeighborScvfIdx;
450 for (
unsigned int localOutsideScvfIdx = 0; localOutsideScvfIdx < scvfs_.size(); ++localOutsideScvfIdx)
452 const auto& outsideScvf = scvfs_[localOutsideScvfIdx];
453 for (
unsigned int j = 0; j < outsideScvf.numOutsideScvs(); ++j)
455 if (outsideScvf.outsideScvIdx(j) == insideScvIdx)
457 return localOutsideScvfIdx;
462 DUNE_THROW(Dune::InvalidStateException,
"No flipped version of this scvf found!");
466 void makeElementGeometries(
const Element& element)
468 using ScvfGridIndexStorage =
typename SubControlVolumeFace::Traits::GridIndexStorage;
470 const auto eIdx = gridGeometry().elementMapper().index(element);
471 scvs_[0] = SubControlVolume(
element.geometry(), eIdx);
472 scvIndices_[0] = eIdx;
474 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
475 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
480 std::vector<bool> handledScvf;
482 handledScvf.resize(
element.subEntities(1),
false);
485 for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
488 if (handledScvf[intersection.indexInInside()])
491 const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
492 if (intersection.neighbor() || intersection.boundary())
494 ScvfGridIndexStorage scvIndices;
495 scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
496 scvIndices[0] = eIdx;
497 std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
499 const bool onBoundary = intersection.boundary() && !intersection.neighbor();
500 hasBoundaryScvf_ = (hasBoundaryScvf_ || onBoundary);
502 scvfs_.emplace_back(intersection,
503 intersection.geometry(),
504 scvFaceIndices[scvfCounter],
507 scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
512 handledScvf[intersection.indexInInside()] =
true;
518 void makeNeighborGeometries(
const Element& element,
const GridIndexType eIdx)
520 using ScvfGridIndexStorage =
typename SubControlVolumeFace::Traits::GridIndexStorage;
523 neighborScvs_.emplace_back(
element.geometry(), eIdx);
524 neighborScvIndices_.push_back(eIdx);
526 const auto& scvFaceIndices = gridGeometry().scvfIndicesOfScv(eIdx);
527 const auto& neighborVolVarIndices = gridGeometry().neighborVolVarIndices(eIdx);
532 std::vector<bool> handledScvf;
534 handledScvf.resize(
element.subEntities(1),
false);
537 for (
const auto& intersection : intersections(gridGeometry().gridView(), element))
540 if (handledScvf[intersection.indexInInside()])
543 if (intersection.neighbor())
546 const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter];
547 if (scvfNeighborVolVarIndices[0] < gridGeometry().gridView().size(0))
552 if (scvfNeighborVolVarIndices[0] == gridGeometry().elementMapper().index(*element_))
554 ScvfGridIndexStorage scvIndices({eIdx, scvfNeighborVolVarIndices[0]});
555 neighborScvfs_.emplace_back(intersection,
556 intersection.geometry(),
557 scvFaceIndices[scvfCounter],
561 neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
570 for (
unsigned outsideScvIdx = 0; outsideScvIdx < scvfNeighborVolVarIndices.size(); ++outsideScvIdx)
572 if (scvfNeighborVolVarIndices[outsideScvIdx] == gridGeometry().elementMapper().index(*element_))
574 ScvfGridIndexStorage scvIndices;
575 scvIndices.resize(scvfNeighborVolVarIndices.size() + 1);
576 scvIndices[0] = eIdx;
577 std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1);
578 neighborScvfs_.emplace_back(intersection,
579 intersection.geometry(),
580 scvFaceIndices[scvfCounter],
584 neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
592 handledScvf[intersection.indexInInside()] =
true;
599 else if (intersection.boundary())
602 handledScvf[intersection.indexInInside()] =
true;
608 const LocalIndexType findLocalIndex(
const GridIndexType idx,
609 const std::vector<GridIndexType>& indices)
const
611 auto it = std::find(indices.begin(), indices.end(), idx);
612 assert(it != indices.end() &&
"Could not find the scv/scvf! Make sure to properly bind this class!");
613 return std::distance(indices.begin(), it);
620 scvfIndices_.clear();
622 flippedScvfIndices_.clear();
624 neighborScvIndices_.clear();
625 neighborScvfIndices_.clear();
626 neighborScvs_.clear();
627 neighborScvfs_.clear();
628 flippedNeighborScvfIndices_.clear();
630 hasBoundaryScvf_ =
false;
633 std::optional<Element> element_;
634 const GridGeometry* gridGeometryPtr_;
637 std::array<GridIndexType, 1> scvIndices_;
638 std::array<SubControlVolume, 1> scvs_;
640 std::vector<GridIndexType> scvfIndices_;
641 std::vector<SubControlVolumeFace> scvfs_;
642 std::vector<std::vector<GridIndexType>> flippedScvfIndices_;
644 std::vector<GridIndexType> neighborScvIndices_;
645 std::vector<SubControlVolume> neighborScvs_;
647 std::vector<GridIndexType> neighborScvfIndices_;
648 std::vector<SubControlVolumeFace> neighborScvfs_;
649 std::vector<std::vector<GridIndexType>> flippedNeighborScvfIndices_;
651 bool hasBoundaryScvf_ =
false;