OGS
SaturationDependentSwelling.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <cmath>
7
11
12namespace MaterialPropertyLib
13{
15 std::string name,
16 std::array<double, 3>
17 swelling_pressures,
18 std::array<double, 3>
19 exponents,
20 double const lower_saturation_limit,
21 double const upper_saturation_limit,
22 ParameterLib::CoordinateSystem const* const local_coordinate_system)
23 : p_(std::move(swelling_pressures)),
24 lambda_(std::move(exponents)),
25 S_min_(lower_saturation_limit),
26 S_max_(upper_saturation_limit),
27 local_coordinate_system_(local_coordinate_system)
28{
29 name_ = std::move(name);
30}
31
33{
34 if (!std::holds_alternative<Phase*>(scale_))
35 {
37 "The property 'SaturationDependentSwelling' is implemented on the "
38 "'phase' scales only.");
39 }
40 auto const phase = std::get<Phase*>(scale_);
41 if (phase->name != "Solid")
42 {
44 "The property 'SaturationDependentSwelling' must be given in the "
45 "'Solid' phase, not in '{:s}' phase.",
46 phase->name);
47 }
48}
49
51 VariableArray const& variable_array,
52 VariableArray const& variable_array_prev,
53 ParameterLib::SpatialPosition const& pos, double const /*t*/,
54 double const dt) const
55{
56 auto const S_L = variable_array.liquid_saturation;
57 auto const S_L_prev = variable_array_prev.liquid_saturation;
58
59 Eigen::Matrix<double, 3, 3> const e =
61 ? Eigen::Matrix<double, 3, 3>::Identity()
62 : local_coordinate_system_->transformation_3d(pos);
63
64 Eigen::Matrix<double, 3, 3> delta_sigma_sw =
65 Eigen::Matrix<double, 3, 3>::Zero();
66
67 if (S_L < S_min_)
68 {
69 return delta_sigma_sw; // still being zero.
70 }
71
72 double const S_eff = std::clamp((S_L - S_min_) / (S_max_ - S_min_), 0., 1.);
73 double const S_eff_prev =
74 std::clamp((S_L_prev - S_min_) / (S_max_ - S_min_), 0., 1.);
75
76 double const delta_S_eff = S_eff - S_eff_prev;
77
78 if (delta_S_eff == 0.)
79 {
80 return delta_sigma_sw; // still being zero.
81 }
82
83 // \Delta\sigma_{sw} = - \sum_i k_i (\lambda p S_{eff}^{(\lambda_i - 1)}
84 // e_i \otimes e_i \Delta S_L / (S_{max} - S_{min}), where
85 // e_i \otimes e_i is a square matrix with e_i,0^2 e_i,0*e_i,1 etc.
86 for (int i = 0; i < 3; ++i)
87 {
88 Eigen::Matrix<double, 3, 3> const ei_otimes_ei =
89 e.col(i) * e.col(i).transpose();
90
91 delta_sigma_sw -=
92 lambda_[i] * p_[i] * std::pow(S_eff, lambda_[i] - 1) * ei_otimes_ei;
93 }
94
95 return (delta_sigma_sw * delta_S_eff / dt).eval();
96}
97
99 VariableArray const& variable_array,
100 VariableArray const& variable_array_prev, Variable const variable,
101 ParameterLib::SpatialPosition const& pos, double const /*t*/,
102 double const /*dt*/) const
103{
104 if (variable != Variable::liquid_saturation)
105 {
106 OGS_FATAL(
107 "SaturationDependentSwelling::dValue is implemented for "
108 "derivatives with respect to liquid saturation only.");
109 }
110
111 auto const S_L = variable_array.liquid_saturation;
112 auto const S_L_prev = variable_array_prev.liquid_saturation;
113
114 Eigen::Matrix<double, 3, 3> const e =
115 local_coordinate_system_ == nullptr
116 ? Eigen::Matrix<double, 3, 3>::Identity()
117 : local_coordinate_system_->transformation_3d(pos);
118
119 Eigen::Matrix<double, 3, 3> delta_sigma_sw =
120 Eigen::Matrix<double, 3, 3>::Zero();
121
122 if (S_L < S_min_)
123 {
124 return delta_sigma_sw; // still being zero.
125 }
126
127 double const S_eff = std::clamp((S_L - S_min_) / (S_max_ - S_min_), 0., 1.);
128 double const S_eff_prev =
129 std::clamp((S_L_prev - S_min_) / (S_max_ - S_min_), 0., 1.);
130
131 double const delta_S_eff = S_eff - S_eff_prev;
132
133 // Heaviside(delta S_eff,sw)
134 if (std::abs(delta_S_eff) <= 0)
135 {
136 return delta_sigma_sw; // still being zero.
137 }
138
139 for (int i = 0; i < 3; ++i)
140 {
141 Eigen::Matrix<double, 3, 3> const ei_otimes_ei =
142 e.col(i) * e.col(i).transpose();
143
144 delta_sigma_sw +=
145 lambda_[i] * p_[i] * std::pow(S_eff, lambda_[i] - 1) * ei_otimes_ei;
146 }
147 return (delta_sigma_sw / (S_max_ - S_min_)).eval();
148}
149} // namespace MaterialPropertyLib
#define OGS_FATAL(...)
Definition Error.h:19
virtual PropertyDataType value() const
std::variant< Medium *, Phase *, Component * > scale_
std::array< double, 3 > const p_
Maximum swelling pressures, one for each spatial dimension.
PropertyDataType dValue(VariableArray const &variable_array, VariableArray const &variable_array_prev, Variable const variable, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
ParameterLib::CoordinateSystem const *const local_coordinate_system_
SaturationDependentSwelling(std::string name, std::array< double, 3 > swelling_pressures, std::array< double, 3 > exponents, double const lower_saturation_limit, double const upper_saturation_limit, ParameterLib::CoordinateSystem const *const local_coordinate_system)
std::array< double, 3 > const lambda_
Exponents, one for each spatial dimension.
std::variant< double, Eigen::Matrix< double, 2, 1 >, Eigen::Matrix< double, 3, 1 >, Eigen::Matrix< double, 2, 2 >, Eigen::Matrix< double, 3, 3 >, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 >, Eigen::MatrixXd > PropertyDataType
A local coordinate system used for tensor transformations.