14#ifndef DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH 
   15#define DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH 
   21#include <dune/common/math.hh> 
   43    template<
class SpatialParams, 
class Element, 
class SubControlVolume, 
class ElemSol>
 
   45                       const Element& element,
 
   46                       const SubControlVolume& scv,
 
   47                       const ElemSol& elemSol)
 
   48    : shape_(spatialParams.gridGeometry().poreGeometry()[scv.dofIndex()])
 
   50    , surfaceTension_(spatialParams.
surfaceTension(element, scv, elemSol))
 
 
   53    template<
class SpatialParams, 
class Element, 
class SubControlVolume, 
class ElemSol>
 
   55                const Element& element,
 
   56                const SubControlVolume& scv,
 
   57                const ElemSol& elemSol)
 
   60        shape_ = gridGeometry.poreGeometry()[scv.dofIndex()];
 
   62        surfaceTension_ = spatialParams.surfaceTension(element, scv, elemSol);
 
 
   73        return Dune::FloatCmp::eq(radius_, p.radius_, 1e-6)
 
   74               && Dune::FloatCmp::eq(surfaceTension_, p.surfaceTension_, 1e-6)
 
   75               && shape_ == p.shape_;
 
 
   81    Scalar surfaceTension_;
 
 
   92template<Pore::Shape shape>
 
   95    template<
class Scalar>
 
   98    template<
class SpatialParams, 
class Element, 
class SubControlVolume, 
class ElemSol>
 
  100                           const Element& element,
 
  101                           const SubControlVolume& scv,
 
  102                           const ElemSol& elemSol)
 
  104        using Scalar = std::decay_t<
decltype(spatialParams.
poreInscribedRadius(element, scv, elemSol))>;
 
 
  114    template<
class Scalar>
 
  117        assert(isPlatonicBody_(params.
poreShape()));
 
  120        sw = clamp(
sw, 0.0, 1.0); 
 
  127        return 2.0*sigma / (poreRadius*(1.0 - exp(-expFactor_<Scalar>()*
sw)));
 
 
  136    template<
class Scalar>
 
  139        assert(isPlatonicBody_(params.
poreShape()));
 
  148        return -1.0/expFactor_<Scalar>()* log(1.0 - 2.0*sigma/(poreRadius*
pc));
 
 
  158    template<
class Scalar>
 
  161        assert(isPlatonicBody_(params.
poreShape()));
 
  164        sw = clamp(
sw, 0.0, 1.0); 
 
  169        const Scalar e = exp(expFactor_<Scalar>()*
sw);
 
  170        return -(2.0*expFactor_<Scalar>()*sigma*e) / (poreRadius*(1.0-e)*(1.0-e));
 
 
  180    template<
class Scalar>
 
  183        assert(isPlatonicBody_(params.
poreShape()));
 
  190        return sigma / (expFactor_<Scalar>()*sigma*
pc - 0.5*expFactor_<Scalar>()*poreRadius*
pc*
pc);
 
 
  195    template<
class Scalar>
 
  196    static constexpr Scalar expFactor_()
 
  215    static constexpr bool isPlatonicBody_(
Pore::Shape s)
 
 
  230template<
class Scalar, 
class BaseLaw>
 
  278        { 
return pcHighSw_; }
 
 
  284        { highSwRegularizationMethod_ = method; }
 
 
  290        { 
return highSwRegularizationMethod_; }
 
 
 
  299    template<
class MaterialLaw>
 
  302        initPcParameters_(m, p, paramGroup);
 
 
  314            return pcLowSwPcValue_() + pcDerivativeLowSw_() * (
sw - pcLowSw_);
 
  322                return pcHighSwPcValue_() * pow(((1.0-
sw)/(1.0-pcHighSw_)), 1.0/3.0);
 
  326                const Scalar slope = -pcHighSwPcValue_() / (1.0 - pcHighSw_);
 
  327                return pcHighSwPcValue_() + (
sw - pcHighSw_) * slope;
 
  331                return pcSpline_().eval(
sw);
 
  334                DUNE_THROW(Dune::NotImplemented, 
"Regularization not method not implemented");
 
  337            return pcDerivativeHighSwEnd_()*(
sw - 1.0);
 
 
  347            if (pcHighSw_ >= 1.0)
 
  350                return pc/pcDerivativeHighSwEnd_() + 1.0;
 
  354        if (
pc > pcLowSwPcValue_())
 
  355            return (
pc - pcLowSwPcValue_())/pcDerivativeLowSw_() + pcLowSw_;
 
  358        else if (
pc <= pcHighSwPcValue_())
 
  364                return power(
pc/pcHighSwPcValue_(), 3) * (pcHighSw_ - 1.0) + 1.0;
 
  368                return pc/pcDerivativeHighSwEnd_() + 1.0;
 
  372                return pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0, 
pc);
 
 
  385            return pcDerivativeLowSw_();
 
  388            return pcDerivativeHighSwEnd_();
 
  390        else if (
sw > pcHighSw_)
 
  395                return pcHighSwPcValue_()/3.0 * 1.0 /((pcHighSw_-1.0) * pow((
sw-1.0)/(pcHighSw_-1.0), 2.0/3.0));
 
  399                return pcDerivativeHighSwEnd_();
 
  402                return pcSpline_().evalDerivative(
sw);
 
 
  416            if (pcHighSw_ >= 1.0)
 
  419                return 1.0/pcDerivativeHighSwEnd_();
 
  423        else if (
pc <= pcHighSwPcValue_())
 
  428                return (3.0*pcHighSw_ - 3.0) * power(
pc, 2) / power(pcHighSwPcValue_(), 3);
 
  432                return 1.0/pcDerivativeHighSwEnd_();
 
  435                return 1.0/pcSpline_().evalDerivative(pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0, 
pc));
 
  438        else if (
pc >= pcLowSwPcValue_())
 
  439            return 1.0/pcDerivativeLowSw_();
 
 
  445    template<
class SpatialParams, 
class Element, 
class SubControlVolume, 
class ElemSol>
 
  447                      const Element& element,
 
  448                      const SubControlVolume& scv,
 
  449                      const ElemSol& elemSol)
 
 
  454    template<
class MaterialLaw>
 
  455    void initPcParameters_(
const MaterialLaw* m, 
const Params<Scalar>& params, 
const std::string& paramGroup)
 
  457        highSwRegularizationMethod_ = params.highSwRegularizationMethod();
 
  460        static const bool hasMethod = 
hasParamInGroup(paramGroup, 
"HighSwRegularizationMethod");
 
  467                if (input == 
"Linear")
 
  469                else if (input == 
"Spline")
 
  471                else if (input == 
"PowerLaw")
 
  474                    DUNE_THROW(Dune::InvalidStateException, input << 
" is not a valid regularization method");
 
  477            highSwRegularizationMethod_ = inputmethod;
 
  481        highSwSplineZeroSlope_ = splineZeroSlope;
 
  484        [[maybe_unused]] 
static const bool printName = [&]
 
  494                DUNE_THROW(Dune::NotImplemented, 
"Regularization not method not implemented");
 
  496            std::cout << 
"\n*****\nUsing " << name << 
" as regularization method for high Sw\n*****" << std::endl;
 
  502        pcLowSw_ = !isnan(pcLowSwInput) ? pcLowSwInput : params.pcLowSw();
 
  504        static const auto pcHighSwInput = 
getParamFromGroup<Scalar>(paramGroup, 
"RegularizationHighSw", std::numeric_limits<Scalar>::quiet_NaN());
 
  505        pcHighSw_ = !isnan(pcHighSwInput) ? pcHighSwInput : params.pcHighSw();
 
  507        baseLawParamsPtr_ = &m->basicParams();
 
  509        static const auto highSwFixedSlopeInput = 
getParamFromGroup<Scalar>(paramGroup, 
"RegularizationHighSwFixedSlope", std::numeric_limits<Scalar>::quiet_NaN());
 
  510        highSwFixedSlope_ = highSwFixedSlopeInput;
 
  519    Scalar pcLowSwPcValue_()
 const 
  522        if (!optionalPcLowSwPcValue_)
 
  523            optionalPcLowSwPcValue_ = BaseLaw::pc(pcLowSw_, *baseLawParamsPtr_);
 
  524        return optionalPcLowSwPcValue_.value();
 
  528    Scalar pcDerivativeLowSw_()
 const 
  530        if (!optionalPcDerivativeLowSw_)
 
  531            optionalPcDerivativeLowSw_ = BaseLaw::dpc_dsw(pcLowSw_, *baseLawParamsPtr_);
 
  532        return optionalPcDerivativeLowSw_.value();
 
  536    Scalar pcHighSwPcValue_()
 const 
  538        if (!optionalPcHighSwPcValue_)
 
  539            optionalPcHighSwPcValue_ = BaseLaw::pc(pcHighSw_, *baseLawParamsPtr_);
 
  540        return optionalPcHighSwPcValue_.value();
 
  544    Scalar pcDerivativeHighSwEnd_()
 const 
  547        if (!isnan(highSwFixedSlope_))
 
  548            return highSwFixedSlope_;
 
  550            return (0.0 - pcHighSwPcValue_()) / (1.0 - pcHighSw_);
 
  553    const Spline<Scalar>& pcSpline_()
 const 
  555        if (!optionalPcSpline_)
 
  557            const auto slopes = highSwSplineZeroSlope_ ? std::array{0.0, 0.0}
 
  558                                                       : std::array{BaseLaw::dpc_dsw(pcHighSw_, *baseLawParamsPtr_), pcDerivativeHighSwEnd_()};
 
  560            optionalPcSpline_ = Spline<Scalar>(pcHighSw_, 1.0, 
 
  561                                               pcHighSwPcValue_(), 0, 
 
  562                                               slopes[0], slopes[1]); 
 
  564        return optionalPcSpline_.value();
 
  567    Scalar pcLowSw_, pcHighSw_;
 
  568    mutable OptionalScalar<Scalar> optionalPcLowSwPcValue_, optionalPcDerivativeLowSw_;
 
  569    mutable OptionalScalar<Scalar> optionalPcHighSwPcValue_;
 
  571    const BaseLawParams* baseLawParamsPtr_;
 
  572    mutable std::optional<Spline<Scalar>> optionalPcSpline_;
 
  573    bool highSwSplineZeroSlope_;
 
  574    Scalar highSwFixedSlope_;
 
 
  581template<Pore::Shape shape, 
typename Scalar = 
double>
 
  591template<Pore::Shape shape, 
typename Scalar = 
double>
 
 
const GridGeometry & gridGeometry() const
The finite volume grid geometry.
Definition common/fvspatialparams.hh:130
Base class for all standard pore-local pc-Sw curves.
Definition singleshapelocalrules.hh:32
Two-phase rules for regularizing the pc-SW for platonic bodies.
Definition localrulesforplatonicbody.hh:232
OptionalScalar< Scalar > dsw_dpc(const Scalar pc) const
The regularized partial derivative of the saturation to the capillary pressure.
Definition localrulesforplatonicbody.hh:412
OptionalScalar< Scalar > sw(const Scalar pc) const
The regularized saturation-capillary pressure curve.
Definition localrulesforplatonicbody.hh:343
void init(const MaterialLaw *m, const Params< Scalar > &p, const std::string ¶mGroup="")
Definition localrulesforplatonicbody.hh:300
HighSwRegularizationMethod
The available options for regularizing the pc-SW curve at high wetting-phase saturations.
Definition localrulesforplatonicbody.hh:241
@ linear
Definition localrulesforplatonicbody.hh:242
@ spline
Definition localrulesforplatonicbody.hh:242
@ powerLaw
Definition localrulesforplatonicbody.hh:242
OptionalScalar< Scalar > pc(const Scalar sw) const
Definition localrulesforplatonicbody.hh:305
void updateParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition localrulesforplatonicbody.hh:446
OptionalScalar< Scalar > dpc_dsw(const Scalar sw) const
The regularized partial derivative of the capillary pressure w.r.t. the saturation.
Definition localrulesforplatonicbody.hh:382
The base class for spatial parameters for pore-network models.
Definition porenetwork/common/spatialparams.hh:33
Scalar poreInscribedRadius(const Element &element, const SubControlVolume &scv, const ElementSolutionVector &elemSol) const
Inscribed radius of the pore body . Can be solution-dependent.
Definition porenetwork/common/spatialparams.hh:103
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:149
bool hasParamInGroup(const std::string ¶mGroup, const std::string ¶m)
Check whether a key exists in the parameter tree with a model group prefix.
Definition parameters.hh:165
SingleShapeTwoPLocalRules< Scalar, TwoPLocalRulesPlatonicBody< shape >, TwoPLocalRulesPlatonicBodyRegularization< Scalar, TwoPLocalRulesPlatonicBody< shape > > > TwoPLocalRulesPlatonicBodyDefault
A default configuration for using the VanGenuchten material law.
Definition localrulesforplatonicbody.hh:582
SingleShapeTwoPLocalRules< Scalar, TwoPLocalRulesPlatonicBody< shape >, Dumux::FluidMatrix::NoRegularization > TwoPLocalRulesPlatonicBodyNoReg
A default configuration without regularization for using the VanGenuchten material law.
Definition localrulesforplatonicbody.hh:592
Definition localrulesforplatonicbody.hh:28
Shape
Collection of different pore-body shapes.
Definition poreproperties.hh:23
@ cube
Definition poreproperties.hh:23
@ octahedron
Definition poreproperties.hh:23
@ tetrahedron
Definition poreproperties.hh:23
@ icosahedron
Definition poreproperties.hh:23
@ dodecahedron
Definition poreproperties.hh:23
A wrapper that can either contain a valid Scalar or NaN.
This file contains functions related to calculate pore-body properties.
Base classes for standard pore-local pc-Sw curves.
Provides 3rd order polynomial splines.
Template which always yields a false value.
Definition common/typetraits/typetraits.hh:24
A tag to turn off regularization and it's overhead.
Definition noregularization.hh:22
A type for an optional scalar (contains either a valid number or NaN)
Definition optionalscalar.hh:27
The parameter type.
Definition localrulesforplatonicbody.hh:36
PlatonicBodyParams()=default
PlatonicBodyParams & setPoreShape(Pore::Shape s)
Definition localrulesforplatonicbody.hh:40
PlatonicBodyParams & setSurfaceTension(Scalar st)
Definition localrulesforplatonicbody.hh:41
PlatonicBodyParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition localrulesforplatonicbody.hh:44
Pore::Shape poreShape() const
Definition localrulesforplatonicbody.hh:65
bool operator==(const PlatonicBodyParams &p) const
Definition localrulesforplatonicbody.hh:71
Scalar surfaceTension() const
Definition localrulesforplatonicbody.hh:69
PlatonicBodyParams & setPoreInscribedRadius(Scalar r)
Definition localrulesforplatonicbody.hh:39
Scalar poreInscribedRadius() const
Definition localrulesforplatonicbody.hh:67
void update(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition localrulesforplatonicbody.hh:54
Implementation of the simplified pore-local capillary pressure-saturation curve for platonic bodies (...
Definition localrulesforplatonicbody.hh:94
static Scalar dpc_dsw(Scalar sw, const Params< Scalar > ¶ms)
The partial derivative of the capillary pressure w.r.t. the wetting phase saturation.
Definition localrulesforplatonicbody.hh:159
static Scalar sw(Scalar pc, const Params< Scalar > ¶ms)
The wetting-phase saturation of a pore body.
Definition localrulesforplatonicbody.hh:137
static Scalar pc(Scalar sw, const Params< Scalar > ¶ms)
The capillary pressure-saturation curve.
Definition localrulesforplatonicbody.hh:115
PlatonicBodyParams< Scalar > Params
Definition localrulesforplatonicbody.hh:96
static Scalar dsw_dpc(Scalar pc, const Params< Scalar > ¶ms)
The partial derivative of the wetting phase saturation w.r.t. the capillary pressure.
Definition localrulesforplatonicbody.hh:181
static auto makeParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition localrulesforplatonicbody.hh:99
Definition localrulesforplatonicbody.hh:247
void setpcHighSw(S pcHighSw)
Set the threshold saturation above which the capillary pressure is regularized.
Definition localrulesforplatonicbody.hh:268
ThisType::HighSwRegularizationMethod HighSwRegularizationMethod
Definition localrulesforplatonicbody.hh:249
void setpcLowSw(S pcLowSw)
Set the threshold saturation below which the capillary pressure is regularized.
Definition localrulesforplatonicbody.hh:256
S pcLowSw() const
Threshold saturation below which the capillary pressure is regularized.
Definition localrulesforplatonicbody.hh:262
S pcHighSw() const
Threshold saturation above which the capillary pressure is regularized.
Definition localrulesforplatonicbody.hh:277
void setHighSwRegularizationMethod(HighSwRegularizationMethod method)
Set the regularization method for high saturations.
Definition localrulesforplatonicbody.hh:283
HighSwRegularizationMethod highSwRegularizationMethod() const
Return the regularization method for high saturations.
Definition localrulesforplatonicbody.hh:289