diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dfadefcaade3aaa0500d26ed3512b7443da3b8e..311f823640d6235ab5144044dc254f993f85f27e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,14 +15,18 @@ Differences Between DuMux 3.3 and DuMux 3.2 In order to use this, include ``. `format`, `format_to`, `format_to_n`, `formatted_size` are available in the `Dumux::Fmt` namespace. The string formatting is documented [here](https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification) and follows the Python string formatting rules. The function are documented on [cppreference](https://en.cppreference.com/w/cpp/utility/format). + - The usage of laws for pc-Sw and kr-Sw has been completely revised. A caller does not have to pass a `parameters` object to the laws anymore. The `spatialParams` now provide a `fluidMatrixInteraction` function which bundles an arbitrary number of + different interaction laws such as a pc-Sw and kr-Sw curve and interfacial areas. + New pre-cached spline laws were added which can help to increase efficiency. The usage of the old interface is deprecated and warnings will be raised. The old interface will be removed after the release of 3.3. ### Immediate interface changes not allowing/requiring a deprecation period: - +- __Flash/Constraintsolver__: The flashes depending on material laws are immediately required to use new-style material laws (fluidMatrixInteraction interface in spatialparams) +- __Box interface solver__: The box interface solver immediately requires the new material law interface without deprecation period. Use the new class `BoxMaterialInterfaces` and update your spatial params to use the new fluidmatrixinteraction interface to be able to use the box interface solver in version 3.3. - For the "sequential" models, the property `BoundaryTypes` has been simply renamed to `SequentialBoundaryTypes` - __Quadmath__: Dumux::Quad has been removed without deprecation. Use Dune::Float128 instead. - Within the RANS group, two additional runtime parameters have been included 'IsFlatWallBounded' and 'WriteFlatWallBoundedFields'. For both the K-Epsilon and Zero-eq RANS models the 'IsFlatWallBounded' runtime parameter should be set as True, -as wall topology is not supported for these models with our geometric contraints. If not set as true, the geometry +as wall topology is not supported for these models with our geometric constraints. If not set as true, the geometry will be checked before the model is run. If either the runtime parameter or the geometry check indicate non-flat walls, the model will terminate. To add FlatWallBounded specific output to the vtk output, WriteFlatWallBoundedFields can be set as True. - __1d3d coupling__: The kernel coupling manager has been replaced with the one from Koch et al (2020) JCP https://doi.org/10.1016/j.jcp.2020.109370 diff --git a/doc/handbook/dumux-handbook.bib b/doc/handbook/dumux-handbook.bib index 9b5588c9ac46388b98565dc4233d2b0c85e0192e..a3b6a3ecb47963c6146aa25bee52984a00febc0c 100644 --- a/doc/handbook/dumux-handbook.bib +++ b/doc/handbook/dumux-handbook.bib @@ -426,6 +426,17 @@ url = {http://elib.uni-stuttgart.de/opus/volltexte/2013/8141} } +@PhdThesis{nuske2014, + author = {Philipp Nuske}, + title = {{Beyond local equilibrium : relaxing local equilibrium assumptions in multiphase flow in porous media}}, + school = {Universit\"at Stuttgart}, + year = {2014}, + address = {Holzgartenstr. 16, 70174 Stuttgart}, + isbn = {978-3-942036-41-2}, + language = {eng}, + url = {https://elib.uni-stuttgart.de/handle/11682/614} +} + @ARTICLE{A3:Braun:2002, author = {Braun, C. and Helmig, R. and Manthey, S.}, title = {{Determination of constitutive relationships for two-phase flow processes diff --git a/dumux/common/deprecated.hh b/dumux/common/deprecated.hh index 3e191a6891295a010468ba4c9be6dc07b0b3f6d2..9164b15ce1c0fcf98e0a82bb7ba063a85e8f84c8 100644 --- a/dumux/common/deprecated.hh +++ b/dumux/common/deprecated.hh @@ -26,6 +26,9 @@ #define DUMUX_COMMON_DEPRECATED_HH #include +#include +#include +#include namespace Dumux { @@ -43,9 +46,521 @@ namespace Deprecated { //////////////////////////////////////////// /////////////////////////////////////////////////////////////// -// Deprecation warnings for effective diffusion coefficients // +// Deprecation warnings for the new material law // /////////////////////////////////////////////////////////////// +// support old interface of the effective thermal conductivity laws +template +struct HasNewFIAIF +{ + template + auto operator()(S&& sp) + -> decltype(sp.fluidMatrixInteraction(std::declval(), + std::declval(), + std::declval())) {} +}; + +template +struct HasNewFIAIFAtPos +{ + template + auto operator()(S&& sp) + -> decltype(sp.fluidMatrixInteractionAtPos(std::declval())) {} +}; + + +template +class PcKrSwHelper : public FluidMatrix::Adapter, FluidMatrix::PcKrSw> +{ +public: + using Scalar = ScalarT; + + // pass scalar so template arguments can all be deduced + PcKrSwHelper(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + Scalar krw(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::krw(params, sw); + } + + Scalar krn(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::krn(params, sw); + } + + Scalar pc(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::pc(params, sw); + } + + Scalar dpc_dsw(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::dpc_dsw(params, sw); + } + + Scalar endPointPc() const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::endPointPc(params); + } + + Scalar sw(const Scalar pc) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::sw(params, pc); + } + + Scalar dsw_dpc(const Scalar pc) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::dsw_dpc(params, pc); + } + + Scalar dkrw_dsw(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::dkrw_dsw(params, sw); + } + + Scalar dkrn_dsw(const Scalar sw) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::dkrn_dsw(params, sw); + } + + const auto& basicParams() const + { return spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); } + + const auto& effToAbsParams() const + { return spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +template +class PcKrSwThreePHelper : public FluidMatrix::Adapter, FluidMatrix::ThreePhasePcKrSw> +{ +public: + using Scalar = ScalarT; + + // pass scalar so template arguments can all be deduced + PcKrSwThreePHelper(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + Scalar pcgw(const Scalar sw, const Scalar /*dummySn*/) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::pcgw(params, sw); + } + + Scalar pcnw(const Scalar sw, const Scalar /*dummySn*/) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::pcnw(params, sw); + } + + Scalar pcgn(const Scalar sw, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::pcgn(params, sw + sn); + } + + Scalar pcAlpha(const Scalar /*dummySw*/, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::pcAlpha(params, sn); + } + + Scalar krw(const Scalar sw, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::krw(params, sw, sn); + } + + Scalar krn(const Scalar sw, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::krw(params, sw, sn); + } + + Scalar krg(const Scalar sw, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::krg(params, sw, sn); + } + + Scalar kr(const int phaseIdx, const Scalar sw, const Scalar sn) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + return SpatialParams::MaterialLaw::kr(params, phaseIdx, sw, sn, 1 - sw - sn); + } + + const auto& basicParams() const + { return spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); } + + const auto& effToAbsParams() const + { return spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +// for implicit models +template +auto makePcKrSw(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) +{ + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + constexpr bool hasNew = decltype(isValid(HasNewFIAIF()).template check())::value; + constexpr bool hasNewAtPos = decltype(isValid(HasNewFIAIFAtPos()).template check())::value; + if constexpr (hasNew) + return sp.fluidMatrixInteraction(element, scv, elemSol); + else if constexpr (hasNewAtPos) + return sp.fluidMatrixInteractionAtPos(scv.center()); + else + { + if constexpr (numPhases == 2) + return makeFluidMatrixInteraction(PcKrSwHelper(scalar, sp, element, scv, elemSol)); + else + return makeFluidMatrixInteraction(PcKrSwThreePHelper(scalar, sp, element, scv, elemSol)); + } +} + +// for sequential models +template +auto makePcKrSw(const Scalar& scalar, + const SpatialParams& sp, + const Element& element) +{ + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + constexpr bool hasNewAtPos = decltype(isValid(HasNewFIAIFAtPos()).template check())::value; + if constexpr (hasNewAtPos) + return sp.fluidMatrixInteractionAtPos(element.geometry().center()); + else + { + using DummyScv = int; + using DummyElemSol = int; + return makeFluidMatrixInteraction(PcKrSwHelper(scalar, sp, element, DummyScv(), DummyElemSol())); + } +} + + +/////////////////////////////////////////////////////////////// +// Deprecation warnings for the mp material law stuff // +/////////////////////////////////////////////////////////////// + +template +class PcKrSwMPHelper : public FluidMatrix::Adapter, FluidMatrix::MultiPhasePcKrSw> +{ + using MaterialLaw = typename SpatialParams::MaterialLaw; + using MPAdapter = Dumux::MPAdapter; +public: + using Scalar = ScalarT; + + // pass scalar so template arguments can all be deduced + PcKrSwMPHelper(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol, + const NumPhases& np) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + template + auto capillaryPressures(const FluidState& fs, int wPhaseIdx) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + Dune::FieldVector pc; + MPAdapter::capillaryPressures(pc, params, fs, wPhaseIdx); + return pc; + } + + template + auto relativePermeabilities(const FluidState& fs, int wPhaseIdx) const + { + const auto& params = spatialParams_.materialLawParamsDeprecated(element_, scv_, elemSol_); + Dune::FieldVector kr; + MPAdapter::capillaryPressures(kr, params, fs, wPhaseIdx); + return kr; + } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +template +auto makeMPPcKrSw(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol, + const NumPhases& np) +{ + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + constexpr bool hasNew = decltype(isValid(HasNewFIAIF()).template check())::value; + constexpr bool hasNewAtPos = decltype(isValid(HasNewFIAIFAtPos()).template check())::value; + if constexpr (hasNew) + return sp.fluidMatrixInteraction(element, scv, elemSol); + else if constexpr (hasNewAtPos) + return sp.fluidMatrixInteractionAtPos(scv.center()); + else + return makeFluidMatrixInteraction(PcKrSwMPHelper(scalar, sp, element, scv, elemSol, np)); +} + +/////////////////////////////////////////////////////////////// +// Deprecation warnings for the kinetic surface areas // +/////////////////////////////////////////////////////////////// + +// support old interface of surface area +template +struct HasNewAns +{ + template + auto operator()(S&& sp) + -> decltype(sp.nonwettingSolidInterfacialArea(std::declval(), + std::declval(), + std::declval())) {} +}; + +template +struct HasNewAnsAtPos +{ + template + auto operator()(S&& sp) + -> decltype(sp.nonwettingSolidInterfacialAreaAtPos(std::declval())) {} +}; + +// support old interface of surface area +template +struct HasNewAnw +{ + template + auto operator()(S&& sp) + -> decltype(sp.wettingNonwettingInterfacialArea(std::declval(), + std::declval(), + std::declval())) {} +}; + +template +struct HasNewAnwAtPos +{ + template + auto operator()(S&& sp) + -> decltype(sp.wettingNonwettingInterfacialAreaAtPos(std::declval())) {} +}; + +// support old interface of surface area +template +struct HasNewAws +{ + template + auto operator()(S&& sp) + -> decltype(sp.wettingSolidInterfacialArea(std::declval(), + std::declval(), + std::declval())) {} +}; + +template +struct HasNewAwsAtPos +{ + template + auto operator()(S&& sp) + -> decltype(sp.wettingSolidInterfacialAreaAtPos(std::declval())) {} +}; + +template +class WettingNonwettingInterfacialArea : public FluidMatrix::Adapter, FluidMatrix::WettingNonwettingInterfacialAreaPcSw> +{ +public: + using Scalar = ScalarT; + + WettingNonwettingInterfacialArea(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + const auto& basicParams() const + { + return spatialParams_.aWettingNonWettingSurfaceParams(element_, scv_, elemSol_); + } + + Scalar area(const Scalar sw, const Scalar pc) const + { + const auto& surfaceParams = spatialParams_.aWettingNonWettingSurfaceParams(element_, scv_, elemSol_); + const auto& materialParams = spatialParams_.materialLawParams(element_, scv_, elemSol_); + using AwnSurface = typename SpatialParams::AwnSurface; + return AwnSurface::interfacialArea(surfaceParams, materialParams, sw, pc); + } + + Scalar darea_dpc(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aWettingNonWettingSurfaceParams(element_, scv_, elemSol_); + using AwnSurface = typename SpatialParams::AwnSurface; + return AwnSurface::dawn_dpc(surfaceParams, sw, pc); + } + + Scalar darea_dsw(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aWettingNonWettingSurfaceParams(element_, scv_, elemSol_); + using AwnSurface = typename SpatialParams::AwnSurface; + return AwnSurface::dawn_dsw(surfaceParams, sw, pc); + } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +template +class NonwettingSolidInterfacialArea : public FluidMatrix::Adapter, FluidMatrix::NonwettingSolidInterfacialAreaPcSw> +{ +public: + using Scalar = ScalarT; + + NonwettingSolidInterfacialArea(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + const auto& basicParams() const + { + return spatialParams_.aNonWettingSolidSurfaceParams(element_, scv_, elemSol_); + } + + Scalar area(const Scalar sw, const Scalar pc) const + { + const auto& surfaceParams = spatialParams_.aNonWettingSolidSurfaceParams(element_, scv_, elemSol_); + const auto& materialParams = spatialParams_.materialLawParams(element_, scv_, elemSol_); + using AnsSurface = typename SpatialParams::AnsSurface; + return AnsSurface::interfacialArea(surfaceParams, materialParams, sw, pc); + } + + Scalar darea_dpc(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aNonWettingSolidSurfaceParams(element_, scv_, elemSol_); + using AnsSurface = typename SpatialParams::AnsSurface; + return AnsSurface::dawn_dpc(surfaceParams, sw, pc); + } + + Scalar darea_dsw(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aNonWettingSolidSurfaceParams(element_, scv_, elemSol_); + using AnsSurface = typename SpatialParams::AnsSurface; + return AnsSurface::dawn_dsw(surfaceParams, sw, pc); + } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +template +class WettingSolidInterfacialArea : public FluidMatrix::Adapter, FluidMatrix::WettingSolidInterfacialAreaPcSw> +{ +public: + using Scalar = ScalarT; + + WettingSolidInterfacialArea(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) + : spatialParams_(sp), element_(element), scv_(scv), elemSol_(elemSol) + {} + + const auto& basicParams() const + { + return spatialParams_.aWettingSolidSurfaceParams(element_, scv_, elemSol_); + } + + Scalar area(const Scalar sw, const Scalar pc) const + { + const auto& surfaceParams = spatialParams_.aWettingSolidSurfaceParams(element_, scv_, elemSol_); + const auto& materialParams = spatialParams_.materialLawParams(element_, scv_, elemSol_); + using AwsSurface = typename SpatialParams::AwsSurface; + return AwsSurface::interfacialArea(surfaceParams, materialParams, sw, pc); + } + + Scalar darea_dpc(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aWettingSolidSurfaceParams(element_, scv_, elemSol_); + using AwsSurface = typename SpatialParams::AwsSurface; + return AwsSurface::dawn_dpc(surfaceParams, sw, pc); + } + + Scalar darea_dsw(const Scalar sw, const Scalar pc) + { + const auto& surfaceParams = spatialParams_.aWettingSolidSurfaceParams(element_, scv_, elemSol_); + using AwsSurface = typename SpatialParams::AwsSurface; + return AwsSurface::dawn_dsw(surfaceParams, sw, pc); + } + +private: + const SpatialParams& spatialParams_; + const Element& element_; + const Scv& scv_; + const ElemSol& elemSol_; +}; + +template +auto makeInterfacialArea(const Scalar& scalar, + const SpatialParams& sp, + const Element& element, + const Scv& scv, + const ElemSol& elemSol) +{ + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + constexpr bool hasNew = decltype(isValid(HasNewFIAIF()).template check())::value; + constexpr bool hasNewAtPos = decltype(isValid(HasNewFIAIFAtPos()).template check())::value; + if constexpr (hasNew) + return sp.fluidMatrixInteraction(element, scv, elemSol); + else if constexpr (hasNewAtPos) + return sp.fluidMatrixInteractionAtPos(scv.center()); + else + return makeFluidMatrixInteraction(WettingNonwettingInterfacialArea(scalar, sp, element, scv, elemSol), + NonwettingSolidInterfacialArea(scalar, sp, element, scv, elemSol), + WettingSolidInterfacialArea(scalar, sp, element, scv, elemSol)); +} + } // end namespace Deprecated #endif diff --git a/dumux/common/monotonecubicspline.hh b/dumux/common/monotonecubicspline.hh index 9fa462e63486c9059a5b1107842ede1dd9694ea9..75abcfd61f099df959a3b3512d763a5824f664ff 100644 --- a/dumux/common/monotonecubicspline.hh +++ b/dumux/common/monotonecubicspline.hh @@ -77,7 +77,7 @@ public: // check some requirements assert (x.size() == y.size()); assert (x.size() >=2); - assert (std::is_sorted(x.begin(), x.end())); + assert (std::is_sorted(x.begin(), x.end()) || std::is_sorted(x.rbegin(), x.rend())); // save a copy of the control points x_ = x; @@ -87,7 +87,8 @@ public: numPoints_ = x.size(); // whether we are increasing - increasing_ = y_.back() > y_.front(); + increasingX_ = x_.back() > x_.front(); + increasingY_ = y_.back() > y_.front(); // the slope at every control point m_.resize(numPoints_); @@ -114,21 +115,12 @@ public: */ Scalar eval(const Scalar x) const { - if (x <= x_.front()) + if ((x <= x_.front() && increasingX_) || (x >= x_.front() && !increasingX_)) return y_.front() + m_.front()*(x - x_.front()); - else if (x > x_.back()) + else if ((x > x_.back() && increasingX_) || (x < x_.back() && !increasingX_)) return y_.back() + m_.back()*(x - x_.back()); - else - { - const auto lookUpIndex = std::distance(x_.begin(), std::lower_bound(x_.begin(), x_.end(), x)); - assert(lookUpIndex != 0); - // interpolate parametrization parameter t in [0,1] - const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]); - const auto t = (x - x_[lookUpIndex-1])/h; - return y_[lookUpIndex-1]*Basis::h00(t) + h*m_[lookUpIndex-1]*Basis::h10(t) - + y_[lookUpIndex]*Basis::h01(t) + h*m_[lookUpIndex]*Basis::h11(t); - } + return eval_(x); } /*! @@ -138,22 +130,12 @@ public: */ Scalar evalDerivative(const Scalar x) const { - if (x <= x_.front()) + if ((x <= x_.front() && increasingX_) || (x >= x_.front() && !increasingX_)) return m_.front(); - else if (x > x_.back()) + else if ((x > x_.back() && increasingX_) || (x < x_.back() && !increasingX_)) return m_.back(); - else - { - const auto lookUpIndex = std::distance(x_.begin(), std::lower_bound(x_.begin(), x_.end(), x)); - assert(lookUpIndex != 0); - // interpolate parametrization parameter t in [0,1] - const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]); - const auto t = (x - x_[lookUpIndex-1])/h; - const auto dtdx = 1.0/h; - return y_[lookUpIndex-1]*Basis::dh00(t)*dtdx + m_[lookUpIndex-1]*Basis::dh10(t) - + y_[lookUpIndex]*Basis::dh01(t)*dtdx + m_[lookUpIndex]*Basis::dh11(t); - } + return evalDerivative_(x); } /*! @@ -164,40 +146,39 @@ public: */ Scalar evalInverse(const Scalar y) const { - if (increasing_) - { - if (y <= y_.front()) - return x_.front() + (y - y_.front())/m_.front(); - else if (y > y_.back()) - return x_.back() + (y - y_.back())/m_.back(); - else - { - const auto lookUpIndex = std::distance(y_.begin(), std::lower_bound(y_.begin(), y_.end(), y)); - assert(lookUpIndex != 0); - - return evalInverse_(y, lookUpIndex); - } - } + if ((y <= y_.front() && increasingY_) || (y >= y_.front() && !increasingY_)) + return x_.front() + (y - y_.front())/m_.front(); + else if ((y > y_.back() && increasingY_) || (y < y_.back() && !increasingY_)) + return x_.back() + (y - y_.back())/m_.back(); - else - { - if (y >= y_.front()) - return x_.front() + (y - y_.front())/m_.front(); - else if (y < y_.back()) - return x_.back() + (y - y_.back())/m_.back(); - else - { - const auto lookUpIndex = y_.size() - std::distance(y_.rbegin(), std::lower_bound(y_.rbegin(), y_.rend(), y)); - assert(lookUpIndex != 0); - - return evalInverse_(y, lookUpIndex); - } - } + return evalInverse_(y); } private: - Scalar evalInverse_(const Scalar y, const std::size_t lookUpIndex) const + Scalar eval_(const Scalar x) const { + // interpolate parametrization parameter t in [0,1] + const auto lookUpIndex = lookUpIndex_(x_, x, increasingX_); + const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]); + const auto t = (x - x_[lookUpIndex-1])/h; + return y_[lookUpIndex-1]*Basis::h00(t) + h*m_[lookUpIndex-1]*Basis::h10(t) + + y_[lookUpIndex]*Basis::h01(t) + h*m_[lookUpIndex]*Basis::h11(t); + } + + Scalar evalDerivative_(const Scalar x) const + { + // interpolate parametrization parameter t in [0,1] + const auto lookUpIndex = lookUpIndex_(x_, x, increasingX_); + const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]); + const auto t = (x - x_[lookUpIndex-1])/h; + const auto dtdx = 1.0/h; + return y_[lookUpIndex-1]*Basis::dh00(t)*dtdx + m_[lookUpIndex-1]*Basis::dh10(t) + + y_[lookUpIndex]*Basis::dh01(t)*dtdx + m_[lookUpIndex]*Basis::dh11(t); + } + + Scalar evalInverse_(const Scalar y) const + { + const auto lookUpIndex = lookUpIndex_(y_, y, increasingY_); auto localPolynomial = [&](const auto x) { // interpolate parametrization parameter t in [0,1] const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]); @@ -211,11 +192,31 @@ private: return findScalarRootBrent(x_[lookUpIndex-1]-eps, x_[lookUpIndex]+eps, localPolynomial); } + auto lookUpIndex_(const std::vector& vec, const Scalar v, bool increasing) const + { + return increasing ? lookUpIndexIncreasing_(vec, v) : lookUpIndexDecreasing_(vec, v); + } + + auto lookUpIndexIncreasing_(const std::vector& vec, const Scalar v) const + { + const auto lookUpIndex = std::distance(vec.begin(), std::lower_bound(vec.begin(), vec.end(), v)); + assert(lookUpIndex != 0); + return lookUpIndex; + } + + auto lookUpIndexDecreasing_(const std::vector& vec, const Scalar v) const + { + const auto lookUpIndex = vec.size() - std::distance(vec.rbegin(), std::lower_bound(vec.rbegin(), vec.rend(), v)); + assert(lookUpIndex != 0); + return lookUpIndex; + } + std::vector x_; //!< the x-coordinates std::vector y_; //!< the y-coordinates std::vector m_; //!< the slope for each control point std::size_t numPoints_; //!< the number of control points - bool increasing_; //!< if we are increasing monotone or not + bool increasingX_; //!< if we are increasing monotone or not + bool increasingY_; //!< if we are increasing monotone or not }; } // end namespace Dumux diff --git a/dumux/io/CMakeLists.txt b/dumux/io/CMakeLists.txt index 6032f37994f30212e869b1f36b982781e8679254..2a491c8b784acd8c59e957097192194b075a8343 100644 --- a/dumux/io/CMakeLists.txt +++ b/dumux/io/CMakeLists.txt @@ -14,6 +14,7 @@ name.hh ploteffectivediffusivitymodel.hh plotmateriallaw.hh plotmateriallaw3p.hh +plotpckrsw.hh plotthermalconductivitymodel.hh pointcloudvtkwriter.hh rasterimagereader.hh diff --git a/dumux/io/plotmateriallaw.hh b/dumux/io/plotmateriallaw.hh index 92488748d5c28cca2f29f880ab747e8baf84a772..cf2ff58006ef61d1f759481b0ee7649edb34fb8d 100644 --- a/dumux/io/plotmateriallaw.hh +++ b/dumux/io/plotmateriallaw.hh @@ -24,6 +24,8 @@ #ifndef DUMUX_PLOT_FLUID_MATRIX_LAW_HH #define DUMUX_PLOT_FLUID_MATRIX_LAW_HH +#warning "This header is deprecated and will be removed after 3.3. Use new 2p material laws and plot tools from io/plotpckrsw.hh" + #include #include #include diff --git a/dumux/io/plotpckrsw.hh b/dumux/io/plotpckrsw.hh new file mode 100644 index 0000000000000000000000000000000000000000..75bd4f2119229ef216b4787b8073fc17c9328c04 --- /dev/null +++ b/dumux/io/plotpckrsw.hh @@ -0,0 +1,223 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup InputOutput + * \brief Interface for plotting the two-phase fluid-matrix-interaction laws + */ +#ifndef DUMUX_IO_PLOT_PC_KR_SW_HH +#define DUMUX_IO_PLOT_PC_KR_SW_HH + +#include +#include +#include +#include + +namespace Dumux { + +namespace Detail { +template +Range evalFunctionForRange(const Function& f, const Range& range) +{ + Range result = range; + std::transform(range.begin(), range.end(), result.begin(), [&](auto x){ return f(x); }); + return result; +} +} // end namespace Detail + +/*! + * \ingroup InputOutput + * \brief sample the pc-sw curve + */ +template +auto samplePcSw(const PcKrSw& curve, const V& sw) +{ + return Detail::evalFunctionForRange([&](const auto s){ return curve.pc(s); }, sw); +} + +/*! + * \ingroup InputOutput + * \brief sample the pc-sw curve derivative wrt sw + */ +template +auto samplePcSwDerivative(const PcKrSw& curve, const V& sw) +{ + return Detail::evalFunctionForRange([&](const auto s){ return curve.dpc_dsw(s); }, sw); +} + +/*! + * \ingroup InputOutput + * \brief sample the sw-pc curve derivative wrt pc + */ +template +auto samplePcSwInverseDerivative(const PcKrSw& curve, const V& pc) +{ + return Detail::evalFunctionForRange([&](const auto p){ return curve.dsw_dpc(p); }, pc); +} + +/*! + * \ingroup InputOutput + * \brief sample sw-pc curve but return the log10 of the capillary pressure + */ +template +auto sampleLog10PcSw(const PcKrSw& curve, const V& sw) +{ + return Detail::evalFunctionForRange([&](const auto s){ using std::log10; return log10(curve.pc(s)); }, sw); +} + +/*! + * \ingroup InputOutput + * \brief sample krw-sw and krn-sw curves + */ +template +auto sampleRelPerms(const PcKrSw& curve, const V& sw) +{ + return std::make_tuple( + Detail::evalFunctionForRange([&](const auto s){ return curve.krw(s); }, sw), + Detail::evalFunctionForRange([&](const auto s){ return curve.krn(s); }, sw) + ); +} + +/*! + * \ingroup InputOutput + * \brief sample the derivatives of the krw-sw and krn-sw curves + */ +template +auto sampleRelPermDerivatives(const PcKrSw& curve, const V& sw) +{ + return std::make_tuple( + Detail::evalFunctionForRange([&](const auto s){ return curve.dkrw_dsw(s); }, sw), + Detail::evalFunctionForRange([&](const auto s){ return curve.dkrn_dsw(s); }, sw) + ); +} + +// forward declaration +template class GnuplotInterface; + +namespace Detail { +template +void addDataSetToGnuplot(GnuplotInterface& gnuplot, + const V& x, const V& y, + const std::string& curveName, + const std::string& curveOptions, + const std::string& xLabel, + const std::string& yLabel) +{ + gnuplot.setXlabel(xLabel); + gnuplot.setYlabel(yLabel); + gnuplot.addDataSetToPlot(x, y, curveName, curveOptions); +} +} // end namespace Detail + +/*! + * \ingroup InputOutput + * \brief Helper functions related to gnuplot + */ +namespace Gnuplot { + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addPcSw(GnuplotInterface& gnuplot, const V& sw, const V& pc, + const std::string& curveName = "pc-sw", + const std::string& curveOptions = "w l", + const std::string& xLabel = "wetting phase saturation [-]", + const std::string& yLabel = "capillary pressure [Pa]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, pc, curveName, curveOptions, xLabel, yLabel); +} + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addPcSwDerivative(GnuplotInterface& gnuplot, const V& sw, const V& dpc_dsw, + const std::string& curveName = "dpc-dsw", + const std::string& curveOptions = "w l", + const std::string& xLabel = "wetting phase saturation [-]", + const std::string& yLabel = "derivative of capillary pressure [Pa]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, dpc_dsw, curveName, curveOptions, xLabel, yLabel); +} + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addPcSwInverseDerivative(GnuplotInterface& gnuplot, const V& sw, const V& dpc_dsw, + const std::string& curveName = "dsw-dpc", + const std::string& curveOptions = "w l", + const std::string& xLabel = "capillary pressure [Pa]", + const std::string& yLabel = "derivative of saturation [1/Pa]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, dpc_dsw, curveName, curveOptions, xLabel, yLabel); +} + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addLog10PcSw(GnuplotInterface& gnuplot, const V& sw, const V& log10pc, + const std::string& curveName = "log10-pc-sw", + const std::string& curveOptions = "w l", + const std::string& xLabel = "wetting phase saturation [-]", + const std::string& yLabel = "log10 of capillary pressure [Pa]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, log10pc, curveName, curveOptions, xLabel, yLabel); +} + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addRelPerms(GnuplotInterface& gnuplot, const V& sw, const V& krw, const V& krn, + const std::string& curveName = "relperm", + const std::string& curveOptions = "w l", + const std::string& xLabel = "wetting phase saturation [-]", + const std::string& yLabel = "relative permeability [-]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, krw, curveName + "_krw", curveOptions, xLabel, yLabel); + Detail::addDataSetToGnuplot(gnuplot, sw, krn, curveName + "_krn", curveOptions, xLabel, yLabel); +} + +/*! + * \ingroup InputOutput + * \brief Convenience function for adding material law quantities to gnuplot + */ +template +void addRelPermDerivatives(GnuplotInterface& gnuplot, const V& sw, const V& krw, const V& krn, + const std::string& curveName = "relperm_dsw", + const std::string& curveOptions = "w l", + const std::string& xLabel = "wetting phase saturation [-]", + const std::string& yLabel = "derivative of the relative permeability [-]") +{ + Detail::addDataSetToGnuplot(gnuplot, sw, krw, curveName + "_krw", curveOptions, xLabel, yLabel); + Detail::addDataSetToGnuplot(gnuplot, sw, krn, curveName + "_krn", curveOptions, xLabel, yLabel); +} + +} // end namespace Gnuplot +} // end namespace Dumux + +#endif diff --git a/dumux/material/constraintsolvers/immiscibleflash.hh b/dumux/material/constraintsolvers/immiscibleflash.hh index b04e524534c0a833df16ecdc4a29513e8675ecd1..1c3a934be8061bf0177315b143c18395354ed4e1 100644 --- a/dumux/material/constraintsolvers/immiscibleflash.hh +++ b/dumux/material/constraintsolvers/immiscibleflash.hh @@ -29,6 +29,7 @@ #include #include +#include namespace Dumux { @@ -117,15 +118,15 @@ public: * \param fluidState Thermodynamic state of the fluids * \param paramCache Container for cache parameters * \param globalMolarities - * \param matParams The material law object + * \param material The material law object * * The phase's fugacities must already be set. */ template - void solve(FluidState &fluidState, - ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, - const ComponentVector &globalMolarities) + void solve(FluidState& fluidState, + ParameterCache& paramCache, + const MaterialLaw& material, + const ComponentVector& globalMolarities) { ///////////////////////// // Check if all fluid phases are incompressible @@ -164,12 +165,12 @@ public: // right hand side Vector b; - completeFluidState_(fluidState, paramCache, matParams); + completeFluidState_(fluidState, paramCache, material); const int nMax = 50; // <- maximum number of newton iterations for (int nIdx = 0; nIdx < nMax; ++nIdx) { // calculate Jacobian matrix and right hand side - linearize_(J, b, fluidState, paramCache, matParams, globalMolarities); + linearize_(J, b, fluidState, paramCache, material, globalMolarities); // Solve J*x = b deltaX = 0; @@ -207,7 +208,7 @@ public: */ // update the fluid quantities. - Scalar relError = update_(fluidState, paramCache, matParams, deltaX); + Scalar relError = update_(fluidState, paramCache, material, deltaX); if (relError < 1e-9) return; @@ -263,7 +264,7 @@ protected: Vector &b, FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, const ComponentVector &globalMolarities) { FluidState origFluidState(fluidState); @@ -287,7 +288,7 @@ protected: // deviate the mole fraction of the i-th component Scalar x_i = getQuantity_(fluidState, pvIdx); const Scalar eps = 1e-10/quantityWeight_(fluidState, pvIdx); - setQuantity_(fluidState, paramCache, matParams, pvIdx, x_i + eps); + setQuantity_(fluidState, paramCache, material, pvIdx, x_i + eps); // compute derivative of the defect calculateDefect_(tmp, origFluidState, fluidState, globalMolarities); @@ -325,7 +326,7 @@ protected: template Scalar update_(FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, const Vector &deltaX) { Scalar relError = 0; @@ -351,7 +352,7 @@ protected: setQuantityRaw_(fluidState, pvIdx, tmp - delta); } - completeFluidState_(fluidState, paramCache, matParams); + completeFluidState_(fluidState, paramCache, material); return relError; } @@ -359,7 +360,7 @@ protected: template void completeFluidState_(FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams) + const MaterialLaw& material) { // calculate the saturation of the last phase as a function of // the other saturations @@ -384,8 +385,7 @@ protected: // update the pressures using the material law (saturations // and first pressure are already set because it is implicitly // solved for.) - ComponentVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fluidState, wettingPhaseIdx_); + const auto pc = material.capillaryPressures(fluidState, wettingPhaseIdx_); for (int phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) fluidState.setPressure(phaseIdx, fluidState.pressure(0) @@ -432,7 +432,7 @@ protected: template void setQuantity_(FluidState &fs, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int pvIdx, Scalar value) { @@ -470,8 +470,7 @@ protected: // update all fluid pressures using the capillary pressure // law - ComponentVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, wettingPhaseIdx_); + const auto pc = material.capillaryPressures(fs, wettingPhaseIdx_); for (int phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) fs.setPressure(phaseIdx, fs.pressure(0) diff --git a/dumux/material/constraintsolvers/ncpflash.hh b/dumux/material/constraintsolvers/ncpflash.hh index 652ba0a9a96689f29c0388908ae882ef3001ea62..f5567a629ecfd488b847d6f40f4912bd6a54cde7 100644 --- a/dumux/material/constraintsolvers/ncpflash.hh +++ b/dumux/material/constraintsolvers/ncpflash.hh @@ -29,6 +29,7 @@ #include #include +#include namespace Dumux { @@ -143,14 +144,14 @@ public: * \param fluidState Thermodynamic state of the fluids * \param paramCache Container for cache parameters * \param globalMolarities - * \param matParams The material law object + * \param material The material law object * * The phase's fugacities must already be set. */ template void solve(FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, const ComponentVector &globalMolarities) { ///////////////////////// @@ -165,9 +166,7 @@ public: Vector b; // make the fluid state consistent with the fluid system. - completeFluidState_(fluidState, - paramCache, - matParams); + completeFluidState_(fluidState, paramCache, material); /* std::cout << "--------------------\n"; @@ -180,7 +179,7 @@ public: const int nMax = 50; // <- maximum number of newton iterations for (int nIdx = 0; nIdx < nMax; ++nIdx) { // calculate Jacobian matrix and right hand side - linearize_(J, b, fluidState, paramCache, matParams, globalMolarities); + linearize_(J, b, fluidState, paramCache, material, globalMolarities); // Solve J*x = b deltaX = 0; @@ -236,7 +235,7 @@ public: */ // update the fluid quantities. - Scalar relError = update_(fluidState, paramCache, matParams, deltaX); + Scalar relError = update_(fluidState, paramCache, material, deltaX); if (relError < 1e-9) return; @@ -313,7 +312,7 @@ protected: Vector &b, FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, const ComponentVector &globalMolarities) { FluidState origFluidState(fluidState); @@ -337,7 +336,7 @@ protected: // deviate the mole fraction of the i-th component Scalar x_i = getQuantity_(fluidState, pvIdx); const Scalar eps = 1e-8/quantityWeight_(fluidState, pvIdx); - setQuantity_(fluidState, paramCache, matParams, pvIdx, x_i + eps); + setQuantity_(fluidState, paramCache, material, pvIdx, x_i + eps); // compute derivative of the defect calculateDefect_(tmp, origFluidState, fluidState, globalMolarities); @@ -418,7 +417,7 @@ protected: template Scalar update_(FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, const Vector &deltaX) { Scalar relError = 0; @@ -486,7 +485,7 @@ protected: } } - completeFluidState_(fluidState, paramCache, matParams); + completeFluidState_(fluidState, paramCache, material); return relError; } @@ -494,7 +493,7 @@ protected: template void completeFluidState_(FluidState &fluidState, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams) + const MaterialLaw& material) { // calculate the saturation of the last phase as a function of // the other saturations @@ -506,8 +505,7 @@ protected: // update the pressures using the material law (saturations // and first pressure are already set because it is implicitly // solved for.) - ComponentVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fluidState, wettingPhaseIdx_); + const auto pc = material.capillaryPressures(fluidState, wettingPhaseIdx_); for (int phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) fluidState.setPressure(phaseIdx, fluidState.pressure(0) @@ -569,7 +567,7 @@ protected: template void setQuantity_(FluidState &fs, ParameterCache ¶mCache, - const typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int pvIdx, Scalar value) { @@ -608,8 +606,7 @@ protected: // update all fluid pressures using the capillary pressure // law - ComponentVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, wettingPhaseIdx_); + const auto pc = material.capillaryPressures(fs, wettingPhaseIdx_); for (int phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) fs.setPressure(phaseIdx, fs.pressure(0) diff --git a/dumux/material/fluidmatrixinteractions/2p/CMakeLists.txt b/dumux/material/fluidmatrixinteractions/2p/CMakeLists.txt index d2a4aacc9616dfdca638ab2e6b651cffb0814625..9c39155a73f5d0a8d07c8a007656bb68826e1b08 100644 --- a/dumux/material/fluidmatrixinteractions/2p/CMakeLists.txt +++ b/dumux/material/fluidmatrixinteractions/2p/CMakeLists.txt @@ -1,20 +1,27 @@ +add_subdirectory(interfacialarea) add_subdirectory(thermalconductivity) install(FILES brookscorey.hh brookscoreyparams.hh +datasplinemateriallaw.hh +efftoabsdefaultpolicy.hh efftoabslaw.hh efftoabslawparams.hh heatpipelaw.hh heatpipelawparams.hh linearmaterial.hh linearmaterialparams.hh +materiallaw.hh +noregularization.hh regularizedbrookscorey.hh regularizedbrookscoreyparams.hh regularizedlinearmaterial.hh regularizedlinearmaterialparams.hh regularizedvangenuchten.hh regularizedvangenuchtenparams.hh +smoothedlinearlaw.hh +splinemateriallaw.hh thermalconductivityjohansen.hh thermalconductivitysimplefluidlumping.hh thermalconductivitysomerton.hh diff --git a/dumux/material/fluidmatrixinteractions/2p/brookscorey.hh b/dumux/material/fluidmatrixinteractions/2p/brookscorey.hh index 19cfc930bc2ca985bfe607a918765857c2a91145..a69963c302d342c3b284904148381461a2261abe 100644 --- a/dumux/material/fluidmatrixinteractions/2p/brookscorey.hh +++ b/dumux/material/fluidmatrixinteractions/2p/brookscorey.hh @@ -22,9 +22,10 @@ * \brief Implementation of the capillary pressure and * relative permeability <-> saturation relations according to Brooks and Corey. */ -#ifndef DUMUX_BROOKS_COREY_HH -#define DUMUX_BROOKS_COREY_HH +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_BROOKS_COREY_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_BROOKS_COREY_HH +// remove from here after release 3.3 ///////////// #include "brookscoreyparams.hh" #include @@ -45,7 +46,7 @@ namespace Dumux { *\see BrooksCoreyParams */ template > -class BrooksCorey +class [[deprecated("Use new material laws and FluidMatrix::BrooksCorey instead!")]] BrooksCorey { public: using Params = ParamsT; @@ -272,5 +273,507 @@ public: }; } // end namespace Dumux +// remove until here after release 3.3 ///////////// + +#include +#include + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * + * \brief Implementation of the Brooks-Corey capillary pressure <-> + * saturation relation. This class bundles the "raw" curves + * as static members and doesn't concern itself converting + * absolute to effective saturations and vice versa. + * + * For general info: EffToAbsLaw + * + *\see BrooksCoreyParams + */ +class BrooksCorey +{ +public: + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + * \note The Brooks Corey laws are parameterized with two parameters: \f$\mathrm{p_{ce}, \lambda}\f$, + * the capillary entry pressure in \f$\mathrm{[Pa]}\f$] and a dimensionless shape parameter, respectively. + */ + template + struct Params + { + Params(Scalar pcEntry, Scalar lambda) + : pcEntry_(pcEntry), lambda_(lambda) + {} + + Scalar pcEntry() const{ return pcEntry_; } + void setPcEntry(Scalar pcEntry){ pcEntry_ = pcEntry; } + + Scalar lambda() const { return lambda_; } + void setLambda(Scalar lambda) { lambda_ = lambda; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(pcEntry(), p.pcEntry(), 1e-6) + && Dune::FloatCmp::eq(lambda(), p.lambda(), 1e-6); + } + + private: + Scalar pcEntry_, lambda_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto pcEntry = getParamFromGroup(paramGroup, "BrooksCoreyPcEntry"); + const auto lambda = getParamFromGroup(paramGroup, "BrooksCoreyLambda"); + return {pcEntry, lambda}; + } + + /*! + * \brief The capillary pressure-saturation curve according to Brooks & Corey. + * + * The Brooks-Corey empirical capillary pressure <-> saturation + * function is given by + * + * \f$\mathrm{ p_c = p_{ce}\overline{S}_w^{-1/\lambda} + * }\f$ + * + * \param swe Effective saturation of the wetting phase \f$\mathrm{[\overline{S}_w]}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Capillary pressure calculated by Brooks & Corey constitutive relation. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar pc(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + return params.pcEntry()*pow(swe, -1.0/params.lambda()); + } + + /*! + * \brief The saturation-capillary pressure curve according to Brooks & Corey. + * + * This is the inverse of the capillary pressure-saturation curve: + * \f$\mathrm{ \overline{S}_w = (\frac{p_c}{p_{ce}})^{-\lambda}}\f$ + * + * \param pc Capillary pressure \f$\mathrm{[p_c]}\f$ in \f$\mathrm{[Pa]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + * \return Effective wetting phase saturation calculated as inverse of BrooksCorey constitutive relation. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar swe(Scalar pc, const Params& params) + { + using std::pow; + using std::max; + + pc = max(pc, 0.0); // the equation below is undefined for negative pcs + + return pow(pc/params.pcEntry(), -params.lambda()); + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + */ + template + static Scalar endPointPc(const Params& params) + { return params.pcEntry(); } + + /*! + * \brief The partial derivative of the capillary + * pressure w.r.t. the effective saturation according to Brooks & Corey. + * + * This is equivalent to + * \f$\mathrm{\frac{\partial p_c}{\partial \overline{S}_w} = + * -\frac{p_{ce}}{\lambda} \overline{S}_w^{-1/\lambda - 1} + * }\f$ + * + * \param swe Effective saturation of the wetting phase \f$\mathrm{[\overline{S}_w]}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + * \return Partial derivative of \f$\mathrm{[p_c]}\f$ w.r.t. effective saturation according to Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dpc_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + return -params.pcEntry()/params.lambda() * pow(swe, -1.0/params.lambda() - 1.0); + } + + /*! + * \brief The partial derivative of the effective + * saturation w.r.t. the capillary pressure according to Brooks & Corey. + * + * \param pc Capillary pressure \f$\mathrm{[p_c]}\f$ in \f$\mathrm{[Pa]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + * \return Partial derivative of effective saturation w.r.t. \f$\mathrm{[p_c]}\f$ according to Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dswe_dpc(Scalar pc, const Params& params) + { + using std::pow; + using std::max; + + pc = max(pc, 0.0); // the equation below is undefined for negative pcs + + return -params.lambda()/params.pcEntry() * pow(pc/params.pcEntry(), - params.lambda() - 1.0); + } + + /*! + * \brief The relative permeability for the wetting phase of + * the medium implied by the Brooks-Corey + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Relative permeability of the wetting phase calculated as implied by Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar krw(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + return pow(swe, 2.0/params.lambda() + 3.0); + } + + /*! + * \brief The derivative of the relative permeability for the + * wetting phase with regard to the wetting saturation of the + * medium implied by the Brooks-Corey parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the relative permeability of the wetting phase w.r.t. effective wetting phase + * saturation calculated as implied by Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dkrw_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + return (2.0/params.lambda() + 3.0)*pow(swe, 2.0/params.lambda() + 2.0); + } + + /*! + * \brief The relative permeability for the non-wetting phase of + * the medium as implied by the Brooks-Corey + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + * \return Relative permeability of the non-wetting phase calculated as implied by Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar krn(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const Scalar exponent = 2.0/params.lambda() + 1.0; + const Scalar sne = 1.0 - swe; + return sne*sne*(1.0 - pow(swe, exponent)); + } + + /*! + * \brief The derivative of the relative permeability for the + * non-wetting phase in regard to the wetting saturation of + * the medium as implied by the Brooks-Corey + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the relative permeability of the non-wetting phase w.r.t. effective wetting phase + * saturation calculated as implied by Brooks & Corey. + * + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dkrn_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const auto lambdaInv = 1.0/params.lambda(); + const auto swePow = pow(swe, 2*lambdaInv); + return 2.0*(swe - 1.0)*(1.0 + (0.5 + lambdaInv)*swePow - (1.5 + lambdaInv)*swePow*swe); + } +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A regularization for the BrooksCorey material law + * \note Regularization can be turned of by setting the threshold parameters + * out of range (runtime) or by replacing + * this class by NoRegularization (compile time). + */ +template +class BrooksCoreyRegularization +{ +public: + //! Regularization parameters + template + struct Params + { + Params(S pcLowSwe = 0.01) : pcLowSwe_(pcLowSwe) {} + + S pcLowSwe() const { return pcLowSwe_; } + void setPcLowSwe(S pcLowSwe) { pcLowSwe_ = pcLowSwe; } + + private: + S pcLowSwe_ = 0.01; + }; + + //! Initialize the spline + template + void init(const MaterialLaw* m, const std::string& paramGroup) + { + pcLowSwe_ = getParamFromGroup(paramGroup, "BrooksCoreyPcLowSweThreshold", 0.01); + entryPressure_ = getParamFromGroup(paramGroup, "BrooksCoreyPcEntry"); + + initPcParameters_(m, pcLowSwe_); + } + + template + void init(const MaterialLaw* m, const BaseParams& bp, const EffToAbsParams& etap, const Params& p) + { + pcLowSwe_ = p.pcLowSwe(); + entryPressure_ = bp.pcEntry(); + + initPcParameters_(m, pcLowSwe_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const BrooksCoreyRegularization& o) const + { + return Dune::FloatCmp::eq(pcLowSwe_, o.pcLowSwe_, 1e-6) + && Dune::FloatCmp::eq(entryPressure_, o.entryPressure_, 1e-6); + } + + /*! + * \brief The regularized capillary pressure-saturation curve + * regularized part: + * - low saturation: extend the \f$\mathrm{p_c(S_w)}\f$ curve with the slope at the regularization point (i.e. no kink). + * - high saturation: connect the high regularization point with \f$\mathrm{\overline{S}_w =1}\f$ + * with a spline and continue linearly for \f$\mathrm{\overline{S}_w > 1}\f$ + */ + OptionalScalar pc(const Scalar swe) const + { + // make sure that the capillary pressure observes a derivative + // != 0 for 'illegal' saturations. This is favourable for the + // newton solver (if the derivative is calculated numerically) + // in order to get the saturation moving to the right + // direction if it temporarily is in an 'illegal' range. + if (swe <= pcLowSwe_) + return pcLowSwePcValue_ + pcDerivativeLowSw_*(swe - pcLowSwe_); + + else if (swe > 1.0) + return pcDerivativeHighSwEnd_*(swe - 1.0) + entryPressure_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized partial derivative of the capillary pressure w.r.t. the saturation + */ + OptionalScalar dpc_dswe(const Scalar swe) const + { + if (swe < pcLowSwe_) + return pcDerivativeLowSw_; + + else if (swe > 1.0) + return pcDerivativeHighSwEnd_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized saturation-capillary pressure curve + */ + OptionalScalar swe(const Scalar pc) const + { + if (pc <= entryPressure_) + return 1.0 + (pc - entryPressure_)/pcDerivativeHighSwEnd_; + + else if (pc >= pcLowSwePcValue_) + return (pc - pcLowSwePcValue_)/pcDerivativeLowSw_ + pcLowSwe_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized partial derivative of the saturation to the capillary pressure + */ + OptionalScalar dswe_dpc(const Scalar pc) const + { + if (pc <= entryPressure_) + return 1.0/pcDerivativeHighSwEnd_; + + else if (pc >= pcLowSwePcValue_) + return 1.0/pcDerivativeLowSw_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized relative permeability for the wetting phase + */ + OptionalScalar krw(const Scalar swe) const + { + if (swe <= 0.0) + return 0.0; + else if (swe >= 1.0) + return 1.0; + else + return {}; // no regularization + } + + /*! + * \brief The regularized derivative of the relative permeability for the wetting phase w.r.t. saturation + */ + OptionalScalar dkrw_dswe(const Scalar swe) const + { + if (swe < 0.0) + return 0.0; + else if (swe >= 1.0) + return 0.0; + else + return {}; // no regularization + } + + /*! + * \brief The regularized relative permeability for the non-wetting phase + */ + OptionalScalar krn(const Scalar swe) const + { + if (swe <= 0.0) + return 1.0; + else if (swe >= 1.0) + return 0.0; + else + return {}; // no regularization + } + + /*! + * \brief The regularized derivative of the relative permeability for the non-wetting phase w.r.t. saturation + */ + OptionalScalar dkrn_dswe(const Scalar swe) const + { + if (swe <= 0.0) + return 0.0; + else if (swe >= 1.0) + return 0.0; + else + return {}; // no regularization + } + +private: + template + void initPcParameters_(const MaterialLaw* m, const Scalar lowSwe) + { + const auto lowSw = MaterialLaw::EffToAbs::sweToSw(lowSwe, m->effToAbsParams()); + const auto highSw = MaterialLaw::EffToAbs::sweToSw(1.0, m->effToAbsParams()); + const auto dsw_dswe = MaterialLaw::EffToAbs::dsw_dswe(m->effToAbsParams()); + pcDerivativeLowSw_ = m->template dpc_dsw(lowSw)*dsw_dswe; + pcDerivativeHighSwEnd_ = m->template dpc_dsw(highSw)*dsw_dswe; + pcLowSwePcValue_ = m->template pc(lowSw); + } + + Scalar pcLowSwe_; + Scalar pcLowSwePcValue_; + Scalar entryPressure_; + Scalar pcDerivativeLowSw_; + Scalar pcDerivativeHighSwEnd_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A default configuration for using the VanGenuchten material law + */ +template +using BrooksCoreyDefault = TwoPMaterialLaw, TwoPEffToAbsDefaultPolicy>; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A default configuration without regularization for using the VanGenuchten material law + */ +template +using BrooksCoreyNoReg = TwoPMaterialLaw; + +} // end namespace Dumux::FluidMatrix #endif diff --git a/dumux/material/fluidmatrixinteractions/2p/brookscoreyparams.hh b/dumux/material/fluidmatrixinteractions/2p/brookscoreyparams.hh index ad0f28a6e77020cdb47d0b02ac2393c8e8ce01fc..a8100a145857da7142ed213210117d3a627fcf43 100644 --- a/dumux/material/fluidmatrixinteractions/2p/brookscoreyparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/brookscoreyparams.hh @@ -36,6 +36,7 @@ namespace Dumux { * for the Brooks Corey constitutive relations. * \see BrooksCorey */ +// "Use new material laws! Removal after 3.3") template class BrooksCoreyParams { diff --git a/dumux/material/fluidmatrixinteractions/2p/datasplinemateriallaw.hh b/dumux/material/fluidmatrixinteractions/2p/datasplinemateriallaw.hh new file mode 100644 index 0000000000000000000000000000000000000000..990e43fd09648b7e20d08365fc8126d05a079637 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/datasplinemateriallaw.hh @@ -0,0 +1,201 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Pc- and Kr-sw curves based on monotone splines through given data points + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_DATA_SPLINE_MATERIAL_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_DATA_SPLINE_MATERIAL_HH + +#include +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Pc- and Kr-sw curves based on monotone splines through given data points + * \tparam S the type for scalar numbers + * \tparam approximatePcSwInverse if this is set true, the + * spline approximates sw(pc) and evaluating pc(sw) needs spline inversion. + * if this is false, the spline approximates pc(sw) and evaluating + * sw(pc) needs spline inversion. Spline inversion is rather expensive + * since it has to be done numerically. + */ +template +class DataSplineTwoPMaterialLaw +: public Adapter, PcKrSw> +{ +public: + + using Scalar = S; + + /*! + * \brief Return the number of fluid phases + */ + static constexpr int numFluidPhases() + { return 2; } + + static constexpr bool isRegularized() + { return false; } + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + DataSplineTwoPMaterialLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + */ + explicit DataSplineTwoPMaterialLaw(const std::string& paramGroup) + { + using V = std::vector; + const std::string swPcGroup = paramGroup.empty() ? "Pc" : paramGroup + ".Pc"; + const auto swPc = getParamFromGroup(swPcGroup, "SwData"); + const std::string krwPcGroup = paramGroup.empty() ? "Krw" : paramGroup + ".Krw"; + const auto swKrw = getParamFromGroup(krwPcGroup, "SwData"); + const std::string krnPcGroup = paramGroup.empty() ? "Krn" : paramGroup + ".Krn"; + const auto swKrn = getParamFromGroup(krnPcGroup, "SwData"); + + const auto pc = getParamFromGroup(paramGroup, "PcData"); + const auto krw = getParamFromGroup(paramGroup, "KrwData"); + const auto krn = getParamFromGroup(paramGroup, "KrnData"); + + updateData_(swPc, pc, swKrw, krw, swKrn, krn); + } + + /*! + * \brief Construct from user data + */ + DataSplineTwoPMaterialLaw(const std::vector& swPc, + const std::vector& pc, + const std::vector& swKrw, + const std::vector& krw, + const std::vector& swKrn, + const std::vector& krn) + { + updateData_(swPc, pc, swKrw, krw, swKrn, krn); + } + + /*! + * \brief The capillary pressure-saturation curve + */ + Scalar pc(const Scalar sw) const + { + if constexpr (approximatePcSwInverse) + return pcSpline_.evalInverse(sw); + else + return pcSpline_.eval(sw); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + Scalar dpc_dsw(const Scalar sw) const + { + if constexpr (approximatePcSwInverse) + return 1.0/pcSpline_.evalDerivative(pcSpline_.evalInverse(sw)); + else + return pcSpline_.evalDerivative(sw); + } + + /*! + * \brief The saturation-capillary pressure curve + */ + Scalar sw(const Scalar pc) const + { + if constexpr (approximatePcSwInverse) + return pcSpline_.eval(pc); + else + return pcSpline_.evalInverse(pc); + } + + /*! + * \brief The partial derivative of the saturation to the capillary pressure + */ + Scalar dsw_dpc(const Scalar pc) const + { + if constexpr (approximatePcSwInverse) + return pcSpline_.evalDerivative(pc); + else + return 1.0/pcSpline_.evalDerivative(pcSpline_.evalInverse(pc)); + } + + /*! + * \brief The relative permeability for the wetting phase + */ + Scalar krw(const Scalar sw) const + { + return krwSpline_.eval(sw); + } + + /*! + * \brief The derivative of the relative permeability for the wetting phase w.r.t. saturation + */ + Scalar dkrw_dsw(const Scalar sw) const + { + return krwSpline_.evalDerivative(sw); + } + + /*! + * \brief The relative permeability for the non-wetting phase + */ + Scalar krn(const Scalar sw) const + { + return krnSpline_.eval(sw); + } + + /*! + * \brief The derivative of the relative permeability for the non-wetting phase w.r.t. saturation + */ + Scalar dkrn_dsw(const Scalar sw) const + { + return krnSpline_.evalDerivative(sw); + } + +private: + void updateData_(const std::vector& swPc, + const std::vector& pc, + const std::vector& swKrw, + const std::vector& krw, + const std::vector& swKrn, + const std::vector& krn) + { + if constexpr (approximatePcSwInverse) + pcSpline_.updatePoints(pc, swPc); + else + pcSpline_.updatePoints(swPc, pc); + + krwSpline_.updatePoints(swKrw, krw); + krnSpline_.updatePoints(swKrn, krn); + } + + MonotoneCubicSpline pcSpline_; + MonotoneCubicSpline krwSpline_; + MonotoneCubicSpline krnSpline_; +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/efftoabsdefaultpolicy.hh b/dumux/material/fluidmatrixinteractions/2p/efftoabsdefaultpolicy.hh new file mode 100644 index 0000000000000000000000000000000000000000..c0af48e267bc868a5014d97509e28c8553f8006a --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/efftoabsdefaultpolicy.hh @@ -0,0 +1,166 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief This is a policy for 2p material laws how to convert absolute to relative + * saturations and vice versa. + * + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_EFF_TO_ABS_DEFAULT_POLICY_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_EFF_TO_ABS_DEFAULT_POLICY_HH + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * + * \brief This is a policy for 2p material laws how to convert absolute to relative + * saturations and vice versa. + * + * Material laws (like VanGenuchten or BrooksCorey) are defined for effective saturations. + * The numeric calculations however are performed with absolute saturations. The policy class converts + * the saturations. This allows for changing the calculation of the effective + * saturations easily, as this is subject of discussion / may be problem specific. + */ +class TwoPEffToAbsDefaultPolicy +{ +public: + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + * \note The efftoabs policy need two parameters: \f$\mathrm{S_{w,r}}, \mathrm{S_{n,r}}\f$. + * For the respective formulas check out the description of the free function. + */ + template + struct Params + { + Params(const Scalar swr = 0.0, const Scalar snr = 0.0) + : swr_(swr), snr_(snr) + {} + + /*! + * \brief Return the residual wetting saturation. + */ + Scalar swr() const + { return swr_; } + + /*! + * \brief Set the residual wetting saturation. + */ + void setSwr(Scalar v) + { swr_ = v; } + + /*! + * \brief Return the residual non-wetting saturation. + */ + Scalar snr() const + { return snr_; } + + /*! + * \brief Set the residual non-wetting saturation. + */ + void setSnr(Scalar v) + { snr_ = v; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(swr(), p.swr(), 1e-6) + && Dune::FloatCmp::eq(snr(), p.snr(), 1e-6); + } + private: + Scalar swr_; + Scalar snr_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + Params params; + params.setSwr(getParamFromGroup(paramGroup, "Swr", 0.0)); + params.setSnr(getParamFromGroup(paramGroup, "Snr", 0.0)); + return params; + } + + /*! + * \brief Convert an absolute wetting saturation to an effective one. + * + * \param sw Absolute saturation of the wetting phase \f$\mathrm{[{S}_w]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Effective saturation of the wetting phase. + */ + template + static Scalar swToSwe(const Scalar sw, const Params& params) + { + return (sw - params.swr())/(1.0 - params.swr() - params.snr()); + } + + /*! + * \brief Convert an effective wetting saturation to an absolute one. + * + * \param swe Effective saturation of the non-wetting phase \f$\mathrm{[\overline{S}_n]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Absolute saturation of the non-wetting phase. + */ + template + static Scalar sweToSw(const Scalar swe, const Params& params) + { + return swe*(1.0 - params.swr() - params.snr()) + params.swr(); + } + + /*! + * \brief Derivative of the effective saturation w.r.t. the absolute saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the effective saturation w.r.t. the absolute saturation. + */ + template + static Scalar dswe_dsw(const Params& params) + { + return 1.0/(1.0 - params.swr() - params.snr()); + } + + /*! + * \brief Derivative of the absolute saturation w.r.t. the effective saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the absolute saturation w.r.t. the effective saturation. + */ + template + static Scalar dsw_dswe(const Params& params) + { + return 1.0 - params.swr() - params.snr(); + } +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh b/dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh index 6afd11a0fa45033379384250574a1790fc1d956d..41a49ea7a172f76ea9dfd3d8fa85127e7022c796 100644 --- a/dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh +++ b/dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_EFF_TO_ABS_LAW_HH #define DUMUX_EFF_TO_ABS_LAW_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include "efftoabslawparams.hh" namespace Dumux { diff --git a/dumux/material/fluidmatrixinteractions/2p/efftoabslawparams.hh b/dumux/material/fluidmatrixinteractions/2p/efftoabslawparams.hh index bd83efb5462a6673701deccb68e465526600f0fc..a9f03997e288a0420dca20ab5752af2f5e726134 100644 --- a/dumux/material/fluidmatrixinteractions/2p/efftoabslawparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/efftoabslawparams.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_EFF_TO_ABS_LAW_PARAMS_HH #define DUMUX_EFF_TO_ABS_LAW_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include namespace Dumux { @@ -37,7 +39,7 @@ namespace Dumux { * saturations. */ template -class EffToAbsLawParams : public EffLawParamsT +class [[deprecated("Use new material laws! Removal after 3.3")]] EffToAbsLawParams : public EffLawParamsT { using EffLawParams = EffLawParamsT; public: diff --git a/dumux/material/fluidmatrixinteractions/2p/heatpipelaw.hh b/dumux/material/fluidmatrixinteractions/2p/heatpipelaw.hh index b21b2ebe5f4ef1c2f57e2749ef4d1a3e3d3292b2..43a96a6170754b17cc21d909f5c0075b177fa2fb 100644 --- a/dumux/material/fluidmatrixinteractions/2p/heatpipelaw.hh +++ b/dumux/material/fluidmatrixinteractions/2p/heatpipelaw.hh @@ -22,9 +22,10 @@ * \brief Implementation of the capillary pressure <-> saturation relation * for the heatpipe problem. */ -#ifndef HEATPIPELAW_HH -#define HEATPIPELAW_HH +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_HEATPIPELAW_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_HEATPIPELAW_HH +// remove from here after release 3.3 ///////////// #include "heatpipelawparams.hh" #include @@ -45,7 +46,7 @@ namespace Dumux { * converting absolute to effective saturations and vince versa. */ template > -class HeatPipeLaw +class [[deprecated("Use new material laws and FluidMatrix::HeatPipeLaw instead!")]] HeatPipeLaw { public: using Params = ParamsT; @@ -166,5 +167,215 @@ private: }; } // end namespace Dumux +// remove until here after release 3.3 ///////////// + +#include +#include + +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the capillary pressure <-> saturation + * relation for the heatpipe problem. + */ +template +class HeatPipeLaw : Adapter, PcKrSw> +{ + +public: + using Scalar = ScalarType; + using EffToAbsParams = typename EffToAbsPolicy::template Params; + using EffToAbs = EffToAbsPolicy; + + /*! + * \brief Return the number of fluid phases + */ + static constexpr int numFluidPhases() + { return 2; } + + /*! + * \brief Return whether this law is regularized + */ + static constexpr bool isRegularized() + { return false; } + + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + */ + struct Params + { + Params(Scalar gamma, Scalar p0) + : gamma_(gamma), p0_(p0) + {} + + Scalar gamma() const { return gamma_; } + void setGamma(Scalar gamma) { gamma_ = gamma; } + + Scalar p0() const { return p0_; } + void setP0(Scalar p0) { p0_ = p0; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(gamma(), p.gamma(), 1e-6) + && Dune::FloatCmp::eq(p0(), p.p0(), 1e-6); + } + + private: + Scalar gamma_, p0_; + }; + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + HeatPipeLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit HeatPipeLaw(const std::string& paramGroup) + { + params_ = makeParams(paramGroup); + effToAbsParams_ = EffToAbs::template makeParams(paramGroup); + } + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + HeatPipeLaw(const Params& params, + const EffToAbsParams& effToAbsParams = {}) + : params_(params) + , effToAbsParams_(effToAbsParams) + , spline_(eps_, 1.0, // x1, x2 + eps_*eps_*eps_, 1.0, // y1, y2 + 3.0*eps_*eps_, 0.0) // m1, m2 + {} + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + static Params makeParams(const std::string& paramGroup) + { + const auto gamma = getParamFromGroup(paramGroup, "HeatpipeLawGamma"); + const auto p0 = getParamFromGroup(paramGroup, "HeatpipeLawP0"); + return {gamma, p0}; + } + + /*! + * \brief The capillary pressure-saturation curve. + * + * \param swe Effective saturation of the wetting phase \f$\mathrm{\overline{S}_w}\f$ + */ + template + Scalar pc(Scalar swe) const + { + const Scalar sne = 1 - swe; + const Scalar p0Gamma = params_.p0()*params_.gamma(); + + // regularization + if (sne >= 1.0) + { + const Scalar y = p0Gamma*( (1.263*1.0 - 2.120)*1.0 + 1.417)*1.0; + const Scalar m = p0Gamma*((3*1.263*1.0 - 2*2.120)*1.0 + 1.417); + return (sne - 1)*m + y; + } + else if (sne <= 0.0) + return sne * p0Gamma*1.417; + else + return p0Gamma*((1.263*sne - 2.120)*sne + 1.417) * sne; + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + */ + template + Scalar endPointPc() const + { return 0.0; } + + /*! + * \brief The partial derivative of the capillary + * pressure w.r.t. the effective saturation. + * + * \param swe Effective saturation of the wetting phase \f$\mathrm{\overline{S}_w}\f$ + */ + template + Scalar dpc_dswe(Scalar swe) const + { + const Scalar sne = 1 - swe; + const Scalar p0Gamma = params_.p0()*params_.gamma(); + if (sne > 1.0) + sne = 1.0; + else if (sne <= 0.0) + return -p0Gamma*1.417; + else + return - p0Gamma*((3*1.263*sne - 2*2.120)*sne + 1.417); + } + + /*! + * \brief The relative permeability for the wetting phase of + * the medium. + * + * \param swe The mobile saturation of the wetting phase. + */ + template + Scalar krw(Scalar swe) const + { + return kr_(swe); + } + + /*! + * \brief The relative permeability for the non-wetting phase + * of the medium. + * + * \param swe The mobile saturation of the wetting phase. + */ + template + Scalar krn(Scalar swe) const + { + const Scalar sne = 1 - swe; // TODO does this make sense? + return kr_(sne); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const HeatPipeLaw& o) const + { + return params_ == o.params_ + && effToAbsParams_ == o.effToAbsParams_; + } + + const EffToAbsParams& effToAbsParams() const + { return effToAbsParams_; } + +private: + + Scalar kr_(Scalar s) const + { + if (s >= 1.0) + return 1; + else if (s <= 0.0) + return 0; + else if (s > eps_) + return spline_.eval(s); // regularize + else + return s*s*s; + } + + Params params_; + EffToAbsParams effToAbsParams_; + static constexpr Scalar eps_ = 0.95; + Dumux::Spline spline_; +}; +} // end namespace Dumux::FluidMatrix #endif diff --git a/dumux/material/fluidmatrixinteractions/2p/heatpipelawparams.hh b/dumux/material/fluidmatrixinteractions/2p/heatpipelawparams.hh index 4f127d89c4f6a2a64556451ce51822d2027419f3..b51e786235b0ab8f64793c86bf7941ad1ac1bfe4 100644 --- a/dumux/material/fluidmatrixinteractions/2p/heatpipelawparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/heatpipelawparams.hh @@ -32,6 +32,7 @@ namespace Dumux { * \brief Reference implementation of a params for the heat pipe's * material law */ +// "Use new material laws! Removal after 3.3") template class HeatPipeLawParams { diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/CMakeLists.txt b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f908e650e54f0f5f52649911c2473d76d69d6dbd --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/CMakeLists.txt @@ -0,0 +1,8 @@ +install(FILES +exponential.hh +exponentialcubic.hh +interfacialarea.hh +pcmax.hh +polynomial2ndorder.hh +polynomialedgezero2ndorder.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/material/fluidmatrixinteractions/2p/interfacialarea) diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponential.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponential.hh new file mode 100644 index 0000000000000000000000000000000000000000..4d3b6b2b81439865bbda73ee94bbe833314ada5e --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponential.hh @@ -0,0 +1,147 @@ +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Specification of a function relating volume specific interfacial area to capillary pressure and saturation. + * This function is exponential. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the exponential function relating + * specific interfacial area to wetting phase saturation and + * capillary pressure as suggested by Nuske(2009) (Diploma thesis) \cite nuske2009 . + */ +class InterfacialAreaExponential +{ +public: + + template + struct Params + { + Params(Scalar swr = 0, Scalar a1 = 0, Scalar a2 = 0, Scalar a3 = 0) + : swr_(swr), a1_(a1), a2_(a2), a3_(a3) {} + + Scalar swr() const { return swr_; } + void setSwr(Scalar swr) { swr_ = swr; } + + Scalar a1() const { return a1_; } + void setA1(Scalar a1) { a1_ = a1; } + + Scalar a2() const { return a2_; } + void setA2(Scalar a2) { a2_ = a2; } + + Scalar a3() const { return a3_; } + void setA3(Scalar a3) { a3_ = a3; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(swr(), p.swr(), 1e-6) + && Dune::FloatCmp::eq(a1(), p.a1(), 1e-6) + && Dune::FloatCmp::eq(a2(), p.a2(), 1e-6) + && Dune::FloatCmp::eq(a3(), p.a3(), 1e-6); + } + + private: + Scalar swr_, a1_, a2_, a3_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto swr = getParamFromGroup(paramGroup, "Swr", 0.0); + const auto a1 = getParamFromGroup(paramGroup, "A1"); + const auto a2 = getParamFromGroup(paramGroup, "A2"); + const auto a3 = getParamFromGroup(paramGroup, "A3"); + return {swr, a1, a2, a3}; + } + + + /*! + * \brief The interfacial area + * + * the suggested (as estimated from pore network models) awn surface: + * \f$\mathrm{ + a_{wn} = a_1 * (S_{wr}-S_w) .* (1-S_w) + a_2 * (S_{wr}-S_w) * (1-S_w) * \exp( a_3 * p_c) ; + }\f$ + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar area(const Scalar swe, const Scalar pc, const Params& params) + { + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + const Scalar swr = params.swr(); + using std::exp; + return a1 * (swr-swe) * (1-swe) + a2 * (swr-swe) * (1-swe) * exp( a3 * pc) ; + } + + /*! \brief the derivative of specific interfacial area function w.r.t. capillary pressure + * + * \param params parameter container for the coefficients of the surface + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + */ + template + static Scalar darea_dpc(const Scalar swe, const Scalar pc, const Params& params) + { + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + const Scalar swr = params.swr(); + using std::exp; + return a2 * a3 * (swr-swe) * (1-swe) * exp(a3*pc); + } + + /*! \brief the derivative of specific interfacial area function w.r.t. saturation + * + * \param params parameter container for the coefficients of the surface + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + */ + template + static Scalar darea_dsw(const Scalar swe, const Scalar pc, const Params& params) + { + Scalar a1 = params.a1(); + Scalar a2 = params.a2(); + Scalar a3 = params.a3(); + Scalar swr = params.swr(); + using std::exp; + return - a1 *(1+swr-2*swe) - a2 * exp(a3*pc) * (1+swr-2*swe); + } + +}; + +} // namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponentialcubic.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponentialcubic.hh new file mode 100644 index 0000000000000000000000000000000000000000..131912dcfb719cf719e77de174263cf304527318 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/exponentialcubic.hh @@ -0,0 +1,110 @@ +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Specification of a function relating volume specific interfacial area to capillary pressure and saturation. + * This function is of third order in pc. + * \note It is used for calculating the interfacial area between the nonwetting and solid phase + * by Nuske 2014 (https://elib.uni-stuttgart.de/handle/11682/614, page 62) \cite nuske2014. + * + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL_CUBIC +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL_CUBIC + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of a exponential function relating + * specific interfacial area to wetting phase saturation and capillary pressure. + */ +class InterfacialAreaExponentialCubic +{ +public: + + template + struct Params + { + Params(Scalar a1 = 0, Scalar a2 = 0, Scalar a3 = 0) + : a1_(a1), a2_(a2), a3_(a3) {} + + Scalar a1() const { return a1_; } + void setA1(Scalar a1) { a1_ = a1; } + + Scalar a2() const { return a2_; } + void setA2(Scalar a2) { a2_ = a2; } + + Scalar a3() const { return a3_; } + void setA3(Scalar a3) { a3_ = a3; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(a1(), p.a1(), 1e-6) + && Dune::FloatCmp::eq(a2(), p.a2(), 1e-6) + && Dune::FloatCmp::eq(a3(), p.a3(), 1e-6); + } + + private: + Scalar a1_, a2_, a3_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto a1 = getParamFromGroup(paramGroup, "A1"); + const auto a2 = getParamFromGroup(paramGroup, "A2"); + const auto a3 = getParamFromGroup(paramGroup, "A3"); + return {a1, a2, a3}; + } + + /*! + * \brief The interfacial area + * + * the suggested (as estimated from pore network models) interfacial area between the nonwetting and solid phase: + * \f$\mathrm{ + a_{ns} = a_1 e^{a_2 * S_w } + a_3 * p_c^3 ; + }\f$ + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar area(const Scalar swe, const Scalar pc, const Params& params) + { + // TODO think about awn surface for relative saturation + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + + using std::exp; + return a1 * exp( a2 * swe) + a3 * pc * pc * pc ; + } +}; + +} // namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/interfacialarea.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/interfacialarea.hh new file mode 100644 index 0000000000000000000000000000000000000000..afd05170b72dd288eb1642e0e931c6d1528b123e --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/interfacialarea.hh @@ -0,0 +1,201 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Implementation helper for capillary-pressure-saturation-interfacial-area relations + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_HH + +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper class to implement regularized laws (pc-sw-a) + * with a conversion policy between absolution and effective saturations + * \tparam ScalarType the scalar type + * \tparam BaseLaw the base law (e.g. VanGenuchten, BrooksCorey, Linear, ...) + * \tparam Regularization the regularization type (set to NoAwnRegularization to turn it off) + * \tparam EffToAbsPolicy the policy how to convert effective <-> absolute saturations + * + * \note The regularization interface is expected to return Dumux::OptionalScalars which + * are wrappers around a Scalar type that provide a boolean operator to + * check whether the result is valid. If the regularization returns + * a non-valid value, it means that the given parameter + * range is outside the regularized region. + * For that case we forward to the call to the standard law. + */ +template class InterfaceType, + class Regularization = NoRegularization, + class EffToAbsPolicy = TwoPEffToAbsDefaultPolicy> +class InterfacialArea : public Adapter, InterfaceType> +{ +public: + + using Scalar = ScalarType; + + using BasicParams = typename BaseLaw::template Params; + using EffToAbsParams = typename EffToAbsPolicy::template Params; + using RegularizationParams = typename Regularization::template Params; + + using EffToAbs = EffToAbsPolicy; + + /*! + * \brief Return whether this law is regularized + */ + static constexpr bool isRegularized() + { return !std::is_same::value; } + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + InterfacialArea() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit InterfacialArea(const std::string& paramGroup) + : basicParams_(makeBasicParams(paramGroup)) + , effToAbsParams_(makeEffToAbsParams(paramGroup)) + { + if constexpr (isRegularized()) + regularization_.init(this, paramGroup); + } + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + InterfacialArea(const BasicParams& baseParams, + const EffToAbsParams& effToAbsParams = {}, + const RegularizationParams& regParams = {}) + : basicParams_(baseParams) + , effToAbsParams_(effToAbsParams) + { + if constexpr (isRegularized()) + regularization_.init(this, baseParams, effToAbsParams, regParams); + } + + /*! + * \brief The capillary pressure-saturation curve + */ + template + Scalar area(const Scalar sw, const Scalar pc) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.area(swe, pc); + if (regularized) + return regularized.value(); + } + + return BaseLaw::area(swe, pc, basicParams_); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + template + Scalar darea_dpc(const Scalar sw, const Scalar pc) const + { + if constexpr (enableRegularization) + { + const auto regularized = regularization_.darea_dpc(sw, pc); + if (regularized) + return regularized.value(); + } + + return BaseLaw::darea_dpc(sw, pc, basicParams_); + } + + /*! + * \brief The partial derivative of the saturation to the capillary pressure + */ + template + Scalar darea_dsw(const Scalar sw, const Scalar pc) const + { + if constexpr (enableRegularization) + { + const auto regularized = regularization_.darea_dsw(sw, pc); + if (regularized) + return regularized.value(); + } + + return BaseLaw::darea_dsw(sw, pc, basicParams_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const InterfacialArea& o) const + { + return basicParams_ == o.basicParams_ + && effToAbsParams_ == o.effToAbsParams_ + && regularization_ == o.regularization_; + } + + /*! + * \brief Create the base law's parameters using + * input file parameters + */ + static BasicParams makeBasicParams(const std::string& paramGroup) + { + return BaseLaw::template makeParams(paramGroup); + } + + /*! + * \brief Return the base law's parameters + */ + const BasicParams& basicParams() const + { return basicParams_; } + + /*! + * \brief Create the parameters of the EffToAbs policy using + * input file parameters + */ + static EffToAbsParams makeEffToAbsParams(const std::string& paramGroup) + { + return EffToAbs::template makeParams(paramGroup); + } + + /*! + * \brief Return the parameters of the EffToAbs policy + */ + const EffToAbsParams& effToAbsParams() const + { return effToAbsParams_; } + +private: + BasicParams basicParams_; + EffToAbsParams effToAbsParams_; + Regularization regularization_; +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/pcmax.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/pcmax.hh new file mode 100644 index 0000000000000000000000000000000000000000..e77234ecc6b90d6a9d393395eece4a88588efc53 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/pcmax.hh @@ -0,0 +1,113 @@ +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Specification of a function relating volume specific interfacial area to capillary pressure and saturation. + * This parametrization uses a maximum value of capillary pressure. + * + * \note It is used for calculating the interfacial area between the nonwetting and wetting phase + * by Nuske 2014 (https://elib.uni-stuttgart.de/handle/11682/614, page 60) \cite nuske2014. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_PC_MAX +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_PC_MAX + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the polynomial of second order relating + * specific interfacial area to wetting phase saturation and capillary pressure. + */ +class InterfacialAreaPcMax +{ +public: + + template + struct Params + { + Params(Scalar pcMax = 0, Scalar a1 = 0, Scalar a2 = 0, Scalar a3 = 0) + : pcMax_(pcMax), a1_(a1), a2_(a2), a3_(a3) {} + + Scalar pcMax() const { return pcMax_; } + void setPcMax(Scalar pcMax) { pcMax_ = pcMax; } + + Scalar a1() const { return a1_; } + void setA1(Scalar a1) { a1_ = a1; } + + Scalar a2() const { return a2_; } + void setA2(Scalar a2) { a2_ = a2; } + + Scalar a3() const { return a3_; } + void setA3(Scalar a3) { a3_ = a3; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(pcMax(), p.pcMax(), 1e-6) + && Dune::FloatCmp::eq(a1(), p.a1(), 1e-6) + && Dune::FloatCmp::eq(a2(), p.a2(), 1e-6) + && Dune::FloatCmp::eq(a3(), p.a3(), 1e-6); + } + + private: + Scalar pcMax_, a1_, a2_, a3_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto pcMax = getParamFromGroup(paramGroup, "PcMax"); + const auto a1 = getParamFromGroup(paramGroup, "A1"); + const auto a2 = getParamFromGroup(paramGroup, "A2"); + const auto a3 = getParamFromGroup(paramGroup, "A3"); + return {pcMax, a1, a2, a3}; + } + + /*! + * \brief The interfacial area + * + * the suggested (as estimated from pore network models) interfacial area between the nonwetting and wetting phase: + * \f$\mathrm{ + a_{wn} = a_{1} (p_{c { \sf max} } - p_{c}) (1-S_{w}) + a_{2} (p_{c {\sf max} } -p_{c})^2 (1-S_{w}) + a_{3} (p_{c {\sf max} }- p_{c}) (1-S_{w})^2 + }\f$ + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar area(const Scalar swe, const Scalar pc, const Params& params) + { + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + const Scalar pcMax = params.pcMax(); + return a1 * (pcMax-pc) * (1.0-swe) + a2*(pcMax-pc)*(pcMax-pc) * (1.-swe) + a3 * (pcMax-pc)*(1-swe)*(1-swe); + } +}; + +} // namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomial2ndorder.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomial2ndorder.hh new file mode 100644 index 0000000000000000000000000000000000000000..05f4243a694ff556e276775194e9cb8cdbf5fda5 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomial2ndorder.hh @@ -0,0 +1,149 @@ +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Specification of a function relating volume specific interfacial area to capillary pressure and saturation. + * This parametrization is a second order polynomial. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_POLYNOMIAL_SECOND_ORDER_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_POLYNOMIAL_SECOND_ORDER_HH + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the polynomial of second order relating + * specific interfacial area to wetting phase saturation and capillary pressure as suggested by Joekar-Niasar(2008) \cite joekar2008 . + */ +class InterfacialAreaPolynomialSecondOrder +{ +public: + + template + struct Params + { + Params(Scalar a00 = 0, Scalar a01 = 0, Scalar a02 = 0, Scalar a10 = 0, Scalar a11 = 0, Scalar a20 = 0) + : a00_(a00), a01_(a01), a02_(a02), a10_(a10), a11_(a11), a20_(a20) {} + + Scalar a00() const { return a00_; } + void setA00(Scalar a00) { a00_ = a00; } + + Scalar a01() const { return a01_; } + void setA01(Scalar a01) { a01_ = a01; } + + Scalar a02() const { return a02_; } + void setA02(Scalar a02) { a02_ = a02; } + + Scalar a10() const { return a10_; } + void setA10(Scalar a10) { a10_ = a10; } + + Scalar a11() const { return a11_; } + void setA11(Scalar a11) { a11_ = a11; } + + Scalar a20() const { return a20_; } + void setA20(Scalar a20) { a20_ = a20; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(a00(), p.a00(), 1e-6) + && Dune::FloatCmp::eq(a01(), p.a01(), 1e-6) + && Dune::FloatCmp::eq(a02(), p.a02(), 1e-6) + && Dune::FloatCmp::eq(a10(), p.a10(), 1e-6) + && Dune::FloatCmp::eq(a11(), p.a11(), 1e-6) + && Dune::FloatCmp::eq(a20(), p.a20(), 1e-6); + } + + private: + Scalar a00_, a01_, a02_, a10_, a11_, a20_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto a00 = getParamFromGroup(paramGroup, "A00", 0.0); + const auto a01 = getParamFromGroup(paramGroup, "A01"); + const auto a02 = getParamFromGroup(paramGroup, "A02"); + const auto a10 = getParamFromGroup(paramGroup, "A10"); + const auto a11 = getParamFromGroup(paramGroup, "A11"); + const auto a20 = getParamFromGroup(paramGroup, "A20"); + return {a00, a01, a02, a10, a11, a20}; + } + + /*! + * \brief The interfacial area + * + * the suggested (as estimated from pore network models) awn surface: + * \f$[ + a_{wn} = a_{00} + a_{10}S_{w} + a_{20}S_{w}^2 + a_{11} S_{w} p_{c} + a_{01} p_{c} + a_{02}p_{c}^2 + \f$] + * \param params parameter container for the coefficients of the surface + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + */ + template + static Scalar area(const Scalar swe, const Scalar pc, const Params& params) + { + const Scalar a00 = params.a00(); + const Scalar a10 = params.a10(); + const Scalar a20 = params.a20(); + const Scalar a11 = params.a11(); + const Scalar a01 = params.a01(); + const Scalar a02 = params.a02(); + + return a00 + a10 * swe + a20 * swe*swe + a11*swe*pc + a01*pc + a02*pc*pc; + } + + /*! + * \brief the derivative of specific interfacial area function w.r.t. capillary pressure + * + * \param params parameter container for the coefficients of the surface + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + */ + template + static Scalar darea_dpc(const Scalar swe, const Scalar pc, const Params& params) + { + return params.a11()*swe + params.a01() + 2.0*params.a02() * pc; + } + + /*! + * \brief the derivative of specific interfacial area function w.r.t. saturation + * + * \param params parameter container for the coefficients of the surface + * \param swe Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + */ + template + static Scalar darea_dsw(const Scalar swe, const Scalar pc, const Params& params) + { + return params.a11()*pc + params.a10() + 2.0*params.a20()*swe; + } +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomialedgezero2ndorder.hh b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomialedgezero2ndorder.hh new file mode 100644 index 0000000000000000000000000000000000000000..4c07969b9002d3f738237919ab2105ad45e870da --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/interfacialarea/polynomialedgezero2ndorder.hh @@ -0,0 +1,145 @@ +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Specification of a function relating volume specific interfacial area to capillary pressure and saturation. + * This parametrization is a second order polynomial which is zero for saturations of zero and one. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL_CUBIC +#define DUMUX_MATERIAL_FLUIDMATRIX_TWO_P_INTERFACIAL_AREA_EXPONENTIAL_CUBIC + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the polynomial of second order relating + * specific interfacial area to wetting phase saturation and capillary pressure. + */ +class InterfacialAreaolynomialEdgeZero2ndOrder +{ +public: + + template + struct Params + { + Params(Scalar swr = 0, Scalar a1 = 0, Scalar a2 = 0, Scalar a3 = 0) + : swr_(swr), a1_(a1), a2_(a2), a3_(a3) {} + + Scalar swr() const { return swr_; } + void setSwr(Scalar swr) { swr_ = swr; } + + Scalar a1() const { return a1_; } + void setA1(Scalar a1) { a1_ = a1; } + + Scalar a2() const { return a2_; } + void setA2(Scalar a2) { a2_ = a2; } + + Scalar a3() const { return a3_; } + void setA3(Scalar a3) { a3_ = a3; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(swr(), p.swr(), 1e-6) + && Dune::FloatCmp::eq(a1(), p.a1(), 1e-6) + && Dune::FloatCmp::eq(a2(), p.a2(), 1e-6) + && Dune::FloatCmp::eq(a3(), p.a3(), 1e-6); + } + + private: + Scalar swr_, a1_, a2_, a3_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto swr = getParamFromGroup(paramGroup, "Swr", 0.0); + const auto a1 = getParamFromGroup(paramGroup, "A1"); + const auto a2 = getParamFromGroup(paramGroup, "A2"); + const auto a3 = getParamFromGroup(paramGroup, "A3"); + return {swr, a1, a2, a3}; + } + + /*! + * \brief The interfacial area + * the suggested (as estimated from pore network models) awn surface: + * \f$[ + a_{wn} = a_{1} (S_{wr}-S_{w})(1.-S_{w}) + a_2 (S_{wr}-S_{w})(1.-S_{w}) p_{c} + a_{3} (S_{wr}-S_{w})(1.-S_{w}) p_{c}^2 + \f$] + * \param sw Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar area(const Scalar sw, const Scalar pc, const Params& params) + { + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + const Scalar swr = params.swr(); + const Scalar factor = (swr-sw)*(1.0-sw) ; + return a1*factor + a2*factor*pc + a3*factor*pc*pc; + } + + /*! + * \brief the derivative of specific interfacial area function w.r.t. capillary pressure + * + * \param sw Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar darea_dpc(const Scalar sw, const Scalar pc, const Params& params) + { + const Scalar swr = params.swr(); + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + return a2*(swr-sw)*(1-sw) + a3*(swr-sw)*(1-sw)*pc; + } + + /*! + * \brief the derivative of specific interfacial area function w.r.t. saturation + * + * \param sw Effective saturation of the wetting phase + * \param pc Capillary pressure in \f$\mathrm{[Pa]}\f$ + * \param params parameter container for the coefficients of the surface + */ + template + static Scalar darea_dsw(const Scalar sw, const Scalar pc, const Params& params) + { + const Scalar swr = params.swr(); + const Scalar a1 = params.a1(); + const Scalar a2 = params.a2(); + const Scalar a3 = params.a3(); + const Scalar derivativeFactor = (sw-1.0)+(sw-swr); + return a1 * derivativeFactor + a2 * derivativeFactor * pc + a3 * derivativeFactor * pc*pc ; + } +}; + +} // namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh b/dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh index b35f3dac9bfad49e45a404b68b959e6f999ac6c5..09ce3ac3fc7f6cb500a93a7726551b73e276c4a0 100644 --- a/dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh +++ b/dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh @@ -22,9 +22,10 @@ * \brief Linear capillary pressure and * relative permeability <-> saturation relations */ -#ifndef LINEAR_MATERIAL_HH -#define LINEAR_MATERIAL_HH +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_LINEAR_MATERIAL_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_LINEAR_MATERIAL_HH +// remove from here after release 3.3 ///////////// #include "linearmaterialparams.hh" #include @@ -44,7 +45,7 @@ namespace Dumux { * \see LinearMaterialParams */ template > -class LinearMaterial +class [[deprecated("Use new material laws and FluidMatrix::LinearMaterial instead!")]] LinearMaterial { public: using Params = ParamsT; @@ -164,5 +165,152 @@ public: } }; } // end namespace Dumux +// remove until here after release 3.3 ///////////// + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * + * \brief Linear capillary pressure and + * relative permeability <-> saturation relations + * + * The entry pressure is reached at \f$\mathrm{ \overline{S}_w = 1}\f$, the maximum + * capillary pressure is observed at \f$\mathrm{ \overline{S}_w = 0}\f$. + * + */ +class LinearMaterial +{ +public: + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + */ + template + struct Params + { + Params(Scalar pcEntry, Scalar pcMax) + : pcEntry_(pcEntry), pcMax_(pcMax) + {} + + Scalar pcEntry() const { return pcEntry_; } + void setPcEntry(Scalar pcEntry) { pcEntry_ = pcEntry; } + + Scalar pcMax() const { return pcMax_; } + void setPcMax(Scalar pcMax) { pcMax_ = pcMax; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(pcEntry(), p.pcEntry(), 1e-6) + && Dune::FloatCmp::eq(pcMax(), p.pcMax(), 1e-6); + } + + private: + Scalar pcEntry_, pcMax_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto pcEntry = getParamFromGroup(paramGroup, "LinearPcEntry"); + const auto pcMax = getParamFromGroup(paramGroup, "LinearPcMax"); + return {pcEntry, pcMax}; + } + + /*! + * \brief The capillary pressure-saturation curve + */ + template + static Scalar pc(Scalar swe, const Params& params) + { + return (1.0 - swe)*(params.pcMax() - params.pcEntry()) + params.pcEntry(); + } + + /*! + * \brief The inverse saturation-capillary pressure curve + */ + template + static Scalar swe(Scalar pc, const Params& params) + { + return 1.0 - (pc - params.pcEntry())/(params.pcMax() - params.pcEntry()); + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + */ + template + static Scalar endPointPc(const Params& params) + { return params.pcEntry(); } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the effective saturation + */ + template + static Scalar dpc_dswe(Scalar swe, const Params& params) + { + return params.pcEntry() - params.pcMax(); + } + + /*! + * \brief The partial derivative of the effective saturation w.r.t. the capillary pressure + */ + template + static Scalar dswe_dpc(Scalar pc, const Params& params) + { + return 1.0/(params.pcEntry() - params.pcMax()); + } + + /*! + * \brief The relative permeability for the wetting phase + */ + template + static Scalar krw(Scalar swe, const Params& params) + { + using std::clamp; + return clamp(swe, 0.0, 1.0); + } + + /*! + * \brief The derivative of the relative permeability + */ + template + static Scalar dkrw_dswe(Scalar swe, const Params& params) + { + return 1.0; + } + + /*! + * \brief The relative permeability for the non-wetting phase + */ + template + static Scalar krn(Scalar swe, const Params& params) + { + using std::clamp; + return clamp(1.0-swe, 0.0, 1.0); + } + + /*! + * \brief The derivative of the relative permeability + */ + template + static Scalar dkrn_dswe(Scalar swe, const Params& params) + { + return -1.0; + } +}; + +template +using LinearMaterialDefault = TwoPMaterialLaw; + +} // end namespace Dumux::FluidMatrix #endif diff --git a/dumux/material/fluidmatrixinteractions/2p/linearmaterialparams.hh b/dumux/material/fluidmatrixinteractions/2p/linearmaterialparams.hh index aa6df583d81e9ba4023b9534b8d59e442ccd05e7..6e8609abbdf085da24d219f5f181d19eef9357ba 100644 --- a/dumux/material/fluidmatrixinteractions/2p/linearmaterialparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/linearmaterialparams.hh @@ -25,6 +25,8 @@ #ifndef LINEAR_MATERIAL_PARAMS_HH #define LINEAR_MATERIAL_PARAMS_HH +// TODO Deprecated. Remove after 3.3 + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2p/materiallaw.hh b/dumux/material/fluidmatrixinteractions/2p/materiallaw.hh new file mode 100644 index 0000000000000000000000000000000000000000..f08fbbf2b4fb00906c99da62a52df22b610fffec --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/materiallaw.hh @@ -0,0 +1,302 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Implementation helper for capillary pressure and + * relative permeability <-> saturation relations for two-phase models + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_MATERIAL_LAW_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_MATERIAL_LAW_HH + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper class to implement regularized material laws (pc-sw, kr-sw) + * with a conversion policy between absolution and effective saturations + * \note See vangenuchten.hh / brookscorey.hh for default configurations using this class + * \tparam ScalarType the scalar type + * \tparam BaseLaw the base law (e.g. VanGenuchten, BrooksCorey, Linear, ...) + * \tparam Regularization the regularization type (set to NoRegularization to turn it off) + * \tparam EffToAbsPolicy the policy how to convert effective <-> absolute saturations + * + * \note The regularization interface is expected to return Dumux::OptionalScalars which + * are wrappers around a Scalar type that provide a boolean operator to + * check whether the result is valid. If the regularization returns + * a non-valid value, it means that the given parameter + * range is outside the regularized region. + * For that case we forward to the call to the standard law. + */ +template +class TwoPMaterialLaw : public Adapter, PcKrSw> +{ +public: + + using Scalar = ScalarType; + + using BasicParams = typename BaseLaw::template Params; + using EffToAbsParams = typename EffToAbsPolicy::template Params; + using RegularizationParams = typename Regularization::template Params; + + using EffToAbs = EffToAbsPolicy; + + /*! + * \brief Return the number of fluid phases + */ + static constexpr int numFluidPhases() + { return 2; } + + /*! + * \brief Return whether this law is regularized + */ + static constexpr bool isRegularized() + { return !std::is_same::value; } + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + TwoPMaterialLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit TwoPMaterialLaw(const std::string& paramGroup) + : basicParams_(makeBasicParams(paramGroup)) + , effToAbsParams_(makeEffToAbsParams(paramGroup)) + { + if constexpr (isRegularized()) + regularization_.init(this, paramGroup); + } + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + TwoPMaterialLaw(const BasicParams& baseParams, + const EffToAbsParams& effToAbsParams = {}, + const RegularizationParams& regParams = {}) + : basicParams_(baseParams) + , effToAbsParams_(effToAbsParams) + { + if constexpr (isRegularized()) + regularization_.init(this, baseParams, effToAbsParams, regParams); + } + + /*! + * \brief The capillary pressure-saturation curve + */ + template + Scalar pc(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.pc(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::pc(swe, basicParams_); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + template + Scalar dpc_dsw(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dpc_dswe(swe); + if (regularized) + return regularized.value()*EffToAbs::dswe_dsw(effToAbsParams_); + } + + return BaseLaw::dpc_dswe(swe, basicParams_)*EffToAbs::dswe_dsw(effToAbsParams_); + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + */ + Scalar endPointPc() const + { + return BaseLaw::endPointPc(basicParams_); + } + + /*! + * \brief The saturation-capillary pressure curve + */ + template + Scalar sw(const Scalar pc) const + { + if constexpr (enableRegularization) + { + const auto regularized = regularization_.swe(pc); + if (regularized) + return EffToAbs::sweToSw(regularized.value(), effToAbsParams_); + } + + return EffToAbs::sweToSw(BaseLaw::swe(pc, basicParams_), effToAbsParams_); + } + + /*! + * \brief The partial derivative of the saturation to the capillary pressure + */ + template + Scalar dsw_dpc(const Scalar pc) const + { + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dswe_dpc(pc); + if (regularized) + return regularized.value()*EffToAbs::dsw_dswe(effToAbsParams_); + } + + return BaseLaw::dswe_dpc(pc, basicParams_)*EffToAbs::dsw_dswe(effToAbsParams_); + } + + /*! + * \brief The relative permeability for the wetting phase + */ + template + Scalar krw(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.krw(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::krw(swe, basicParams_); + } + + /*! + * \brief The derivative of the relative permeability for the wetting phase w.r.t. saturation + */ + template + Scalar dkrw_dsw(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dkrw_dswe(swe); + if (regularized) + return regularized.value()*EffToAbs::dswe_dsw(effToAbsParams_); + } + + return BaseLaw::dkrw_dswe(swe, basicParams_)*EffToAbs::dswe_dsw(effToAbsParams_); + } + + /*! + * \brief The relative permeability for the non-wetting phase + */ + template + Scalar krn(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.krn(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::krn(swe, basicParams_); + } + + /*! + * \brief The derivative of the relative permeability for the non-wetting phase w.r.t. saturation + */ + template + Scalar dkrn_dsw(const Scalar sw) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dkrn_dswe(swe); + if (regularized) + return regularized.value()*EffToAbs::dswe_dsw(effToAbsParams_); + } + + return BaseLaw::dkrn_dswe(swe, basicParams_)*EffToAbs::dswe_dsw(effToAbsParams_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const TwoPMaterialLaw& o) const + { + return basicParams_ == o.basicParams_ + && effToAbsParams_ == o.effToAbsParams_ + && regularization_ == o.regularization_; + } + + /*! + * \brief Create the base law's parameters using + * input file parameters + */ + static BasicParams makeBasicParams(const std::string& paramGroup) + { + return BaseLaw::template makeParams(paramGroup); + } + + /*! + * \brief Return the base law's parameters + */ + const BasicParams& basicParams() const + { return basicParams_; } + + /*! + * \brief Create the parameters of the EffToAbs policy using + * input file parameters + */ + static EffToAbsParams makeEffToAbsParams(const std::string& paramGroup) + { + return EffToAbs::template makeParams(paramGroup); + } + + /*! + * \brief Return the parameters of the EffToAbs policy + */ + const EffToAbsParams& effToAbsParams() const + { return effToAbsParams_; } + +private: + BasicParams basicParams_; + EffToAbsParams effToAbsParams_; + Regularization regularization_; +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/noregularization.hh b/dumux/material/fluidmatrixinteractions/2p/noregularization.hh new file mode 100644 index 0000000000000000000000000000000000000000..24036477d1852a2a30b6293467fbd7eb289aeb93 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/noregularization.hh @@ -0,0 +1,45 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief A tag to turn off regularization and it's overhead + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_NO_REGULARIZATION_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_NO_REGULARIZATION_HH + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A tag to turn off regularization and it's overhead + */ +struct NoRegularization +{ + //! Empty parameter structure + template struct Params {}; + + //! We are always equal to other instances of our kind + bool operator== (const NoRegularization& o) const + { return true; } +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh index 4857f91b0583354b06a0584e894b01b2a28c4b88..e891f04c0afbd4ae2b47ed411fae6138eb61efe9 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh @@ -25,6 +25,8 @@ #ifndef REGULARIZED_BROOKS_COREY_HH #define REGULARIZED_BROOKS_COREY_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include "brookscorey.hh" #include "regularizedbrookscoreyparams.hh" diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscoreyparams.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscoreyparams.hh index 3ea49468a04fcb0027a298edb067f9e68c279620..7e769ae2157090f530e0476108b33c689e52cbd6 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscoreyparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedbrookscoreyparams.hh @@ -25,6 +25,8 @@ #ifndef DUMUX_REGULARIZED_BROOKS_COREY_PARAMS_HH #define DUMUX_REGULARIZED_BROOKS_COREY_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include "brookscoreyparams.hh" @@ -37,7 +39,7 @@ namespace Dumux { * the Brooks-Corey capillary pressure model. */ template -class RegularizedBrooksCoreyParams : public BrooksCoreyParams +class [[deprecated("Use new material laws! Removal after 3.3")]] RegularizedBrooksCoreyParams : public BrooksCoreyParams { using BrooksCoreyParams = Dumux::BrooksCoreyParams; diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh index 02f81c4a0737037ad4b97ab0f73bb5dfe1804c0c..1a96667ca55c20d6ebafce0de6476ac25e670d73 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh @@ -25,6 +25,8 @@ #ifndef DUMUX_REGULARIZED_LINEAR_MATERIAL_HH #define DUMUX_REGULARIZED_LINEAR_MATERIAL_HH +#warning "This header is deprecated. Removal after 3.3" + #include "linearmaterial.hh" #include "regularizedlinearmaterialparams.hh" diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterialparams.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterialparams.hh index 71970148c953dedbc3e34c8f7ab9d0207d94cb51..cc1885fc94a569768d4a4bac8d3fe042016e27e3 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterialparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterialparams.hh @@ -25,6 +25,8 @@ #ifndef REGULARIZED_LINEAR_PARAMS_HH #define REGULARIZED_LINEAR_PARAMS_HH +#warning "This header is deprecated. Use SmoothedLinearLaw instead. Removal after 3.3" + #include "linearmaterialparams.hh" namespace Dumux { @@ -35,7 +37,7 @@ namespace Dumux { * the linear constitutive relations. */ template -class RegularizedLinearMaterialParams : public LinearMaterialParams +class [[deprecated("Use new material laws! Removal after 3.3")]] RegularizedLinearMaterialParams : public LinearMaterialParams { public: using Scalar = ScalarT; diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh index 1973cf212caca473292c7b5599b0255cd31387eb..897a40b5737bd8eb0b1550c86f04460dcc6f4b02 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh @@ -25,6 +25,8 @@ #ifndef REGULARIZED_VAN_GENUCHTEN_HH #define REGULARIZED_VAN_GENUCHTEN_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include "vangenuchten.hh" #include "regularizedvangenuchtenparams.hh" diff --git a/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchtenparams.hh b/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchtenparams.hh index 452d15825711a3b9e74e119c615b2bc539ec3cf5..03e7657d326912814e8a33dc36c0fe7eccda3fab 100644 --- a/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchtenparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchtenparams.hh @@ -25,6 +25,8 @@ #ifndef REGULARIZED_VAN_GENUCHTEN_PARAMS_HH #define REGULARIZED_VAN_GENUCHTEN_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include "vangenuchtenparams.hh" @@ -37,7 +39,7 @@ namespace Dumux { * VanGenuchten "material law". */ template -class RegularizedVanGenuchtenParams : public VanGenuchtenParams +class [[deprecated("Use new material laws! Removal after 3.3")]] RegularizedVanGenuchtenParams : public VanGenuchtenParams { public: using Scalar = ScalarT; diff --git a/dumux/material/fluidmatrixinteractions/2p/smoothedlinearlaw.hh b/dumux/material/fluidmatrixinteractions/2p/smoothedlinearlaw.hh new file mode 100644 index 0000000000000000000000000000000000000000..7cf2badd391a75cfb4b084ea906884d23531224b --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/smoothedlinearlaw.hh @@ -0,0 +1,245 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the capillary pressure / relPerm <-> saturation relation + * using a linear relation smoothed at the upper and lower bounds for kr. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_SMOOTHED_LINEAR_LAW_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_SMOOTHED_LINEAR_LAW_HH + + +#include +#include + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implements a linear saturation-capillary pressure relation + * + * The entry pressure is reached at \f$\mathrm{\overline{S}_w = 1}\f$, the maximum + * capillary pressure is observed at \f$\mathrm{\overline{S}_w = 0}\f$. + * + * The relative permeabilities are 0 or 1 outside of the range of effective saturation. + * However, the transition between the linearly changing and the constant part is not smooth but with a kink. + * The Newton scheme does not like that. Therefore a smooth transition is accomplished by interpolating these + * regions with a spline. + * + * An example of the regularization of the relative permeability is shown below: + * \image html regularizedLinearKr.png + */ +template +class SmoothedLinearLaw : public Adapter, PcKrSw> +{ + +public: + using Scalar = ScalarType; + using EffToAbsParams = typename EffToAbsPolicy::template Params; + using EffToAbs = EffToAbsPolicy; + + /*! + * \brief Return whether this law is regularized + */ + static constexpr bool isRegularized() + { return false; } + + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + */ + struct Params + { + Params(Scalar pe, Scalar pcMax, Scalar krLowS, Scalar krHighS) + : pe_(pe), pcMax_(pcMax), krLowS_(krLowS), krHighS_(krHighS) + {} + + Scalar pe() const { return pe_; } + void setPe(Scalar pe) { pe_ = pe; } + + Scalar pcMax() const { return pcMax_; } + void setPcMax(Scalar pcMax) { pcMax_ = pcMax; } + + Scalar krLowS() const { return krLowS_; } + void setKrLowS(Scalar krLowS) { krLowS_ = krLowS; } + + Scalar krHighS() const { return krHighS_; } + void setKrHighS(Scalar krHighS) { krHighS_ = krHighS; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(pe(), p.pe(), 1e-6) + && Dune::FloatCmp::eq(pcMax(), p.pcMax(), 1e-6) + && Dune::FloatCmp::eq(krLowS(), p.krLowS(), 1e-6) + && Dune::FloatCmp::eq(krHighS(), p.krHighS(), 1e-6); + } + + private: + Scalar pe_, pcMax_, krLowS_, krHighS_; + }; + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + SmoothedLinearLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit SmoothedLinearLaw(const std::string& paramGroup) + : SmoothedLinearLaw(makeParams(paramGroup), EffToAbs::template makeParams(paramGroup)) + {} + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + SmoothedLinearLaw(const Params& params, + const EffToAbsParams& effToAbsParams = {}) + : params_(params) + , effToAbsParams_(effToAbsParams) + , splineM_((1.0 - ((1.0 - params_.krHighS()) + params_.krLowS())/2.0 ) + / (1.0 - (1.0 - params_.krHighS()) - params_.krLowS())) + , splineLowS_(0.0, params_.krLowS(), // x1, x2 + 0.0, params_.krLowS()/2.0, // y1, y2 + 0.0, splineM_) // m1, m2 + , splineHighS_(params_.krHighS(), 1.0, // x1, x2 + 1.0 - (1.0 - params_.krHighS())/2.0, 1.0, // y1, y2 + splineM_, 0.0) // m1, m2 + {} + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + static Params makeParams(const std::string& paramGroup) + { + const auto pe = getParamFromGroup(paramGroup, "SmoothedLinearLawPe"); + const auto pcMax = getParamFromGroup(paramGroup, "SmoothedLinearLawPcMax"); + const auto krLowS = getParamFromGroup(paramGroup, "SmoothedLinearLawKrLowS"); + const auto krHighS = getParamFromGroup(paramGroup, "SmoothedLinearLawKrHighS"); + return {pe, pcMax, krLowS, krHighS}; + } + + /*! + * \brief The capillary pressure-saturation curve + */ + Scalar pc(Scalar swe) const + { + return (1.0 - swe)*(params_.pcMax() - params_.pe()) + params_.pe(); + } + + /*! + * \brief The inverse saturation-capillary pressure curve + */ + Scalar swe(Scalar pc) const + { + return 1.0 - (pc - params_.pe())/(params_.pcMax() - params_.pe()); + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + */ + Scalar endPointPc() const + { return params_.pe(); } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the effective saturation + */ + Scalar dpc_dswe(Scalar swe) const + { + return params_.pe() - params_.pcMax(); + } + + /*! + * \brief The partial derivative of the effective saturation w.r.t. the capillary pressure + */ + Scalar dswe_dpc(Scalar pc) const + { + return 1.0/(params_.pe() - params_.pcMax()); + } + + /*! + * \brief The relative permeability for the wetting phase. + */ + Scalar krw(Scalar swe) const + { + return relperm_(swe); + } + + /*! + * \brief The relative permeability for the non-wetting phase. + */ + Scalar krn(Scalar swe) const + { + Scalar sne = 1.0 - swe; + return relperm_(sne); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const SmoothedLinearLaw& o) const + { + return params_ == o.params_ + && effToAbsParams_ == o.effToAbsParams_; + } + + const EffToAbsParams& effToAbsParams() const + { return effToAbsParams_; } + +private: + + Scalar relperm_(Scalar S) const + { + const Scalar lowS = params_.krLowS(); + const Scalar highS = params_.krHighS(); + + // check whether the saturation is unpyhsical + if (S >= 1.0) + return 1.0; + else if (S <= 0.0) + return 0; + // check wether the permeability needs to be regularized + else if (S < lowS) + return splineLowS_.eval(S); + else if (S > highS) + return splineHighS_.eval(S); + + // straight line for S \in [lowS, highS] + return lowS/2.0 + splineM_*(S - lowS); + } + + Params params_; + EffToAbsParams effToAbsParams_; + Scalar splineM_; + Dumux::Spline splineLowS_; + Dumux::Spline splineHighS_; +}; +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/splinemateriallaw.hh b/dumux/material/fluidmatrixinteractions/2p/splinemateriallaw.hh new file mode 100644 index 0000000000000000000000000000000000000000..78e196738414afcc09b3189e47803985e26b2532 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/2p/splinemateriallaw.hh @@ -0,0 +1,258 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief A spline approximation wrapper for 2p material laws + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_TWOP_SPLINE_MATERIAL_LAW_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_TWOP_SPLINE_MATERIAL_LAW_HH + +#include // unique_ptr + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A spline approximation wrapper for 2p material laws + * \tparam TwoPMaterialLaw the type of material law to be wrapped + * \tparam approximatePcSwInverse if this is set true, the + * spline approximates sw(pc) and evaluating pc(sw) needs spline inversion. + * if this is false, the spline approximates pc(sw) and evaluating + * sw(pc) needs spline inversion. Spline inversion is rather expensive + * since it has to be done numerically. + */ +template +class SplineTwoPMaterialLaw +: public TwoPMaterialLaw +, public Adapter, PcKrSw> +{ +public: + using Scalar = typename TwoPMaterialLaw::Scalar; + + using BasicParams = typename TwoPMaterialLaw::BasicParams; + using EffToAbsParams = typename TwoPMaterialLaw::BasicParams; + using RegularizationParams = typename TwoPMaterialLaw::RegularizationParams; + + /*! + * \brief Return the number of fluid phases + */ + static constexpr int numFluidPhases() + { return 2; } + + /*! + * \brief We are always regularized in the sense that we replace + * the orginal curve by a cubic spline + */ + static constexpr bool isRegularized() + { return true; } + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + SplineTwoPMaterialLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit SplineTwoPMaterialLaw(const std::string& paramGroup) + : TwoPMaterialLaw(paramGroup) + { + const std::array defaultInterval{{ 0.01, 1.0 }}; + const auto sweInterval = getParamFromGroup>(paramGroup, "SplineSweInterval", defaultInterval); + swInterval_ = {{ TwoPMaterialLaw::EffToAbs::sweToSw(sweInterval[0], this->effToAbsParams()), + TwoPMaterialLaw::EffToAbs::sweToSw(sweInterval[1], this->effToAbsParams()) }}; + swIntervalPc_ = {{ TwoPMaterialLaw::pc(swInterval_[1]), + TwoPMaterialLaw::pc(swInterval_[0]) }}; + numSwSamples_ = getParamFromGroup(paramGroup, "SplineNumSwSamples", 30); + + pcSpline_ = makeSweSpline_( + [this](const auto s){ return TwoPMaterialLaw::pc(s); }, + approximatePcSwInverse + ); + + krwSpline_ = makeSweSpline_( + [this](const auto s){ return TwoPMaterialLaw::krw(s); } + ); + + krnSpline_ = makeSweSpline_( + [this](const auto s){ return TwoPMaterialLaw::krn(s); } + ); + } + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + SplineTwoPMaterialLaw(const std::array& sweInterval, + std::size_t numSwSamples, + TwoPMaterialLaw&& twoP) + : TwoPMaterialLaw(std::move(twoP)) + , numSwSamples_(numSwSamples) + { + swInterval_ = {{ TwoPMaterialLaw::EffToAbs::sweToSw(sweInterval[0], this->effToAbsParams()), + TwoPMaterialLaw::EffToAbs::sweToSw(sweInterval[1], this->effToAbsParams()) }}; + swIntervalPc_ = {{ TwoPMaterialLaw::pc(swInterval_[1]), + TwoPMaterialLaw::pc(swInterval_[0]) }}; + } + + /*! + * \brief The capillary pressure-saturation curve + */ + Scalar pc(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + { + if constexpr (approximatePcSwInverse) + return pcSpline_->evalInverse(sw); + else + return pcSpline_->eval(sw); + } + + return TwoPMaterialLaw::pc(sw); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + Scalar dpc_dsw(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + { + if constexpr (approximatePcSwInverse) + return 1.0/pcSpline_->evalDerivative(pcSpline_->evalInverse(sw)); + else + return pcSpline_->evalDerivative(sw); + } + + return TwoPMaterialLaw::dpc_dsw(sw); + } + + /*! + * \brief The saturation-capillary pressure curve + */ + Scalar sw(const Scalar pc) const + { + if (pc > swIntervalPc_[0] && pc < swIntervalPc_[1]) + { + if constexpr (approximatePcSwInverse) + return pcSpline_->eval(pc); + else + return pcSpline_->evalInverse(pc); + } + + return TwoPMaterialLaw::sw(pc); + } + + /*! + * \brief The partial derivative of the saturation to the capillary pressure + */ + Scalar dsw_dpc(const Scalar pc) const + { + if (pc > swIntervalPc_[0] && pc < swIntervalPc_[1]) + { + if constexpr (approximatePcSwInverse) + return pcSpline_->evalDerivative(pc); + else + return 1.0/pcSpline_->evalDerivative(pcSpline_->evalInverse(pc)); + } + + return TwoPMaterialLaw::dsw_dpc(pc); + } + + /*! + * \brief The relative permeability for the wetting phase + */ + Scalar krw(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + return krwSpline_->eval(sw); + + return TwoPMaterialLaw::krw(sw); + } + + /*! + * \brief The derivative of the relative permeability for the wetting phase w.r.t. saturation + */ + Scalar dkrw_dsw(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + return krwSpline_->evalDerivative(sw); + + return TwoPMaterialLaw::dkrw_dsw(sw); + } + + /*! + * \brief The relative permeability for the non-wetting phase + */ + Scalar krn(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + return krnSpline_->eval(sw); + + return TwoPMaterialLaw::krn(sw); + } + + /*! + * \brief The derivative of the relative permeability for the non-wetting phase w.r.t. saturation + */ + Scalar dkrn_dsw(const Scalar sw) const + { + if (sw > swInterval_[0] && sw < swInterval_[1]) + return krnSpline_->evalDerivative(sw); + + return TwoPMaterialLaw::dkrn_dsw(sw); + } + +private: + template + auto makeSweSpline_(const Function& f, bool invert = false) const + { + const auto sw = linspace(swInterval_[0], swInterval_[1], numSwSamples_); + + auto values = sw; + std::transform(sw.begin(), sw.end(), values.begin(), + [&](auto s){ return f(s); } + ); + + if (invert) + return std::make_unique>(values, sw); + else + return std::make_unique>(sw, values); + } + + std::unique_ptr> pcSpline_; + std::unique_ptr> krwSpline_; + std::unique_ptr> krnSpline_; + + std::array swInterval_; + std::array swIntervalPc_; + std::size_t numSwSamples_; +}; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/2p/vangenuchten.hh b/dumux/material/fluidmatrixinteractions/2p/vangenuchten.hh index 0f124f069948b376aaa03923e16d2066fd0f7906..69aeb71099088c2905810378ac3fa211e63f0288 100644 --- a/dumux/material/fluidmatrixinteractions/2p/vangenuchten.hh +++ b/dumux/material/fluidmatrixinteractions/2p/vangenuchten.hh @@ -22,9 +22,10 @@ * \brief Implementation of the capillary pressure and * relative permeability <-> saturation relations according to van Genuchten. */ -#ifndef DUMUX_VAN_GENUCHTEN_HH -#define DUMUX_VAN_GENUCHTEN_HH +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_VAN_GENUCHTEN_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_VAN_GENUCHTEN_HH +// remove from here after release 3.3 ///////////// #include "vangenuchtenparams.hh" #include @@ -48,7 +49,7 @@ namespace Dumux { * \see VanGenuchtenParams */ template > -class VanGenuchten +class [[deprecated("Use new material laws and FluidMatrix::VanGenuchten instead!")]] VanGenuchten { public: using Params = ParamsT; @@ -280,5 +281,628 @@ public: }; } // end namespace Dumux +// remove until here after release 3.3 ///////////// + +#include +#include + +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of the van Genuchten capillary pressure <-> + * saturation relation, and relative permeability. + * + * \note Capillary pressure model from van Genuchten (1980), + * relative permeability model from Mualem (1976) + */ +class VanGenuchten +{ + +public: + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + * \note The van Genuchten laws are parameterized with four parameters: \f$\mathrm{n, m, \alpha, l}\f$. + * + * - \f$\mathrm{\alpha}\f$ shape parameter \f$\mathrm{[1/Pa]}\f$ + * - \f$\mathrm{m}\f$ shape parameter \f$\mathrm{[-]}\f$ + * - \f$\mathrm{n}\f$ shape parameter \f$\mathrm{[-]}\f$ + * - \f$\mathrm{l}\f$ pore-connectivity parameter \f$\mathrm{[-]}\f$ of Mualem's relative permeability curve + * + * \note In the original Mualem (1976) paper the pore-connectivity parameter is called "n". It's referred to as "l" in + * several later publication of van Genuchten, e.g. van Genuchten (1991), Shaap & van Genuchten (2006). + */ + template + struct Params + { + Params(Scalar alpha, Scalar n, Scalar l = 0.5) + : alpha_(alpha), n_(n), m_(1.0 - 1.0/n), l_(l) + {} + + Scalar alpha() const { return alpha_; } + void setAlpha(Scalar alpha) { alpha_ = alpha; } + + Scalar m() const { return m_; } + void setM(Scalar m) { m_ = m; n_ = 1.0/(1.0 - m); } + + Scalar n() const{ return n_; } + void setN(Scalar n){ n_ = n; m_ = 1.0 - 1.0/n; } + + Scalar l() const { return l_; } + void setL(Scalar l) { l_ = l; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(alpha_, p.alpha_, 1e-6) + && Dune::FloatCmp::eq(n_, p.n_, 1e-6) + && Dune::FloatCmp::eq(m_, p.m_, 1e-6) + && Dune::FloatCmp::eq(l_, p.l_, 1e-6); + } + + private: + Scalar alpha_, n_, m_, l_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto n = getParamFromGroup(paramGroup, "VanGenuchtenN"); + const auto alpha = getParamFromGroup(paramGroup, "VanGenuchtenAlpha"); + // l is usually chosen to be 0.5 (according to Mualem (1976), WRR) + const auto l = getParamFromGroup(paramGroup, "VanGenuchtenL", 0.5); + return Params(alpha, n, l); + } + + /*! + * \brief The capillary pressure-saturation curve according to van Genuchten. + * + * Van Genuchten's empirical capillary pressure <-> saturation + * function is given by + * \f$\mathrm{ + p_c = (\overline{S}_w^{-1/m} - 1)^{1/n}/\alpha + }\f$ + * \param swe Effective saturation of the wetting phase \f$\mathrm{\overline{S}_w}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if swe is not in the valid range, we return a valid number, + * by clamping the input. Note that pc(swe = 0.0) = inf, have a look at RegularizedVanGenuchten if this is a problem. + */ + template + static Scalar pc(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const Scalar pc = pow(pow(swe, -1.0/params.m()) - 1, 1.0/params.n())/params.alpha(); + return pc; + } + + /*! + * \brief The saturation-capillary pressure curve according to van Genuchten. + * + * This is the inverse of the capillary pressure-saturation curve: + * \f$\mathrm{ + \overline{S}_w = {p_c}^{-1} = ((\alpha p_c)^n + 1)^{-m} + }\f$ + * + * \param pc Capillary pressure \f$\mathrm{p_c}\f$ in \f$\mathrm{[Pa]}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \return The effective saturation of the wetting phase \f$\mathrm{\overline{S}_w}\f$ + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * i.e. sw(pc < 0.0) = 0.0, by clamping the input to the physical bounds. + */ + template + static Scalar swe(Scalar pc, const Params& params) + { + using std::pow; + using std::max; + + pc = max(pc, 0.0); // the equation below is undefined for negative pcs + + const Scalar sw = pow(pow(params.alpha()*pc, params.n()) + 1, -params.m()); + return sw; + } + + /*! + * \brief The capillary pressure at Swe = 1.0 also called end point capillary pressure + * \param params A container object that is populated with the appropriate coefficients for the respective law. + */ + template + static Scalar endPointPc(const Params& params) + { return 0.0; } + + /*! + * \brief The partial derivative of the capillary + * pressure w.r.t. the effective saturation according to van Genuchten. + * + * This is equivalent to + * \f$\mathrm{ + \frac{\partial p_c}{\partial \overline{S}_w} = + -\frac{1}{\alpha} (\overline{S}_w^{-1/m} - 1)^{1/n - } + \overline{S}_w^{-1/m} / \overline{S}_w / m + }\f$ + * + * \param swe Effective saturation of the wetting phase \f$\mathrm{\overline{S}_w}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if swe is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dpc_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const Scalar powSwe = pow(swe, -1/params.m()); + return - 1.0/params.alpha() * pow(powSwe - 1, 1.0/params.n() - 1)/params.n() + * powSwe/swe/params.m(); + } + + /*! + * \brief The partial derivative of the effective + * saturation to the capillary pressure according to van Genuchten. + * + * \param pc Capillary pressure \f$\mathrm{p_C}\f$ in \f$\mathrm{[Pa]}\f$ + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dswe_dpc(Scalar pc, const Params& params) + { + using std::pow; + using std::max; + + pc = max(pc, 0.0); // the equation below is undefined for negative pcs + + const Scalar powAlphaPc = pow(params.alpha()*pc, params.n()); + return -pow(powAlphaPc + 1, -params.m()-1)*params.m()*powAlphaPc/pc*params.n(); + } + + /*! + * \brief The relative permeability for the wetting phase of + * the medium implied by van Genuchten / Mualem + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar krw(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const Scalar r = 1.0 - pow(1.0 - pow(swe, 1.0/params.m()), params.m()); + return pow(swe, params.l())*r*r; + } + + /*! + * \brief The derivative of the relative permeability for the + * wetting phase in regard to the wetting saturation of the + * medium implied by the van Genuchten parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dkrw_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const Scalar x = 1.0 - pow(swe, 1.0/params.m()); + const Scalar xToM = pow(x, params.m()); + return (1.0 - xToM)*pow(swe, params.l()-1) * ( (1.0 - xToM)*params.l() + 2*xToM*(1.0-x)/x ); + } + + /*! + * \brief The relative permeability for the non-wetting phase + * of the medium implied by van Genuchten's + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar krn(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + return pow(1 - swe, params.l()) * pow(1 - pow(swe, 1.0/params.m()), 2*params.m()); + } + + /*! + * \brief The derivative of the relative permeability for the + * non-wetting phase in regard to the wetting saturation of + * the medium as implied by the van Genuchten + * parameterization. + * + * \param swe The mobile saturation of the wetting phase. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * \note Instead of undefined behaviour if pc is not in the valid range, we return a valid number, + * by clamping the input. + */ + template + static Scalar dkrn_dswe(Scalar swe, const Params& params) + { + using std::pow; + using std::clamp; + + swe = clamp(swe, 0.0, 1.0); // the equation below is only defined for 0.0 <= sw <= 1.0 + + const auto sne = 1.0 - swe; + const auto x = 1.0 - pow(swe, 1.0/params.m()); + return -pow(sne, params.l()-1.0) * pow(x, 2*params.m() - 1.0) * ( params.l()*x + 2.0*sne/swe*(1.0 - x) ); + } +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A regularization for the VanGenuchten material law + * \note Regularization can be turned of by setting the threshold parameters + * out of range (runtime) or by replacing + * this class by NoRegularization (compile time). + */ +template +class VanGenuchtenRegularization +{ +public: + //! Regularization parameters + template + struct Params + { + /*! + * \brief Set the threshold saturation below which the capillary pressure is regularized. + * + * Most problems are very sensitive to this value (e.g. making it smaller might + * result in very high capillary pressures) + */ + void setPcLowSwe(Scalar pcLowSwe) + { pcLowSwe_ = pcLowSwe; } + + /*! + * \brief Threshold saturation below which the capillary pressure is regularized. + */ + Scalar pcLowSwe() const + { return pcLowSwe_; } + + /*! + * \brief Set the threshold saturation above which the capillary pressure is regularized. + */ + void setPcHighSwe(Scalar pcHighSwe) + { pcHighSwe_ = pcHighSwe; } + + /*! + * \brief Threshold saturation above which the capillary pressure is regularized. + * + * Most problems are very sensitive to this value (e.g. making it smaller might + * result in negative capillary pressures). + */ + Scalar pcHighSwe() const + { return pcHighSwe_; } + + /*! + * \brief Set the threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + void setKrnLowSwe(Scalar krnLowSwe) + { krnLowSwe_ = krnLowSwe; } + + /*! + * \brief Threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + Scalar krnLowSwe() const + { return krnLowSwe_; } + + /*! + * \brief Set the threshold saturation above which the relative + * permeability of the wetting phase gets regularized. + */ + void setKrwHighSwe(Scalar krwHighSwe) + { krwHighSwe_ = krwHighSwe; } + + /*! + * \brief Threshold saturation above which the relative + * permeability of the wetting phase gets regularized. + */ + Scalar krwHighSwe() const + { return krwHighSwe_; } + +private: + S pcLowSwe_ = 0.01; + S pcHighSwe_ = 0.99; + S krnLowSwe_ = 0.1; + S krwHighSwe_ = 0.9; + }; + + //! Initialize the spline + template + void init(const MaterialLaw* m, const std::string& paramGroup) + { + pcLowSwe_ = getParamFromGroup(paramGroup, "VanGenuchtenPcLowSweThreshold", 0.01); + pcHighSwe_ = getParamFromGroup(paramGroup, "VanGenuchtenPcHighSweThreshold", 0.99); + krwHighSwe_ = getParamFromGroup(paramGroup, "VanGenuchtenKrwHighSweThreshold", 0.9); + krnLowSwe_ = getParamFromGroup(paramGroup, "VanGenuchtenKrnLowSweThreshold", 0.1); + + initPcParameters_(m, pcLowSwe_, pcHighSwe_); + initKrParameters_(m, krnLowSwe_, krwHighSwe_); + } + + template + void init(const MaterialLaw* m, const BaseParams& bp, const EffToAbsParams& etap, const Params& p) + { + pcLowSwe_ = p.pcLowSwe(); + pcHighSwe_ = p.pcHighSwe(); + krwHighSwe_ = p.krwHighSwe(); + krnLowSwe_ = p.krnLowSwe(); + + initPcParameters_(m, pcLowSwe_, pcHighSwe_); + initKrParameters_(m, krnLowSwe_, krwHighSwe_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const VanGenuchtenRegularization& o) const + { + return Dune::FloatCmp::eq(pcLowSwe_, o.pcLowSwe_, 1e-6) + && Dune::FloatCmp::eq(pcHighSwe_, o.pcHighSwe_, 1e-6) + && Dune::FloatCmp::eq(krwHighSwe_, o.krwHighSwe_, 1e-6) + && Dune::FloatCmp::eq(krnLowSwe_, o.krnLowSwe_, 1e-6); + } + + /*! + * \brief The regularized capillary pressure-saturation curve + * regularized part: + * - low saturation: extend the \f$\mathrm{p_c(S_w)}\f$ curve with the slope at the regularization point (i.e. no kink). + * - high saturation: connect the high regularization point with \f$\mathrm{\overline{S}_w =1}\f$ + * with a spline and continue linearly for \f$\mathrm{\overline{S}_w > 1}\f$ + */ + OptionalScalar pc(const Scalar swe) const + { + // make sure that the capillary pressure observes a derivative + // != 0 for 'illegal' saturations. This is favourable for the + // newton solver (if the derivative is calculated numerically) + // in order to get the saturation moving to the right + // direction if it temporarily is in an 'illegal' range. + if (swe < pcLowSwe_) + return pcLowSwePcValue_ + pcDerivativeLowSw_*(swe - pcLowSwe_); + + else if (swe > 1.0) + return pcDerivativeHighSweEnd_*(swe - 1.0); + + else if (swe > pcHighSwe_) + return pcSpline_.eval(swe); + + else + return {}; // no regularization + } + + /*! + * \brief The regularized partial derivative of the capillary pressure w.r.t. the saturation + */ + OptionalScalar dpc_dswe(const Scalar swe) const + { + if (swe < pcLowSwe_) + return pcDerivativeLowSw_; + + else if (swe > 1.0) + return pcDerivativeHighSweEnd_; + + else if (swe > pcHighSwe_) + return pcSpline_.evalDerivative(swe); + + else + return {}; // no regularization + } + + /*! + * \brief The regularized saturation-capillary pressure curve + */ + OptionalScalar swe(const Scalar pc) const + { + if (pc <= 0.0) + { + if (pcHighSwe_ > 1.0 - std::numeric_limits::epsilon()) + return 1.0; + else + return pc/pcDerivativeHighSweEnd_ + 1.0; + } + + // invert spline + else if (pc < pcHighSwePcValue_) + return pcSpline_.intersectInterval(pcHighSwe_, 1.0, 0.0, 0.0, 0.0, pc); + + else if (pc >= pcLowSwePcValue_) + return (pc - pcLowSwePcValue_)/pcDerivativeLowSw_ + pcLowSwe_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized partial derivative of the saturation to the capillary pressure + */ + OptionalScalar dswe_dpc(const Scalar pc) const + { + if (pc <= 0.0) + { + if (pcHighSwe_ > 1.0 - std::numeric_limits::epsilon()) + return 0.0; + else + return 1.0/pcDerivativeHighSweEnd_; + } + + // derivative of the inverse of the function is one over derivative of the function + else if (pc < pcHighSwePcValue_) + return 1.0/pcSpline_.evalDerivative(pcSpline_.intersectInterval(pcHighSwe_, 1.0, 0.0, 0.0, 0.0, pc)); + + else if (pc >= pcLowSwePcValue_) + return 1.0/pcDerivativeLowSw_; + + else + return {}; // no regularization + } + + /*! + * \brief The regularized relative permeability for the wetting phase + */ + OptionalScalar krw(const Scalar swe) const + { + if (swe < 0.0) + return 0.0; + else if (swe > 1.0 - std::numeric_limits::epsilon()) + return 1.0; + else if (swe > krwHighSwe_) + return krwSpline_.eval(swe); + else + return {}; // no regularization + } + + /*! + * \brief The regularized derivative of the relative permeability for the wetting phase w.r.t. saturation + */ + OptionalScalar dkrw_dswe(const Scalar swe) const + { + if (swe < 0.0) + return 0.0; + else if (swe > 1.0 - std::numeric_limits::epsilon()) + return 0.0; + else if (swe > krwHighSwe_) + return krwSpline_.evalDerivative(swe); + else + return {}; // no regularization + } + + /*! + * \brief The regularized relative permeability for the non-wetting phase + */ + OptionalScalar krn(const Scalar swe) const + { + if (swe < 0.0) + return 1.0; + else if (swe > 1.0 - std::numeric_limits::epsilon()) + return 0.0; + else if (swe < krnLowSwe_) + return krnSpline_.eval(swe); + else + return {}; // no regularization + } + + /*! + * \brief The regularized derivative of the relative permeability for the non-wetting phase w.r.t. saturation + */ + OptionalScalar dkrn_dswe(const Scalar swe) const + { + if (swe < 0.0) + return 0.0; + else if (swe > 1.0 - std::numeric_limits::epsilon()) + return 0.0; + else if (swe < krnLowSwe_) + return krnSpline_.evalDerivative(swe); + else + return {}; // no regularization + } + +private: + template + void initPcParameters_(const MaterialLaw* m, const Scalar lowSwe, const Scalar highSwe) + { + const auto lowSw = MaterialLaw::EffToAbs::sweToSw(lowSwe, m->effToAbsParams()); + const auto highSw = MaterialLaw::EffToAbs::sweToSw(highSwe, m->effToAbsParams()); + const auto dsw_dswe = MaterialLaw::EffToAbs::dsw_dswe(m->effToAbsParams()); + + pcDerivativeLowSw_ = m->template dpc_dsw(lowSw)*dsw_dswe; + + pcDerivativeHighSweThreshold_ = m->template dpc_dsw(highSw)*dsw_dswe; + pcDerivativeHighSweEnd_ = 2.0*(0.0 - m->template pc(highSw))/(1.0 - highSwe); + + pcLowSwePcValue_ = m->template pc(lowSw); + pcHighSwePcValue_ = m->template pc(highSw); + + pcSpline_ = Spline(highSwe, 1.0, // x0, x1 + pcHighSwePcValue_, 0, // y0, y1 + pcDerivativeHighSweThreshold_, pcDerivativeHighSweEnd_); // m0, m1 + + + } + + template + void initKrParameters_(const MaterialLaw* m, const Scalar lowSwe, const Scalar highSwe) + { + const auto lowSw = MaterialLaw::EffToAbs::sweToSw(lowSwe, m->effToAbsParams()); + const auto highSw = MaterialLaw::EffToAbs::sweToSw(highSwe, m->effToAbsParams()); + const auto dsw_dswe = MaterialLaw::EffToAbs::dsw_dswe(m->effToAbsParams()); + + const auto krwHighSw = m->template krw(highSw); + const auto dkrwHighSw = m->template dkrw_dsw(highSw)*dsw_dswe; + + const auto krnLowSw = m->template krn(lowSw); + const auto dkrnLowSw = m->template dkrn_dsw(lowSw)*dsw_dswe; + + krwSpline_ = Spline(highSwe, 1.0, // x0, x1 + krwHighSw, 1.0, // y0, y1 + dkrwHighSw, 0.0); // m0, m1 + + krnSpline_ = Spline(0.0, lowSwe, // x0, x1 + 1.0, krnLowSw, // y0, y1 + 0.0, dkrnLowSw); // m0, m1 + + } + + Scalar pcLowSwe_, pcHighSwe_; + Scalar pcLowSwePcValue_, pcHighSwePcValue_; + Scalar krwHighSwe_, krnLowSwe_; + Scalar pcDerivativeLowSw_; + Scalar pcDerivativeHighSweThreshold_, pcDerivativeHighSweEnd_; + + Spline pcSpline_; + Spline krwSpline_; + Spline krnSpline_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A default configuration for using the VanGenuchten material law + */ +template +using VanGenuchtenDefault = TwoPMaterialLaw, TwoPEffToAbsDefaultPolicy>; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A default configuration without regularization for using the VanGenuchten material law + */ +template +using VanGenuchtenNoReg = TwoPMaterialLaw; + +} // end namespace Dumux::FluidMatrix #endif diff --git a/dumux/material/fluidmatrixinteractions/2p/vangenuchtenoftemperature.hh b/dumux/material/fluidmatrixinteractions/2p/vangenuchtenoftemperature.hh index 87c8afeed4cd15b9d45b81c7a555f93e4ceca07d..92a0e00511e726b2cab2764b62eeb303f526ee2b 100644 --- a/dumux/material/fluidmatrixinteractions/2p/vangenuchtenoftemperature.hh +++ b/dumux/material/fluidmatrixinteractions/2p/vangenuchtenoftemperature.hh @@ -26,6 +26,8 @@ #ifndef REGULARIZED_VAN_GENUCHTEN_OF_TEMPERATURE_HH #define REGULARIZED_VAN_GENUCHTEN_OF_TEMPERATURE_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include @@ -40,7 +42,7 @@ namespace Dumux { * Everything except the capillary pressure is taken from the parent, i.e. Regularized VanGenuchten. */ template > -class RegularizedVanGenuchtenOfTemperature : public RegularizedVanGenuchten +class [[deprecated("Use new material laws! Removal after 3.3")]] RegularizedVanGenuchtenOfTemperature : public RegularizedVanGenuchten { using RegularizedVanGenuchten = Dumux::RegularizedVanGenuchten; // Data is in /home/pnuske/paper/pcOfT/ diff --git a/dumux/material/fluidmatrixinteractions/2p/vangenuchtenparams.hh b/dumux/material/fluidmatrixinteractions/2p/vangenuchtenparams.hh index 1f35d26e2587f10176d2bc7917c5f3d5ec38b1a9..f5c3ab17566cca9610f7b06a57435de09ca16f38 100644 --- a/dumux/material/fluidmatrixinteractions/2p/vangenuchtenparams.hh +++ b/dumux/material/fluidmatrixinteractions/2p/vangenuchtenparams.hh @@ -25,6 +25,8 @@ #ifndef DUMUX_VAN_GENUCHTEN_PARAMS_HH #define DUMUX_VAN_GENUCHTEN_PARAMS_HH +// TODO Deprecated. Remove after 3.3 + #include namespace Dumux { @@ -109,7 +111,7 @@ public: */ void setVgn(Scalar n) { vgn_ = n; vgm_ = 1 - 1/vgn_; } - + /*! * \brief Return the \f$\mathrm{n}\f$ shape parameter \f$\mathrm{[-]}\f$ of van Genuchten's * curve. diff --git a/dumux/material/fluidmatrixinteractions/2pia/CMakeLists.txt b/dumux/material/fluidmatrixinteractions/2pia/CMakeLists.txt index 4040d3bc88bb94d6831f70c691f388ddba601fc4..5d3da0acb35c7ee38cecc99aed4006f804bd603b 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/CMakeLists.txt +++ b/dumux/material/fluidmatrixinteractions/2pia/CMakeLists.txt @@ -1,3 +1,4 @@ +# this folder is deprecated. Use headers in 2p/interfacialarea/ install(FILES awnsurfaceexpfct.hh awnsurfaceexpfctparams.hh diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfct.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfct.hh index 556e25dd2ed9f11bf6c8376b2a1b79d1e6cb07f7..2faca94bcc5791b9d9ec7b4076b26658daeff8af 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfct.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfct.hh @@ -31,6 +31,8 @@ #include #include +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -40,7 +42,7 @@ namespace Dumux { * apillary pressure as suggested by Nuske(2009) (Diploma thesis) \cite nuske2009 . */ template -class AwnSurfaceExpFct +class [[deprecated("Use new material laws and FluidMatrix::InterfacialAreaExponential instead!")]] AwnSurfaceExpFct { public: using Params = ParamsT; diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfctparams.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfctparams.hh index f954343a6d74ec0b91b8a8c651d900bcf06d89c8..c8d8ab963678bd6a1e995aee92f5700a891eb5f1 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfctparams.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpfctparams.hh @@ -23,6 +23,8 @@ #ifndef AWN_SURFACE_EXP_FCT_PARAMS_HH #define AWN_SURFACE_EXP_FCT_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh index 7551db9a6daea9a76f203c649543fd4ca75741f2..6a49616d85d57b4bebbf8883224d9f914b0ee8d1 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3.hh @@ -31,6 +31,8 @@ #include #include +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -39,7 +41,7 @@ namespace Dumux { * specific interfacial area to wetting phase saturation and capillary pressure. */ template > -class AwnSurfaceExpSwPcTo3 +class [[deprecated("Use new material laws and FluidMatrix::InterfacialAreaExponentialCubic instead!")]] AwnSurfaceExpSwPcTo3 { public: using Params = ParamsT; diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3params.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3params.hh index 7b3b390b467b8b3f4c5fe418a678696593a0177a..884d72556f17cc7838d09d39163881771a07005e 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3params.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfaceexpswpcto3params.hh @@ -23,6 +23,8 @@ #ifndef AWN_SURFACE_EXP_SW_PC_TO_3_PARAMS #define AWN_SURFACE_EXP_SW_PC_TO_3_PARAMS +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh index 35baae348e05a9b62a2555e8d228307e0b98cb96..e09298706d309fdbbd656b95d98f7c0f3f7bcffd 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfct.hh @@ -26,6 +26,8 @@ #include "awnsurfacepcmaxfctparams.hh" #include +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -40,7 +42,7 @@ namespace Dumux { */ template > -class AwnSurfacePcMaxFct +class [[deprecated("Use new material laws and FluidMatrix::InterfacialAreaPcMax instead!")]] AwnSurfacePcMaxFct { public: using Params = ParamsT; diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfctparams.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfctparams.hh index 99801bad249435564e320eae222fe1b75c4b0e18..a7c18332ba62c9410055c4c6c84c97159a583053 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfctparams.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepcmaxfctparams.hh @@ -23,6 +23,8 @@ #ifndef AWN_SURFACE_PCMAX_FCT_PARAMS_HH #define AWN_SURFACE_PCMAX_FCT_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh index b9d27b88ce0db84927c3b288d76cd15bef054f52..d4a60bb2ba911ceeb556bc39040add0af7575935 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorder.hh @@ -31,6 +31,8 @@ #include #include +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -39,7 +41,7 @@ namespace Dumux { * specific interfacial area to wetting phase saturation and capillary pressure as suggested by Joekar-Niasar(2008) \cite joekar2008 . */ template > -class AwnSurfacePolynomial2ndOrder +class [[deprecated("Use new material laws and FluidMatrix::InterfacialAreaPolynomialSecondOrder instead!")]] AwnSurfacePolynomial2ndOrder { public: using Params = ParamsT; diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorderparams.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorderparams.hh index 8a4227a80764e1eb1cfea25abddb646a0ffa2525..24fbc5924ad329d8ee2ae0896e490834434aabec 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorderparams.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomial2ndorderparams.hh @@ -23,6 +23,8 @@ #ifndef AWN_SURFACE_POLYNOMIAL_2ND_ORDER_PARAMS_HH #define AWN_SURFACE_POLYNOMIAL_2ND_ORDER_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorder.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorder.hh index 14380960bb8e71fa121079ee2056c09430d77fc4..e8698ffeae529db92fb1f15a82e99b4736a0c947 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorder.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorder.hh @@ -31,6 +31,8 @@ #include #include +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -39,7 +41,7 @@ namespace Dumux { * specific interfacial area to wetting phase saturation and capillary pressure. */ template -class AwnSurfacePolynomialEdgeZero2ndOrder +class [[deprecated("Use new material laws and FluidMatrix::InterfacialAreaolynomialEdgeZero2ndOrder instead!")]] AwnSurfacePolynomialEdgeZero2ndOrder { public: using Params = ParamsT; diff --git a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorderparams.hh b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorderparams.hh index 109f695301c5db8b403a8b92b1d8a546354ec696..37a6ed9b03a77af09698618ce4a4d65b0133839a 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorderparams.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/awnsurfacepolynomialedgezero2ndorderparams.hh @@ -23,6 +23,8 @@ #ifndef AWN_SURFACE_POLYNOMIAL_EDGE_ZERO_2ND_ORDER_PARAMS_HH #define AWN_SURFACE_POLYNOMIAL_EDGE_ZERO_2ND_ORDER_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh b/dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh index 6d8fc4ffc5d5b3bd6445512f1fca2fb2d3678dfa..c959fa69c909e1ce475d51765deb500113b390fe 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/efftoabslawia.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_EFF_TO_ABS_LAW_IA_HH #define DUMUX_EFF_TO_ABS_LAW_IA_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include "efftoabslawiaparams.hh" diff --git a/dumux/material/fluidmatrixinteractions/2pia/efftoabslawiaparams.hh b/dumux/material/fluidmatrixinteractions/2pia/efftoabslawiaparams.hh index f1d0881e4194d4b4fef0330f061f769c4d047c0b..72dd0d763ed5c3afe8c8e7efdd73c9571bc1251e 100644 --- a/dumux/material/fluidmatrixinteractions/2pia/efftoabslawiaparams.hh +++ b/dumux/material/fluidmatrixinteractions/2pia/efftoabslawiaparams.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_EFF_TO_ABS_LAW_IA_PARAMS_HH #define DUMUX_EFF_TO_ABS_LAW_IA_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! @@ -35,7 +37,7 @@ namespace Dumux { * from effective to absolute saturations. */ template -class EffToAbsLawIAParams : public EffIALawParamsT +class [[deprecated("Use new material laws! Removal after 3.3")]] EffToAbsLawIAParams : public EffIALawParamsT { using EffIALawParams = EffIALawParamsT; public: diff --git a/dumux/material/fluidmatrixinteractions/3p/CMakeLists.txt b/dumux/material/fluidmatrixinteractions/3p/CMakeLists.txt index 63d05e3b0364413bb1b3d841d2473e1aeb55ebeb..3cb201ecc21f2fa1e097b98bbc1e2b7ab043f8b1 100644 --- a/dumux/material/fluidmatrixinteractions/3p/CMakeLists.txt +++ b/dumux/material/fluidmatrixinteractions/3p/CMakeLists.txt @@ -1,8 +1,10 @@ install(FILES efftoabslaw.hh efftoabslawparams.hh +napladsorption.hh parkervangen3p.hh parkervangen3pparams.hh +parkervangenuchten.hh regularizedparkervangen3p.hh regularizedparkervangen3pparams.hh thermalconductivitysomerton3p.hh diff --git a/dumux/material/fluidmatrixinteractions/3p/efftoabslaw.hh b/dumux/material/fluidmatrixinteractions/3p/efftoabslaw.hh index cdc4fa6435995c069eed847bcedb9fb32091a568..ee92afb5fc0c7b65495aeb6051a2181718fa421c 100644 --- a/dumux/material/fluidmatrixinteractions/3p/efftoabslaw.hh +++ b/dumux/material/fluidmatrixinteractions/3p/efftoabslaw.hh @@ -29,6 +29,8 @@ #include #include "efftoabslawparams.hh" +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/3p/efftoabslawparams.hh b/dumux/material/fluidmatrixinteractions/3p/efftoabslawparams.hh index 4fd831ccbdabaffd8517b068561f4f7ea6672607..495190741cf7ba07c1c2bd043f4db195ed5618d6 100644 --- a/dumux/material/fluidmatrixinteractions/3p/efftoabslawparams.hh +++ b/dumux/material/fluidmatrixinteractions/3p/efftoabslawparams.hh @@ -26,6 +26,8 @@ #ifndef DUMUX_EFF_TO_ABS_LAW_PARAMS_HH #define DUMUX_EFF_TO_ABS_LAW_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/3p/napladsorption.hh b/dumux/material/fluidmatrixinteractions/3p/napladsorption.hh new file mode 100644 index 0000000000000000000000000000000000000000..689ceb4f675fbb4b150fd7247beefb9381263fd2 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/3p/napladsorption.hh @@ -0,0 +1,88 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Implementation of a NAPL adsorption model. + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_INTERACTIONS_3P_NAPL_ADSORPTION +#define DUMUX_MATERIAL_FLUIDMATRIX_INTERACTIONS_3P_NAPL_ADSORPTION + +#include +#include + +namespace Dumux::FluidMatrix { + +template +class ThreePNAPLAdsorption : Adapter, Adsorption> +{ +public: + + struct Params + { + Params(const Scalar rhoBulk, const Scalar kdNAPL) + : rhoBulk_(rhoBulk), kdNAPL_(kdNAPL) {} + + Scalar rhoBulk() const { return rhoBulk_; } + void setRhoBulk(const Scalar rhoBulk) { rhoBulk_ = rhoBulk; } + + Scalar kdNAPL() const { return kdNAPL_; } + void setKdNAPL(const Scalar kdNAPL) { kdNAPL_ = kdNAPL; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(kdNAPL(), p.kdNAPL(), 1e-6) + && Dune::FloatCmp::eq(rhoBulk(), p.rhoBulk(), 1e-6); + } + + private: + Scalar rhoBulk_, kdNAPL_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + static Params makeParams(const std::string& paramGroup) + { + const auto rhoBulk = getParamFromGroup(paramGroup, "ThreePNAPLAdsorptionRhoBulk"); + const auto kdNAPL = getParamFromGroup(paramGroup, "ThreePNAPLAdsorptionKdNAPL"); + return {rhoBulk, kdNAPL}; + } + + ThreePNAPLAdsorption(const Params& params): params_(params) {} + + ThreePNAPLAdsorption(const std::string& paramGroup) + : params_(makeParams(paramGroup)) {} + + /*! + * \brief the basis for calculating adsorbed NAPL in storage term + * \param params Array of parameters + */ + Scalar bulkDensTimesAdsorpCoeff () const + { + return params_.rhoBulk() * params_.kdNAPL(); + } + +private: + Params params_; +}; +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/3p/parkervangen3p.hh b/dumux/material/fluidmatrixinteractions/3p/parkervangen3p.hh index 1f7da166996089671177ca7011576f52d3da685b..f5b8c861680fdccc7263391b0449340eb94009cc 100644 --- a/dumux/material/fluidmatrixinteractions/3p/parkervangen3p.hh +++ b/dumux/material/fluidmatrixinteractions/3p/parkervangen3p.hh @@ -28,6 +28,8 @@ #include "parkervangen3pparams.hh" +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + namespace Dumux { /*! diff --git a/dumux/material/fluidmatrixinteractions/3p/parkervangen3pparams.hh b/dumux/material/fluidmatrixinteractions/3p/parkervangen3pparams.hh index 7e407ed4da60bb24a56783f24424a99377de7a71..23dda11b0bb5e3fc71de8a80f5161c40881304ea 100644 --- a/dumux/material/fluidmatrixinteractions/3p/parkervangen3pparams.hh +++ b/dumux/material/fluidmatrixinteractions/3p/parkervangen3pparams.hh @@ -28,6 +28,8 @@ #ifndef PARKERVANGEN_PARAMS_3P_HH #define PARKERVANGEN_PARAMS_3P_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include diff --git a/dumux/material/fluidmatrixinteractions/3p/parkervangenuchten.hh b/dumux/material/fluidmatrixinteractions/3p/parkervangenuchten.hh new file mode 100644 index 0000000000000000000000000000000000000000..5e4a59e7250474e830f433deca3a7e62f0537583 --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/3p/parkervangenuchten.hh @@ -0,0 +1,1362 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Implementation of van Genuchten's capillary pressure-saturation relation for three phases. + */ +#ifndef PARKER_VANGENUCHTEN_3P_HH +#define PARKER_VANGENUCHTEN_3P_HH + +#include +#include +#include +#include +#include + +namespace Dumux::FluidMatrix { + +struct ParkerVanGenuchten3PEffToAbsPolicy +{ + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + * \note The efftoabs policy need two parameters: \f$\mathrm{S_{w,r}}, \mathrm{S_{n,r}}\f$. + * For the respective formulas check out the description of the free function. + */ + template + struct Params + { + Params(const Scalar swr = 0.0, const Scalar snr = 0.0, const Scalar sgr = 0.0) + : swr_(swr), snr_(snr), sgr_(sgr) + {} + + /*! + * \brief Return the residual wetting saturation. + */ + Scalar swr() const + { return swr_; } + + /*! + * \brief Set the residual wetting saturation. + */ + void setSwr(Scalar v) + { swr_ = v; } + + /*! + * \brief Return the residual non-wetting saturation. + */ + Scalar snr() const + { return snr_; } + + /*! + * \brief Set the residual non-wetting saturation. + */ + void setSnr(Scalar v) + { snr_ = v; } + /*! + + * \brief Return the residual gas phase saturation. + */ + Scalar sgr() const + { return sgr_; } + + /*! + * \brief Set the residual gas phase saturation. + */ + void setSgr(Scalar v) + { sgr_ = v; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(swr(), p.swr(), 1e-6) + && Dune::FloatCmp::eq(snr(), p.snr(), 1e-6) + && Dune::FloatCmp::eq(sgr(), p.sgr(), 1e-6); + } + private: + Scalar swr_; + Scalar snr_; + Scalar sgr_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + Params params; + params.setSwr(getParamFromGroup(paramGroup, "Swr", 0.0)); + params.setSnr(getParamFromGroup(paramGroup, "Snr", 0.0)); + params.setSgr(getParamFromGroup(paramGroup, "Sgr", 0.0)); + return params; + } + + /*! + * \brief Convert an absolute wetting saturation to an effective one. + * + * \param sw Absolute saturation of the wetting phase \f$\mathrm{[{S}_w]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Effective saturation of the wetting phase. + */ + template + static Scalar swToSwe(const Scalar sw, const Params& params) + { + return (sw - params.swr())/(1.0 - params.swr()); // TODO other residual saturations? + } + + /*! + * \brief Convert an effective wetting saturation to an absolute one. + * + * \param swe Effective saturation of the non-wetting phase \f$\mathrm{[\overline{S}_n]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Absolute saturation of the non-wetting phase. + */ + template + static Scalar sweToSw(const Scalar swe, const Params& params) + { + return swe*(1.0 - params.swr()) + params.swr(); // TODO other residual saturations? + } + + /*! + * \brief Derivative of the effective saturation w.r.t. the absolute saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the effective saturation w.r.t. the absolute saturation. + */ + template + static Scalar dswe_dsw(const Params& params) + { + return 1.0/(1.0 - params.swr()); // TODO other residual saturations? + } + + /*! + * \brief Derivative of the absolute saturation w.r.t. the effective saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the absolute saturation w.r.t. the effective saturation. + */ + template + static Scalar dsw_dswe(const Params& params) + { + return 1.0 - params.swr(); // TODO other residual saturations? + } + + /*! + * \brief Convert an absolute non-wetting saturation to an effective one. + * + * \param sn Absolute saturation of the non-wetting phase \f$\mathrm{[{S}_n]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Effective saturation of the non-wetting phase. + */ + template + static Scalar snToSne(const Scalar sn, const Params& params) + { + return sn; // sne equals sn // TODO other residual saturations? + } + + /*! + * \brief Convert an absolute total liquid saturation to an effective one. + * + * \param st Absolute saturation of the total liquid phase (sw+sn) \f$\mathrm{[{S}_n]}\f$. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Effective saturation of the non-wetting phase. + */ + template + static Scalar stToSte(const Scalar st, const Params& params) + { + return (st-params.swr()) / (1-params.swr()); // TODO other residual saturations? + } + + /*! + * \brief Convert an effective wetting saturation to an absolute one. + * + * \param ste Effective total liquid (wetting + non-wetting) saturation + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Absolute saturation of the non-wetting phase. + */ + template + static Scalar steToSt(const Scalar ste, const Params& params) + { + return ste*(1.0 - params.swr()) + params.swr(); // TODO other residual saturations? + } + + /*! + * \brief Derivative of the effective saturation w.r.t. the absolute saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the effective saturation w.r.t. the absolute saturation. + */ + template + static Scalar dste_dst(const Params& params) + { + return 1.0/(1.0 - params.swr() /*- params.snr() - params.sgr()*/); // TODO other residual saturations? + } + + /*! + * \brief Derivative of the absolute saturation w.r.t. the effective saturation. + * + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, + * and then the params container is constructed accordingly. Afterwards the values are set there, too. + * \return Derivative of the absolute saturation w.r.t. the effective saturation. + */ + template + static Scalar dst_dste(const Params& params) + { + return 1.0 - params.swr(); // TODO other residual saturations? + } +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implementation of van Genuchten's capillary pressure <-> + * saturation relation. This class bundles the "raw" curves + * as static members and doesn't concern itself converting + * absolute to effective saturations and vince versa. + * + * \sa VanGenuchten, VanGenuchtenThreephase + */ +class ParkerVanGenuchten3P +{ + +public: + /*! + * \brief The parameter type + * \tparam Scalar The scalar type + * \note The van Genuchten laws are parameterized with four parameters: \f$\mathrm{n, m, \alpha, l}\f$. + * + * - \f$\mathrm{\alpha}\f$ shape parameter \f$\mathrm{[1/Pa]}\f$ + * - \f$\mathrm{m}\f$ shape parameter \f$\mathrm{[-]}\f$ + * - \f$\mathrm{n}\f$ shape parameter \f$\mathrm{[-]}\f$ + * - \f$\mathrm{l}\f$ pore-connectivity parameter \f$\mathrm{[-]}\f$ of Mualem's relative permeability curve + * + */ + template + struct Params + { + Params(Scalar alpha, Scalar n, Scalar swr = 0.0, Scalar snr = 0.0, + Scalar betaNw = 1.0, Scalar betaGn = 1.0, Scalar betaGw = 1.0, bool regardSnr = false) + : alpha_(alpha), n_(n), m_(1.0 - 1.0/n), swr_(swr), snr_(snr) + , betaNw_(betaNw), betaGn_(betaGn), betaGw_(betaGw), regardSnr_(regardSnr) + {} + + Scalar alpha() const { return alpha_; } + void setAlpha(Scalar alpha) { alpha_ = alpha; } + + Scalar m() const { return m_; } + void setM(Scalar m) { m_ = m; n_ = 1.0/(1.0 - m); } + + Scalar n() const{ return n_; } + void setN(Scalar n){ n_ = n; m_ = 1.0 - 1.0/n; } + + Scalar swr() const { return swr_; } + void setSwr(Scalar swr) { swr_ = swr; } + + Scalar snr() const { return snr_; } + void setSnr(Scalar swr) { snr_ = swr; } + + Scalar betaNw() const { return betaNw_; } + void setBetaNw(Scalar betaNw) { betaNw_ = betaNw; } + + Scalar betaGn() const { return betaNw_; } + void setBetaGn(Scalar betaGn) { betaGn_ = betaGn; } + + Scalar betaGw() const { return betaGw_; } + void setBetaGw(Scalar betaGw) { betaGw_ = betaGw; } + + bool regardSnrForKrn() const { return regardSnr_; } + void setRegardSnrForKrn(bool v) {regardSnr_ = v; } + + bool operator== (const Params& p) const + { + return Dune::FloatCmp::eq(alpha_, p.alpha_, 1e-6) + && Dune::FloatCmp::eq(n_, p.n_, 1e-6) + && Dune::FloatCmp::eq(m_, p.m_, 1e-6) + && Dune::FloatCmp::eq(swr_, p.swr_, 1e-6) + && Dune::FloatCmp::eq(snr_, p.snr_, 1e-6) + && Dune::FloatCmp::eq(betaNw_, p.betaNw_, 1e-6) + && Dune::FloatCmp::eq(betaGn_, p.betaGn_, 1e-6) + && Dune::FloatCmp::eq(betaGw_, p.betaGw_, 1e-6) + && regardSnr_ == p.regardSnr_; + } + + private: + Scalar alpha_, n_, m_, swr_, snr_, betaNw_, betaGn_, betaGw_; + bool regardSnr_; + }; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + template + static Params makeParams(const std::string& paramGroup) + { + const auto n = getParamFromGroup(paramGroup, "ParkerVanGenuchtenN"); + const auto alpha = getParamFromGroup(paramGroup, "ParkerVanGenuchtenAlpha"); + const auto swr = getParamFromGroup(paramGroup, "Swr", 0.0); + const auto snr = getParamFromGroup(paramGroup, "Snr", 0.0); + const auto betaNw = getParamFromGroup(paramGroup, "ParkerVanGenuchtenBetaNw", 1.0); + const auto betaGn = getParamFromGroup(paramGroup, "ParkerVanGenuchtenBetaGn", 1.0); + const auto betaGw = getParamFromGroup(paramGroup, "ParkerVanGenuchtenBetaGw", 1.0); + const auto regardSnr = getParamFromGroup(paramGroup, "ParkerVanGenuchtenRegardSnrForKrn", false); + return Params(alpha, n, swr, snr, + betaNw, betaGn, betaGw, regardSnr ); + } + + + /*! + * \brief The capillary pressure-saturation curve for the gas and wetting phase + * \param params Array of parameters + * \param swe Effective wetting phase saturation + * + */ + template + static Scalar pcgw(Scalar swe, const Params& params) + { + assert(0 <= swe && swe <= 1); + return pc_(swe, params); + } + + /*! + * \brief The capillary pressure-saturation curve for the non-wettigng and wetting phase + * \param params Array of parameters + * \param swe Effective wetting phase saturation + */ + template + static Scalar pcnw(Scalar swe, const Params& params) + { + assert(0 <= swe && swe <= 1); + return pc_(swe, params)/params.betaNw(); + } + + /*! + * \brief The capillary pressure-saturation curve for the gas and non-wetting phase + * \param params Array of parameters + * \param ste Effective total liquid (wetting + non-wetting) saturation + */ + template + static Scalar pcgn(const Scalar ste, const Params& params) + { + assert(0 <= ste && ste <= 1); + return pc_(ste, params)/params.betaGn(); + } + + /*! + * \brief This function ensures a continuous transition from 2 to 3 phases and vice versa + * \param params Array of parameters + * \param sne Non-wetting liquid saturation + */ + template + static Scalar pcAlpha(Scalar sne, const Params& params) + { + /* regularization */ + if (sne <= 0.001) + sne = 0.0; + if (sne >= 1.0) + sne = 1.0; + + if (sne > params.snr()) + return 1.0; + else + { + if (params.snr() >= 0.001) + return sne/params.snr(); + else + return 0.0; + }; + } + + /*! + * \brief Returns the partial derivative of the capillary + * pressure to the effective saturation. + * \param params Array of parameters + * \param swe Effective wetting phase saturation for regularization + */ + template + static Scalar dpcgw_dswe(const Scalar swe, const Params& params) + { + using std::pow; + const Scalar powSeRegu = pow(swe, -1/params.m()); + return - 1.0/params.alpha() * pow(powSeRegu - 1, 1.0/params.n() - 1)/params.n() + * powSeRegu/swe/params.m()/params.betaGw(); + } + + /*! + * \brief Returns the partial derivative of the capillary + * pressure to the effective saturation. + * \param params Array of parameters + * \param swe Effective wetting phase saturation for regularization + */ + template + static Scalar dpcnw_dswe(const Scalar swe, const Params& params) + { + using std::pow; + const Scalar powSeRegu = pow(swe, -1/params.m()); + return - 1.0/params.alpha() * pow(powSeRegu - 1, 1.0/params.n() - 1)/params.n() + * powSeRegu/swe/params.m()/params.betaNw(); + } + + /*! + * \brief Returns the partial derivative of the capillary + * pressure to the effective saturation. + * \param params Array of parameters + * \param ste Effective total liquid (wetting + non-wetting) saturation for regularization + */ + template + static Scalar dpcgn_dste(const Scalar ste, const Params& params) + { + using std::pow; + const Scalar powSeRegu = pow(ste, -1/params.m()); + return - 1.0/params.alpha() * pow(powSeRegu - 1, 1.0/params.n() - 1)/params.n() + * powSeRegu/ste/params.m()/params.betaGn(); + } + + /*! + * \brief The relative permeability for the wetting phase of + * the medium implied by van Genuchten's + * parameterization. + * + * The permeability of water in a 3p system equals the standard 2p description. + * (see p61. in "Comparison of the Three-Phase Oil Relative Permeability Models" + * MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.) \cite delshad1989
+ * + * \param params Array of parameters. + * \param swe Effective wetting phase saturation + */ + template + static Scalar krw(const Scalar swe, const Params& params) + { + using std::pow; + using std::sqrt; + const Scalar r = 1.0 - pow(1 - pow(swe, 1/params.m()), params.m()); + return sqrt(swe)*r*r; + } + + /*! + * \brief The relative permeability for the non-wetting phase + * after the Model of Parker et al. (1987). + * + * See model 7 in "Comparison of the Three-Phase Oil Relative Permeability Models" + * MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83 \cite delshad1989
+ * or more comprehensive in + * "Estimation of primary drainage three-phase relative permeability for organic + * liquid transport in the vadose zone", Leonardo I. Oliveira, Avery H. Demond, + * Journal of Contaminant Hydrology 66 (2003), 261-285 \cite oliveira2003
+ * + * + * \param params Array of parameters. + * \param swe Effective wetting phase saturation + * \param sn Absolute non-wetting liquid saturation + * \param ste Effective total liquid (wetting + non-wetting) saturation + */ + template + static Scalar krn(const Scalar swe, const Scalar sn, const Scalar ste, const Params& params) + { + Scalar krn; + using std::pow; + krn = pow(1 - pow(swe, 1/params.m()), params.m()); + krn -= pow(1 - pow(ste, 1/params.m()), params.m()); + krn *= krn; + + using std::clamp; + using std::sqrt; + if (params.regardSnrForKrn()) + { + // regard Snr in the permeability of the n-phase, see Helmig1997 + const Scalar resIncluded = clamp(sn - params.snr()/ (1-params.swr()), 0.0, 1.0); + krn *= sqrt(resIncluded); + } + else + krn *= sqrt(sn / (1 - params.swr())); // Hint: (ste - swe) = sn / (1-Swr) + + return krn; + } + + /*! + * \brief The relative permeability for the non-wetting phase + * of the medium implied by van Genuchten's + * parameterization. + * + * The permeability of gas in a 3p system equals the standard 2p description. + * (see p61. in "Comparison of the Three-Phase Oil Relative Permeability Models" + * MOJDEH DELSHAD and GARY A. POPE, Transport in Porous Media 4 (1989), 59-83.) \cite delshad1989
+ * + * \param params Array of parameters. + * \param ste Effective total liquid (wetting + non-wetting) saturation + */ + template + static Scalar krg(const Scalar ste, const Params& params) + { + assert(0 <= ste && ste <= 1); + using std::cbrt; + using std::pow; + return cbrt(1 - ste) * pow(1 - pow(ste, 1/params.m()), 2*params.m()); + } + + /*! + * \brief The derivative of the relative permeability for the + * gas phase in regard to the total liquid saturation of + * the medium as implied by the van Genuchten + * parameterization. + * + * \param ste The mobile total liquid saturation. + * \param params A container object that is populated with the appropriate coefficients for the respective law. + * Therefore, in the (problem specific) spatialParameters first, the material law is chosen, and then the params container + * is constructed accordingly. Afterwards the values are set there, too. + */ + template + static Scalar dkrg_dste(const Scalar ste, const Params& params) + { + assert(0 < ste && ste <= 1); + + using std::pow; + const Scalar x = pow(ste, 1.0/params.m()); + return + -pow(1.0 - x, 2*params.m()) + *pow(1.0 - ste, -2.0/3) + *(1.0/3 + 2*x/ste); + } + + /*! + * \brief The relative permeability for a phase. + * \param params Array of parameters. + * \param phaseIdx Indicator, The saturation of all phases. + * \param swe Effective wetting phase saturation + * \param sne Effective non-wetting saturation + */ + template + static Scalar kr(const int phaseIdx, const Scalar swe, const Scalar sne, const Params& params) + { + switch (phaseIdx) + { + case 0: + return krw(params, swe, sne); + case 1: + return krn(params, swe, sne); + case 2: + return krg(params, swe, sne); + } + DUNE_THROW(Dune::InvalidStateException, + "Invalid phase index "); + } + +private: + + /*! + * \brief The standard van Genuchten two-phase pc-S relation either with respect to + * the effective wetting phase saturation Swe or the effective total liquid saturation Ste. + * \param params Array of parameters. + * \param se Effective wetting phase ortotal liquid saturation + */ + template + const static Scalar pc_(const Scalar se, const Params& params) + { + using std::pow; + return pow(pow(se, -1/params.m()) - 1, 1/params.n())/params.alpha(); + } + +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A regularization for the VanGenuchten material law + * \note Regularization can be turned of by setting the threshold parameters + * out of range (runtime) or by replacing + * this class by NoRegularization (compile time). + */ +template +class ParkerVanGenuchten3PRegularization +{ + using BaseLawParams = typename ParkerVanGenuchten3P::Params; + +public: + //! Regularization parameters + template + struct Params + { + /*! + * \brief Set the threshold saturation below which the capillary pressure is regularized. + * + * Most problems are very sensitive to this value (e.g. making it smaller might + * result in very high capillary pressures) + */ + void setPcLowSwe(Scalar pcLowSwe) + { pcLowSwe_ = pcLowSwe; } + + /*! + * \brief Threshold saturation below which the capillary pressure is regularized. + */ + Scalar pcLowSwe() const + { return pcLowSwe_; } + + /*! + * \brief Set the threshold saturation above which the capillary pressure is regularized. + */ + void setPcHighSwe(Scalar pcHighSwe) + { pcHighSwe_ = pcHighSwe; } + + /*! + * \brief Threshold saturation above which the capillary pressure is regularized. + * + * Most problems are very sensitive to this value (e.g. making it smaller might + * result in negative capillary pressures). + */ + Scalar pcHighSwe() const + { return pcHighSwe_; } + + /*! + * \brief Set the threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + void setKrnLowSwe(Scalar krnLowSwe) + { krnLowSwe_ = krnLowSwe; } + + /*! + * \brief Threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + Scalar krnLowSwe() const + { return krnLowSwe_; } + + /*! + * \brief Set the threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + void setKrgLowSte(Scalar krgLowSte) + { krgLowSte_ = krgLowSte; } + + /*! + * \brief Threshold saturation below which the relative + * permeability of the non-wetting phase gets regularized. + */ + Scalar krgLowSte() const + { return krgLowSte_; } + + /*! + * \brief Set the threshold saturation above which the relative + * permeability of the wetting phase gets regularized. + */ + void setKrwHighSwe(Scalar krwHighSwe) + { krwHighSwe_ = krwHighSwe; } + + /*! + * \brief Threshold saturation above which the relative + * permeability of the wetting phase gets regularized. + */ + Scalar krwHighSwe() const + { return krwHighSwe_; } + + + /*! + * \brief Choose whether to use a constant value for regularization of the + * pc-S curves or not + * \param input True or false + */ + void setConstRegularization(const bool input) + { constRegularization_ = input; } + + /*! + * \brief Returns whether to use a constant value for regularization of the + * pc-S curves or not + */ + bool constRegularization() const + { return constRegularization_; } + +private: + S pcLowSwe_ = 0.01; + S pcHighSwe_ = 0.99; + S krnLowSwe_ = 0.1; + S krwHighSwe_ = 0.9; + S krgLowSte_ = 1e-3; + bool constRegularization_ = false; + }; + + //! Initialize the spline + template + void init(const MaterialLaw* m, const std::string& paramGroup) + { + pcLowSwe_ = getParamFromGroup(paramGroup, "ParkerVanGenuchtenPcLowSweThreshold", 0.01); + pcHighSwe_ = getParamFromGroup(paramGroup, "ParkerVanGenuchtenPcHighSweThreshold", 0.99); + krwHighSwe_ = getParamFromGroup(paramGroup, "ParkerVanGenuchtenKrwHighSweThreshold", 0.9); + krnLowSwe_ = getParamFromGroup(paramGroup, "ParkerVanGenuchtenKrnLowSweThreshold", 0.1); + krgLowSte_ = getParamFromGroup(paramGroup, "ParkerVanGenuchtenKrgLowSteThreshold", 1e-3); + constRegularization_ = getParamFromGroup(paramGroup, "VanGenuchtenConstantRegularization", false); + + initPcParameters_(m, pcLowSwe_, pcHighSwe_); + initKrParameters_(m, krnLowSwe_, krwHighSwe_); + } + + template + void init(const MaterialLaw* m, const BaseParams& bp, const EffToAbsParams& etap, const Params& p) + { + pcLowSwe_ = p.pcLowSwe(); + pcHighSwe_ = p.pcHighSwe(); + krwHighSwe_ = p.krwHighSwe(); + krnLowSwe_ = p.krnLowSwe(); + krgLowSte_ = p.krgLowSte(); + constRegularization_ = p.constRegularization(); + + initPcParameters_(m, pcLowSwe_, pcHighSwe_); + initKrParameters_(m, krnLowSwe_, krwHighSwe_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const ParkerVanGenuchten3PRegularization& o) const + { + return Dune::FloatCmp::eq(pcLowSwe_, o.pcLowSwe_, 1e-6) + && Dune::FloatCmp::eq(pcHighSwe_, o.pcHighSwe_, 1e-6) + && Dune::FloatCmp::eq(krwHighSwe_, o.krwHighSwe_, 1e-6) + && Dune::FloatCmp::eq(krnLowSwe_, o.krnLowSwe_, 1e-6) + && constRegularization_ == o.constRegularization_; + } + + /*! + * \brief The regularized capillary pressure-saturation curve or the gas and wetting phase + * regularized part: + * - low saturation: extend the \f$\mathrm{p_c(S_w)}\f$ curve with the slope at the regularization point (i.e. no kink). + * - high saturation: connect the high regularization point with \f$\mathrm{\overline{S}_w =1}\f$ + * with a spline and continue linearly for \f$\mathrm{\overline{S}_w > 1}\f$ + * \param swe Effective wetting phase saturation + */ + OptionalScalar pcgw(Scalar swe) const + { + // if specified, a constant value is used for regularization + using std::clamp; + if (constRegularization_) + swe = clamp(swe, 0.0, 1.0); + + // make sure that the capillary pressure observes a derivative + // != 0 for 'illegal' saturations. This is favourable for the + // newton solver (if the derivative is calculated numerically) + // in order to get the saturation moving to the right + // direction if it temporarily is in an 'illegal' range. + if (swe < pcLowSwe_) + return pcgwLowSwePcgwValue_ + pcgwDerivativeLowSw_*(swe - pcLowSwe_); + + else if (swe > 1.0) + return pcgwDerivativeHighSweEnd_*(swe - 1.0); + + else if (swe > pcHighSwe_) + return pcgwSpline_.eval(swe); + + else + return {}; // no regularization + } + + OptionalScalar pcnw(Scalar swe) const + { + // if specified, a constant value is used for regularization + using std::clamp; + if (constRegularization_) + swe = clamp(swe, 0.0, 1.0); + + // make sure that the capillary pressure observes a derivative + // != 0 for 'illegal' saturations. This is favourable for the + // newton solver (if the derivative is calculated numerically) + // in order to get the saturation moving to the right + // direction if it temporarily is in an 'illegal' range. + if (swe < pcLowSwe_) + return pcnwLowSwePcnwValue_ + pcnwDerivativeLowSw_*(swe - pcLowSwe_); + + else if (swe > pcHighSwe_) + return pcnwSpline_.eval(swe); + + else + return {}; // no regularization + } + + OptionalScalar pcgn(Scalar ste) const + { + // if specified, a constant value is used for regularization + using std::clamp; + if (constRegularization_) + ste = clamp(ste, 0.0, 1.0); + + + // make sure that the capillary pressure observes a derivative + // != 0 for 'illegal' saturations. This is favourable for the + // newton solver (if the derivative is calculated numerically) + // in order to get the saturation moving to the right + // direction if it temporarily is in an 'illegal' range. + const Scalar pcLowSte = pcLowSwe_; + const Scalar pcHighSte = pcHighSwe_; + if (ste < pcLowSte) + return pcgnLowStePcgnValue_ + pcgnDerivativeLowSt_*(ste - pcLowSte); + + else if (ste > pcHighSte) + return pcgnSpline_.eval(ste); + + else + return {}; // no regularization + } + + /*! + * \brief This function ensures a continuous transition from 2 to 3 phases and vice versa + * \param sne Effective non-wetting liquid saturation + */ + OptionalScalar pcAlpha(Scalar sne) const + { + // no regularization + return {}; + } + + /*! + * \brief The regularized relative permeability for the wetting phase + * \param swe Effective wetting phase saturation + */ + OptionalScalar krw(const Scalar swe) const + { + if (swe < 0.0) + return 0.0; + else if (swe > 1.0 - std::numeric_limits::epsilon()) + return 1.0; + else + return {}; // no regularization + } + + + /*! + * \brief The regularized relative permeability for the non-wetting phase + * \param swe Effective wetting phase saturation + * \param sn Non-wetting saturation + * \param ste Effective total (wetting + non-wetting) saturation + */ + OptionalScalar krn(Scalar swe, const Scalar sn, Scalar ste) const + { + using std::clamp; + swe = clamp(swe, 0.0, 1.0); + ste = clamp(ste, 0.0, 1.0); + + if (ste - swe <= 0.0) + return 0.0; + else + return ParkerVanGenuchten3P::krn(swe, sn, ste, *baseLawParamsPtr_); + } + + /*! + * \brief The regularized relative permeability for the gas phase + * \param ste Effective total (wetting + non-wetting) saturation + */ + OptionalScalar krg(const Scalar ste) const + { + //return 0 if there is no gas + if (ste > 1.0 - std::numeric_limits::epsilon()) + return 0.0; + + // use linear regularization for very high gas saturations + // to avoid a kink in the curve and to maintain a slope for + // the Newton solver + if (ste <= krgLowSte_) + return krgLowStkrgValue_ + krgDerivativeLowSt_*(ste - krgLowSte_); + else + { + // For very low gas saturations: + // We use a scaling factor that decreases the gas phase permeability quite fast a very low gas phase + // saturations, thus making that phase virtually immobile. + // This prevents numerical issues related to the degeneration of the gas phase mass balance for the 3p3c model + // at very low gas phase saturations. + + // get the absolute gas phase saturation + const Scalar st = ste*(1 - swr_) + swr_; + const Scalar sg = 1.0 - st; + + // do not regularize + if (sg > 0.1) + return {}; + + // return original curve scaled by factor + using std::max; + const Scalar scalFact = max(0.0, (sg - sgr_)/(0.1 - sgr_)); + + return ParkerVanGenuchten3P::krg(ste, *baseLawParamsPtr_) * scalFact; + } + } + + /*! + * \brief The relative permeability for a phase. + * \param phaseIdx Indicator, The saturation of all phases. + * \param swe Effective wetting phase saturation + * \param sne Effective non-wetting saturation + */ + OptionalScalar kr(const int phaseIdx, const Scalar swe, const Scalar sne) const + { + switch (phaseIdx) + { + case 0: + return krw(swe, sne); + case 1: + return krn(swe, sne); + case 2: + return krg(swe, sne); + } + DUNE_THROW(Dune::InvalidStateException, + "Invalid phase index "); + } + +private: + template + void initPcParameters_(const MaterialLaw* m, const Scalar lowSwe, const Scalar highSwe) + { + const auto lowSw = MaterialLaw::EffToAbs::sweToSw(lowSwe, m->effToAbsParams()); + const auto highSw = MaterialLaw::EffToAbs::sweToSw(highSwe, m->effToAbsParams()); + const auto dsw_dswe = MaterialLaw::EffToAbs::dsw_dswe(m->effToAbsParams()); + const auto dst_dste = MaterialLaw::EffToAbs::dst_dste(m->effToAbsParams()); + + baseLawParamsPtr_ = &m->basicParams(); + + + + // pcgw + pcgwLowSwePcgwValue_ = m->template pcgw(lowSw, 0.0); + pcgwDerivativeLowSw_ = m->template dpcgw_dsw(lowSw, 0.0)*dsw_dswe; + pcgwHighSwePcgwValue_ = m->template pcgw(highSw, 0.0); + pcgwDerivativeHighSweThreshold_ = m->template dpcgw_dsw(highSw, 0.0)*dsw_dswe; + pcgwDerivativeHighSweEnd_ = 2.0*(0.0 - m->template pcgw(highSw, 0.0))/(1.0 - highSwe); + pcgwSpline_ = Spline(highSwe, 1.0, // x0, x1 + pcgwHighSwePcgwValue_, 0, // y0, y1 + pcgwDerivativeHighSweThreshold_, pcgwDerivativeHighSweEnd_); // m0, m1 + + // pcnw + pcnwLowSwePcnwValue_ = m->template pcnw(lowSw, 0.0); + pcnwDerivativeLowSw_ = m->template dpcnw_dsw(lowSw, 0.0)*dsw_dswe; + pcnwHighSwePcnwValue_ = m->template pcnw(highSw, 0.0); + pcnwDerivativeHighSweThreshold_ = m->template dpcnw_dsw(highSw, 0.0); + pcnwDerivativeHighSweEnd_ = 2.0*(0.0 - m->template pcnw(highSw, 0.0))/(1.0 - highSwe); + pcnwSpline_ = Spline(highSwe, 1.0, // x0, x1 + pcnwHighSwePcnwValue_, 0, // y0, y1 + pcnwDerivativeHighSweThreshold_, pcnwDerivativeHighSweEnd_); // m0, m1 + + // pcgn + pcgnLowStePcgnValue_ = m->template pcgn(lowSw, 0.0); + pcgnDerivativeLowSt_ = m->template dpcgn_dst(lowSw, 0.0)*dst_dste; + pcgnHighSwePcgnValue_ = m->template pcgn(highSw, 0.0); + pcgnDerivativeHighSweThreshold_ = m->template dpcgn_dst(highSw, 0.0); + pcgnDerivativeHighSweEnd_ = 2.0*(0.0 - m->template pcgn(highSw, 0.0))/(1.0 - highSwe); + pcgnSpline_ = Spline(highSwe, 1.0, // x0, x1 + pcgnHighSwePcgnValue_, 0, // y0, y1 + pcgnDerivativeHighSweThreshold_, pcgnDerivativeHighSweEnd_); // m0, m1 + + } + + template + void initKrParameters_(const MaterialLaw* m, const Scalar lowSwe, const Scalar highSwe) + { + krgLowStkrgValue_ = ParkerVanGenuchten3P::krg(krgLowSte_, *baseLawParamsPtr_); + krgDerivativeLowSt_ = ParkerVanGenuchten3P::dkrg_dste(krgLowSte_, *baseLawParamsPtr_); + + swr_ = m->effToAbsParams().swr(); + sgr_ = m->effToAbsParams().sgr(); + } + + Scalar krgLowStkrgValue_; + Scalar krgDerivativeLowSt_; + + Scalar pcLowSwe_, pcHighSwe_; + Scalar krwHighSwe_, krnLowSwe_, krgLowSte_; + + // pcgw + Scalar pcgwLowSwePcgwValue_; + Scalar pcgwHighSwePcgwValue_; + Scalar pcgwDerivativeLowSw_; + Scalar pcgwDerivativeHighSweThreshold_; + Scalar pcgwDerivativeHighSweEnd_; + + // pcgn + Scalar pcgnLowStePcgnValue_; + Scalar pcgnHighSwePcgnValue_; + Scalar pcgnDerivativeLowSt_; + Scalar pcgnDerivativeHighSweThreshold_; + Scalar pcgnDerivativeHighSweEnd_; + + // pcnw + Scalar pcnwLowSwePcnwValue_; + Scalar pcnwHighSwePcnwValue_; + Scalar pcnwDerivativeLowSw_; + Scalar pcnwDerivativeHighSweThreshold_; + Scalar pcnwDerivativeHighSweEnd_; + + Spline pcgwSpline_; + Spline pcnwSpline_; + Spline pcgnSpline_; + Spline krwSpline_; + Spline krnSpline_; + + Scalar swr_, sgr_; + + bool constRegularization_; + + const BaseLawParams* baseLawParamsPtr_; +}; + +template +class ParkerVanGenuchtenMaterialLaw : public Adapter, ThreePhasePcKrSw> +{ +public: + + using Scalar = ScalarType; + + using BasicParams = typename BaseLaw::template Params; + using EffToAbsParams = typename EffToAbsPolicy::template Params; + using RegularizationParams = typename Regularization::template Params; + + using EffToAbs = EffToAbsPolicy; + + /*! + * \brief Return whether this law is regularized + */ + static constexpr bool isRegularized() + { return !std::is_same::value; } + + /*! + * \brief Deleted default constructor (so we are never in an undefined state) + * \note store owning pointers to laws instead if you need default-constructible objects + */ + ParkerVanGenuchtenMaterialLaw() = delete; + + /*! + * \brief Construct from a subgroup from the global parameter tree + * \note This will give you nice error messages if a mandatory parameter is missing + */ + explicit ParkerVanGenuchtenMaterialLaw(const std::string& paramGroup) + : basicParams_(makeBasicParams(paramGroup)) + , effToAbsParams_(makeEffToAbsParams(paramGroup)) + { + if constexpr (isRegularized()) + regularization_.init(this, paramGroup); + } + + /*! + * \brief Construct from parameter structs + * \note More efficient constructor but you need to ensure all parameters are initialized + */ + ParkerVanGenuchtenMaterialLaw(const BasicParams& baseParams, + const EffToAbsParams& effToAbsParams = {}, + const RegularizationParams& regParams = {}) + : basicParams_(baseParams) + , effToAbsParams_(effToAbsParams) + { + if constexpr (isRegularized()) + regularization_.init(this, baseParams, effToAbsParams, regParams); + } + + /*! + * \brief The capillary pressure-saturation curve for the gas and wetting phase + */ + template + Scalar pcgw(const Scalar sw, const Scalar /*dummySn*/) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.pcgw(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::pcgw(swe, basicParams_); + } + + /*! + * \brief The capillary pressure-saturation curve for the non-wetting and wetting phase + */ + template + Scalar pcnw(const Scalar sw, const Scalar /*dummySn*/) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.pcnw(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::pcnw(swe, basicParams_); + } + + /*! + * \brief The capillary pressure-saturation curve for the gas and non-wetting phase + * \param sw Wetting saturation + * \param sn Non-wetting saturation + */ + template + Scalar pcgn(const Scalar sw, const Scalar sn) const + { + const auto swe = EffToAbs::swToSwe(sw + sn, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.pcgn(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::pcgn(swe, basicParams_); + } + + /*! + * \brief This function ensures a continuous transition from 2 to 3 phases and vice versa + */ + template + Scalar pcAlpha(const Scalar /*dummySw*/, const Scalar sn) const + { + const auto sne = EffToAbs::snToSne(sn, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.pcAlpha(sne); + if (regularized) + return regularized.value(); + } + return BaseLaw::pcAlpha(sne, basicParams_); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + template + Scalar dpcgw_dsw(const Scalar sw, const Scalar /*dummyS*/) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dpcgw_dswe(swe); + if (regularized) + return regularized.value()*EffToAbs::dswe_dsw(effToAbsParams_); + } + + return BaseLaw::dpcgw_dswe(swe, basicParams_)*EffToAbs::dswe_dsw(effToAbsParams_); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + template + Scalar dpcnw_dsw(const Scalar sw, const Scalar /*dummySw*/) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dpcnw_dswe(swe); + if (regularized) + return regularized.value()*EffToAbs::dswe_dsw(effToAbsParams_); + } + + return BaseLaw::dpcnw_dswe(swe, basicParams_)*EffToAbs::dswe_dsw(effToAbsParams_); + } + + /*! + * \brief The partial derivative of the capillary pressure w.r.t. the saturation + */ + template + Scalar dpcgn_dst(const Scalar st, const Scalar /*dummySw*/) const + { + const auto ste = EffToAbs::stToSte(st, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dpcgn_dste(ste); + if (regularized) + return regularized.value()*EffToAbs::dswte_dst(effToAbsParams_); + } + + return BaseLaw::dpcgn_dste(ste, basicParams_)*EffToAbs::dste_dst(effToAbsParams_); + } + + /*! + * \brief The relative permeability for the wetting phase + * \param sw Wetting saturation + * \param sn Non-wetting saturation + */ + template + Scalar krw(const Scalar sw, const Scalar sn) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.krw(swe); + if (regularized) + return regularized.value(); + } + + return BaseLaw::krw(swe, basicParams_); + } + + /*! + * \brief The relative permeability for the non-wetting phase + * \param sw Wetting saturation + * \param sn Non-wetting saturation + */ + template + Scalar krn(const Scalar sw, const Scalar sn) const + { + const auto swe = EffToAbs::swToSwe(sw, effToAbsParams_); + const auto ste = EffToAbs::stToSte(sw + sn, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.krn(swe, sn, ste); + if (regularized) + return regularized.value(); + } + + return BaseLaw::krn(swe, sn, ste, basicParams_); + } + + /*! + * \brief The relative permeability for the non-wetting phase + * \param sw Wetting saturation + * \param sn Non-wetting saturation + */ + template + Scalar krg(const Scalar sw, const Scalar sn) const + { + const auto ste = EffToAbs::stToSte(sw + sn, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.krg(ste); + if (regularized) + return regularized.value(); + } + + return BaseLaw::krg(ste, basicParams_); + } + + /*! + * \brief The relative permeability for the non-wetting phase + * \param phaseIdx Indicator, The saturation of all phases. + * \param sw Wetting saturation + * \param sn Non-wetting saturation + */ + template + Scalar kr(const int phaseIdx, const Scalar sw, const Scalar sn) const + { + switch (phaseIdx) + { + case 0: + return krw(sw, sn); + case 1: + return krn(sw, sn); + case 2: + return krg(sw, sn); + } + DUNE_THROW(Dune::InvalidStateException, + "Invalid phase index "); + } + + /*! + * \brief The derivative of the relative permeability for the non-wetting phase w.r.t. saturation + * \param st Total (wetting + non-wetting) saturation + */ + template + Scalar dkrg_dst(const Scalar st) const + { + const auto ste = EffToAbs::stToSte(st, effToAbsParams_); + if constexpr (enableRegularization) + { + const auto regularized = regularization_.dkrg_dste(ste); + if (regularized) + return regularized.value()*EffToAbs::dste_dst(effToAbsParams_); + } + + return BaseLaw::dkrg_dste(ste, basicParams_)*EffToAbs::dste_dst(effToAbsParams_); + } + + /*! + * \brief Equality comparison with another instance + */ + bool operator== (const ParkerVanGenuchtenMaterialLaw& o) const + { + return basicParams_ == o.basicParams_ + && effToAbsParams_ == o.effToAbsParams_ + && regularization_ == o.regularization_; + } + + /*! + * \brief Create the base law's parameters using + * input file parameters + */ + static BasicParams makeBasicParams(const std::string& paramGroup) + { + return BaseLaw::template makeParams(paramGroup); + } + + /*! + * \brief Return the base law's parameters + */ + const BasicParams& basicParams() const + { return basicParams_; } + + /*! + * \brief Create the parameters of the EffToAbs policy using + * input file parameters + */ + static EffToAbsParams makeEffToAbsParams(const std::string& paramGroup) + { + return EffToAbs::template makeParams(paramGroup); + } + + /*! + * \brief Return the parameters of the EffToAbs policy + */ + const EffToAbsParams& effToAbsParams() const + { return effToAbsParams_; } + +private: + BasicParams basicParams_; + EffToAbsParams effToAbsParams_; + Regularization regularization_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A configuration for using the ParkerVanGenuchten material law without regularization + */ +template +using ParkerVanGenuchten3PNoReg = ParkerVanGenuchtenMaterialLaw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief A default configuration for using the ParkerVanGenuchten material law + */ +template +using ParkerVanGenuchten3PDefault = ParkerVanGenuchtenMaterialLaw, ParkerVanGenuchten3PEffToAbsPolicy>; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3p.hh b/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3p.hh index 231218d4d71cd27ec0705a99e02f69e8cd028981..95726acdda4208d74a52f69617933c3c727619e7 100644 --- a/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3p.hh +++ b/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3p.hh @@ -25,6 +25,8 @@ #ifndef REGULARIZED_PARKERVANGEN_3P_HH #define REGULARIZED_PARKERVANGEN_3P_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include #include "parkervangen3p.hh" diff --git a/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3pparams.hh b/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3pparams.hh index d9717cde8b1605fd896d4a4a8bce47564d6ce677..d83485540a602dad1f200257588afc6bae6fac18 100644 --- a/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3pparams.hh +++ b/dumux/material/fluidmatrixinteractions/3p/regularizedparkervangen3pparams.hh @@ -25,6 +25,8 @@ #ifndef DUMUX_REGULARIZED_PARKERVANGEN_3P_PARAMS_HH #define DUMUX_REGULARIZED_PARKERVANGEN_3P_PARAMS_HH +#warning "This header is deprecated. Removal after 3.3. Use new material laws." + #include "parkervangen3pparams.hh" namespace Dumux { diff --git a/dumux/material/fluidmatrixinteractions/CMakeLists.txt b/dumux/material/fluidmatrixinteractions/CMakeLists.txt index 1d9150947d95f2e230030bf0f186c99408677856..a91d616193b43dc98927c250c1ea6565de89e52f 100644 --- a/dumux/material/fluidmatrixinteractions/CMakeLists.txt +++ b/dumux/material/fluidmatrixinteractions/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(mp) install(FILES diffusivityconstanttortuosity.hh diffusivitymillingtonquirk.hh +fluidmatrixinteraction.hh permeabilitykozenycarman.hh porositydeformation.hh porosityprecipitation.hh diff --git a/dumux/material/fluidmatrixinteractions/fluidmatrixinteraction.hh b/dumux/material/fluidmatrixinteractions/fluidmatrixinteraction.hh new file mode 100644 index 0000000000000000000000000000000000000000..74abc3f422d8b2d12f60b8ccac5f3b241e6f223e --- /dev/null +++ b/dumux/material/fluidmatrixinteractions/fluidmatrixinteraction.hh @@ -0,0 +1,280 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type to combine an arbitrary number of different laws + * for fluid-matrix interaction (e.g., pc-Sw-curves). + */ +#ifndef DUMUX_MATERIAL_FLUIDMATRIX_INTERACTIONS_FLUIDMATRIX_INTERACTION_HH +#define DUMUX_MATERIAL_FLUIDMATRIX_INTERACTIONS_FLUIDMATRIX_INTERACTION_HH + +#include +#include + +namespace Dumux { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type to combine an arbitrary number of different laws + * for fluid-matrix interaction (e.g., pc-Sw-curves). + */ +template +struct FluidMatrixInteraction : public Laws... +{ + FluidMatrixInteraction(Laws&&... laws) : Laws(std::forward(laws))... {} +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Helper function to create an FluidMatrixInteraction object containing an arbitrary number + * of fluid matrix interaction laws (e.g., pc-Sw curves and interfacial area laws). + * To be used in the spatial parameters. + */ +template +auto makeFluidMatrixInteraction(Laws&&... laws) +{ + return FluidMatrixInteraction(wrap(std::forward(laws))...); +} + +} // end namespace Dumux + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Adapter to inherit from, allowing the inheriting class to be wrapped + * by the @ref makeFluidMatrixInteraction function. + */ +template class Wrapper> +struct Adapter +{ + template>, int> = 0> + friend auto wrap(T&& t) { return Wrapper(std::forward(t)); } +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for laws providing pc-Sw and kr-Sw rules. + */ +template +class PcKrSw +{ +public: + using Scalar = typename std::decay_t::Scalar; + + using PcKrSwType = const T; + + PcKrSw(T&& impl) : impl_(std::forward(impl)) {} + + Scalar pc(const Scalar sw) const { return impl_.pc(sw); } + Scalar dpc_dsw(const Scalar sw) const { return impl_.dpc_dsw(sw); } + Scalar endPointPc() const { return impl_.endPointPc(); } + Scalar sw(const Scalar pc) const { return impl_.sw(pc); } + Scalar dsw_dpc(const Scalar pc) const { return impl_.dsw_dpc(pc); } + Scalar krw(const Scalar sw) const { return impl_.krw(sw); } + Scalar dkrw_dsw(const Scalar sw) const { return impl_.dkrw_dsw(sw); } + Scalar krn(const Scalar sw) const { return impl_.krn(sw); } + Scalar dkrn_dsw(const Scalar sw) const { return impl_.dkrn_dsw(sw); } + + const T& pcSwCurve() const { return impl_; } + const T& krSwCurve() const { return impl_; } + +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the PcKrSw class. + * Makes sure that PcKrSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +PcKrSw(T&&) -> PcKrSw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for multiphase interface laws providing pc-S and kr-S rules. + */ +template +class MultiPhasePcKrSw +{ +public: + using Scalar = typename std::decay_t::Scalar; + + MultiPhasePcKrSw(T&& impl) : impl_(std::forward(impl)) {} + + template + auto capillaryPressures(const FS& fs, int wp) const { return impl_.capillaryPressures(fs, wp); } + template + auto relativePermeabilities(const FS& fs, int wp) const { return impl_.relativePermeabilities(fs, wp); } + + const T& multiPhasePcKrS() const { return impl_; } + +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the MultiPhasePcKrSw class. + * Makes sure that MultiPhasePcKrSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +MultiPhasePcKrSw(T&&) -> MultiPhasePcKrSw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for 3p interface laws providing pc-S and kr-S rules. + */ +template +struct ThreePhasePcKrSw +{ + using Scalar = typename std::decay_t::Scalar; + using value_type = const T; + + using PcKrSwType = const T; + + ThreePhasePcKrSw(T&& impl) : impl_(std::forward(impl)) {} + + Scalar pcgw(const Scalar sw, const Scalar sn) const { return impl_.pcgw(sw, sn); } + Scalar pcnw(const Scalar sw, const Scalar sn) const { return impl_.pcnw(sw, sn); } + Scalar pcgn(const Scalar sw, const Scalar sn) const { return impl_.pcgn(sw, sn); } + Scalar pcAlpha(const Scalar sw, const Scalar sn) const { return impl_.pcAlpha(sw, sn); } + + Scalar krw(const Scalar sw, const Scalar sn) const { return impl_.krw(sw, sn); } + Scalar krn(const Scalar sw, const Scalar sn) const { return impl_.krn(sw, sn); } + Scalar krg(const Scalar sw, const Scalar sn) const { return impl_.krn(sw, sn); } + Scalar kr(const int phaseIdx, const Scalar sw, const Scalar sn) const { return impl_.kr(phaseIdx, sw, sn); } + + const T& pcSwCurve() const { return impl_; } + const T& krSwCurve() const { return impl_; } +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the ThreePhasePcKrSw class. + * Makes sure that ThreePhasePcKrSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +ThreePhasePcKrSw(T&&) -> ThreePhasePcKrSw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for laws providing rules for the wetting-nonwetting interfacial area. + */ +template +class WettingNonwettingInterfacialAreaPcSw +{ +public: + WettingNonwettingInterfacialAreaPcSw(T&& impl) : impl_(std::forward(impl)) {} + const T& wettingNonwettingInterface() const { return impl_; } +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the WettingNonwettingInterfacialAreaPcSw class. + * Makes sure that WettingNonwettingInterfacialAreaPcSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +WettingNonwettingInterfacialAreaPcSw(T&&) -> WettingNonwettingInterfacialAreaPcSw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for laws providing rules for the wetting-solid interfacial area. + */ +template +class WettingSolidInterfacialAreaPcSw +{ +public: + WettingSolidInterfacialAreaPcSw(T&& impl) : impl_(std::forward(impl)) {} + const T& wettingSolidInterface() const { return impl_; } +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the WettingSolidInterfacialAreaPcSw class. + * Makes sure that WettingSolidInterfacialAreaPcSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +WettingSolidInterfacialAreaPcSw(T&&) -> WettingSolidInterfacialAreaPcSw; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for laws providing rules for the nonwetting-solid interfacial area. + */ +template +class NonwettingSolidInterfacialAreaPcSw +{ +public: + NonwettingSolidInterfacialAreaPcSw(T&& impl) : impl_(std::forward(impl)) {} + const T& nonwettingSolidInterface() const { return impl_; } +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the NonwettingSolidInterfacialAreaPcSw class. + * Makes sure that NonwettingSolidInterfacialAreaPcSw stores a copy of T if + * the constructor is called with a temporary object. + */ +template +NonwettingSolidInterfacialAreaPcSw(T&&) -> NonwettingSolidInterfacialAreaPcSw; + + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Wrapper type for adsorption laws. + */ +template +class Adsorption +{ +public: + using value_type = T; + + Adsorption(T&& impl) : impl_(std::forward(impl)) {} + const T& adsorptionModel() const { return impl_; } +private: + const T impl_; +}; + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Deduction guide for the Adsorption class. + * Makes sure that Adsorption stores a copy of T if + * the constructor is called with a temporary object. + */ +template +Adsorption(T&&) -> Adsorption; + +} // end namespace Dumux::FluidMatrix + +#endif diff --git a/dumux/material/fluidmatrixinteractions/mp/mpadapter.hh b/dumux/material/fluidmatrixinteractions/mp/mpadapter.hh index 7176f552b32313068ecee6496c82132d064561e0..bb3b4a2c9aa42a940ceefb28d9c582ba68e74a68 100644 --- a/dumux/material/fluidmatrixinteractions/mp/mpadapter.hh +++ b/dumux/material/fluidmatrixinteractions/mp/mpadapter.hh @@ -27,24 +27,27 @@ #ifndef DUMUX_MP_ADAPTER_HH #define DUMUX_MP_ADAPTER_HH +// remove from here after release 3.3 ///////////// + #include #include #include namespace Dumux { + /*! * \ingroup Fluidmatrixinteractions * \brief An adapter for mpnc to use the capillary pressure-saturation relationships */ -template +template class MPAdapter { static_assert(AlwaysFalse::value, "Adapter not implemented for the specified number of phases"); }; template -class MPAdapter +class [[deprecated("Use new material laws and FluidMatrix::MPAdapter instead!")]] MPAdapter { public: using Params = typename MaterialLaw::Params; @@ -88,6 +91,80 @@ public: values[nPhaseIdx] = MaterialLaw::krn(params, state.saturation(wPhaseIdx)); } }; + + } // end namespace Dumux +// remove until here after release 3.3 ///////////// + +#include +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief An adapter for mpnc to use the capillary pressure-saturation relationships + */ +template +class MPAdapter +{ + static_assert(AlwaysFalse::value, "Adapter not implemented for the specified number of phases"); +}; + + +template +class MPAdapter +: public Adapter, MultiPhasePcKrSw> +{ +public: + using Scalar = typename MaterialLaw::Scalar; + + MPAdapter(const MaterialLaw& pcKrS) + : pcKrS_(pcKrS) + {} + + /*! + * \brief The capillary pressure-saturation curve. + * \param state Fluidstate + * \param wPhaseIdx the phase index of the wetting phase + */ + template + auto capillaryPressures(const FluidState& state, int wPhaseIdx) const + { + Dune::FieldVector values; + + const int nPhaseIdx = 1 - wPhaseIdx; + // non-wetting phase gets the capillary pressure added + values[nPhaseIdx] = 0; + // wetting phase does not get anything added + values[wPhaseIdx] = - pcKrS_.pc(state.saturation(wPhaseIdx)); + + return values; + } + + /*! + * \brief The relative permeability of all phases. + * \param state Fluidstate + * \param wPhaseIdx The phase index of the wetting phase + */ + template + auto relativePermeabilities(const FluidState& state, int wPhaseIdx) const + { + Dune::FieldVector values; + + const int nPhaseIdx = 1 - wPhaseIdx; + values[wPhaseIdx] = pcKrS_.krw(state.saturation(wPhaseIdx)); + values[nPhaseIdx] = pcKrS_.krn(state.saturation(wPhaseIdx)); + + return values; + } +private: + const MaterialLaw& pcKrS_; +}; + +} // end namespace Dumux::FluidMatrix + + #endif diff --git a/dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh b/dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh index e5bb06f603fda29c5b6071091544b532cfa8f19d..09f59be9769706a0984769c6df5f631cf41d14b7 100644 --- a/dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh +++ b/dumux/material/fluidmatrixinteractions/mp/mplinearmaterial.hh @@ -43,7 +43,7 @@ namespace Dumux { * \sa MpLinearMaterialParams */ template > -class MpLinearMaterial +class [[deprecated("Use FluidMatrix::MPLinearMaterial. Will be removed after 3.3")]] MpLinearMaterial { public: using Params = ParamsT; @@ -97,4 +97,89 @@ public: }; } // end namespace Dumux +#include +#include + +namespace Dumux::FluidMatrix { + +/*! + * \ingroup Fluidmatrixinteractions + * \brief Implements a linear saturation-capillary pressure relation + * + * Implements a linear saturation-capillary pressure relation for + * M-phase fluid systems. + * + */ +template +class MPLinearMaterial +: public Adapter, MultiPhasePcKrSw> +{ + struct Params + { + Params(const std::array& pcMaxSat, + const std::array& pcMinSat) + : pcMaxSat_(pcMaxSat), pcMinSat_(pcMinSat) {} + + S pcMaxSat(int phaseIdx) const { return pcMaxSat_[phaseIdx]; } + S pcMinSat(int phaseIdx) const { return pcMinSat_[phaseIdx]; } + private: + std::array pcMaxSat_; + std::array pcMinSat_; + }; + +public: + using BasicParams = Params; + using Scalar = S; + + MPLinearMaterial(const BasicParams& basicParams) + : basicParams_(basicParams) + {} + + /*! + * \brief The linear capillary pressure-saturation curve. + * + * This material law is linear: + * \f[ + p_C = (1 - \overline{S}_w) (p_{C,max} - p_{C,entry}) + p_{C,entry} + \f] + * + * \param state The fluid state + * \param wPhaseIdx The phase index of the wetting phase + */ + template + auto capillaryPressures(const FluidState& state, int wPhaseIdx = 0) const + { + static_assert(FluidState::numPhases == numFluidPhases, "FluidState doesn't match the number of fluid phases!"); + Dune::FieldVector values; + for (int phaseIdx = 0; phaseIdx < numFluidPhases; ++phaseIdx) + { + const Scalar saturation = state.saturation(phaseIdx); + values[phaseIdx] = + saturation*basicParams_.pcMaxSat(phaseIdx) + + (1 - saturation)*basicParams_.pcMinSat(phaseIdx); + } + return values; + } + + /*! + * \brief The relative permeability of all phases. + * \param state The fluid state + * \param wPhaseIdx The phase index of the wetting phase + */ + template + auto relativePermeabilities(const FluidState& state, int wPhaseIdx = 0) const + { + static_assert(FluidState::numPhases == numFluidPhases, "FluidState doesn't match the number of fluid phases!"); + using std::clamp; + Dune::FieldVector values; + for (int phaseIdx = 0; phaseIdx < FluidState::numPhases; ++phaseIdx) + values[phaseIdx] = clamp(state.saturation(phaseIdx), 0.0, 1.0); + return values; + } +private: + BasicParams basicParams_; +}; + +} // end namespace Dumux::FluidMatrix + #endif diff --git a/dumux/material/fluidmatrixinteractions/mp/mplinearmaterialparams.hh b/dumux/material/fluidmatrixinteractions/mp/mplinearmaterialparams.hh index 6a4477f651b5b2c25c19cbba439c7df813d7d0a8..2d12172450962947eeddfcacca4e7247221d2e95 100644 --- a/dumux/material/fluidmatrixinteractions/mp/mplinearmaterialparams.hh +++ b/dumux/material/fluidmatrixinteractions/mp/mplinearmaterialparams.hh @@ -39,6 +39,7 @@ public: using Scalar = ScalarT; enum { numPhases = numPhasesV }; + [[deprecated("Use FluidMatrix::MPLinearMaterial. Class will be removed after 3.3.")]] MpLinearMaterialParams() { for (int i = 0; i < numPhases; ++i) { diff --git a/dumux/material/spatialparams/fv.hh b/dumux/material/spatialparams/fv.hh index 4fb8c097b5c9340fd975218cf9086151f4044dc3..655061380f02ab87e5b2b3e36c49d5bf6c23de73 100644 --- a/dumux/material/spatialparams/fv.hh +++ b/dumux/material/spatialparams/fv.hh @@ -68,6 +68,16 @@ public: : ParentType(gridGeometry) {} + // make sure we get a deprecation warning (remove this after release 3.3) + template + [[deprecated("Use the new style material laws. Old material laws and this interface will no longer be supported after release 3.3")]] + decltype(auto) materialLawParamsDeprecated(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + return this->asImp_().materialLawParams(element, scv, elemSol); + } + /*! * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). * @@ -77,6 +87,7 @@ public: * \return the material parameters object */ template + [[deprecated("Use the new style material laws. Old material laws and this interface will no longer be supported after release 3.3")]] decltype(auto) materialLawParams(const Element& element, const SubControlVolume& scv, const ElementSolution& elemSol) const diff --git a/dumux/material/spatialparams/sequentialfv.hh b/dumux/material/spatialparams/sequentialfv.hh index d491465768e7b5eb21571afec331a747a15a9a1e..4dedf42b25ee408d3a8e40af21634372bcc84a39 100644 --- a/dumux/material/spatialparams/sequentialfv.hh +++ b/dumux/material/spatialparams/sequentialfv.hh @@ -53,9 +53,6 @@ class SequentialFVSpatialParams: public SequentialFVSpatialParamsOneP using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - /// @cond false - using MaterialLawParams = typename GetPropType::Params; - /// @endcond public: SequentialFVSpatialParams(const Problem& problem) @@ -63,15 +60,26 @@ public: { } + + // make sure we get a deprecation warning (remove this after release 3.3) + template + [[deprecated("Use the new style material laws. Old material laws and this interface will no longer be supported after release 3.3")]] + decltype(auto) materialLawParamsDeprecated(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + return this->asImp_().materialLawParams(element); + } + /*! * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). * * \return the material parameters object * \param element The element */ - const MaterialLawParams& materialLawParams(const Element &element) const + const auto& materialLawParams(const Element &element) const { - return asImp_().materialLawParamsAtPos(element.geometry().center()); + return asImp_().materialLawParamsAtPos(element.geometry().center()); } /*! @@ -80,7 +88,7 @@ public: * \return the material parameters object * \param globalPos The position of the center of the element */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + const auto& materialLawParamsAtPos(const GlobalPosition& globalPos) const { DUNE_THROW(Dune::InvalidStateException, "The spatial parameters do not provide " diff --git a/dumux/porousmediumflow/2p/CMakeLists.txt b/dumux/porousmediumflow/2p/CMakeLists.txt index 5497ae6e4ce11efe7f922c1305264005299823e9..d7847edce06c9478d83dce41a0f7b323483704ff 100644 --- a/dumux/porousmediumflow/2p/CMakeLists.txt +++ b/dumux/porousmediumflow/2p/CMakeLists.txt @@ -1,7 +1,7 @@ add_subdirectory(sequential) install(FILES -boxmaterialinterfaceparams.hh +boxmaterialinterfaces.hh formulation.hh gridadaptindicator.hh griddatatransfer.hh diff --git a/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh b/dumux/porousmediumflow/2p/boxmaterialinterfaces.hh similarity index 66% rename from dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh rename to dumux/porousmediumflow/2p/boxmaterialinterfaces.hh index 5dcb9055d4709a45a61b3f4f123f9802c5779b2b..ab1e84f16d76ac5c3a0fc3f1abe2860062100b80 100644 --- a/dumux/porousmediumflow/2p/boxmaterialinterfaceparams.hh +++ b/dumux/porousmediumflow/2p/boxmaterialinterfaces.hh @@ -19,11 +19,11 @@ /*! * \file * \ingroup TwoPModel - * \copydoc Dumux::BoxMaterialInterfaceParams + * \copydoc Dumux::BoxMaterialInterfaces */ -#ifndef DUMUX_2P_BOX_MATERIAL_INTERFACE_PARAMS_HH -#define DUMUX_2P_BOX_MATERIAL_INTERFACE_PARAMS_HH +#ifndef DUMUX_2P_BOX_MATERIAL_INTERFACES_HH +#define DUMUX_2P_BOX_MATERIAL_INTERFACES_HH #include @@ -42,11 +42,19 @@ namespace Dumux { * of freedom. On the basis of these parameters, the saturations in the * remaining sub-control volumes connected to the vertex can be reconstructed. */ -template -class BoxMaterialInterfaceParams +template +class BoxMaterialInterfaces { + using SubControlVolume = typename GridGeometry::SubControlVolume; + public: - using MaterialLawParams = typename SpatialParams::MaterialLaw::Params; + template + BoxMaterialInterfaces(const GridGeometry& gridGeometry, + const SpatialParams& spatialParams, + const SolutionVector& x) + { + update(gridGeometry, spatialParams, x); + } /*! * \brief Updates the scv -> dofparameter map @@ -55,30 +63,18 @@ public: * \param spatialParams Class encapsulating the spatial parameters * \param x The current state of the solution vector */ - template + template void update(const GridGeometry& gridGeometry, const SpatialParams& spatialParams, const SolutionVector& x) { - using MaterialLaw = typename SpatialParams::MaterialLaw; - - // Make sure the spatial params return a const ref and no copy! - using Elem = typename GridGeometry::GridView::template Codim<0>::Entity; - using ElemSol = decltype( elementSolution(Elem(), x, gridGeometry) ); - using Scv = typename GridGeometry::SubControlVolume; - using ReturnType = decltype(spatialParams.materialLawParams(Elem(), Scv(), ElemSol())); - static_assert(std::is_lvalue_reference::value, - "In order to use the box-interface solver please provide access " - "to the material law parameters via returning (const) references"); - // make sure this is only called for geometries of the box method! if (GridGeometry::discMethod != DiscretizationMethod::box) DUNE_THROW(Dune::InvalidStateException, "Determination of the interface material parameters with " "this class only makes sense when using the box method!"); - isUpdated_ = true; isOnMaterialInterface_.resize(gridGeometry.numDofs(), false); - dofParams_.resize(gridGeometry.numDofs(), nullptr); + pcSwAtDof_.resize(gridGeometry.numDofs(), nullptr); for (const auto& element : elements(gridGeometry.gridView())) { const auto elemSol = elementSolution(element, x, gridGeometry); @@ -87,40 +83,43 @@ public: fvGeometry.bind(element); for (const auto& scv : scvs(fvGeometry)) { - const auto& params = spatialParams.materialLawParams(element, scv, elemSol); + const auto fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + const auto& pcKrSw = fluidMatrixInteraction.pcSwCurve(); + + // assert current preconditions on requiring the spatial params to store the pckrSw curve + static_assert(std::is_lvalue_reference::PcKrSwType>::value, + "In order to use the box-interface solver please provide access " + "to the material law parameters via returning (const) references"); // if no parameters had been set, set them now - if (dofParams_[scv.dofIndex()] == nullptr) - dofParams_[scv.dofIndex()] = ¶ms; + if (!pcSwAtDof_[scv.dofIndex()]) + pcSwAtDof_[scv.dofIndex()] = &pcKrSw; // otherwise only use the current ones if endPointPc (e.g. Brooks-Corey entry pressure) is lower - else if (MaterialLaw::endPointPc( params ) < MaterialLaw::endPointPc( *(dofParams_[scv.dofIndex()]) )) + else if (pcKrSw.endPointPc() < pcSwAtDof_[scv.dofIndex()]->endPointPc()) { - dofParams_[scv.dofIndex()] = ¶ms; + pcSwAtDof_[scv.dofIndex()] = &pcKrSw; isOnMaterialInterface_[scv.dofIndex()] = true; } // keep track of material interfaces in any case - else if ( !(params == *(dofParams_[scv.dofIndex()])) ) + else if ( !(pcKrSw == *(pcSwAtDof_[scv.dofIndex()])) ) isOnMaterialInterface_[scv.dofIndex()] = true; } } } //! Returns if this scv is connected to a material interface - template - bool isOnMaterialInterface(const Scv& scv) const - { assert(isUpdated_); return isOnMaterialInterface_[scv.dofIndex()]; } + bool isOnMaterialInterface(const SubControlVolume& scv) const + { return isOnMaterialInterface_[scv.dofIndex()]; } //! Returns the material parameters associated with the dof - template - const MaterialLawParams& getDofParams(const Scv& scv) const - { assert(isUpdated_); return *(dofParams_[scv.dofIndex()]); } + const PcKrSw& pcSwAtDof(const SubControlVolume& scv) const + { return *(pcSwAtDof_[scv.dofIndex()]); } private: - bool isUpdated_{false}; std::vector isOnMaterialInterface_; - std::vector dofParams_; + std::vector pcSwAtDof_; }; } // end namespace Dumux diff --git a/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh b/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh index 5cd473eaf8bd5c6a6b9d924208d00932be7e3191..06779218e9ddad106957529fa7c294d7d32a55d6 100644 --- a/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh +++ b/dumux/porousmediumflow/2p/incompressiblelocalresidual.hh @@ -38,6 +38,8 @@ #include #include +#include + namespace Dumux { /*! @@ -169,7 +171,6 @@ public: static_assert(ModelTraits::priVarFormulation() == TwoPFormulation::p0s1, "2p/incompressiblelocalresidual.hh: Analytic differentiation has to be checked for p1-s0 formulation!"); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; using AdvectionType = GetPropType; // evaluate the current wetting phase Darcy flux and resulting upwind weights @@ -189,12 +190,23 @@ public: const auto& outsideScv = fvGeometry.scv(outsideScvIdx); const auto& insideVolVars = curElemVolVars[insideScvIdx]; const auto& outsideVolVars = curElemVolVars[outsideScvIdx]; - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, - insideScv, - elementSolution(insideVolVars.priVars())); - const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(outsideElement, - outsideScv, - elementSolution(outsideVolVars.priVars())); + + // old material law interface is deprecated: Replace this by + // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, + // insideScv, + // elementSolution(insideVolVars.priVars())); + // const auto& outsidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(outsideElement, + // outsideScv, + // elementSolution(outsideVolVars.priVars())); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + element, + insideScv, + elementSolution(insideVolVars.priVars())); + const auto& outsidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + outsideElement, + outsideScv, + elementSolution(outsideVolVars.priVars())); // get references to the two participating derivative matrices auto& dI_dI = derivativeMatrices[insideScvIdx]; @@ -213,12 +225,12 @@ public: // derivative w.r.t. to Sn is the negative of the one w.r.t. Sw const auto insideSw = insideVolVars.saturation(0); const auto outsideSw = outsideVolVars.saturation(0); - const auto dKrw_dSn_inside = -1.0*MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); - const auto dKrw_dSn_outside = -1.0*MaterialLaw::dkrw_dsw(outsideMaterialParams, outsideSw); - const auto dKrn_dSn_inside = -1.0*MaterialLaw::dkrn_dsw(insideMaterialParams, insideSw); - const auto dKrn_dSn_outside = -1.0*MaterialLaw::dkrn_dsw(outsideMaterialParams, outsideSw); - const auto dpc_dSn_inside = -1.0*MaterialLaw::dpc_dsw(insideMaterialParams, insideSw); - const auto dpc_dSn_outside = -1.0*MaterialLaw::dpc_dsw(outsideMaterialParams, outsideSw); + const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw); + const auto dKrw_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrw_dsw(outsideSw); + const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw); + const auto dKrn_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrn_dsw(outsideSw); + const auto dpc_dSn_inside = -1.0*insidefluidMatrixInteraction.dpc_dsw(insideSw); + const auto dpc_dSn_outside = -1.0*outsidefluidMatrixInteraction.dpc_dsw(outsideSw); const auto tij = elemFluxVarsCache[scvf].advectionTij(); @@ -288,7 +300,6 @@ public: static_assert(ModelTraits::priVarFormulation() == TwoPFormulation::p0s1, "2p/incompressiblelocalresidual.hh: Analytic differentiation has to be checked for p0-s1 formulation!"); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; using AdvectionType = GetPropType; // evaluate the current wetting phase Darcy flux and resulting upwind weights @@ -310,8 +321,22 @@ public: const auto elemSol = elementSolution(element, curElemVolVars, fvGeometry); - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, elemSol); - const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(element, outsideScv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, + // insideScv, + // elemSol); + // const auto& outsidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, + // outsideScv, + // elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + element, + insideScv, + elemSol); + const auto& outsidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + element, + outsideScv, + elemSol); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho_w = insideVolVars.density(0); @@ -366,19 +391,19 @@ public: { // partial derivative of the wetting phase flux w.r.t. S_n const auto insideSw = insideVolVars.saturation(0); - const auto dKrw_dSn_inside = -1.0*MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); + const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw); const auto dFluxW_dSnJ = rho_mu_flux_w*dKrw_dSn_inside*insideWeight_w; dI_dJ_inside[globalJ][conti0EqIdx+0][saturationIdx] += dFluxW_dSnJ; dI_dJ_outside[globalJ][conti0EqIdx+0][saturationIdx] -= dFluxW_dSnJ; // partial derivative of the nonwetting phase flux w.r.t. S_n (k_rn contribution) - const auto dKrn_dSn_inside = -1.0*MaterialLaw::dkrn_dsw(insideMaterialParams, insideSw); + const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw); const auto dFluxN_dSnJ_krn = rho_mu_flux_n*dKrn_dSn_inside*insideWeight_n; dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_krn; dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_krn; // partial derivative of the nonwetting phase flux w.r.t. S_n (p_c contribution) - const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*MaterialLaw::dpc_dsw(insideMaterialParams, insideSw); + const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*insidefluidMatrixInteraction.dpc_dsw(insideSw); dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc; dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc; } @@ -386,25 +411,34 @@ public: { // see comments for (globalJ == insideScvIdx) const auto outsideSw = outsideVolVars.saturation(0); - const auto dKrw_dSn_outside = -1.0*MaterialLaw::dkrw_dsw(outsideMaterialParams, outsideSw); + const auto dKrw_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrw_dsw(outsideSw); const auto dFluxW_dSnJ = rho_mu_flux_w*dKrw_dSn_outside*outsideWeight_w; dI_dJ_inside[globalJ][conti0EqIdx+0][saturationIdx] += dFluxW_dSnJ; dI_dJ_outside[globalJ][conti0EqIdx+0][saturationIdx] -= dFluxW_dSnJ; - const auto dKrn_dSn_outside = -1.0*MaterialLaw::dkrn_dsw(outsideMaterialParams, outsideSw); + const auto dKrn_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrn_dsw(outsideSw); const auto dFluxN_dSnJ_krn = rho_mu_flux_n*dKrn_dSn_outside*outsideWeight_n; dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_krn; dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_krn; - const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*MaterialLaw::dpc_dsw(outsideMaterialParams, outsideSw); + const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*outsidefluidMatrixInteraction.dpc_dsw(outsideSw); dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc; dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc; } else { - const auto& paramsJ = problem.spatialParams().materialLawParams(element, scvJ, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteractionJ = problem.spatialParams().fluidMatrixInteraction(element, + // scvJ, + // elemSol); + + // after the release of 3.3, when the deprecated interface is no longer supported + const auto& fluidMatrixInteractionJ = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + element, + scvJ, + elemSol); const auto swJ = curElemVolVars[scvJ].saturation(0); - const auto dFluxN_dSnJ_pc = tj_up_n*MaterialLaw::dpc_dsw(paramsJ, swJ); + const auto dFluxN_dSnJ_pc = tj_up_n*fluidMatrixInteractionJ.dpc_dsw(swJ); dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc; dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc; } @@ -434,7 +468,6 @@ public: const ElementFluxVariablesCache& elemFluxVarsCache, const SubControlVolumeFace& scvf) const { - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; using AdvectionType = GetPropType; // evaluate the current wetting phase Darcy flux and resulting upwind weights @@ -451,9 +484,16 @@ public: const auto& insideScv = fvGeometry.scv(insideScvIdx); const auto& insideVolVars = curElemVolVars[insideScvIdx]; const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()]; - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, - insideScv, - elementSolution(insideVolVars.priVars())); + + // old material law interface is deprecated: Replace this by + // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, + // insideScv, + // elementSolution(insideVolVars.priVars())); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), + element, + insideScv, + elementSolution(insideVolVars.priVars())); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho_w = insideVolVars.density(0); @@ -470,9 +510,9 @@ public: // derivative w.r.t. to Sn is the negative of the one w.r.t. Sw const auto insideSw = insideVolVars.saturation(0); - const auto dKrw_dSn_inside = -1.0*MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); - const auto dKrn_dSn_inside = -1.0*MaterialLaw::dkrn_dsw(insideMaterialParams, insideSw); - const auto dpc_dSn_inside = -1.0*MaterialLaw::dpc_dsw(insideMaterialParams, insideSw); + const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw); + const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw); + const auto dpc_dSn_inside = -1.0*insidefluidMatrixInteraction.dpc_dsw(insideSw); const auto tij = elemFluxVarsCache[scvf].advectionTij(); // partial derivative of the wetting phase flux w.r.t. p_w diff --git a/dumux/porousmediumflow/2p/saturationreconstruction.hh b/dumux/porousmediumflow/2p/saturationreconstruction.hh index ef2b49216b8910920fc42998a8cf9aad6c75d017..7a94627486ff4d541f523e2db2b43e3b367cb472 100644 --- a/dumux/porousmediumflow/2p/saturationreconstruction.hh +++ b/dumux/porousmediumflow/2p/saturationreconstruction.hh @@ -53,7 +53,7 @@ public: * \param element The finite element the scv is embedded in * \param scv The sub-control volume for which the saturation is computed * \param elemSol The solution at all dofs inside this element - * \param Sn The nonwetting phase saturation at the global dof + * \param sn The nonwetting phase saturation at the global dof */ template static typename ElemSol::PrimaryVariables::value_type @@ -61,8 +61,8 @@ public: const Element& element, const Scv& scv, const ElemSol& elemSol, - typename ElemSol::PrimaryVariables::value_type Sn) - { return Sn; } + typename ElemSol::PrimaryVariables::value_type sn) + { return sn; } }; //! Specialization for the box scheme with the interface solver enabled @@ -77,7 +77,7 @@ public: * \param element The finite element the scv is embedded in * \param scv The sub-control volume for which the saturation is computed * \param elemSol The solution at all dofs inside this element - * \param Sn The nonwetting phase saturation at the global dof + * \param sn The nonwetting phase saturation at the global dof */ template static typename ElemSol::PrimaryVariables::value_type @@ -85,23 +85,25 @@ public: const Element& element, const Scv& scv, const ElemSol& elemSol, - typename ElemSol::PrimaryVariables::value_type Sn) + typename ElemSol::PrimaryVariables::value_type sn) { // if this dof doesn't lie on a material interface, simply return Sn - if (!spatialParams.materialInterfaceParams().isOnMaterialInterface(scv)) - return Sn; + const auto& materialInterfaces = spatialParams.materialInterfaces(); + if (!materialInterfaces.isOnMaterialInterface(scv)) + return sn; - using MaterialLaw = typename SpatialParams::MaterialLaw; // compute capillary pressure using material parameters associated with the dof - const auto& ifMaterialParams = spatialParams.materialInterfaceParams().getDofParams(scv); - const auto pc = MaterialLaw::pc(ifMaterialParams, /*Sw=*/1.0 - Sn); + const auto& interfacePcSw = materialInterfaces.pcSwAtDof(scv); + const auto pc = interfacePcSw.pc(/*ww=*/1.0 - sn); // reconstruct by inverting the pc-sw curve - const auto& materialLawParams = spatialParams.materialLawParams(element, scv, elemSol); - const auto pcMin = MaterialLaw::endPointPc(materialLawParams); + const auto& pcSw = spatialParams.fluidMatrixInteraction(element, scv, elemSol).pcSwCurve(); + const auto pcMin = pcSw.endPointPc(); - if (pc < pcMin && pcMin > 0.0) return 0.0; - else return 1.0 - MaterialLaw::sw(materialLawParams, pc); + if (pc < pcMin && pcMin > 0.0) + return 0.0; + else + return 1.0 - pcSw.sw(pc); } }; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/pressure.hh b/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/pressure.hh index b3c867d583c0c7d89d84a99be1e052885c4360fc..d68266be0dd9f4f526314c3563c1c2179a337f93 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/pressure.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/pressure.hh @@ -30,6 +30,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -121,7 +123,6 @@ template class FVPressure2P: public FVPressure using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -920,13 +921,20 @@ const Intersection& intersection, const CellData& cellData, const bool first) satW = cellData.saturation(wPhaseIdx); satNw = cellData.saturation(nPhaseIdx); } - Scalar temperature = problem_.temperature(element); + + const Scalar temperature = problem_.temperature(element); // get Dirichlet pressure boundary condition - Scalar pressBound = boundValues[pressureIdx]; + const Scalar pressBound = boundValues[pressureIdx]; //calculate constitutive relations depending on the kind of saturation used - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); // determine phase pressures from primary pressure variable Scalar pressW = 0; @@ -967,9 +975,9 @@ const Intersection& intersection, const CellData& cellData, const bool first) rhoMeanNw = 0.5 * (cellData.density(nPhaseIdx) + densityNwBound); } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) + Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosityWBound; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) + Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosityNwBound; Scalar fractionalWBound = lambdaWBound / (lambdaWBound + lambdaNwBound); @@ -1095,13 +1103,17 @@ void FVPressure2P::updateMaterialLaws() CellData& cellData = problem_.variables().cellData(eIdxGlobal); - Scalar temperature = problem_.temperature(element); + const Scalar temperature = problem_.temperature(element); // determine phase saturations from primary saturation variable + const Scalar satW = cellData.saturation(wPhaseIdx); - Scalar satW = cellData.saturation(wPhaseIdx); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pc = fluidMatrixInteraction.pc(satW); // determine phase pressures from primary pressure variable Scalar pressW = 0; @@ -1151,8 +1163,8 @@ void FVPressure2P::updateMaterialLaws() } // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) / viscosity_[nPhaseIdx]; + Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; if (compressibility_) { @@ -1168,7 +1180,7 @@ void FVPressure2P::updateMaterialLaws() cellData.setFracFlowFunc(wPhaseIdx, mobilityW / (mobilityW + mobilityNw)); cellData.setFracFlowFunc(nPhaseIdx, mobilityNw / (mobilityW + mobilityNw)); - Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_; + const Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_; Scalar potW = pressW + gravityDiff * density_[wPhaseIdx]; Scalar potNw = pressNw + gravityDiff * density_[nPhaseIdx]; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/velocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/velocity.hh index 7bd5b3f8a91f16168cdb849d798b47d1e6d6e00b..337358c6c6f33278bf7ff94b098bf2f28bcf0234 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/velocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/cellcentered/velocity.hh @@ -28,6 +28,8 @@ #include #include +#include + namespace Dumux { /*! @@ -64,7 +66,6 @@ class FVVelocity2P using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -564,8 +565,14 @@ void FVVelocity2P::calculateVelocityOnBoundary(const Intersection& inte satNw = cellData.saturation(nPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); // determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -582,7 +589,7 @@ void FVVelocity2P::calculateVelocityOnBoundary(const Intersection& inte } // get temperature at current position - Scalar temperature = problem_.temperature(element); + const Scalar temperature = problem_.temperature(element); Scalar densityWBound = density_[wPhaseIdx]; Scalar densityNwBound = density_[nPhaseIdx]; @@ -604,9 +611,9 @@ void FVVelocity2P::calculateVelocityOnBoundary(const Intersection& inte viscosityNwBound = FluidSystem::viscosity(fluidState, nPhaseIdx) / densityNwBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) + Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosityWBound; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) + Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosityNwBound; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); @@ -657,7 +664,7 @@ void FVVelocity2P::calculateVelocityOnBoundary(const Intersection& inte (Dune::FloatCmp::eq(potentialDiffNw, 0.0, 1.0e-30)) ? 0.5 * (cellData.density(nPhaseIdx) + densityNwBound) : density_[nPhaseIdx]; } - Scalar scalarPerm = permeability.two_norm(); + const Scalar scalarPerm = permeability.two_norm(); // calculate the gravity term Dune::FieldVector velocityW(unitOuterNormal); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimetic.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimetic.hh index 4056d8f7037d01fdc636e8861de5cb6f1de78edf..c457759256f595f77e1e09749bd0a8cabe030d70 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimetic.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimetic.hh @@ -42,6 +42,8 @@ #include +#include + namespace Dumux { /*! @@ -96,7 +98,6 @@ class MimeticTwoPLocalStiffness: public LocalStiffness using CellData = GetPropType; using FluidSystem = GetPropType; using FluidState = GetPropType; - using MaterialLaw = GetPropType; public: // define the number of components of your system, this is used outside @@ -682,10 +683,13 @@ void MimeticTwoPLocalStiffness::assembleElementMatrices(const Element& PrimaryVariables boundValues(0.0); problem_.dirichlet(boundValues, intersection); - Scalar krw = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - boundValues[saturationIdx]); - Scalar krn = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), - boundValues[saturationIdx]); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar krw = fluidMatrixInteraction.krw(boundValues[saturationIdx]); + const Scalar krn = fluidMatrixInteraction.krn(boundValues[saturationIdx]); switch (pressureType) { diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimeticadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimeticadaptive.hh index 60585c6ccc2ff05c084c6718f1c64e829d5d1bb4..3de77fd91c467ff7daa0b5336997fbe5f46d15d7 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimeticadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/mimeticadaptive.hh @@ -44,6 +44,8 @@ #include #include +#include + namespace Dumux { /*! @@ -98,7 +100,6 @@ class MimeticTwoPLocalStiffnessAdaptive: public LocalStiffness using CellData = GetPropType; using FluidSystem = GetPropType; using FluidState = GetPropType; - using MaterialLaw = GetPropType; using IntersectionMapper = Dumux::IntersectionMapper; @@ -701,10 +702,13 @@ void MimeticTwoPLocalStiffnessAdaptive::assembleElementMatrices(const E PrimaryVariables boundValues(0.0); problem_.dirichlet(boundValues, intersection); - Scalar krw = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - boundValues[saturationIdx]); - Scalar krn = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), - boundValues[saturationIdx]); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar krw = fluidMatrixInteraction.krw(boundValues[saturationIdx]); + const Scalar krn = fluidMatrixInteraction.krn(boundValues[saturationIdx]); switch (pressureType) { diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operator.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operator.hh index ca84c4a800ac7d295890a0b0a7fcdc0d53bd6804..d4d10fbc0abd087601c6f664a809394d4d3a42e1 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operator.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operator.hh @@ -28,6 +28,8 @@ #include #include +#include + namespace Dumux { /*! @@ -57,7 +59,6 @@ class MimeticOperatorAssemblerTwoP: public CROperatorAssemblerTwoP using Element = typename GridView::template Codim<0>::Entity; using CellData = GetPropType; - using MaterialLaw = GetPropType; using FluidSystem = GetPropType; using FluidState = GetPropType; using BoundaryTypes = GetPropType; @@ -247,14 +248,18 @@ public: PrimaryVariables boundValues(0.0); problem.dirichlet(boundValues, intersection); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element); + if (velocityW[idxInInside] >= 0.) { mobilityW = cellData.mobility(wPhaseIdx); } else { - mobilityW = MaterialLaw::krw(problem.spatialParams().materialLawParams(element), - boundValues[saturationIdx]) / viscosityW; + mobilityW = fluidMatrixInteraction.krw(boundValues[saturationIdx]) / viscosityW; } if (velocityNw[idxInInside] >= 0.) @@ -263,8 +268,7 @@ public: } else { - mobilityNw = MaterialLaw::krn(problem.spatialParams().materialLawParams(element), - boundValues[saturationIdx]) / viscosityNw; + mobilityNw = fluidMatrixInteraction.krn(boundValues[saturationIdx]) / viscosityNw; } } else diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operatoradaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operatoradaptive.hh index d204e8af45dc7dc305dac41f949f733f8e5e715d..32135a2b63be61cdcd051e56b6a0fadb10e038bd 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operatoradaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/operatoradaptive.hh @@ -28,6 +28,8 @@ #include #include +#include + namespace Dumux { /*! @@ -59,7 +61,6 @@ class MimeticOperatorAssemblerTwoPAdaptive : public CROperatorAssemblerTwoPAdapt using Element = typename GridView::template Codim<0>::Entity; using CellData = GetPropType; - using MaterialLaw = GetPropType; using FluidSystem = GetPropType; using FluidState = GetPropType; using BoundaryTypes = GetPropType; @@ -255,14 +256,18 @@ public: PrimaryVariables boundValues(0.0); problem.dirichlet(boundValues, intersection); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element); + if (velocityW[intersectionIdx] >= 0.) { mobilityW = cellData.mobility(wPhaseIdx); } else { - mobilityW = MaterialLaw::krw(problem.spatialParams().materialLawParams(element), - boundValues[saturationIdx]) / viscosityW; + mobilityW = fluidMatrixInteraction.krw(boundValues[saturationIdx]) / viscosityW; } if (velocityNw[intersectionIdx] >= 0.) @@ -271,8 +276,7 @@ public: } else { - mobilityNw = MaterialLaw::krn(problem.spatialParams().materialLawParams(element), - boundValues[saturationIdx]) / viscosityNw; + mobilityNw = fluidMatrixInteraction.krn(boundValues[saturationIdx]) / viscosityNw; } } else diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressure.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressure.hh index 92fa2c1259aa26fb13c6bbb4b0d7b746482aa480..9da440fb954c4c52bbb8503da52d7454819fb1d2 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressure.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressure.hh @@ -32,6 +32,8 @@ #include #include +#include + namespace Dumux { /*! @@ -67,7 +69,6 @@ template class MimeticPressure2P using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -515,13 +516,16 @@ void MimeticPressure2P::updateMaterialLaws() CellData& cellData = problem_.variables().cellData(eIdxGlobal); - Scalar satW = cellData.saturation(wPhaseIdx); + const Scalar satW = cellData.saturation(wPhaseIdx); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressureadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressureadaptive.hh index fb0f271f81bc7401adb27cfe5d3feba591b44013..7ecf0b88390f2656af98dc27e73fa2d70d9ee530 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressureadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mimetic/pressureadaptive.hh @@ -32,6 +32,8 @@ #include #include +#include + namespace Dumux { /*! @@ -67,7 +69,6 @@ template class MimeticPressure2PAdaptive using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -532,13 +533,16 @@ void MimeticPressure2PAdaptive::updateMaterialLaws() CellData& cellData = problem_.variables().cellData(eIdxGlobal); - Scalar satW = cellData.saturation(wPhaseIdx); + const Scalar satW = cellData.saturation(wPhaseIdx); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressure.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressure.hh index 34c6c1fabbee46583ad257bc8c2853498cceb422..d5491eaa97202573cbe0c36b69b581eeeceaf426 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressure.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressure.hh @@ -29,6 +29,8 @@ #include #include "2dtransmissibilitycalculator.hh" +#include + namespace Dumux { /*! @@ -82,7 +84,6 @@ class FvMpfaL2dPressure2p: public FVPressure using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -1664,19 +1665,20 @@ void FvMpfaL2dPressure2p::assemble() } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector lambdaBound( - MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; @@ -1840,15 +1842,18 @@ void FvMpfaL2dPressure2p::updateMaterialLaws() Scalar satW = cellData.saturation(wPhaseIdx); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pc = fluidMatrixInteraction.pc(satW); cellData.setCapillaryPressure(pc); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressureadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressureadaptive.hh index e19b8d174061157570608baf227fc08bf82b694a..6813decae3097f5d93591889f15202b846a1804a 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressureadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressureadaptive.hh @@ -30,6 +30,8 @@ #include #include "2dtransmissibilitycalculator.hh" +#include + namespace Dumux { /*! @@ -85,7 +87,6 @@ class FvMpfaL2dPressure2pAdaptive: public FVPressure using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -2383,19 +2384,20 @@ void FvMpfaL2dPressure2pAdaptive::assemble() } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector lambdaBound( - MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; @@ -2556,17 +2558,20 @@ void FvMpfaL2dPressure2pAdaptive::updateMaterialLaws() CellData& cellData = problem_.variables().cellData(eIdxGlobal); - Scalar satW = cellData.saturation(wPhaseIdx); + const Scalar satW = cellData.saturation(wPhaseIdx); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pc = fluidMatrixInteraction.pc(satW); cellData.setCapillaryPressure(pc); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocity.hh index 59b40398247266434f7e834a16ecd959c0638fcc..15b59fadef74300305ddf1e8ee2ef0a74a021d51 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocity.hh @@ -27,6 +27,8 @@ #include "2dpressure.hh" #include "2dvelocity.hh" +#include + namespace Dumux { /*! @@ -61,7 +63,6 @@ template class FvMpfaL2dPressureVelocity2p: public FvMpfaL2dPress using PrimaryVariables = typename SolutionTypes::PrimaryVariables; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -453,8 +454,14 @@ void FvMpfaL2dPressureVelocity2p::calculateVelocityOnBoundary(const Int satW = cellData.saturation(wPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); //determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -470,10 +477,8 @@ void FvMpfaL2dPressureVelocity2p::calculateVelocityOnBoundary(const Int pressNwBound = pressBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocityadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocityadaptive.hh index d4a741869292c5ddf4ede6a4017ba094f8f2740e..87b3176ead6acf59ef8d78d999019f7bd0699b4b 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocityadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dpressurevelocityadaptive.hh @@ -27,6 +27,8 @@ #include "2dpressureadaptive.hh" #include "2dvelocityadaptive.hh" +#include + namespace Dumux { /*! @@ -63,7 +65,6 @@ template class FvMpfaL2dPressureVelocity2pAdaptive: public FvMpfa using PrimaryVariables = typename SolutionTypes::PrimaryVariables; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -589,8 +590,14 @@ void FvMpfaL2dPressureVelocity2pAdaptive::calculateVelocityOnBoundary(c satW = cellData.saturation(wPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); //determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -606,10 +613,8 @@ void FvMpfaL2dPressureVelocity2pAdaptive::calculateVelocityOnBoundary(c pressNwBound = pressBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocity.hh index 269960826c4a6b674404ffa3a7f2bd0dce5e9458..0e6df329cd43c587de7c1bcfbde16aee595df24e 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocity.hh @@ -30,6 +30,8 @@ #include #include "2dtransmissibilitycalculator.hh" +#include + namespace Dumux { /*! @@ -66,7 +68,6 @@ template class FvMpfaL2dVelocity2p using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -786,21 +787,20 @@ void FvMpfaL2dVelocity2p::calculateBoundaryInteractionVolumeVelocity(In } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector < Scalar, numPhases - > lambdaBound( - MaterialLaw::krw( - problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocityadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocityadaptive.hh index 2fddf014ca55d706416d8bab54c12dd2bb8a06fb..85cbc3586bb69a5742d19fb1caf38d595068d2ac 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocityadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/2dvelocityadaptive.hh @@ -63,7 +63,6 @@ template class FvMpfaL2dVelocity2pAdaptive : public FvMpfaL2dVelo using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressure.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressure.hh index 68a418328fb95d7ce21e5f78e3cf7f9c56e007d9..8eefe30623c7caf559eeccea2256e062271c0d69 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressure.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressure.hh @@ -32,6 +32,8 @@ #include "3dinteractionvolumecontainer.hh" #include "3dtransmissibilitycalculator.hh" +#include + namespace Dumux { /*! @@ -85,7 +87,6 @@ class FvMpfaL3dPressure2p: public FVPressure using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -2351,18 +2352,20 @@ void FvMpfaL3dPressure2p::assembleBoundaryInteractionVolume(Interaction } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector - lambdaBound(MaterialLaw::krw(problem_.spatialParams().materialLawParams(element),satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; @@ -2489,14 +2492,19 @@ void FvMpfaL3dPressure2p::updateMaterialLaws() Scalar satW = cellData.saturation(wPhaseIdx); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pc = fluidMatrixInteraction.pc(satW); cellData.setCapillaryPressure(pc); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) + Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) + Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressureadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressureadaptive.hh index a5129ed870ea096794f3e1bf2936a2b572e1677a..ef2aef01af18b077ea2085f47015db0f9901df36 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressureadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressureadaptive.hh @@ -89,7 +89,6 @@ class FvMpfaL3dPressure2pAdaptive: public FvMpfaL3dPressure2p using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocity.hh index 025df282e2959caae797b596bf9dd99e97dcbfa7..595ff582d94fb2393b487115671bbbad7819f2d1 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocity.hh @@ -28,6 +28,8 @@ #include "3dpressure.hh" #include "3dvelocity.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -77,7 +79,6 @@ template class FvMpfaL3dPressureVelocity2p: public FvMpfaL3dPress using SolutionTypes = GetProp; using PrimaryVariables = typename SolutionTypes::PrimaryVariables; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using InteractionVolume = GetPropType; using Intersection = typename GridView::Intersection; @@ -452,8 +453,14 @@ void FvMpfaL3dPressureVelocity2p::calculateVelocityOnBoundary(const Int satW = cellData.saturation(wPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); //determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -469,10 +476,8 @@ void FvMpfaL3dPressureVelocity2p::calculateVelocityOnBoundary(const Int pressNwBound = pressBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocityadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocityadaptive.hh index 5782b15acf17d3b4e3bec7f2046b468e6dc51877..84a8ba579aaca865da74121371139e95e0922ec4 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocityadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dpressurevelocityadaptive.hh @@ -27,6 +27,8 @@ #include "3dpressureadaptive.hh" #include "3dvelocityadaptive.hh" +#include + namespace Dumux { /*! @@ -79,7 +81,6 @@ template class FvMpfaL3dPressureVelocity2pAdaptive: public FvMpfa using SolutionTypes = GetProp; using PrimaryVariables = typename SolutionTypes::PrimaryVariables; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using InteractionVolume = GetPropType; using Intersection = typename GridView::Intersection; @@ -553,8 +554,14 @@ void FvMpfaL3dPressureVelocity2pAdaptive::calculateVelocityOnBoundary(c satW = cellData.saturation(wPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); //determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -570,10 +577,8 @@ void FvMpfaL3dPressureVelocity2pAdaptive::calculateVelocityOnBoundary(c pressNwBound = pressBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocity.hh index 8aef1f4cb8e9b5f0a868ed53fcff349b6f268337..818f50b71bd314160b1ab206a1bfcb082ce4b9f2 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocity.hh @@ -29,6 +29,8 @@ #include #include "3dtransmissibilitycalculator.hh" +#include + namespace Dumux { /*! @@ -63,7 +65,6 @@ template class FvMpfaL3dVelocity2p using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -1972,19 +1973,20 @@ void FvMpfaL3dVelocity2p::calculateBoundaryInteractionVolumeVelocity(In } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector lambdaBound( - MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocityadaptive.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocityadaptive.hh index 9aa9447370a29fdfb15e209433c24f3d04073764..1afe847c7f7f7f275196c7253d25cb14402cdad3 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocityadaptive.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/lmethod/3dvelocityadaptive.hh @@ -65,7 +65,6 @@ template class FvMpfaL3dVelocity2pAdaptive: public FvMpfaL3dVeloc using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressure.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressure.hh index fe1b2e99703644bb228bdb06c0b2a259477c47f7..97f3be5fe571963888641670ad3c3898ea8337c0 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressure.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressure.hh @@ -28,6 +28,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -77,7 +79,6 @@ class FvMpfaO2dPressure2p: public FVPressure using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -1763,19 +1764,20 @@ void FvMpfaO2dPressure2p::assemble() } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector lambdaBound( - MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; @@ -1938,17 +1940,20 @@ void FvMpfaO2dPressure2p::updateMaterialLaws() CellData& cellData = problem_.variables().cellData(eIdxGlobal); - Scalar satW = cellData.saturation(wPhaseIdx); + const Scalar satW = cellData.saturation(wPhaseIdx); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pc = fluidMatrixInteraction.pc(satW); cellData.setCapillaryPressure(pc); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressurevelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressurevelocity.hh index a38f5e39d1f612ae3e307dd04d45b0b4c1a10ffd..eb00f5a0777fd038b11ec6af18aa8747356476af 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressurevelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dpressurevelocity.hh @@ -27,6 +27,8 @@ #include "2dpressure.hh" #include "2dvelocity.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -60,7 +62,6 @@ template class FvMpfaO2dPressureVelocity2p: public FvMpfaO2dPress using PrimaryVariables = typename SolutionTypes::PrimaryVariables; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using FluidSystem = GetPropType; using FluidState = GetPropType; @@ -454,8 +455,14 @@ void FvMpfaO2dPressureVelocity2p::calculateVelocityOnBoundary(const Int satW = cellData.saturation(wPhaseIdx); } - Scalar pressBound = boundValues[pressureIdx]; - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + const Scalar pressBound = boundValues[pressureIdx]; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pcBound = fluidMatrixInteraction.pc(satW); //determine phase pressures from primary pressure variable Scalar pressWBound = 0; @@ -471,10 +478,8 @@ void FvMpfaO2dPressureVelocity2p::calculateVelocityOnBoundary(const Int pressNwBound = pressBound; } - Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[wPhaseIdx]; - Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) - / viscosity_[nPhaseIdx]; + const Scalar lambdaWBound = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar lambdaNwBound = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex); Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex); diff --git a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dvelocity.hh b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dvelocity.hh index b9ede8717aa6b397cd3b9d74621f2bb994007ee4..36a08b2bd7e74cb075c15fbfbdc338d1478a8a28 100644 --- a/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dvelocity.hh +++ b/dumux/porousmediumflow/2p/sequential/diffusion/mpfa/omethod/2dvelocity.hh @@ -30,6 +30,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -65,7 +67,6 @@ template class FvMpfaO2dVelocity2P using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -619,21 +620,20 @@ void FvMpfaO2dVelocity2P::calculateBoundaryInteractionVolumeVelocity(In } - Scalar pcBound = MaterialLaw::pc( - problem_.spatialParams().materialLawParams(element), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]); pcBound += gravityDiffBound; - Dune::FieldVector < Scalar, numPhases - > lambdaBound( - MaterialLaw::krw( - problem_.spatialParams().materialLawParams(element), - satWBound)); - lambdaBound[nPhaseIdx] = MaterialLaw::krn( - problem_.spatialParams().materialLawParams(element), satWBound); + Dune::FieldVector < Scalar, numPhases> lambdaBound(fluidMatrixInteraction.krw(satWBound)); + lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound); lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx]; lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx]; diff --git a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/capillarydiffusion.hh b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/capillarydiffusion.hh index 4e50446756bcdb6b3aad9495fca7b06f0b62a08e..dfdc2b3ae04831af4b78662d2a6f4d99e936bb98 100644 --- a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/capillarydiffusion.hh +++ b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/capillarydiffusion.hh @@ -27,6 +27,8 @@ #include #include "properties.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -54,7 +56,6 @@ private: using Indices = typename GetPropType::Indices; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using FluidSystem = GetPropType; using FluidState = GetPropType; @@ -112,6 +113,11 @@ public: Scalar mobilityWI = 0; Scalar mobilityNwI = 0; + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + if (preComput_) { mobilityWI = CellDataI.mobility(wPhaseIdx); @@ -123,9 +129,9 @@ public: fluidState.setPressure(wPhaseIdx, referencePressure); fluidState.setPressure(nPhaseIdx, referencePressure); fluidState.setTemperature(temperature); - mobilityWI = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satI); + mobilityWI = fluidMatrixInteraction.krw(satI); mobilityWI /= FluidSystem::viscosity(fluidState, wPhaseIdx); - mobilityNwI = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satI); + mobilityNwI = fluidMatrixInteraction.krn(satI); mobilityNwI /= FluidSystem::viscosity(fluidState, nPhaseIdx); } @@ -172,9 +178,14 @@ public: fluidState.setPressure(nPhaseIdx, referencePressure); fluidState.setTemperature(temperature); - mobilityWJ = MaterialLaw::krw(problem_.spatialParams().materialLawParams(neighbor), satJ); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteractionNeighbor = spatialParams.fluidMatrixInteractionAtPos(neighbor.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteractionNeighbor = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), neighbor); + + mobilityWJ = fluidMatrixInteractionNeighbor.krw(satJ); mobilityWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); - mobilityNwJ = MaterialLaw::krn(problem_.spatialParams().materialLawParams(neighbor), satJ); + mobilityNwJ = fluidMatrixInteractionNeighbor.krn(satJ); mobilityNwJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); } Scalar mobilityWMean = 0.5*(mobilityWI + mobilityWJ); @@ -207,9 +218,9 @@ public: fluidState.setPressure(wPhaseIdx, referencePressure); fluidState.setPressure(nPhaseIdx, referencePressure); fluidState.setTemperature(temperature); - mobilityWJ = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satJ); + mobilityWJ = fluidMatrixInteraction.krw(satJ); mobilityWJ /= FluidSystem::viscosity(fluidState, wPhaseIdx); - mobilityNwJ = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satJ); + mobilityNwJ = fluidMatrixInteraction.krn(satJ); mobilityNwJ /= FluidSystem::viscosity(fluidState, nPhaseIdx); Scalar mobWMean = 0.5 * (mobilityWI + mobilityWJ); diff --git a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxcoats.hh b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxcoats.hh index 0f43ac4153a351d4c83048a9cc62f62a903cefec..4750fe67abebe790db361ed4a4bc5cb83ff5e9b4 100644 --- a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxcoats.hh +++ b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxcoats.hh @@ -28,6 +28,8 @@ #include #include "evalcflflux.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -44,7 +46,6 @@ private: using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using FluidSystem = GetPropType; using FluidState = GetPropType; using Indices = typename GetPropType::Indices; @@ -357,7 +358,12 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, Scalar lambdaWI = cellDataI.mobility(wPhaseIdx); Scalar lambdaNwI = cellDataI.mobility(nPhaseIdx); - Scalar dpc_dsI = MaterialLaw::dpc_dsw(problem_.spatialParams().materialLawParams(element), satI); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar dpc_dsI = fluidMatrixInteraction.dpc_dsw(satI); const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal(); @@ -407,7 +413,12 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, Scalar lambdaWJ = cellDataI.mobility(wPhaseIdx); Scalar lambdaNwJ = cellDataI.mobility(nPhaseIdx); - Scalar dpc_dsJ = MaterialLaw::dpc_dsw(problem_.spatialParams().materialLawParams(neighbor), satJ); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(neighbor.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteractionNeighbor = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), neighbor); + + const Scalar dpc_dsJ = fluidMatrixInteractionNeighbor.dpc_dsw(satJ); // compute vectorized permeabilities DimVector permeability(0); @@ -448,8 +459,8 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, ds += epsDerivative_; } - Scalar dLambdaWDs = MaterialLaw::krw(problem_.spatialParams().materialLawParams(neighbor), abs(satPlus)) / viscosityW; - dLambdaWDs -= MaterialLaw::krw(problem_.spatialParams().materialLawParams(neighbor), abs(satMinus)) / viscosityW; + Scalar dLambdaWDs = fluidMatrixInteractionNeighbor.krw(abs(satPlus)) / viscosityW; + dLambdaWDs -= fluidMatrixInteractionNeighbor.krw(abs(satMinus)) / viscosityW; dLambdaWDs /= (ds); if (upwindNwI) @@ -471,8 +482,8 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, ds += epsDerivative_; } - Scalar dLambdaNwDs = MaterialLaw::krn(problem_.spatialParams().materialLawParams(neighbor), satPlus) / viscosityNw; - dLambdaNwDs -= MaterialLaw::krn(problem_.spatialParams().materialLawParams(neighbor), satMinus) / viscosityNw; + Scalar dLambdaNwDs = fluidMatrixInteractionNeighbor.krn(satPlus) / viscosityNw; + dLambdaNwDs -= fluidMatrixInteractionNeighbor.krn(satMinus) / viscosityNw; dLambdaNwDs /= (ds); Scalar lambdaWCap = 0.5 * (lambdaWI + lambdaWJ); @@ -559,13 +570,13 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, case pw: { potWBound = bcValues[eqIdxPress] + density_[wPhaseIdx] * gdeltaZ; - potNwBound = bcValues[eqIdxPress] + MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satWBound) + potNwBound = bcValues[eqIdxPress] + fluidMatrixInteraction.pc(satWBound) + density_[nPhaseIdx] * gdeltaZ; break; } case pn: { - potWBound = bcValues[eqIdxPress] - MaterialLaw::pc(problem_.spatialParams().materialLawParams(element),satWBound) + potWBound = bcValues[eqIdxPress] - fluidMatrixInteraction.pc(satWBound) + density_[wPhaseIdx] * gdeltaZ; potNwBound = bcValues[eqIdxPress] + density_[nPhaseIdx] * gdeltaZ; break; @@ -602,12 +613,12 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, if (hasPotWBound && !hasPotNwBound) { - potNwBound = potWBound + MaterialLaw::pc(problem_.spatialParams().materialLawParams(element),satWBound) + potNwBound = potWBound + fluidMatrixInteraction.pc(satWBound) + (density_[nPhaseIdx] - density_[wPhaseIdx]) * gdeltaZ; } else if (!hasPotWBound && hasPotNwBound) { - potWBound = potNwBound - MaterialLaw::pc(problem_.spatialParams().materialLawParams(element),satWBound) + potWBound = potNwBound - fluidMatrixInteraction.pc(satWBound) + (density_[nPhaseIdx] - density_[wPhaseIdx]) * gdeltaZ; } } @@ -651,7 +662,7 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, return; } - Scalar dpc_dsBound = MaterialLaw::dpc_dsw(problem_.spatialParams().materialLawParams(element), satWBound); + const Scalar dpc_dsBound = fluidMatrixInteraction.dpc_dsw(satWBound); Scalar lambdaWBound = 0; Scalar lambdaNwBound = 0; @@ -666,8 +677,8 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, Scalar viscosityWBound = FluidSystem::viscosity(fluidState, wPhaseIdx); Scalar viscosityNwBound = FluidSystem::viscosity(fluidState, nPhaseIdx); - lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satWBound) / viscosityWBound; - lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satWBound) / viscosityNwBound; + lambdaWBound = fluidMatrixInteraction.krw(satWBound) / viscosityWBound; + lambdaNwBound = fluidMatrixInteraction.krn(satWBound) / viscosityNwBound; Scalar satUpw = 0; using std::max; @@ -690,8 +701,8 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, ds += epsDerivative_; } - Scalar dLambdaWDs = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satPlus) / viscosityW; - dLambdaWDs -= MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satMinus) / viscosityW; + Scalar dLambdaWDs = fluidMatrixInteraction.krw(satPlus) / viscosityW; + dLambdaWDs -= fluidMatrixInteraction.krw(satMinus) / viscosityW; dLambdaWDs /= (ds); if (cellDataI.fluxData().isUpwindCell(nPhaseIdx, indexInInside)) @@ -713,8 +724,8 @@ void EvalCflFluxCoats::addCoatsFlux(Scalar& lambdaW, Scalar& lambdaNw, ds += epsDerivative_; } - Scalar dLambdaNwDs = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satPlus) / viscosityNw; - dLambdaNwDs -= MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satMinus) / viscosityNw; + Scalar dLambdaNwDs = fluidMatrixInteraction.krn(satPlus) / viscosityNw; + dLambdaNwDs -= fluidMatrixInteraction.krn(satMinus) / viscosityNw; dLambdaNwDs /= (ds); Scalar lambdaWCap = 0.5 * (lambdaWI + lambdaWBound); diff --git a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxdefault.hh b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxdefault.hh index ae2e2ac4ec4378b80aa7d3f1ecf13de490ef2247..d249715a254cfda8d4c7699b151444df743afb3a 100644 --- a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxdefault.hh +++ b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/evalcflfluxdefault.hh @@ -27,6 +27,8 @@ #include #include "evalcflflux.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -234,11 +236,16 @@ private: template typename EvalCflFluxDefault::Scalar EvalCflFluxDefault::getCflFluxFunction(const Element& element) { - Scalar residualSatW = problem_.spatialParams().materialLawParams(element).swr(); - Scalar residualSatNw = problem_.spatialParams().materialLawParams(element).snr(); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar residualSatW = fluidMatrixInteraction.pcSwCurve().effToAbsParams().swr(); + const Scalar residualSatNw = fluidMatrixInteraction.pcSwCurve().effToAbsParams().snr(); // compute dt restriction - Scalar volumeCorrectionFactor = 1 - residualSatW - residualSatNw; + const Scalar volumeCorrectionFactor = 1 - residualSatW - residualSatNw; Scalar volumeCorrectionFactorOutW = 0; Scalar volumeCorrectionFactorOutNw = 0; @@ -273,7 +280,7 @@ typename EvalCflFluxDefault::Scalar EvalCflFluxDefault::getCfl } //determine timestep - Scalar cFLFluxFunction = min(cFLFluxIn, cFLFluxOut); + const Scalar cFLFluxFunction = min(cFLFluxIn, cFLFluxOut); return cFLFluxFunction; } diff --git a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/gravitypart.hh b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/gravitypart.hh index 59cb77ff6a6da2c8af82a0e1b8351df8f849b061..2e2eab73755495943755449ec9b73319abdd6bf7 100644 --- a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/gravitypart.hh +++ b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/gravitypart.hh @@ -27,6 +27,8 @@ #include #include "properties.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPModel @@ -54,7 +56,6 @@ private: using Indices = typename GetPropType::Indices; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using FluidSystem = GetPropType; using FluidState = GetPropType; @@ -100,6 +101,11 @@ public: Scalar lambdaWJ = 0; Scalar lambdaNwJ = 0; + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + if (preComput_) { lambdaWI=cellDataI.mobility(wPhaseIdx); @@ -107,9 +113,9 @@ public: } else { - lambdaWI = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satI); + lambdaWI = fluidMatrixInteraction.krw(satI); lambdaWI /= viscosity_[wPhaseIdx]; - lambdaNwI = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satI); + lambdaNwI = fluidMatrixInteraction.krn(satI); lambdaNwI /= viscosity_[nPhaseIdx]; } @@ -144,9 +150,14 @@ public: } else { - lambdaWJ = MaterialLaw::krw(problem_.spatialParams().materialLawParams(neighbor), satJ); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(neighbor.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteractionNeighbor = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), neighbor); + + lambdaWJ = fluidMatrixInteractionNeighbor.krw(satJ); lambdaWJ /= viscosity_[wPhaseIdx]; - lambdaNwJ = MaterialLaw::krn(problem_.spatialParams().materialLawParams(neighbor), satJ); + lambdaNwJ = fluidMatrixInteractionNeighbor.krn(satJ); lambdaNwJ /= viscosity_[nPhaseIdx]; } @@ -164,9 +175,9 @@ public: distVec = intersection.geometry().center() - element.geometry().center(); //calculate lambda_n*f_w at the boundary - lambdaWJ = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satJ); + lambdaWJ = fluidMatrixInteraction.krw(satJ); lambdaWJ /= viscosity_[wPhaseIdx]; - lambdaNwJ = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satJ); + lambdaNwJ = fluidMatrixInteraction.krn(satJ); lambdaNwJ /= viscosity_[nPhaseIdx]; //If potential is zero always take value from the boundary! diff --git a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/saturation.hh b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/saturation.hh index d8331db50676270f8242d0e37dfeb673e0575f52..da29f8af87cde5f5c87d0698867619ea9b6a47f5 100644 --- a/dumux/porousmediumflow/2p/sequential/transport/cellcentered/saturation.hh +++ b/dumux/porousmediumflow/2p/sequential/transport/cellcentered/saturation.hh @@ -27,6 +27,8 @@ #include #include +#include + namespace Dumux { /*! @@ -92,7 +94,6 @@ class FVSaturation2P: public FVTransport using GravityFlux = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; @@ -803,7 +804,12 @@ void FVSaturation2P::getFluxOnBoundary(Scalar& update, const Intersecti } } - Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(elementI), satWBound); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), elementI); + + const Scalar pcBound = fluidMatrixInteraction.pc(satWBound); Scalar lambdaW = 0; Scalar lambdaNw = 0; @@ -821,12 +827,12 @@ void FVSaturation2P::getFluxOnBoundary(Scalar& update, const Intersecti { if (compressibility_) { - lambdaW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(elementI), satWBound) + lambdaW = fluidMatrixInteraction.krw(satWBound) / FluidSystem::viscosity(cellDataI.fluidState(), wPhaseIdx); } else { - lambdaW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(elementI), satWBound) + lambdaW = fluidMatrixInteraction.krw(satWBound) / viscosity_[wPhaseIdx]; } } @@ -843,12 +849,12 @@ void FVSaturation2P::getFluxOnBoundary(Scalar& update, const Intersecti { if (compressibility_) { - lambdaNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(elementI), satWBound) + lambdaNw = fluidMatrixInteraction.krn(satWBound) / FluidSystem::viscosity(cellDataI.fluidState(), nPhaseIdx); } else { - lambdaNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(elementI), satWBound) + lambdaNw = fluidMatrixInteraction.krn(satWBound) / viscosity_[nPhaseIdx]; } } @@ -1196,13 +1202,18 @@ void FVSaturation2P::updateMaterialLaws() //determine phase saturations from primary saturation variable Scalar satW = cellData.saturation(wPhaseIdx); - Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + + const Scalar pc = fluidMatrixInteraction.pc(satW); cellData.setCapillaryPressure(pc); // initialize mobilities - Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW) / viscosity_[wPhaseIdx]; - Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW) / viscosity_[nPhaseIdx]; + const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx]; + const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx]; // initialize mobilities cellData.setMobility(wPhaseIdx, mobilityW); diff --git a/dumux/porousmediumflow/2p/volumevariables.hh b/dumux/porousmediumflow/2p/volumevariables.hh index e65fdfc30bbe8a65f9966339cc580259a7f269a5..e1f1ee6d96d8fc24e453fbd733f182dbf74d6d66 100644 --- a/dumux/porousmediumflow/2p/volumevariables.hh +++ b/dumux/porousmediumflow/2p/volumevariables.hh @@ -31,6 +31,8 @@ #include #include +#include + namespace Dumux { /*! @@ -93,18 +95,20 @@ public: completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); const int wPhaseIdx = fluidState_.wettingPhase(); const int nPhaseIdx = 1 - wPhaseIdx; mobility_[wPhaseIdx] = - MaterialLaw::krw(materialParams, fluidState_.saturation(wPhaseIdx)) + fluidMatrixInteraction.krw(fluidState_.saturation(wPhaseIdx)) / fluidState_.viscosity(wPhaseIdx); mobility_[nPhaseIdx] = - MaterialLaw::krn(materialParams, fluidState_.saturation(wPhaseIdx)) + fluidMatrixInteraction.krn(fluidState_.saturation(wPhaseIdx)) / fluidState_.viscosity(nPhaseIdx); // porosity calculation over inert volumefraction @@ -136,8 +140,11 @@ public: { EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState, solidState); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto& priVars = elemSol[scv.localDofIndex()]; const auto wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); @@ -149,7 +156,7 @@ public: { fluidState.setSaturation(phase1Idx, priVars[saturationIdx]); fluidState.setSaturation(phase0Idx, 1 - priVars[saturationIdx]); - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); fluidState.setPressure(phase1Idx, priVars[pressureIdx] - pc_); } else @@ -158,7 +165,7 @@ public: scv, elemSol, priVars[saturationIdx]); fluidState.setSaturation(phase1Idx, Sn); fluidState.setSaturation(phase0Idx, 1 - Sn); - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); fluidState.setPressure(phase1Idx, priVars[pressureIdx] + pc_); } } @@ -171,14 +178,14 @@ public: scv, elemSol, priVars[saturationIdx]); fluidState.setSaturation(phase0Idx, Sn); fluidState.setSaturation(phase1Idx, 1 - Sn); - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); fluidState.setPressure(phase0Idx, priVars[pressureIdx] + pc_); } else { fluidState.setSaturation(phase0Idx, priVars[saturationIdx]); fluidState.setSaturation(phase1Idx, 1 - priVars[saturationIdx]); - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); fluidState.setPressure(phase0Idx, priVars[pressureIdx] - pc_); } } diff --git a/dumux/porousmediumflow/2p1c/volumevariables.hh b/dumux/porousmediumflow/2p1c/volumevariables.hh index 2359d89fc42f136dfea612d5161b728d8565ca1b..4908100d5ec3d391e09f372da78d608c435053b1 100644 --- a/dumux/porousmediumflow/2p1c/volumevariables.hh +++ b/dumux/porousmediumflow/2p1c/volumevariables.hh @@ -36,6 +36,8 @@ #include "primaryvariableswitch.hh" +#include + namespace Dumux { /*! @@ -126,8 +128,11 @@ public: ///////////// // calculate the remaining quantities ///////////// - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); // Second instance of a parameter cache. // Could be avoided if diffusion coefficients also @@ -140,10 +145,10 @@ public: // relative permeabilities Scalar kr; if (phaseIdx == wPhaseIdx) - kr = MaterialLaw::krw(materialParams, saturation(wPhaseIdx)); + kr = fluidMatrixInteraction.krw(saturation(wPhaseIdx)); else // ATTENTION: krn requires the wetting phase saturation // as parameter! - kr = MaterialLaw::krn(materialParams, saturation(wPhaseIdx)); + kr = fluidMatrixInteraction.krn(saturation(wPhaseIdx)); relativePermeability_[phaseIdx] = kr; } @@ -176,7 +181,6 @@ public: { // capillary pressure parameters - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); const auto wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); @@ -211,8 +215,12 @@ public: DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid."); // set pressures of the fluid phases - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); if (formulation == TwoPFormulation::p0s1) { fluidState.setPressure(liquidPhaseIdx, priVars[pressureIdx]); diff --git a/dumux/porousmediumflow/2p2c/sequential/fv2dtransportadaptive.hh b/dumux/porousmediumflow/2p2c/sequential/fv2dtransportadaptive.hh index b7937fb722fbd09beeeb9492edf157af861b8c27..37754d5bde9a4e8a729dfe68a53b623f2e1ce985 100644 --- a/dumux/porousmediumflow/2p2c/sequential/fv2dtransportadaptive.hh +++ b/dumux/porousmediumflow/2p2c/sequential/fv2dtransportadaptive.hh @@ -33,6 +33,8 @@ #include "adaptiveproperties.hh" #include "fvtransport.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -366,13 +368,18 @@ void FV2dTransport2P2CAdaptive::getMpfaFlux(Dune::FieldVector class FV3dPressure2P2CAdaptive using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; using BoundaryTypes = GetPropType; diff --git a/dumux/porousmediumflow/2p2c/sequential/fv3dtransportadaptive.hh b/dumux/porousmediumflow/2p2c/sequential/fv3dtransportadaptive.hh index 4e505d0e7005d004fed613e271b99db00300462e..e18141fe406ff5994278df36e119f6c4f8376347 100644 --- a/dumux/porousmediumflow/2p2c/sequential/fv3dtransportadaptive.hh +++ b/dumux/porousmediumflow/2p2c/sequential/fv3dtransportadaptive.hh @@ -33,6 +33,8 @@ #include "adaptiveproperties.hh" #include "fvtransport.hh" +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -57,7 +59,6 @@ class FV3dTransport2P2CAdaptive : public FVTransport2P2C using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; using BoundaryTypes = GetPropType; @@ -364,13 +365,18 @@ void FV3dTransport2P2CAdaptive::getMpfaFlux(Dune::FieldVector #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -79,7 +81,6 @@ template class FVPressure2P2C using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; using BoundaryTypes = GetPropType; @@ -677,6 +678,11 @@ void FVPressure2P2C::getFluxOnBoundary(Dune::FieldVector& en PhaseVector pressBC(0.); Scalar pcBound (0.); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + /********** Dirichlet Boundary *************/ if (bcType.isDirichlet(Indices::pressureEqIdx)) { @@ -754,11 +760,9 @@ void FVPressure2P2C::getFluxOnBoundary(Dune::FieldVector& en else if(getPropValue() == Indices::permDependent) { lambdaWBound - = MaterialLaw::krw(problem().spatialParams().materialLawParams(elementI), - BCfluidState.saturation(wPhaseIdx)) / viscosityWBound; + = fluidMatrixInteraction.krw(BCfluidState.saturation(wPhaseIdx)) / viscosityWBound; lambdaNWBound - = MaterialLaw::krn(problem().spatialParams().materialLawParams(elementI), - BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound; + = fluidMatrixInteraction.krn(BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound; } // get average density Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + densityWBound); @@ -953,6 +957,13 @@ void FVPressure2P2C::updateMaterialLawsInElement(const Element& element PhaseVector pressure; CompositionalFlash flashSolver; + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), element); + + if(getPropValue()) // iterate capillary pressure and saturation { unsigned int maxiter = 6; @@ -981,8 +992,7 @@ void FVPressure2P2C::updateMaterialLawsInElement(const Element& element // calculate new pc Scalar oldPc = pc; - pc = MaterialLaw::pc(problem().spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)); + pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); if (fabs(oldPc-pc)<10 && iter != 0) break; @@ -999,11 +1009,9 @@ void FVPressure2P2C::updateMaterialLawsInElement(const Element& element } // initialize mobilities - cellData.setMobility(wPhaseIdx, MaterialLaw::krw(problem().spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)) + cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx)) / cellData.viscosity(wPhaseIdx)); - cellData.setMobility(nPhaseIdx, MaterialLaw::krn(problem().spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)) + cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx)) / cellData.viscosity(nPhaseIdx)); // determine volume mismatch between actual fluid volume and pore volume diff --git a/dumux/porousmediumflow/2p2c/sequential/fvpressurecompositional.hh b/dumux/porousmediumflow/2p2c/sequential/fvpressurecompositional.hh index f99bd8dad98ef3d06a1f7781ad43f881d0b9a134..e0734b718febc94ae0dfba2cb29f5bd8b113aaf3 100644 --- a/dumux/porousmediumflow/2p2c/sequential/fvpressurecompositional.hh +++ b/dumux/porousmediumflow/2p2c/sequential/fvpressurecompositional.hh @@ -34,6 +34,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -78,9 +80,6 @@ template class FVPressureCompositional using FluidSystem = GetPropType; using FluidState = GetPropType; - ///@cond false - using MaterialLaw = typename GetPropType::MaterialLaw; - ///@endcond using CellData = GetPropType; enum @@ -547,6 +546,11 @@ void FVPressureCompositional::initialMaterialLaws(bool compositional) FluidState& fluidState = cellData.manipulateFluidState(); CompositionalFlash flashSolver; + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element); + // initial conditions PhaseVector pressure(0.); Scalar sat_0=0.; @@ -579,8 +583,7 @@ void FVPressureCompositional::initialMaterialLaws(bool compositional) Scalar pc=0.; if(getPropValue()) { - pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), - sat_0); + pc = fluidMatrixInteraction.pc(sat_0); } else pc = 0.; @@ -640,16 +643,14 @@ void FVPressureCompositional::initialMaterialLaws(bool compositional) Scalar oldPc = pc; //update with better pressures flashSolver.concentrationFlash2p2c(fluidState, Z0, pressure, problem_.temperatureAtPos(globalPos)); - pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)); + pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); // TODO: get right criterion, do output for evaluation //converge criterion using std::abs; if (abs(oldPc - pc) < 10.0) iter = maxiter; - pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)); + pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); } } else // capillary pressure neglected @@ -667,11 +668,9 @@ void FVPressureCompositional::initialMaterialLaws(bool compositional) problem_.transportModel().totalConcentration(nCompIdx,eIdxGlobal) = cellData.massConcentration(nCompIdx); // initialize mobilities - cellData.setMobility(wPhaseIdx, MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)) + cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx)) / cellData.viscosity(wPhaseIdx)); - cellData.setMobility(nPhaseIdx, MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), - fluidState.saturation(wPhaseIdx)) + cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx)) / cellData.viscosity(nPhaseIdx)); // calculate perimeter used as weighting factor diff --git a/dumux/porousmediumflow/2p2c/sequential/fvpressuremultiphysics.hh b/dumux/porousmediumflow/2p2c/sequential/fvpressuremultiphysics.hh index ed873d286d9fed9e09f2fb6f4bb258965dee7b45..2b6540239f38c3eb296b2f0188328153e0ae6a86 100644 --- a/dumux/porousmediumflow/2p2c/sequential/fvpressuremultiphysics.hh +++ b/dumux/porousmediumflow/2p2c/sequential/fvpressuremultiphysics.hh @@ -31,6 +31,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -75,7 +77,6 @@ class FVPressure2P2CMultiPhysics : public FVPressure2P2C using Problem = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; using BoundaryTypes = GetPropType; @@ -700,23 +701,23 @@ void FVPressure2P2CMultiPhysics::get1pFluxOnBoundary(Dune::FieldVector< Scalar lambdaBound = 0.; switch (getPropValue()) { - case Indices::satDependent: + case Indices::satDependent: { - lambdaBound = BCfluidState.saturation(phaseIdx) - / viscosityBound; - break; + lambdaBound = BCfluidState.saturation(phaseIdx) / viscosityBound; + break; } - case Indices::permDependent: + case Indices::permDependent: { - if (phaseIdx == wPhaseIdx) - lambdaBound = MaterialLaw::krw( - problem().spatialParams().materialLawParams(elementI), BCfluidState.saturation(wPhaseIdx)) - / viscosityBound; - else - lambdaBound = MaterialLaw::krn( - problem().spatialParams().materialLawParams(elementI), BCfluidState.saturation(wPhaseIdx)) - / viscosityBound; - break; + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + + if (phaseIdx == wPhaseIdx) + lambdaBound = fluidMatrixInteraction.krw(BCfluidState.saturation(wPhaseIdx)) / viscosityBound; + else + lambdaBound = fluidMatrixInteraction.krn(BCfluidState.saturation(wPhaseIdx)) / viscosityBound; + break; } } Scalar rhoMean = 0.5 * (cellDataI.density(phaseIdx) + densityBound); @@ -931,14 +932,18 @@ void FVPressure2P2CMultiPhysics::update1pMaterialLawsInElement(const El // acess the simple fluid state and prepare for manipulation auto& pseudoFluidState = cellData.manipulateSimpleFluidState(); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + // prepare phase pressure for fluid state // both phase pressures are necessary for the case 1p domain is assigned for // the next 2p subdomain PhaseVector pressure(0.); Scalar pc = 0; if(getPropValue()) - pc = MaterialLaw::pc(problem().spatialParams().materialLawParams(elementI), - ((presentPhaseIdx == wPhaseIdx) ? 1. : 0.)); // assign sw = 1 if wPhase present, else 0 + pc = fluidMatrixInteraction.pc(((presentPhaseIdx == wPhaseIdx) ? 1. : 0.)); // assign sw = 1 if wPhase present, else 0 if(pressureType == wPhaseIdx) { pressure[wPhaseIdx] = this->pressure(eIdxGlobal); @@ -970,15 +975,13 @@ void FVPressure2P2CMultiPhysics::update1pMaterialLawsInElement(const El if(presentPhaseIdx == wPhaseIdx) { cellData.setMobility(wPhaseIdx, - MaterialLaw::krw(problem().spatialParams().materialLawParams(elementI), pseudoFluidState.saturation(wPhaseIdx)) - / cellData.viscosity(wPhaseIdx)); + fluidMatrixInteraction.krw(pseudoFluidState.saturation(wPhaseIdx)) / cellData.viscosity(wPhaseIdx)); cellData.setMobility(nPhaseIdx, 0.); } else { cellData.setMobility(nPhaseIdx, - MaterialLaw::krn(problem().spatialParams().materialLawParams(elementI), pseudoFluidState.saturation(wPhaseIdx)) - / cellData.viscosity(nPhaseIdx)); + fluidMatrixInteraction.krn(pseudoFluidState.saturation(wPhaseIdx)) / cellData.viscosity(nPhaseIdx)); cellData.setMobility(wPhaseIdx, 0.); } diff --git a/dumux/porousmediumflow/2p2c/sequential/fvtransport.hh b/dumux/porousmediumflow/2p2c/sequential/fvtransport.hh index 3bd9aa0be41232291b71228671dddb1b2f0705d6..eff7ac11f344abed237610ee40a18b0f30075683 100644 --- a/dumux/porousmediumflow/2p2c/sequential/fvtransport.hh +++ b/dumux/porousmediumflow/2p2c/sequential/fvtransport.hh @@ -35,6 +35,8 @@ #include #include +#include + namespace Dumux { /*! * \ingroup SequentialTwoPTwoCModel @@ -64,7 +66,6 @@ class FVTransport2P2C using Implementation = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; using Indices = typename GetPropType::Indices; using BoundaryTypes = GetPropType; @@ -598,13 +599,18 @@ void FVTransport2P2C::getFlux(ComponentVector& fluxEntries, Scalar pcI = cellDataI.capillaryPressure(); DimMatrix K_I(problem().spatialParams().intrinsicPermeability(elementI)); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + PhaseVector SmobI(0.); using std::max; SmobI[wPhaseIdx] = max((cellDataI.saturation(wPhaseIdx) - - problem().spatialParams().materialLawParams(elementI).swr()) + - fluidMatrixInteraction.pcSwCurve().effToAbsParams().swr()) , 1e-2); SmobI[nPhaseIdx] = max((cellDataI.saturation(nPhaseIdx) - - problem().spatialParams().materialLawParams(elementI).snr()) + - fluidMatrixInteraction.pcSwCurve().effToAbsParams().snr()) , 1e-2); Scalar densityWI (0.), densityNWI(0.); @@ -909,11 +915,16 @@ void FVTransport2P2C::getFluxOnBoundary(ComponentVector& fluxEntries, K_I[axis][axis] = minimalBoundaryPermeability; } + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + Scalar SwmobI = max((cellDataI.saturation(wPhaseIdx) - - problem().spatialParams().materialLawParams(elementI).swr()) + - fluidMatrixInteraction.pcSwCurve().effToAbsParams().swr()) , 1e-2); Scalar SnmobI = max((cellDataI.saturation(nPhaseIdx) - - problem().spatialParams().materialLawParams(elementI).snr()) + - fluidMatrixInteraction.pcSwCurve().effToAbsParams().snr()) , 1e-2); Scalar densityWI (0.), densityNWI(0.); @@ -1001,6 +1012,11 @@ void FVTransport2P2C::getFluxOnBoundary(ComponentVector& fluxEntries, potential[wPhaseIdx] *= fabs(K * unitOuterNormal); potential[nPhaseIdx] *= fabs(K * unitOuterNormal); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(elementI.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI); + // do upwinding for lambdas PhaseVector lambda(0.); if (potential[wPhaseIdx] >= 0.) @@ -1010,9 +1026,7 @@ void FVTransport2P2C::getFluxOnBoundary(ComponentVector& fluxEntries, if(getPropValue()==Indices::satDependent) lambda[wPhaseIdx] = BCfluidState.saturation(wPhaseIdx) / viscosityWBound; else - lambda[wPhaseIdx] = MaterialLaw::krw( - problem().spatialParams().materialLawParams(elementI), BCfluidState.saturation(wPhaseIdx)) - / viscosityWBound; + lambda[wPhaseIdx] = fluidMatrixInteraction.krw(BCfluidState.saturation(wPhaseIdx)) / viscosityWBound; } if (potential[nPhaseIdx] >= 0.) lambda[nPhaseIdx] = cellDataI.mobility(nPhaseIdx); @@ -1021,9 +1035,7 @@ void FVTransport2P2C::getFluxOnBoundary(ComponentVector& fluxEntries, if(getPropValue()==Indices::satDependent) lambda[nPhaseIdx] = BCfluidState.saturation(nPhaseIdx) / viscosityNWBound; else - lambda[nPhaseIdx] = MaterialLaw::krn( - problem().spatialParams().materialLawParams(elementI), BCfluidState.saturation(wPhaseIdx)) - / viscosityNWBound; + lambda[nPhaseIdx] = fluidMatrixInteraction.krn(BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound; } // calculate and standardized velocity @@ -1117,16 +1129,21 @@ void FVTransport2P2C::evalBoundary(GlobalPosition globalPosFace, PrimaryVariables primaryVariablesOnBoundary(0.); problem().dirichlet(primaryVariablesOnBoundary, intersection); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem().spatialParams.fluidMatrixInteractionAtPos(element.geometry().center()); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), element); + // read boundary type typename Indices::BoundaryFormulation bcType; problem().boundaryFormulation(bcType, intersection); if (bcType == Indices::saturation) { Scalar satBound = primaryVariablesOnBoundary[contiWEqIdx]; + if(getPropValue()) { - Scalar pcBound = MaterialLaw::pc(problem().spatialParams().materialLawParams(element), - satBound); + Scalar pcBound = fluidMatrixInteraction.pc(satBound); switch (pressureType) { case pw: @@ -1159,8 +1176,7 @@ void FVTransport2P2C::evalBoundary(GlobalPosition globalPosFace, if(getPropValue()) { - Scalar pcBound = MaterialLaw::pc(problem().spatialParams().materialLawParams(element), - BCfluidState.saturation(wPhaseIdx)); + Scalar pcBound = fluidMatrixInteraction.pc(BCfluidState.saturation(wPhaseIdx)); int maxiter = 3; //start iteration loop for(int iter=0; iter < maxiter; iter++) @@ -1189,8 +1205,7 @@ void FVTransport2P2C::evalBoundary(GlobalPosition globalPosFace, //update with better pressures flashSolver.concentrationFlash2p2c(BCfluidState, Z0Bound, pressBound, problem().temperatureAtPos(globalPosFace)); - pcBound = MaterialLaw::pc(problem().spatialParams().materialLawParams(element), - BCfluidState.saturation(wPhaseIdx)); + pcBound = fluidMatrixInteraction.pc(BCfluidState.saturation(wPhaseIdx)); // TODO: get right criterion, do output for evaluation //converge criterion using std::abs; diff --git a/dumux/porousmediumflow/2p2c/volumevariables.hh b/dumux/porousmediumflow/2p2c/volumevariables.hh index a4c440e6981501d4936295754507e145e7e78839..44667dc3757d5204746d03f89f481f4176165696 100644 --- a/dumux/porousmediumflow/2p2c/volumevariables.hh +++ b/dumux/porousmediumflow/2p2c/volumevariables.hh @@ -37,6 +37,8 @@ #include #include +#include + namespace Dumux { // forward declaration @@ -141,15 +143,17 @@ public: ParentType::update(elemSol, problem, element, scv); asImp_().completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& matParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); const int wPhaseIdx = fluidState_.wettingPhase(); const int nPhaseIdx = 1 - wPhaseIdx; // relative permeabilities -> require wetting phase saturation as parameter! - relativePermeability_[wPhaseIdx] = MaterialLaw::krw(matParams, saturation(wPhaseIdx)); - relativePermeability_[nPhaseIdx] = MaterialLaw::krn(matParams, saturation(wPhaseIdx)); + relativePermeability_[wPhaseIdx] = fluidMatrixInteraction.krw(saturation(wPhaseIdx)); + relativePermeability_[nPhaseIdx] = fluidMatrixInteraction.krn(saturation(wPhaseIdx)); // porosity & permeabilty updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps); @@ -192,8 +196,11 @@ public: const auto& priVars = elemSol[scv.localDofIndex()]; const auto phasePresence = priVars.state(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); @@ -225,7 +232,7 @@ public: DUNE_THROW(Dune::InvalidStateException, "Invalid phase presence."); // set pressures of the fluid phases - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); if (formulation == TwoPFormulation::p0s1) { fluidState.setPressure(phase0Idx, priVars[pressureIdx]); diff --git a/dumux/porousmediumflow/2pnc/volumevariables.hh b/dumux/porousmediumflow/2pnc/volumevariables.hh index 7886ee83918f4ecf3502b1803038ce322935b227..f50e8cab6233dfa435d457a20d1ef29f4bec446d 100644 --- a/dumux/porousmediumflow/2pnc/volumevariables.hh +++ b/dumux/porousmediumflow/2pnc/volumevariables.hh @@ -44,6 +44,8 @@ #include "primaryvariableswitch.hh" +#include + namespace Dumux { /*! @@ -140,14 +142,18 @@ public: // calculate the remaining quantities ///////////// - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& matParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const int wPhaseIdx = fluidState_.wettingPhase(); const int nPhaseIdx = 1 - wPhaseIdx; // mobilities -> require wetting phase saturation as parameter! - mobility_[wPhaseIdx] = MaterialLaw::krw(matParams, saturation(wPhaseIdx))/fluidState_.viscosity(wPhaseIdx); - mobility_[nPhaseIdx] = MaterialLaw::krn(matParams, saturation(wPhaseIdx))/fluidState_.viscosity(nPhaseIdx); + mobility_[wPhaseIdx] = fluidMatrixInteraction.krw(saturation(wPhaseIdx))/fluidState_.viscosity(wPhaseIdx); + mobility_[nPhaseIdx] = fluidMatrixInteraction.krn(saturation(wPhaseIdx))/fluidState_.viscosity(nPhaseIdx); //update porosity before calculating the effective properties depending on it updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps); @@ -190,8 +196,11 @@ public: const auto& priVars = elemSol[scv.localDofIndex()]; const auto phasePresence = priVars.state(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); @@ -223,7 +232,7 @@ public: DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid."); // set pressures of the fluid phases - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); if (formulation == TwoPFormulation::p0s1) { fluidState.setPressure(phase0Idx, priVars[pressureIdx]); @@ -260,13 +269,12 @@ public: } else if (phasePresence == secondPhaseOnly) { - - Dune::FieldVector moleFrac; + Dune::FieldVector moleFrac; moleFrac[comp0Idx] = priVars[switchIdx]; Scalar sumMoleFracOtherComponents = moleFrac[comp0Idx]; - for (int compIdx = numMajorComponents; compIdx < ModelTraits::numFluidComponents(); ++compIdx) + for (int compIdx = numMajorComponents; compIdx < ModelTraits::numFluidComponents(); ++compIdx) { moleFrac[compIdx] = priVars[compIdx]; sumMoleFracOtherComponents += moleFrac[compIdx]; diff --git a/dumux/porousmediumflow/3p/volumevariables.hh b/dumux/porousmediumflow/3p/volumevariables.hh index 2f70cf36a6f46bf090b8810221ba3a47f794c620..8680f1cd611c97a6e0b8c5b98a08da484174b911 100644 --- a/dumux/porousmediumflow/3p/volumevariables.hh +++ b/dumux/porousmediumflow/3p/volumevariables.hh @@ -31,6 +31,8 @@ #include #include +#include + namespace Dumux { /*! @@ -89,21 +91,21 @@ public: const Scv& scv) { ParentType::update(elemSol, problem, element, scv); + completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); - // capillary pressure parameters - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); - completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); + const auto sw = fluidState_.saturation(wPhaseIdx); + const auto sn = fluidState_.saturation(nPhaseIdx); // mobilities for (int phaseIdx = 0; phaseIdx < ParentType::numFluidPhases(); ++phaseIdx) { - mobility_[phaseIdx] = MaterialLaw::kr(materialParams, phaseIdx, - fluidState_.saturation(wPhaseIdx), - fluidState_.saturation(nPhaseIdx), - fluidState_.saturation(gPhaseIdx)) - / fluidState_.viscosity(phaseIdx); + mobility_[phaseIdx] = fluidMatrixInteraction.kr(phaseIdx, sw, sn) + / fluidState_.viscosity(phaseIdx); } // porosity @@ -136,9 +138,13 @@ public: { EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState, solidState); - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); const auto& priVars = elemSol[scv.localDofIndex()]; + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const Scalar sw = priVars[swIdx]; const Scalar sn = priVars[snIdx]; const Scalar sg = 1.0 - sw - sn; @@ -151,12 +157,11 @@ public: const Scalar pg = priVars[pressureIdx]; // calculate capillary pressures - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const Scalar pcgw = MaterialLaw::pcgw(materialParams, sw); - const Scalar pcnw = MaterialLaw::pcnw(materialParams, sw); - const Scalar pcgn = MaterialLaw::pcgn(materialParams, sw + sn); + const Scalar pcgw = fluidMatrixInteraction.pcgw(sw, sn); + const Scalar pcnw = fluidMatrixInteraction.pcnw(sw, sn); + const Scalar pcgn = fluidMatrixInteraction.pcgn(sw, sn); - const Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn); + const Scalar pcAlpha = fluidMatrixInteraction.pcAlpha(sw, sn); const Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file const Scalar pn = pg- pcAlpha * pcgn - (1.0 - pcAlpha)*(pcgw - pcNW1); diff --git a/dumux/porousmediumflow/3p3c/volumevariables.hh b/dumux/porousmediumflow/3p3c/volumevariables.hh index 2bde2eec54f1eab31877408245882a37ca5d4bd2..1eb6858fa26de327611f00ad56b180a697ba78b5 100644 --- a/dumux/porousmediumflow/3p3c/volumevariables.hh +++ b/dumux/porousmediumflow/3p3c/volumevariables.hh @@ -33,11 +33,25 @@ #include #include #include +#include #include "primaryvariableswitch.hh" +#include + namespace Dumux { +namespace Detail { +// helper struct and function detecting if the fluid matrix interaction features a adsorptionModel() function +template +using AdsorptionModelDetector = decltype(std::declval().adsorptionModel()); + +template +static constexpr bool hasAdsorptionModel() +{ return Dune::Std::is_detected::value; } + +} + /*! * \ingroup ThreePThreeCModel * \brief Contains the quantities which are are constant within a @@ -123,11 +137,6 @@ public: constexpr bool useConstraintSolver = ModelTraits::useConstraintSolver(); - // capillary pressure parameters - const auto &materialParams = - problem.spatialParams().materialLawParams(element, scv, elemSol); - - EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState_, solidState_); /* first the saturations */ @@ -178,13 +187,18 @@ public: pg_ = priVars[pressureIdx]; // calculate capillary pressures - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - Scalar pcgw = MaterialLaw::pcgw(materialParams, sw_); - Scalar pcnw = MaterialLaw::pcnw(materialParams, sw_); - Scalar pcgn = MaterialLaw::pcgn(materialParams, sw_ + sn_); - Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn_); - Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + Scalar pcgw = fluidMatrixInteraction.pcgw(sw_, sn_); + Scalar pcnw = fluidMatrixInteraction.pcnw(sw_, sn_); + Scalar pcgn = fluidMatrixInteraction.pcgn(sw_, sn_); + + const Scalar pcAlpha = fluidMatrixInteraction.pcAlpha(sw_, sn_); + const Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file pn_ = pg_- pcAlpha * pcgn - (1.-pcAlpha)*(pcgw - pcNW1); pw_ = pn_ - pcAlpha * pcnw - (1.-pcAlpha)*pcNW1; @@ -528,29 +542,26 @@ public: } } else - { DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid."); - } - for (int phaseIdx = 0; phaseIdx < ModelTraits::numFluidPhases(); ++phaseIdx) { - // Mobilities + for (int phaseIdx = 0; phaseIdx < ModelTraits::numFluidPhases(); ++phaseIdx) + { + // mobilities const Scalar mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx); fluidState_.setViscosity(phaseIdx,mu); - Scalar kr; - kr = MaterialLaw::kr(materialParams, phaseIdx, + const Scalar kr = fluidMatrixInteraction.kr(phaseIdx, fluidState_.saturation(wPhaseIdx), - fluidState_.saturation(nPhaseIdx), - fluidState_.saturation(gPhaseIdx)); + fluidState_.saturation(nPhaseIdx)); mobility_[phaseIdx] = kr / mu; } - // material dependent parameters for NAPL adsorption - bulkDensTimesAdsorpCoeff_ = - MaterialLaw::bulkDensTimesAdsorpCoeff(materialParams); + // material dependent parameters for NAPL adsorption (only if law is provided) + if constexpr (Detail::hasAdsorptionModel>()) + bulkDensTimesAdsorpCoeff_ = fluidMatrixInteraction.adsorptionModel().bulkDensTimesAdsorpCoeff(); /* compute the diffusion coefficient * \note This is the part of the diffusion coefficient determined by the fluid state, e.g. @@ -675,9 +686,7 @@ public: * \param phaseIdx The phase index */ Scalar mobility(const int phaseIdx) const - { - return mobility_[phaseIdx]; - } + { return mobility_[phaseIdx]; } /*! * \brief Returns the effective capillary pressure within the control volume. @@ -695,7 +704,12 @@ public: * \brief Returns the adsorption information. */ Scalar bulkDensTimesAdsorpCoeff() const - { return bulkDensTimesAdsorpCoeff_; } + { + if (bulkDensTimesAdsorpCoeff_) + return bulkDensTimesAdsorpCoeff_.value(); + else + DUNE_THROW(Dune::NotImplemented, "Your spatialParams do not provide an adsorption model"); + } /*! * \brief Returns the average permeability within the control volume in \f$[m^2]\f$. @@ -732,7 +746,7 @@ private: PermeabilityType permeability_; //!< Effective permeability within the control volume Scalar mobility_[ModelTraits::numFluidPhases()]; //!< Effective mobility within the control volume - Scalar bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL + OptionalScalar bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL DiffusionCoefficients effectiveDiffCoeff_; }; diff --git a/dumux/porousmediumflow/3pwateroil/volumevariables.hh b/dumux/porousmediumflow/3pwateroil/volumevariables.hh index 06195036b0fac2a2c376fc7d7f211657909f04ad..93df10bd504c495d44452f03c50cc0551ee70ffa 100644 --- a/dumux/porousmediumflow/3pwateroil/volumevariables.hh +++ b/dumux/porousmediumflow/3pwateroil/volumevariables.hh @@ -37,12 +37,28 @@ #include #include +#include #include #include "primaryvariableswitch.hh" +#include + namespace Dumux { +namespace Detail { +// helper struct and function detecting if the fluid matrix interaction features a adsorptionModel() function +#ifndef DOXYGEN // hide from doxygen +template +using AdsorptionModelDetector = decltype(std::declval().adsorptionModel()); +#endif // DOXYGEN + +template +static constexpr bool hasAdsorptionModel() +{ return Dune::Std::is_detected::value; } + +} + /*! * \ingroup ThreePWaterOilModel * \brief Contains the quantities which are are constant within a @@ -123,11 +139,7 @@ public: const auto& priVars = elemSol[scv.localDofIndex()]; const auto phasePresence = priVars.state(); - // capillary pressure parameters - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); - - if(!onlyGasPhaseCanDisappear()) + if constexpr (!onlyGasPhaseCanDisappear()) { /* first the saturations */ if (phasePresence == threePhases) @@ -172,34 +184,29 @@ public: fluidState_.setSaturation(gPhaseIdx, sg_); fluidState_.setSaturation(nPhaseIdx, sn_); + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + // calculate capillary pressures + const Scalar pcgw = fluidMatrixInteraction.pcgw(sw_, sn_); + const Scalar pcnw = fluidMatrixInteraction.pcnw(sw_, sn_); + const Scalar pcgn = fluidMatrixInteraction.pcgn(sw_, sn_); + + const Scalar pcAlpha = fluidMatrixInteraction.pcAlpha(sw_, sn_); + const Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file + /* now the pressures */ if (phasePresence == threePhases || phasePresence == gnPhaseOnly || phasePresence == gPhaseOnly || phasePresence == wgPhaseOnly) { pg_ = priVars[pressureIdx]; - - // calculate capillary pressures - Scalar pcgw = MaterialLaw::pcgw(materialParams, sw_); - Scalar pcnw = MaterialLaw::pcnw(materialParams, sw_); - Scalar pcgn = MaterialLaw::pcgn(materialParams, sw_ + sn_); - - Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn_); - Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file - pn_ = pg_- pcAlpha * pcgn - (1.-pcAlpha)*(pcgw - pcNW1); pw_ = pn_ - pcAlpha * pcnw - (1.-pcAlpha)*pcNW1; } else if (phasePresence == wPhaseOnly || phasePresence == wnPhaseOnly) { pw_ = priVars[pressureIdx]; - - // calculate capillary pressures - Scalar pcgw = MaterialLaw::pcgw(materialParams, sw_); - Scalar pcnw = MaterialLaw::pcnw(materialParams, sw_); - Scalar pcgn = MaterialLaw::pcgn(materialParams, sw_ + sn_); - - Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn_); - Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file - pn_ = pw_ + pcAlpha * pcnw + (1.-pcAlpha)*pcNW1; pg_ = pn_ + pcAlpha * pcgn + (1.-pcAlpha)*(pcgw - pcNW1); } @@ -504,6 +511,7 @@ public: else assert(false); // unhandled phase state } // end of if(!UseSimpleModel), i.e. the more complex version with six phase states + else // use the simpler model with only two phase states { /* first the saturations */ @@ -525,34 +533,29 @@ public: fluidState_.setSaturation(gPhaseIdx, sg_); fluidState_.setSaturation(nPhaseIdx, sn_); + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + // calculate capillary pressures + const Scalar pcgw = fluidMatrixInteraction.pcgw(sw_, sn_); + const Scalar pcnw = fluidMatrixInteraction.pcnw(sw_, sn_); + const Scalar pcgn = fluidMatrixInteraction.pcgn(sw_, sn_); + + const Scalar pcAlpha = fluidMatrixInteraction.pcAlpha(sw_, sn_); + const Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file + /* now the pressures */ if (phasePresence == threePhases) { pg_ = priVars[pressureIdx]; - - // calculate capillary pressures - Scalar pcgw = MaterialLaw::pcgw(materialParams, sw_); - Scalar pcnw = MaterialLaw::pcnw(materialParams, sw_); - Scalar pcgn = MaterialLaw::pcgn(materialParams, sw_ + sn_); - - Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn_); - Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file - pn_ = pg_- pcAlpha * pcgn - (1.-pcAlpha)*(pcgw - pcNW1); pw_ = pn_ - pcAlpha * pcnw - (1.-pcAlpha)*pcNW1; } else if (phasePresence == wnPhaseOnly) { pw_ = priVars[pressureIdx]; - - // calculate capillary pressures - Scalar pcgw = MaterialLaw::pcgw(materialParams, sw_); - Scalar pcnw = MaterialLaw::pcnw(materialParams, sw_); - Scalar pcgn = MaterialLaw::pcgn(materialParams, sw_ + sn_); - - Scalar pcAlpha = MaterialLaw::pcAlpha(materialParams, sn_); - Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file - pn_ = pw_ + pcAlpha * pcnw + (1.-pcAlpha)*pcNW1; pg_ = pn_ + pcAlpha * pcgn + (1.-pcAlpha)*(pcgw - pcNW1); } @@ -723,25 +726,30 @@ public: fluidState_.setMolarDensity(nPhaseIdx, rhoNMolar); } else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid."); - } + } - for (int phaseIdx = 0; phaseIdx < numPs; ++phaseIdx) { + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw<3>(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + for (int phaseIdx = 0; phaseIdx < numPs; ++phaseIdx) + { // Mobilities const Scalar mu = FluidSystem::viscosity(fluidState_, phaseIdx); fluidState_.setViscosity(phaseIdx,mu); - Scalar kr; - kr = MaterialLaw::kr(materialParams, phaseIdx, + const Scalar kr = fluidMatrixInteraction.kr(phaseIdx, fluidState_.saturation(wPhaseIdx), - fluidState_.saturation(nPhaseIdx), - fluidState_.saturation(gPhaseIdx)); + fluidState_.saturation(nPhaseIdx)); mobility_[phaseIdx] = kr / mu; } - // material dependent parameters for NAPL adsorption - bulkDensTimesAdsorpCoeff_ = MaterialLaw::bulkDensTimesAdsorpCoeff(materialParams); + // material dependent parameters for NAPL adsorption (only if law is provided) + if constexpr (Detail::hasAdsorptionModel>()) + bulkDensTimesAdsorpCoeff_ = fluidMatrixInteraction.adsorptionModel().bulkDensTimesAdsorpCoeff(); // porosity updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps); @@ -902,10 +910,15 @@ public: { return effectiveDiffCoeff_(phaseIdx, compIIdx, compJIdx); } /*! - * \brief Returns the adsorption information + * \brief Returns the adsorption information. */ Scalar bulkDensTimesAdsorpCoeff() const - { return bulkDensTimesAdsorpCoeff_; } + { + if (bulkDensTimesAdsorpCoeff_) + return bulkDensTimesAdsorpCoeff_.value(); + else + DUNE_THROW(Dune::NotImplemented, "Your spatialParams do not provide an adsorption model"); + } /*! * \brief Returns the total internal energy of a phase in the @@ -937,7 +950,7 @@ private: Scalar permeability_; //!< Effective porosity within the control volume Scalar mobility_[numPs]; //!< Effective mobility within the control volume - Scalar bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL + OptionalScalar bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL //!< Binary diffusion coefficients of the 3 components in the phases DiffusionCoefficients effectiveDiffCoeff_; diff --git a/dumux/porousmediumflow/co2/volumevariables.hh b/dumux/porousmediumflow/co2/volumevariables.hh index 17cfd5725ec68868fc0072b24e131dd2cf504643..14821bd6931949b364823f2358d25e094bc01004 100644 --- a/dumux/porousmediumflow/co2/volumevariables.hh +++ b/dumux/porousmediumflow/co2/volumevariables.hh @@ -37,6 +37,8 @@ #include "primaryvariableswitch.hh" +#include + namespace Dumux { /*! @@ -135,15 +137,17 @@ public: typename FluidSystem::ParameterCache paramCache; paramCache.updateAll(fluidState_); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& matParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); const int wPhaseIdx = fluidState_.wettingPhase(); const int nPhaseIdx = 1 - wPhaseIdx; // relative permeabilities -> require wetting phase saturation as parameter! - relativePermeability_[wPhaseIdx] = MaterialLaw::krw(matParams, saturation(wPhaseIdx)); - relativePermeability_[nPhaseIdx] = MaterialLaw::krn(matParams, saturation(wPhaseIdx)); + relativePermeability_[wPhaseIdx] = fluidMatrixInteraction.krw(saturation(wPhaseIdx)); + relativePermeability_[nPhaseIdx] = fluidMatrixInteraction.krn(saturation(wPhaseIdx)); // porosity & permeabilty updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps); @@ -187,11 +191,14 @@ public: const auto& priVars = elemSol[scv.localDofIndex()]; const auto phasePresence = priVars.state(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); const auto wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + // set the saturations if (phasePresence == secondPhaseOnly) { @@ -220,7 +227,7 @@ public: DUNE_THROW(Dune::InvalidStateException, "Invalid phase presence."); // set pressures of the fluid phases - pc_ = MaterialLaw::pc(materialParams, fluidState.saturation(wPhaseIdx)); + pc_ = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx)); if (formulation == TwoPFormulation::p0s1) { fluidState.setPressure(phase0Idx, priVars[pressureIdx]); diff --git a/dumux/porousmediumflow/mpnc/volumevariables.hh b/dumux/porousmediumflow/mpnc/volumevariables.hh index 1ab4d5ec0fd4dc1a8c56608ddb63dc995a02d6b7..0ce2f71a600bbac61bd40fef6a0fbb137fbd6b0e 100644 --- a/dumux/porousmediumflow/mpnc/volumevariables.hh +++ b/dumux/porousmediumflow/mpnc/volumevariables.hh @@ -26,13 +26,14 @@ #ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH #define DUMUX_MPNC_VOLUME_VARIABLES_HH +#include + #include #include #include #include #include -#include #include "pressureformulation.hh" namespace Dumux { @@ -72,6 +73,9 @@ class MPNCVolumeVariablesImplementation using EffDiffModel = typename Traits::EffectiveDiffusivityModel; using DiffusionCoefficients = typename Traits::DiffusionType::DiffusionCoefficientsContainer; + // remove this after deprecation period, i.e. after release 3.3 + static constexpr auto numPhases = std::integral_constant{}; + public: //! Export the type encapsulating primary variable indices using Indices = typename Traits::ModelTraits::Indices; @@ -108,13 +112,18 @@ public: completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); + // Old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported. + // We can safely use the two-p wrapper here without breaking compatibility because the MPAdapter only supports + // two phases anyway... + const auto fluidMatrixInteraction = Deprecated::makeMPPcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol, numPhases); + //calculate the remaining quantities - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); const int wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); // relative permeabilities - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - MPAdapter::relativePermeabilities(relativePermeability_, materialParams, fluidState_, wPhaseIdx); + const auto relPerm = fluidMatrixInteraction.relativePermeabilities(fluidState_, wPhaseIdx); + std::copy(relPerm.begin(), relPerm.end(), relativePermeability_.begin()); typename FluidSystem::ParameterCache paramCache; paramCache.updateAll(fluidState_); @@ -178,13 +187,15 @@ public: // capillary pressure parameters const int wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); - const auto& materialParams = - problem.spatialParams().materialLawParams(element, scv, elemSol); // capillary pressures - std::vector capPress(numFluidPhases()); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - MPAdapter::capillaryPressures(capPress, materialParams, fluidState, wPhaseIdx); + + // Old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported. + // We can safely use the two-p wrapper here without breaking compatibility because the MPAdapter only supports + // two phases anyway... + const auto fluidMatrixInteraction = Deprecated::makeMPPcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol, numPhases); + const auto capPress = fluidMatrixInteraction.capillaryPressures(fluidState, wPhaseIdx); // add to the pressure of the first fluid phase // depending on which pressure is stored in the primary variables @@ -513,6 +524,9 @@ class MPNCVolumeVariablesImplementation using EffDiffModel = typename Traits::EffectiveDiffusivityModel; using DiffusionCoefficients = typename Traits::DiffusionType::DiffusionCoefficientsContainer; + // remove this after deprecation period, i.e. after release 3.3 + static constexpr auto numPhases = std::integral_constant{}; + public: //! Export the underlying fluid system using FluidSystem = typename Traits::FluidSystem; @@ -549,13 +563,16 @@ public: completeFluidState(elemSol, problem, element, scv, fluidState_, solidState_); // calculate the remaining quantities - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); const int wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); - // relative permeabilities - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - MPAdapter::relativePermeabilities(relativePermeability_, materialParams, fluidState_, wPhaseIdx); + // Old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported. + const auto fluidMatrixInteraction = Deprecated::makeMPPcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol, numPhases); + + const auto relPerm = fluidMatrixInteraction.relativePermeabilities(fluidState_, wPhaseIdx); + std::copy(relPerm.begin(), relPerm.end(), relativePermeability_.begin()); + typename FluidSystem::ParameterCache paramCache; paramCache.updateAll(fluidState_); @@ -612,15 +629,17 @@ public: // set the phase pressures ///////////// // capillary pressure parameters - const auto& materialParams = - problem.spatialParams().materialLawParams(element, scv, elemSol); const int wPhaseIdx = problem.spatialParams().template wettingPhase(element, scv, elemSol); fluidState.setWettingPhase(wPhaseIdx); // capillary pressures - std::vector capPress(numFluidPhases()); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - MPAdapter::capillaryPressures(capPress, materialParams, fluidState, wPhaseIdx); + + // Old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported. + // We can safely use the two-p wrapper here without breaking compatibility because the MPAdapter only supports + // two phases anyway... + const auto fluidMatrixInteraction = Deprecated::makeMPPcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol, numPhases); + const auto capPress = fluidMatrixInteraction.capillaryPressures(fluidState, wPhaseIdx); // add to the pressure of the first fluid phase // depending on which pressure is stored in the primary variables diff --git a/dumux/porousmediumflow/nonequilibrium/volumevariables.hh b/dumux/porousmediumflow/nonequilibrium/volumevariables.hh index 54ec786a0876fab8f6d788f57e1e62efb51b0b21..d5081ccd67a4900a36fde374bd9b649327861709 100644 --- a/dumux/porousmediumflow/nonequilibrium/volumevariables.hh +++ b/dumux/porousmediumflow/nonequilibrium/volumevariables.hh @@ -36,6 +36,8 @@ #include #include +#include + namespace Dumux { /*! @@ -176,24 +178,23 @@ public: const Element& element, const Scv& scv) { - // obtain (standard) material parameters (needed for the residual saturations) - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); - - //obtain parameters for interfacial area constitutive relations - const auto& aWettingNonwettingSurfaceParams = problem.spatialParams().aWettingNonwettingSurfaceParams(element, scv, elemSol); - const Scalar pc = fluidState.pressure(phase1Idx) - fluidState.pressure(phase0Idx); const Scalar Sw = fluidState.saturation(phase0Idx); - using AwnSurface = typename Problem::SpatialParams::AwnSurface; - const auto awn = AwnSurface::interfacialArea(aWettingNonwettingSurfaceParams, materialParams, Sw, pc); + // old material law interface is deprecated: Replace this by + // const auto& wettingNonwettingInterfacialArea = spatialParams.wettingNonwettingInterfacialArea(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makeInterfacialArea(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + const auto awn = fluidMatrixInteraction.wettingNonwettingInterface().area(Sw, pc); interfacialArea_[phase0Idx][phase1Idx] = awn; interfacialArea_[phase1Idx][phase0Idx] = interfacialArea_[phase0Idx][phase1Idx]; interfacialArea_[phase0Idx][phase0Idx] = 0.; - using AnsSurface = typename Problem::SpatialParams::AnsSurface; - const auto& aNonwettingSolidSurfaceParams = problem.spatialParams().aNonwettingSolidSurfaceParams(element, scv, elemSol); - const auto ans = AnsSurface::interfacialArea(aNonwettingSolidSurfaceParams, materialParams, Sw, pc); + // old material law interface is deprecated: Replace this by + // const auto& nonwettingSolidInterfacialArea = spatialParams.nonwettingSolidInterfacialArea(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto ans = fluidMatrixInteraction.nonwettingSolidInterface().area(Sw, pc); // Switch for using a a_{wn} relations that has some "maximum capillary pressure" as parameter // That value is obtained by regularization of the pc(Sw) function. @@ -201,15 +202,17 @@ public: if (computeAwsFromAnsAndPcMax) { // I know the solid surface from the pore network. But it is more consistent to use the fit value. - const Scalar pcMax = aWettingNonwettingSurfaceParams.pcMax(); - const auto solidSurface = AnsSurface::interfacialArea(aNonwettingSolidSurfaceParams, materialParams, /*Sw=*/0., pcMax); + const Scalar pcMax = fluidMatrixInteraction.wettingNonwettingInterface().basicParams().pcMax(); + const auto solidSurface = fluidMatrixInteraction.nonwettingSolidInterface().area(/*Sw=*/0., pcMax); interfacialArea_[phase0Idx][sPhaseIdx] = solidSurface - ans; } else { - using AwsSurface = typename Problem::SpatialParams::AwsSurface; - const auto& aWettingSolidSurfaceParams = problem.spatialParams().aWettingSolidSurfaceParams(element, scv, elemSol); - interfacialArea_[phase0Idx][sPhaseIdx] = AwsSurface::interfacialArea(aWettingSolidSurfaceParams, materialParams, Sw, pc); + // old material law interface is deprecated: Replace this by + // const auto& wettingSolidInterfacialArea = spatialParams.wettingSolidInterfacialArea(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makeInterfacialArea(Scalar{}, problem.spatialParams(), element, scv, elemSol); + interfacialArea_[phase0Idx][sPhaseIdx] = fluidMatrixInteraction.wettingSolidInterface().area(Sw, pc); } interfacialArea_[sPhaseIdx][phase0Idx] = interfacialArea_[phase0Idx][sPhaseIdx]; @@ -536,16 +539,17 @@ public: const Scv& scv) { // obtain parameters for awnsurface and material law - const auto& awnSurfaceParams = problem.spatialParams().aWettingNonwettingSurfaceParams(element, scv, elemSol) ; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol) ; + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makeInterfacialArea(Scalar{}, problem.spatialParams(), element, scv, elemSol); const auto Sw = fluidState.saturation(phase0Idx) ; const auto pc = fluidState.pressure(phase1Idx) - fluidState.pressure(phase0Idx); // when we only consider chemical non-equilibrium there is only mass transfer between - // the fluid phases, so in 2p only interfacial area between wetting and nonwetting - using AwnSurface = typename Problem::SpatialParams::AwnSurface; - interfacialArea_ = AwnSurface::interfacialArea(awnSurfaceParams, materialParams, Sw, pc); + // the fluid phases, so in 2p only interfacial area between wetting and non-wetting + interfacialArea_ = fluidMatrixInteraction.wettingNonwettingInterface().area(Sw, pc); } /*! @@ -720,24 +724,20 @@ public: const Element& element, const Scv& scv) { - // obtain (standard) material parameters (needed for the residual saturations) - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); - - //obtain parameters for interfacial area constitutive relations - const auto& aWettingNonwettingSurfaceParams = problem.spatialParams().aWettingNonwettingSurfaceParams(element, scv, elemSol); - const Scalar pc = fluidState.pressure(phase1Idx) - fluidState.pressure(phase0Idx); const Scalar Sw = fluidState.saturation(phase0Idx); - using AwnSurface = typename Problem::SpatialParams::AwnSurface; - const auto awn = AwnSurface::interfacialArea(aWettingNonwettingSurfaceParams, materialParams, Sw, pc); + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makeInterfacialArea(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + const auto awn = fluidMatrixInteraction.wettingNonwettingInterface().area(Sw, pc); interfacialArea_[phase0Idx][phase1Idx] = awn; interfacialArea_[phase1Idx][phase0Idx] = interfacialArea_[phase0Idx][phase1Idx]; interfacialArea_[phase0Idx][phase0Idx] = 0.; - using AnsSurface = typename Problem::SpatialParams::AnsSurface; - const auto& aNonwettingSolidSurfaceParams = problem.spatialParams().aNonwettingSolidSurfaceParams(element, scv, elemSol); - const auto ans = AnsSurface::interfacialArea(aNonwettingSolidSurfaceParams, materialParams, Sw, pc); + const auto ans = fluidMatrixInteraction.nonwettingSolidInterface().area(Sw, pc); // Switch for using a a_{wn} relations that has some "maximum capillary pressure" as parameter. // That value is obtained by regularization of the pc(Sw) function. @@ -745,16 +745,12 @@ public: if (computeAwsFromAnsAndPcMax) { // I know the solid surface from the pore network. But it is more consistent to use the fit value. - const Scalar pcMax = aWettingNonwettingSurfaceParams.pcMax(); - const auto solidSurface = AnsSurface::interfacialArea(aNonwettingSolidSurfaceParams, materialParams, /*Sw=*/0., pcMax); + const Scalar pcMax = fluidMatrixInteraction.wettingNonwettingInterface().basicParams().pcMax(); + const auto solidSurface = fluidMatrixInteraction.nonwettingSolidInterface().area(/*Sw=*/0., pcMax); interfacialArea_[phase0Idx][sPhaseIdx] = solidSurface - ans; } else - { - using AwsSurface = typename Problem::SpatialParams::AwsSurface; - const auto& aWettingSolidSurfaceParams = problem.spatialParams().aWettingSolidSurfaceParams(element, scv, elemSol); - interfacialArea_[phase0Idx][sPhaseIdx] = AwsSurface::interfacialArea(aWettingSolidSurfaceParams, materialParams, Sw, pc); - } + interfacialArea_[phase0Idx][sPhaseIdx] = fluidMatrixInteraction.wettingSolidInterface().area(Sw, pc); interfacialArea_[sPhaseIdx][phase0Idx] = interfacialArea_[phase0Idx][sPhaseIdx]; interfacialArea_[sPhaseIdx][sPhaseIdx] = 0.; diff --git a/dumux/porousmediumflow/richards/localresidual.hh b/dumux/porousmediumflow/richards/localresidual.hh index dbf42d9544fe49857ae86e3bb1608d2d81d4e0f5..748e978a43e416182807a176f57a262d02bf0238 100644 --- a/dumux/porousmediumflow/richards/localresidual.hh +++ b/dumux/porousmediumflow/richards/localresidual.hh @@ -33,6 +33,8 @@ #include #include +#include + namespace Dumux { /*! @@ -198,13 +200,14 @@ public: const auto poreVolume = Extrusion::volume(scv)*curVolVars.porosity(); static const auto rho = curVolVars.density(0); - // material law for pc-sw - const auto& matParams = problem.spatialParams().materialLawParams(element, scv, InvalidElemSol{}); + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, InvalidElemSol{}); // partial derivative of storage term w.r.t. p_w // d(Sw*rho*phi*V/dt)/dpw = rho*phi*V/dt*dsw/dpw = rho*phi*V/dt*dsw/dpc*dpc/dpw = -rho*phi*V/dt*dsw/dpc - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - partialDerivatives[conti0EqIdx][0] += -rho*poreVolume/this->timeLoop().timeStepSize()*MaterialLaw::dsw_dpc(matParams, curVolVars.capillaryPressure()); + partialDerivatives[conti0EqIdx][0] += -rho*poreVolume/this->timeLoop().timeStepSize()*fluidMatrixInteraction.dsw_dpc(curVolVars.capillaryPressure()); } /*! @@ -267,8 +270,6 @@ public: const auto& outsideScv = fvGeometry.scv(outsideScvIdx); const auto& insideVolVars = curElemVolVars[insideScvIdx]; const auto& outsideVolVars = curElemVolVars[outsideScvIdx]; - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, InvalidElemSol{}); - const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(outsideElement, outsideScv, InvalidElemSol{}); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho = insideVolVars.density(0); @@ -284,16 +285,21 @@ public: const auto outsideWeight = 1.0 - insideWeight; const auto upwindTerm = rho*insideVolVars.mobility(0)*insideWeight + rho*outsideVolVars.mobility(0)*outsideWeight; + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto insideFluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, insideScv, InvalidElemSol{}); + const auto outsideFluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), outsideElement, outsideScv, InvalidElemSol{}); + // material law derivatives const auto insideSw = insideVolVars.saturation(0); const auto outsideSw = outsideVolVars.saturation(0); const auto insidePc = insideVolVars.capillaryPressure(); const auto outsidePc = outsideVolVars.capillaryPressure(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto dkrw_dsw_inside = MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); - const auto dkrw_dsw_outside = MaterialLaw::dkrw_dsw(outsideMaterialParams, outsideSw); - const auto dsw_dpw_inside = -MaterialLaw::dsw_dpc(insideMaterialParams, insidePc); - const auto dsw_dpw_outside = -MaterialLaw::dsw_dpc(outsideMaterialParams, outsidePc); + const auto dkrw_dsw_inside = insideFluidMatrixInteraction.dkrw_dsw(insideSw); + const auto dkrw_dsw_outside = outsideFluidMatrixInteraction.dkrw_dsw(outsideSw); + const auto dsw_dpw_inside = -insideFluidMatrixInteraction.dsw_dpc(insidePc); + const auto dsw_dpw_outside = -outsideFluidMatrixInteraction.dsw_dpc(outsidePc); // the transmissibility const auto tij = elemFluxVarsCache[scvf].advectionTij(); @@ -342,8 +348,6 @@ public: const auto& outsideScv = fvGeometry.scv(outsideScvIdx); const auto& insideVolVars = curElemVolVars[insideScvIdx]; const auto& outsideVolVars = curElemVolVars[outsideScvIdx]; - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, InvalidElemSol{}); - const auto& outsideMaterialParams = problem.spatialParams().materialLawParams(element, outsideScv, InvalidElemSol{}); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho = insideVolVars.density(0); @@ -359,16 +363,21 @@ public: const auto outsideWeight = 1.0 - insideWeight; const auto upwindTerm = rho*insideVolVars.mobility(0)*insideWeight + rho*outsideVolVars.mobility(0)*outsideWeight; + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto insideFluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, insideScv, InvalidElemSol{}); + const auto outsideFluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, outsideScv, InvalidElemSol{}); + // material law derivatives const auto insideSw = insideVolVars.saturation(0); const auto outsideSw = outsideVolVars.saturation(0); const auto insidePc = insideVolVars.capillaryPressure(); const auto outsidePc = outsideVolVars.capillaryPressure(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto dkrw_dsw_inside = MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); - const auto dkrw_dsw_outside = MaterialLaw::dkrw_dsw(outsideMaterialParams, outsideSw); - const auto dsw_dpw_inside = -MaterialLaw::dsw_dpc(insideMaterialParams, insidePc); - const auto dsw_dpw_outside = -MaterialLaw::dsw_dpc(outsideMaterialParams, outsidePc); + const auto dkrw_dsw_inside = insideFluidMatrixInteraction.dkrw_dsw(insideSw); + const auto dkrw_dsw_outside = outsideFluidMatrixInteraction.dkrw_dsw(outsideSw); + const auto dsw_dpw_inside = -insideFluidMatrixInteraction.dsw_dpc(insidePc); + const auto dsw_dpw_outside = -outsideFluidMatrixInteraction.dsw_dpc(outsidePc); // so far it was the same as for tpfa // the transmissibilities (flux derivatives with respect to all pw-dofs on the element) @@ -439,7 +448,11 @@ public: const auto& insideScv = fvGeometry.scv(insideScvIdx); const auto& insideVolVars = curElemVolVars[insideScvIdx]; const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()]; - const auto& insideMaterialParams = problem.spatialParams().materialLawParams(element, insideScv, InvalidElemSol{}); + + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto insideFluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, insideScv, InvalidElemSol{}); // some quantities to be reused (rho & mu are constant and thus equal for all cells) static const auto rho = insideVolVars.density(0); @@ -458,9 +471,8 @@ public: // material law derivatives const auto insideSw = insideVolVars.saturation(0); const auto insidePc = insideVolVars.capillaryPressure(); - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto dkrw_dsw_inside = MaterialLaw::dkrw_dsw(insideMaterialParams, insideSw); - const auto dsw_dpw_inside = -MaterialLaw::dsw_dpc(insideMaterialParams, insidePc); + const auto dkrw_dsw_inside = insideFluidMatrixInteraction.dkrw_dsw(insideSw); + const auto dsw_dpw_inside = -insideFluidMatrixInteraction.dsw_dpc(insidePc); // the transmissibility const auto tij = elemFluxVarsCache[scvf].advectionTij(); diff --git a/dumux/porousmediumflow/richards/newtonsolver.hh b/dumux/porousmediumflow/richards/newtonsolver.hh index fd3e9dbbd53af8be86659c77a6b205b7ac342fa7..007506df957afe1b472f6137fd1e92b0c36cf828 100644 --- a/dumux/porousmediumflow/richards/newtonsolver.hh +++ b/dumux/porousmediumflow/richards/newtonsolver.hh @@ -26,6 +26,8 @@ #define DUMUX_RICHARDS_NEWTON_SOLVER_HH #include +#include +#include #include #include @@ -44,8 +46,6 @@ class RichardsNewtonSolver : public NewtonSolver using Scalar = typename Assembler::Scalar; using ParentType = NewtonSolver; using SolutionVector = typename Assembler::ResidualType; - - using MaterialLaw = typename Assembler::Problem::SpatialParams::MaterialLaw; using Indices = typename Assembler::GridVariables::VolumeVariables::Indices; enum { pressureIdx = Indices::pressureIdx }; @@ -86,17 +86,22 @@ private: // calculate the old wetting phase saturation const auto& spatialParams = this->assembler().problem().spatialParams(); const auto elemSol = elementSolution(element, uCurrentIter, gridGeometry); - const auto& materialLawParams = spatialParams.materialLawParams(element, scv, elemSol); - const Scalar pcMin = MaterialLaw::pc(materialLawParams, 1.0); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.1, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, spatialParams, element, scv, elemSol); + + const Scalar pcMin = fluidMatrixInteraction.pc(1.0); const Scalar pw = uLastIter[dofIdxGlobal][pressureIdx]; using std::max; const Scalar pn = max(this->assembler().problem().nonwettingReferencePressure(), pw + pcMin); const Scalar pcOld = pn - pw; - const Scalar SwOld = max(0.0, MaterialLaw::sw(materialLawParams, pcOld)); + const Scalar SwOld = max(0.0, fluidMatrixInteraction.sw(pcOld)); // convert into minimum and maximum wetting phase pressures - const Scalar pwMin = pn - MaterialLaw::pc(materialLawParams, SwOld - 0.2); - const Scalar pwMax = pn - MaterialLaw::pc(materialLawParams, SwOld + 0.2); + const Scalar pwMin = pn - fluidMatrixInteraction.pc(SwOld - 0.2); + const Scalar pwMax = pn - fluidMatrixInteraction.pc(SwOld + 0.2); // clamp the result using std::clamp; diff --git a/dumux/porousmediumflow/richards/volumevariables.hh b/dumux/porousmediumflow/richards/volumevariables.hh index 218e88abfc5bf6132d6ec47760bef839f0e68ae3..3410489549e847e57fbd310367e12636a402578b 100644 --- a/dumux/porousmediumflow/richards/volumevariables.hh +++ b/dumux/porousmediumflow/richards/volumevariables.hh @@ -29,6 +29,8 @@ #include +#include + #include #include #include @@ -48,7 +50,7 @@ struct VolVarsWithPVSwitch struct VolVarsWithOutPVSwitch {}; -} +} // end namespace Detail /*! * \ingroup RichardsModel @@ -105,14 +107,18 @@ public: const Scv& scv) { ParentType::update(elemSol, problem, element, scv); - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + + // old material law interface is deprecated: Replace this by + // const auto fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto& priVars = elemSol[scv.localDofIndex()]; const auto phasePresence = priVars.state(); // precompute the minimum capillary pressure (entry pressure) // needed to make sure we don't compute unphysical capillary pressures and thus saturations - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - minPc_ = MaterialLaw::endPointPc(materialParams); + minPc_ = fluidMatrixInteraction.endPointPc(); typename FluidSystem::ParameterCache paramCache; auto getEffectiveDiffusionCoefficient = [&](int phaseIdx, int compIIdx, int compJIdx) @@ -138,7 +144,7 @@ public: EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState_, solidState_); // get pc for sw = 0.0 - const Scalar pc = MaterialLaw::pc(materialParams, 0.0); + const Scalar pc = fluidMatrixInteraction.pc(0.0); // set the wetting pressure fluidState_.setPressure(FluidSystem::liquidPhaseIdx, problem.nonwettingReferencePressure() - pc); @@ -215,7 +221,7 @@ public: ////////// // specify the other parameters ////////// - relativePermeabilityWetting_ = MaterialLaw::krw(materialParams, fluidState_.saturation(FluidSystem::liquidPhaseIdx)); + relativePermeabilityWetting_ = fluidMatrixInteraction.krw(fluidState_.saturation(FluidSystem::liquidPhaseIdx)); updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, numFluidComps); EnergyVolVars::updateSolidEnergyParams(elemSol, problem, element, scv, solidState_); permeability_ = problem.spatialParams().permeability(element, scv, elemSol); @@ -246,13 +252,16 @@ public: { EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState, solidState); - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto& priVars = elemSol[scv.localDofIndex()]; // set the wetting pressure using std::max; - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - Scalar minPc = MaterialLaw::pc(materialParams, 1.0); + Scalar minPc = fluidMatrixInteraction.pc(1.0); fluidState.setPressure(FluidSystem::liquidPhaseIdx, priVars[Indices::pressureIdx]); fluidState.setPressure(FluidSystem::gasPhaseIdx, max(problem.nonwettingReferencePressure(), fluidState.pressure(FluidSystem::liquidPhaseIdx) + minPc)); @@ -260,9 +269,9 @@ public: // make sure that we the capillary pressure is not smaller than the minimum pc // this would possibly return unphysical values from regularized material laws using std::max; - const Scalar pc = max(MaterialLaw::endPointPc(materialParams), + const Scalar pc = max(fluidMatrixInteraction.endPointPc(), problem.nonwettingReferencePressure() - fluidState.pressure(FluidSystem::liquidPhaseIdx)); - const Scalar sw = MaterialLaw::sw(materialParams, pc); + const Scalar sw = fluidMatrixInteraction.sw(pc); fluidState.setSaturation(FluidSystem::liquidPhaseIdx, sw); fluidState.setSaturation(FluidSystem::gasPhaseIdx, 1.0-sw); diff --git a/dumux/porousmediumflow/richardsnc/volumevariables.hh b/dumux/porousmediumflow/richardsnc/volumevariables.hh index 6e2194f452ce513d7bed5154b9154ed644ad4d81..1ebae93f9a814a66f29b3b67e5d8eaff04ba6dfe 100644 --- a/dumux/porousmediumflow/richardsnc/volumevariables.hh +++ b/dumux/porousmediumflow/richardsnc/volumevariables.hh @@ -33,6 +33,8 @@ #include #include +#include + namespace Dumux { /*! @@ -93,13 +95,17 @@ public: ////////// // specify the other parameters ////////// - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); - relativePermeabilityWetting_ = MaterialLaw::krw(materialParams, fluidState_.saturation(0)); + + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + + relativePermeabilityWetting_ = fluidMatrixInteraction.krw(fluidState_.saturation(0)); // precompute the minimum capillary pressure (entry pressure) // needed to make sure we don't compute unphysical capillary pressures and thus saturations - minPc_ = MaterialLaw::endPointPc(materialParams); + minPc_ = fluidMatrixInteraction.endPointPc(); pn_ = problem.nonwettingReferencePressure(); //porosity updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, ParentType::numFluidComponents()); @@ -150,7 +156,11 @@ public: { EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState, solidState); - const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol); + // old material law interface is deprecated: Replace this by + // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteraction(element, scv, elemSol); + // after the release of 3.3, when the deprecated interface is no longer supported + const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(), element, scv, elemSol); + const auto& priVars = elemSol[scv.localDofIndex()]; // set the wetting pressure @@ -160,10 +170,9 @@ public: // make sure that we the capillary pressure is not smaller than the minimum pc // this would possibly return unphysical values from regularized material laws using std::max; - using MaterialLaw = typename Problem::SpatialParams::MaterialLaw; - const Scalar pc = max(MaterialLaw::endPointPc(materialParams), + const Scalar pc = max(fluidMatrixInteraction.endPointPc(), problem.nonwettingReferencePressure() - fluidState.pressure(0)); - const Scalar sw = MaterialLaw::sw(materialParams, pc); + const Scalar sw = fluidMatrixInteraction.sw(pc); fluidState.setSaturation(0, sw); // set the mole/mass fractions diff --git a/examples/2pinfiltration/params.input b/examples/2pinfiltration/params.input index e49c6f4dd3bbd9ab0506b05d11294a92bc13036b..ba7188008a148c58ddba8106c8461bb59d781d3e 100644 --- a/examples/2pinfiltration/params.input +++ b/examples/2pinfiltration/params.input @@ -11,6 +11,16 @@ Refinement = 1 LensLowerLeft = 1.0 2.0 # [m] coordinates of the lower left lens corner LensUpperRight = 4.0 3.0 # [m] coordinates of the upper right lens corner +[SpatialParams.Lens] +Swr = 0.18 +VanGenuchtenN = 7.3 +VanGenuchtenAlpha = 0.00045 + +[SpatialParams.Outer] +Swr = 0.05 +VanGenuchtenN = 4.7 +VanGenuchtenAlpha = 0.0037 + [Problem] Name = 2padaptive # name passed to the output routines diff --git a/examples/2pinfiltration/spatialparams.hh b/examples/2pinfiltration/spatialparams.hh index 7ef356def8016ad268c4658353d10f8ab481f678..23bca1f22c81c5c69fee233e75413566e091db93 100644 --- a/examples/2pinfiltration/spatialparams.hh +++ b/examples/2pinfiltration/spatialparams.hh @@ -28,8 +28,7 @@ #include // We include all laws which are needed to define the interaction between the solid matrix and the fluids, e.g. laws for capillary pressure saturation relationships. -#include -#include +#include // ### The spatial parameters class // In the TwoPTestSpatialParams class we define all functions needed to describe the porous matrix, e.g. porosity and permeability. We inherit from the `FVSpatialParams` class, which is the base class for multiphase porous medium flow applications. @@ -51,11 +50,9 @@ class TwoPTestSpatialParams static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; // [[/codeblock]] @@ -63,31 +60,18 @@ public: // [[codeblock]] TwoPTestSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwLens_("SpatialParams.Lens") // read params from input file + , pcKrSwOuter_("SpatialParams.Outer") // read params from input file { // We get the position of the lens from the params.input file. // The lens is defined by the position of the lower left and the upper right corner lensLowerLeft_ = getParam("SpatialParams.LensLowerLeft"); lensUpperRight_ = getParam("SpatialParams.LensUpperRight"); - // We set the parameters for the material law (here Van-Genuchten Law). - // First we set the residual saturations for the wetting phase and the nonwetting phase. - // lensMaterialParams_ define the material parameters for the lens while - // outerMaterialParams_ define material params for the rest of the domain. - lensMaterialParams_.setSwr(0.18); - lensMaterialParams_.setSnr(0.0); - outerMaterialParams_.setSwr(0.05); - outerMaterialParams_.setSnr(0.0); - - //We set the parameters for the Van Genuchten law alpha and n - lensMaterialParams_.setVgAlpha(0.00045); - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - outerMaterialParams_.setVgn(4.7); - - //Here, we get the permeabilities from the params.input file. - //In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used - lensK_ = getParam("SpatialParams.lensK", 9.05e-12); - outerK_ = getParam("SpatialParams.outerK", 4.6e-10); + // Here, we get the permeabilities from the params.input file. + // In case that no parameter is set, the default parameters (9.05e-12 and 4.6e-10) are used + lensK_ = getParam("SpatialParams.Lens.Permeability", 9.05e-12); + outerK_ = getParam("SpatialParams.Outer.Permeability", 4.6e-10); } // [[/codeblock]] @@ -112,13 +96,13 @@ public: // We set the parameter object for the Van Genuchten material law. template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { if (isInLens_(element.geometry().center())) - return lensMaterialParams_; - return outerMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwLens_); + return makeFluidMatrixInteraction(pcKrSwOuter_); } @@ -147,8 +131,9 @@ private: Scalar lensK_; Scalar outerK_; - MaterialLawParams lensMaterialParams_; - MaterialLawParams outerMaterialParams_; + + const PcKrSwCurve pcKrSwLens_; + const PcKrSwCurve pcKrSwOuter_; static constexpr Scalar eps_ = 1.5e-7; }; diff --git a/examples/biomineralization/params.input b/examples/biomineralization/params.input index 9ec5f2339709a7ad991a94f797d8402fe4aa9141..4aaa2e64c4da3b74ee60c0aaf2ba66e130a8410b 100644 --- a/examples/biomineralization/params.input +++ b/examples/biomineralization/params.input @@ -44,6 +44,10 @@ Cells = 56 # [-] number of cells in x,y-di [SpatialParams] ReferencePorosity = 0.4 # [-] ReferencePermeability = 2e-10 # [m^2] +BrooksCoreyPcEntry = 1e4 # [Pa] +BrooksCoreyLambda = 2.0 # [-] +Swr = 0.2 # [-] +Snr = 0.05 # [-] [BioCoefficients] Ca1 = 8.3753e-8 # [1/s] fitted parameter, see Hommel et al. 2015 diff --git a/examples/biomineralization/spatialparams.hh b/examples/biomineralization/spatialparams.hh index 68ab59cfe01a323b225d9e5229a7d25ed1000d69..ef9d00a88637d6df734b550600c4992fc20100a0 100644 --- a/examples/biomineralization/spatialparams.hh +++ b/examples/biomineralization/spatialparams.hh @@ -32,12 +32,8 @@ // [[details]] includes // We include the basic spatial parameters for finite volumes file from which we will inherit #include -// We include the files for the two-phase laws: the linear material law -#include -// We include the files for the two-phase laws: the regularized Brooks-Corey pc-Sw and relative permeability laws -#include -// We include the files for the two-phase laws: the scaling from effective to absolute saturations -#include +// We include the files for the two-phase laws: the Brooks-Corey pc-Sw and relative permeability laws +#include // We include the laws for changing porosity due to precipitation #include // We include the laws for changing permeability based on porosity change according to Kozeny-Carman @@ -61,34 +57,25 @@ class ICPSpatialParams using ThisType = ICPSpatialParams; using ParentType = FVSpatialParams; using GridView = typename GridGeometry::GridView; - using EffectiveLaw = RegularizedBrooksCorey; using SubControlVolume = typename GridGeometry::SubControlVolume; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; public: // type used for the permeability (i.e. tensor or scalar) using PermeabilityType = Scalar; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; // [[/codeblock]] // #### Using porosity and permeability laws to return the updated values // Due due calcium carbonate precipitation the porosity and the permeability change with time. At first, the initial values for the porosity and permeability are defined. Moreover, the functions that return the updated values, based on the chosen laws are defined. // [[codeblock]] ICPSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSw_("SpatialParams") // initialize from input file { // We read reference values for porosity and permeability from the input referencePorosity_ = getParam("SpatialParams.ReferencePorosity", 0.4); referencePermeability_ = getParam("SpatialParams.ReferencePermeability", 2.e-10); - - // Setting residual saturations - materialParams_.setSwr(0.2); - materialParams_.setSnr(0.05); - - // Setting parameters for the Brooks-Corey law - materialParams_.setPe(1e4); - materialParams_.setLambda(2.0); } // We return the reference or initial porosity. @@ -119,9 +106,9 @@ public: return permLaw_.evaluatePermeability(referencePermeability_, referencePorosity_, poro); } // [[/codeblock]] - // Return the brooks-corey context depending on the position - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + // Return the fluid matrix interactions (here only Brooks-Corey curves) + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { return makeFluidMatrixInteraction(pcKrSw_); } // Define the wetting phase template @@ -133,7 +120,7 @@ public: // [[codeblock]] private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSw_; // Setting porosity precipitation as the porosity law PorosityPrecipitation poroLaw_; // Setting the Kozeny-Carman porosity-permeability relation as the permeability law diff --git a/test/common/spline/test_monotonecubicspline.cc b/test/common/spline/test_monotonecubicspline.cc index dc59b47701e148291e17191ae651697dbb261440..04596dcb17bd52bccaf3c96e8ed0c1c2a4842da8 100644 --- a/test/common/spline/test_monotonecubicspline.cc +++ b/test/common/spline/test_monotonecubicspline.cc @@ -45,82 +45,109 @@ int main(int argc, char** argv) { Dune::MPIHelper::instance(argc, argv); - // we test the spline interpolation against a sample function - const auto f = [](double x){ return x*x*x; }; - const auto df = [](double x){ return 3*x*x; }; - - // create some test samples - const auto testPoints = Dumux::linspace(0.0, 4.0, 1000); - const auto ref = eval(f, testPoints); - const auto refDeriv = eval(df, testPoints); - - // create the spline sample points - const auto samplePoints = Dumux::linspace(0.0, 5.0, 10); - const auto y = eval(f, samplePoints); - - // create the spline - Dumux::MonotoneCubicSpline spline(samplePoints, y); - - // evaluate spline and derivative - const auto result = eval([&](const double x) { return spline.eval(x); }, testPoints); - const auto resultDeriv = eval([&](const double x) { return spline.evalDerivative(x); }, testPoints); - - // compute largest difference - auto diff = result; auto diffDeriv = result; - std::transform(result.begin(), result.end(), ref.begin(), diff.begin(), [](auto a, auto b){ return std::abs(a-b); }); - std::transform(resultDeriv.begin(), resultDeriv.end(), refDeriv.begin(), diffDeriv.begin(), [](auto a, auto b){ return std::abs(a-b); }); - const auto maxNorm = std::accumulate(diff.begin(), diff.end(), diff[0], [](auto a, auto b){ return std::max(a, b); }) - /(*std::max_element(ref.begin(), ref.end())); - const auto maxNormDeriv = std::accumulate(diffDeriv.begin(), diffDeriv.end(), diffDeriv[0], [](auto a, auto b){ return std::max(a, b); }) - /(*std::max_element(refDeriv.begin(), refDeriv.end())); - std::cout << "Maximum error: " << maxNorm << "\n"; - std::cout << "Maximum error in derivative: " << maxNormDeriv << "\n"; - - if (maxNorm > 0.0008 || maxNormDeriv > 0.013) - DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); - - // test inverse by evaluating (x = f^-1(f(x))) for monotonically increasing function + const auto test = [](auto f, auto df, const auto& testPoints, const auto& samplePoints, const std::string& prefix) { - const auto resultX = eval([&](double x){ return spline.evalInverse(spline.eval(x)); }, testPoints); - auto diffInverse = resultX; - std::transform(resultX.begin(), resultX.end(), testPoints.begin(), diffInverse.begin(), [](auto a, auto b){ return std::abs(a-b); }); - const auto maxNormInverse = std::accumulate(diffInverse.begin(), diffInverse.end(), diffInverse[0], [](auto a, auto b){ return std::max(a, b); }) - /(*std::max_element(testPoints.begin(), testPoints.end())); + // create some test samples + const auto ref = eval(f, testPoints); + const auto refDeriv = eval(df, testPoints); + + // create the spline sample points + const auto y = eval(f, samplePoints); + + // create the spline + Dumux::MonotoneCubicSpline spline(samplePoints, y); + + // evaluate spline and derivative + const auto result = eval([&](const double x) { return spline.eval(x); }, testPoints); + const auto resultDeriv = eval([&](const double x) { return spline.evalDerivative(x); }, testPoints); + + // compute largest difference + auto diff = result; auto diffDeriv = result; + std::transform(result.begin(), result.end(), ref.begin(), diff.begin(), [](auto a, auto b){ return std::abs(a-b); }); + std::transform(resultDeriv.begin(), resultDeriv.end(), refDeriv.begin(), diffDeriv.begin(), [](auto a, auto b){ return std::abs(a-b); }); + const auto maxNorm = std::accumulate(diff.begin(), diff.end(), diff[0], [](auto a, auto b){ return std::max(a, b); }) + /std::abs(*std::max_element(ref.begin(), ref.end(), [](auto a, auto b){ return abs(a) < abs(b); })); + const auto maxNormDeriv = std::accumulate(diffDeriv.begin(), diffDeriv.end(), diffDeriv[0], [](auto a, auto b){ return std::max(a, b); }) + /std::abs(*std::max_element(refDeriv.begin(), refDeriv.end(), [](auto a, auto b){ return abs(a) < abs(b); })); + std::cout << "Maximum error: " << std::scientific << maxNorm << "\n"; + std::cout << "Maximum error in derivative: " << std::scientific << maxNormDeriv << "\n"; + + if (maxNorm > 0.0008 || maxNormDeriv > 0.013) + DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); + // test inverse by evaluating (x = f^-1(f(x))) for monotonically increasing function + { + const auto resultX = eval([&](double x){ return spline.evalInverse(spline.eval(x)); }, testPoints); + auto diffInverse = resultX; + std::transform(resultX.begin(), resultX.end(), testPoints.begin(), diffInverse.begin(), [](auto a, auto b){ return std::abs(a-b); }); + const auto maxNormInverse = std::accumulate(diffInverse.begin(), diffInverse.end(), diffInverse[0], [](auto a, auto b){ return std::max(a, b); }) + /std::abs(*std::max_element(testPoints.begin(), testPoints.end(), [](auto a, auto b){ return abs(a) < abs(b); })); + + + std::cout << "Maximum error in identity using the inverse (mon. incr.): " << std::scientific << maxNormInverse << "\n"; + if (maxNormInverse > 1e-13) + DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); + } + // test inverse by evaluating (x = f^-1(f(x))) for monotonically decreasing function + { + auto reverseTest = testPoints; + std::reverse(reverseTest.begin(), reverseTest.end()); + const auto resultX = eval([&](double x){ return spline.evalInverse(spline.eval(x)); }, reverseTest); + auto diffInverse = resultX; + std::transform(resultX.begin(), resultX.end(), reverseTest.begin(), diffInverse.begin(), [](auto a, auto b){ return std::abs(a-b); }); + const auto maxNormInverse = std::accumulate(diffInverse.begin(), diffInverse.end(), diffInverse[0], [](auto a, auto b){ return std::max(a, b); }) + /std::abs(*std::max_element(reverseTest.begin(), reverseTest.end(), [](auto a, auto b){ return abs(a) < abs(b); })); + + std::cout << "Maximum error in identity using the inverse (mon. decr.): " << std::scientific << maxNormInverse << "\n"; + if (maxNormInverse > 1e-13) + DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); + } + + // plot with Gnuplot (plot a bit more so we can see the linear extension) + const auto plotPoints = Dumux::linspace(-1.0, 5.0, 1000); + const auto refPlot = eval(f, plotPoints); + const auto refDerivPlot = eval(df, plotPoints); + const auto resultPlot = eval([&](const double x) { return spline.eval(x); }, plotPoints); + const auto resultDerivPlot = eval([&](const double x) { return spline.evalDerivative(x); }, plotPoints); + + Dumux::GnuplotInterface gnuplot(/*persist=*/false); + gnuplot.setOpenPlotWindow(false); + gnuplot.addDataSetToPlot(plotPoints, refPlot, prefix + "exp_reference"); + gnuplot.addDataSetToPlot(plotPoints, refDerivPlot, prefix + "exp_reference_derivative"); + gnuplot.addDataSetToPlot(plotPoints, resultPlot, prefix + "monotspline"); + gnuplot.addDataSetToPlot(plotPoints, resultDerivPlot, prefix + "monotspline_derivative"); + gnuplot.plot(prefix + "monotspline"); + }; - std::cout << "Maximum error in identity using the inverse (mon. incr.): " << std::scientific << maxNormInverse << "\n"; - if (maxNormInverse > 1e-13) - DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); - } - // test inverse by evaluating (x = f^-1(f(x))) for monotonically decreasing function { - auto reverseTest = testPoints; - std::reverse(reverseTest.begin(), reverseTest.end()); - const auto resultX = eval([&](double x){ return spline.evalInverse(spline.eval(x)); }, reverseTest); - auto diffInverse = resultX; - std::transform(resultX.begin(), resultX.end(), reverseTest.begin(), diffInverse.begin(), [](auto a, auto b){ return std::abs(a-b); }); - const auto maxNormInverse = std::accumulate(diffInverse.begin(), diffInverse.end(), diffInverse[0], [](auto a, auto b){ return std::max(a, b); }) - /(*std::max_element(reverseTest.begin(), reverseTest.end())); - - std::cout << "Maximum error in identity using the inverse (mon. decr.): " << std::scientific << maxNormInverse << "\n"; - if (maxNormInverse > 1e-13) - DUNE_THROW(Dune::Exception, "Maximum error in spline interpolation too large!"); + // we test the spline interpolation against a sample function + // monotonically increasing function + const auto f = [](double x){ return x*x*x; }; + const auto df = [](double x){ return 3*x*x; }; + + const auto testPoints = Dumux::linspace(0.0, 4.0, 1000); + const auto samplePoints = Dumux::linspace(0.0, 5.0, 10); + test(f, df, testPoints, samplePoints, "x3in"); + + const auto testPoints2 = Dumux::linspace(4.0, 0.0, 1000); + const auto samplePoints2 = Dumux::linspace(5.0, 0.0, 10); + test(f, df, testPoints2, samplePoints2, "x3de"); } - // plot with Gnuplot (plot a bit more so we can see the linear extension) - const auto plotPoints = Dumux::linspace(-1.0, 5.0, 1000); - const auto refPlot = eval(f, plotPoints); - const auto refDerivPlot = eval(df, plotPoints); - const auto resultPlot = eval([&](const double x) { return spline.eval(x); }, plotPoints); - const auto resultDerivPlot = eval([&](const double x) { return spline.evalDerivative(x); }, plotPoints); - - Dumux::GnuplotInterface gnuplot(/*persist=*/false); - gnuplot.setOpenPlotWindow(false); - gnuplot.addDataSetToPlot(plotPoints, refPlot, "exp_reference"); - gnuplot.addDataSetToPlot(plotPoints, refDerivPlot, "exp_reference_derivative"); - gnuplot.addDataSetToPlot(plotPoints, resultPlot, "monotspline"); - gnuplot.addDataSetToPlot(plotPoints, resultDerivPlot, "monotspline_derivative"); - gnuplot.plot("monotspline"); + { + // we test the spline interpolation against a sample function + // monotonically decreasing function + const auto f = [](double x){ return -x*x*x; }; + const auto df = [](double x){ return -3*x*x; }; + + const auto testPoints = Dumux::linspace(0.0, 4.0, 1000); + const auto samplePoints = Dumux::linspace(0.0, 5.0, 10); + test(f, df, testPoints, samplePoints, "mx3in"); + + const auto testPoints2 = Dumux::linspace(4.0, 0.0, 1000); + const auto samplePoints2 = Dumux::linspace(5.0, 0.0, 10); + test(f, df, testPoints2, samplePoints2, "mx3de"); + } return 0; } diff --git a/test/material/compositionalflash/test_compositionalflash.cc b/test/material/compositionalflash/test_compositionalflash.cc index f7eeafed72c9e89f5a9c5ea25ec8efe205fbca92..50f24900c96e5904e187de040babb117d53f007c 100644 --- a/test/material/compositionalflash/test_compositionalflash.cc +++ b/test/material/compositionalflash/test_compositionalflash.cc @@ -39,10 +39,7 @@ #include #include -#include -#include -#include -#include +#include #include @@ -91,7 +88,7 @@ void checkSame(const FluidState1 &fsRef, const FluidState2 &fsFlash) } } -template +template void checkCompositionalFlash(const FluidState &fsRef) { enum { numPhases = FluidSystem::numPhases }; @@ -122,7 +119,7 @@ void checkCompositionalFlash(const FluidState &fsRef) checkSame(fsRef, fsFlash); } -template +template void checkCompositionalFlashSequential(const FluidState &fsRef, int refPhaseIdx) { enum { numPhases = FluidSystem::numPhases }; @@ -154,13 +151,12 @@ void checkCompositionalFlashSequential(const FluidState &fsRef, int refPhaseIdx) template void completeReferenceFluidState(FluidState &fs, - typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int refPhaseIdx) { enum { numPhases = FluidSystem::numPhases }; using ComputeFromReferencePhase = Dumux::ComputeFromReferencePhase; - using PhaseVector = Dune::FieldVector; int otherPhaseIdx = 1 - refPhaseIdx; @@ -168,8 +164,7 @@ void completeReferenceFluidState(FluidState &fs, fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx)); // calulate the capillary pressure - PhaseVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, /*liquidPhaseIdx=*/0); + const auto pc = material.capillaryPressures(fs, /*liquidPhaseIdx=*/0); fs.setPressure(otherPhaseIdx, fs.pressure(refPhaseIdx) + (pc[otherPhaseIdx] - pc[refPhaseIdx])); @@ -184,7 +179,7 @@ void completeReferenceFluidState(FluidState &fs, template void completeReferenceFluidStateSequential(FluidState &fs, - typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int refPhaseIdx) { enum { numPhases = FluidSystem::numPhases }; @@ -200,8 +195,7 @@ void completeReferenceFluidStateSequential(FluidState &fs, (1. - fs.moleFraction(refPhaseIdx, 0)) * FluidSystem::molarMass(1)); // calulate the capillary pressure - PhaseVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, /*liquidPhaseIdx=*/0); + const auto pc = material.capillaryPressures(fs, /*liquidPhaseIdx=*/0); PhaseVector phasePressures(0.0); phasePressures[refPhaseIdx] = fs.pressure(refPhaseIdx); @@ -230,10 +224,8 @@ int main() enum { H2OIdx = FluidSystem::H2OIdx }; enum { N2Idx = FluidSystem::N2Idx }; - using EffMaterialLaw = Dumux::RegularizedBrooksCorey; - using MaterialLaw = Dumux::EffToAbsLaw; - using MaterialLawParams = MaterialLaw::Params; - using MPAdapter = Dumux::MPAdapter; + using MaterialLaw = Dumux::FluidMatrix::BrooksCoreyDefault; + using MPAdapter = Dumux::FluidMatrix::MPAdapter; Scalar T = 273.15 + 25; @@ -249,11 +241,8 @@ int main() FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np); // set the parameters for the capillary pressure law - MaterialLawParams matParams; - matParams.setSwr(0.0); - matParams.setSnr(0.0); - matParams.setPe(0); - matParams.setLambda(2.0); + MaterialLaw pcKrSw(typename MaterialLaw::BasicParams{/*pe*/0.0, /*lambda*/2.0}); + MPAdapter material(pcKrSw); CompositionalFluidState fsRef; FluidState1p2c fsRefSeq; @@ -287,18 +276,18 @@ int main() fsRef.setWettingPhase(wPhaseIdx); // "complete" the fluid state - completeReferenceFluidState(fsRef, matParams, liquidPhaseIdx); + completeReferenceFluidState(fsRef, material, liquidPhaseIdx); // check the flash calculation - checkCompositionalFlash(fsRef); + checkCompositionalFlash(fsRef); std::cout << "testing single-phase liquid for consistency with other sequential routines\n"; // "complete" the fluid state - completeReferenceFluidStateSequential(fsRefSeq, matParams, liquidPhaseIdx); + completeReferenceFluidStateSequential(fsRefSeq, material, liquidPhaseIdx); // check the flash calculation - checkCompositionalFlashSequential(fsRefSeq, liquidPhaseIdx); + checkCompositionalFlashSequential(fsRefSeq, liquidPhaseIdx); //////////////// // only gas @@ -319,18 +308,18 @@ int main() fsRefSeq.setMoleFraction(gasPhaseIdx, H2OIdx, 0.001); // "complete" the fluid state - completeReferenceFluidState(fsRef, matParams, gasPhaseIdx); + completeReferenceFluidState(fsRef, material, gasPhaseIdx); // check the flash calculation - checkCompositionalFlash(fsRef); + checkCompositionalFlash(fsRef); std::cout << "testing single-phase gas for consistency with other sequential routines\n"; // "complete" the fluid state - completeReferenceFluidStateSequential(fsRefSeq, matParams, gasPhaseIdx); + completeReferenceFluidStateSequential(fsRefSeq, material, gasPhaseIdx); // check the flash calculation - checkCompositionalFlashSequential(fsRefSeq, gasPhaseIdx); + checkCompositionalFlashSequential(fsRefSeq, gasPhaseIdx); //////////////// // both phases @@ -350,7 +339,7 @@ int main() MiscibleMultiPhaseComposition::solve(fsRef, paramCache); // check the flash calculation - checkCompositionalFlash(fsRef); + checkCompositionalFlash(fsRef); std::cout << "testing two-phase for consistency with other sequential routines\n"; @@ -363,18 +352,15 @@ int main() pressures, 0/*dummy*/, fsRef.temperature(0)); // check the flash calculation - checkCompositionalFlash(fsRef); + checkCompositionalFlash(fsRef); //////////////// // with capillary pressure //////////////// std::cout << "testing two-phase against implicit routines, including capillary pressure\n"; - MaterialLawParams matParams2; - matParams2.setSwr(0.0); - matParams2.setSnr(0.0); - matParams2.setPe(1e3); - matParams2.setLambda(2.0); + MaterialLaw pcKrS2(typename MaterialLaw::BasicParams{/*pe*/1e3, /*lambda*/2.0}); + MPAdapter material2(pcKrS2); // set gas saturation fsRef.setSaturation(gasPhaseIdx, 0.5); @@ -384,8 +370,7 @@ int main() fsRef.setPressure(liquidPhaseIdx, 1e6); // calulate the capillary pressure - PhaseVector pc; - MPAdapter::capillaryPressures(pc, matParams2, fsRef, /*wPhaseIdx=*/0); + const auto pc = material2.capillaryPressures(fsRef, /*wPhaseIdx=*/0); fsRef.setPressure(gasPhaseIdx, fsRef.pressure(liquidPhaseIdx) + (pc[gasPhaseIdx] - pc[liquidPhaseIdx])); @@ -395,7 +380,7 @@ int main() // check the flash calculation - checkCompositionalFlash(fsRef); + checkCompositionalFlash(fsRef); return 0; } diff --git a/test/material/fluidmatrixinteractions/2p/CMakeLists.txt b/test/material/fluidmatrixinteractions/2p/CMakeLists.txt index ce1b775409a6d89fdc118b996e88852f3fbd6c82..4b9a096a99b4f2e125ddb054258fbc905f3d92f5 100644 --- a/test/material/fluidmatrixinteractions/2p/CMakeLists.txt +++ b/test/material/fluidmatrixinteractions/2p/CMakeLists.txt @@ -23,3 +23,12 @@ dumux_add_test(SOURCES test_material_2p_brookscorey.cc --files ${CMAKE_SOURCE_DIR}/test/references/test_pcsw_brookscorey.dat ${CMAKE_CURRENT_BINARY_DIR}/test_pcsw_brookscorey.dat --command "${CMAKE_CURRENT_BINARY_DIR}/test_material_2p_brookscorey") + + +dune_add_test(SOURCES test_material_2p_spline.cc + LABELS unit material) + +dune_add_test(SOURCES test_material_2p_dataspline.cc + LABELS unit material) + +dune_symlink_to_source_files(FILES test_material_2p_spline.input test_material_2p_dataspline.input) diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_brookscorey.cc b/test/material/fluidmatrixinteractions/2p/test_material_2p_brookscorey.cc index c9e487ba50640231816e4a572249f1200d22f1eb..81f5d15930f9c56329ef9d07b745e01029686d76 100644 --- a/test/material/fluidmatrixinteractions/2p/test_material_2p_brookscorey.cc +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_brookscorey.cc @@ -2,11 +2,7 @@ #include -#include #include -#include -#include -#include #include #include "testmateriallawfunctions.hh" @@ -15,11 +11,10 @@ namespace Dumux::Test { // test if endPointPc() is the same as evaluation at sw=1 template -void checkEndPointPc(const typename Law::Params& params) +void checkEndPointPc(const Law& law, const double entryPressure) { - const auto pcSat = Law::pc(params, Law::sweToSw(params, 1.0)); - const auto endPointPc = Law::endPointPc(params); - const auto entryPressure = params.pe(); + const auto pcSat = law.pc(Law::EffToAbs::sweToSw(1.0, law.effToAbsParams())); + const auto endPointPc = law.endPointPc(); static constexpr double eps = 1e-10; if (Dune::FloatCmp::ne(pcSat, endPointPc, eps)) @@ -34,27 +29,34 @@ int main(int argc, char** argv) { using namespace Dumux; - using BCRegEff = RegularizedBrooksCorey; - using BCEff = BrooksCorey; - using BCReg = EffToAbsLaw; - using BC = EffToAbsLaw; + using BCReg = FluidMatrix::BrooksCoreyDefault; + using BC = FluidMatrix::BrooksCoreyNoReg; // set some parameters - BCReg::Params params; - params.setPe(1e4); - params.setLambda(2.0); - params.setSwr(0.1); - params.setSnr(0.1); - params.setThresholdSw(0.01); + const double pcEntry = 1e4; + const double lambda = 2.0; + BCReg::BasicParams params(pcEntry, lambda); - Test::checkEndPointPc(params); - Test::checkEndPointPc(params); + BCReg::EffToAbsParams eaParams; + eaParams.setSwr(0.1); + eaParams.setSnr(0.1); - const auto sw = Dumux::linspace(0.0, 1.0, 100); - const auto swNonReg = Dumux::linspace(BCReg::sweToSw(params, params.thresholdSw()), BCReg::sweToSw(params, 1.0), 100); + BCReg::RegularizationParams regParams; + const double thresholdSw = 0.01; + regParams.setPcLowSwe(thresholdSw); - Test::runMaterialLawTest("brookscorey", params, sw, swNonReg); - Test::runEffToAbsTest("brookscorey-efftoabs", params, sw); + BCReg bcRegLaw(params, eaParams, regParams); + BC bcLaw(params, eaParams); + + Test::checkEndPointPc(bcRegLaw, pcEntry); + Test::checkEndPointPc(bcLaw, pcEntry); + + const auto sw = linspace(0.0, 1.0, 100); + const auto swNonReg = linspace(BCReg::EffToAbs::sweToSw(thresholdSw, eaParams), BCReg::EffToAbs::sweToSw(1.0, eaParams), 100); + + Test::runMaterialLawTest("brookscorey", bcLaw, bcRegLaw, sw, swNonReg); + Test::runEffToAbsTest("brookscorey-efftoabs", bcLaw, sw); + Test::runEffToAbsTest("brookscorey-reg-efftoabs", bcRegLaw, sw); return 0; } diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.cc b/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.cc new file mode 100644 index 0000000000000000000000000000000000000000..82e66f2482eaddacb54283c1c355fdf77ea81aa2 --- /dev/null +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.cc @@ -0,0 +1,112 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup MaterialTests + * \brief Test for two-phase material laws + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +namespace Dumux { + +template +std::vector eval(const Function& f, const std::vector& x) +{ + auto y = x; + std::transform(x.begin(), x.end(), y.begin(), [&](const double x) { return f(x); }); + return y; +} + +template +void runTest(const std::string& name, const Function& f, + const Orig& orig, const Spline& spline, + bool plot = true) +{ + std::cout << "-----------------------\n" + << name << "\n" + << "-----------------------\n"; + + + if (plot) + { + const auto [swMinPlot, swMaxPlot] + = getParam>("Plot.Range", std::array{{0.1, 1.0}}); + + const auto sw = linspace(swMinPlot, swMaxPlot, 1000); + const auto value = eval([&](auto sw){ return f(sw, orig); }, sw); + const auto valueSpline = eval([&](auto sw){ return f(sw, spline); }, sw); + + GnuplotInterface gnuplot(false); + gnuplot.addDataSetToPlot(sw, value, name + "-orig.dat", "title 'orig. curve'"); + gnuplot.addDataSetToPlot(sw, valueSpline, name + "-spline.dat", "title 'spline'"); + gnuplot.setOption("set xrange [0.0 : 1.0]"); + gnuplot.plot(name); + } +} + +} // end namespace Dumux + +int main(int argc, char** argv) try +{ + using namespace Dumux; + + Parameters::init(argc, argv); + + using MaterialLaw = FluidMatrix::LinearMaterialDefault; + MaterialLaw lin("MaterialLaw"); // read parameters from input file (group MaterialLaw) + + using MaterialLawSpline = FluidMatrix::DataSplineTwoPMaterialLaw; + MaterialLawSpline linSpline("MaterialLaw"); // read parameters from input file (group MaterialLaw) + + const bool plot = getParam("Plot.EnablePlot"); + + runTest("lin-pc", [](auto sw, const auto& law){ return law.pc(sw); }, lin, linSpline, plot); + runTest("lin-dpc", [](auto sw, const auto& law){ return law.dpc_dsw(sw); }, lin, linSpline, plot); + runTest("lin-krw", [](auto sw, const auto& law){ return law.krw(sw); }, lin, linSpline, plot); + runTest("lin-dkrw", [](auto sw, const auto& law){ return law.dkrw_dsw(sw); }, lin, linSpline, plot); + runTest("lin-krn", [](auto sw, const auto& law){ return law.krn(sw); }, lin, linSpline, plot); + runTest("lin-dkrn", [](auto sw, const auto& law){ return law.dkrn_dsw(sw); }, lin, linSpline, plot); + + // inversions + runTest("lin-sw-i", [](auto sw, const auto& law){ return law.sw(law.pc(sw)); }, lin, linSpline, plot); + runTest("lin-dsw-i", [](auto sw, const auto& law){ return law.dsw_dpc(law.pc(sw)); }, lin, linSpline, plot); + + return 0; +} +// ////////////////////////////////// +// Error handler +// ///////////////////////////////// +catch (const Dune::Exception& e) { + + std::cout << e << std::endl; + return 1; +} diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.input b/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.input new file mode 100644 index 0000000000000000000000000000000000000000..9e1ee32f54f8838f0b29f0308f2a8928e55d42ec --- /dev/null +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_dataspline.input @@ -0,0 +1,12 @@ +[MaterialLaw] +LinearPcEntry = 0.0 +LinearPcMax = 1.0 +SwData = 0.0 0.2 0.5 0.7 1.0 +PcData = 1.0 0.8 0.5 0.3 0.0 +KrwData= 0.0 0.2 0.5 0.7 1.0 +KrnData = 1.0 0.8 0.6 0.5 0.3 0.0 +Krn.SwData = 0.0 0.2 0.4 0.5 0.7 1.0 + +[Plot] +EnablePlot = false +Range = 0.0 1.0 diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.cc b/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.cc new file mode 100644 index 0000000000000000000000000000000000000000..fe123a17ea4480be9889278449d9cba55e73559e --- /dev/null +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.cc @@ -0,0 +1,148 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup MaterialTests + * \brief Test for two-phase material laws + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +namespace Dumux { + +template +std::vector eval(const Function& f, const std::vector& x) +{ + auto y = x; + std::transform(x.begin(), x.end(), y.begin(), [&](const double x) { return f(x); }); + return y; +} + +template +void runTest(const std::string& name, const Function& f, + const Orig& orig, const Spline& spline, + bool plot = true) +{ + std::cout << "-----------------------\n" + << name << "\n" + << "-----------------------\n"; + + + if (plot) + { + const auto [swMinPlot, swMaxPlot] + = getParam>("Plot.Range", std::array{{0.1, 1.0}}); + + const auto sw = linspace(swMinPlot, swMaxPlot, 1000); + const auto value = eval([&](auto sw){ return f(sw, orig); }, sw); + const auto valueSpline = eval([&](auto sw){ return f(sw, spline); }, sw); + + GnuplotInterface gnuplot(false); + gnuplot.addDataSetToPlot(sw, value, name + "-orig.dat", "title 'orig. curve'"); + gnuplot.addDataSetToPlot(sw, valueSpline, name + "-spline.dat", "title 'spline'"); + gnuplot.setOption("set xrange [0.0 : 1.0]"); + gnuplot.plot(name); + } + + // speed test + { + const auto [swMinSpline, swMaxSpline] + = getParam>("MaterialLaw.SplineSweInterval", std::array{{0.1, 1.0}}); + + constexpr std::size_t testSamples = 1000000; + const auto swTest = linspace(swMinSpline, swMaxSpline, testSamples); + auto pcTest = swTest; + + Dune::Timer timer; + auto resOrig = swTest; + for (int i = 0; i < testSamples; ++i) + resOrig[i] = f(swTest[i], orig); + timer.stop(); + + const auto vgTime = timer.elapsed(); + std::cout << "Unregularized law computed " << testSamples << " samples in " << vgTime << " seconds." << std::endl; + + timer.reset(); + timer.start(); + auto resSpline = swTest; + for (int i = 0; i < testSamples; ++i) + resSpline[i] = f(swTest[i], spline); + timer.stop(); + + const auto vgSplineTime = timer.elapsed(); + std::cout << "Spline law computed " << testSamples << " samples in " << vgSplineTime << " seconds." << std::endl; + + std::cout << "Speed-up factor ca. " << (vgTime/vgSplineTime) << "x (only in spline region)" << std::endl; + + auto error = resOrig; + for (int i = 0; i < error.size(); ++i) + error[i] = std::abs(error[i]-resSpline[i]); + std::cout << "Maximum error: " << *std::max_element(error.begin(), error.end()) << std::endl; + } +} + +} // end namespace Dumux + +int main(int argc, char** argv) try +{ + using namespace Dumux; + + Parameters::init(argc, argv); + + using MaterialLaw = FluidMatrix::VanGenuchtenNoReg; + MaterialLaw vg("MaterialLaw"); // read parameters from input file (group MaterialLaw) + + using MaterialLawSpline = FluidMatrix::SplineTwoPMaterialLaw; + MaterialLawSpline vgSpline("MaterialLaw"); // read parameters from input file (group MaterialLaw) + + const bool plot = getParam("Plot.EnablePlot"); + + runTest("vg-pc", [](auto sw, const auto& law){ return law.pc(sw); }, vg, vgSpline, plot); + runTest("vg-dpc", [](auto sw, const auto& law){ return law.dpc_dsw(sw); }, vg, vgSpline, plot); + runTest("vg-krw", [](auto sw, const auto& law){ return law.krw(sw); }, vg, vgSpline, plot); + runTest("vg-dkrw", [](auto sw, const auto& law){ return law.dkrw_dsw(sw); }, vg, vgSpline, plot); + runTest("vg-krn", [](auto sw, const auto& law){ return law.krn(sw); }, vg, vgSpline, plot); + runTest("vg-dkrn", [](auto sw, const auto& law){ return law.dkrn_dsw(sw); }, vg, vgSpline, plot); + + // inversions + runTest("vg-sw-i", [](auto sw, const auto& law){ return law.sw(law.pc(sw)); }, vg, vgSpline, plot); + runTest("vg-dsw-i", [](auto sw, const auto& law){ return law.dsw_dpc(law.pc(sw)); }, vg, vgSpline, plot); + + return 0; +} +// ////////////////////////////////// +// Error handler +// ///////////////////////////////// +catch (const Dune::Exception& e) { + + std::cout << e << std::endl; + return 1; +} diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.input b/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.input new file mode 100644 index 0000000000000000000000000000000000000000..6a8c5c01a126ef5b07abcfa5d874479d0bd87dbf --- /dev/null +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_spline.input @@ -0,0 +1,9 @@ +[MaterialLaw] +VanGenuchtenAlpha = 2.956e-4 +VanGenuchtenN = 1.5 +SplineSweInterval = 0.1 0.9 +SplineNumSwSamples = 100 + +[Plot] +EnablePlot = false +Range = 0.05 1.0 diff --git a/test/material/fluidmatrixinteractions/2p/test_material_2p_vangenuchten.cc b/test/material/fluidmatrixinteractions/2p/test_material_2p_vangenuchten.cc index fa2830c8c03d00f6ae5cdc3d743a1ff2f32a7478..f092cbe9d32b831abb02bb04165d921b96afd5f1 100644 --- a/test/material/fluidmatrixinteractions/2p/test_material_2p_vangenuchten.cc +++ b/test/material/fluidmatrixinteractions/2p/test_material_2p_vangenuchten.cc @@ -2,11 +2,7 @@ #include -#include #include -#include -#include -#include #include #include "testmateriallawfunctions.hh" @@ -15,13 +11,13 @@ namespace Dumux::Test { // test if endPointPc() is the same as evaluation at sw=1 template -void checkEndPointPc(const typename Law::Params& params) +void checkEndPointPc(const Law& law) { - const auto pcSat = Law::pc(params, Law::sweToSw(params, 1.0)); - const auto endPointPc = Law::endPointPc(params); - static constexpr double eps = 1e-10; + const auto pcSat = law.pc(Law::EffToAbs::sweToSw(1.0, law.effToAbsParams())); + const auto endPointPc = law.endPointPc(); + static constexpr double eps = 1e-7; - if (Dune::FloatCmp::ne(pcSat, endPointPc, eps)) + if (Dune::FloatCmp::lt(eps, std::abs(pcSat-endPointPc))) DUNE_THROW(Dune::Exception, "pc(sw=1) != endPointPc(): " << pcSat << " != " << endPointPc); } @@ -31,31 +27,37 @@ int main(int argc, char** argv) { using namespace Dumux; - using VGRegEff = RegularizedVanGenuchten; - using VGEff = VanGenuchten; - using VGReg = EffToAbsLaw; - using VG = EffToAbsLaw; + using VGReg = FluidMatrix::VanGenuchtenDefault; + using VG = FluidMatrix::VanGenuchtenNoReg; // set some parameters - VGReg::Params params; - params.setVgAlpha(6.66e-5); - params.setVgn(3.652); - params.setVgl(0.5); - params.setSwr(0.1); - params.setSnr(0.1); - params.setPcLowSw(0.01); - params.setPcHighSw(0.99); - params.setKrnLowSw(0.1); - params.setKrwHighSw(0.9); - - Test::checkEndPointPc(params); - Test::checkEndPointPc(params); - - const auto sw = Dumux::linspace(0.0, 1.0, 100); - const auto swNonReg = Dumux::linspace(VGReg::sweToSw(params, params.pcLowSw()), VGReg::sweToSw(params, params.pcHighSw()), 100); - - Test::runMaterialLawTest("vangenuchten", params, sw, swNonReg); - Test::runEffToAbsTest("vangenuchten-efftoabs", params, sw); + const double alpha = 6.66e-5; + const double n = 3.652; + const double l = 0.5; + VGReg::BasicParams params(alpha, n, l); + + VGReg::EffToAbsParams eaParams; + eaParams.setSwr(0.1); + eaParams.setSnr(0.1); + + VGReg::RegularizationParams regParams; + regParams.setPcLowSwe(0.01); + regParams.setPcHighSwe(0.99); + regParams.setKrnLowSwe(0.1); + regParams.setKrwHighSwe(0.9); + + VGReg vgRegLaw(params, eaParams, regParams); + VG vgLaw(params, eaParams); + + Test::checkEndPointPc(vgRegLaw); + Test::checkEndPointPc(vgLaw); + + const auto sw = linspace(0.0, 1.0, 100); + const auto swNonReg = linspace(VGReg::EffToAbs::sweToSw(regParams.pcLowSwe(), eaParams), VGReg::EffToAbs::sweToSw(regParams.pcHighSwe(), eaParams), 100); + + Test::runMaterialLawTest("vangenuchten", vgLaw, vgRegLaw, sw, swNonReg); + Test::runEffToAbsTest("vangenuchten-efftoabs", vgLaw, sw); + Test::runEffToAbsTest("vangenuchten-reg-efftoabs", vgRegLaw, sw); return 0; } diff --git a/test/material/fluidmatrixinteractions/2p/testmateriallawfunctions.hh b/test/material/fluidmatrixinteractions/2p/testmateriallawfunctions.hh index f6e893348df9305b23c885448460ec0e280380ca..2ceed1fd751e5b088702a1e47d0a57050c72193b 100644 --- a/test/material/fluidmatrixinteractions/2p/testmateriallawfunctions.hh +++ b/test/material/fluidmatrixinteractions/2p/testmateriallawfunctions.hh @@ -76,46 +76,44 @@ void testValueEqualRange(std::string_view testName, template -void runMaterialLawTest(const std::string& name, const typename RegLaw::Params& params, +void runMaterialLawTest(const std::string& name, + const Law& law, + const RegLaw& regLaw, const std::vector& sw, const std::vector& swNonReg) { const auto pc = [&](){ auto pc = sw; for (int i = 0; i < sw.size(); ++i) - pc[i] = RegLaw::pc(params, sw[i]); + pc[i] = regLaw.pc(sw[i]); return pc; }(); - testDerivatives("dpc_dsw", sw, [&](auto sw){ return RegLaw::pc(params, sw); }, [&](auto sw){ return RegLaw::dpc_dsw(params, sw); }); - testDerivatives("dkrw_dsw", sw, [&](auto sw){ return RegLaw::krw(params, sw); }, [&](auto sw){ return RegLaw::dkrw_dsw(params, sw); }); - testDerivatives("dkrn_dsw", sw, [&](auto sw){ return RegLaw::krn(params, sw); }, [&](auto sw){ return RegLaw::dkrn_dsw(params, sw); }); - testDerivatives("dsw_dpc", pc, [&](auto pc){ return RegLaw::sw(params, pc); }, [&](auto pc){ return RegLaw::dsw_dpc(params, pc); }); - testValueEqualRange("Checking sw == sw(pc(sw))", sw, [](auto sw){ return sw; }, [&](auto sw) { return RegLaw::sw(params, RegLaw::pc(params, sw)); }); - testValueEqualRange("Checking 1.0 == dsw_dpc*dpc_dsw^-1", sw, [](auto sw){ return 1.0; }, [&](auto sw) { return RegLaw::dpc_dsw(params, sw)*RegLaw::dsw_dpc(params, RegLaw::pc(params, sw)); }); + testDerivatives("dpc_dsw", sw, [&](auto sw){ return regLaw.pc(sw); }, [&](auto sw){ return regLaw.dpc_dsw(sw); }); + testDerivatives("dkrw_dsw", sw, [&](auto sw){ return regLaw.krw(sw); }, [&](auto sw){ return regLaw.dkrw_dsw(sw); }); + testDerivatives("dkrn_dsw", sw, [&](auto sw){ return regLaw.krn(sw); }, [&](auto sw){ return regLaw.dkrn_dsw(sw); }); + testDerivatives("dsw_dpc", pc, [&](auto pc){ return regLaw.sw(pc); }, [&](auto pc){ return regLaw.dsw_dpc(pc); }); + testValueEqualRange("Checking sw == sw(pc(sw))", sw, [](auto sw){ return sw; }, [&](auto sw) { return regLaw.sw(regLaw.pc(sw)); }); + testValueEqualRange("Checking 1.0 == dsw_dpc*dpc_dsw^-1", sw, [](auto sw){ return 1.0; }, [&](auto sw) { return regLaw.dpc_dsw(sw)*regLaw.dsw_dpc(regLaw.pc(sw)); }); // check that regularized and unregularized are the same in the region without regularization - testValueEqualRange("Checking NoReg::pc == Reg::pc", swNonReg, [&](auto sw){ return RegLaw::pc(params, sw); }, [&](auto sw) { return Law::pc(params, sw); }); + testValueEqualRange("Checking NoReg::pc == Reg::pc", swNonReg, [&](auto sw){ return law.pc(sw); }, [&](auto sw) { return regLaw.pc(sw); }); // test pc-sw curve against some precomputed values writeContainerToFile(pc, "test_pcsw_" + name + ".dat", 100); } -template -void runEffToAbsTest(const std::string& name, const typename AbsLaw::Params& params, - const std::vector& sw) +template +void runEffToAbsTest(const std::string& name, const FluidMatrix& fmLaw, + const std::vector& sw) { - testValueEqualRange("Checking 1.0 == Abs::swToSwe(1-snr)", sw, [](auto sw){ return 1.0; }, [&](auto sw) { return AbsLaw::swToSwe(params, 1-params.snr()); }); - testValueEqualRange("Checking 0.0 == Abs::swToSwe(snr)", sw, [](auto sw){ return 0.0; }, [&](auto sw) { return AbsLaw::swToSwe(params, params.snr()); }); - testValueEqualRange("Checking 1.0 == Abs::snToSne(1-swr)", sw, [](auto sw){ return 1.0; }, [&](auto sw) { return AbsLaw::snToSne(params, 1-params.swr()); }); - testValueEqualRange("Checking 0.0 == Abs::snToSne(swr)", sw, [](auto sw){ return 0.0; }, [&](auto sw) { return AbsLaw::snToSne(params, params.swr()); }); + using EffToAbs = typename FluidMatrix::EffToAbs; + const auto params = fmLaw.effToAbsParams(); - testValueEqualRange("Checking sn == sneToSn(snToSne(sn))", sw, [](auto sn){ return sn; }, [&](auto sn) { return AbsLaw::sneToSn(params, AbsLaw::snToSne(params, sn)); }); - testValueEqualRange("Checking sw == sweToSw(swToSwe(sw))", sw, [](auto sw){ return sw; }, [&](auto sw) { return AbsLaw::sweToSw(params, AbsLaw::swToSwe(params, sw)); }); - - testValueEqualRange("Checking Abs::pc(1-snr) == Eff::pc(1.0)", sw, [&](auto pc){ return AbsLaw::pc(params, 1-params.snr()); }, [&](auto pc) { return EffLaw::pc(params, 1.0); }); - testValueEqualRange("Checking Abs::endPointPc == Eff::pc(1.0)", sw, [&](auto pc){ return AbsLaw::endPointPc(params); }, [&](auto pc) { return EffLaw::pc(params, 1.0); }); + testValueEqualRange("Checking 1.0 == Abs::swToSwe(1-snr)", sw, [](auto sw){ return 1.0; }, [&](auto sw) { return EffToAbs::swToSwe(1-params.snr(), params); }); + testValueEqualRange("Checking 0.0 == Abs::swToSwe(snr)", sw, [](auto sw){ return 0.0; }, [&](auto sw) { return EffToAbs::swToSwe(params.snr(), params); }); + testValueEqualRange("Checking sw == sweToSw(swToSwe(sw))", sw, [](auto sw){ return sw; }, [&](auto sw) { return EffToAbs::sweToSw(EffToAbs::swToSwe(sw, params), params); }); } } // end namespace Dumux diff --git a/test/material/immiscibleflash/test_immiscibleflash.cc b/test/material/immiscibleflash/test_immiscibleflash.cc index 6608553dd196cfa8bac17c0cd64dbc3395dbafc5..dff4e5f2a818b9c8efc21820db6a0d5487310c9d 100644 --- a/test/material/immiscibleflash/test_immiscibleflash.cc +++ b/test/material/immiscibleflash/test_immiscibleflash.cc @@ -37,12 +37,8 @@ #include -#include #include -#include -#include -#include -#include +#include #include @@ -94,7 +90,7 @@ void checkSame(const FluidState &fsRef, const FluidState &fsFlash) template void checkImmiscibleFlash(const FluidState &fsRef, - typename MaterialLaw::Params &matParams) + const MaterialLaw& material) { enum { numPhases = FluidSystem::numPhases }; enum { numComponents = FluidSystem::numComponents }; @@ -120,7 +116,7 @@ void checkImmiscibleFlash(const FluidState &fsRef, // run the flash calculation typename FluidSystem::ParameterCache paramCache; flash.guessInitial(fsFlash, paramCache, globalMolarities); - flash.template solve(fsFlash, paramCache, matParams, globalMolarities); + flash.solve(fsFlash, paramCache, material, globalMolarities); // compare the "flashed" fluid state with the reference one checkSame(fsRef, fsFlash); @@ -129,21 +125,18 @@ void checkImmiscibleFlash(const FluidState &fsRef, template void completeReferenceFluidState(FluidState &fs, - typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int refPhaseIdx) { enum { numPhases = FluidSystem::numPhases }; - using PhaseVector = Dune::FieldVector; - int otherPhaseIdx = 1 - refPhaseIdx; // calculate the other saturation fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx)); // calulate the capillary pressure - PhaseVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, /*wPhaseIdx=*/0); + const auto pc = material.capillaryPressures(fs, /*wPhaseIdx=*/0); fs.setPressure(otherPhaseIdx, fs.pressure(refPhaseIdx) + (pc[otherPhaseIdx] - pc[refPhaseIdx])); @@ -171,10 +164,7 @@ int main() enum { liquidPhaseIdx = FluidSystem::liquidPhaseIdx }; enum { gasPhaseIdx = FluidSystem::gasPhaseIdx }; - using EffMaterialLaw = Dumux::RegularizedBrooksCorey; - using MaterialLaw = Dumux::EffToAbsLaw; - using MPAdapter = Dumux::MPAdapter; - using MaterialLawParams = MaterialLaw::Params; + using PcKrSw = Dumux::FluidMatrix::BrooksCoreyDefault; Scalar T = 273.15 + 25; @@ -190,11 +180,9 @@ int main() FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np); // set the parameters for the capillary pressure law - MaterialLawParams matParams; - matParams.setSwr(0.0); - matParams.setSnr(0.0); - matParams.setPe(0); - matParams.setLambda(2.0); + typename PcKrSw::BasicParams bParams(/*pe*/0.0, /*lambda*/2.0); + auto pcKrSw = PcKrSw(bParams); + auto material = Dumux::FluidMatrix::MPAdapter(pcKrSw); ImmiscibleFluidState fsRef; @@ -213,10 +201,10 @@ int main() fsRef.setPressure(liquidPhaseIdx, 1e6); // set the remaining parameters of the reference fluid state - completeReferenceFluidState(fsRef, matParams, liquidPhaseIdx); + completeReferenceFluidState(fsRef, material, liquidPhaseIdx); // check the flash calculation - checkImmiscibleFlash(fsRef, matParams); + checkImmiscibleFlash(fsRef, material); //////////////// // only gas @@ -228,10 +216,10 @@ int main() fsRef.setPressure(gasPhaseIdx, 1e6); // set the remaining parameters of the reference fluid state - completeReferenceFluidState(fsRef, matParams, gasPhaseIdx); + completeReferenceFluidState(fsRef, material, gasPhaseIdx); // check the flash calculation - checkImmiscibleFlash(fsRef, matParams); + checkImmiscibleFlash(fsRef, material); //////////////// // both phases @@ -243,21 +231,19 @@ int main() fsRef.setPressure(liquidPhaseIdx, 1e6); // set the remaining parameters of the reference fluid state - completeReferenceFluidState(fsRef, matParams, liquidPhaseIdx); + completeReferenceFluidState(fsRef, material, liquidPhaseIdx); // check the flash calculation - checkImmiscibleFlash(fsRef, matParams); + checkImmiscibleFlash(fsRef, material); //////////////// // with capillary pressure //////////////// std::cout << "testing two-phase with capillary pressure\n"; - MaterialLawParams matParams2; - matParams2.setSwr(0.0); - matParams2.setSnr(0.0); - matParams2.setPe(1e3); - matParams2.setLambda(2.0); + typename PcKrSw::BasicParams bParams2(/*pe*/1e3, /*lambda*/2.0); + auto pcKrSw2 = PcKrSw(bParams2); + auto material2 = Dumux::FluidMatrix::MPAdapter(pcKrSw2); // set liquid saturation fsRef.setSaturation(liquidPhaseIdx, 0.5); @@ -266,10 +252,10 @@ int main() fsRef.setPressure(liquidPhaseIdx, 1e6); // set the remaining parameters of the reference fluid state - completeReferenceFluidState(fsRef, matParams2, liquidPhaseIdx); + completeReferenceFluidState(fsRef, material2, liquidPhaseIdx); // check the flash calculation - checkImmiscibleFlash(fsRef, matParams2); + checkImmiscibleFlash(fsRef, material2); return 0; } diff --git a/test/material/ncpflash/test_ncpflash.cc b/test/material/ncpflash/test_ncpflash.cc index d2e50019921a0c63a8359bbda82048974ec7b1fc..03603a686aa23682c7613881e19233d6313cf107 100644 --- a/test/material/ncpflash/test_ncpflash.cc +++ b/test/material/ncpflash/test_ncpflash.cc @@ -38,8 +38,7 @@ #include #include -#include -#include +#include #include @@ -90,7 +89,7 @@ void checkSame(const FluidState &fsRef, const FluidState &fsFlash) template void checkNcpFlash(const FluidState &fsRef, - typename MaterialLaw::Params &matParams) + const MaterialLaw& material) { enum { numPhases = FluidSystem::numPhases }; enum { numComponents = FluidSystem::numComponents }; @@ -116,7 +115,7 @@ void checkNcpFlash(const FluidState &fsRef, // run the flash calculation typename FluidSystem::ParameterCache paramCache; flash.guessInitial(fsFlash, paramCache, globalMolarities); - flash.template solve(fsFlash, paramCache, matParams, globalMolarities); + flash.solve(fsFlash, paramCache, material, globalMolarities); // compare the "flashed" fluid state with the reference one checkSame(fsRef, fsFlash); @@ -125,13 +124,12 @@ void checkNcpFlash(const FluidState &fsRef, template void completeReferenceFluidState(FluidState &fs, - typename MaterialLaw::Params &matParams, + const MaterialLaw& material, int refPhaseIdx) { enum { numPhases = FluidSystem::numPhases }; using ComputeFromReferencePhase = Dumux::ComputeFromReferencePhase; - using PhaseVector = Dune::FieldVector; int otherPhaseIdx = 1 - refPhaseIdx; @@ -139,8 +137,7 @@ void completeReferenceFluidState(FluidState &fs, fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx)); // calulate the capillary pressure - PhaseVector pc; - MaterialLaw::capillaryPressures(pc, matParams, fs, /*wPhaseIdx=*/0); + const auto pc = material.capillaryPressures(fs, /*wPhaseIdx=*/0); fs.setPressure(otherPhaseIdx, fs.pressure(refPhaseIdx) + (pc[otherPhaseIdx] - pc[refPhaseIdx])); @@ -169,10 +166,7 @@ int main() enum { H2OIdx = FluidSystem::H2OIdx }; enum { N2Idx = FluidSystem::N2Idx }; - using EffMaterialLaw = Dumux::RegularizedBrooksCorey; - using MaterialLaw = Dumux::EffToAbsLaw; - using MaterialLawParams = MaterialLaw::Params; - using MPAdapter = Dumux::MPAdapter; + using PcKrSw = Dumux::FluidMatrix::BrooksCoreyDefault; Scalar T = 273.15 + 25; @@ -188,11 +182,9 @@ int main() FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np); // set the parameters for the capillary pressure law - MaterialLawParams matParams; - matParams.setSwr(0.0); - matParams.setSnr(0.0); - matParams.setPe(0); - matParams.setLambda(2.0); + typename PcKrSw::BasicParams bParams(/*pe*/0.0, /*lambda*/2.0); + auto pcKrSw = PcKrSw(bParams); + auto material = Dumux::FluidMatrix::MPAdapter(pcKrSw); CompositionalFluidState fsRef; @@ -219,10 +211,10 @@ int main() fsRef.setWettingPhase(wPhaseIdx); // "complete" the fluid state - completeReferenceFluidState(fsRef, matParams, liquidPhaseIdx); + completeReferenceFluidState(fsRef, material, liquidPhaseIdx); // check the flash calculation - checkNcpFlash(fsRef, matParams); + checkNcpFlash(fsRef, material); //////////////// // only gas @@ -239,10 +231,10 @@ int main() fsRef.setMoleFraction(gasPhaseIdx, H2OIdx, 0.001); // "complete" the fluid state - completeReferenceFluidState(fsRef, matParams, gasPhaseIdx); + completeReferenceFluidState(fsRef, material, gasPhaseIdx); // check the flash calculation - checkNcpFlash(fsRef, matParams); + checkNcpFlash(fsRef, material); //////////////// // both phases @@ -262,17 +254,15 @@ int main() MiscibleMultiPhaseComposition::solve(fsRef, paramCache); // check the flash calculation - checkNcpFlash(fsRef, matParams); + checkNcpFlash(fsRef, material); //////////////// // with capillary pressure //////////////// - MaterialLawParams matParams2; - matParams2.setSwr(0.0); - matParams2.setSnr(0.0); - matParams2.setPe(1e3); - matParams2.setLambda(2.0); + typename PcKrSw::BasicParams bParams2(/*pe*/1e3, /*lambda*/2.0); + auto pcKrSw2 = PcKrSw(bParams2); + auto material2 = Dumux::FluidMatrix::MPAdapter(pcKrSw2); // set gas saturation fsRef.setSaturation(gasPhaseIdx, 0.5); @@ -282,9 +272,7 @@ int main() fsRef.setPressure(liquidPhaseIdx, 1e6); // calulate the capillary pressure - using PhaseVector = Dune::FieldVector; - PhaseVector pc; - MPAdapter::capillaryPressures(pc, matParams2, fsRef, /*wPhaseIdx=*/0); + const auto pc = material2.capillaryPressures(fsRef, /*wPhaseIdx=*/0); fsRef.setPressure(gasPhaseIdx, fsRef.pressure(liquidPhaseIdx) + (pc[gasPhaseIdx] - pc[liquidPhaseIdx])); @@ -294,7 +282,7 @@ int main() // check the flash calculation - checkNcpFlash(fsRef, matParams2); + checkNcpFlash(fsRef, material2); return 0; } diff --git a/test/material/pengrobinson/test_pengrobinson.cc b/test/material/pengrobinson/test_pengrobinson.cc index e113c1648b0532c9be271d736962b7bdbabf1fdd..80865d29ded0a83785f91abb93fa239cf37fa1ad 100644 --- a/test/material/pengrobinson/test_pengrobinson.cc +++ b/test/material/pengrobinson/test_pengrobinson.cc @@ -43,24 +43,19 @@ Scalar bringOilToSurface(FluidState &surfaceFluidState, Scalar alpha, const Flui numComponents = FluidSystem::numComponents }; - using MaterialLaw = Dumux::MpLinearMaterial; - using MaterialLawParams = typename MaterialLaw::Params; - using ComponentVector = Dune::FieldVector; - // create a flash Dumux::NcpFlash flash(/*wettingPhaseIdx=*/0); const Scalar refPressure = 1.0135e5; // [Pa] // set the parameters for the capillary pressure law - MaterialLawParams matParams; - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - matParams.setPcMinSat(phaseIdx, 0.0); - matParams.setPcMaxSat(phaseIdx, 0.0); - } + using PcKrSw = Dumux::FluidMatrix::MPLinearMaterial; + typename PcKrSw::BasicParams params({}, {}); + PcKrSw pcKrSw(params); // retrieve the global volumetric component molarities surfaceFluidState.setTemperature(273.15 + 20); + using ComponentVector = Dune::FieldVector; ComponentVector molarities; for (int compIdx = 0; compIdx < numComponents; ++ compIdx) molarities[compIdx] = reservoirFluidState.molarity(oPhaseIdx, compIdx); @@ -95,7 +90,7 @@ Scalar bringOilToSurface(FluidState &surfaceFluidState, Scalar alpha, const Flui // calculate the deviation from the standard pressure tmpMolarities = molarities; tmpMolarities /= alpha; - flash.template solve(surfaceFluidState, paramCache, matParams, tmpMolarities); + flash.solve(surfaceFluidState, paramCache, pcKrSw, tmpMolarities); Scalar f = surfaceFluidState.pressure(gPhaseIdx) - refPressure; // calculate the derivative of the deviation from the standard @@ -103,7 +98,7 @@ Scalar bringOilToSurface(FluidState &surfaceFluidState, Scalar alpha, const Flui Scalar eps = alpha*1e-10; tmpMolarities = molarities; tmpMolarities /= alpha + eps; - flash.template solve(surfaceFluidState, paramCache, matParams, tmpMolarities); + flash.solve(surfaceFluidState, paramCache, pcKrSw, tmpMolarities); Scalar fStar = surfaceFluidState.pressure(gPhaseIdx) - refPressure; Scalar fPrime = (fStar - f)/eps; @@ -119,7 +114,7 @@ Scalar bringOilToSurface(FluidState &surfaceFluidState, Scalar alpha, const Flui // calculate the final result tmpMolarities = molarities; tmpMolarities /= alpha; - flash.template solve(surfaceFluidState, paramCache, matParams, tmpMolarities); + flash.solve(surfaceFluidState, paramCache, pcKrSw, tmpMolarities); return alpha; } @@ -144,12 +139,7 @@ int main(int argc, char** argv) C20Idx = FluidSystem::C20Idx }; - using ComponentVector = Dune::FieldVector; using FluidState = Dumux::CompositionalFluidState; - - using MaterialLaw = Dumux::MpLinearMaterial; - using MaterialLawParams = MaterialLaw::Params; - using ParameterCache = FluidSystem::ParameterCache; //////////// @@ -159,11 +149,9 @@ int main(int argc, char** argv) FluidSystem::init(); // set the parameters for the capillary pressure law - MaterialLawParams matParams; - for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { - matParams.setPcMinSat(phaseIdx, 0.0); - matParams.setPcMaxSat(phaseIdx, 0.0); - } + using PcKrSw = Dumux::FluidMatrix::MPLinearMaterial; + typename PcKrSw::BasicParams params({}, {}); + PcKrSw pcKrSw(params); //////////// // Create a fluid state @@ -199,6 +187,7 @@ int main(int argc, char** argv) //////////// // Calculate the total molarities of the components //////////// + using ComponentVector = Dune::FieldVector; ComponentVector molarities; for (int compIdx = 0; compIdx < numComponents; ++ compIdx) molarities[compIdx] = fluidState.saturation(oPhaseIdx)*fluidState.molarity(oPhaseIdx, compIdx); @@ -213,7 +202,7 @@ int main(int argc, char** argv) FluidState flashFluidState, surfaceFluidState; flashFluidState.assign(fluidState); flash.guessInitial(flashFluidState, paramCache, molarities); - flash.solve(flashFluidState, paramCache, matParams, molarities); + flash.solve(flashFluidState, paramCache, pcKrSw, molarities); Scalar surfaceAlpha = 50; bringOilToSurface(surfaceFluidState, surfaceAlpha, flashFluidState, /*guessInitial=*/true); @@ -234,7 +223,7 @@ int main(int argc, char** argv) curMolarities /= alpha; // "flash" the modified reservoir oil - flash.solve(flashFluidState, paramCache, matParams, curMolarities); + flash.solve(flashFluidState, paramCache, pcKrSw, curMolarities); Scalar alphaSurface = bringOilToSurface(surfaceFluidState, surfaceAlpha, diff --git a/test/multidomain/boundary/darcydarcy/1p_2p/params.input b/test/multidomain/boundary/darcydarcy/1p_2p/params.input index 28d525347c05f7819745a078ed87a20eda3b7114..9721af3d3584833ec3dcc33895ddf2a774af5967 100644 --- a/test/multidomain/boundary/darcydarcy/1p_2p/params.input +++ b/test/multidomain/boundary/darcydarcy/1p_2p/params.input @@ -20,3 +20,9 @@ Name = 2p LowerLeft = -2000 -2000 UpperRight = 2000 2000 Cells = 50 50 + +[SpatialParams] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 diff --git a/test/multidomain/boundary/darcydarcy/1p_2p/spatialparams.hh b/test/multidomain/boundary/darcydarcy/1p_2p/spatialparams.hh index 7cf67002da5f86550b4570bf17f6afdd07a5316a..ba0442cbbea6cc7fc85149e028a427c4b2710c57 100644 --- a/test/multidomain/boundary/darcydarcy/1p_2p/spatialparams.hh +++ b/test/multidomain/boundary/darcydarcy/1p_2p/spatialparams.hh @@ -27,7 +27,6 @@ #include #include -#include namespace Dumux { @@ -50,20 +49,15 @@ class TestSpatialParams static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; -public: - using MaterialLaw = EffToAbsLaw>; - using MaterialLawParams = typename MaterialLaw::Params; + using PcKrSwCurve = FluidMatrix::VanGenuchtenNoReg; +public: using PermeabilityType = Scalar; TestSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) - { - materialParams_.setSwr(0.05); - materialParams_.setSnr(0.0); - materialParams_.setVgAlpha(0.0037); - materialParams_.setVgn(4.7); - } + , pcKrSwCurve_("SpatialParams") + {} /*! * \brief Function for defining the (intrinsic) permeability \f$[m^2]\f$. @@ -85,14 +79,13 @@ public: } /*! - * \brief Returns the parameter object for the Brooks-Corey material law. + * \brief Returns the parameters for the material law at a given location * - * In this test, we use element-wise distributed material parameters. - * \return the material parameters object + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! @@ -108,7 +101,7 @@ public: } private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params.input b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params.input index 5e94b99bb856faa1c0b7710d7812555471b1dea9..640ce27c385448b1d8d1da76a7a47bf7dcbd903b 100644 --- a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params.input +++ b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params.input @@ -39,8 +39,8 @@ Permeability = 2.65e-10 AlphaBJ = 1.0 Swr = 0.005 Snr = 0.01 -VgAlpha = 6.371e-4 -VgN = 6.9 +VanGenuchtenAlpha = 6.371e-4 +VanGenuchtenN = 6.9 [Problem] Name = test_stokes1p2cdarcy2p2chorizontal diff --git a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params_nonisothermal.input b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params_nonisothermal.input index 2b8814c19ee3179ea1622f36dc015b620f62dda8..d210df63f9cfda5afaff5a9e2ea4a13c3f78ffb9 100644 --- a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params_nonisothermal.input +++ b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/params_nonisothermal.input @@ -39,8 +39,8 @@ Permeability = 2.65e-10 AlphaBJ = 1.0 Swr = 0.005 Snr = 0.01 -VgAlpha = 6.371e-4 -VgN = 6.9 +VanGenuchtenAlpha = 6.371e-4 +VanGenuchtenN = 6.9 [Problem] Name = test_stokes1p2cnidarcy2p2cnihorizontal diff --git a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/spatialparams.hh b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/spatialparams.hh index 8e63965ff1a793835d8146d719eaad63612dbc42..389b3fff5e516130d709bd740629e5514b60d9a2 100644 --- a/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/spatialparams.hh +++ b/test/multidomain/boundary/stokesdarcy/1p2c_2p2c/spatialparams.hh @@ -26,9 +26,7 @@ #define DUMUX_CONSERVATION_SPATIAL_PARAMS_HH #include -#include -#include -#include +#include namespace Dumux { @@ -49,26 +47,19 @@ class TwoPTwoCSpatialParams using ParentType = FVSpatialParams>; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; TwoPTwoCSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) + : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { permeability_ = getParam("SpatialParams.Permeability"); porosity_ = getParam("SpatialParams.Porosity"); alphaBJ_ = getParam("SpatialParams.AlphaBJ"); - - // residual saturations - params_.setSwr(getParam("SpatialParams.Swr")); - params_.setSnr(getParam("SpatialParams.Snr")); - // parameters for the vanGenuchten law - params_.setVgAlpha(getParam("SpatialParams.VgAlpha")); - params_.setVgn(getParam("SpatialParams.VgN")); } /*! @@ -95,20 +86,14 @@ public: { return alphaBJ_; } /*! - * \brief Returns the parameter object for the Brooks-Corey material law. - * - * In this test, we use element-wise distributed material parameters. + * \brief Returns the parameters for the material law at a given location * - * \param element The current element - * \param scv The sub-control volume inside the element. - * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object + * \param globalPos The global coordinates for the given location */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolutionVector& elemSol) const - { return params_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -124,7 +109,7 @@ private: Scalar permeability_; Scalar porosity_; Scalar alphaBJ_; - MaterialLawParams params_; + const PcKrSwCurve pcKrSwCurve_; static constexpr Scalar eps_ = 1.0e-7; }; diff --git a/test/multidomain/boundary/stokesdarcy/1p_2p/params.input b/test/multidomain/boundary/stokesdarcy/1p_2p/params.input index a5532ea8682cc23394c0bb5338b4f1dcdc3f799a..513cf67522144de516847a81a40c9b9578c630d7 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_2p/params.input +++ b/test/multidomain/boundary/stokesdarcy/1p_2p/params.input @@ -30,8 +30,8 @@ Permeability = 2.65e-10 AlphaBJ = 1.0 Swr = 0.005 Snr = 0.01 -VgAlpha = 6.371e-4 -VgN = 8.0 +VanGenuchtenAlpha = 6.371e-4 +VanGenuchtenN = 8.0 [Problem] EnableGravity = false diff --git a/test/multidomain/boundary/stokesdarcy/1p_2p/spatialparams.hh b/test/multidomain/boundary/stokesdarcy/1p_2p/spatialparams.hh index e78d2f634a5a35572fda371dd76a476d8fea2c55..d218d2e90d29c819beb17defeaeda2ed73ac291b 100644 --- a/test/multidomain/boundary/stokesdarcy/1p_2p/spatialparams.hh +++ b/test/multidomain/boundary/stokesdarcy/1p_2p/spatialparams.hh @@ -26,9 +26,7 @@ #define DUMUX_CONSERVATION_SPATIAL_PARAMS_HH #include -#include -#include -#include +#include namespace Dumux { @@ -51,26 +49,19 @@ class ConservationSpatialParams using ParentType = FVSpatialParams; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; ConservationSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) + : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { permeability_ = getParam("SpatialParams.Permeability"); porosity_ = getParam("SpatialParams.Porosity"); alphaBJ_ = getParam("SpatialParams.AlphaBJ"); - - // residual saturations - params_.setSwr(getParam("SpatialParams.Swr")); - params_.setSnr(getParam("SpatialParams.Snr")); - // parameters for the vanGenuchten law - params_.setVgAlpha(getParam("SpatialParams.VgAlpha")); - params_.setVgn(getParam("SpatialParams.VgN")); } /*! @@ -97,20 +88,14 @@ public: { return alphaBJ_; } /*! - * \brief Returns the parameter object for the Brooks-Corey material law. - * - * In this test, we use element-wise distributed material parameters. + * \brief Returns the parameters for the material law at a given location * - * \param element The current element - * \param scv The sub-control volume inside the element. - * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object + * \param globalPos The global coordinates for the given location */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolutionVector& elemSol) const - { return params_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -126,7 +111,7 @@ private: Scalar permeability_; Scalar porosity_; Scalar alphaBJ_; - MaterialLawParams params_; + const PcKrSwCurve pcKrSwCurve_; static constexpr Scalar eps_ = 1.0e-7; }; diff --git a/test/multidomain/embedded/1d3d/1p2c_richards2c/params.input b/test/multidomain/embedded/1d3d/1p2c_richards2c/params.input index 48d97f0393964b551b1d4e772cb9d5a063d0fc09..003bc1edb665cacc509754a14c7c2410a33c48c2 100644 --- a/test/multidomain/embedded/1d3d/1p2c_richards2c/params.input +++ b/test/multidomain/embedded/1d3d/1p2c_richards2c/params.input @@ -28,6 +28,9 @@ InitTopSaturation = 0.3 [Soil] SpatialParams.Permeability = 2.57e-12 # [m^2] SpatialParams.Porosity = 0.4 # [-] +SpatialParams.Swr = 0.05 +SpatialParams.VanGenuchtenAlpha = 2.956e-4 +SpatialParams.VanGenuchtenN = 1.5 Problem.Name = 3d [Root] diff --git a/test/multidomain/embedded/1d3d/1p2c_richards2c/problem_soil.hh b/test/multidomain/embedded/1d3d/1p2c_richards2c/problem_soil.hh index 7459221af590e7a96d2f2bfee4886b06eb374ec9..7b67f2eb3d06540d9213b4cffbc50e45d840d8da 100644 --- a/test/multidomain/embedded/1d3d/1p2c_richards2c/problem_soil.hh +++ b/test/multidomain/embedded/1d3d/1p2c_richards2c/problem_soil.hh @@ -158,8 +158,7 @@ public: // for initial conditions const Scalar sw = getParam("Problem.InitTopSaturation", 0.3); // start with 30% saturation on top - using MaterialLaw = typename GetPropType::MaterialLaw; - pcTop_ = MaterialLaw::pc(this->spatialParams().materialLawParamsAtPos(gridGeometry->bBoxMax()), sw); + pcTop_ = this->spatialParams().fluidMatrixInteractionAtPos(gridGeometry->bBoxMax()).pc(sw); } /*! diff --git a/test/multidomain/embedded/1d3d/1p2c_richards2c/spatialparams_soil.hh b/test/multidomain/embedded/1d3d/1p2c_richards2c/spatialparams_soil.hh index 342eb9079ec7a1bcdb3671462e7d065b1d31d340..85f028d7b0331dd1b2fdd494f3ea05b1c055c7f4 100644 --- a/test/multidomain/embedded/1d3d/1p2c_richards2c/spatialparams_soil.hh +++ b/test/multidomain/embedded/1d3d/1p2c_richards2c/spatialparams_soil.hh @@ -27,8 +27,7 @@ #include #include -#include -#include +#include namespace Dumux { @@ -47,26 +46,16 @@ class SoilSpatialParams using SubControlVolume = typename GridGeometry::SubControlVolume; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; + public: // export permeability type using PermeabilityType = Scalar; - // export material law type - using MaterialLaw = EffToAbsLaw>; - // export material law params - using MaterialLawParams = typename MaterialLaw::Params; SoilSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("Soil.SpatialParams") { - // residual saturations - materialParams_.setSwr(0.05); - materialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - materialParams_.setVgAlpha(2.956e-4); - materialParams_.setVgn(1.5); - // perm and poro permeability_ = getParam("Soil.SpatialParams.Permeability"); porosity_ = getParam("Soil.SpatialParams.Porosity"); @@ -105,16 +94,15 @@ public: /*! * \brief Returns the parameters for the material law at a given location * - * This method is not actually required by the Richards model, but provided - * for the convenience of the RichardsLensProblem - * - * \param globalPos A global coordinate vector + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition &globalPos) const - { return materialParams_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; Scalar permeability_; Scalar porosity_; }; diff --git a/test/multidomain/embedded/1d3d/1p_richards/params.input b/test/multidomain/embedded/1d3d/1p_richards/params.input index fe09ff1a666d46b5cec8437e7599da4534f03b63..294a0d327ab672d991035cbdf572bcb1ab2e1c49 100644 --- a/test/multidomain/embedded/1d3d/1p_richards/params.input +++ b/test/multidomain/embedded/1d3d/1p_richards/params.input @@ -24,6 +24,9 @@ OutputName = test_md_embedded1d3d_1p_richards [Soil] SpatialParams.Permeability = 2.57e-12 # [m^2] SpatialParams.Porosity = 0.3 # [-] +SpatialParams.Swr = 0.05 +SpatialParams.VanGenuchtenAlpha = 2.956e-4 +SpatialParams.VanGenuchtenN = 1.5 Problem.Name = 3d [Root] diff --git a/test/multidomain/embedded/1d3d/1p_richards/spatialparams_soil.hh b/test/multidomain/embedded/1d3d/1p_richards/spatialparams_soil.hh index f2baa36fd3730a66a79e1346bed9acdfe3239f79..802e7cf4c8c36b8a29bea22d65fb033008451ad7 100644 --- a/test/multidomain/embedded/1d3d/1p_richards/spatialparams_soil.hh +++ b/test/multidomain/embedded/1d3d/1p_richards/spatialparams_soil.hh @@ -27,8 +27,7 @@ #include #include -#include -#include +#include namespace Dumux { @@ -47,26 +46,16 @@ class SoilSpatialParams using SubControlVolume = typename GridGeometry::SubControlVolume; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; + public: // export permeability type using PermeabilityType = Scalar; - // export material law type - using MaterialLaw = EffToAbsLaw>; - // export material law params - using MaterialLawParams = typename MaterialLaw::Params; SoilSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("Soil.SpatialParams") { - // residual saturations - materialParams_.setSwr(0.05); - materialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - materialParams_.setVgAlpha(2.956e-4); - materialParams_.setVgn(1.5); - // perm and poro permeability_ = getParam("Soil.SpatialParams.Permeability"); porosity_ = getParam("Soil.SpatialParams.Porosity"); @@ -105,16 +94,15 @@ public: /*! * \brief Returns the parameters for the material law at a given location * - * This method is not actually required by the Richards model, but provided - * for the convenience of the RichardsLensProblem - * - * \param globalPos A global coordinate vector + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition &globalPos) const - { return materialParams_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; Scalar permeability_; Scalar porosity_; }; diff --git a/test/multidomain/poromechanics/el2p/params.input b/test/multidomain/poromechanics/el2p/params.input index 7c96b619fa01347afaa96ac8afd69ed2bc62e7db..addf0055f2f672979d00f1e155477ccda00ec995 100644 --- a/test/multidomain/poromechanics/el2p/params.input +++ b/test/multidomain/poromechanics/el2p/params.input @@ -21,6 +21,10 @@ Name = twop # name passed to the output routines [SpatialParams] Permeability = 1e-14 # [m^2] InitialPorosity = 0.2 # [-] +Swr = 0.3 +Snr = 0.05 +BrooksCoreyPcEntry = 1.99e4 +BrooksCoreyLambda = 0 # will be overwritten internally [LinearSolver] ResidualReduction = 1e-20 diff --git a/test/multidomain/poromechanics/el2p/spatialparams_2p.hh b/test/multidomain/poromechanics/el2p/spatialparams_2p.hh index 543c5660b0473276ef7679cf3ee5a2b94279b646..ec9573bb9ff957293cfede5d5b9cb339aa8b2cdc 100644 --- a/test/multidomain/poromechanics/el2p/spatialparams_2p.hh +++ b/test/multidomain/poromechanics/el2p/spatialparams_2p.hh @@ -28,8 +28,7 @@ #include #include -#include -#include +#include #include #include #include @@ -52,10 +51,9 @@ class TwoPSpatialParams : public FVSpatialParams; using ParentType = FVSpatialParams; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + public: - using EffectiveLaw = RegularizedBrooksCorey; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; // export permeability type using PermeabilityType = Scalar; @@ -67,18 +65,16 @@ public: , initPorosity_(getParam("SpatialParams.InitialPorosity")) { // given Van Genuchten m - Scalar m = 0.457; + const Scalar m = 0.457; // Brooks Corey lambda using std::pow; - Scalar brooksCoreyLambda = m / (1 - m) * (1 - pow(0.5, 1/m)); + const Scalar brooksCoreyLambda = m / (1 - m) * (1 - pow(0.5, 1/m)); - // residual saturations - myMaterialParams_.setSwr(0.3); - myMaterialParams_.setSnr(0.05); + auto baseParams = PcKrSwCurve::makeBasicParams("SpatialParams"); + baseParams.setLambda(brooksCoreyLambda); + const auto effToAbsParams = PcKrSwCurve::makeEffToAbsParams("SpatialParams"); - // parameters for the Brooks Corey law - myMaterialParams_.setPe(1.99e4); - myMaterialParams_.setLambda(brooksCoreyLambda); + pcKrSwCurve_ = std::make_unique(baseParams, effToAbsParams); } //! Returns the porosity for a sub-control volume. @@ -106,24 +102,15 @@ public: return permLaw.evaluatePermeability(initPermeability_, initPorosity_, porosity(element, scv, elemSol)); } - /*! - * \brief Returns the parameter object for the Brooks-Corey material law. - * - * In this test, we use element-wise distributed material parameters. - * - * \param element The current element - * \param scv The sub-control volume inside the element. - * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object - */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { - // do not use different parameters in the test with inverted wettability - return myMaterialParams_; - } + /*! + * \brief Returns the parameters for the material law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { + return makeFluidMatrixInteraction(*pcKrSwCurve_); + } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -145,8 +132,7 @@ private: std::shared_ptr couplingManagerPtr_; Scalar initPermeability_; Scalar initPorosity_; - - MaterialLawParams myMaterialParams_; + std::unique_ptr pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/1p/sequential/test_diffusion.input b/test/porousmediumflow/1p/sequential/test_diffusion.input index bb3e7d6221129e591e0c489675b03caa5dd7e166..11347cafdf0f8307b9b9f980400522822534aa0b 100644 --- a/test/porousmediumflow/1p/sequential/test_diffusion.input +++ b/test/porousmediumflow/1p/sequential/test_diffusion.input @@ -13,3 +13,7 @@ LiquidKinematicViscosity = 1.0 [LinearSolver.Preconditioner] Iterations = 2 + +[SpatialParams] +LinearPcEntry = 0 +LinearPcMax = 0 diff --git a/test/porousmediumflow/1p/sequential/test_diffusion3d.input b/test/porousmediumflow/1p/sequential/test_diffusion3d.input index 86a65843f1d22f5a01a8139a4cfeb97c002ff374..a524d48095d4125dbcb4c2f6e3e8adb60ffd2fbd 100644 --- a/test/porousmediumflow/1p/sequential/test_diffusion3d.input +++ b/test/porousmediumflow/1p/sequential/test_diffusion3d.input @@ -15,3 +15,7 @@ RefinementRatio = 0 GMResRestart = 80 MaxIterations = 1000 ResidualReduction = 1e-8 + +[SpatialParams] +LinearPcEntry = 0 +LinearPcMax = 0 diff --git a/test/porousmediumflow/1p/sequential/test_diffusion3d_reference.input b/test/porousmediumflow/1p/sequential/test_diffusion3d_reference.input index 69a160a2f3bba2b9f800849f50b592554c81b0b5..b17075925c673c170a1a2312ecf3986a4cb93c91 100644 --- a/test/porousmediumflow/1p/sequential/test_diffusion3d_reference.input +++ b/test/porousmediumflow/1p/sequential/test_diffusion3d_reference.input @@ -14,3 +14,7 @@ RefinementRatio = 0 GMResRestart = 80 MaxIterations = 1000 ResidualReduction = 1e-8 + +[SpatialParams] +LinearPcEntry = 0 +LinearPcMax = 0 diff --git a/test/porousmediumflow/1p/sequential/test_diffusionspatialparams.hh b/test/porousmediumflow/1p/sequential/test_diffusionspatialparams.hh index 7fd27e7dc22718888a07a5b86b1bcc07f716c145..87ad388043378565d1712e804ef185173ab43296 100644 --- a/test/porousmediumflow/1p/sequential/test_diffusionspatialparams.hh +++ b/test/porousmediumflow/1p/sequential/test_diffusionspatialparams.hh @@ -28,7 +28,6 @@ #include #include #include -#include namespace Dumux { @@ -48,16 +47,6 @@ struct TestDiffusionSpatialParams {}; template struct SpatialParams { using type = TestDiffusionSpatialParams; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = LinearMaterial; -public: - using type = EffToAbsLaw; -}; } /*! @@ -84,9 +73,9 @@ class TestDiffusionSpatialParams: public SequentialFVSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FieldMatrix = Dune::FieldMatrix; + using PcKrSwCurve = FluidMatrix::LinearMaterialDefault; + public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; const FieldMatrix& intrinsicPermeability (const Element& element) const { @@ -98,11 +87,14 @@ public: return 0.2; } - - // return the parameter object for the Brooks-Corey material law which depends on the position - const MaterialLawParams& materialLawParams(const Element &element) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialLawParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } void initialize(const double delta) @@ -140,16 +132,11 @@ public: } TestDiffusionSpatialParams(const Problem& problem) - : ParentType(problem),gridView_(problem.gridView()), indexSet_(problem.gridView().indexSet()), permeability_(0) - { - // residual saturations - materialLawParams_.setSwr(0.0); - materialLawParams_.setSnr(0.0); - - // parameters for the linear entry pressure function - materialLawParams_.setEntryPc(0); - materialLawParams_.setMaxPc(0); - } + : ParentType(problem),gridView_(problem.gridView()) + , indexSet_(problem.gridView().indexSet()) + , pcKrSwCurve_("SpatialParams") + , permeability_(0) + {} private: void perm (FieldMatrix& perm, const GlobalPosition& globalPos) const @@ -163,7 +150,7 @@ private: const GridView gridView_; const IndexSet& indexSet_; - MaterialLawParams materialLawParams_; + const PcKrSwCurve pcKrSwCurve_; std::vector permeability_; double delta_; }; diff --git a/test/porousmediumflow/1p/sequential/test_diffusionspatialparams3d.hh b/test/porousmediumflow/1p/sequential/test_diffusionspatialparams3d.hh index 58fee09815bd66f0ec4bdf3ce655ad9283e167ca..4dc891770dedb53952a748b84113cbad2e9e3e69 100644 --- a/test/porousmediumflow/1p/sequential/test_diffusionspatialparams3d.hh +++ b/test/porousmediumflow/1p/sequential/test_diffusionspatialparams3d.hh @@ -27,7 +27,6 @@ #include #include #include -#include namespace Dumux { @@ -47,16 +46,6 @@ struct TestDiffusionSpatialParams3d {}; template struct SpatialParams { using type = TestDiffusionSpatialParams3d; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = LinearMaterial; -public: - using type = EffToAbsLaw; -}; } /*! @@ -80,9 +69,9 @@ class TestDiffusionSpatialParams3d: public SequentialFVSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FieldMatrix = Dune::FieldMatrix; + using PcKrSwCurve = FluidMatrix::LinearMaterialDefault; + public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; const FieldMatrix& intrinsicPermeabilityAtPos (const GlobalPosition& globalPos) const { @@ -94,31 +83,28 @@ public: return 1.0; } - - // return the parameter object for the Brooks-Corey material law which depends on the position - const MaterialLawParams& materialLawParams(const Element &element) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialLawParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } TestDiffusionSpatialParams3d(const Problem& problem) - : ParentType(problem), permeability_(0) + : ParentType(problem) + , pcKrSwCurve_("SpatialParams") + , permeability_(0) { - // residual saturations - materialLawParams_.setSwr(0.0); - materialLawParams_.setSnr(0.0); - - // parameters for the linear entry pressure function - materialLawParams_.setEntryPc(0); - materialLawParams_.setMaxPc(0); - // permeability values permeability_[0][0] = permeability_[1][1] = permeability_[2][2] = 1.0; permeability_[0][1] = permeability_[1][0] = permeability_[1][2] = permeability_[2][1] = 0.5; } private: - MaterialLawParams materialLawParams_; + const PcKrSwCurve pcKrSwCurve_; FieldMatrix permeability_; }; diff --git a/test/porousmediumflow/2p/implicit/adaptive/params.input b/test/porousmediumflow/2p/implicit/adaptive/params.input index a650f89187e66c1618c6670a2079aa1e037920b4..3f474517c314484a02e741179203df197b5e64cc 100644 --- a/test/porousmediumflow/2p/implicit/adaptive/params.input +++ b/test/porousmediumflow/2p/implicit/adaptive/params.input @@ -13,6 +13,16 @@ ClosureType = Green LensLowerLeft = 1.0 2.0 # [m] coordinates of the lower left lens corner LensUpperRight = 4.0 3.0 # [m] coordinates of the upper right lens corner +[SpatialParams.Lens] +Swr = 0.18 +VanGenuchtenAlpha = 0.00045 +VanGenuchtenN = 7.3 + +[SpatialParams.Outer] +Swr = 0.05 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 + [Problem] Name = 2padaptive # name passed to the output routines diff --git a/test/porousmediumflow/2p/implicit/boxdfm/CMakeLists.txt b/test/porousmediumflow/2p/implicit/boxdfm/CMakeLists.txt index 8384582b8d519e411c2d2b61af3e8cd2907a9b1a..3abbc2e2380122da55b690f336c63be9e82d15de 100644 --- a/test/porousmediumflow/2p/implicit/boxdfm/CMakeLists.txt +++ b/test/porousmediumflow/2p/implicit/boxdfm/CMakeLists.txt @@ -2,7 +2,7 @@ dune_symlink_to_source_files(FILES "params.input" "grids") # quadrilaterals alu grid dumux_add_test(NAME test_2p_boxdfm_quads_alu - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm SOURCES main.cc CMAKE_GUARD dune-alugrid_FOUND CMAKE_GUARD dune-foamgrid_FOUND @@ -16,7 +16,7 @@ dumux_add_test(NAME test_2p_boxdfm_quads_alu # quadrilaterals ug grid dumux_add_test(NAME test_2p_boxdfm_quads_ug - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm SOURCES main.cc CMAKE_GUARD dune-uggrid_FOUND CMAKE_GUARD dune-foamgrid_FOUND @@ -30,7 +30,7 @@ dumux_add_test(NAME test_2p_boxdfm_quads_ug # triangles alu dumux_add_test(NAME test_2p_boxdfm_trias_alu - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm TIMEOUT 1500 SOURCES main.cc CMAKE_GUARD dune-foamgrid_FOUND @@ -45,7 +45,7 @@ dumux_add_test(NAME test_2p_boxdfm_trias_alu # triangles ug dumux_add_test(NAME test_2p_boxdfm_trias_ug - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm TIMEOUT 1500 SOURCES main.cc CMAKE_GUARD dune-uggrid_FOUND @@ -60,7 +60,7 @@ dumux_add_test(NAME test_2p_boxdfm_trias_ug # tetrahedra alu dumux_add_test(NAME test_2p_boxdfm_tets_alu - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm SOURCES main.cc CMAKE_GUARD dune-foamgrid_FOUND CMAKE_GUARD dune-alugrid_FOUND @@ -74,7 +74,7 @@ dumux_add_test(NAME test_2p_boxdfm_tets_alu # tetrahedra ug dumux_add_test(NAME test_2p_boxdfm_tets_ug - LABELS porousmediumflow 2p + LABELS porousmediumflow 2p boxdfm SOURCES main.cc CMAKE_GUARD dune-uggrid_FOUND CMAKE_GUARD dune-foamgrid_FOUND diff --git a/test/porousmediumflow/2p/implicit/boxdfm/main.cc b/test/porousmediumflow/2p/implicit/boxdfm/main.cc index 6fe43aa027977f319432b4976beaafac3bc25248..e59caef33e4ba99aad92abd086451c9d923e38bb 100644 --- a/test/porousmediumflow/2p/implicit/boxdfm/main.cc +++ b/test/porousmediumflow/2p/implicit/boxdfm/main.cc @@ -131,7 +131,7 @@ int main(int argc, char** argv) auto xOld = x; // update the interface parameters - problem->spatialParams().updateMaterialInterfaceParams(x); + problem->spatialParams().updateMaterialInterfaces(x); // the grid variables using GridVariables = GetPropType; diff --git a/test/porousmediumflow/2p/implicit/boxdfm/params.input b/test/porousmediumflow/2p/implicit/boxdfm/params.input index 18cb950644f244bef653e1b32c9cc7d9bfa0bbcf..6705416a25aefa7b89617af1c91fb37122a2b8a0 100644 --- a/test/porousmediumflow/2p/implicit/boxdfm/params.input +++ b/test/porousmediumflow/2p/implicit/boxdfm/params.input @@ -9,6 +9,16 @@ File = grids/durlofsky.msh [SpatialParams] FractureAperture = 1e-3 +[SpatialParams.Matrix] +Swr = 0.18 +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2 + +[SpatialParams.Fracture] +Swr = 0.05 +BrooksCoreyPcEntry = 1e3 +BrooksCoreyLambda = 2 + [Problem] Name = 2pboxdfm EnableGravity = false diff --git a/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh b/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh index 5d0455254f81a265a3ccd89f82785c3bb62285d0..8183314ecb8786ec214d956080b619d6c1fc985d 100644 --- a/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/boxdfm/spatialparams.hh @@ -28,11 +28,9 @@ #include #include -#include -#include -#include +#include -#include +#include namespace Dumux { @@ -41,7 +39,8 @@ namespace Dumux { * \brief The spatial params for the incompressible 2p test. */ template -class TwoPTestSpatialParams : public FVSpatialParams< GridGeometry, Scalar, TwoPTestSpatialParams > +class TwoPTestSpatialParams +: public FVSpatialParams< GridGeometry, Scalar, TwoPTestSpatialParams > { using ThisType = TwoPTestSpatialParams; using ParentType = FVSpatialParams; @@ -55,25 +54,16 @@ class TwoPTestSpatialParams : public FVSpatialParams< GridGeometry, Scalar, TwoP static constexpr int dimWorld = GridView::dimensionworld; + using PcKrSw = FluidMatrix::BrooksCoreyDefault; + using MaterialInterfaces = BoxMaterialInterfaces; public: - using MaterialLaw = EffToAbsLaw< RegularizedBrooksCorey >; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; - TwoPTestSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) - { - // residual saturations - matrixMaterialParams_.setSwr(0.18); - matrixMaterialParams_.setSnr(0.0); - fractureMaterialParams_.setSwr(0.05); - fractureMaterialParams_.setSnr(0.0); - - // parameters for the Brooks-Corey law - matrixMaterialParams_.setPe(1e4); - matrixMaterialParams_.setLambda(2); - fractureMaterialParams_.setPe(1e3); - fractureMaterialParams_.setLambda(2); - } + TwoPTestSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + , pcKrSwMatrix_("SpatialParams.Matrix") + , pcKrSwFracture_("SpatialParams.Fracture") + {} /*! * \brief Function for defining the (intrinsic) permeability \f$[m^2]\f$. @@ -115,24 +105,23 @@ public: } /*! - * \brief Returns the parameter object for the Brooks-Corey material law. + * \brief Returns the fluid-matrix interaction law. * * In this test, we use element-wise distributed material parameters. * * \param element The current element * \param scv The sub-control volume inside the element. * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object */ template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { if (scv.isOnFracture()) - return fractureMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwFracture_); else - return matrixMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwMatrix_); } /*! @@ -147,21 +136,18 @@ public: //! Updates the map of which material parameters are associated with a nodal dof. template - void updateMaterialInterfaceParams(const SolutionVector& x) - { - materialInterfaceParams_.update(this->gridGeometry(), *this, x); - } + void updateMaterialInterfaces(const SolutionVector& x) + { materialInterfaces_ = std::make_unique(this->gridGeometry(), *this, x); } //! Returns the material parameters associated with a nodal dof - const BoxMaterialInterfaceParams& materialInterfaceParams() const - { return materialInterfaceParams_; } + const MaterialInterfaces& materialInterfaces() const + { return *materialInterfaces_; } private: - MaterialLawParams matrixMaterialParams_; - MaterialLawParams fractureMaterialParams_; + PcKrSw pcKrSwMatrix_; + PcKrSw pcKrSwFracture_; - // Determines the parameters associated with the dofs at material interfaces - BoxMaterialInterfaceParams materialInterfaceParams_; + std::unique_ptr materialInterfaces_; static constexpr Scalar eps_ = 1.5e-7; }; diff --git a/test/porousmediumflow/2p/implicit/cornerpoint/params.input b/test/porousmediumflow/2p/implicit/cornerpoint/params.input index b4e0ef3e375034edd8372993ecbe524b4fc39e14..b9ecbd3a1723834bd4d4c61aede3aa72393c3600 100644 --- a/test/porousmediumflow/2p/implicit/cornerpoint/params.input +++ b/test/porousmediumflow/2p/implicit/cornerpoint/params.input @@ -10,3 +10,9 @@ Name = cc2pcornerpoint # name passed to the output routines Homogeneous = 0 # use a homogeneous permeablity/porosity distribution InjectionElement = 0 # index of the element where injection should take place InjectionRate = 0.1 # injection rate in kg/s + +[SpatialParams] +Swr = 0.0 +Snr = 0.0 +VanGenuchtenAlpha = 0.00045 +VanGenuchtenN = 7.3; diff --git a/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh b/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh index 22d56066eae216c2d03bbcec595c5da6ba461979..f036ee25348f27d7df35156f64ee15b9d37bd8eb 100644 --- a/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/cornerpoint/spatialparams.hh @@ -29,8 +29,7 @@ #include #include -#include -#include +#include namespace Dumux { @@ -52,19 +51,18 @@ class TwoPCornerPointTestSpatialParams static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; using DimWorldMatrix = Dune::FieldMatrix; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = DimWorldMatrix; TwoPCornerPointTestSpatialParams(std::shared_ptr gridGeometry, std::shared_ptr deck) : ParentType(gridGeometry) , deck_(deck) + , pcCurve_("SpatialParams") { homogeneous_ = getParam("Problem.Homogeneous"); @@ -115,9 +113,6 @@ public: permZ_ = permX_; } - // parameters for the Van Genuchten law - materialParams_.setVgAlpha(0.00045); - materialParams_.setVgn(7.3); } /*! @@ -170,11 +165,11 @@ public: * \return The material parameters object */ template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { - return materialParams_; + return makeFluidMatrixInteraction(pcCurve_); } /*! @@ -197,7 +192,7 @@ public: private: std::shared_ptr deck_; //!< the eclipse deck - MaterialLawParams materialParams_; + PcKrSwCurve pcCurve_; std::vector porosity_; std::vector permX_; std::vector permZ_; diff --git a/test/porousmediumflow/2p/implicit/fracture/params.input b/test/porousmediumflow/2p/implicit/fracture/params.input index 666a5013f64e734a5995588299c5700a3ff22ca4..fa2fb1f6862e8d22af5ddd3926325e437828eeed 100644 --- a/test/porousmediumflow/2p/implicit/fracture/params.input +++ b/test/porousmediumflow/2p/implicit/fracture/params.input @@ -15,3 +15,9 @@ ResidualReduction = 1e-16 [Newton] MaxRelativeShift = 1e-10 + +[SpatialParams] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenN = 4.7 +VanGenuchtenAlpha = 0.0037 diff --git a/test/porousmediumflow/2p/implicit/fracture/spatialparams.hh b/test/porousmediumflow/2p/implicit/fracture/spatialparams.hh index d9d13cedc8f5687e2623570b38c4d24eaf2403f2..66adff4cd38808e691dbb7b11b4586f47f797ab1 100644 --- a/test/porousmediumflow/2p/implicit/fracture/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/fracture/spatialparams.hh @@ -27,9 +27,7 @@ #define DUMUX_TWOP_FRACTURE_TEST_SPATIALPARAMS_HH #include -#include -#include -#include +#include #include @@ -54,27 +52,16 @@ class FractureSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: //! export permeability type using PermeabilityType = Scalar; - //! export the type used for the material law - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; FractureSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) - { - // residual saturations - materialParams_.setSwr(0.05); - materialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - materialParams_.setVgAlpha(0.0037); - materialParams_.setVgn(4.7); - } + , pcKrSwCurve_("SpatialParams") + {} /*! * \brief Returns the scalar intrinsic permeability \f$[m^2]\f$ @@ -97,8 +84,8 @@ public: * * \param globalPos The position at which we evaluate */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + auto fluidMatrixInteractionAtPos (const GlobalPosition& globalPos) const + { return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -111,7 +98,7 @@ public: { return FluidSystem::phase0Idx; } private: - MaterialLawParams materialParams_; + PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2p/implicit/incompressible/CMakeLists.txt b/test/porousmediumflow/2p/implicit/incompressible/CMakeLists.txt index 3175b589b7eca192652c1b4754828ef4aa37d427..4ba02c91beca189ecd0c83f3c3001f744184fb3a 100644 --- a/test/porousmediumflow/2p/implicit/incompressible/CMakeLists.txt +++ b/test/porousmediumflow/2p/implicit/incompressible/CMakeLists.txt @@ -55,7 +55,7 @@ dumux_add_test(NAME test_2p_incompressible_box_analytic CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_2p_incompressible_box-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/test_2p_incompressible_box_analytic-00007.vtu - --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p_incompressible_box params.input -Problem.Name test_2p_incompressible_box_analytic -Newton.EnablePartialReassembly false") + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p_incompressible_box_analytic params.input -Problem.Name test_2p_incompressible_box_analytic -Newton.EnablePartialReassembly false") # using box with interface solver dumux_add_test(NAME test_2p_incompressible_box_ifsolver diff --git a/test/porousmediumflow/2p/implicit/incompressible/main.cc b/test/porousmediumflow/2p/implicit/incompressible/main.cc index 0d7c8192bb2941722fd22bf3ddc96ee22cb7bef9..382447424697eeb77ff534e2af06bd746164361f 100644 --- a/test/porousmediumflow/2p/implicit/incompressible/main.cc +++ b/test/porousmediumflow/2p/implicit/incompressible/main.cc @@ -151,7 +151,7 @@ int main(int argc, char** argv) // maybe update the interface parameters if (ENABLEINTERFACESOLVER) - problem->spatialParams().updateMaterialInterfaceParams(x); + problem->spatialParams().updateMaterialInterfaces(x); // the grid variables using GridVariables = GetPropType; diff --git a/test/porousmediumflow/2p/implicit/incompressible/params.input b/test/porousmediumflow/2p/implicit/incompressible/params.input index 336df6cf83b0f396fee77f0b57e0fabb6bcb1eaf..17b87d2465c003f3d9ce232716c8d85c450618cd 100644 --- a/test/porousmediumflow/2p/implicit/incompressible/params.input +++ b/test/porousmediumflow/2p/implicit/incompressible/params.input @@ -11,6 +11,16 @@ Cells = 48 32 LensLowerLeft = 1.0 2.0 # [m] coordinates of the lower left lens corner LensUpperRight = 4.0 3.0 # [m] coordinates of the upper right lens corner +[SpatialParams.Lens] +Swr = 0.18 +VanGenuchtenAlpha = 0.00045 +VanGenuchtenN = 7.3 + +[SpatialParams.Outer] +Swr = 0.05 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 + [Problem] Name = 2p EnableGravity = true diff --git a/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh b/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh index 1232ca5d2b4c72808481de848cc3484d0df8ac0f..fdb750dcb2c7d3aa35d23757364e119b5d1a55e6 100644 --- a/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/incompressible/spatialparams.hh @@ -26,10 +26,8 @@ #define DUMUX_INCOMPRESSIBLE_TWOP_TEST_SPATIAL_PARAMS_HH #include -#include -#include - -#include +#include +#include namespace Dumux { @@ -51,36 +49,24 @@ class TwoPTestSpatialParams static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSw = FluidMatrix::VanGenuchtenDefault; + using MaterialInterfaces = BoxMaterialInterfaces; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; TwoPTestSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , lensPcKrSw_("SpatialParams.Lens") + , outerPcKrSw_("SpatialParams.Outer") { lensIsOilWet_ = getParam("SpatialParams.LensIsOilWet", false); lensLowerLeft_ = getParam("SpatialParams.LensLowerLeft"); lensUpperRight_ = getParam("SpatialParams.LensUpperRight"); - // residual saturations - lensMaterialParams_.setSwr(0.18); - lensMaterialParams_.setSnr(0.0); - outerMaterialParams_.setSwr(0.05); - outerMaterialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - lensMaterialParams_.setVgAlpha(0.00045); - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - outerMaterialParams_.setVgn(4.7); - - lensK_ = getParam("SpatialParams.lensK", 9.05e-12); - outerK_ = getParam("SpatialParams.outerK", 4.6e-10); + lensK_ = getParam("SpatialParams.Lens.Permeability", 9.05e-12); + outerK_ = getParam("SpatialParams.Outer.Permeability", 4.6e-10); } /*! @@ -123,14 +109,14 @@ public: * \return The material parameters object */ template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { // do not use different parameters in the test with inverted wettability if (isInLens_(element.geometry().center()) && !lensIsOilWet_) - return lensMaterialParams_; - return outerMaterialParams_; + return makeFluidMatrixInteraction(lensPcKrSw_); + return makeFluidMatrixInteraction(outerPcKrSw_); } /*! @@ -149,15 +135,15 @@ public: //! Updates the map of which material parameters are associated with a nodal dof. template - void updateMaterialInterfaceParams(const SolutionVector& x) + void updateMaterialInterfaces(const SolutionVector& x) { if (GridGeometry::discMethod == DiscretizationMethod::box) - materialInterfaceParams_.update(this->gridGeometry(), *this, x); + materialInterfaces_ = std::make_unique(this->gridGeometry(), *this, x); } //! Returns the material parameters associated with a nodal dof - const BoxMaterialInterfaceParams& materialInterfaceParams() const - { return materialInterfaceParams_; } + const MaterialInterfaces& materialInterfaces() const + { return *materialInterfaces_; } //! Returns whether or not the lens is oil wet bool lensIsOilWet() const { return lensIsOilWet_; } @@ -178,11 +164,11 @@ private: Scalar lensK_; Scalar outerK_; - MaterialLawParams lensMaterialParams_; - MaterialLawParams outerMaterialParams_; - // Determines the parameters associated with the dofs at material interfaces - BoxMaterialInterfaceParams materialInterfaceParams_; + const PcKrSw lensPcKrSw_; + const PcKrSw outerPcKrSw_; + + std::unique_ptr materialInterfaces_; static constexpr Scalar eps_ = 1.5e-7; }; diff --git a/test/porousmediumflow/2p/implicit/nonisothermal/params.input b/test/porousmediumflow/2p/implicit/nonisothermal/params.input index e30e238016d2716ad2d040dfe30eb3ee94d2e810..246559beeaa9a08dfedc31cd5d6662c1d0cd51ee 100644 --- a/test/porousmediumflow/2p/implicit/nonisothermal/params.input +++ b/test/porousmediumflow/2p/implicit/nonisothermal/params.input @@ -17,3 +17,13 @@ WriteConvergence = 1 # write convergence behaviour to disk? SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +FineMaterial.Swr = 0.2 +FineMaterial.Snr = 0.0 +FineMaterial.BrooksCoreyPcEntry = 1e4 +FineMaterial.BrooksCoreyLambda = 2.0 +CoarseMaterial.Swr = 0.2 +CoarseMaterial.Snr = 0.0 +CoarseMaterial.BrooksCoreyPcEntry = 1e4 +CoarseMaterial.BrooksCoreyLambda = 2.0 diff --git a/test/porousmediumflow/2p/implicit/rotationsymmetry/params.input b/test/porousmediumflow/2p/implicit/rotationsymmetry/params.input index efe4baef169dea37dfcdef341136fb6ab0dd6fa6..49bd7c80bbd132b55f6330d89bb833f4d1e74d12 100644 --- a/test/porousmediumflow/2p/implicit/rotationsymmetry/params.input +++ b/test/porousmediumflow/2p/implicit/rotationsymmetry/params.input @@ -12,3 +12,9 @@ EnableGravity = true [Vtk] OutputInterval = 50 + +[SpatialParams] +Swr = 0.0 +Snr = 0.0 +BrooksCoreyPcEntry = 0.0 +BrooksCoreyLambda = 2.0 diff --git a/test/porousmediumflow/2p/implicit/rotationsymmetry/spatialparams.hh b/test/porousmediumflow/2p/implicit/rotationsymmetry/spatialparams.hh index da0361a7f85e0c4d6342bb27655bfbc0b8e3c109..fb0346fb2c3e23601fc1ef31846595b8e6ca5add 100644 --- a/test/porousmediumflow/2p/implicit/rotationsymmetry/spatialparams.hh +++ b/test/porousmediumflow/2p/implicit/rotationsymmetry/spatialparams.hh @@ -24,8 +24,7 @@ #define DUMUX_TEST_TWOP_ROTATIONALSYMMETRY_SPATIAL_PARAMS_HH #include -#include -#include +#include namespace Dumux { @@ -38,22 +37,14 @@ class TwoPRotationalSymmetrySpatialParams using Element = typename GridGeometry::GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; public: - using MaterialLaw = EffToAbsLaw>; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; TwoPRotationalSymmetrySpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) - { - // residual saturations - materialLawParams_.setSwr(0.0); - materialLawParams_.setSnr(0.0); - - // parameters for the material law - materialLawParams_.setPe(0.0); - materialLawParams_.setLambda(2.0); - } + ,pcKrSwCurve_("SpatialParams") + {} PermeabilityType permeabilityAtPos(const GlobalPosition& globalPos) const { return 1e-11; } @@ -61,15 +52,15 @@ public: Scalar porosityAtPos(const GlobalPosition& globalPos) const { return 0.4; } - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialLawParams_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { return makeFluidMatrixInteraction(pcKrSwCurve_); } template int wettingPhaseAtPos(const GlobalPosition& globalPos) const { return FluidSystem::phase0Idx; } private: - MaterialLawParams materialLawParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2p/sequential/buckleyleverettanalyticsolution.hh b/test/porousmediumflow/2p/sequential/buckleyleverettanalyticsolution.hh index 8a8114bb6276675bb3fd2ace695acee0bf563d05..e54f31ba0df2f2ac8b226e1e35b7d7a21fc00515 100644 --- a/test/porousmediumflow/2p/sequential/buckleyleverettanalyticsolution.hh +++ b/test/porousmediumflow/2p/sequential/buckleyleverettanalyticsolution.hh @@ -24,9 +24,6 @@ #define DUMUX_BUCKLEYLEVERETT_ANALYTICAL_HH #include -#include -#include - namespace Dumux { @@ -36,33 +33,6 @@ namespace Dumux * the Buckley-Leverett problem */ -template -struct CheckMaterialLaw -{ - static bool isLinear() - { - return false; - } -}; - -template -struct CheckMaterialLaw > -{ - static bool isLinear() - { - return true; - } -}; - -template -struct CheckMaterialLaw > > -{ - static bool isLinear() - { - return true; - } -}; - /** * \file * \brief Analytical solution of the buckley-leverett problem @@ -74,8 +44,6 @@ template class BuckleyLeverettAnalytic using Scalar = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; - using MaterialLawParams = typename MaterialLaw::Params; using FluidSystem = GetPropType; using FluidState = GetPropType; @@ -119,10 +87,10 @@ private: void prepareAnalytic() { const auto& dummyElement = *problem_.gridView().template begin<0>(); - const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(dummyElement)); + const auto& fluidMatrixInteraction = problem_->spatialParams().fluidMatrixInteractionAtPos(dummyElement.geometry().center()); - swr_ = materialLawParams.swr(); - snr_ = materialLawParams.snr(); + swr_ = fluidMatrixInteraction.effToAbsParams().swr(); + snr_ = fluidMatrixInteraction.effToAbsParams().snr(); Scalar porosity = problem_.spatialParams().porosity(dummyElement); FluidState fluidState; @@ -132,8 +100,7 @@ private: Scalar viscosityW = FluidSystem::viscosity(fluidState, wPhaseIdx); Scalar viscosityNW = FluidSystem::viscosity(fluidState, nPhaseIdx); - - if (CheckMaterialLaw::isLinear() && viscosityW == viscosityNW) + if constexpr (SpatialParams::pcSwCurveIsLinear() && viscosityW == viscosityNW) { std::pair entry; entry.first = 1 - snr_; @@ -145,32 +112,32 @@ private: else { Scalar sw0 = swr_; - Scalar fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW; - fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW); + Scalar fw0 = fluidMatrixInteraction.krw(sw0)/viscosityW; + fw0 /= (fw0 + fluidMatrixInteraction.krn(sw0)/viscosityNW); Scalar sw1 = sw0 + deltaS_; - Scalar fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; - fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + Scalar fw1 = fluidMatrixInteraction.krw(sw1)/viscosityW; + fw1 /= (fw1 + fluidMatrixInteraction.krn(sw1)/viscosityNW); Scalar tangentSlopeOld = (fw1 - fw0)/(sw1 - sw0); sw1 += deltaS_; - fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; - fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + fw1 = fluidMatrixInteraction.krw(sw1)/viscosityW; + fw1 /= (fw1 + fluidMatrixInteraction.krn(sw1)/viscosityNW); Scalar tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0); while (tangentSlopeNew >= tangentSlopeOld && sw1 < (1.0 - snr_)) { tangentSlopeOld = tangentSlopeNew; sw1 += deltaS_; - fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; - fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + fw1 = fluidMatrixInteraction.krw(sw1)/viscosityW; + fw1 /= (fw1 + fluidMatrixInteraction.krn(sw1)/viscosityNW); tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0); } sw0 = sw1 - deltaS_; - fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW; - fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW); + fw0 = fluidMatrixInteraction.krw(sw0)/viscosityW; + fw0 /= (fw0 + fluidMatrixInteraction.krn(sw0)/viscosityNW); Scalar sw2 = sw1 + deltaS_; - Scalar fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW; - fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW); + Scalar fw2 = fluidMatrixInteraction.krw(sw2)/viscosityW; + fw2 /= (fw2 + fluidMatrixInteraction.krn(sw2)/viscosityNW); while (sw1 <= (1.0 - snr_)) { std::pair entry; @@ -188,8 +155,8 @@ private: fw1 = fw2; sw2 += deltaS_; - fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW; - fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW); + fw2 = fluidMatrixInteraction.krw(sw2)/viscosityW; + fw2 /= (fw2 + fluidMatrixInteraction.krn(sw2)/viscosityNW); } } diff --git a/test/porousmediumflow/2p/sequential/mcwhorteranalyticsolution.hh b/test/porousmediumflow/2p/sequential/mcwhorteranalyticsolution.hh index f2e9fe4cafd4433608bbd14974c76df2ced98517..311dc2479c12e389ec3b3aa2470730a82d8aac37 100644 --- a/test/porousmediumflow/2p/sequential/mcwhorteranalyticsolution.hh +++ b/test/porousmediumflow/2p/sequential/mcwhorteranalyticsolution.hh @@ -47,8 +47,6 @@ class McWhorterAnalytic using Scalar = GetPropType; using SpatialParams = GetPropType; - using MaterialLaw = typename SpatialParams::MaterialLaw; - using MaterialLawParams = typename MaterialLaw::Params; using FluidSystem = GetPropType; using FluidState = GetPropType; @@ -132,10 +130,10 @@ private: void prepareAnalytic() { const auto& dummyElement = *problem_.gridView().template begin<0>(); - const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(dummyElement)); + const auto& fluidMatrixInteraction = problem_->spatialParams().fluidMatrixInteractionAtPos(dummyElement.geometry().center()); - swr_ = materialLawParams.swr(); - snr_ = materialLawParams.snr(); + swr_ = fluidMatrixInteraction.effToAbsParams().swr(); + snr_ = fluidMatrixInteraction.effToAbsParams().snr(); porosity_ = problem_.spatialParams().porosity(dummyElement); permeability_ = problem_.spatialParams().intrinsicPermeability(dummyElement)[0][0]; PrimaryVariables initVec; @@ -165,17 +163,15 @@ private: // get fractional flow function vector for (int i=0; i #include -#include -#include -#include +#include namespace Dumux { @@ -48,16 +46,6 @@ struct TestIMPESSpatialParams {}; template struct SpatialParams { using type = TestIMPESSpatialParams; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = RegularizedBrooksCorey; -public: - using type = EffToAbsLaw; -}; } /*! @@ -80,10 +68,9 @@ class TestIMPESSpatialParams: public SequentialFVSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; -public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; +public: Scalar intrinsicPermeability (const Element& element) const { @@ -95,36 +82,22 @@ public: return 0.2; } - - // return the parameter object for the Brooks-Corey material law which depends on the position -// const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - const MaterialLawParams& materialLawParams(const Element& element) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialLawParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } - TestIMPESSpatialParams(const Problem& problem) - : ParentType(problem) - { - // residual saturations - materialLawParams_.setSwr(0.2); - materialLawParams_.setSnr(0.2); - -// // parameters for the Brooks-Corey Law -// // entry pressures - materialLawParams_.setPe(0); -// // Brooks-Corey shape parameters - materialLawParams_.setLambda(2); - - // parameters for the linear - // entry pressures function -// materialLawParams_.setEntryPc(0); -// materialLawParams_.setMaxPc(0); - } + : ParentType(problem), pcKrSwCurve_("SpatialParams") + {} private: - MaterialLawParams materialLawParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace diff --git a/test/porousmediumflow/2p/sequential/test_impeswithamg.input b/test/porousmediumflow/2p/sequential/test_impeswithamg.input index b28fbd28a01e625590c4270a3dc06b260b31a564..60f65f7ee133e53dd536dc14bf16177609007355 100644 --- a/test/porousmediumflow/2p/sequential/test_impeswithamg.input +++ b/test/porousmediumflow/2p/sequential/test_impeswithamg.input @@ -13,4 +13,10 @@ Name = test_impeswithamg # name passed to the output routines EnableGravity = 0 [Vtk] -OutputLevel = 0 \ No newline at end of file +OutputLevel = 0 + +[SpatialParams] +Swr = 0.2 +Snr = 0.2 +BrooksCoreyPcEntry = 0 +BrooksCoreyLambda = 2 diff --git a/test/porousmediumflow/2p/sequential/test_mpfa2pproblem.hh b/test/porousmediumflow/2p/sequential/test_mpfa2pproblem.hh index 964e6e2c6737283db051678822b988c9399710ab..7f7598a1d93ce1bbf929ae9b8a53df715e9f7908 100644 --- a/test/porousmediumflow/2p/sequential/test_mpfa2pproblem.hh +++ b/test/porousmediumflow/2p/sequential/test_mpfa2pproblem.hh @@ -71,12 +71,6 @@ struct FVAdaptiveTwoPTest { using InheritsFrom = std::tuple; }; struct MPFALTwoPTest { using InheritsFrom = std::tuple; }; struct MPFALAdaptiveTwoPTest { using InheritsFrom = std::tuple; }; -// NEW_TYPE_TAG(FVTwoPTest, INHERITS_FROM(FVPressureTwoP, FVTransportTwoP, IMPESTwoP, MPFATwoPTest)); -// NEW_TYPE_TAG(FVAdaptiveTwoPTest, INHERITS_FROM(FVPressureTwoPAdaptive, FVTransportTwoP, IMPESTwoPAdaptive, MPFATwoPTest)); -// NEW_TYPE_TAG(MPFAOTwoPTest, INHERITS_FROM(FvMpfaO2dPressureTwoP, FVTransportTwoP, IMPESTwoP, MPFATwoPTest)); -// NEW_TYPE_TAG(MPFALTwoPTest, INHERITS_FROM(FvMpfaL2dPressureTwoP, FVTransportTwoP, IMPESTwoP, MPFATwoPTest)); -// NEW_TYPE_TAG(MPFALAdaptiveTwoPTest, INHERITS_FROM(FvMpfaL2dPressureTwoPAdaptive, FVTransportTwoP, IMPESTwoPAdaptive, MPFATwoPTest)); - } // end namespace TTag diff --git a/test/porousmediumflow/2p/sequential/test_mpfa2pspatialparams.hh b/test/porousmediumflow/2p/sequential/test_mpfa2pspatialparams.hh index ada177a2946c477738c3d03cdd4c02986d325ecd..d758aef5ec9d66d99fd3c355a99a0cbb0e3597d7 100644 --- a/test/porousmediumflow/2p/sequential/test_mpfa2pspatialparams.hh +++ b/test/porousmediumflow/2p/sequential/test_mpfa2pspatialparams.hh @@ -25,9 +25,7 @@ #include #include -#include -#include - +#include namespace Dumux { @@ -46,18 +44,13 @@ struct Test2PSpatialParams {}; template struct SpatialParams { using type = Test2PSpatialParams; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = RegularizedBrooksCorey; -public: - using type = EffToAbsLaw; -}; } +// forward declaration +template +class LinearMaterialDefault; +class LinearMaterial; + /*! * \ingroup SequentialTwoPTests * \brief Test problem for the sequential 2p models @@ -81,9 +74,14 @@ class Test2PSpatialParams: public SequentialFVSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FieldMatrix = Dune::FieldMatrix; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; + + static constexpr bool pcSwCurveIsLinear() + { + return std::is_same_v || std::is_same_v; + } const FieldMatrix& intrinsicPermeabilityAtPos(const GlobalPosition& globalPos) const { @@ -108,17 +106,17 @@ public: #endif } - // return the brooks-corey context depending on the position - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - if (isLensOne(globalPos)) - return materialLawParamsLenses_; - else if (isLensTwo(globalPos)) - return materialLawParamsLenses_; - else if (isLensThree(globalPos)) - return materialLawParamsLenses_; + if (isLensOne(globalPos) || isLensTwo(globalPos) || isLensThree(globalPos)) + return makeFluidMatrixInteraction(*pcKrSwCurveLenses_); else - return materialLawParamsBackground_; + return makeFluidMatrixInteraction(*pcKrSwCurveBackground_); } Test2PSpatialParams(const Problem& problem) : @@ -126,53 +124,25 @@ public: lensOneLowerLeft_(0), lensOneUpperRight_(0), lensTwoLowerLeft_(0), lensTwoUpperRight_(0), lensThreeLowerLeft_(0), lensThreeUpperRight_(0) { #if PROBLEM == 0 - // residual saturations - materialLawParamsBackground_.setSwr(0.2); - materialLawParamsBackground_.setSnr(0.2); - - materialLawParamsLenses_.setSwr(0.2); - materialLawParamsLenses_.setSnr(0.2); - - //parameters for Brooks-Corey law + typename PcKrSwCurve::BasicParams params(0/*pe*/, 2/*lambda*/); + typename PcKrSwCurve::EffToAbsParams effToAbsParams(0.2/*swr*/, 0.2/*snr*/); + pcKrSwCurveBackground_ = std::make_unique(params, effToAbsParams); + pcKrSwCurveLenses_ = std::make_unique(params, effToAbsParams); - // entry pressures function - materialLawParamsBackground_.setPe(0.); - materialLawParamsLenses_.setPe(0.); #elif PROBLEM == 1 - // residual saturations - materialLawParamsBackground_.setSwr(0.); - materialLawParamsBackground_.setSnr(0.); + typename PcKrSwCurve::BasicParams params(5000/*pe*/, 2/*lambda*/); + typename PcKrSwCurve::EffToAbsParams effToAbsParams(0/*swr*/, 0/*snr*/); + pcKrSwCurveBackground_ = std::make_unique(params, effToAbsParams); + pcKrSwCurveLenses_ = std::make_unique(params, effToAbsParams); - materialLawParamsLenses_.setSwr(0.); - materialLawParamsLenses_.setSnr(0.); - - //parameters for Brooks-Corey law - - // entry pressures function - materialLawParamsBackground_.setPe(5000.); - materialLawParamsLenses_.setPe(5000.); #else - // residual saturations - materialLawParamsBackground_.setSwr(0.); - materialLawParamsBackground_.setSnr(0.); - - materialLawParamsLenses_.setSwr(0.); - materialLawParamsLenses_.setSnr(0.); - - //parameters for Brooks-Corey law - - // entry pressures - materialLawParamsBackground_.setPe(getParam("SpatialParams.BackgroundEntryPressure", 0.0)); - materialLawParamsLenses_.setPe(getParam("SpatialParams.LenseEntryPressure", 0.0)); -#endif - - // Brooks-Corey shape parameters -#if PROBLEM == 2 - materialLawParamsBackground_.setLambda(getParam("SpatialParams.BackgroundLambda", 3.0)); - materialLawParamsLenses_.setLambda(getParam("SpatialParams.LenseLambda", 2.0)); -#else - materialLawParamsBackground_.setLambda(2.0); - materialLawParamsLenses_.setLambda(2.0); + typename PcKrSwCurve::BasicParams paramsBackground(getParam("SpatialParams.BackgroundEntryPressure", 0.0), + getParam("SpatialParams.BackgroundLambda", 3.0)); + typename PcKrSwCurve::BasicParams paramsLenses(getParam("SpatialParams.LenseEntryPressure", 0.0), + getParam("SpatialParams.LenseLambda", 2.0)); + typename PcKrSwCurve::EffToAbsParams effToAbsParams(0/*swr*/, 0/*snr*/); + pcKrSwCurveBackground_ = std::make_unique(paramsBackground, effToAbsParams); + pcKrSwCurveLenses_ = std::make_unique(paramsLenses, effToAbsParams); #endif #if PROBLEM == 0 @@ -240,8 +210,9 @@ private: return true; } - MaterialLawParams materialLawParamsBackground_; - MaterialLawParams materialLawParamsLenses_; + std::unique_ptr pcKrSwCurveBackground_; + std::unique_ptr pcKrSwCurveLenses_; + FieldMatrix permBackground_; FieldMatrix permLenses_; GlobalPosition lensOneLowerLeft_; diff --git a/test/porousmediumflow/2p/sequential/test_transport.input b/test/porousmediumflow/2p/sequential/test_transport.input index 2c59caec82b49f82222d2674aac62db7d6a27495..fd79b3f2ebd85b4be52605f64a2ce64689883f48 100644 --- a/test/porousmediumflow/2p/sequential/test_transport.input +++ b/test/porousmediumflow/2p/sequential/test_transport.input @@ -11,3 +11,9 @@ LiquidKinematicViscosity = 1.0 [Grid] File = ./grids/test_transport.dgf + +[SpatialParams] +Swr = 0 +Snr = 0 +LinearPcEntry = 0 +LinearPcMax = 0 diff --git a/test/porousmediumflow/2p/sequential/test_transportspatialparams.hh b/test/porousmediumflow/2p/sequential/test_transportspatialparams.hh index ef1d19dd80331cc6920ef62ebd26b61466ecdb26..b16a128274b2c529ebfd689b9466de40102ff898 100644 --- a/test/porousmediumflow/2p/sequential/test_transportspatialparams.hh +++ b/test/porousmediumflow/2p/sequential/test_transportspatialparams.hh @@ -27,8 +27,6 @@ #include #include #include -#include -#include namespace Dumux { @@ -51,16 +49,6 @@ struct TestTransportSpatialParams {}; template struct SpatialParams { using type = TestTransportSpatialParams; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = LinearMaterial; -public: - using type = EffToAbsLaw; -}; } /*! @@ -77,10 +65,12 @@ class TestTransportSpatialParams: public SequentialFVSpatialParams using Scalar = GetPropType; using Element = typename Grid::Traits::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + + using PcKrSwCurve = FluidMatrix::LinearMaterialDefault; public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; + Scalar intrinsicPermeability (const Element& element) const { @@ -92,28 +82,21 @@ public: return 0.2; } - - // return the parameter object for the Brooks-Corey material law which depends on the position - const MaterialLawParams& materialLawParams(const Element &element) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const { - return materialLawParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } - TestTransportSpatialParams(const Problem& problem) - : ParentType(problem) - { - // residual saturations - materialLawParams_.setSwr(0.0); - materialLawParams_.setSnr(0.0); - - // parameters for the linear entry pressures function - materialLawParams_.setEntryPc(0); - materialLawParams_.setMaxPc(0); - } + : ParentType(problem), pcKrSwCurve_("SpatialParams") + {} private: - MaterialLawParams materialLawParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace diff --git a/test/porousmediumflow/2p1c/implicit/params_box.input b/test/porousmediumflow/2p1c/implicit/params_box.input index 0cfbd646e155627593a35caa21ca70046b0cd079..c93fdeeb0c96d7ffe08e9dd3f5757eef6ce4a19c 100644 --- a/test/porousmediumflow/2p1c/implicit/params_box.input +++ b/test/porousmediumflow/2p1c/implicit/params_box.input @@ -13,3 +13,9 @@ Name = test_boxsteaminjection # name passed to the output routines SolidDensity = 2650 SolidThermalConductivity = 2.8 SolidHeatCapacity = 850.0 + +[SpatialParams] +Swr = 0.1 +Snr = 0 +VanGenuchtenAlpha = 0.0028 +VanGenuchtenN = 2.0 diff --git a/test/porousmediumflow/2p1c/implicit/params_tpfa.input b/test/porousmediumflow/2p1c/implicit/params_tpfa.input index 8d5fbbc7da10136513f7a2bb5a4f0e30f15ef827..9b18fbb3c48a2fd1802071e1eea1e9e8c0a8e751 100644 --- a/test/porousmediumflow/2p1c/implicit/params_tpfa.input +++ b/test/porousmediumflow/2p1c/implicit/params_tpfa.input @@ -13,3 +13,9 @@ Name = test_ccsteaminjection # name passed to the output routines SolidDensity = 2650 SolidThermalConductivity = 2.8 SolidHeatCapacity = 850.0 + +[SpatialParams] +Swr = 0.1 +Snr = 0 +VanGenuchtenAlpha = 0.0028 +VanGenuchtenN = 2.0 diff --git a/test/porousmediumflow/2p1c/implicit/spatialparams.hh b/test/porousmediumflow/2p1c/implicit/spatialparams.hh index b298ab78a125aa8f96c0aa55a1611abfd46ef559..6046c2e3fafd177e7aab31e14ba364d334fdf165 100644 --- a/test/porousmediumflow/2p1c/implicit/spatialparams.hh +++ b/test/porousmediumflow/2p1c/implicit/spatialparams.hh @@ -27,8 +27,7 @@ #include #include -#include -#include +#include namespace Dumux { /*! @@ -53,23 +52,16 @@ class InjectionProblemSpatialParams using DimWorldMatrix = Dune::FieldMatrix; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = DimWorldMatrix; InjectionProblemSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { gasWetting_ = getParam("SpatialParams.GasWetting", false); - - // set Van Genuchten Parameters - materialParams_.setSwr(0.1); - materialParams_.setSnr(0.0); - materialParams_.setVgAlpha(0.0028); - materialParams_.setVgn(2.0); } /*! @@ -104,9 +96,9 @@ public: * * \param globalPos The global position */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! @@ -126,7 +118,7 @@ public: private: bool gasWetting_; - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; }; } diff --git a/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/params.input b/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/params.input index 353c491f265ce36fc7300c2430f8a7cc3e9f397b..1b6a94cf71466db1efb057a69054a7bb44c27ebd 100644 --- a/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/params.input +++ b/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/params.input @@ -12,11 +12,16 @@ Name = chemicalnonequilibrium EnableGravity = false [SpatialParams] -WettingNonwettingAreaA1 = -1.603e-01 -WettingNonwettingAreaA2 = 1.429e-05 -WettingNonwettingAreaA3 = 1.915e-01 +WettingNonwettingArea.PcMax = 0 # will be overwritten internally +WettingNonwettingArea.A1 = -1.603e-01 +WettingNonwettingArea.A2 = 1.429e-05 +WettingNonwettingArea.A3 = 1.915e-01 MeanPoreSize = 5e-4 MassTransferFactor = 0.5 +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2.0 +Swr = 0.2 +Snr = 0.1 [Component] SolidDensity = 2700 diff --git a/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/spatialparams.hh b/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/spatialparams.hh index 50f229a1580d8eab66a627d50e159ee2ce60c6e9..4a917e81a80147be9dd33297bd277e70ebd1a1cd 100644 --- a/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/spatialparams.hh +++ b/test/porousmediumflow/2p2c/implicit/chemicalnonequilibrium/spatialparams.hh @@ -28,16 +28,11 @@ #include #include #include -#include -#include -#include +#include +#include +#include -// material laws for interfacial area -#include -#include -#include -#include namespace Dumux { /** @@ -61,49 +56,30 @@ class TwoPTwoCChemicalNonequilibriumSpatialParams enum {dimWorld=GridView::dimensionworld}; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + using WettingNonwettingInterfacialArea = FluidMatrix::InterfacialArea; public: //! Export permeability type using PermeabilityType = Scalar; - //! Export the type used for the material law - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - using EffectiveIALawAwn = AwnSurfacePcMaxFct; - using AwnSurface = EffToAbsLawIA; - using AwnSurfaceParams = typename AwnSurface::Params; TwoPTwoCChemicalNonequilibriumSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , permeability_(1e-11) + , porosity_(0.4) + , pcKrSwCurve_("SpatialParams") { - // intrinsic permeabilities - coarseK_ = 1e-11; - - // the porosity - porosity_ = 0.4; - - // residual saturations - coarseMaterialParams_.setSwr(0.2); - coarseMaterialParams_.setSnr(0.1); - - // parameters for the Brooks-Corey law - coarseMaterialParams_.setPe(1e4); - coarseMaterialParams_.setLambda(2.0); + characteristicLength_ = getParam("SpatialParams.MeanPoreSize"); + factorMassTransfer_ = getParam("SpatialParams.MassTransferFactor"); - aWettingNonwettingA1_ = getParam("SpatialParams.WettingNonwettingAreaA1"); - aWettingNonwettingA2_ = getParam("SpatialParams.WettingNonwettingAreaA2"); - aWettingNonwettingA3_ = getParam("SpatialParams.WettingNonwettingAreaA3"); + auto anwParams = WettingNonwettingInterfacialArea::makeBasicParams("SpatialParams.WettingNonwettingArea"); - // wetting-non wetting: surface which goes to zero on the edges, but is a polynomial - aWettingNonwettingSurfaceParams_.setA1(aWettingNonwettingA1_); - aWettingNonwettingSurfaceParams_.setA2(aWettingNonwettingA2_); - aWettingNonwettingSurfaceParams_.setA3(aWettingNonwettingA3_); // determine maximum capillary pressure for wetting-nonwetting surface - using TwoPLaw = EffToAbsLaw>; - pcMax_ = TwoPLaw::pc(coarseMaterialParams_, /*sw = */0.0); - aWettingNonwettingSurfaceParams_.setPcMax(pcMax_); - characteristicLength_ =getParam("SpatialParams.MeanPoreSize"); - factorMassTransfer_ = getParam("SpatialParams.MassTransferFactor"); + anwParams.setPcMax(pcKrSwCurve_.pc(/*sw = */0.0)); + + aNw_ = std::make_unique(anwParams); } template @@ -111,7 +87,7 @@ public: const SubControlVolume& scv, const ElementSolution& elemSol) const { - return coarseK_; + return permeability_; } /*! @@ -126,53 +102,13 @@ public: } /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). - * - * \param globalPos The global position of the sub-control volume. - * \return The material parameters object - */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { - return coarseMaterialParams_; - } - - /*!\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 fluid-matrix interaction law at a given location */ - template - const AwnSurfaceParams& aWettingNonwettingSurfaceParams(const Element &element, - const SubControlVolume &scv, - const ElementSolution &elemSol) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return aWettingNonwettingSurfaceParams_ ; + return makeFluidMatrixInteraction(pcKrSwCurve_, *aNw_); } - /*!\brief Returns the maximum capillary pressure for the given pc-Sw curve - * - * Of course physically there is no such thing as a maximum capillary pressure. - * The parametrization (VG/BC) goes to infinity and physically there is only one pressure - * for single phase conditions. - * Here, this is used for fitting the interfacial area surface: the capillary pressure, - * where the interfacial area is zero. - * 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. - * \param element The finite element - * \param scv The sub-control volume - * \param elemSol The element solution - */ - template - const Scalar pcMax(const Element &element, - const SubControlVolume &scv, - const ElementSolution &elemSol) const - { return aWettingNonwettingSurfaceParams_.pcMax() ; } - /*! * \brief Returns the characteristic length for the mass transfer. * @@ -201,18 +137,12 @@ public: private: - Scalar coarseK_; - Scalar porosity_; - MaterialLawParams coarseMaterialParams_; + const Scalar permeability_; + const Scalar porosity_; static constexpr Scalar eps_ = 1e-6; - AwnSurfaceParams aWettingNonwettingSurfaceParams_; - Scalar pcMax_ ; - - // interfacial area parameters - Scalar aWettingNonwettingA1_ ; - Scalar aWettingNonwettingA2_ ; - Scalar aWettingNonwettingA3_ ; + const PcKrSwCurve pcKrSwCurve_; + std::unique_ptr aNw_; Scalar factorMassTransfer_ ; Scalar characteristicLength_ ; diff --git a/test/porousmediumflow/2p2c/implicit/injection/params.input b/test/porousmediumflow/2p2c/implicit/injection/params.input index 2a03857bf954d35d9f4fe6aeb891cd91c26f8c3d..eba1e4ef071fda6d14f32a5e3c3b2fe38979aa61 100644 --- a/test/porousmediumflow/2p2c/implicit/injection/params.input +++ b/test/porousmediumflow/2p2c/implicit/injection/params.input @@ -24,3 +24,13 @@ TemperatureHigh = 314.15 # [Pa] upper temperature limit for tabularization PriVarNamesState1 = p_liq x^N2_liq PriVarNamesState2 = p_liq x^H2O_gas PriVarNamesState3 = p_liq S_gas + +[SpatialParams] +FineMaterial.Swr = 0.2 +FineMaterial.Snr = 0.0 +FineMaterial.BrooksCoreyPcEntry = 1e4 +FineMaterial.BrooksCoreyLambda = 2.0 +CoarseMaterial.Swr = 0.2 +CoarseMaterial.Snr = 0.0 +CoarseMaterial.BrooksCoreyPcEntry = 1e4 +CoarseMaterial.BrooksCoreyLambda = 2.0 diff --git a/test/porousmediumflow/2p2c/implicit/injection/spatialparams.hh b/test/porousmediumflow/2p2c/implicit/injection/spatialparams.hh index d23d12282e1e3e3e4892014ff082da307f2a5822..5f74e016ad9902f51c1706081e23270bbb6b88f7 100644 --- a/test/porousmediumflow/2p2c/implicit/injection/spatialparams.hh +++ b/test/porousmediumflow/2p2c/implicit/injection/spatialparams.hh @@ -28,8 +28,7 @@ #include #include -#include -#include +#include namespace Dumux { @@ -51,19 +50,18 @@ class InjectionSpatialParams static constexpr int dimWorld = GridView::dimensionworld; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; InjectionSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , finePcKrSwCurve_("SpatialParams.FineMaterial") + , coarsePcKrSwCurve_("SpatialParams.CoarseMaterial") { layerBottom_ = 22.5; @@ -74,18 +72,6 @@ public: // porosities finePorosity_ = 0.3; coarsePorosity_ = 0.3; - - // residual saturations - fineMaterialParams_.setSwr(0.2); - fineMaterialParams_.setSnr(0.0); - coarseMaterialParams_.setSwr(0.2); - coarseMaterialParams_.setSnr(0.0); - - // parameters for the Brooks-Corey law - fineMaterialParams_.setPe(1e4); - coarseMaterialParams_.setPe(1e4); - fineMaterialParams_.setLambda(2.0); - coarseMaterialParams_.setLambda(2.0); } /*! @@ -119,11 +105,11 @@ public: * * \param globalPos The global position */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + const auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - return coarseMaterialParams_; + return makeFluidMatrixInteraction(finePcKrSwCurve_); + return makeFluidMatrixInteraction(coarsePcKrSwCurve_); } /*! @@ -147,8 +133,8 @@ private: Scalar finePorosity_; Scalar coarsePorosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const PcKrSwCurve finePcKrSwCurve_; + const PcKrSwCurve coarsePcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2p2c/implicit/mpnccomparison/params.input b/test/porousmediumflow/2p2c/implicit/mpnccomparison/params.input index 740e5317e7df3b66e8fb0e9b26aa983e7bea34ba..7dbea708cabc39f005b25caf3949af3e84a0bf8f 100644 --- a/test/porousmediumflow/2p2c/implicit/mpnccomparison/params.input +++ b/test/porousmediumflow/2p2c/implicit/mpnccomparison/params.input @@ -11,3 +11,13 @@ ResidualReduction = 1e-12 [Problem] Name = obstacle_2p + +[SpatialParams] +FineMaterial.Swr = 0.2 +FineMaterial.Snr = 0.0 +FineMaterial.BrooksCoreyPcEntry = 1e4 +FineMaterial.BrooksCoreyLambda = 2.0 +CoarseMaterial.Swr = 0.2 +CoarseMaterial.Snr = 0.0 +CoarseMaterial.BrooksCoreyPcEntry = 1e4 +CoarseMaterial.BrooksCoreyLambda = 2.0 diff --git a/test/porousmediumflow/2p2c/implicit/mpnccomparison/spatialparams.hh b/test/porousmediumflow/2p2c/implicit/mpnccomparison/spatialparams.hh index d984c54cb98e7ee6de914dc9aa97cafc21fd9f60..4720777dba398f3ebcc1fa9d64a9273970bb1022 100644 --- a/test/porousmediumflow/2p2c/implicit/mpnccomparison/spatialparams.hh +++ b/test/porousmediumflow/2p2c/implicit/mpnccomparison/spatialparams.hh @@ -27,10 +27,7 @@ #include #include -#include -#include - -#include +#include namespace Dumux { @@ -55,17 +52,16 @@ class TwoPTwoCComparisonSpatialParams enum {dimWorld=GridView::dimensionworld}; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve =FluidMatrix::BrooksCoreyDefault; public: //! Export permeability type using PermeabilityType = Scalar; - //! Export the type used for the material law - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - - TwoPTwoCComparisonSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + TwoPTwoCComparisonSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + , finePcKrSwCurve_("SpatialParams.FineMaterial") + , coarsePcKrSwCurve_("SpatialParams.CoarseMaterial") { // intrinsic permeabilities coarseK_ = 1e-12; @@ -73,18 +69,6 @@ public: // the porosity porosity_ = 0.3; - - // residual saturations - fineMaterialParams_.setSwr(0.2); - fineMaterialParams_.setSnr(0.0); - coarseMaterialParams_.setSwr(0.2); - coarseMaterialParams_.setSnr(0.0); - - // parameters for the Brooks-Corey law - fineMaterialParams_.setPe(1e4); - coarseMaterialParams_.setPe(1e4); - fineMaterialParams_.setLambda(2.0); - coarseMaterialParams_.setLambda(2.0); } template @@ -115,12 +99,11 @@ public: * \param globalPos The global position of the sub-control volume. * \return The material parameters object */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(finePcKrSwCurve_); + return makeFluidMatrixInteraction(coarsePcKrSwCurve_); } /*! @@ -149,8 +132,9 @@ private: Scalar coarseK_; Scalar fineK_; Scalar porosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + + const PcKrSwCurve finePcKrSwCurve_; + const PcKrSwCurve coarsePcKrSwCurve_; static constexpr Scalar eps_ = 1e-6; }; diff --git a/test/porousmediumflow/2p2c/implicit/waterair/params.input b/test/porousmediumflow/2p2c/implicit/waterair/params.input index 14fd8b735969e415c12a05115e9509a3c31190b8..d9191a92bb2ccf2a9ebb40f40c2d005173f68dd4 100644 --- a/test/porousmediumflow/2p2c/implicit/waterair/params.input +++ b/test/porousmediumflow/2p2c/implicit/waterair/params.input @@ -24,3 +24,9 @@ MaxRelativeShift = 1e-13 SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2 +Swr = 0.2 +Snr = 0.0 diff --git a/test/porousmediumflow/2p2c/implicit/waterair/problem.hh b/test/porousmediumflow/2p2c/implicit/waterair/problem.hh index 3cdd37b7fbc5786b3384c1a4b018b8ecc1da098c..89dd1fdf7f185a6ab6883ee874ae5edfdd2891dd 100644 --- a/test/porousmediumflow/2p2c/implicit/waterair/problem.hh +++ b/test/porousmediumflow/2p2c/implicit/waterair/problem.hh @@ -266,9 +266,8 @@ public: values[contiN2EqIdx] = useMoles ? -1e-3/FluidSystem::molarMass(N2Idx) : -1e-3; // kg/(m^2*s) or mole/(m^2*s) const auto initialValues = initial_(globalPos); - const auto& mParams = this->spatialParams().materialLawParamsAtPos(globalPos); - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - const auto pn = initialValues[pressureIdx] + MaterialLaw::endPointPc(mParams); + const auto& fluidMatrixInteraction = this->spatialParams().fluidMatrixInteractionAtPos(globalPos); + const auto pn = initialValues[pressureIdx] + fluidMatrixInteraction.endPointPc(); const auto t = initialValues[temperatureIdx]; // note: energy equation is always formulated in terms of mass specific quantities, not per mole diff --git a/test/porousmediumflow/2p2c/implicit/waterair/spatialparams.hh b/test/porousmediumflow/2p2c/implicit/waterair/spatialparams.hh index fa6f8a26b9fffa58427fe5ad00ae21c97534e49e..0ee720606fe174b35e496c8ee227bd2bded3bb26 100644 --- a/test/porousmediumflow/2p2c/implicit/waterair/spatialparams.hh +++ b/test/porousmediumflow/2p2c/implicit/waterair/spatialparams.hh @@ -24,14 +24,14 @@ #ifndef DUMUX_WATER_AIR_SPATIAL_PARAMS_HH #define DUMUX_WATER_AIR_SPATIAL_PARAMS_HH +#include #include #include -#include +#include #include #include #include -#include -#include +#include namespace Dumux { @@ -52,15 +52,16 @@ class WaterAirSpatialParams static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the type used for the material law - using MaterialLaw = EffToAbsLaw>; - using MaterialLawParams = typename MaterialLaw::Params; + WaterAirSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { layerBottom_ = 22.0; @@ -72,18 +73,6 @@ public: finePorosity_ = 0.3; coarsePorosity_ = 0.3; - // residual saturations - fineMaterialParams_.setSwr(0.2); - fineMaterialParams_.setSnr(0.0); - coarseMaterialParams_.setSwr(0.2); - coarseMaterialParams_.setSnr(0.0); - - // parameters for the Brooks-Corey law - fineMaterialParams_.setPe(1e4); - coarseMaterialParams_.setPe(1e4); - fineMaterialParams_.setLambda(2.0); - coarseMaterialParams_.setLambda(2.0); - plotFluidMatrixInteractions_ = getParam("Output.PlotFluidMatrixInteractions"); } @@ -93,18 +82,21 @@ public: */ void plotMaterialLaw() { - PlotMaterialLaw plotMaterialLaw; GnuplotInterface gnuplot(plotFluidMatrixInteractions_); gnuplot.setOpenPlotWindow(plotFluidMatrixInteractions_); - plotMaterialLaw.addpcswcurve(gnuplot, fineMaterialParams_, 0.2, 1.0, "fine", "w lp"); - plotMaterialLaw.addpcswcurve(gnuplot, coarseMaterialParams_, 0.2, 1.0, "coarse", "w l"); + + const auto sw = linspace(0.2, 1.0, 1000); + + const auto pc = samplePcSw(pcKrSwCurve_, sw); + Gnuplot::addPcSw(gnuplot, sw, pc, "pc-Sw", "w lp"); gnuplot.setOption("set xrange [0:1]"); gnuplot.setOption("set label \"residual\\nsaturation\" at 0.1,100000 center"); gnuplot.plot("pc-Sw"); gnuplot.resetAll(); - plotMaterialLaw.addkrcurves(gnuplot, fineMaterialParams_, 0.2, 1.0, "fine"); - plotMaterialLaw.addkrcurves(gnuplot, coarseMaterialParams_, 0.2, 1.0, "coarse"); + + const auto [krw, krn] = sampleRelPerms(makeFluidMatrixInteraction(pcKrSwCurve_), sw); // test wrapped law + Gnuplot::addRelPerms(gnuplot, sw, krw, krn, "kr-Sw", "w lp"); gnuplot.plot("kr"); } @@ -134,19 +126,13 @@ public: return coarsePorosity_; } - /*! - * \brief Returns the parameter object for the Brooks-Corey material law - * which depends on the position - * - * \param globalPos The global position + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! @@ -170,8 +156,7 @@ private: Scalar finePorosity_; Scalar coarsePorosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const PcKrSwCurve pcKrSwCurve_; bool plotFluidMatrixInteractions_; }; diff --git a/test/porousmediumflow/2p2c/sequential/test_dec2p2c_spatialparams.hh b/test/porousmediumflow/2p2c/sequential/test_dec2p2c_spatialparams.hh index 5aea20656e729b8f80cc732b69716a276555c6b4..cbbc484c06c289780f62b9aaa0b94e4c1a923621 100644 --- a/test/porousmediumflow/2p2c/sequential/test_dec2p2c_spatialparams.hh +++ b/test/porousmediumflow/2p2c/sequential/test_dec2p2c_spatialparams.hh @@ -28,7 +28,6 @@ #include #include #include -#include namespace Dumux { @@ -47,16 +46,6 @@ struct Test2P2CSpatialParams {}; template struct SpatialParams { using type = Test2P2CSpatialParams; }; -// Set the material law -template -struct MaterialLaw -{ -private: - using Scalar = GetPropType; - using RawMaterialLaw = LinearMaterial; -public: - using type = EffToAbsLaw; -}; } /*! @@ -72,12 +61,13 @@ class Test2P2CSpatialParams : public SequentialFVSpatialParams enum { dim = GridView::dimension }; using Element = typename GridView::Traits::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FieldMatrix = Dune::FieldMatrix; + using PcKrSwCurve = FluidMatrix::LinearMaterialDefault; + public: - using MaterialLaw = GetPropType; - using MaterialLawParams = typename MaterialLaw::Params; const FieldMatrix& intrinsicPermeability (const Element& element) const { @@ -89,23 +79,22 @@ public: return 0.2; } - - // return the parameter object for the Brooks-Corey material law which depends on the position - const MaterialLawParams& materialLawParams(const Element &element) const + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * + * \param globalPos The global coordinates for the given location + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialLawParams_; + return makeFluidMatrixInteraction(*pcKrSwCurve_); } - - Test2P2CSpatialParams(const Problem& problem) : SequentialFVSpatialParams(problem), - constPermeability_(0) + Test2P2CSpatialParams(const Problem& problem) + : SequentialFVSpatialParams(problem) + , constPermeability_(0) { - // residual saturations - materialLawParams_.setSwr(0); - materialLawParams_.setSnr(0); - - materialLawParams_.setEntryPc(0); - materialLawParams_.setMaxPc(10000); + typename PcKrSwCurve::BasicParams params(0/*pcEntry*/, 10000/*pcMax*/); + pcKrSwCurve_ = std::make_unique(params); for(int i = 0; i < dim; i++) { @@ -114,8 +103,8 @@ public: } private: - MaterialLawParams materialLawParams_; FieldMatrix constPermeability_; + std::unique_ptr pcKrSwCurve_; }; diff --git a/test/porousmediumflow/2pnc/implicit/diffusion/params.input b/test/porousmediumflow/2pnc/implicit/diffusion/params.input index b658cedc1385c9db7beeee5d4cb8e7e06510140a..49248e5f84fe1c3b7c283f2a867bf4e40662efab 100644 --- a/test/porousmediumflow/2pnc/implicit/diffusion/params.input +++ b/test/porousmediumflow/2pnc/implicit/diffusion/params.input @@ -9,3 +9,9 @@ Cells = 50 5 [Problem] Name = 2pnc_diffusion EnableGravity = false + +[SpatialParams] +BrooksCoreyPcEntry = 1e2 +BrooksCoreyLambda = 1.3 +Swr = 0.02 +Snr = 0.0 diff --git a/test/porousmediumflow/2pnc/implicit/diffusion/spatialparams.hh b/test/porousmediumflow/2pnc/implicit/diffusion/spatialparams.hh index dcbcfce6cf24771446ac4fcd4cead35bba358a57..e291b2a8fb2446dad257d879ac2d81db92d72eb7 100644 --- a/test/porousmediumflow/2pnc/implicit/diffusion/spatialparams.hh +++ b/test/porousmediumflow/2pnc/implicit/diffusion/spatialparams.hh @@ -28,10 +28,7 @@ #include #include -#include -#include -#include -#include +#include namespace Dumux { /*! @@ -55,33 +52,22 @@ class TwoPNCDiffusionSpatialParams using DimWorldMatrix = Dune::FieldMatrix; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; public: using PermeabilityType = DimWorldMatrix; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - TwoPNCDiffusionSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry), K_(0) + : ParentType(gridGeometry) + , K_(0) + , pcKrSwCurve_("SpatialParams") { // intrinsic permeabilities K_[0][0] = 5e-11; K_[1][1] = 5e-11; - - // porosities - porosity_ = 0.2; - - // residual saturations - materialParams_.setSwr(0.02); - materialParams_.setSnr(0.0); - - // parameters for the vanGenuchten law - materialParams_.setPe(1e2); // alpha = 1/pcb - materialParams_.setLambda(1.3); } + /*! * \brief Returns the hydraulic conductivity \f$[m^2]\f$ * @@ -99,13 +85,12 @@ public: { return 0.2; } /*! - * \brief Returns the parameter object for the Brooks-Corey material law - * which depends on the position. + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The global position + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -119,9 +104,8 @@ public: private: DimWorldMatrix K_; - Scalar porosity_; static constexpr Scalar eps_ = 1e-6; - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2pnc/implicit/fuelcell/params.input b/test/porousmediumflow/2pnc/implicit/fuelcell/params.input index 39d050f5a1ba930ff3d52dc19f83cd081c584b64..e26db822b16aab8511ba3e64c0ad795702e74efb 100644 --- a/test/porousmediumflow/2pnc/implicit/fuelcell/params.input +++ b/test/porousmediumflow/2pnc/implicit/fuelcell/params.input @@ -42,3 +42,9 @@ SurfaceIncreasingFactor = 60 TransportNumberH20 = 0.2327 # [-] account for osmotic H20 transport term from membrane, value Lena Walter pO2Inlet = 0.3e5 # [Pa] partial pressure of oxygen at gas channel inlet MaxIterations = 300 # [-] Maximum number for iterations for solving electrochemical system + +[SpatialParams] +VanGenuchtenN = 3.652 +VanGenuchtenAlpha = 6.66e-5 +Swr = 0.12 +Snr = 0.0 diff --git a/test/porousmediumflow/2pnc/implicit/fuelcell/spatialparams.hh b/test/porousmediumflow/2pnc/implicit/fuelcell/spatialparams.hh index 33c29ca340550653c509913c931e517768884016..6292e4659fe021bf1ac8e5b94efad20e10986e7d 100644 --- a/test/porousmediumflow/2pnc/implicit/fuelcell/spatialparams.hh +++ b/test/porousmediumflow/2pnc/implicit/fuelcell/spatialparams.hh @@ -28,10 +28,7 @@ #include #include -#include -#include -#include -#include +#include namespace Dumux { /*! @@ -55,30 +52,19 @@ class FuelCellSpatialParams using DimWorldMatrix = Dune::FieldMatrix; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = DimWorldMatrix; FuelCellSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry), K_(0) + : ParentType(gridGeometry) + , K_(0) + , pcKrSwCurve_("SpatialParams") { // intrinsic permeabilities K_[0][0] = 5e-11; K_[1][1] = 5e-11; - - // porosities - porosity_ = 0.2; - - // residual saturations - materialParams_.setSwr(0.12); // air is wetting phase - materialParams_.setSnr(0.0); // water is nonwetting - - //parameters for the vanGenuchten law - materialParams_.setVgAlpha(6.66e-5); // alpha = 1/pcb - materialParams_.setVgn(3.652); } /*! @@ -95,21 +81,16 @@ public: * \param globalPos The global position */ Scalar porosityAtPos(const GlobalPosition& globalPos) const - { - if (globalPos[1] < eps_) - return porosity_; - else - return 0.2; - } + { return 0.2; } /*! - * \brief Returns the parameter object for the Brooks-Corey material law - * which depends on the position. - * - * \param globalPos The global position + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -124,9 +105,8 @@ public: private: DimWorldMatrix K_; - Scalar porosity_; static constexpr Scalar eps_ = 1e-6; - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2pncmin/implicit/isothermal/params.input b/test/porousmediumflow/2pncmin/implicit/isothermal/params.input index 0fd2372265fbdf8e1a9d062ca49c134a604bacd2..94578dd96b84662c9571dd0fddedb4a25b97a65d 100644 --- a/test/porousmediumflow/2pncmin/implicit/isothermal/params.input +++ b/test/porousmediumflow/2pncmin/implicit/isothermal/params.input @@ -37,10 +37,10 @@ InitPrecipitatedSaltBlock = 0.05 # [-] initial precipitated salt in the b SolubilityLimit = 0.26 # [-] solubility limit of salt in brine referencePorosity = 0.11 # [-] initial porosity referencePermeability = 2.23e-14 -IrreducibleLiqSat = 0.2 # [-] irreducible liquid saturation -IrreducibleGasSat = 0.001 # [-] irreducible gas saturation -Pentry1 = 500 # [Pa] -BCLambda1 = 2 # [-] +Swr = 0.2 # [-] irreducible liquid saturation +Snr = 0.001 # [-] irreducible gas saturation +BrooksCoreyPcEntry = 500 # [Pa] +BrooksCoreyLambda = 2 # [-] [Vtk] AddVelocity = 1 # Add extra information diff --git a/test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh b/test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh index bcdb15a870c63a5ec9de6ff55b0733d063eac1b2..38ff73993981b55256115ac62bacfffbb15ee486 100644 --- a/test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh +++ b/test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh @@ -27,9 +27,7 @@ #define DUMUX_INJECTION_SPATIAL_PARAMETERS_HH #include -#include -#include -#include +#include #include #include @@ -53,35 +51,21 @@ class DissolutionSpatialParams using ParentType = FVSpatialParams>; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; using GlobalPosition = typename SubControlVolume::GlobalPosition; public: // type used for the permeability (i.e. tensor or scalar) using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; DissolutionSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { solubilityLimit_ = getParam("SpatialParams.SolubilityLimit", 0.26); referencePorosity_ = getParam("SpatialParams.referencePorosity", 0.11); referencePermeability_ = getParam("SpatialParams.referencePermeability", 2.23e-14); - irreducibleLiqSat_ = getParam("SpatialParams.IrreducibleLiqSat", 0.2); - irreducibleGasSat_ = getParam("SpatialParams.IrreducibleGasSat", 1e-3); - pEntry1_ = getParam("SpatialParams.Pentry1", 500); - bcLambda1_ = getParam("SpatialParams.BCLambda1", 2); - - // residual saturations - materialParams_.setSwr(irreducibleLiqSat_); - materialParams_.setSnr(irreducibleGasSat_); - - // parameters of Brooks & Corey Law - materialParams_.setPe(pEntry1_); - materialParams_.setLambda(bcLambda1_); } /*! @@ -144,9 +128,14 @@ public: Scalar theta(const SubControlVolume &scv) const { return 10.0; } - // return the brooks-corey context depending on the position - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } // define which phase is to be considered as the wetting phase template @@ -155,17 +144,12 @@ public: private: - MaterialLawParams materialParams_; - PermeabilityKozenyCarman permLaw_; Scalar solubilityLimit_; Scalar referencePorosity_; PermeabilityType referencePermeability_ = 0.0; - Scalar irreducibleLiqSat_; - Scalar irreducibleGasSat_; - Scalar pEntry1_; - Scalar bcLambda1_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input index b8eecf0438621629fd80733786dd9ebe4d13e718..51d63dc04c19a8e8b6aa9943a93fcd2bbfacde34 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input @@ -40,10 +40,10 @@ RefTemperature = 299 # [K] temperature in the air abo SolubilityLimit = 0.26 # [-] solubility limit of NaCl in brine referencePorosity = 0.4 # [-] initial porosity referencePermeability = 1e-13 # [m²] initial permeability -VGAlpha = 0.00015 # Van Genuchten parameter -VGn = 14.0 # Van Genuchten parameter -IrreducibleLiqSat = 0.25 # [-] irreducible liquid saturation -IrreducibleGasSat = 0.025 # [-] irreducible gas saturation +VanGenuchtenAlpha = 0.00015 # Van Genuchten parameter +VanGenuchtenN = 14.0 # Van Genuchten parameter +Swr = 0.25 # [-] irreducible liquid saturation +Snr = 0.025 # [-] irreducible gas saturation [Vtk] AddVelocity = 1 # Add extra information diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh b/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh index ecb694b7a6d4b8e2dd21baa37fca66225b67e92b..04d8d7df54ed1ba1fa175ec02b7291d9d8b7fa14 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh b/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh index 276f8764c317fabd9498a1dae56fab78925f9555..b0f95c14862b4356c4511a2bb57ec1848bb5c981 100644 --- a/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh @@ -26,12 +26,8 @@ #ifndef DUMUX_SALINIZATION_SPATIAL_PARAMETERS_HH #define DUMUX_SALINIZATION_SPATIAL_PARAMETERS_HH -#include -#include #include -#include -#include -#include +#include #include #include @@ -55,38 +51,21 @@ class SalinizationSpatialParams using ParentType = FVSpatialParams>; - using EffectiveLaw = RegularizedVanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; using GlobalPosition = typename SubControlVolume::GlobalPosition; public: // type used for the permeability (i.e. tensor or scalar) using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; SalinizationSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { solubilityLimit_ = getParam("SpatialParams.SolubilityLimit", 0.26); referencePorosity_ = getParam("SpatialParams.referencePorosity", 0.11); referencePermeability_ = getParam("SpatialParams.referencePermeability", 2.23e-14); - irreducibleLiqSat_ = getParam("SpatialParams.IrreducibleLiqSat", 0.2); - irreducibleGasSat_ = getParam("SpatialParams.IrreducibleGasSat", 1e-3); - vgAlpha_ = getParam("SpatialParams.VGAlpha", 1.5); - vgn_ = getParam("SpatialParams.VGn", 4.0); - - plotFluidMatrixInteractions_ = getParam("Output.PlotFluidMatrixInteractions"); - - //Van Genuchen parameters - // residual saturations - materialParams_.setSwr(irreducibleLiqSat_); - materialParams_.setSnr(irreducibleGasSat_); - - //Van Genuchen parameters - materialParams_.setVgAlpha(vgAlpha_ ); - materialParams_.setVgn(vgn_); } /*! @@ -150,9 +129,14 @@ public: Scalar theta(const SubControlVolume &scv) const { return 10.0; } - // return the brooks-corey context depending on the position - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { return materialParams_; } + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const + { + return makeFluidMatrixInteraction(pcKrSwCurve_); + } // define which phase is to be considered as the wetting phase template @@ -161,19 +145,13 @@ public: private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; PermeabilityKozenyCarman permLaw_; Scalar solubilityLimit_; Scalar referencePorosity_; PermeabilityType referencePermeability_ = 0.0; - Scalar irreducibleLiqSat_; - Scalar irreducibleGasSat_; - Scalar vgAlpha_; - Scalar vgn_ ; - - bool plotFluidMatrixInteractions_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/3p/implicit/conduction/params.input b/test/porousmediumflow/3p/implicit/conduction/params.input index 4f9840b5f7e5bea1bb3bd45ee3450997de2b286b..3d57f515125616c73d7dbdfd5b41342306d3654f 100644 --- a/test/porousmediumflow/3p/implicit/conduction/params.input +++ b/test/porousmediumflow/3p/implicit/conduction/params.input @@ -19,3 +19,11 @@ AddVelocity = true #Enable velocity output SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +Swr = 0.12 +Snr = 0.10 +Sgr = 0.01 +ParkerVanGenuchtenAlpha = 0.5 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenRegardSnrForKrn = true diff --git a/test/porousmediumflow/3p/implicit/conduction/spatialparams.hh b/test/porousmediumflow/3p/implicit/conduction/spatialparams.hh index 6fa0971a8e5c32d2586b8c42dba346db593ae88d..78f77d58c21b3f778e44ed43d624ea008eaf19d4 100644 --- a/test/porousmediumflow/3p/implicit/conduction/spatialparams.hh +++ b/test/porousmediumflow/3p/implicit/conduction/spatialparams.hh @@ -27,9 +27,7 @@ #include #include -#include -#include -#include +#include namespace Dumux { @@ -49,36 +47,20 @@ class ThreePNISpatialParams using ParentType = FVSpatialParams>; - using EffectiveLaw = RegularizedParkerVanGen3P; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; + public: //! Export permeability type using PermeabilityType = Scalar; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - ThreePNISpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { permeability_ = 1e-10; porosity_ = 0.4; - - // residual saturations - materialParams_.setSwr(0.12); - materialParams_.setSnr(0.10); - materialParams_.setSgr(0.01); - - // parameters for the 3phase van Genuchten law - materialParams_.setVgAlpha(0.5); - materialParams_.setVgn(4.0); - materialParams_.setKrRegardsSnr(true); - - // parameters for adsorption - materialParams_.setKdNAPL(0.); - materialParams_.setRhoBulk(1500.); } /*! @@ -102,18 +84,18 @@ public: } /*! - * \brief Returns the parameter object for the Brooks-Corey material law + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The global position + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } private: - MaterialLawParams materialParams_; + const ThreePhasePcKrSw pcKrSwCurve_; Scalar permeability_; Scalar porosity_; }; diff --git a/test/porousmediumflow/3p/implicit/convection/params.input b/test/porousmediumflow/3p/implicit/convection/params.input index ddc172cec4f29f7a7c4acb22445c48649bc997b7..d2b95c95978f8169a778c59639ce126769c49db9 100644 --- a/test/porousmediumflow/3p/implicit/convection/params.input +++ b/test/porousmediumflow/3p/implicit/convection/params.input @@ -20,3 +20,11 @@ AddVelocity = true #Enable velocity output SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +Swr = 0.12 +Snr = 0.10 +Sgr = 0.01 +ParkerVanGenuchtenAlpha = 0.5 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenRegardSnrForKrn = true diff --git a/test/porousmediumflow/3p/implicit/infiltration/params.input b/test/porousmediumflow/3p/implicit/infiltration/params.input index 2fc97e822c6883ea43f696ddb6d15cca2a256f48..b313b408180f21acab1c7b482800d27c2f962ae5 100644 --- a/test/porousmediumflow/3p/implicit/infiltration/params.input +++ b/test/porousmediumflow/3p/implicit/infiltration/params.input @@ -12,8 +12,15 @@ Name = infiltration3pcc [SpatialParams] permeability = 1.e-11 # m^2 porosity = 0.40 -vanGenuchtenAlpha = 0.0005 -vanGenuchtenN = 4.0 + +ParkerVanGenuchtenAlpha = 0.0005 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenBetaNw = 1 +ParkerVanGenuchtenBetaGw = 1 +ParkerVanGenuchtenBetaGn = 1 +Swr = 0.12 +Snr = 0.07 +Sgr = 0.03 [Output] PlotFluidMatrixInteractions = false diff --git a/test/porousmediumflow/3p/implicit/infiltration/problem.hh b/test/porousmediumflow/3p/implicit/infiltration/problem.hh index 79cb2e8974872fb63e1838fab27a6cf3efbc7c02..8dfc7cd19c72a9887053b232cce3b5a05e4c5d5d 100644 --- a/test/porousmediumflow/3p/implicit/infiltration/problem.hh +++ b/test/porousmediumflow/3p/implicit/infiltration/problem.hh @@ -291,35 +291,36 @@ private: void initial_(PrimaryVariables &values, const GlobalPosition &globalPos) const { - Scalar y = globalPos[1]; - Scalar x = globalPos[0]; + const Scalar y = globalPos[1]; + const Scalar x = globalPos[0]; Scalar sw, swr=0.12, sgr=0.03; - if(y > (-1.E-3*x+5) - eps_) + if (y > (-1e-3*x + 5) - eps_) { - Scalar pc = 9.81 * 1000.0 * (y - (-5E-4*x+5)); + Scalar pc = 9.81 * 1000.0 * (y - (-5e-4*x + 5)); if (pc < 0.0) pc = 0.0; sw = invertPcgw_(pc, - this->spatialParams().materialLawParamsAtPos(globalPos)); + this->spatialParams().fluidMatrixInteractionAtPos(globalPos)); if (sw < swr) sw = swr; if (sw > 1.-sgr) sw = 1.-sgr; values[pressureIdx] = 1e5 ; values[swIdx] = sw; values[snIdx] = 0.; - }else { - values[pressureIdx] = 1e5 + 9.81 * 1000.0 * ((-5E-4*x+5) - y); + } + else + { + values[pressureIdx] = 1e5 + 9.81 * 1000.0 * ((-5e-4*x + 5) - y); values[swIdx] = 1.-sgr; values[snIdx] = 0.; } } // small solver inverting the pc curve - template - static Scalar invertPcgw_(Scalar pcIn, const MaterialLawParams &pcParams) + template + static Scalar invertPcgw_(Scalar pcIn, const FMInteraction& fluidMatrixInteraction) { - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; Scalar lower,upper; int k; int maxIt = 50; @@ -329,7 +330,7 @@ private: for (k=1; k<=25; k++) { sw = 0.5*(upper+lower); - pcgw = MaterialLaw::pcgw(pcParams, sw); + pcgw = fluidMatrixInteraction.pcgw(sw, 0.0); Scalar delta = pcgw-pcIn; if (delta<0.) delta*=-1.; if (delta #include -#include -#include -#include +#include #include -#include +#include namespace Dumux { /*! @@ -53,18 +51,15 @@ class InfiltrationThreePSpatialParams using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedParkerVanGen3P; + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; public: //! Export permeability type using PermeabilityType = Scalar; - //! Get the material law from the property system - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - InfiltrationThreePSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { // intrinsic permeabilities fineK_ = getParam("SpatialParams.permeability"); @@ -72,22 +67,6 @@ public: // porosities porosity_ = getParam("SpatialParams.porosity"); - vGAlpha_ = getParam("SpatialParams.vanGenuchtenAlpha"); - vGN_ = getParam("SpatialParams.vanGenuchtenN"); - // residual saturations - materialParams_.setSwr(0.12); - materialParams_.setSnr(0.07); - materialParams_.setSgr(0.03); - - // parameters for the 3phase van Genuchten law - materialParams_.setVgAlpha(vGAlpha_); - materialParams_.setVgn(vGN_); - materialParams_.setKrRegardsSnr(false); - - // parameters for adsorption - materialParams_.setKdNAPL(0.); - materialParams_.setRhoBulk(1500.); - plotFluidMatrixInteractions_ = getParam("Output.PlotFluidMatrixInteractions"); } @@ -99,15 +78,40 @@ public: { GnuplotInterface gnuplot(plotFluidMatrixInteractions_); gnuplot.setOpenPlotWindow(plotFluidMatrixInteractions_); - PlotMaterialLaw plotMaterialLaw(plotFluidMatrixInteractions_); + + const Scalar sg = 0.2; // assume a fixed gas saturation + auto swRange = linspace(0.2, 1.0, 1000); + + // assume fixed sn = 0.2 for pcgw curve + auto pcgw = swRange; + std::transform(swRange.begin(), swRange.end(), pcgw.begin(), [&](auto x){ return this->pcKrSwCurve_.pcgw(x, 0.2); }); gnuplot.resetAll(); - plotMaterialLaw.addpc(gnuplot, materialParams_); - gnuplot.plot("pc"); + gnuplot.setXlabel("Sw"); + gnuplot.setYlabel("pcgw"); + gnuplot.addDataSetToPlot(swRange, pcgw, "pcgw", "w l"); + gnuplot.plot("pcgw-sw"); + + // plot kr + swRange = linspace(0.2, 0.8, 1000); + auto krw = swRange; + auto krn = swRange; + auto krg = swRange; + for (const auto& [i, sw] : enumerate(swRange)) + { + const Scalar sn = 1.0 - sg - sw; + krw[i] = pcKrSwCurve_.krw(sw, sn); + krn[i] = pcKrSwCurve_.krn(sw, sn); + krg[i] = pcKrSwCurve_.krg(sw, sn); + } gnuplot.resetAll(); - plotMaterialLaw.addkr(gnuplot, materialParams_); - gnuplot.plot("kr"); + gnuplot.setXlabel("Sw"); + gnuplot.setYlabel("kr"); + gnuplot.addDataSetToPlot(swRange, krw, "krw", "w l"); + gnuplot.addDataSetToPlot(swRange, krn, "krn", "w l"); + gnuplot.addDataSetToPlot(swRange, krg, "krg", "w l"); + gnuplot.plot("kr-sw"); } /*! @@ -139,29 +143,26 @@ public: } /*! - * \brief Returns the parameter object for the Brooks-Corey material law + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The global position + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } + private: bool isFineMaterial_(const GlobalPosition &globalPos) const - { return - 70. - eps_ <= globalPos[0] && globalPos[0] <= 85. + eps_ && - 7.0 - eps_ <= globalPos[1] && globalPos[1] <= 7.50 + eps_; + { + return 70. - eps_ <= globalPos[0] && globalPos[0] <= 85. + eps_ && + 7.0 - eps_ <= globalPos[1] && globalPos[1] <= 7.50 + eps_; } Scalar fineK_; Scalar coarseK_; - Scalar porosity_; - Scalar vGN_; - Scalar vGAlpha_; - - MaterialLawParams materialParams_; + const ThreePhasePcKrSw pcKrSwCurve_; bool plotFluidMatrixInteractions_; diff --git a/test/porousmediumflow/3p3c/implicit/columnxylol/params.input b/test/porousmediumflow/3p3c/implicit/columnxylol/params.input index f502ce89f7a8b2490bad797bcbf7b1c8d9126b08..0da3b34d3bd9fd2199c876343e1e1d1a2666fa60 100644 --- a/test/porousmediumflow/3p3c/implicit/columnxylol/params.input +++ b/test/porousmediumflow/3p3c/implicit/columnxylol/params.input @@ -18,3 +18,12 @@ SolidDensity = 2650 SolidThermalConductivity = 2.8 SolidHeatCapacityFine = 850 SolidHeatCapacityCoarse = 84000 + +[SpatialParams] +Swr = 0.12 +Snr = 0.10 +Sgr = 0.01 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenRegardSnrForKrn = true +Fine.ParkerVanGenuchtenAlpha = 0.0005 +Coarse.ParkerVanGenuchtenAlpha = 0.5 diff --git a/test/porousmediumflow/3p3c/implicit/columnxylol/spatialparams.hh b/test/porousmediumflow/3p3c/implicit/columnxylol/spatialparams.hh index 4de10b8032374a6a9a8eb9bb503cc8e6ea368f1c..3fade2a52bae389e536546396ca3ee0f15c75b39 100644 --- a/test/porousmediumflow/3p3c/implicit/columnxylol/spatialparams.hh +++ b/test/porousmediumflow/3p3c/implicit/columnxylol/spatialparams.hh @@ -26,9 +26,7 @@ #include #include -#include -#include -#include +#include namespace Dumux { @@ -50,15 +48,16 @@ class ColumnSpatialParams ColumnSpatialParams>; using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedParkerVanGen3P; + + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; ColumnSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurveFine_("SpatialParams.Fine") + , pcKrSwCurveCoarse_("SpatialParams.Coarse") { // intrinsic permeabilities fineK_ = 1.4e-11; @@ -70,29 +69,6 @@ public: // specific heat capacities fineHeatCap_ = getParam("Component.SolidHeatCapacityFine", 850.0); coarseHeatCap_ = getParam("Component.SolidHeatCapacityCoarse", 84000.0); - - // residual saturations - fineMaterialParams_.setSwr(0.12); - fineMaterialParams_.setSnr(0.10); - fineMaterialParams_.setSgr(0.01); - coarseMaterialParams_.setSwr(0.12); - coarseMaterialParams_.setSnr(0.10); - coarseMaterialParams_.setSgr(0.01); - - // parameters for the 3phase van Genuchten law - fineMaterialParams_.setVgAlpha(0.0005); - coarseMaterialParams_.setVgAlpha(0.5); - fineMaterialParams_.setVgn(4.0); - coarseMaterialParams_.setVgn(4.0); - - coarseMaterialParams_.setKrRegardsSnr(true); - fineMaterialParams_.setKrRegardsSnr(true); - - // parameters for adsorption - coarseMaterialParams_.setKdNAPL(0.); - coarseMaterialParams_.setRhoBulk(1500.); - fineMaterialParams_.setKdNAPL(0.); - fineMaterialParams_.setRhoBulk(1500.); } /*! @@ -116,32 +92,31 @@ public: } /*! \brief Defines the porosity in [-]. - * - * \param globalPos The global position where we evaluate - */ + * + * \param globalPos The global position where we evaluate + */ Scalar porosityAtPos(const GlobalPosition& globalPos) const { return porosity_; } /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). + * \brief Returns the fluid-matrix interaction law. * * \param element The current element * \param scv The sub-control volume inside the element. * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + template + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { const auto& globalPos = scv.dofPosition(); if (isFineMaterial_(globalPos)) - return fineMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurveFine_); else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurveCoarse_); } /*! @@ -180,8 +155,8 @@ private: Scalar fineHeatCap_; Scalar coarseHeatCap_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const ThreePhasePcKrSw pcKrSwCurveFine_; + const ThreePhasePcKrSw pcKrSwCurveCoarse_; static constexpr Scalar eps_ = 1e-6; }; diff --git a/test/porousmediumflow/3p3c/implicit/infiltration/params.input b/test/porousmediumflow/3p3c/implicit/infiltration/params.input index d910fd45112ccb392383ce3737ace10045a15e58..9a76b58299f39173f69059a0abec6822ca21fe2e 100644 --- a/test/porousmediumflow/3p3c/implicit/infiltration/params.input +++ b/test/porousmediumflow/3p3c/implicit/infiltration/params.input @@ -14,3 +14,11 @@ NumericDifferenceMethod = 0 # -1 backward differences, 0: central differences, + [Newton] MaxRelativeShift = 1e-6 + +[SpatialParams] +Swr = 0.12 +Snr = 0.07 +Sgr = 0.03 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenAlpha = 0.0005 +ParkerVanGenuchtenRegardSnrForKrn = false diff --git a/test/porousmediumflow/3p3c/implicit/infiltration/problem.hh b/test/porousmediumflow/3p3c/implicit/infiltration/problem.hh index c710cf2b9be4bd1cb0cc28fdd4801b777599edf7..ba40089f112f4100ca4a3cf5f5398cab2303d273 100644 --- a/test/porousmediumflow/3p3c/implicit/infiltration/problem.hh +++ b/test/porousmediumflow/3p3c/implicit/infiltration/problem.hh @@ -274,7 +274,7 @@ private: Scalar pc = 9.81 * 1000.0 * (y - (-5E-4*x+5)); if (pc < 0.0) pc = 0.0; - sw = invertPcgw_(pc, this->spatialParams().materialLawParamsAtPos(globalPos)); + sw = invertPcgw_(pc, this->spatialParams().fluidMatrixInteractionAtPos(globalPos)); if (sw < swr) sw = swr; if (sw > 1.-sgr) sw = 1.-sgr; @@ -289,10 +289,9 @@ private: return values; } - template - static Scalar invertPcgw_(Scalar pcIn, const MaterialLawParams &pcParams) + template + static Scalar invertPcgw_(Scalar pcIn, const FluidMatrixInteraction& fluidmatrixinteraction) { - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; Scalar lower,upper; int k; int maxIt = 50; @@ -302,7 +301,7 @@ private: for (k=1; k<=25; k++) { sw = 0.5*(upper+lower); - pcgw = MaterialLaw::pcgw(pcParams, sw); + pcgw = fluidmatrixinteraction.pcgw(sw, 0.0/*sn*/); Scalar delta = pcgw-pcIn; if (delta<0.) delta*=-1.; if (delta #include -#include -#include -#include -#include +#include namespace Dumux { @@ -51,17 +48,16 @@ class InfiltrationThreePThreeCSpatialParams using ParentType = FVSpatialParams>; - using EffectiveLaw = RegularizedParkerVanGen3P; - using GlobalPosition = typename SubControlVolume::GlobalPosition; + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; + public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; InfiltrationThreePThreeCSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { // intrinsic permeabilities fineK_ = 1.e-11; @@ -69,20 +65,6 @@ public: // porosities porosity_ = 0.40; - - // residual saturations - materialParams_.setSwr(0.12); - materialParams_.setSnr(0.07); - materialParams_.setSgr(0.03); - - // parameters for the 3phase van Genuchten law - materialParams_.setVgAlpha(0.0005); - materialParams_.setVgn(4.); - materialParams_.setKrRegardsSnr(false); - - // parameters for adsorption - materialParams_.setKdNAPL(0.); - materialParams_.setRhoBulk(1500.); } /*! @@ -115,15 +97,14 @@ public: return porosity_; } - /*! - * \brief Returns the parameter object for the material law which depends on the position + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The position for which the material law should be evaluated + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } private: @@ -138,7 +119,7 @@ private: Scalar porosity_; - MaterialLawParams materialParams_; + const ThreePhasePcKrSw pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/3p3c/implicit/kuevette/params.input b/test/porousmediumflow/3p3c/implicit/kuevette/params.input index 757f876da79f58a5e98fe3755ecc8f1c843fa581..06718dd5d12c6521f1aef062dea3612731f7f916 100644 --- a/test/porousmediumflow/3p3c/implicit/kuevette/params.input +++ b/test/porousmediumflow/3p3c/implicit/kuevette/params.input @@ -22,3 +22,13 @@ SolidDensity = 2650 SolidThermalConductivity = 2.8 SolidHeatCapacity = 850 +[SpatialParams] +Swr = 0.12 +Snr = 0.07 +Sgr = 0.01 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenRegardSnrForKrn = true +Fine.ParkerVanGenuchtenAlpha = 0.0005 +Coarse.ParkerVanGenuchtenAlpha = 0.005 +ThreePNAPLAdsorptionRhoBulk = 1500 +ThreePNAPLAdsorptionKdNAPL = 0 diff --git a/test/porousmediumflow/3p3c/implicit/kuevette/spatialparams.hh b/test/porousmediumflow/3p3c/implicit/kuevette/spatialparams.hh index 4f9bb865bbc23b1732461d6c4018232c5203b937..b3ad2a6277eb72d448ed122f4c825bf8ea370995 100644 --- a/test/porousmediumflow/3p3c/implicit/kuevette/spatialparams.hh +++ b/test/porousmediumflow/3p3c/implicit/kuevette/spatialparams.hh @@ -29,9 +29,9 @@ #include #include -#include -#include -#include + +#include +#include namespace Dumux { @@ -54,15 +54,17 @@ class KuevetteSpatialParams using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedParkerVanGen3P; + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; + using AdsorptionModel = FluidMatrix::ThreePNAPLAdsorption; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; KuevetteSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurveFine_("SpatialParams.Fine") + , pcKrSwCurveCoarse_("SpatialParams.Coarse") + , adsorption_("SpatialParams") { // intrinsic permeabilities fineK_ = 6.28e-12; @@ -71,29 +73,6 @@ public: // porosities finePorosity_ = 0.42; coarsePorosity_ = 0.42; - - // residual saturations - fineMaterialParams_.setSwr(0.12); - fineMaterialParams_.setSnr(0.07); - fineMaterialParams_.setSgr(0.01); - coarseMaterialParams_.setSwr(0.12); - coarseMaterialParams_.setSnr(0.07); - coarseMaterialParams_.setSgr(0.01); - - // parameters for the 3phase van Genuchten law - fineMaterialParams_.setVgAlpha(0.0005); - coarseMaterialParams_.setVgAlpha(0.005); - fineMaterialParams_.setVgn(4.0); - coarseMaterialParams_.setVgn(4.0); - - coarseMaterialParams_.setKrRegardsSnr(true); - fineMaterialParams_.setKrRegardsSnr(true); - - // parameters for adsorption - coarseMaterialParams_.setKdNAPL(0.); - coarseMaterialParams_.setRhoBulk(1500.); - fineMaterialParams_.setKdNAPL(0.); - fineMaterialParams_.setRhoBulk(1500.); } /*! @@ -129,25 +108,17 @@ public: return coarsePorosity_; } - /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). + * \brief Returns the fluid-matrix interaction law at a given location * - * \param element The current element - * \param scv The sub-control volume inside the element. - * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object + * \param globalPos The global coordinates for the given location */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - const auto& globalPos = scv.dofPosition(); if (isFineMaterial_(globalPos)) - return fineMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurveFine_, adsorption_); else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurveCoarse_, adsorption_); } private: @@ -167,8 +138,9 @@ private: Scalar finePorosity_; Scalar coarsePorosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const ThreePhasePcKrSw pcKrSwCurveFine_; + const ThreePhasePcKrSw pcKrSwCurveCoarse_; + const AdsorptionModel adsorption_; }; diff --git a/test/porousmediumflow/3pwateroil/implicit/params.input b/test/porousmediumflow/3pwateroil/implicit/params.input index 3eee8b7db6446264bcb9c9dd9fe7287a061ff66b..e0656f7d1bfe3353e3ddf76721241aebc78cee96 100644 --- a/test/porousmediumflow/3pwateroil/implicit/params.input +++ b/test/porousmediumflow/3pwateroil/implicit/params.input @@ -16,3 +16,11 @@ MaxSteps = 8 SolidDensity = 2650 SolidThermalConductivity = 2.8 SolidHeatCapacity = 850 + +[SpatialParams] +Swr = 0.1 +Snr = 0.09 +Sgr = 0.01 +ParkerVanGenuchtenN = 4 +ParkerVanGenuchtenAlpha = 1 +ParkerVanGenuchtenRegardSnrForKrn = false diff --git a/test/porousmediumflow/3pwateroil/implicit/spatialparams.hh b/test/porousmediumflow/3pwateroil/implicit/spatialparams.hh index 94790c03570605340441641b7034921ddcea5bcf..ba21820bbde58afc9f66718e8f8fa102d3aa47fc 100644 --- a/test/porousmediumflow/3pwateroil/implicit/spatialparams.hh +++ b/test/porousmediumflow/3pwateroil/implicit/spatialparams.hh @@ -28,11 +28,7 @@ #include #include -#include - -#include -#include -#include +#include namespace Dumux { @@ -57,15 +53,15 @@ class SagdSpatialParams using ParentType = FVSpatialParams>; - using EffectiveLaw = RegularizedParkerVanGen3P; + using ThreePhasePcKrSw = FluidMatrix::ParkerVanGenuchten3PDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; SagdSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry), eps_(1e-6) + : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") + , eps_(1e-6) { layerBottom_ = 35.0; @@ -76,23 +72,6 @@ public: // porosities finePorosity_ = 0.10; coarsePorosity_ = 0.1; - - // residual saturations - fineMaterialParams_.setSwr(0.1); - fineMaterialParams_.setSnr(0.09); //Residual of NAPL if there is no water - fineMaterialParams_.setSgr(0.01); - coarseMaterialParams_.setSwr(0.1); - coarseMaterialParams_.setSnr(0.09); - coarseMaterialParams_.setSgr(0.01); - - // parameters for the 3phase van Genuchten law - fineMaterialParams_.setVgn(4.0); - coarseMaterialParams_.setVgn(4.0); - fineMaterialParams_.setVgAlpha(1.); - coarseMaterialParams_.setVgAlpha(1.); - - coarseMaterialParams_.setKrRegardsSnr(false); - fineMaterialParams_.setKrRegardsSnr(false); } /*! @@ -136,41 +115,19 @@ public: } /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). - * - * \param element The current element - * \param scv The sub-control volume inside the element. - * \param elemSol The solution at the dofs connected to the element. - * \return The material parameters object - */ - template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { - return materialLawParamsAtPos(scv.dofPosition()); - } - - /*! - * \brief Returns the parameter object for the capillary-pressure/ - * saturation material law + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The global position + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } - private: - bool isFineMaterial_(const GlobalPosition &pos) const - { - return pos[dimWorld-1] > layerBottom_ - eps_; - }; + + bool isFineMaterial_(const GlobalPosition& pos) const + { return pos[dimWorld-1] > layerBottom_ - eps_; } Scalar layerBottom_; @@ -180,8 +137,7 @@ private: Scalar finePorosity_; Scalar coarsePorosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const ThreePhasePcKrSw pcKrSwCurve_; Scalar eps_; }; diff --git a/test/porousmediumflow/co2/implicit/params.input b/test/porousmediumflow/co2/implicit/params.input index 5569a89c4c65ce70c1d4af0fb1a33d9244a35afd..cac8bfa421daf00a441a0c6e8877cd7bce020ea8 100644 --- a/test/porousmediumflow/co2/implicit/params.input +++ b/test/porousmediumflow/co2/implicit/params.input @@ -22,3 +22,9 @@ InjectionRate = 3e-3 # [kg/sq/s] [Brine] Salinity = 1e-1 + +[SpatialParams] +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2.0 +Swr = 0.05 +Snr = 0.0 diff --git a/test/porousmediumflow/co2/implicit/paramsni.input b/test/porousmediumflow/co2/implicit/paramsni.input index 427e46671b2ef4456f1ce1c96a577131753442b6..ae75655a2eef40778ce678656b3d566a34311f54 100644 --- a/test/porousmediumflow/co2/implicit/paramsni.input +++ b/test/porousmediumflow/co2/implicit/paramsni.input @@ -29,3 +29,9 @@ InjectionTemperature = 305 # [K] SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2.0 +Swr = 0.05 +Snr = 0.0 diff --git a/test/porousmediumflow/co2/implicit/spatialparams.hh b/test/porousmediumflow/co2/implicit/spatialparams.hh index d858b2dab749e3c0f4a81ffb0f727fac3d1f1598..8cfeada7b74d7e503c9ab8fe6fac220dbe03b6ce 100644 --- a/test/porousmediumflow/co2/implicit/spatialparams.hh +++ b/test/porousmediumflow/co2/implicit/spatialparams.hh @@ -29,8 +29,7 @@ #include #include -#include -#include +#include #include @@ -57,18 +56,17 @@ class HeterogeneousSpatialParams using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedBrooksCorey; + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using PermeabilityType = Scalar; HeterogeneousSpatialParams(std::shared_ptr gridGeometry, std::shared_ptr> gridData) - : ParentType(gridGeometry), gridData_(gridData) + : ParentType(gridGeometry) + , gridData_(gridData) + , pcKrSwCurve_("SpatialParams") { - // Set the permeability for the layers barrierTopK_ = 1e-17; //sqm barrierMiddleK_ = 1e-15; //sqm @@ -78,12 +76,6 @@ public: barrierTopPorosity_ = 0.001; barrierMiddlePorosity_ = 0.05; reservoirPorosity_ = 0.2; - - // Same material parameters for every layer - materialParams_.setSwr(0.2); - materialParams_.setSwr(0.05); - materialParams_.setLambda(2.0); - materialParams_.setPe(1e4); } /*! @@ -175,15 +167,12 @@ public: /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos The position of the center of the element - * \return The material parameters object + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const - { - return materialParams_; - } + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const + { return makeFluidMatrixInteraction(pcKrSwCurve_); } /*! * \brief Function for defining which phase is to be considered as the wetting phase. @@ -211,8 +200,8 @@ private: Scalar barrierMiddleK_; Scalar reservoirK_; - MaterialLawParams materialParams_; std::vector paramIdx_; + const PcKrSwCurve pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/params.input b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/params.input index 0ca290b1678da0e719fc2776801d042cb33af522..2fe2cab4408eabe4d0376f239cd31d1f91bd29b2 100644 --- a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/params.input +++ b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/params.input @@ -6,9 +6,13 @@ TEnd = 1e4 # [s] UpperRight = 60 40 Cells = 24 16 +[SpatialParams] +Swr = 0.2 +BrooksCoreyPcEntry = 1e4 +BrooksCoreyLambda = 2.0 + [LinearSolver] ResidualReduction = 1e-12 [Problem] Name = obstacle - diff --git a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/problem.hh b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/problem.hh index b97fd347eb06a3cad45865deed1cd6e3b4389a6b..14a844f864fefdf1737b1461e107eff33d4efde5 100644 --- a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/problem.hh +++ b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/problem.hh @@ -261,20 +261,16 @@ private: // set pressure of the gas phase fs.setPressure(gasPhaseIdx, 1e5); // calulate the capillary pressure - const auto& matParams = - this->spatialParams().materialLawParamsAtPos(globalPos); - PhaseVector pc; - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - + const auto& fm = + this->spatialParams().fluidMatrixInteractionAtPos(globalPos); const int wPhaseIdx = this->spatialParams().template wettingPhaseAtPos(globalPos); - MPAdapter::capillaryPressures(pc, matParams, fs, wPhaseIdx); + const auto pc = fm.capillaryPressures(fs, wPhaseIdx); fs.setPressure(liquidPhaseIdx, fs.pressure(gasPhaseIdx) + pc[liquidPhaseIdx] - pc[gasPhaseIdx]); // make the fluid state consistent with local thermodynamic // equilibrium - using MiscibleMultiPhaseComposition = Dumux::MiscibleMultiPhaseComposition; + using MiscibleMultiPhaseComposition = Dumux::MiscibleMultiPhaseComposition; ParameterCache paramCache; MiscibleMultiPhaseComposition::solve(fs, paramCache); diff --git a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/spatialparams.hh b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/spatialparams.hh index b3697ee9d1fadd515aa16b1bcddddd65f4afae09..2478cbe98faadc35620e32d7706f35ba48068084 100644 --- a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/spatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/spatialparams.hh @@ -27,10 +27,8 @@ #include #include -#include -#include - -#include +#include +#include namespace Dumux { @@ -53,14 +51,16 @@ class MPNCComparisonSpatialParams MPNCComparisonSpatialParams>; using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedBrooksCorey; + + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + using MPAdapter = Dumux::FluidMatrix::MPAdapter; public: using PermeabilityType = Scalar; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - MPNCComparisonSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + MPNCComparisonSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + , pcKrSw_("SpatialParams") { // intrinsic permeabilities coarseK_ = 1e-12; @@ -68,18 +68,6 @@ public: // the porosity porosity_ = 0.3; - - // residual saturations - fineMaterialParams_.setSwr(0.2); - fineMaterialParams_.setSnr(0.0); - coarseMaterialParams_.setSwr(0.2); - coarseMaterialParams_.setSnr(0.0); - - // parameters for the Brooks-Corey law - fineMaterialParams_.setPe(1e4); - coarseMaterialParams_.setPe(1e4); - fineMaterialParams_.setLambda(2.0); - coarseMaterialParams_.setLambda(2.0); } template @@ -95,7 +83,6 @@ public: /*! * \brief Defines the porosity \f$[-]\f$ of the soil - * * \param globalPos The global Position */ Scalar porosityAtPos(const GlobalPosition& globalPos) const @@ -105,23 +92,16 @@ public: /*! * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). - * * \param globalPos The global position of the sub-control volume. - * \return The material parameters object */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(MPAdapter(pcKrSw_)); } /*! * \brief Function for defining which phase is to be considered as the wetting phase. - * * \param globalPos The global position - * \return The wetting phase index */ template int wettingPhaseAtPos(const GlobalPosition& globalPos) const @@ -144,8 +124,7 @@ private: Scalar coarseK_; Scalar fineK_; Scalar porosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + PcKrSwCurve pcKrSw_; static constexpr Scalar eps_ = 1e-6; }; diff --git a/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh b/test/porousmediumflow/mpnc/implicit/kinetic/problem.hh index 92a34e8a354e8acb229c99fb83d84a160bb67e1f..24ed4fb559c1e6df61bc5fceea64b665a69ae0db 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 -#include -#include -#include -#include -#include - namespace Dumux { /*! * \ingroup MPNCTests @@ -389,15 +381,10 @@ private: equilibriumFluidState.setTemperature(phaseIdx, TInitial_ ); } - const auto &materialParams = - this->spatialParams().materialLawParamsAtPos(globalPos); - std::vector capPress(numPhases); // obtain pc according to saturation - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - const int wPhaseIdx = this->spatialParams().template wettingPhaseAtPos(globalPos); - MPAdapter::capillaryPressures(capPress, materialParams, equilibriumFluidState, wPhaseIdx); + const auto& fm = this->spatialParams().fluidMatrixInteractionAtPos(globalPos); + const auto capPress = fm.capillaryPressures(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 644fb6d817e04ae47653d06758b1b7bb4555a0f3..ca8ba66062229e4eb99596cb27a5957d1706b69e 100644 --- a/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/kinetic/spatialparams.hh @@ -28,18 +28,18 @@ #include #include -#include -#include -#include -#include -#include + +#include +#include +#include + #include // material laws for interfacial area -#include -#include -#include -#include +#include +#include +#include +#include namespace Dumux { @@ -61,37 +61,34 @@ class EvaporationAtmosphereSpatialParams using GlobalPosition = typename Element::Geometry::GlobalCoordinate; static constexpr auto dimWorld = GridView::dimensionworld; + + using PcKrSwCurve = FluidMatrix::BrooksCoreyDefault; + using MPAdapter = Dumux::FluidMatrix::MPAdapter; + + using NonwettingSolidInterfacialArea = FluidMatrix::InterfacialArea; + using WettingSolidInterfacialArea = FluidMatrix::InterfacialArea; + using WettingNonwettingInterfacialArea = FluidMatrix::InterfacialArea; public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw>; - //! Convenience aliases of the law parameters - using MaterialLawParams = typename MaterialLaw::Params; - - //! Export the types used for interfacial area calculations - using EffectiveIALawAws = AwnSurfacePolynomial2ndOrder; - using EffectiveIALawAwn = AwnSurfacePcMaxFct; - using EffectiveIALawAns = AwnSurfaceExpSwPcTo3; - using AwnSurface = EffToAbsLawIA; - using AwsSurface = EffToAbsLawIA; - using AnsSurface = EffToAbsLawIA; - - using AwnSurfaceParams = typename AwnSurface::Params; - using AwsSurfaceParams = typename AwsSurface::Params; - using AnsSurfaceParams = typename AnsSurface::Params; EvaporationAtmosphereSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { - heightPM_ = getParam>("Grid.Positions1")[1]; - heightDomain_ = getParam>("Grid.Positions1")[2]; + heightPM_ = getParam>("Grid.Positions1")[1]; + heightDomain_ = getParam>("Grid.Positions1")[2]; - porosityPM_ = getParam("SpatialParams.PorousMedium.porosity"); - intrinsicPermeabilityPM_ = getParam("SpatialParams.PorousMedium.permeability"); + porosityPM_ = getParam("SpatialParams.PorousMedium.porosity"); + intrinsicPermeabilityPM_ = getParam("SpatialParams.PorousMedium.permeability"); - porosityFF_ = getParam("SpatialParams.FreeFlow.porosity"); - intrinsicPermeabilityFF_ = getParam("SpatialParams.FreeFlow.permeability"); + porosityFF_ = getParam("SpatialParams.FreeFlow.porosity"); + intrinsicPermeabilityFF_ = getParam("SpatialParams.FreeFlow.permeability"); aWettingNonwettingA1_ = getParam("SpatialParams.soil.aWettingNonwettingA1"); aWettingNonwettingA2_ = getParam("SpatialParams.soil.aWettingNonwettingA2"); @@ -101,31 +98,26 @@ public: aNonwettingSolidA2_ = getParam("SpatialParams.soil.aNonwettingSolidA2"); aNonwettingSolidA3_ = getParam("SpatialParams.soil.aNonwettingSolidA3"); - BCPd_ = getParam("SpatialParams.soil.BCPd"); - BClambda_ = getParam("SpatialParams.soil.BClambda"); - Swr_ = getParam("SpatialParams.soil.Swr"); - Snr_ = getParam("SpatialParams.soil.Snr"); + BCPd_ = getParam("SpatialParams.soil.BCPd"); + BClambda_ = getParam("SpatialParams.soil.BClambda"); + Swr_ = getParam("SpatialParams.soil.Swr"); + Snr_ = getParam("SpatialParams.soil.Snr"); - characteristicLengthFF_ = getParam("SpatialParams.FreeFlow.meanPoreSize"); - characteristicLengthPM_ = getParam("SpatialParams.PorousMedium.meanPoreSize"); + characteristicLengthFF_ = getParam("SpatialParams.FreeFlow.meanPoreSize"); + characteristicLengthPM_ = getParam("SpatialParams.PorousMedium.meanPoreSize"); factorEnergyTransfer_ = getParam("SpatialParams.PorousMedium.factorEnergyTransfer"); factorMassTransfer_ = getParam("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(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(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 +128,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>; - 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(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(anwParams, effToAbsParamsPM); + + // zero-initialized dummys for free flow: no interface where there is only one phase + aNwFreeFlow_ = std::make_unique(WettingNonwettingInterfacialAreaParams(), effToAbsParamsFF); + aNsFreeFlow_ = std::make_unique(NonwettingSolidInterfacialAreaParams(), effToAbsParamsFF); + + // dummy + using WettingSolidInterfacialAreaParams = typename WettingSolidInterfacialArea::BasicParams; + WettingSolidInterfacialAreaParams awsParams; + aWs_ = std::make_unique(awsParams, effToAbsParamsPM); // use ctor without effToAbs } template @@ -200,81 +195,63 @@ public: DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); } - template - 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 fluid-matrix interaction 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 fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector */ - template - 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 fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector */ - template - 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 fluid-matrix interaction law at a given location */ template - 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 fluid-matrix interaction 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(MPAdapter(*pcKrSwCurveFF_), *aNsFreeFlow_, *aNwFreeFlow_, *aWs_); + else if (inPM_(globalPos)) + return makeFluidMatrixInteraction(MPAdapter(*pcKrSwCurvePM_), *aNs_, *aNw_, *aWs_); + else DUNE_THROW(Dune::InvalidStateException, "You should not be here: x=" << globalPos[0] << " y= "<< globalPos[dimWorld-1]); } /*! @@ -368,11 +345,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 +352,13 @@ private: Scalar factorEnergyTransfer_ ; Scalar factorMassTransfer_ ; Scalar characteristicLengthPM_ ; - MaterialLawParams materialParamsPM_ ; + std::unique_ptr pcKrSwCurvePM_; // Free Flow Domain Scalar porosityFF_ ; Scalar intrinsicPermeabilityFF_ ; Scalar characteristicLengthFF_ ; - MaterialLawParams materialParamsFF_ ; + std::unique_ptr pcKrSwCurveFF_; // interfacial area parameters Scalar aWettingNonwettingA1_ ; @@ -403,6 +375,15 @@ private: Scalar Swr_ ; Scalar Snr_ ; std::vector gridVector_; + + std::unique_ptr aNs_; + std::unique_ptr aNw_; + + std::unique_ptr aNwFreeFlow_; + std::unique_ptr aNsFreeFlow_; + + std::unique_ptr aWs_; // dummy, never used + }; } // end namespace Dumux diff --git a/test/porousmediumflow/mpnc/implicit/obstacle/params.input b/test/porousmediumflow/mpnc/implicit/obstacle/params.input index 49708ce61f0df6cc716cbd11313c1f8463904107..d3db3d37d4a65fdabdb1697ebf9cc2a5236b86a2 100644 --- a/test/porousmediumflow/mpnc/implicit/obstacle/params.input +++ b/test/porousmediumflow/mpnc/implicit/obstacle/params.input @@ -11,3 +11,9 @@ ResidualReduction = 1e-12 [Problem] Name = obstacle + +[SpatialParams] +SmoothedLinearLawPe = 0.0 +SmoothedLinearLawPcMax = 0.0 +SmoothedLinearLawKrLowS = 0.05 +SmoothedLinearLawKrHighS = 0.95 diff --git a/test/porousmediumflow/mpnc/implicit/obstacle/problem.hh b/test/porousmediumflow/mpnc/implicit/obstacle/problem.hh index 35b9d03dab6cd6474b36ad46a009ee75d085173e..905fed1f690d0c21a984ca7b4a5687c137341cf5 100644 --- a/test/porousmediumflow/mpnc/implicit/obstacle/problem.hh +++ b/test/porousmediumflow/mpnc/implicit/obstacle/problem.hh @@ -329,14 +329,10 @@ private: // set the other saturation fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx)); - // calulate the capillary pressure - const auto& matParams = this->spatialParams().materialLawParamsAtPos(globalPos); - PhaseVector pc; - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - + // calculate the capillary pressure + const auto fluidMatrixInteraction = this->spatialParams().fluidMatrixInteractionAtPos(globalPos); const int wPhaseIdx = this->spatialParams().template wettingPhaseAtPos(globalPos); - MPAdapter::capillaryPressures(pc, matParams, fs, wPhaseIdx); + const auto pc = fluidMatrixInteraction.capillaryPressures(fs, wPhaseIdx); fs.setPressure(otherPhaseIdx, fs.pressure(refPhaseIdx) + (pc[otherPhaseIdx] - pc[refPhaseIdx])); diff --git a/test/porousmediumflow/mpnc/implicit/obstacle/spatialparams.hh b/test/porousmediumflow/mpnc/implicit/obstacle/spatialparams.hh index 1272af0a7e6b339d5a1a4c158f0f627b52e7596f..5b60e7488a70c4c66a292578d81aa3df8a947ef3 100644 --- a/test/porousmediumflow/mpnc/implicit/obstacle/spatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/obstacle/spatialparams.hh @@ -27,8 +27,9 @@ #include #include -#include -#include +#include +#include +#include namespace Dumux { @@ -51,37 +52,22 @@ class ObstacleSpatialParams enum {dimWorld=GridView::dimensionworld}; using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = RegularizedLinearMaterial; + + using PcKrSwCurve = FluidMatrix::SmoothedLinearLaw; + using MPAdapter = Dumux::FluidMatrix::MPAdapter; public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - ObstacleSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) - { - // intrinsic permeabilities - coarseK_ = 1e-12; - fineK_ = 1e-15; - - // the porosity - porosity_ = 0.3; - - // residual saturations - fineMaterialParams_.setSwr(0.0); - fineMaterialParams_.setSnr(0.0); - coarseMaterialParams_.setSwr(0.0); - coarseMaterialParams_.setSnr(0.0); - - // parameters for the linear law, i.e. minimum and maximum - // pressures - fineMaterialParams_.setEntryPc(0.0); - coarseMaterialParams_.setEntryPc(0.0); - fineMaterialParams_.setMaxPc(0.0); - coarseMaterialParams_.setMaxPc(0.0); - } + + ObstacleSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") // initialize the material law + , coarseK_(1e-12) // intrinsic permeability + , fineK_(1e-15) // intrinsic permeability + , porosity_(0.3) + {} template PermeabilityType permeability(const Element& element, @@ -103,17 +89,11 @@ public: { return porosity_; } /*! - * \brief Function for defining the parameters needed by constitutive relationships (kr-sw, pc-sw, etc.). - * - * \param globalPos The global position of the sub-control volume. - * \return The material parameters object + * \brief Returns the fluid-matrix interaction law at a given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const { - if (isFineMaterial_(globalPos)) - return fineMaterialParams_; - else - return coarseMaterialParams_; + return makeFluidMatrixInteraction(MPAdapter(pcKrSwCurve_)); } /*! @@ -140,11 +120,10 @@ private: 0 - eps_ <= pos[1] && pos[1] <= 35 + eps_; } - Scalar coarseK_; - Scalar fineK_; - Scalar porosity_; - MaterialLawParams fineMaterialParams_; - MaterialLawParams coarseMaterialParams_; + const PcKrSwCurve pcKrSwCurve_; + const Scalar coarseK_; + const Scalar fineK_; + const Scalar porosity_; static constexpr Scalar eps_ = 1e-6; }; diff --git a/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/problem.hh b/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/problem.hh index de62ede286634ebebfa5fb76dd99d2471a8dbc5c..48ffdd6503a6377799d5d636591e3a80765dbad1 100644 --- a/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/problem.hh +++ b/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/problem.hh @@ -197,7 +197,6 @@ class CombustionProblemOneComponent: public PorousMediumFlowProblem using Indices = typename ModelTraits::Indices; enum {dimWorld = GridView::dimensionworld}; - enum {numPhases = ModelTraits::numFluidPhases()}; enum {numComponents = ModelTraits::numFluidComponents()}; enum {s0Idx = Indices::s0Idx}; enum {p0Idx = Indices::p0Idx}; @@ -211,6 +210,8 @@ class CombustionProblemOneComponent: public PorousMediumFlowProblem enum {wCompIdx = FluidSystem::H2OIdx}; enum {nCompIdx = FluidSystem::N2Idx}; + static constexpr auto numPhases = ModelTraits::numFluidPhases(); + // formulations static constexpr auto pressureFormulation = ModelTraits::pressureFormulation(); static constexpr auto mostWettingFirst = MpNcPressureFormulation::mostWettingFirst; @@ -448,16 +449,11 @@ private: ////////////////////////////////////// priVars[energyEq0Idx] = thisTemperature; priVars[energyEqSolidIdx] = thisTemperature; - std::vector capPress(numPhases); //obtain pc according to saturation - const auto &materialParams = - this->spatialParams().materialLawParamsAtPos(globalPos); - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - using MPAdapter = MPAdapter; - const int wettingPhaseIdx = this->spatialParams().template wettingPhaseAtPos(globalPos); - MPAdapter::capillaryPressures(capPress, materialParams, fluidState, wettingPhaseIdx); + const auto& fm = this->spatialParams().fluidMatrixInteractionAtPos(globalPos); + const auto capPress = fm.capillaryPressures(fluidState, wettingPhaseIdx); Scalar p[numPhases]; diff --git a/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/spatialparams.hh b/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/spatialparams.hh index 32ef6c727d68805c24509e517bfb686d7f1c6a3f..f273a4e84fa35c445bed63342c03e2b034358822 100644 --- a/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/spatialparams.hh +++ b/test/porousmediumflow/mpnc/implicit/thermalnonequilibrium/spatialparams.hh @@ -30,9 +30,8 @@ #include #include -#include #include -#include +#include #include #include #include @@ -57,16 +56,15 @@ class CombustionSpatialParams enum {dimWorld = GridView::dimensionworld}; using GlobalPosition = typename SubControlVolume::GlobalPosition; - using EffectiveLaw = HeatPipeLaw; + using PcKrSwCurve = FluidMatrix::HeatPipeLaw; + using MPAdapter = Dumux::FluidMatrix::MPAdapter; public: //! Export the type used for the permeability using PermeabilityType = Scalar; - //! Export the material law type used - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; using FluidSolidInterfacialAreaFormulation = FluidSolidInterfacialAreaShiWang; + CombustionSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) { // this is the parameter value from file part @@ -75,9 +73,6 @@ public: porosityOutFlow_ = getParam("SpatialParams.Outflow.porosityOutFlow"); interfacialTension_ = getParam("Constants.interfacialTension"); - Swr_ = getParam("SpatialParams.soil.Swr"); - Snr_ = getParam("SpatialParams.soil.Snr"); - characteristicLength_ =getParam("SpatialParams.PorousMedium.meanPoreSize"); using std::pow; @@ -86,13 +81,16 @@ public: factorEnergyTransfer_ = getParam("SpatialParams.PorousMedium.factorEnergyTransfer"); lengthPM_ = getParam("Grid.lengthPM"); - // residual saturations - materialParams_.setSwr(Swr_) ; - materialParams_.setSnr(Snr_) ; - using std::sqrt; - materialParams_.setP0(sqrt(porosity_/intrinsicPermeability_)); - materialParams_.setGamma(interfacialTension_); // interfacial tension of water-air at 100°C + const Scalar p0 = sqrt(porosity_/intrinsicPermeability_); + const Scalar gamma = interfacialTension_; // interfacial tension of water-air at 100°C + typename PcKrSwCurve::Params params(p0, gamma); + + typename PcKrSwCurve::EffToAbsParams effToAbsParams; + effToAbsParams.setSwr(getParam("SpatialParams.soil.Swr")); + effToAbsParams.setSnr(getParam("SpatialParams.soil.Snr")); + + pcKrSwCurve_ = std::make_unique(params, effToAbsParams); } template @@ -169,13 +167,6 @@ public: return FluidSystem::phase0Idx; } - /*! - * \brief Returns a reference to the material parameters of the material law. - * \param globalPos The position in global coordinates. - */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition & globalPos) const - { return materialParams_ ; } - /*! * \brief Returns the characteristic length for the mass transfer. * \param globalPos The position in global coordinates. @@ -197,6 +188,15 @@ public: //! Returns the interfacial tension Scalar interfacialTension() const { return interfacialTension_ ; } + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos A global coordinate vector + */ + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const + { + return makeFluidMatrixInteraction(MPAdapter(*pcKrSwCurve_)); + } + private: static constexpr Scalar eps_ = 1e-6; @@ -205,7 +205,6 @@ private: Scalar porosity_ ; Scalar factorEnergyTransfer_ ; Scalar characteristicLength_ ; - MaterialLawParams materialParams_ ; // Outflow Domain Scalar intrinsicPermeabilityOutFlow_ ; @@ -214,13 +213,10 @@ private: // solid parameters Scalar interfacialTension_ ; - - // capillary pressures parameters - Scalar Swr_ ; - Scalar Snr_ ; - // grid Scalar lengthPM_ ; + + std::unique_ptr pcKrSwCurve_; }; } diff --git a/test/porousmediumflow/richards/implicit/analytical/spatialparams.hh b/test/porousmediumflow/richards/implicit/analytical/spatialparams.hh index 19ef43964d4fa8e541f7894ae0beff5c808c216d..62c184ac94141e3bea8bfa11004b141450c59055 100644 --- a/test/porousmediumflow/richards/implicit/analytical/spatialparams.hh +++ b/test/porousmediumflow/richards/implicit/analytical/spatialparams.hh @@ -27,7 +27,6 @@ #include #include -#include #include @@ -50,22 +49,20 @@ class RichardsAnalyticalSpatialParams using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; -public: + using PcKrSwCurve = FluidMatrix::LinearMaterialDefault; - using MaterialLaw = EffToAbsLaw>; - using MaterialLawParams = typename MaterialLaw::Params; +public: // export permeability type using PermeabilityType = Scalar; RichardsAnalyticalSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) + : ParentType(gridGeometry) { permeability_ = 5e-12; - materialParams_.setSwr(0.0); - materialParams_.setSnr(0.0); - materialParams_.setEntryPc(0); - materialParams_.setMaxPc(1e10); + + typename PcKrSwCurve::BasicParams params(0/*pcEntry*/, 1e10/*pcMax*/); + pcKrSwCurve_ = std::make_unique(params); } /*! @@ -85,17 +82,17 @@ public: { return 0.4; } /*! - * \brief Returns the parameters for the material law at a given location + * \brief Returns the fluid-matrix interaction law at a given location * \param globalPos A global coordinate vector */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition &globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition &globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(*pcKrSwCurve_); } private: Scalar permeability_; - MaterialLawParams materialParams_; + std::unique_ptr pcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/richards/implicit/lens/params.input b/test/porousmediumflow/richards/implicit/lens/params.input index 72e9e5fedd8e3ab958f3ea220a40e769b8efd0b6..b39661fa2c79450ca371f4382880b0ea10f178c5 100644 --- a/test/porousmediumflow/richards/implicit/lens/params.input +++ b/test/porousmediumflow/richards/implicit/lens/params.input @@ -21,3 +21,15 @@ Type = bicgstabsolver Type = amg AmgMaxLevel = 2 AmgAccumulationMode = atOnce + +[SpatialParams.Lens] +Swr = 0.18 +Snr = 0.0 +VanGenuchtenAlpha = 0.00045 +VanGenuchtenN = 7.3 + +[SpatialParams.OuterDomain] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 diff --git a/test/porousmediumflow/richards/implicit/lens/problem.hh b/test/porousmediumflow/richards/implicit/lens/problem.hh index 69f408cfe33203df79cd55c44b13e8551fbde7eb..d1a3e3d9eccbf8a0a3f0e3fa622f50a4b13d4af5 100644 --- a/test/porousmediumflow/richards/implicit/lens/problem.hh +++ b/test/porousmediumflow/richards/implicit/lens/problem.hh @@ -247,8 +247,7 @@ private: { PrimaryVariables values(0.0); const Scalar sw = 0.0; - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - const Scalar pc = MaterialLaw::pc(this->spatialParams().materialLawParamsAtPos(globalPos), sw); + const Scalar pc = this->spatialParams().fluidMatrixInteractionAtPos(globalPos).pc(sw); values[pressureIdx] = nonwettingReferencePressure() - pc; values.setState(bothPhases); return values; diff --git a/test/porousmediumflow/richards/implicit/lens/spatialparams.hh b/test/porousmediumflow/richards/implicit/lens/spatialparams.hh index 100ecb90da7aacc9e53d3a7e7919a3d1e1c34e25..015d8a31e7b531ca688b246907ec1cf42bd0ed30 100644 --- a/test/porousmediumflow/richards/implicit/lens/spatialparams.hh +++ b/test/porousmediumflow/richards/implicit/lens/spatialparams.hh @@ -26,8 +26,7 @@ #define DUMUX_RICHARDS_LENS_SPATIAL_PARAMETERS_HH #include -#include -#include +#include #include @@ -51,32 +50,19 @@ class RichardsLensSpatialParams enum { dimWorld = GridView::dimensionworld }; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; + public: - using MaterialLaw = EffToAbsLaw>; - using MaterialLawParams = typename MaterialLaw::Params; // export permeability type using PermeabilityType = Scalar; RichardsLensSpatialParams(std::shared_ptr gridGeometry) : ParentType(gridGeometry) + , pcKrSwCurveLens_("SpatialParams.Lens") + , pcKrSwCurveOuterDomain_("SpatialParams.OuterDomain") { - lensLowerLeft_ = {1.0, 2.0}; lensUpperRight_ = {4.0, 3.0}; - - // residual saturations - lensMaterialParams_.setSwr(0.18); - lensMaterialParams_.setSnr(0.0); - outerMaterialParams_.setSwr(0.05); - outerMaterialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - lensMaterialParams_.setVgAlpha(0.00045); - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - outerMaterialParams_.setVgn(4.7); - lensK_ = 1e-12; outerK_ = 5e-12; } @@ -102,7 +88,7 @@ public: { return 0.4; } /*! - * \brief Returns the parameters for the material law for the sub-control volume + * \brief Returns the fluid-matrix interaction law for the sub-control volume * * This method is not actually required by the Richards model, but provided * for the convenience of the RichardsLensProblem @@ -112,28 +98,23 @@ public: * \param elemSol The current element solution */ template - const MaterialLawParams& materialLawParams(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + auto fluidMatrixInteraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const { const auto& globalPos = scv.dofPosition(); - - return materialLawParamsAtPos(globalPos); + return fluidMatrixInteractionAtPos(globalPos); } /*! - * \brief Returns the parameters for the material law at a given location - * - * This method is not actually required by the Richards model, but provided - * for the convenience of the RichardsLensProblem - * + * \brief Returns the fluid-matrix interaction law at a given location * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { if (isInLens_(globalPos)) - return lensMaterialParams_; - return outerMaterialParams_; + return makeFluidMatrixInteraction(pcKrSwCurveLens_); + return makeFluidMatrixInteraction(pcKrSwCurveOuterDomain_); } private: @@ -153,8 +134,8 @@ private: Scalar lensK_; Scalar outerK_; - MaterialLawParams lensMaterialParams_; - MaterialLawParams outerMaterialParams_; + const PcKrSwCurve pcKrSwCurveLens_; + const PcKrSwCurve pcKrSwCurveOuterDomain_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/richards/implicit/nonisothermal/conduction/params.input b/test/porousmediumflow/richards/implicit/nonisothermal/conduction/params.input index 0304a8a78002529433cb5d57f3fd27029fe03a02..03be824f3d4e5aca0fac79c1d6da022cd2431b91 100644 --- a/test/porousmediumflow/richards/implicit/nonisothermal/conduction/params.input +++ b/test/porousmediumflow/richards/implicit/nonisothermal/conduction/params.input @@ -19,3 +19,9 @@ EnableChop = false # chop for better convergence SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 diff --git a/test/porousmediumflow/richards/implicit/nonisothermal/convection/params.input b/test/porousmediumflow/richards/implicit/nonisothermal/convection/params.input index a286867c03461c87f34f1215ef041c7520bd563f..e0841d4f4ada4b42f0d7d4096884ec86ba325ffa 100644 --- a/test/porousmediumflow/richards/implicit/nonisothermal/convection/params.input +++ b/test/porousmediumflow/richards/implicit/nonisothermal/convection/params.input @@ -20,3 +20,9 @@ EnableChop = false # chop for better convergence SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 diff --git a/test/porousmediumflow/richards/implicit/nonisothermal/evaporation/params.input b/test/porousmediumflow/richards/implicit/nonisothermal/evaporation/params.input index 1f6701d4efafbab233c7a9037cd8dbe981e16e0e..49e1c6baa09b0faff04dae607a3cd913e920cdaf 100644 --- a/test/porousmediumflow/richards/implicit/nonisothermal/evaporation/params.input +++ b/test/porousmediumflow/richards/implicit/nonisothermal/evaporation/params.input @@ -20,3 +20,9 @@ EnableChop = false # chop for better convergence SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 + +[SpatialParams] +Swr = 0.05 +Snr = 0.0 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 diff --git a/test/porousmediumflow/richards/implicit/nonisothermal/spatialparams.hh b/test/porousmediumflow/richards/implicit/nonisothermal/spatialparams.hh index 6b6da0eb446682db076772b5257a92724424deb7..31ff4d037735b98d519a4c019dc13debd86c09bc 100644 --- a/test/porousmediumflow/richards/implicit/nonisothermal/spatialparams.hh +++ b/test/porousmediumflow/richards/implicit/nonisothermal/spatialparams.hh @@ -26,9 +26,7 @@ #define DUMUX_RICHARDSNI_SPATIAL_PARAMS_HH #include -#include -#include -#include +#include #include namespace Dumux { @@ -47,33 +45,20 @@ class RichardsNISpatialParams enum { dimWorld=GridView::dimensionworld }; - using EffectiveLaw = RegularizedVanGenuchten; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using PcKrSwCurve = FluidMatrix::VanGenuchtenDefault; + public: // export permeability type using PermeabilityType = Scalar; - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; - RichardsNISpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) + : ParentType(gridGeometry) + , pcKrSwCurve_("SpatialParams") { permeability_ = 1e-10; porosity_ = 0.4; - - - // residual saturations - materialParams_.setSwr(0.05); - materialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - - materialParams_.setVgAlpha(0.0037); - materialParams_.setVgn(4.7); } /*! @@ -96,20 +81,18 @@ public: return porosity_; } - /*! - * \brief Returns the parameter object for the Brooks-Corey material law - * which depends on the position - * - * \param globalPos The global position where we evaluate + /*! + * \brief Returns the fluid-matrix interaction law at a given location + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition &globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { - return materialParams_; + return makeFluidMatrixInteraction(pcKrSwCurve_); } private: - MaterialLawParams materialParams_; + const PcKrSwCurve pcKrSwCurve_; Scalar permeability_; Scalar porosity_; }; diff --git a/test/porousmediumflow/richardsnc/implicit/params.input b/test/porousmediumflow/richardsnc/implicit/params.input index ebded49d422eea457984403251a8a0b670611fc2..366a917b75659b249f593e1a1f23bf0cc84ee700 100644 --- a/test/porousmediumflow/richardsnc/implicit/params.input +++ b/test/porousmediumflow/richardsnc/implicit/params.input @@ -25,3 +25,13 @@ AddVelocity = true [Newton] EnableChop = false + +[SpatialParams] +Lens.Swr = 0.18 +Lens.Snr = 0.0 +Lens.VanGenuchtenAlpha = 0.00045 +Lens.VanGenuchtenN = 7.3 +OuterDomain.Swr = 0.05 +OuterDomain.Snr = 0.0 +OuterDomain.VanGenuchtenAlpha = 0.0037 +OuterDomain.VanGenuchtenN = 4.7 diff --git a/test/porousmediumflow/richardsnc/implicit/problem.hh b/test/porousmediumflow/richardsnc/implicit/problem.hh index 4986d23678073cb955f94edbc8f7b910898ee903..2f2a70d73f808747643d83e11ad7abd2316c6517 100644 --- a/test/porousmediumflow/richardsnc/implicit/problem.hh +++ b/test/porousmediumflow/richardsnc/implicit/problem.hh @@ -144,9 +144,8 @@ public: pumpRate_ = getParam("Problem.PumpRate"); // in kg/s // for initial conditions - const Scalar sw = 0.4; // start with 80% saturation on top - using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; - pcTop_ = MaterialLaw::pc(this->spatialParams().materialLawParamsAtPos(this->gridGeometry().bBoxMax()), sw); + const Scalar sw = 0.4; // start with 40% saturation on top + pcTop_ = this->spatialParams().fluidMatrixInteractionAtPos(this->gridGeometry().bBoxMax()).pc(sw); // for post time step mass balance accumulatedSource_ = 0.0; diff --git a/test/porousmediumflow/richardsnc/implicit/spatialparams.hh b/test/porousmediumflow/richardsnc/implicit/spatialparams.hh index a1ce847777776fa19b0e9e6f90f07e847c30f354..5d755c32011de2e9ab466d58b0c22dc44ffc9fd1 100644 --- a/test/porousmediumflow/richardsnc/implicit/spatialparams.hh +++ b/test/porousmediumflow/richardsnc/implicit/spatialparams.hh @@ -27,13 +27,9 @@ #include #include -#include #include -#include -#include - namespace Dumux { /*! @@ -54,37 +50,20 @@ class RichardsWellTracerSpatialParams using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using EffectiveLaw = VanGenuchten; + using PcKrSwCurve = FluidMatrix::VanGenuchtenNoReg; public: - using MaterialLaw = EffToAbsLaw; - using MaterialLawParams = typename MaterialLaw::Params; // export permeability type using PermeabilityType = Scalar; RichardsWellTracerSpatialParams(std::shared_ptr gridGeometry) - : ParentType(gridGeometry) + : ParentType(gridGeometry) + , lensPcKrSwCurve_("SpatialParams.Lens") + , outerPcKrSwCurve_("SpatialParams.OuterDomain") { - lensLowerLeft_ = getParam("Problem.LensLowerLeft"); lensUpperRight_ = getParam("Problem.LensUpperRight"); - // residual saturations - lensMaterialParams_.setSwr(0.18); - lensMaterialParams_.setSnr(0.0); - outerMaterialParams_.setSwr(0.05); - outerMaterialParams_.setSnr(0.0); - - // parameters for the Van Genuchten law - // alpha and n - lensMaterialParams_.setVgAlpha(0.00045); - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - outerMaterialParams_.setVgn(4.7); - - lensMaterialParams_.setVgn(7.3); - outerMaterialParams_.setVgAlpha(0.0037); - lensK_ = 1e-14; outerK_ = 5e-12; } @@ -114,15 +93,16 @@ public: } /*! - * \brief Returns the parameters for the material law at a given location + * \brief Returns the fluid-matrix interaction law at a given location * - * \param globalPos A global coordinate vector + * \param globalPos The global coordinates for the given location */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition &globalPos) const + auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const { if (isInLens_(globalPos)) - return lensMaterialParams_; - return outerMaterialParams_; + return makeFluidMatrixInteraction(lensPcKrSwCurve_); + else + return makeFluidMatrixInteraction(outerPcKrSwCurve_); } private: @@ -142,8 +122,9 @@ private: Scalar lensK_; Scalar outerK_; - MaterialLawParams lensMaterialParams_; - MaterialLawParams outerMaterialParams_; + + const PcKrSwCurve lensPcKrSwCurve_; + const PcKrSwCurve outerPcKrSwCurve_; }; } // end namespace Dumux diff --git a/test/porousmediumflow/tracer/2ptracer/main.cc b/test/porousmediumflow/tracer/2ptracer/main.cc index ddb9ec50e55540bba5ef22f18ce5e15ad820374f..cb08ccc40a2d7d5e9c1f0e7d062c47c62ab9bf3c 100644 --- a/test/porousmediumflow/tracer/2ptracer/main.cc +++ b/test/porousmediumflow/tracer/2ptracer/main.cc @@ -107,8 +107,8 @@ int main(int argc, char** argv) auto pOld = p; // maybe update the interface parameters - if (ENABLEINTERFACESOLVER) - twoPProblem->spatialParams().updateMaterialInterfaceParams(p); + if constexpr (ENABLEINTERFACESOLVER) + twoPProblem->spatialParams().updateMaterialInterfaces(p); // the grid variables using TwoPGridVariables = GetPropType; diff --git a/test/porousmediumflow/tracer/2ptracer/params.input b/test/porousmediumflow/tracer/2ptracer/params.input index bf62610a9536349f1ad169def61ea2f9404d4057..ea81574f6be7d37dc316c90b8e0c601996a01d1e 100644 --- a/test/porousmediumflow/tracer/2ptracer/params.input +++ b/test/porousmediumflow/tracer/2ptracer/params.input @@ -10,8 +10,18 @@ Cells = 48 32 [SpatialParams] LensLowerLeft = 1.0 2.0 # [m] coordinates of the lower left lens corner LensUpperRight = 4.0 3.0 # [m] coordinates of the upper right lens corner -outerK = 1e-09 # [m^2] -lensK = 1e-12 # [m^2] + +[SpatialParams.Lens] +Swr = 0.18 +VanGenuchtenAlpha = 0.00045 +VanGenuchtenN = 7.3 +Permeability = 1e-12 # [m^2] + +[SpatialParams.Outer] +Swr = 0.05 +VanGenuchtenAlpha = 0.0037 +VanGenuchtenN = 4.7 +Permeability = 1e-09 # [m^2] [Problem] Name = test_2ptracer_lens_tpfa