25#ifndef DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH
26#define DUMUX_PNM_2P_LOCAL_RULES_FOR_PLATONIC_BODY_HH
31#include <dune/common/math.hh>
53 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
55 const Element& element,
56 const SubControlVolume& scv,
57 const ElemSol& elemSol)
58 : shape_(spatialParams.gridGeometry().poreGeometry()[scv.dofIndex()])
60 , surfaceTension_(spatialParams.
surfaceTension(element, scv, elemSol))
63 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
64 void update(
const SpatialParams& spatialParams,
65 const Element& element,
66 const SubControlVolume& scv,
67 const ElemSol& elemSol)
69 const auto& gridGeometry = spatialParams.gridGeometry();
70 shape_ = gridGeometry.poreGeometry()[scv.dofIndex()];
71 radius_ = spatialParams.poreInscribedRadius(element, scv, elemSol);
72 surfaceTension_ = spatialParams.surfaceTension(element, scv, elemSol);
83 return Dune::FloatCmp::eq(radius_, p.radius_, 1e-6)
84 && Dune::FloatCmp::eq(surfaceTension_, p.surfaceTension_, 1e-6)
85 && shape_ == p.shape_;
91 Scalar surfaceTension_;
101template<Pore::Shape shape>
104 template<
class Scalar>
107 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
109 const Element& element,
110 const SubControlVolume& scv,
111 const ElemSol& elemSol)
113 using Scalar = std::decay_t<
decltype(spatialParams.poreInscribedRadius(element, scv, elemSol))>;
123 template<
class Scalar>
126 assert(isPlatonicBody_(params.
poreShape()));
129 sw = clamp(
sw, 0.0, 1.0);
136 return 2.0*sigma / (poreRadius*(1.0 - exp(-expFactor_<Scalar>()*
sw)));
145 template<
class Scalar>
148 assert(isPlatonicBody_(params.
poreShape()));
157 return -1.0/expFactor_<Scalar>()* log(1.0 - 2.0*sigma/(poreRadius*
pc));
167 template<
class Scalar>
170 assert(isPlatonicBody_(params.
poreShape()));
173 sw = clamp(
sw, 0.0, 1.0);
178 const Scalar e = exp(expFactor_<Scalar>()*
sw);
179 return -(2.0*expFactor_<Scalar>()*sigma*e) / (poreRadius*(1.0-e)*(1.0-e));
189 template<
class Scalar>
192 assert(isPlatonicBody_(params.
poreShape()));
199 return sigma / (expFactor_<Scalar>()*sigma*
pc - 0.5*expFactor_<Scalar>()*poreRadius*
pc*
pc);
204 template<
class Scalar>
205 static constexpr Scalar expFactor_()
224 static constexpr bool isPlatonicBody_(
Pore::Shape s)
234template<
class Scalar,
class BaseLaw>
246 linear, spline, powerLaw
282 {
return pcHighSw_; }
288 { highSwRegularizationMethod_ = method; }
294 {
return highSwRegularizationMethod_; }
303 template<
class MaterialLaw>
306 initPcParameters_(m, p, paramGroup);
318 return pcLowSwPcValue_() + pcDerivativeLowSw_() * (
sw - pcLowSw_);
326 return pcHighSwPcValue_() * pow(((1.0-
sw)/(1.0-pcHighSw_)), 1.0/3.0);
330 const Scalar slope = -pcHighSwPcValue_() / (1.0 - pcHighSw_);
331 return pcHighSwPcValue_() + (
sw - pcHighSw_) * slope;
335 return pcSpline_().eval(
sw);
338 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
341 return pcDerivativeHighSwEnd_()*(
sw - 1.0);
351 if (pcHighSw_ >= 1.0)
354 return pc/pcDerivativeHighSwEnd_() + 1.0;
358 if (
pc > pcLowSwPcValue_())
359 return (
pc - pcLowSwPcValue_())/pcDerivativeLowSw_() + pcLowSw_;
362 else if (
pc <= pcHighSwPcValue_())
368 return power(
pc/pcHighSwPcValue_(), 3) * (pcHighSw_ - 1.0) + 1.0;
372 return pc/pcDerivativeHighSwEnd_() + 1.0;
376 return pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc);
389 return pcDerivativeLowSw_();
392 return pcDerivativeHighSwEnd_();
394 else if (
sw > pcHighSw_)
399 return pcHighSwPcValue_()/3.0 * 1.0 /((pcHighSw_-1.0) * pow((
sw-1.0)/(pcHighSw_-1.0), 2.0/3.0));
403 return pcDerivativeHighSwEnd_();
406 return pcSpline_().evalDerivative(
sw);
420 if (pcHighSw_ >= 1.0)
423 return 1.0/pcDerivativeHighSwEnd_();
427 else if (
pc <= pcHighSwPcValue_())
432 return (3.0*pcHighSw_ - 3.0) * power(
pc, 2) / power(pcHighSwPcValue_(), 3);
436 return 1.0/pcDerivativeHighSwEnd_();
439 return 1.0/pcSpline_().evalDerivative(pcSpline_().intersectInterval(pcHighSw_, 1.0, 0.0, 0.0, 0.0,
pc));
442 else if (
pc >= pcLowSwPcValue_())
443 return 1.0/pcDerivativeLowSw_();
449 template<
class SpatialParams,
class Element,
class SubControlVolume,
class ElemSol>
451 const Element& element,
452 const SubControlVolume& scv,
453 const ElemSol& elemSol)
458 template<
class MaterialLaw>
459 void initPcParameters_(
const MaterialLaw* m,
const Params<Scalar>& params,
const std::string& paramGroup)
461 highSwRegularizationMethod_ = params.highSwRegularizationMethod();
464 static const bool hasMethod =
hasParamInGroup(paramGroup,
"HighSwRegularizationMethod");
470 static const auto input = getParamFromGroup<std::string>(paramGroup,
"HighSwRegularizationMethod");
471 if (input ==
"Linear")
473 else if (input ==
"Spline")
475 else if (input ==
"PowerLaw")
478 DUNE_THROW(Dune::InvalidStateException, input <<
" is not a valid regularization method");
481 highSwRegularizationMethod_ = inputmethod;
484 static const bool splineZeroSlope = getParamFromGroup<bool>(paramGroup,
"HighSwSplineZeroSlope",
true);
485 highSwSplineZeroSlope_ = splineZeroSlope;
488 [[maybe_unused]]
static const bool printName = [&]
498 DUNE_THROW(Dune::NotImplemented,
"Regularization not method not implemented");
500 std::cout <<
"\n*****\nUsing " << name <<
" as regularization method for high Sw\n*****" << std::endl;
505 static const auto pcLowSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationLowSw", params.pcLowSw());
506 pcLowSw_ = !isnan(pcLowSwInput) ? pcLowSwInput : params.pcLowSw();
508 static const auto pcHighSwInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSw", std::numeric_limits<Scalar>::quiet_NaN());
509 pcHighSw_ = !isnan(pcHighSwInput) ? pcHighSwInput : params.pcHighSw();
511 baseLawParamsPtr_ = &m->basicParams();
513 static const auto highSwFixedSlopeInput = getParamFromGroup<Scalar>(paramGroup,
"RegularizationHighSwFixedSlope", std::numeric_limits<Scalar>::quiet_NaN());
514 highSwFixedSlope_ = highSwFixedSlopeInput;
523 Scalar pcLowSwPcValue_()
const
526 if (!optionalPcLowSwPcValue_)
527 optionalPcLowSwPcValue_ = BaseLaw::pc(pcLowSw_, *baseLawParamsPtr_);
528 return optionalPcLowSwPcValue_.
value();
532 Scalar pcDerivativeLowSw_()
const
534 if (!optionalPcDerivativeLowSw_)
535 optionalPcDerivativeLowSw_ = BaseLaw::dpc_dsw(pcLowSw_, *baseLawParamsPtr_);
536 return optionalPcDerivativeLowSw_.
value();
540 Scalar pcHighSwPcValue_()
const
542 if (!optionalPcHighSwPcValue_)
543 optionalPcHighSwPcValue_ = BaseLaw::pc(pcHighSw_, *baseLawParamsPtr_);
544 return optionalPcHighSwPcValue_.
value();
548 Scalar pcDerivativeHighSwEnd_()
const
551 if (!isnan(highSwFixedSlope_))
552 return highSwFixedSlope_;
554 return (0.0 - pcHighSwPcValue_()) / (1.0 - pcHighSw_);
557 const Spline<Scalar>& pcSpline_()
const
559 if (!optionalPcSpline_)
561 const auto slopes = highSwSplineZeroSlope_ ? std::array{0.0, 0.0}
562 : std::array{BaseLaw::dpc_dsw(pcHighSw_, *baseLawParamsPtr_), pcDerivativeHighSwEnd_()};
564 optionalPcSpline_ = Spline<Scalar>(pcHighSw_, 1.0,
565 pcHighSwPcValue_(), 0,
566 slopes[0], slopes[1]);
568 return optionalPcSpline_.value();
571 Scalar pcLowSw_, pcHighSw_;
572 mutable OptionalScalar<Scalar> optionalPcLowSwPcValue_, optionalPcDerivativeLowSw_;
573 mutable OptionalScalar<Scalar> optionalPcHighSwPcValue_;
575 const BaseLawParams* baseLawParamsPtr_;
576 mutable std::optional<Spline<Scalar>> optionalPcSpline_;
577 bool highSwSplineZeroSlope_;
578 Scalar highSwFixedSlope_;
585template<Pore::Shape shape,
typename Scalar =
double>
595template<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:374
Definition: localrulesforplatonicbody.hh:38
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
T value() const
Definition: optionalscalar.hh:48
Template which always yields a false value.
Definition: typetraits.hh:36
A tag to turn off regularization and it's overhead.
Definition: noregularization.hh:34
The parameter type.
Definition: localrulesforplatonicbody.hh:46
PlatonicBodyParams()=default
PlatonicBodyParams & setPoreShape(Pore::Shape s)
Definition: localrulesforplatonicbody.hh:50
PlatonicBodyParams & setSurfaceTension(Scalar st)
Definition: localrulesforplatonicbody.hh:51
PlatonicBodyParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:54
Pore::Shape poreShape() const
Definition: localrulesforplatonicbody.hh:75
bool operator==(const PlatonicBodyParams &p) const
Definition: localrulesforplatonicbody.hh:81
Scalar surfaceTension() const
Definition: localrulesforplatonicbody.hh:79
PlatonicBodyParams & setPoreInscribedRadius(Scalar r)
Definition: localrulesforplatonicbody.hh:49
Scalar poreInscribedRadius() const
Definition: localrulesforplatonicbody.hh:77
void update(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:64
Implementation of the simplified pore-local capillary pressure-saturation curve for platonic bodies (...
Definition: localrulesforplatonicbody.hh:103
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:168
static Scalar sw(Scalar pc, const Params< Scalar > ¶ms)
The wetting-phase saturation of a pore body.
Definition: localrulesforplatonicbody.hh:146
static Scalar pc(Scalar sw, const Params< Scalar > ¶ms)
The capillary pressure-saturation curve.
Definition: localrulesforplatonicbody.hh:124
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:190
static auto makeParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:108
Definition: localrulesforplatonicbody.hh:236
OptionalScalar< Scalar > dsw_dpc(const Scalar pc) const
The regularized partial derivative of the saturation to the capillary pressure.
Definition: localrulesforplatonicbody.hh:416
OptionalScalar< Scalar > sw(const Scalar pc) const
The regularized saturation-capillary pressure curve.
Definition: localrulesforplatonicbody.hh:347
void init(const MaterialLaw *m, const Params< Scalar > &p, const std::string ¶mGroup="")
Definition: localrulesforplatonicbody.hh:304
HighSwRegularizationMethod
The available options for regularizing the pc-SW curve at high wetting-phase saturations.
Definition: localrulesforplatonicbody.hh:245
OptionalScalar< Scalar > pc(const Scalar sw) const
Definition: localrulesforplatonicbody.hh:309
void updateParams(const SpatialParams &spatialParams, const Element &element, const SubControlVolume &scv, const ElemSol &elemSol)
Definition: localrulesforplatonicbody.hh:450
OptionalScalar< Scalar > dpc_dsw(const Scalar sw) const
The regularized partial derivative of the capillary pressure w.r.t. the saturation.
Definition: localrulesforplatonicbody.hh:386
Definition: localrulesforplatonicbody.hh:251
void setpcHighSw(S pcHighSw)
Set the threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:272
void setpcLowSw(S pcLowSw)
Set the threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:260
S pcLowSw() const
Threshold saturation below which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:266
S pcHighSw() const
Threshold saturation above which the capillary pressure is regularized.
Definition: localrulesforplatonicbody.hh:281
void setHighSwRegularizationMethod(HighSwRegularizationMethod method)
Set the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:287
HighSwRegularizationMethod highSwRegularizationMethod() const
Return the regularization method for high saturations.
Definition: localrulesforplatonicbody.hh:293
Base class for all standard pore-local pc-Sw curves.
Definition: singleshapelocalrules.hh:42