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)
237template<
class Scalar,
class BaseLaw>
249 linear, spline, powerLaw
285 {
return pcHighSw_; }
291 { highSwRegularizationMethod_ = method; }
297 {
return highSwRegularizationMethod_; }
306 template<
class MaterialLaw>
309 initPcParameters_(m, p, paramGroup);
321 return pcLowSwPcValue_() + pcDerivativeLowSw_() * (
sw - pcLowSw_);
329 return pcHighSwPcValue_() * pow(((1.0-
sw)/(1.0-pcHighSw_)), 1.0/3.0);
333 const Scalar slope = -pcHighSwPcValue_() / (1.0 - pcHighSw_);
334 return pcHighSwPcValue_() + (
sw - pcHighSw_) * slope;
338 return pcSpline_().eval(
sw);
341 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
344 return pcDerivativeHighSwEnd_()*(
sw - 1.0);
354 if (pcHighSw_ >= 1.0)
357 return pc/pcDerivativeHighSwEnd_() + 1.0;
361 if (
pc > pcLowSwPcValue_())
362 return (
pc - pcLowSwPcValue_())/pcDerivativeLowSw_() + pcLowSw_;
365 else if (
pc <= pcHighSwPcValue_())
371 return power(
pc/pcHighSwPcValue_(), 3) * (pcHighSw_ - 1.0) + 1.0;
375 return pc/pcDerivativeHighSwEnd_() + 1.0;
379 return pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc);
392 return pcDerivativeLowSw_();
395 return pcDerivativeHighSwEnd_();
397 else if (
sw > pcHighSw_)
402 return pcHighSwPcValue_()/3.0 * 1.0 /((pcHighSw_-1.0) * pow((
sw-1.0)/(pcHighSw_-1.0), 2.0/3.0));
406 return pcDerivativeHighSwEnd_();
409 return pcSpline_().evalDerivative(
sw);
423 if (pcHighSw_ >= 1.0)
426 return 1.0/pcDerivativeHighSwEnd_();
430 else if (
pc <= pcHighSwPcValue_())
435 return (3.0*pcHighSw_ - 3.0) * power(
pc, 2) / power(pcHighSwPcValue_(), 3);
439 return 1.0/pcDerivativeHighSwEnd_();
442 return 1.0/pcSpline_().evalDerivative(pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc));
445 else if (
pc >= pcLowSwPcValue_())
446 return 1.0/pcDerivativeLowSw_();
452 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
454 const Element& element,
455 const SubControlVolume& scv,
456 const ElemSol& elemSol)
461 template<
class MaterialLaw>
462 void initPcParameters_(
const MaterialLaw* m,
const Params<Scalar>& params,
const std::string& paramGroup)
464 highSwRegularizationMethod_ = params.highSwRegularizationMethod();
467 static const bool hasMethod =
hasParamInGroup(paramGroup,
"HighSwRegularizationMethod");
473 static const auto input = getParamFromGroup<std::string>(paramGroup,
"HighSwRegularizationMethod");
474 if (input ==
"Linear")
476 else if (input ==
"Spline")
478 else if (input ==
"PowerLaw")
481 DUNE_THROW(Dune::InvalidStateException, input <<
" is not a valid regularization method");
484 highSwRegularizationMethod_ = inputmethod;
487 static const bool splineZeroSlope = getParamFromGroup<bool>(paramGroup,
"HighSwSplineZeroSlope",
true);
488 highSwSplineZeroSlope_ = splineZeroSlope;
491 [[maybe_unused]]
static const bool printName = [&]
501 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
503 std::cout <<
"\n*****\nUsing " << name <<
" as regularization method for high Sw\n*****" << std::endl;
508 static const auto pcLowSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationLowSw", params.pcLowSw());
509 pcLowSw_ = !isnan(pcLowSwInput) ? pcLowSwInput : params.pcLowSw();
511 static const auto pcHighSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSw", std::numeric_limits<Scalar>::quiet_NaN());
512 pcHighSw_ = !isnan(pcHighSwInput) ? pcHighSwInput : params.pcHighSw();
514 baseLawParamsPtr_ = &m->basicParams();
516 static const auto highSwFixedSlopeInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSwFixedSlope", std::numeric_limits<Scalar>::quiet_NaN());
517 highSwFixedSlope_ = highSwFixedSlopeInput;
526 Scalar pcLowSwPcValue_()
const
529 if (!optionalPcLowSwPcValue_)
530 optionalPcLowSwPcValue_ = BaseLaw::pc(pcLowSw_, *baseLawParamsPtr_);
531 return optionalPcLowSwPcValue_.
value();
535 Scalar pcDerivativeLowSw_()
const
537 if (!optionalPcDerivativeLowSw_)
538 optionalPcDerivativeLowSw_ = BaseLaw::dpc_dsw(pcLowSw_, *baseLawParamsPtr_);
539 return optionalPcDerivativeLowSw_.
value();
543 Scalar pcHighSwPcValue_()
const
545 if (!optionalPcHighSwPcValue_)
546 optionalPcHighSwPcValue_ = BaseLaw::pc(pcHighSw_, *baseLawParamsPtr_);
547 return optionalPcHighSwPcValue_.
value();
551 Scalar pcDerivativeHighSwEnd_()
const
554 if (!isnan(highSwFixedSlope_))
555 return highSwFixedSlope_;
557 return (0.0 - pcHighSwPcValue_()) / (1.0 - pcHighSw_);
560 const Spline<Scalar>& pcSpline_()
const
562 if (!optionalPcSpline_)
564 const auto slopes = highSwSplineZeroSlope_ ? std::array{0.0, 0.0}
565 : std::array{BaseLaw::dpc_dsw(pcHighSw_, *baseLawParamsPtr_), pcDerivativeHighSwEnd_()};
567 optionalPcSpline_ = Spline<Scalar>(pcHighSw_, 1.0,
568 pcHighSwPcValue_(), 0,
569 slopes[0], slopes[1]);
571 return optionalPcSpline_.value();
574 Scalar pcLowSw_, pcHighSw_;
575 mutable OptionalScalar<Scalar> optionalPcLowSwPcValue_, optionalPcDerivativeLowSw_;
576 mutable OptionalScalar<Scalar> optionalPcHighSwPcValue_;
578 const BaseLawParams* baseLawParamsPtr_;
579 mutable std::optional<Spline<Scalar>> optionalPcSpline_;
580 bool highSwSplineZeroSlope_;
581 Scalar highSwFixedSlope_;
589template<Pore::Shape shape,
typename Scalar =
double>
600template<Pore::Shape shape,
typename Scalar =
double>
Provides 3rd order polynomial splines.
A wrapper that can either contain a valid Scalar or NaN.
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:176
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
Definition: localrulesforplatonicbody.hh:239
OptionalScalar< Scalar > dsw_dpc(const Scalar pc) const
The regularized partial derivative of the saturation to the capillary pressure.
Definition: localrulesforplatonicbody.hh:419
OptionalScalar< Scalar > sw(const Scalar pc) const
The regularized saturation-capillary pressure curve.
Definition: localrulesforplatonicbody.hh:350
void init(const MaterialLaw *m, const Params< Scalar > &p, const std::string ¶mGroup="")
Definition: localrulesforplatonicbody.hh:307
HighSwRegularizationMethod
The available options for regularizing the pc-SW curve at high wetting-phase saturations.
Definition: localrulesforplatonicbody.hh:248
OptionalScalar< Scalar > pc(const Scalar sw) const
Definition: localrulesforplatonicbody.hh:312
void updateParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:453
OptionalScalar< Scalar > dpc_dsw(const Scalar sw) const
The regularized partial derivative of the capillary pressure w.r.t. the saturation.
Definition: localrulesforplatonicbody.hh:389
Definition: localrulesforplatonicbody.hh:254
void setpcHighSw(S pcHighSw)
Set the threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:275
void setpcLowSw(S pcLowSw)
Set the threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:263
S pcLowSw() const
Threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:269
S pcHighSw() const
Threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:284
void setHighSwRegularizationMethod(HighSwRegularizationMethod method)
Set the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:290
HighSwRegularizationMethod highSwRegularizationMethod() const
Return the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:296
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