diff --git a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh index a93c7ce63970a589ca92cdf883dd9547556e1ee2..2288f3b49d00aa2d83089d6d30224ae23928162d 100644 --- a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh +++ b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh @@ -87,10 +87,11 @@ public: } //! Inserts scvf data + template<typename OutsideGridIndexStorage> void insert(const bool boundary, const GridIndexType scvfIdx, const GridIndexType insideScvIdx, - const std::vector<GridIndexType>& outsideScvIndices) + const OutsideGridIndexStorage& outsideScvIndices) { // this should always be called only once per scvf assert(std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx ) == scvfIndices_.end() diff --git a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh index 44b8f899fe6fdb14221087ea24a8bd92bf36fb6b..66928c912115b17854afe58988f2e4c00fd587f2 100644 --- a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh @@ -378,7 +378,7 @@ private: if (dim < dimWorld) { const auto indexInInside = is.indexInInside(); - if(finishedFacets[indexInInside]) + if (finishedFacets[indexInInside]) continue; else finishedFacets[indexInInside] = true; diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh index 248c0129d9739c625ab49c728ab6f79c0414d3da..c355667c6ce89dae36982ac820648cc26cccf83d 100644 --- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh @@ -69,6 +69,7 @@ class CCMpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using ScvfOutsideGridIndexStorage = typename SubControlVolumeFace::Traits::OutsideGridIndexStorage; using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -185,9 +186,9 @@ public: std::vector<GridIndexType> scvfIndexSet; scvfIndexSet.reserve(MpfaHelper::getNumLocalScvfs(elementGeometry.type())); - // for network grids there might be multiple intersections with the same geometryInInside + // for network grids there might be multiple intersection with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<GridIndexType>> outsideIndices; + std::vector<ScvfOutsideGridIndexStorage> outsideIndices; if (dim < dimWorld) { outsideIndices.resize(element.subEntities(1)); @@ -195,8 +196,7 @@ public: { if (intersection.neighbor()) { - const auto& outside = intersection.outside(); - auto nIdx = this->elementMapper().index(outside); + const auto nIdx = this->elementMapper().index( intersection.outside() ); outsideIndices[intersection.indexInInside()].push_back(nIdx); } } @@ -257,18 +257,11 @@ public: const auto& outsideScvIndices = [&] () { if (!boundary) - { return dim == dimWorld ? - std::vector<GridIndexType>({this->elementMapper().index(is.outside())}) : + ScvfOutsideGridIndexStorage({this->elementMapper().index(is.outside())}) : outsideIndices[indexInInside]; - } else - { - // compute boundary scv idx and increment counter - const GridIndexType bIdx = numScvs + numBoundaryScvf_; - numBoundaryScvf_++; - return std::vector<GridIndexType>(1, bIdx); - } + return ScvfOutsideGridIndexStorage({GridIndexType(numScvs) + numBoundaryScvf_++}); } (); scvfIndexSet.push_back(scvfIdx); @@ -382,7 +375,7 @@ private: // containers storing the global data std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_; std::vector<bool> secondaryInteractionVolumeVertices_; - std::size_t numBoundaryScvf_; + GridIndexType numBoundaryScvf_; // needed for embedded surface and network grids (dim < dimWorld) std::vector<std::vector<GridIndexType>> flipScvfIndices_; @@ -414,6 +407,7 @@ class CCMpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using ScvfOutsideGridIndexStorage = typename SubControlVolumeFace::Traits::OutsideGridIndexStorage; using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); @@ -529,13 +523,13 @@ public: // the element-wise index sets for finite volume geometry const auto numLocalFaces = MpfaHelper::getNumLocalScvfs(elementGeometry.type()); std::vector<GridIndexType> scvfsIndexSet; - std::vector< std::vector<GridIndexType> > neighborVolVarIndexSet; + std::vector<ScvfOutsideGridIndexStorage> neighborVolVarIndexSet; scvfsIndexSet.reserve(numLocalFaces); neighborVolVarIndexSet.reserve(numLocalFaces); // for network grids there might be multiple intersections with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<GridIndexType>> outsideIndices; + std::vector<ScvfOutsideGridIndexStorage> outsideIndices; if (dim < dimWorld) { outsideIndices.resize(element.subEntities(1)); @@ -543,8 +537,7 @@ public: { if (intersection.neighbor()) { - const auto& outside = intersection.outside(); - auto nIdx = this->elementMapper().index(outside); + auto nIdx = this->elementMapper().index( intersection.outside() ); outsideIndices[intersection.indexInInside()].push_back(nIdx); } } @@ -595,18 +588,11 @@ public: const auto& outsideScvIndices = [&] () { if (!boundary) - { return dim == dimWorld ? - std::vector<GridIndexType>({this->elementMapper().index(is.outside())}) : + ScvfOutsideGridIndexStorage({this->elementMapper().index(is.outside())}) : outsideIndices[indexInInside]; - } else - { - // compute boundary scv idx and increment counter - const GridIndexType bIdx = numScvs_ + numBoundaryScvf_; - numBoundaryScvf_++; - return std::vector<GridIndexType>(1, bIdx); - } + return ScvfOutsideGridIndexStorage({GridIndexType(numScvs_) + numBoundaryScvf_++}); } (); // insert the scvf data into the dual grid index set @@ -646,7 +632,7 @@ public: { return scvfIndicesOfScv_[scvIdx]; } //! Returns the neighboring vol var indices for each scvf contained in an scv. - const std::vector< std::vector<GridIndexType> >& neighborVolVarIndices(GridIndexType scvIdx) const + const std::vector<ScvfOutsideGridIndexStorage>& neighborVolVarIndices(GridIndexType scvIdx) const { return neighborVolVarIndices_[scvIdx]; } //! Returns the connectivity map of which dofs @@ -662,12 +648,12 @@ private: // containers storing the global data std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_; - std::vector< std::vector< std::vector<GridIndexType> > > neighborVolVarIndices_; + std::vector<std::vector<ScvfOutsideGridIndexStorage>> neighborVolVarIndices_; std::vector<bool> secondaryInteractionVolumeVertices_; std::vector<bool> isGhostVertex_; - std::size_t numScvs_; - std::size_t numScvf_; - std::size_t numBoundaryScvf_; + GridIndexType numScvs_; + GridIndexType numScvf_; + GridIndexType numBoundaryScvf_; // The grid interaction volume index set GridIVIndexSets ivIndexSets_; diff --git a/dumux/discretization/cellcentered/mpfa/properties.hh b/dumux/discretization/cellcentered/mpfa/properties.hh index ce805e818a37a5fa7f8c5395f284b6fd4d15a26f..aeb2b83479025d7084328b63d81079ad77a1b6d8 100644 --- a/dumux/discretization/cellcentered/mpfa/properties.hh +++ b/dumux/discretization/cellcentered/mpfa/properties.hh @@ -25,9 +25,6 @@ #ifndef DUMUX_CC_MPFA_PROPERTIES_HH #define DUMUX_CC_MPFA_PROPERTIES_HH -#include <dune/common/fvector.hh> -#include <dune/geometry/multilineargeometry.hh> - #include <dumux/common/properties.hh> #include <dumux/assembly/cclocalresidual.hh> @@ -165,60 +162,20 @@ SET_TYPE_PROP(CCMpfaModel, GridVolumeVariables, CCGridVolumeVariables<TypeTag, G SET_PROP(CCMpfaModel, SubControlVolume) { private: - using Grid = typename GET_PROP_TYPE(TypeTag, Grid); - struct ScvGeometryTraits - { - using Geometry = typename Grid::template Codim<0>::Geometry; - using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; - using LocalIndexType = unsigned int; - using Scalar = typename Geometry::ctype; - using GlobalPosition = Dune::FieldVector<Scalar, Geometry::coorddimension>; - }; + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Traits = CCDefaultScvGeometryTraits<GridView>; public: - using type = CCSubControlVolume<ScvGeometryTraits>; + using type = CCSubControlVolume<Traits>; }; //! The sub-control volume face class SET_PROP(CCMpfaModel, SubControlVolumeFace) { private: - using Grid = typename GET_PROP_TYPE(TypeTag, Grid); - static const int dim = Grid::dimension; - static const int dimWorld = Grid::dimensionworld; - - // we use geometry traits that use static corner vectors to and a fixed geometry type - template <class ct> - struct ScvfMLGTraits : public Dune::MultiLinearGeometryTraits<ct> - { - // we use static vectors to store the corners as we know - // the number of corners in advance (2^(dim-1) corners (1<<(dim-1)) - template< int mydim, int cdim > - struct CornerStorage - { - using Type = std::array< Dune::FieldVector< ct, cdim >, (1<<(dim-1)) >; - }; - - // we know all scvfs will have the same geometry type - template< int dim > - struct hasSingleGeometryType - { - static const bool v = true; - static const unsigned int topologyId = Dune::Impl::CubeTopology< dim >::type::id; - }; - }; - - struct ScvfGeometryTraits - { - using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; - using LocalIndexType = unsigned int; - using Scalar = typename Grid::ctype; - using Geometry = Dune::MultiLinearGeometry<Scalar, dim-1, dimWorld, ScvfMLGTraits<Scalar> >; - using CornerStorage = typename ScvfMLGTraits<Scalar>::template CornerStorage<dim-1, dimWorld>::Type; - using GlobalPosition = typename CornerStorage::value_type; - }; - + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Traits = CCMpfaDefaultScvfGeometryTraits<GridView>; public: - using type = Dumux::CCMpfaSubControlVolumeFace< ScvfGeometryTraits>; + using type = Dumux::CCMpfaSubControlVolumeFace<Traits>; }; //! Set the solution vector type for an element diff --git a/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh index 45bd3cc55a86d4b51e1c0102de357429722ef881..dfc14bfc61d970a2db2f3fbfbdb471e1ee27d455 100644 --- a/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh +++ b/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh @@ -25,12 +25,57 @@ #define DUMUX_DISCRETIZATION_CC_MPFA_SUBCONTROLVOLUMEFACE_HH #include <vector> +#include <array> #include <dune/common/version.hh> +#include <dune/common/reservedvector.hh> +#include <dune/common/fvector.hh> #include <dune/geometry/type.hh> +#include <dune/geometry/multilineargeometry.hh> namespace Dumux { +template<class GridView> +struct CCMpfaDefaultScvfGeometryTraits +{ + using Grid = typename GridView::Grid; + + static const int dim = Grid::dimension; + static const int dimWorld = Grid::dimensionworld; + + using Scalar = typename Grid::ctype; + using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; + using LocalIndexType = unsigned int; + using OutsideGridIndexStorage = typename std::conditional_t< (dim<dimWorld), + std::vector<GridIndexType>, + Dune::ReservedVector<GridIndexType, 1> >; + + // we use geometry traits that use static corner vectors to and a fixed geometry type + template <class ct> + struct ScvfMLGTraits : public Dune::MultiLinearGeometryTraits<ct> + { + // we use static vectors to store the corners as we know + // the number of corners in advance (2^(dim-1) corners (1<<(dim-1)) + template< int mydim, int cdim > + struct CornerStorage + { + using Type = std::array< Dune::FieldVector< ct, cdim >, (1<<(dim-1)) >; + }; + + // we know all scvfs will have the same geometry type + template< int dim > + struct hasSingleGeometryType + { + static const bool v = true; + static const unsigned int topologyId = Dune::Impl::CubeTopology< dim >::type::id; + }; + }; + + using Geometry = Dune::MultiLinearGeometry<Scalar, dim-1, dimWorld, ScvfMLGTraits<Scalar> >; + using CornerStorage = typename ScvfMLGTraits<Scalar>::template CornerStorage<dim-1, dimWorld>::Type; + using GlobalPosition = typename CornerStorage::value_type; +}; + /*! * \ingroup CCMpfaDiscretization * \brief Class for a sub control volume face in mpfa methods, i.e a part of the boundary @@ -45,6 +90,7 @@ class CCMpfaSubControlVolumeFace using Scalar = typename ScvfGeometryTraits::Scalar; using GlobalPosition = typename ScvfGeometryTraits::GlobalPosition; using CornerStorage = typename ScvfGeometryTraits::CornerStorage; + using OutsideGridIndexStorage = typename ScvfGeometryTraits::OutsideGridIndexStorage; using Geometry = typename ScvfGeometryTraits::Geometry; public: @@ -73,7 +119,7 @@ public: unsigned int vIdxLocal, GridIndexType scvfIndex, GridIndexType insideScvIdx, - const std::vector<GridIndexType>& outsideScvIndices, + const OutsideGridIndexStorage& outsideScvIndices, Scalar q, bool boundary) : boundary_(boundary) @@ -122,7 +168,7 @@ public: GridIndexType outsideScvIdx(int i = 0) const { return outsideScvIndices_[i]; } //! returns the outside scv indices (can be more than one index for dim < dimWorld) - const std::vector<GridIndexType>& outsideScvIndices() const { return outsideScvIndices_; } + const OutsideGridIndexStorage& outsideScvIndices() const { return outsideScvIndices_; } //! Returns the number of corners std::size_t corners() const { return corners_.size(); } @@ -161,7 +207,7 @@ private: GridIndexType vertexIndex_; GridIndexType scvfIndex_; GridIndexType insideScvIdx_; - std::vector<GridIndexType> outsideScvIndices_; + OutsideGridIndexStorage outsideScvIndices_; unsigned int vIdxInElement_; CornerStorage corners_; diff --git a/dumux/discretization/cellcentered/subcontrolvolume.hh b/dumux/discretization/cellcentered/subcontrolvolume.hh index c9521b8bbe4481579a1b7d376edfbda546523c61..1c6cd9db19025d1affe3ecc7fac2e4450fd80e60 100644 --- a/dumux/discretization/cellcentered/subcontrolvolume.hh +++ b/dumux/discretization/cellcentered/subcontrolvolume.hh @@ -24,11 +24,28 @@ #ifndef DUMUX_DISCRETIZATION_CC_SUBCONTROLVOLUME_HH #define DUMUX_DISCRETIZATION_CC_SUBCONTROLVOLUME_HH +#include <dune/common/fvector.hh> #include <dumux/discretization/subcontrolvolumebase.hh> #include <dumux/common/optional.hh> namespace Dumux { + +/*! + * \ingroup CCDiscretization + * \brief Default traits class to be used for the sub-control volumes + * for the cell-centered finite volume scheme using TPFA + */ +template<class GridView> +struct CCDefaultScvGeometryTraits +{ + using Geometry = typename GridView::template Codim<0>::Geometry; + using GridIndexType = typename GridView::IndexSet::IndexType; + using LocalIndexType = unsigned int; + using Scalar = typename GridView::ctype; + using GlobalPosition = Dune::FieldVector<Scalar, GridView::dimensionworld>; +}; + /*! * \ingroup CCDiscretization * \brief Sub control volumes for cell-centered discretization schemes diff --git a/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh index b77ff57df69394e92020284290216af7897d874f..4ff6ebcdd9f677ee407e0d3ede15d603a76ee542 100644 --- a/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh +++ b/dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_DISCRETIZATION_CCTPFA_FV_ELEMENT_GEOMETRY_HH #define DUMUX_DISCRETIZATION_CCTPFA_FV_ELEMENT_GEOMETRY_HH +#include <algorithm> + #include <dune/common/exceptions.hh> #include <dune/common/iteratorrange.hh> #include <dumux/common/properties.hh> @@ -395,6 +397,8 @@ private: //! create scvs and scvfs of the bound element void makeElementGeometries(const Element& element) { + using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage; + const auto eIdx = fvGridGeometry().elementMapper().index(element); scvs_[0] = SubControlVolume(element.geometry(), eIdx); scvIndices_[0] = eIdx; @@ -416,10 +420,14 @@ private: if (handledScvf[intersection.indexInInside()]) continue; + const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter]; + if (intersection.neighbor() || intersection.boundary()) { - std::vector<IndexType> scvIndices({eIdx}); - scvIndices.insert(scvIndices.end(), neighborVolVarIndices[scvfCounter].begin(), neighborVolVarIndices[scvfCounter].end()); + ScvfGridIndexStorage scvIndices; + scvIndices.resize(scvfNeighborVolVarIndices.size() + 1); + scvIndices[0] = eIdx; + std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1); scvfs_.emplace_back(intersection, intersection.geometry(), scvFaceIndices[scvfCounter], @@ -438,6 +446,8 @@ private: //! create the necessary scvs and scvfs of the neighbor elements to the bound elements void makeNeighborGeometries(const Element& element, const IndexType eIdx) { + using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage; + // create the neighbor scv neighborScvs_.emplace_back(element.geometry(), eIdx); neighborScvIndices_.push_back(eIdx); @@ -459,6 +469,8 @@ private: if (handledScvf[intersection.indexInInside()]) continue; + const auto& scvfNeighborVolVarIndices = neighborVolVarIndices[scvfCounter]; + if (intersection.neighbor()) { // only create subcontrol faces where the outside element is the bound element @@ -466,8 +478,7 @@ private: { if (intersection.outside() == *elementPtr_) { - std::vector<IndexType> scvIndices({eIdx}); - scvIndices.insert(scvIndices.end(), neighborVolVarIndices[scvfCounter].begin(), neighborVolVarIndices[scvfCounter].end()); + ScvfGridIndexStorage scvIndices({eIdx, scvfNeighborVolVarIndices[0]}); neighborScvfs_.emplace_back(intersection, intersection.geometry(), scvFaceIndices[scvfCounter], @@ -483,12 +494,14 @@ private: // (will be optimized away for dim == dimWorld) else { - for (unsigned outsideScvIdx = 0; outsideScvIdx < neighborVolVarIndices[scvfCounter].size(); ++outsideScvIdx) + for (unsigned outsideScvIdx = 0; outsideScvIdx < scvfNeighborVolVarIndices.size(); ++outsideScvIdx) { - if (neighborVolVarIndices[scvfCounter][outsideScvIdx] == fvGridGeometry().elementMapper().index(*elementPtr_)) + if (scvfNeighborVolVarIndices[outsideScvIdx] == fvGridGeometry().elementMapper().index(*elementPtr_)) { - std::vector<IndexType> scvIndices({eIdx}); - scvIndices.insert(scvIndices.end(), neighborVolVarIndices[scvfCounter].begin(), neighborVolVarIndices[scvfCounter].end()); + ScvfGridIndexStorage scvIndices; + scvIndices.resize(scvfNeighborVolVarIndices.size() + 1); + scvIndices[0] = eIdx; + std::copy(scvfNeighborVolVarIndices.begin(), scvfNeighborVolVarIndices.end(), scvIndices.begin()+1); neighborScvfs_.emplace_back(intersection, intersection.geometry(), scvFaceIndices[scvfCounter], diff --git a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh index 520823347a851b3c135c18374cd7145aa9da41f8..08a559b12ade704f4c1d5c9cb77aed080d413c71 100644 --- a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_DISCRETIZATION_CCTPFA_FV_GRID_GEOMETRY_HH #define DUMUX_DISCRETIZATION_CCTPFA_FV_GRID_GEOMETRY_HH +#include <algorithm> + #include <dune/common/version.hh> #include <dumux/discretization/methods.hh> @@ -60,6 +62,7 @@ class CCTpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> using IndexType = typename GridView::IndexSet::IndexType; using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage; using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper); using Element = typename GridView::template Codim<0>::Entity; @@ -154,19 +157,21 @@ public: // for network grids there might be multiple intersection with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<IndexType>> outsideIndices; + std::vector<ScvfGridIndexStorage> outsideIndices; if (dim < dimWorld) { + //! first, push inside index in all neighbor sets outsideIndices.resize(element.subEntities(1)); + std::for_each(outsideIndices.begin(), outsideIndices.end(), [eIdx] (auto& nIndices) { nIndices.push_back(eIdx); }); + + // second, insert neighbors for (const auto& intersection : intersections(this->gridView(), element)) { if (intersection.neighbor()) { - const auto& outside = intersection.outside(); - const auto nIdx = this->elementMapper().index(outside); + const auto nIdx = this->elementMapper().index( intersection.outside() ); outsideIndices[intersection.indexInInside()].push_back(nIdx); } - } } @@ -181,7 +186,7 @@ public: scvfs_.emplace_back(intersection, intersection.geometry(), scvfIdx, - std::vector<IndexType>({eIdx, nIdx}), + ScvfGridIndexStorage({eIdx, nIdx}), false); scvfsIndexSet.push_back(scvfIdx++); } @@ -195,12 +200,10 @@ public: continue; else { - std::vector<IndexType> scvIndices({eIdx}); - scvIndices.insert(scvIndices.end(), outsideIndices[indexInInside].begin(), outsideIndices[indexInInside].end()); scvfs_.emplace_back(intersection, intersection.geometry(), scvfIdx, - scvIndices, + outsideIndices[indexInInside], false); scvfsIndexSet.push_back(scvfIdx++); outsideIndices[indexInInside].clear(); @@ -213,7 +216,7 @@ public: scvfs_.emplace_back(intersection, intersection.geometry(), scvfIdx, - std::vector<IndexType>({eIdx, this->gridView().size(0) + numBoundaryScvf_++}), + ScvfGridIndexStorage({eIdx, this->gridView().size(0) + numBoundaryScvf_++}), true); scvfsIndexSet.push_back(scvfIdx++); } @@ -320,6 +323,7 @@ class CCTpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using IndexType = typename GridView::IndexSet::IndexType; using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage; using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper); using Element = typename GridView::template Codim<0>::Entity; @@ -331,6 +335,10 @@ class CCTpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> using CoordScalar = typename GridView::ctype; using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>; + using NeighborVolVarIndices = typename std::conditional_t< (dim<dimWorld), + ScvfGridIndexStorage, + Dune::ReservedVector<IndexType, 1> >; + public: //! export discretization method static constexpr DiscretizationMethods discretizationMethod = DiscretizationMethods::CCTpfa; @@ -399,13 +407,13 @@ public: // the element-wise index sets for finite volume geometry auto numLocalFaces = element.subEntities(1); std::vector<IndexType> scvfsIndexSet; - std::vector<std::vector<IndexType>> neighborVolVarIndexSet; + std::vector<NeighborVolVarIndices> neighborVolVarIndexSet; scvfsIndexSet.reserve(numLocalFaces); neighborVolVarIndexSet.reserve(numLocalFaces); // for network grids there might be multiple intersection with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<IndexType>> outsideIndices; + std::vector<NeighborVolVarIndices> outsideIndices; if (dim < dimWorld) { outsideIndices.resize(numLocalFaces); @@ -413,11 +421,9 @@ public: { if (intersection.neighbor()) { - const auto& outside = intersection.outside(); - const auto nIdx = this->elementMapper().index(outside); + const auto nIdx = this->elementMapper().index(intersection.outside()); outsideIndices[intersection.indexInInside()].push_back(nIdx); } - } } @@ -430,7 +436,7 @@ public: { scvfsIndexSet.push_back(numScvf_++); const auto nIdx = this->elementMapper().index(intersection.outside()); - neighborVolVarIndexSet.push_back({nIdx}); + neighborVolVarIndexSet.emplace_back(NeighborVolVarIndices({nIdx})); } // this is for network grids // (will be optimized away of dim == dimWorld) @@ -443,7 +449,7 @@ public: else { scvfsIndexSet.push_back(numScvf_++); - neighborVolVarIndexSet.push_back(outsideIndices[indexInInside]); + neighborVolVarIndexSet.emplace_back(std::move(outsideIndices[indexInInside])); outsideIndices[indexInInside].clear(); } } @@ -452,7 +458,7 @@ public: else if (intersection.boundary()) { scvfsIndexSet.push_back(numScvf_++); - neighborVolVarIndexSet.push_back({numScvs_ + numBoundaryScvf_++}); + neighborVolVarIndexSet.emplace_back(NeighborVolVarIndices({numScvs_ + numBoundaryScvf_++})); } } @@ -469,7 +475,7 @@ public: { return scvfIndicesOfScv_[scvIdx]; } //! Return the neighbor volVar indices for all scvfs in the scv with index scvIdx - const std::vector<std::vector<IndexType>>& neighborVolVarIndices(IndexType scvIdx) const + const std::vector<NeighborVolVarIndices>& neighborVolVarIndices(IndexType scvIdx) const { return neighborVolVarIndices_[scvIdx]; } /*! @@ -491,7 +497,7 @@ private: //! vectors that store the global data std::vector<std::vector<IndexType>> scvfIndicesOfScv_; - std::vector<std::vector<std::vector<IndexType>>> neighborVolVarIndices_; + std::vector<std::vector<NeighborVolVarIndices>> neighborVolVarIndices_; }; } // end namespace Dumux diff --git a/dumux/discretization/cellcentered/tpfa/properties.hh b/dumux/discretization/cellcentered/tpfa/properties.hh index c9262c4b141561ec9b65bdec6de69c0019461f51..1524324e2874c8101019fca8b60ceb4d615192f4 100644 --- a/dumux/discretization/cellcentered/tpfa/properties.hh +++ b/dumux/discretization/cellcentered/tpfa/properties.hh @@ -99,52 +99,20 @@ public: SET_PROP(CCTpfaModel, SubControlVolume) { private: - using Grid = typename GET_PROP_TYPE(TypeTag, Grid); - struct ScvGeometryTraits - { - using Geometry = typename Grid::template Codim<0>::Geometry; - using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; - using LocalIndexType = unsigned int; - using Scalar = typename Grid::ctype; - using GlobalPosition = Dune::FieldVector<Scalar, Grid::dimensionworld>; - }; + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Traits = CCDefaultScvGeometryTraits<GridView>; public: - using type = CCSubControlVolume<ScvGeometryTraits>; + using type = CCSubControlVolume<Traits>; }; //! The sub control volume face SET_PROP(CCTpfaModel, SubControlVolumeFace) { private: - using Grid = typename GET_PROP_TYPE(TypeTag, Grid); - static constexpr int dim = Grid::dimension; - static constexpr int dimWorld = Grid::dimensionworld; - - // we use geometry traits that use static corner vectors to and a fixed geometry type - template <class ct> - struct ScvfMLGTraits : public Dune::MultiLinearGeometryTraits<ct> - { - // we use static vectors to store the corners as we know - // the number of corners in advance (2^(dim-1) corners (1<<(dim-1)) - template< int mydim, int cdim > - struct CornerStorage - { - using Type = Dune::ReservedVector< Dune::FieldVector< ct, cdim >, (1<<(dim-1)) >; - }; - }; - - struct ScvfGeometryTraits - { - using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; - using LocalIndexType = unsigned int; - using Scalar = typename Grid::ctype; - using Geometry = Dune::MultiLinearGeometry<Scalar, dim-1, dimWorld, ScvfMLGTraits<Scalar> >; - using CornerStorage = typename ScvfMLGTraits<Scalar>::template CornerStorage<dim-1, dimWorld>::Type; - using GlobalPosition = typename CornerStorage::value_type; - using BoundaryFlag = Dumux::BoundaryFlag<Grid>; - }; + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Traits = CCTpfaDefaultScvfGeometryTraits<GridView>; public: - using type = Dumux::CCTpfaSubControlVolumeFace<ScvfGeometryTraits>; + using type = Dumux::CCTpfaSubControlVolumeFace<Traits>; }; //! Set the solution vector type for an element diff --git a/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh index 58c837af98aa0982817d2e04d1f706a75baa93c9..755dbeef0dd2fa0c3aa276a31b85803fbe924ab7 100644 --- a/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh +++ b/dumux/discretization/cellcentered/tpfa/subcontrolvolumeface.hh @@ -31,6 +31,45 @@ namespace Dumux { +/*! + * \ingroup CCDiscretization + * \brief Default traits class to be used for the sub-control volume faces + * for the cell-centered finite volume scheme using TPFA + */ +template<class GridView> +struct CCTpfaDefaultScvfGeometryTraits +{ + using Grid = typename GridView::Grid; + + static constexpr int dim = Grid::dimension; + static constexpr int dimWorld = Grid::dimensionworld; + + using Scalar = typename Grid::ctype; + using GridIndexType = typename Grid::LeafGridView::IndexSet::IndexType; + using LocalIndexType = unsigned int; + using GridIndexStorage = typename std::conditional_t< (dim<dimWorld), + std::vector<GridIndexType>, + Dune::ReservedVector<GridIndexType, 2> >; + + // we use geometry traits that use static corner vectors to and a fixed geometry type + template <class ct> + struct ScvfMLGTraits : public Dune::MultiLinearGeometryTraits<ct> + { + // we use static vectors to store the corners as we know + // the number of corners in advance (2^(dim-1) corners (1<<(dim-1)) + template< int mydim, int cdim > + struct CornerStorage + { + using Type = Dune::ReservedVector< Dune::FieldVector< ct, cdim >, (1<<(dim-1)) >; + }; + }; + + using Geometry = Dune::MultiLinearGeometry<Scalar, dim-1, dimWorld, ScvfMLGTraits<Scalar> >; + using CornerStorage = typename ScvfMLGTraits<Scalar>::template CornerStorage<dim-1, dimWorld>::Type; + using GlobalPosition = typename CornerStorage::value_type; + using BoundaryFlag = Dumux::BoundaryFlag<Grid>; +}; + /*! * \ingroup CCTpfaDiscretization * \brief The sub control volume face @@ -43,6 +82,7 @@ class CCTpfaSubControlVolumeFace : public SubControlVolumeFaceBase<CCTpfaSubCont using Scalar = typename ScvfGeometryTraits::Scalar; using GlobalPosition = typename ScvfGeometryTraits::GlobalPosition; using CornerStorage = typename ScvfGeometryTraits::CornerStorage; + using GridIndexStorage = typename ScvfGeometryTraits::GridIndexStorage; using Geometry = typename ScvfGeometryTraits::Geometry; using BoundaryFlag = typename ScvfGeometryTraits::BoundaryFlag; @@ -66,7 +106,7 @@ public: CCTpfaSubControlVolumeFace(const Intersection& is, const typename Intersection::Geometry& isGeometry, GridIndexType scvfIndex, - const std::vector<GridIndexType>& scvIndices, + const GridIndexStorage& scvIndices, bool isBoundary) : ParentType() , geomType_(isGeometry.type()) @@ -165,7 +205,7 @@ private: GlobalPosition center_; GlobalPosition unitOuterNormal_; GridIndexType scvfIndex_; - std::vector<GridIndexType> scvIndices_; + GridIndexStorage scvIndices_; bool boundary_; BoundaryFlag boundaryFlag_; };