26#ifndef DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH
27#define DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH
33#include <dune/common/math.hh>
55 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
57 const Element& element,
58 const SubControlVolume& scv,
59 const ElemSol& elemSol)
60 : shape_(spatialParams.gridGeometry().poreGeometry()[scv.dofIndex()])
62 , surfaceTension_(spatialParams.
surfaceTension(element, scv, elemSol))
65 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
67 const Element& element,
68 const SubControlVolume& scv,
69 const ElemSol& elemSol)
72 shape_ = gridGeometry.poreGeometry()[scv.dofIndex()];
74 surfaceTension_ = spatialParams.surfaceTension(element, scv, elemSol);
85 return Dune::FloatCmp::eq(radius_, p.radius_, 1e-6)
86 && Dune::FloatCmp::eq(surfaceTension_, p.surfaceTension_, 1e-6)
87 && shape_ == p.shape_;
93 Scalar surfaceTension_;
104template<Pore::Shape shape>
107 template<
class Scalar>
110 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
112 const Element& element,
113 const SubControlVolume& scv,
114 const ElemSol& elemSol)
116 using Scalar = std::decay_t<
decltype(spatialParams.
poreInscribedRadius(element, scv, elemSol))>;
126 template<
class Scalar>
129 assert(isPlatonicBody_(params.
poreShape()));
132 sw = clamp(
sw, 0.0, 1.0);
139 return 2.0*sigma / (poreRadius*(1.0 - exp(-expFactor_<Scalar>()*
sw)));
148 template<
class Scalar>
151 assert(isPlatonicBody_(params.
poreShape()));
160 return -1.0/expFactor_<Scalar>()* log(1.0 - 2.0*sigma/(poreRadius*
pc));
170 template<
class Scalar>
173 assert(isPlatonicBody_(params.
poreShape()));
176 sw = clamp(
sw, 0.0, 1.0);
181 const Scalar e = exp(expFactor_<Scalar>()*
sw);
182 return -(2.0*expFactor_<Scalar>()*sigma*e) / (poreRadius*(1.0-e)*(1.0-e));
192 template<
class Scalar>
195 assert(isPlatonicBody_(params.
poreShape()));
202 return sigma / (expFactor_<Scalar>()*sigma*
pc - 0.5*expFactor_<Scalar>()*poreRadius*
pc*
pc);
207 template<
class Scalar>
208 static constexpr Scalar expFactor_()
227 static constexpr bool isPlatonicBody_(
Pore::Shape s)
242template<
class Scalar,
class BaseLaw>
254 linear, spline, powerLaw
290 {
return pcHighSw_; }
296 { highSwRegularizationMethod_ = method; }
302 {
return highSwRegularizationMethod_; }
311 template<
class MaterialLaw>
314 initPcParameters_(m, p, paramGroup);
326 return pcLowSwPcValue_() + pcDerivativeLowSw_() * (
sw - pcLowSw_);
334 return pcHighSwPcValue_() * pow(((1.0-
sw)/(1.0-pcHighSw_)), 1.0/3.0);
338 const Scalar slope = -pcHighSwPcValue_() / (1.0 - pcHighSw_);
339 return pcHighSwPcValue_() + (
sw - pcHighSw_) * slope;
343 return pcSpline_().eval(
sw);
346 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
349 return pcDerivativeHighSwEnd_()*(
sw - 1.0);
359 if (pcHighSw_ >= 1.0)
362 return pc/pcDerivativeHighSwEnd_() + 1.0;
366 if (
pc > pcLowSwPcValue_())
367 return (
pc - pcLowSwPcValue_())/pcDerivativeLowSw_() + pcLowSw_;
370 else if (
pc <= pcHighSwPcValue_())
376 return power(
pc/pcHighSwPcValue_(), 3) * (pcHighSw_ - 1.0) + 1.0;
380 return pc/pcDerivativeHighSwEnd_() + 1.0;
384 return pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc);
397 return pcDerivativeLowSw_();
400 return pcDerivativeHighSwEnd_();
402 else if (
sw > pcHighSw_)
407 return pcHighSwPcValue_()/3.0 * 1.0 /((pcHighSw_-1.0) * pow((
sw-1.0)/(pcHighSw_-1.0), 2.0/3.0));
411 return pcDerivativeHighSwEnd_();
414 return pcSpline_().evalDerivative(
sw);
428 if (pcHighSw_ >= 1.0)
431 return 1.0/pcDerivativeHighSwEnd_();
435 else if (
pc <= pcHighSwPcValue_())
440 return (3.0*pcHighSw_ - 3.0) * power(
pc, 2) / power(pcHighSwPcValue_(), 3);
444 return 1.0/pcDerivativeHighSwEnd_();
447 return 1.0/pcSpline_().evalDerivative(pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc));
450 else if (
pc >= pcLowSwPcValue_())
451 return 1.0/pcDerivativeLowSw_();
457 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
459 const Element& element,
460 const SubControlVolume& scv,
461 const ElemSol& elemSol)
466 template<
class MaterialLaw>
467 void initPcParameters_(
const MaterialLaw* m,
const Params<Scalar>& params,
const std::string& paramGroup)
469 highSwRegularizationMethod_ = params.highSwRegularizationMethod();
472 static const bool hasMethod =
hasParamInGroup(paramGroup,
"HighSwRegularizationMethod");
478 static const auto input = getParamFromGroup<std::string>(paramGroup,
"HighSwRegularizationMethod");
479 if (input ==
"Linear")
481 else if (input ==
"Spline")
483 else if (input ==
"PowerLaw")
486 DUNE_THROW(Dune::InvalidStateException, input <<
" is not a valid regularization method");
489 highSwRegularizationMethod_ = inputmethod;
492 static const bool splineZeroSlope = getParamFromGroup<bool>(paramGroup,
"HighSwSplineZeroSlope",
true);
493 highSwSplineZeroSlope_ = splineZeroSlope;
496 [[maybe_unused]]
static const bool printName = [&]
506 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
508 std::cout <<
"\n*****\nUsing " << name <<
" as regularization method for high Sw\n*****" << std::endl;
513 static const auto pcLowSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationLowSw", params.pcLowSw());
514 pcLowSw_ = !isnan(pcLowSwInput) ? pcLowSwInput : params.pcLowSw();
516 static const auto pcHighSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSw", std::numeric_limits<Scalar>::quiet_NaN());
517 pcHighSw_ = !isnan(pcHighSwInput) ? pcHighSwInput : params.pcHighSw();
519 baseLawParamsPtr_ = &m->basicParams();
521 static const auto highSwFixedSlopeInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSwFixedSlope", std::numeric_limits<Scalar>::quiet_NaN());
522 highSwFixedSlope_ = highSwFixedSlopeInput;
531 Scalar pcLowSwPcValue_()
const
534 if (!optionalPcLowSwPcValue_)
535 optionalPcLowSwPcValue_ = BaseLaw::pc(pcLowSw_, *baseLawParamsPtr_);
536 return optionalPcLowSwPcValue_.
value();
540 Scalar pcDerivativeLowSw_()
const
542 if (!optionalPcDerivativeLowSw_)
543 optionalPcDerivativeLowSw_ = BaseLaw::dpc_dsw(pcLowSw_, *baseLawParamsPtr_);
544 return optionalPcDerivativeLowSw_.
value();
548 Scalar pcHighSwPcValue_()
const
550 if (!optionalPcHighSwPcValue_)
551 optionalPcHighSwPcValue_ = BaseLaw::pc(pcHighSw_, *baseLawParamsPtr_);
552 return optionalPcHighSwPcValue_.
value();
556 Scalar pcDerivativeHighSwEnd_()
const
559 if (!isnan(highSwFixedSlope_))
560 return highSwFixedSlope_;
562 return (0.0 - pcHighSwPcValue_()) / (1.0 - pcHighSw_);
565 const Spline<Scalar>& pcSpline_()
const
567 if (!optionalPcSpline_)
569 const auto slopes = highSwSplineZeroSlope_ ? std::array{0.0, 0.0}
570 : std::array{BaseLaw::dpc_dsw(pcHighSw_, *baseLawParamsPtr_), pcDerivativeHighSwEnd_()};
572 optionalPcSpline_ = Spline<Scalar>(pcHighSw_, 1.0,
573 pcHighSwPcValue_(), 0,
574 slopes[0], slopes[1]);
576 return optionalPcSpline_.value();
579 Scalar pcLowSw_, pcHighSw_;
580 mutable OptionalScalar<Scalar> optionalPcLowSwPcValue_, optionalPcDerivativeLowSw_;
581 mutable OptionalScalar<Scalar> optionalPcHighSwPcValue_;
583 const BaseLawParams* baseLawParamsPtr_;
584 mutable std::optional<Spline<Scalar>> optionalPcSpline_;
585 bool highSwSplineZeroSlope_;
586 Scalar highSwFixedSlope_;
594template<Pore::Shape shape,
typename Scalar =
double>
605template<Pore::Shape shape,
typename Scalar =
double>
A wrapper that can either contain a valid Scalar or NaN.
Provides 3rd order polynomial splines.
Base classes for standard pore-local pc-Sw curves.
This file contains functions related to calculate pore-body properties.
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:177
Definition: localrulesforplatonicbody.hh:40
Shape
Collection of different pore-body shapes.
Definition: poreproperties.hh:35
constexpr Shape shape(const Scalar shapeFactor) noexcept
Returns the shape for a given shape factor.
Definition: throatproperties.hh:177
const GridGeometry & gridGeometry() const
The finite volume grid geometry.
Definition: common/fvspatialparams.hh:142
T value() const
Definition: optionalscalar.hh:48
Template which always yields a false value.
Definition: typetraits.hh:35
A tag to turn off regularization and it's overhead.
Definition: noregularization.hh:34
The parameter type.
Definition: localrulesforplatonicbody.hh:48
PlatonicBodyParams()=default
PlatonicBodyParams & setPoreShape(Pore::Shape s)
Definition: localrulesforplatonicbody.hh:52
PlatonicBodyParams & setSurfaceTension(Scalar st)
Definition: localrulesforplatonicbody.hh:53
PlatonicBodyParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:56
Pore::Shape poreShape() const
Definition: localrulesforplatonicbody.hh:77
bool operator==(const PlatonicBodyParams &p) const
Definition: localrulesforplatonicbody.hh:83
Scalar surfaceTension() const
Definition: localrulesforplatonicbody.hh:81
PlatonicBodyParams & setPoreInscribedRadius(Scalar r)
Definition: localrulesforplatonicbody.hh:51
Scalar poreInscribedRadius() const
Definition: localrulesforplatonicbody.hh:79
void update(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:66
Implementation of the simplified pore-local capillary pressure-saturation curve for platonic bodies (...
Definition: localrulesforplatonicbody.hh:106
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:171
static Scalar sw(Scalar pc, const Params< Scalar > ¶ms)
The wetting-phase saturation of a pore body.
Definition: localrulesforplatonicbody.hh:149
static Scalar pc(Scalar sw, const Params< Scalar > ¶ms)
The capillary pressure-saturation curve.
Definition: localrulesforplatonicbody.hh:127
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:193
static auto makeParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:111
Two-phase rules for regularizing the pc-SW for platonic bodies.
Definition: localrulesforplatonicbody.hh:244
OptionalScalar< Scalar > dsw_dpc(const Scalar pc) const
The regularized partial derivative of the saturation to the capillary pressure.
Definition: localrulesforplatonicbody.hh:424
OptionalScalar< Scalar > sw(const Scalar pc) const
The regularized saturation-capillary pressure curve.
Definition: localrulesforplatonicbody.hh:355
void init(const MaterialLaw *m, const Params< Scalar > &p, const std::string ¶mGroup="")
Definition: localrulesforplatonicbody.hh:312
HighSwRegularizationMethod
The available options for regularizing the pc-SW curve at high wetting-phase saturations.
Definition: localrulesforplatonicbody.hh:253
OptionalScalar< Scalar > pc(const Scalar sw) const
Definition: localrulesforplatonicbody.hh:317
void updateParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:458
OptionalScalar< Scalar > dpc_dsw(const Scalar sw) const
The regularized partial derivative of the capillary pressure w.r.t. the saturation.
Definition: localrulesforplatonicbody.hh:394
Definition: localrulesforplatonicbody.hh:259
void setpcHighSw(S pcHighSw)
Set the threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:280
void setpcLowSw(S pcLowSw)
Set the threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:268
S pcLowSw() const
Threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:274
S pcHighSw() const
Threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:289
void setHighSwRegularizationMethod(HighSwRegularizationMethod method)
Set the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:295
HighSwRegularizationMethod highSwRegularizationMethod() const
Return the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:301
Base class for all standard pore-local pc-Sw curves.
Definition: singleshapelocalrules.hh:44
The base class for spatial parameters for pore-network models.
Definition: porenetwork/common/spatialparams.hh:45
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:115