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>
242 linear, spline, powerLaw
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");
466 static const auto input = getParamFromGroup<std::string>(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;
480 static const bool splineZeroSlope = getParamFromGroup<bool>(paramGroup,
"HighSwSplineZeroSlope",
true);
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;
501 static const auto pcLowSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationLowSw", params.pcLowSw());
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
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
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
Definition: localrulesforplatonicbody.hh:28
Shape
Collection of different pore-body shapes.
Definition: poreproperties.hh:23
constexpr Shape shape(const Scalar shapeFactor) noexcept
Returns the shape for a given shape factor.
Definition: throatproperties.hh:165
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
T value() const
Definition: optionalscalar.hh:36
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
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
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