From 92caa4f013b77108f087fa1ea5e43cdb2ea25fa2 Mon Sep 17 00:00:00 2001 From: Kilian <kilian.weishaupt@iws.uni-stuttgart.de> Date: Wed, 27 Feb 2019 17:50:01 +0100 Subject: [PATCH] [freeflow][discretization] Adapt freeflow for compile time order definition --- dumux/common/properties.hh | 2 + .../staggered/freeflow/connectivitymap.hh | 38 +++-- .../staggered/freeflow/facevariables.hh | 113 ++++++++----- .../freeflow/fvgridgeometrytraits.hh | 6 +- .../staggered/freeflow/properties.hh | 14 +- .../freeflow/staggeredgeometryhelper.hh | 91 +++++++--- .../freeflow/subcontrolvolumeface.hh | 11 +- dumux/freeflow/higherorderapproximation.hh | 12 +- .../navierstokes/staggered/fluxvariables.hh | 158 ++++++++++++------ 9 files changed, 297 insertions(+), 148 deletions(-) diff --git a/dumux/common/properties.hh b/dumux/common/properties.hh index d3ce6cfa36..3dd939e20f 100644 --- a/dumux/common/properties.hh +++ b/dumux/common/properties.hh @@ -234,6 +234,8 @@ template<class TypeTag, class MyTypeTag> struct StaggeredFaceSolution { using type = UndefinedProperty; }; //!< A vector containing the solution for a face (similar to ElementSolution) template<class TypeTag, class MyTypeTag> struct EnableGridFaceVariablesCache { using type = UndefinedProperty; }; //!< Switch on/off caching of face variables +template<class TypeTag, class MyTypeTag> +struct UpwindGeometryOrder { using type = UndefinedProperty; }; //!< Specifies the order of the upwinding scheme (1 == basic upwinding, 2 == higher order) ///////////////////////////////////////////////////////////// // Properties used by the mpnc model diff --git a/dumux/discretization/staggered/freeflow/connectivitymap.hh b/dumux/discretization/staggered/freeflow/connectivitymap.hh index e43321f1c0..7622726ec6 100644 --- a/dumux/discretization/staggered/freeflow/connectivitymap.hh +++ b/dumux/discretization/staggered/freeflow/connectivitymap.hh @@ -54,6 +54,8 @@ class StaggeredFreeFlowConnectivityMap using Stencil = std::vector<GridIndexType>; + static constexpr bool useHigherOrder = false; //TODO + public: //! Update the map and prepare the stencils @@ -186,24 +188,9 @@ private: { if(stencil.empty()) { - for(int i = 0; i < stencilOrder_ - 1; i++) - { - if(scvf.hasBackwardNeighbor(i)) - { - stencil.push_back(scvf.axisData().inAxisBackwardDofs[i]); - } - } - stencil.push_back(scvf.axisData().selfDof); stencil.push_back(scvf.axisData().oppositeDof); - - for(int i = 0; i < stencilOrder_ - 1; i++) - { - if(scvf.hasForwardNeighbor(i)) - { - stencil.push_back(scvf.axisData().inAxisForwardDofs[i]); - } - } + addHigherOrderInAxisDofs(std::integral_constant<bool, useHigherOrder>{}, scvf, stencil); } for(const auto& data : scvf.pairData()) @@ -224,6 +211,25 @@ private: } } + void addHigherOrderInAxisDofs(std::false_type, const SubControlVolumeFace& scvf, Stencil& stencil) {} + + void addHigherOrderInAxisDofs(std::true_type, const SubControlVolumeFace& scvf, Stencil& stencil) + { + for (int i = 0; i < stencilOrder_ - 1; i++) + { + if (scvf.hasBackwardNeighbor(i)) + { + stencil.push_back(scvf.axisData().inAxisBackwardDofs[i]); + } + + if (scvf.hasForwardNeighbor(i)) + { + stencil.push_back(scvf.axisData().inAxisForwardDofs[i]); + } + } + } + + CellCenterToCellCenterMap cellCenterToCellCenterMap_; CellCenterToFaceMap cellCenterToFaceMap_; FaceToCellCenterMap faceToCellCenterMap_; diff --git a/dumux/discretization/staggered/freeflow/facevariables.hh b/dumux/discretization/staggered/freeflow/facevariables.hh index e227cfdc04..2f1943d9b8 100644 --- a/dumux/discretization/staggered/freeflow/facevariables.hh +++ b/dumux/discretization/staggered/freeflow/facevariables.hh @@ -29,17 +29,42 @@ namespace Dumux { +namespace Detail { + +template<class Scalar, int geometryOrder> +struct InAxisVelocities; + +template<class Scalar> +struct InAxisVelocities<Scalar, 1> +{ + Scalar self = 0.0; + Scalar opposite = 0.0; +}; + +template<class Scalar, int geometryOrder> +struct InAxisVelocities +{ + Scalar self = 0.0; + Scalar opposite = 0.0; + std::array<Scalar, geometryOrder-1> forward{}; + std::array<Scalar, geometryOrder-1> backward{}; +}; + +} + /*! * \ingroup StaggeredDiscretization * \brief The face variables class for free flow staggered grid models. * Contains all relevant velocities for the assembly of the momentum balance. */ -template<class FacePrimaryVariables, int dim> +template<class FacePrimaryVariables, int dim, int geometryOrder> // TODO doc class StaggeredFaceVariables { static constexpr int numPairs = (dim == 2) ? 2 : 4; - static constexpr int order = 2; + static constexpr bool useHigherOrder = geometryOrder > 1; + using Scalar = typename FacePrimaryVariables::block_type; + using InAxisVelocities = Detail::InAxisVelocities<Scalar, geometryOrder>; public: @@ -50,7 +75,7 @@ public: */ void updateOwnFaceOnly(const FacePrimaryVariables& priVars) { - velocitySelf_ = priVars[0]; + inAxisVelocities_.self = priVars[0]; } /*! @@ -71,52 +96,30 @@ public: const FVElementGeometry& fvGeometry, const SubControlVolumeFace& scvf) { - velocitySelf_ = faceSol[scvf.dofIndex()]; - velocityOpposite_ = faceSol[scvf.dofIndexOpposingFace()]; + inAxisVelocities_.self = faceSol[scvf.dofIndex()]; + inAxisVelocities_.opposite = faceSol[scvf.dofIndexOpposingFace()]; - // treat the velocity forward of the self face i.e. the face that is - // forward wrt the self face by degree i - velocityForward_.fill(0.0); - for (int i = 0; i < scvf.axisData().inAxisForwardDofs.size(); i++) - { - if(!(scvf.axisData().inAxisForwardDofs[i] < 0)) - { - velocityForward_[i]= faceSol[scvf.axisData().inAxisForwardDofs[i]]; - } - } - - // treat the velocity at the first backward face i.e. the face that is - // behind the opposite face by degree i - velocityBackward_.fill(0.0); - for (int i = 0; i < scvf.axisData().inAxisBackwardDofs.size(); i++) - { - if(!(scvf.axisData().inAxisBackwardDofs[i] < 0)) - { - velocityBackward_[i] = faceSol[scvf.axisData().inAxisBackwardDofs[i]]; - } - } + addHigherOrderInAxisVelocities(std::integral_constant<bool, useHigherOrder>{}, faceSol, scvf); // handle all sub faces - for(int i = 0; i < velocityParallel_.size(); ++i) + for (int i = 0; i < velocityParallel_.size(); ++i) velocityParallel_[i].fill(0.0); - for(int i = 0; i < scvf.pairData().size(); ++i) + for (int i = 0; i < scvf.pairData().size(); ++i) { const auto& subFaceData = scvf.pairData(i); // treat the velocities normal to the face velocityNormalInside_[i] = faceSol[subFaceData.normalPair.first]; - if(scvf.hasOuterNormal(i)) + if (scvf.hasOuterNormal(i)) velocityNormalOutside_[i] = faceSol[subFaceData.normalPair.second]; // treat the velocities parallel to the self face - for(int j = 0; j < subFaceData.parallelDofs.size(); j++) + for (int j = 0; j < geometryOrder; j++) { - if(scvf.hasParallelNeighbor(i,j)) - { + if (scvf.hasParallelNeighbor(i,j)) velocityParallel_[i][j] = faceSol[subFaceData.parallelDofs[j]]; - } } } } @@ -126,7 +129,7 @@ public: */ Scalar velocitySelf() const { - return velocitySelf_; + return inAxisVelocities_.self; } /*! @@ -134,7 +137,7 @@ public: */ Scalar velocityOpposite() const { - return velocityOpposite_; + return inAxisVelocities_.opposite; } /*! @@ -142,9 +145,10 @@ public: * * \param backwardIdx The index describing how many faces backward this dof is from the opposite face */ + template<bool enable = useHigherOrder, std::enable_if_t<enable, int> = 0> Scalar velocityBackward(const int backwardIdx) const { - return velocityBackward_[backwardIdx]; + return inAxisVelocities_.backward[backwardIdx]; } /*! @@ -152,9 +156,10 @@ public: * * \param forwardIdx The index describing how many faces forward this dof is of the self face */ + template<bool enable = useHigherOrder, std::enable_if_t<enable, int> = 0> Scalar velocityForward(const int forwardIdx) const { - return velocityForward_[forwardIdx]; + return inAxisVelocities_.forward[forwardIdx]; } /*! @@ -163,7 +168,7 @@ public: * \param localSubFaceIdx The local index of the subface * \param parallelDegreeIdx The index describing how many faces parallel this dof is of the parallel face */ - Scalar velocityParallel(const int localSubFaceIdx, const int parallelDegreeIdx) const + Scalar velocityParallel(const int localSubFaceIdx, const int parallelDegreeIdx = 0) const { return velocityParallel_[localSubFaceIdx][parallelDegreeIdx]; } @@ -189,11 +194,33 @@ public: } private: - Scalar velocitySelf_; - Scalar velocityOpposite_; - std::array<Scalar, order-1> velocityForward_; - std::array<Scalar, order-1> velocityBackward_; - std::array<std::array<Scalar, order>, numPairs> velocityParallel_; + + template<class SolVector, class SubControlVolumeFace> + void addHigherOrderInAxisVelocities(std::false_type, const SolVector& faceSol, const SubControlVolumeFace& scvf) {} + + template<class SolVector, class SubControlVolumeFace> + void addHigherOrderInAxisVelocities(std::true_type, const SolVector& faceSol, const SubControlVolumeFace& scvf) + { + + // treat the velocity forward of the self face i.e. the face that is + // forward wrt the self face by degree i + for (int i = 0; i < scvf.axisData().inAxisForwardDofs.size(); i++) + { + if (!(scvf.axisData().inAxisForwardDofs[i] < 0)) + inAxisVelocities_.forward[i]= faceSol[scvf.axisData().inAxisForwardDofs[i]]; + } + + // treat the velocity at the first backward face i.e. the face that is + // behind the opposite face by degree i + for (int i = 0; i < scvf.axisData().inAxisBackwardDofs.size(); i++) + { + if (!(scvf.axisData().inAxisBackwardDofs[i] < 0)) + inAxisVelocities_.backward[i] = faceSol[scvf.axisData().inAxisBackwardDofs[i]]; + } + } + + InAxisVelocities inAxisVelocities_; + std::array<std::array<Scalar, geometryOrder>, numPairs> velocityParallel_; std::array<Scalar, numPairs> velocityNormalInside_; std::array<Scalar, numPairs> velocityNormalOutside_; diff --git a/dumux/discretization/staggered/freeflow/fvgridgeometrytraits.hh b/dumux/discretization/staggered/freeflow/fvgridgeometrytraits.hh index 4b88982ba9..c882c55a39 100644 --- a/dumux/discretization/staggered/freeflow/fvgridgeometrytraits.hh +++ b/dumux/discretization/staggered/freeflow/fvgridgeometrytraits.hh @@ -39,14 +39,14 @@ namespace Dumux { * \ingroup StaggeredDiscretization * \brief Default traits for the finite volume grid geometry. */ -template<class GridView, class MapperTraits = DefaultMapperTraits<GridView>> +template<class GridView, int geometryOrder, class MapperTraits = DefaultMapperTraits<GridView>> struct StaggeredFreeFlowDefaultFVGridGeometryTraits : public MapperTraits { using SubControlVolume = CCSubControlVolume<GridView>; - using SubControlVolumeFace = FreeFlowStaggeredSubControlVolumeFace<GridView>; + using SubControlVolumeFace = FreeFlowStaggeredSubControlVolumeFace<GridView, geometryOrder>; using IntersectionMapper = ConformingGridIntersectionMapper<GridView>; - using GeometryHelper = FreeFlowStaggeredGeometryHelper<GridView>; + using GeometryHelper = FreeFlowStaggeredGeometryHelper<GridView, geometryOrder>; struct DofTypeIndices { diff --git a/dumux/discretization/staggered/freeflow/properties.hh b/dumux/discretization/staggered/freeflow/properties.hh index 3075fc93c6..3c568c7d29 100644 --- a/dumux/discretization/staggered/freeflow/properties.hh +++ b/dumux/discretization/staggered/freeflow/properties.hh @@ -81,9 +81,10 @@ template<class TypeTag> struct FVGridGeometry<TypeTag, TTag::StaggeredFreeFlowModel> { private: - using GridView = GetPropType<TypeTag, Properties::GridView>; - using Traits = StaggeredFreeFlowDefaultFVGridGeometryTraits<GridView>; + static constexpr auto upwindGeometryOrder = getPropValue<TypeTag, Properties::UpwindGeometryOrder>(); static constexpr bool enableCache = getPropValue<TypeTag, Properties::EnableFVGridGeometryCache>(); + using GridView = GetPropType<TypeTag, Properties::GridView>; + using Traits = StaggeredFreeFlowDefaultFVGridGeometryTraits<GridView, upwindGeometryOrder>; public: using type = StaggeredFVGridGeometry<GridView, enableCache, Traits>; }; @@ -95,8 +96,9 @@ struct FaceVariables<TypeTag, TTag::StaggeredFreeFlowModel> private: using FacePrimaryVariables = GetPropType<TypeTag, Properties::FacePrimaryVariables>; using GridView = GetPropType<TypeTag, Properties::GridView>; + static constexpr auto upwindGeometryOrder = getPropValue<TypeTag, Properties::UpwindGeometryOrder>(); public: - using type = StaggeredFaceVariables<FacePrimaryVariables, GridView::dimension>; + using type = StaggeredFaceVariables<FacePrimaryVariables, GridView::dimension, upwindGeometryOrder>; }; //! Set the default global volume variables cache vector class @@ -128,6 +130,12 @@ struct VelocityOutput<TypeTag, TTag::StaggeredFreeFlowModel> GetPropType<TypeTag, Properties::SolutionVector>>; }; +/*! + * \brief Set the order of the upwinding scheme to 1 by default. + */ +template<class TypeTag> +struct UpwindGeometryOrder<TypeTag, TTag::StaggeredFreeFlowModel> { static constexpr int value = 1; }; + } // namespace Properties } // namespace Dumux diff --git a/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh b/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh index 6990c0daed..0872330b0e 100644 --- a/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh +++ b/dumux/discretization/staggered/freeflow/staggeredgeometryhelper.hh @@ -43,13 +43,20 @@ template<class Scalar, class GlobalPosition, int geometryOrder> struct PairData { std::array<int, geometryOrder> parallelDofs; - std::array<Scalar, geometryOrder+1> parallelDistances; - std::pair<signed int,signed int> normalPair; + std::array<Scalar, geometryOrder+1/*geometryOrder*/> parallelDistances; // TODO + std::pair<signed int, signed int> normalPair; int localNormalFaceIdx; Scalar normalDistance; GlobalPosition virtualFirstParallelFaceDofPos; }; + +/*! + * \ingroup StaggeredDiscretization + * \brief In Axis Data stored per sub face + */ +template<class Scalar, int geometryOrder> +struct AxisData; /*! * \ingroup StaggeredDiscretization * \brief In Axis Data stored per sub face @@ -57,6 +64,14 @@ struct PairData template<class Scalar, int geometryOrder> struct AxisData { + AxisData() + { + inAxisForwardDofs.fill(-1); + inAxisBackwardDofs.fill(-1); + inAxisForwardDistances.fill(0); + inAxisBackwardDistances.fill(0); + } + int selfDof; int oppositeDof; std::array<int, geometryOrder-1> inAxisForwardDofs; @@ -66,6 +81,21 @@ struct AxisData std::array<Scalar, geometryOrder-1> inAxisBackwardDistances; }; +/*! + * \ingroup StaggeredDiscretization + * \brief In Axis Data stored per sub face + */ +template<class Scalar> +struct AxisData<Scalar, 1> +{ + int selfDof; + int oppositeDof; + Scalar selfToOppositeDistance; +}; + +// template<class Scalar, int geometryOrder> +// using AxisData + /*! * \ingroup StaggeredDiscretization * \brief Returns the dirction index of the facet (0 = x, 1 = y, 2 = z) @@ -83,7 +113,7 @@ inline static unsigned int directionIndex(Vector&& vector) * \brief Helper class constructing the dual grid finite volume geometries * for the free flow staggered discretization method. */ -template<class GridView> +template<class GridView, int geometryOrder> class FreeFlowStaggeredGeometryHelper { using Scalar = typename GridView::ctype; @@ -107,6 +137,9 @@ class FreeFlowStaggeredGeometryHelper static constexpr int numfacets = dimWorld * 2; static constexpr int numPairs = 2 * (dimWorld - 1); + static constexpr bool useHigherOrder = geometryOrder > 1; + + public: FreeFlowStaggeredGeometryHelper(const Element& element, const GridView& gridView) : element_(element), elementGeometry_(element.geometry()), gridView_(gridView) @@ -118,8 +151,8 @@ public: { intersection_ = intersection; innerNormalFacePos_.clear(); - fillPairData_(); - fillAxisData_(); + fillPairData_(std::integral_constant<bool, true>{}); //TODO + fillAxisData_(std::integral_constant<bool, useHigherOrder>{}); } /*! @@ -162,33 +195,44 @@ public: return Dumux::directionIndex(std::move(intersection.centerUnitOuterNormal())); } - static constexpr int geometryOrder = 2; - private: + + + void fillAxisData_(std::false_type) + { + const auto inIdx = intersection_.indexInInside(); + const auto oppIdx = localOppositeIdx_(inIdx); + + // Set the self Dof + axisData_.selfDof = gridView_.indexSet().subIndex(intersection_.inside(), inIdx, codimIntersection); + + // Set the opposite Dof + axisData_.oppositeDof = gridView_.indexSet().subIndex(intersection_.inside(), oppIdx, codimIntersection); + + // Set the Self to Opposite Distance + const auto self = getFacet_(inIdx, element_); + const auto opposite = getFacet_(oppIdx, element_); + axisData_.selfToOppositeDistance = (self.geometry().center() - opposite.geometry().center()).two_norm(); + } /*! * \brief Fills all entries of the in axis data */ - void fillAxisData_() + void fillAxisData_(std::true_type) { - unsigned int numForwardBackwardAxisDofs = axisData_.inAxisForwardDofs.size(); + const auto numForwardBackwardAxisDofs = axisData_.inAxisForwardDofs.size(); const auto inIdx = intersection_.indexInInside(); const auto oppIdx = localOppositeIdx_(inIdx); - this->axisData_.inAxisForwardDofs.fill(-1); - this->axisData_.inAxisBackwardDofs.fill(-1); - this->axisData_.inAxisForwardDistances.fill(0); - this->axisData_.inAxisBackwardDistances.fill(0); - // Set the self Dof - this->axisData_.selfDof = gridView_.indexSet().subIndex(this->intersection_.inside(), inIdx, codimIntersection); - const auto self = getFacet_(inIdx, element_); + axisData_.selfDof = gridView_.indexSet().subIndex(intersection_.inside(), inIdx, codimIntersection); // Set the opposite Dof - this->axisData_.oppositeDof = gridView_.indexSet().subIndex(this->intersection_.inside(), oppIdx, codimIntersection); - const auto opposite = getFacet_(oppIdx, element_); + axisData_.oppositeDof = gridView_.indexSet().subIndex(intersection_.inside(), oppIdx, codimIntersection); // Set the Self to Opposite Distance - this->axisData_.selfToOppositeDistance = (self.geometry().center() - opposite.geometry().center()).two_norm(); + const auto self = getFacet_(inIdx, element_); + const auto opposite = getFacet_(oppIdx, element_); + axisData_.selfToOppositeDistance = (self.geometry().center() - opposite.geometry().center()).two_norm(); // Set the Forward Dofs std::stack<Element> inAxisForwardElementStack; @@ -298,10 +342,17 @@ private: } } + void fillPairData_(std::false_type) + { + + // TODO + + } + /*! * \brief Fills all entries of the pair data */ - void fillPairData_() + void fillPairData_(std::true_type) { // initialize values that could remain unitialized if the intersection lies on a boundary for(auto& data : pairData_) diff --git a/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh b/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh index 0fa6efc607..8dcc9b9327 100644 --- a/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh +++ b/dumux/discretization/staggered/freeflow/subcontrolvolumeface.hh @@ -42,23 +42,24 @@ namespace Dumux { * of a sub control volume we compute fluxes on. This is a specialization for free flow models. */ template<class GV, + int geometryOrder, class T = StaggeredDefaultScvfGeometryTraits<GV> > class FreeFlowStaggeredSubControlVolumeFace -: public SubControlVolumeFaceBase<FreeFlowStaggeredSubControlVolumeFace<GV, T>, T> +: public SubControlVolumeFaceBase<FreeFlowStaggeredSubControlVolumeFace<GV, geometryOrder, T>, T> { - using ThisType = FreeFlowStaggeredSubControlVolumeFace<GV, T>; + using ThisType = FreeFlowStaggeredSubControlVolumeFace<GV, geometryOrder, T>; using ParentType = SubControlVolumeFaceBase<ThisType, T>; using Geometry = typename T::Geometry; using GridIndexType = typename IndexTraits<GV>::GridIndex; using LocalIndexType = typename IndexTraits<GV>::LocalIndex; - using GeometryHelper = FreeFlowStaggeredGeometryHelper<GV>; using Scalar = typename T::Scalar; static const int dim = Geometry::mydimension; static const int dimworld = Geometry::coorddimension; static constexpr int numPairs = 2 * (dimworld - 1); - static constexpr int geometryOrder = GeometryHelper::geometryOrder; + + static constexpr bool useHigherOrder = geometryOrder > 1; public: using GlobalPosition = typename T::GlobalPosition; @@ -255,6 +256,7 @@ public: * * \param backwardIdx The index describing how many faces backward this dof is from the opposite face */ + template<bool enable = useHigherOrder, std::enable_if_t<enable, int> = 0> bool hasBackwardNeighbor(const int backwardIdx) const { return !(axisData().inAxisBackwardDofs[backwardIdx] < 0); @@ -265,6 +267,7 @@ public: * * \param forwardIdx The index describing how many faces forward this dof is of the self face */ + template<bool enable = useHigherOrder, std::enable_if_t<enable, int> = 0> bool hasForwardNeighbor(const int forwardIdx) const { return !(axisData().inAxisForwardDofs[forwardIdx] < 0); diff --git a/dumux/freeflow/higherorderapproximation.hh b/dumux/freeflow/higherorderapproximation.hh index 601bf115d2..3e98307415 100644 --- a/dumux/freeflow/higherorderapproximation.hh +++ b/dumux/freeflow/higherorderapproximation.hh @@ -53,6 +53,8 @@ class HigherOrderApproximation public: HigherOrderApproximation(const std::string& paramGroup = "") { + upwindWeight_ = getParamFromGroup<Scalar>(paramGroup, "Flux.UpwindWeight"); + if (hasParamInGroup(paramGroup, "Discretization.TvdApproach")) { // Read the runtime parameters @@ -188,15 +190,14 @@ public: } } + /** * \brief Upwind Method */ - Scalar upwind(const Scalar downstreamVelocity, - const Scalar upstreamVelocity, - const Scalar density, - const Scalar upwindWeight) const + Scalar upwind(const Scalar downstreamMomentum, + const Scalar upstreamMomentum) const { - return (upwindWeight * upstreamVelocity + (1.0 - upwindWeight) * downstreamVelocity) * density; + return (upwindWeight_ * upstreamMomentum + (1.0 - upwindWeight_) * downstreamMomentum); } /** @@ -451,6 +452,7 @@ public: private: TvdApproach tvdApproach_; DifferencingScheme differencingScheme_; + Scalar upwindWeight_; std::function<Scalar(const Scalar, const Scalar)> limiter_; }; diff --git a/dumux/freeflow/navierstokes/staggered/fluxvariables.hh b/dumux/freeflow/navierstokes/staggered/fluxvariables.hh index a39cd4824f..37ad3fd3cb 100644 --- a/dumux/freeflow/navierstokes/staggered/fluxvariables.hh +++ b/dumux/freeflow/navierstokes/staggered/fluxvariables.hh @@ -86,6 +86,8 @@ class NavierStokesFluxVariablesImpl<TypeTag, DiscretizationMethod::staggered> static constexpr auto cellCenterIdx = FVGridGeometry::cellCenterIdx(); static constexpr auto faceIdx = FVGridGeometry::faceIdx(); + static constexpr bool useHigherOrder = false; // TODO + public: using HeatConductionType = GetPropType<TypeTag, Properties::HeatConductionType>; @@ -200,7 +202,8 @@ public: // The velocities of the dof at interest and the one of the opposite scvf. const Scalar velocitySelf = elemFaceVars[scvf].velocitySelf(); const Scalar velocityOpposite = elemFaceVars[scvf].velocityOpposite(); - static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight"); + + // const bool selfIsUpstream = scvf.directionSign() != sign(transportingVelocity); // The volume variables within the current element. We only require those (and none of neighboring elements) // because the fluxes are calculated over the staggered face at the center of the element. @@ -212,39 +215,37 @@ public: // Get the average velocity at the center of the element (i.e. the location of the staggered face). const Scalar transportingVelocity = (velocitySelf + velocityOpposite) * 0.5; - // Check if the the velocity of the dof at interest lies up- or downstream w.r.t. to the transporting velocity. - const bool selfIsUpstream = scvf.directionSign() != sign(transportingVelocity); - - Scalar momentum = 0.0; + const auto upwindingMomenta = getFrontalUpwindingMomenta_(scvf, elemFaceVars, insideVolVars.density(), transportingVelocity); + const Scalar momentum = doMomentumUpwinding_(scvf, upwindingMomenta, gridFluxVarsCache); // Variables that will store the velocities of interest: // velocities[0]: downstream velocity // velocities[1]: upstream velocity // velocities[2]: upstream-upstream velocity - std::array<Scalar, 3> velocities{0.0, 0.0, 0.0}; + // std::array<Scalar, 3> velocities{0.0, 0.0, 0.0}; // Variables that will store the distances between the dofs of interest: // distances[0]: upstream to downstream distance // distances[1]: upstream-upstream to upstream distance // distances[2]: downstream staggered cell size - std::array<Scalar, 3> distances{0.0, 0.0, 0.0}; + // std::array<Scalar, 3> distances{0.0, 0.0, 0.0}; - const auto& highOrder = gridFluxVarsCache.higherOrderApproximation(); + // const auto& highOrder = gridFluxVarsCache.higherOrderApproximation(); // If a Tvd approach has been specified and I am not too near to the boundary I can use a second order // approximation for the velocity. In this frontal flux I use for the density always the value that I have on the scvf. - if (highOrder.tvdApproach() != TvdApproach::none) - { - if (canFrontalSecondOrder_(scvf, selfIsUpstream, velocities, distances, elemFaceVars[scvf])) - { - momentum = highOrder.tvd(velocities[0], velocities[1], velocities[2], distances[0], distances[1], distances[2], selfIsUpstream, insideVolVars.density(), highOrder.tvdApproach()); - } - else - momentum = highOrder.upwind(velocities[0], velocities[1], insideVolVars.density(), upwindWeight); - } - else - momentum = selfIsUpstream ? highOrder.upwind(velocityOpposite, velocitySelf, insideVolVars.density(), upwindWeight) - : highOrder.upwind(velocitySelf, velocityOpposite, insideVolVars.density(), upwindWeight); + // if (highOrder.tvdApproach() != TvdApproach::none) + // { + // if (canFrontalSecondOrder_(scvf, selfIsUpstream, velocities, distances, elemFaceVars[scvf])) + // { + // momentum = highOrder.tvd(velocities[0], velocities[1], velocities[2], distances[0], distances[1], distances[2], selfIsUpstream, insideVolVars.density(), highOrder.tvdApproach()); + // } + // else + // momentum = highOrder.upwind(velocities[0], velocities[1], insideVolVars.density()); + // } + // else + // momentum = selfIsUpstream ? highOrder.upwind(velocityOpposite, velocitySelf, insideVolVars.density()) + // : highOrder.upwind(velocitySelf, velocityOpposite, insideVolVars.density()); // Account for the orientation of the staggered face's normal outer normal vector // (pointing in opposite direction of the scvf's one). @@ -310,7 +311,7 @@ public: const GridFluxVariablesCache& gridFluxVarsCache) { FacePrimaryVariables normalFlux(0.0); - auto& faceVars = elemFaceVars[scvf]; + const auto& faceVars = elemFaceVars[scvf]; const int numSubFaces = scvf.pairData().size(); // Account for all sub faces. @@ -413,50 +414,45 @@ private: // of interest is located. const Scalar transportingVelocity = faceVars.velocityNormalInside(localSubFaceIdx); - static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight", 1.0); + const auto parallelUpwindingMomenta = getParallelUpwindingMomenta_(problem, element, scvf, normalFace, elemVolVars, faceVars, + transportingVelocity, localSubFaceIdx, + lateralFaceHasDirichletPressure, lateralFaceHasBJS); - // Check whether the own or the neighboring element is upstream. - const bool selfIsUpstream = ( normalFace.directionSign() == sign(transportingVelocity) ); - - // Get the volume variables of the own and the neighboring element - const auto& insideVolVars = elemVolVars[normalFace.insideScvIdx()]; - const auto& outsideVolVars = elemVolVars[normalFace.outsideScvIdx()]; - - Scalar momentum = 0.0; + const Scalar momentum = doMomentumUpwinding_(scvf, parallelUpwindingMomenta, gridFluxVarsCache); // Variables that will store the velocities of interest: // velocities[0]: downstream velocity // velocities[1]: upsteram velocity // velocities[2]: upstream-upstream velocity - std::array<Scalar, 3> velocities{0.0, 0.0, 0.0}; + // std::array<Scalar, 3> velocities{0.0, 0.0, 0.0}; // Variables that will store the distances between the dofs of interest: // distances[0]: upstream to downstream distance // distances[1]: upstream-upstream to upstream distance // distances[2]: downstream staggered cell size - std::array<Scalar, 3> distances{0.0, 0.0, 0.0}; - - const auto& highOrder = gridFluxVarsCache.higherOrderApproximation(); - - // If a Tvd approach has been specified and I am not too near to the boundary I can use a second order approximation. - if (highOrder.tvdApproach() != TvdApproach::none) - { - if (canLateralSecondOrder_(scvf, fvGeometry, selfIsUpstream, localSubFaceIdx, velocities, distances, problem, element, faceVars, lateralFaceHasDirichletPressure, lateralFaceHasBJS)) - { - momentum = highOrder.tvd(velocities[0], velocities[1], velocities[2], distances[0], distances[1], distances[2], selfIsUpstream, selfIsUpstream ? insideVolVars.density() : outsideVolVars.density(), highOrder.tvdApproach()); - } - else - momentum = highOrder.upwind(velocities[0], velocities[1], selfIsUpstream ? insideVolVars.density() : outsideVolVars.density(), upwindWeight); - } - else - { - const Scalar velocityFirstParallel = scvf.hasParallelNeighbor(localSubFaceIdx, 0) - ? faceVars.velocityParallel(localSubFaceIdx, 0) - : getParallelVelocityFromBoundary_(problem, scvf, normalFace, faceVars.velocitySelf(), localSubFaceIdx, element, lateralFaceHasDirichletPressure, lateralFaceHasBJS); - - momentum = selfIsUpstream ? highOrder.upwind(velocityFirstParallel, faceVars.velocitySelf(), insideVolVars.density(), upwindWeight) - : highOrder.upwind(faceVars.velocitySelf(), velocityFirstParallel, outsideVolVars.density(), upwindWeight); - } + // std::array<Scalar, 3> distances{0.0, 0.0, 0.0}; + + // const auto& highOrder = gridFluxVarsCache.higherOrderApproximation(); + // + // // If a Tvd approach has been specified and I am not too near to the boundary I can use a second order approximation. + // if (highOrder.tvdApproach() != TvdApproach::none) + // { + // if (canLateralSecondOrder_(scvf, fvGeometry, selfIsUpstream, localSubFaceIdx, velocities, distances, problem, element, faceVars, lateralFaceHasDirichletPressure, lateralFaceHasBJS)) + // { + // momentum = highOrder.tvd(velocities[0], velocities[1], velocities[2], distances[0], distances[1], distances[2], selfIsUpstream, selfIsUpstream ? insideVolVars.density() : outsideVolVars.density(), highOrder.tvdApproach()); + // } + // else + // momentum = highOrder.upwind(velocities[0], velocities[1], selfIsUpstream ? insideVolVars.density() : outsideVolVars.density()); + // } + // else + // { + // const Scalar velocityFirstParallel = scvf.hasParallelNeighbor(localSubFaceIdx, 0) + // ? faceVars.velocityParallel(localSubFaceIdx, 0) + // : getParallelVelocityFromBoundary_(problem, scvf, normalFace, faceVars.velocitySelf(), localSubFaceIdx, element, lateralFaceHasDirichletPressure, lateralFaceHasBJS); + // + // momentum = selfIsUpstream ? highOrder.upwind(velocityFirstParallel, faceVars.velocitySelf(), insideVolVars.density()) + // : highOrder.upwind(faceVars.velocitySelf(), velocityFirstParallel, outsideVolVars.density()); + // } // Account for the orientation of the staggered normal face's outer normal vector // and its area (0.5 of the coinciding scfv). @@ -881,6 +877,60 @@ private: DUNE_THROW(Dune::InvalidStateException, "Something went wrong with the boundary conditions for the momentum equations at global position " << boundarySubFaceCenter); } } + + Scalar doMomentumUpwinding_(const SubControlVolumeFace& scvf, + const std::array<Scalar, 2>& momentum, + const GridFluxVariablesCache& gridFluxVarsCache) const + { + const auto& upwindScheme = gridFluxVarsCache.higherOrderApproximation(); + return upwindScheme.upwind(momentum[0], momentum[1]); + } + + std::array<Scalar, 2> getFrontalUpwindingMomenta_(const SubControlVolumeFace& scvf, + const ElementFaceVariables& elemFaceVars, + const Scalar density, + const Scalar transportingVelocity) const + { + const Scalar momentumSelf = elemFaceVars[scvf].velocitySelf() * density; + const Scalar momentumOpposite = elemFaceVars[scvf].velocityOpposite() * density; + const bool selfIsUpstream = scvf.directionSign() != sign(transportingVelocity); + + return selfIsUpstream ? std::array<Scalar, 2>{momentumOpposite, momentumSelf} + : std::array<Scalar, 2>{momentumSelf, momentumOpposite}; + } + + std::array<Scalar, 2> getParallelUpwindingMomenta_(const Problem& problem, + const Element& element, + const SubControlVolumeFace& ownFace, + const SubControlVolumeFace& lateralFace, + const ElementVolumeVariables& elemVolVars, + const FaceVariables& faceVars, + const Scalar transportingVelocity, + const int localSubFaceIdx, + bool lateralFaceHasDirichletPressure, + bool lateralFaceHasBJS) const + { + + // Check whether the own or the neighboring element is upstream. + const bool selfIsUpstream = lateralFace.directionSign() == sign(transportingVelocity); + + // Get the volume variables of the own and the neighboring element + const auto& insideVolVars = elemVolVars[lateralFace.insideScvIdx()]; + const auto& outsideVolVars = elemVolVars[lateralFace.outsideScvIdx()]; + + const Scalar momentumSelf = faceVars.velocitySelf() * insideVolVars.density(); + + const Scalar momentumParallel = ownFace.hasParallelNeighbor(localSubFaceIdx, 0) + ? faceVars.velocityParallel(localSubFaceIdx, 0) * outsideVolVars.density() + : (getParallelVelocityFromBoundary_(problem, ownFace, lateralFace, + faceVars.velocitySelf(), localSubFaceIdx, element, + lateralFaceHasDirichletPressure, lateralFaceHasBJS) + * insideVolVars.density()); + + return selfIsUpstream ? std::array<Scalar, 2>{momentumParallel, momentumSelf} + : std::array<Scalar, 2>{momentumSelf, momentumParallel}; + } + }; } // end namespace Dumux -- GitLab