From 82b83f75dceb82891be1b779cc3b5b7c806120dd Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de> Date: Wed, 30 Sep 2020 17:49:11 +0200 Subject: [PATCH] [test][mpnckinetic] Adapt spatialparams --- .../mpnc/implicit/kinetic/problem.hh | 15 +- .../mpnc/implicit/kinetic/spatialparams.hh | 249 ++++++++---------- 2 files changed, 116 insertions(+), 148 deletions(-) diff --git a/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh b/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh index 92a34e8a35..8423989dd1 100644 --- a/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh +++ b/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh @@ -51,14 +51,6 @@ #include "spatialparams.hh" -// material laws for interfacial area -#include <dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorder.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfct.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh> - namespace Dumux { /*! * \ingroup MPNCTests @@ -389,15 +381,12 @@ private: equilibriumFluidState.setTemperature(phaseIdx, TInitial_ ); } - const auto &materialParams = - this->spatialParams().materialLawParamsAtPos(globalPos); std::vector<Scalar> capPress(numPhases); // obtain pc according to saturation - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter<MaterialLaw, numPhases>; + using MPAdapter = FluidMatrix::MPAdapter<numPhases>; const int wPhaseIdx = this->spatialParams().template wettingPhaseAtPos<FluidSystem>(globalPos); - MPAdapter::capillaryPressures(capPress, materialParams, equilibriumFluidState, wPhaseIdx); + MPAdapter::capillaryPressures(capPress, this->spatialParams().fluidMatrixInteractionAtPos(globalPos), equilibriumFluidState, wPhaseIdx); Scalar p[numPhases]; if (this->spatialParams().inPM_(globalPos)){ diff --git a/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh b/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh index 644fb6d817..15c3c3863c 100644 --- a/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh @@ -28,18 +28,17 @@ #include <dumux/porousmediumflow/properties.hh> #include <dumux/material/spatialparams/fvnonequilibrium.hh> -#include <dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh> -#include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh> -#include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh> -#include <dumux/material/fluidmatrixinteractions/2p/vangenuchtenoftemperature.hh> -#include <dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh> + +#include <dumux/material/fluidmatrixinteractions/fluidmatrixinteraction.hh> +#include <dumux/material/fluidmatrixinteractions/2p/brookscorey.hh> + #include <dumux/common/parameters.hh> // material laws for interfacial area -#include <dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh> -#include <dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh> +#include <dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomial2ndorder.hh> +#include <dumux/material/fluidmatrixinteractions/2p/interfacialarea/pcmax.hh> +#include <dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponentialcubic.hh> +#include <dumux/material/fluidmatrixinteractions/2p/interfacialarea/interfacialarea.hh> namespace Dumux { @@ -61,37 +60,33 @@ class EvaporationAtmosphereSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; static constexpr auto dimWorld = GridView::dimensionworld; + + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault<Scalar>; + + using NonwettingSolidInterfacialArea = FluidMatrix::InterfacialArea<Scalar, + FluidMatrix::InterfacialAreaExponentialCubic, + FluidMatrix::NonwettingSolidInterfacialAreaPcSw>; + using WettingSolidInterfacialArea = FluidMatrix::InterfacialArea<Scalar, + FluidMatrix::InterfacialAreaPolynomialSecondOrder, + FluidMatrix::WettingSolidInterfacialAreaPcSw>; + using WettingNonwettingInterfacialArea = FluidMatrix::InterfacialArea<Scalar, + FluidMatrix::InterfacialAreaPcMax, + FluidMatrix::WettingNonwettingInterfacialAreaPcSw>; public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw<RegularizedBrooksCorey<Scalar>>; - //! Convenience aliases of the law parameters - using MaterialLawParams = typename MaterialLaw::Params; - - //! Export the types used for interfacial area calculations - using EffectiveIALawAws = AwnSurfacePolynomial2ndOrder<Scalar>; - using EffectiveIALawAwn = AwnSurfacePcMaxFct<Scalar>; - using EffectiveIALawAns = AwnSurfaceExpSwPcTo3<Scalar>; - using AwnSurface = EffToAbsLawIA<EffectiveIALawAwn, MaterialLawParams>; - using AwsSurface = EffToAbsLawIA<EffectiveIALawAws, MaterialLawParams>; - using AnsSurface = EffToAbsLawIA<EffectiveIALawAns, MaterialLawParams>; - - using AwnSurfaceParams = typename AwnSurface::Params; - using AwsSurfaceParams = typename AwsSurface::Params; - using AnsSurfaceParams = typename AnsSurface::Params; EvaporationAtmosphereSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry) : ParentType(gridGeometry) { - heightPM_ = getParam<std::vector<Scalar>>("Grid.Positions1")[1]; - heightDomain_ = getParam<std::vector<Scalar>>("Grid.Positions1")[2]; + heightPM_ = getParam<std::vector<Scalar>>("Grid.Positions1")[1]; + heightDomain_ = getParam<std::vector<Scalar>>("Grid.Positions1")[2]; - porosityPM_ = getParam<Scalar>("SpatialParams.PorousMedium.porosity"); - intrinsicPermeabilityPM_ = getParam<Scalar>("SpatialParams.PorousMedium.permeability"); + porosityPM_ = getParam<Scalar>("SpatialParams.PorousMedium.porosity"); + intrinsicPermeabilityPM_ = getParam<Scalar>("SpatialParams.PorousMedium.permeability"); - porosityFF_ = getParam<Scalar>("SpatialParams.FreeFlow.porosity"); - intrinsicPermeabilityFF_ = getParam<Scalar>("SpatialParams.FreeFlow.permeability"); + porosityFF_ = getParam<Scalar>("SpatialParams.FreeFlow.porosity"); + intrinsicPermeabilityFF_ = getParam<Scalar>("SpatialParams.FreeFlow.permeability"); aWettingNonwettingA1_ = getParam<Scalar>("SpatialParams.soil.aWettingNonwettingA1"); aWettingNonwettingA2_ = getParam<Scalar>("SpatialParams.soil.aWettingNonwettingA2"); @@ -101,31 +96,26 @@ public: aNonwettingSolidA2_ = getParam<Scalar>("SpatialParams.soil.aNonwettingSolidA2"); aNonwettingSolidA3_ = getParam<Scalar>("SpatialParams.soil.aNonwettingSolidA3"); - BCPd_ = getParam<Scalar>("SpatialParams.soil.BCPd"); - BClambda_ = getParam<Scalar>("SpatialParams.soil.BClambda"); - Swr_ = getParam<Scalar>("SpatialParams.soil.Swr"); - Snr_ = getParam<Scalar>("SpatialParams.soil.Snr"); + BCPd_ = getParam<Scalar>("SpatialParams.soil.BCPd"); + BClambda_ = getParam<Scalar>("SpatialParams.soil.BClambda"); + Swr_ = getParam<Scalar>("SpatialParams.soil.Swr"); + Snr_ = getParam<Scalar>("SpatialParams.soil.Snr"); - characteristicLengthFF_ = getParam<Scalar>("SpatialParams.FreeFlow.meanPoreSize"); - characteristicLengthPM_ = getParam<Scalar>("SpatialParams.PorousMedium.meanPoreSize"); + characteristicLengthFF_ = getParam<Scalar>("SpatialParams.FreeFlow.meanPoreSize"); + characteristicLengthPM_ = getParam<Scalar>("SpatialParams.PorousMedium.meanPoreSize"); factorEnergyTransfer_ = getParam<Scalar>("SpatialParams.PorousMedium.factorEnergyTransfer"); factorMassTransfer_ = getParam<Scalar>("SpatialParams.PorousMedium.factorMassTransfer"); - // residual saturations - materialParamsFF_.setSwr(0.0); - materialParamsFF_.setSnr(0.00); - - materialParamsPM_.setSwr(Swr_); - materialParamsPM_.setSnr(Snr_); - - // pc / kr parameters - materialParamsPM_.setLambda(BClambda_); - materialParamsPM_.setPe(BCPd_); + // PM parameters for Brooks-Corey + typename PcKrSwCurve::BasicParams paramsPM(BCPd_, BClambda_); + typename PcKrSwCurve::EffToAbsParams effToAbsParamsPM(Swr_, Snr_); + pcKrSwCurvePM_ = std::make_unique<PcKrSwCurve>(paramsPM, effToAbsParamsPM); - // for making pc == 0 in the FF - materialParamsFF_.setLambda(42.); - materialParamsFF_.setPe(0.); + // FF parameters for Brooks-Corey + typename PcKrSwCurve::BasicParams paramsFF(0/*dummy pe*/, 42/*dummy lambda*/); + typename PcKrSwCurve::EffToAbsParams effToAbsParamsFF(0.0/*swr*/, 0.0/*snr*/); + pcKrSwCurveFF_ = std::make_unique<PcKrSwCurve>(paramsFF, effToAbsParamsFF); // determine maximum capillary pressure for wetting-nonwetting surface /* Of course physically there is no such thing as a maximum capillary pressure. @@ -136,30 +126,33 @@ public: * Technically this value is obtained as the capillary pressure of saturation zero. * This value of course only exists for the case of a regularized pc-Sw relation. */ - using TwoPLaw = EffToAbsLaw<RegularizedBrooksCorey<Scalar>>; - const auto pcMax = TwoPLaw::pc(materialParamsPM_, /*sw = */0.0); - aWettingNonwettingSurfaceParams_.setPcMax(pcMax); + const auto pcMax = pcKrSwCurvePM_->pc(/*sw = */0.0); + + // non-wetting-solid + using NonwettingSolidInterfacialAreaParams = typename NonwettingSolidInterfacialArea::BasicParams; + NonwettingSolidInterfacialAreaParams ansParams; + ansParams.setA1(aNonwettingSolidA1_); + ansParams.setA2(aNonwettingSolidA2_); + ansParams.setA3(aNonwettingSolidA3_); + aNs_ = std::make_unique<NonwettingSolidInterfacialArea>(ansParams, effToAbsParamsPM); // wetting-non wetting: surface which goes to zero on the edges, but is a polynomial - aWettingNonwettingSurfaceParams_.setA1(aWettingNonwettingA1_); - aWettingNonwettingSurfaceParams_.setA2(aWettingNonwettingA2_); - aWettingNonwettingSurfaceParams_.setA3(aWettingNonwettingA3_); - - // nonwetting-solid - aNonwettingSolidSurfaceParams_.setA1(aNonwettingSolidA1_); - aNonwettingSolidSurfaceParams_.setA2(aNonwettingSolidA2_); - aNonwettingSolidSurfaceParams_.setA3(aNonwettingSolidA3_); - - // dummys for free flow: no interface where there is only one phase - aWettingNonwettingSurfaceParamsFreeFlow_.setA1(0.); - aWettingNonwettingSurfaceParamsFreeFlow_.setA2(0.); - aWettingNonwettingSurfaceParamsFreeFlow_.setA3(0.); - aWettingNonwettingSurfaceParamsFreeFlow_.setPcMax(42.); // not needed because it is anyways zero; - - // dummys for free flow: no interface where there is only one phase - aNonwettingSolidSurfaceParamsFreeFlow_.setA1(0.); - aNonwettingSolidSurfaceParamsFreeFlow_.setA2(0.); - aNonwettingSolidSurfaceParamsFreeFlow_.setA3(0.); + using WettingNonwettingInterfacialAreaParams = typename WettingNonwettingInterfacialArea::BasicParams; + WettingNonwettingInterfacialAreaParams anwParams; + anwParams.setPcMax(pcMax); + anwParams.setA1(aWettingNonwettingA1_); + anwParams.setA2(aWettingNonwettingA2_); + anwParams.setA3(aWettingNonwettingA3_); + aNw_ = std::make_unique<WettingNonwettingInterfacialArea>(anwParams, effToAbsParamsPM); + + // zero-initialized dummys for free flow: no interface where there is only one phase + aNwFreeFlow_ = std::make_unique<WettingNonwettingInterfacialArea>(WettingNonwettingInterfacialAreaParams(), effToAbsParamsFF); + aNsFreeFlow_ = std::make_unique<NonwettingSolidInterfacialArea>(NonwettingSolidInterfacialAreaParams(), effToAbsParamsFF); + + // dummy + using WettingSolidInterfacialAreaParams = typename WettingSolidInterfacialArea::BasicParams; + WettingSolidInterfacialAreaParams awsParams; + aWs_ = std::make_unique<WettingSolidInterfacialArea>(awsParams, effToAbsParamsPM); // use ctor without effToAbs } template<class ElementSolution> @@ -200,81 +193,63 @@ public: DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); } - template<class ElementSolution> - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { return materialLawParamsAtPos(scv.dofPosition()); } - - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + /*! + * \brief Returns the parameters for the material law at a given location + * \param globalPos A global coordinate vector + */ + const NonwettingSolidInterfacialArea& nonwettingSolidInterfacialAreaAtPos(const GlobalPosition &globalPos) const { - if (inFF_(globalPos)) - return materialParamsFF_; + if (inFF_(globalPos) ) + return *aNsFreeFlow_ ; else if (inPM_(globalPos)) - return materialParamsPM_; + return *aNs_ ; else DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); } - /*!\brief Returns a reference to the container object for the - * parametrization of the surface between wetting and nonwetting phase. - * - * The position is determined based on the coordinate of - * the vertex belonging to the considered sub-control volume. - * - * \param element The finite element - * \param scv The sub-control volume - * \param elemSol The element solution + /*! + * \brief Returns the parameters for the material law at a given location + * \param globalPos A global coordinate vector */ - template<class ElementSolution> - const AwnSurfaceParams& aWettingNonwettingSurfaceParams(const Element &element, - const SubControlVolume &scv, - const ElementSolution &elemSol) const + const WettingSolidInterfacialArea& wettingSolidInterfacialAreaAtPos(const GlobalPosition &globalPos) const { - const auto& globalPos = scv.dofPosition(); - if (inFF_(globalPos) ) - return aWettingNonwettingSurfaceParamsFreeFlow_ ; - else if (inPM_(globalPos)) - return aWettingNonwettingSurfaceParams_ ; - else DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); + DUNE_THROW(Dune::InvalidStateException, "Should not be called in this test."); } - /*!\brief Returns a reference to the container object for the - * parametrization of the surface between nonwetting and solid phase. - * - * The position is determined based on the coordinate of - * the vertex belonging to the considered sub-control volume. - * \param element The finite element - * \param scv The sub-control volume - * \param elemSol The element solution + /*! + * \brief Returns the parameters for the material law at a given location + * \param globalPos A global coordinate vector */ - template<class ElementSolution> - const AnsSurfaceParams& aNonwettingSolidSurfaceParams(const Element &element, - const SubControlVolume &scv, - const ElementSolution &elemSol) const + const WettingNonwettingInterfacialArea& wettingNonwettingInterfacialAreaAtPos(const GlobalPosition &globalPos) const { - const auto& globalPos = scv.dofPosition(); if (inFF_(globalPos) ) - return aNonwettingSolidSurfaceParamsFreeFlow_ ; + return *aNwFreeFlow_ ; else if (inPM_(globalPos)) - return aNonwettingSolidSurfaceParams_ ; + return *aNw_ ; else DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); + } - /*!\brief Returns a reference to the container object for the - * parametrization of the surface between wetting and solid phase. - * - * The position is determined based on the coordinate of - * the vertex belonging to the considered sub-control volume. - * \param element The finite element - * \param scv The sub-control volume - * \param elemSol The element solution + /*! + * \brief Returns the parameters for the material law at a given location */ template<class ElementSolution> - const AwsSurfaceParams& aWettingSolidSurfaceParams(const Element &element, - const SubControlVolume &scv, - const ElementSolution &elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + return fluidMatrixInteractionAtPos(scv.dofPosition()); + } + + /*! + * \brief Returns the parameters for the material law at a given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const { - DUNE_THROW(Dune::NotImplemented, "wetting-solid-interface surface params"); + if (inFF_(globalPos)) + return makeFluidMatrixInteraction(*pcKrSwCurveFF_, *aNsFreeFlow_, *aNwFreeFlow_, *aWs_); + else if (inPM_(globalPos)) + return makeFluidMatrixInteraction(*pcKrSwCurvePM_, *aNs_, *aNw_, *aWs_); + else DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); } /*! @@ -368,11 +343,6 @@ private: static constexpr Scalar eps_ = 1e-6; Scalar heightDomain_ ; - AwnSurfaceParams aWettingNonwettingSurfaceParams_; - AnsSurfaceParams aNonwettingSolidSurfaceParams_ ; - AwnSurfaceParams aWettingNonwettingSurfaceParamsFreeFlow_; - AnsSurfaceParams aNonwettingSolidSurfaceParamsFreeFlow_ ; - // Porous Medium Domain Scalar intrinsicPermeabilityPM_ ; Scalar porosityPM_ ; @@ -380,13 +350,13 @@ private: Scalar factorEnergyTransfer_ ; Scalar factorMassTransfer_ ; Scalar characteristicLengthPM_ ; - MaterialLawParams materialParamsPM_ ; + std::unique_ptr<PcKrSwCurve> pcKrSwCurvePM_; // Free Flow Domain Scalar porosityFF_ ; Scalar intrinsicPermeabilityFF_ ; Scalar characteristicLengthFF_ ; - MaterialLawParams materialParamsFF_ ; + std::unique_ptr<PcKrSwCurve> pcKrSwCurveFF_; // interfacial area parameters Scalar aWettingNonwettingA1_ ; @@ -403,6 +373,15 @@ private: Scalar Swr_ ; Scalar Snr_ ; std::vector<Scalar> gridVector_; + + std::unique_ptr<NonwettingSolidInterfacialArea> aNs_; + std::unique_ptr<WettingNonwettingInterfacialArea> aNw_; + + std::unique_ptr<WettingNonwettingInterfacialArea> aNwFreeFlow_; + std::unique_ptr<NonwettingSolidInterfacialArea> aNsFreeFlow_; + + std::unique_ptr<WettingSolidInterfacialArea> aWs_; // dummy, never used + }; } // end namespace Dumux -- GitLab