OGS
EffectiveThermalConductivityPorosityMixing.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
10
11namespace MaterialPropertyLib
12{
13template <int GlobalDim>
16 std::string name,
17 ParameterLib::CoordinateSystem const* const local_coordinate_system)
18 : local_coordinate_system_(local_coordinate_system)
19{
20 name_ = std::move(name);
21}
22
23template <int GlobalDim>
25{
26 if (!std::holds_alternative<Medium*>(scale_))
27 {
29 "The property 'EffectiveThermalConductivityPorosityMixing' is "
30 "implemented on the 'medium' scale only.");
31 }
32}
33
34template <int GlobalDim>
36 VariableArray const& variable_array,
37 ParameterLib::SpatialPosition const& pos, double const t,
38 double const dt) const
39{
40 auto const& medium = std::get<Medium*>(scale_);
41 // Assuming there is either a gas phase or a liquid phase or both.
42 auto const gas_phase = getOptionalPhase(*medium, PhaseName::Gas);
43 auto const liquid_phase =
45 // Assuming there is always a solid phase.
46 auto const& solid_phase = medium->phase(PhaseName::Solid);
47
48 auto const gas_thermal_conductivity =
49 gas_phase
50 ? gas_phase
51 ->property(
53 .template value<double>(variable_array, pos, t, dt)
54 : 0.;
55
56 auto const liquid_thermal_conductivity =
57 liquid_phase
58 ? liquid_phase
59 ->property(
61 .template value<double>(variable_array, pos, t, dt)
62 : 0.;
63
64 auto solid_thermal_conductivity = formEigenTensor<GlobalDim>(
65 solid_phase
67 .value(variable_array, pos, t, dt));
68
69 auto const porosity = variable_array.porosity;
70
71 auto const S_L = variable_array.liquid_saturation;
72 auto const S_G = 1. - S_L;
73
74 auto const phi_G = porosity * S_G;
75 auto const phi_L = porosity * S_L;
76 auto const phi_S = 1. - porosity;
77
78 if constexpr (GlobalDim == 1)
79 {
80 // For 1D, return scalar value
81 double const effective_thermal_conductivity =
82 phi_G * gas_thermal_conductivity +
83 phi_L * liquid_thermal_conductivity +
84 phi_S * solid_thermal_conductivity[0];
85
86 return effective_thermal_conductivity;
87 }
88 else
89 {
90 // For 2D/3D, use tensor operations
91
92 // Local coordinate transformation is only applied for the case that the
93 // initial solid thermal conductivity is given with orthotropic
94 // assumption.
96 {
97 solid_thermal_conductivity =
98 local_coordinate_system_->rotateTensor<GlobalDim>(
99 solid_thermal_conductivity, pos);
100 }
101 auto const I = Eigen::Matrix<double, GlobalDim, GlobalDim>::Identity();
102 Eigen::Matrix<double, GlobalDim, GlobalDim> const
103 effective_thermal_conductivity =
104 (phi_G * gas_thermal_conductivity +
105 phi_L * liquid_thermal_conductivity) *
106 I +
107 phi_S * solid_thermal_conductivity;
108 return effective_thermal_conductivity;
109 }
110}
111
112template <int GlobalDim>
114 VariableArray const& variable_array, Variable const variable,
115 ParameterLib::SpatialPosition const& pos, double const t,
116 double const dt) const
117{
118 if (variable != Variable::temperature)
119 {
120 OGS_FATAL(
121 "The derivative of the "
122 "EffectiveThermalConductivityPorosityMixing is implemented only "
123 "w.r.t. temperature.");
124 }
125
126 auto const& medium = std::get<Medium*>(scale_);
127 // Assuming there is either a gas phase or a liquid phase or both.
128 auto const gas_phase = getOptionalPhase(*medium, PhaseName::Gas);
129 auto const liquid_phase =
131 // Assuming there is always a solid phase.
132 auto const& solid_phase = medium->phase(PhaseName::Solid);
133
134 auto const gas_thermal_conductivity =
135 gas_phase
136 ? gas_phase
137 ->property(
139 .template value<double>(variable_array, pos, t, dt)
140 : 0.;
141
142 auto const liquid_thermal_conductivity =
143 liquid_phase
144 ? liquid_phase
145 ->property(
147 .template value<double>(variable_array, pos, t, dt)
148 : 0.;
149
150 auto const porosity = variable_array.porosity;
151
152 auto const S_L = variable_array.liquid_saturation;
153 auto const S_G = 1. - S_L;
154
155 auto const phi_G = porosity * S_G;
156 auto const phi_L = porosity * S_L;
157 auto const phi_S = 1. - porosity;
158
159 // Derivatives of thermal conductivities w.r.t. temperature
160 auto const d_gas_thermal_conductivity_dT =
161 gas_phase
162 ? gas_phase
163 ->property(
165 .template dValue<double>(variable_array,
166 Variable::temperature, pos, t, dt)
167 : 0.;
168
169 auto const d_liquid_thermal_conductivity_dT =
170 liquid_phase
171 ? liquid_phase
172 ->property(
174 .template dValue<double>(variable_array,
175 Variable::temperature, pos, t, dt)
176 : 0.;
177
178 // For volume fractions, we need to consider derivatives w.r.t. porosity and
179 // saturation. Assuming porosity and saturation may depend on temperature
180 // d(phi_G)/dT =
181 // = d(porosity * S_G)/dT
182 // = d(porosity)/dT * S_G + porosity * d(S_G)/dT
183 // = d(porosity)/dT * S_G - porosity * d(S_L)/dT
184 // d(phi_L)/dT =
185 // = d(porosity * S_L)/dT
186 // = d(porosity)/dT * S_L + porosity * d(S_L)/dT
187 // d(phi_S)/dT =
188 // = d(1 - porosity)/dT
189 // = -d(porosity)/dT.
190 double const d_porosity_dT =
192 .template dValue<double>(variable_array, Variable::temperature, pos,
193 t, dt);
194 double const d_S_L_dT =
195 // Some processes might not have saturation property (like THM) and
196 // saturation passed in the variable_array is always 1.
199 .template dValue<double>(variable_array,
200 Variable::temperature, pos, t, dt)
201 : 0.;
202
203 auto const d_phi_G_dT = d_porosity_dT * S_G - porosity * d_S_L_dT;
204 auto const d_phi_L_dT = d_porosity_dT * S_L + porosity * d_S_L_dT;
205 auto const d_phi_S_dT = -d_porosity_dT;
206
207 auto solid_thermal_conductivity = formEigenTensor<GlobalDim>(
208 solid_phase
210 .value(variable_array, pos, t, dt));
211
212 auto d_solid_thermal_conductivity_dT = formEigenTensor<GlobalDim>(
213 solid_phase
215 .dValue(variable_array, Variable::temperature, pos, t, dt));
216
217 if constexpr (GlobalDim == 1)
218 {
219 // For 1D, return scalar derivative
220 // Total derivative of effective thermal conductivity w.r.t. temperature
221 double const d_effective_thermal_conductivity_dT =
222 d_phi_G_dT * gas_thermal_conductivity +
223 phi_G * d_gas_thermal_conductivity_dT +
224 d_phi_L_dT * liquid_thermal_conductivity +
225 phi_L * d_liquid_thermal_conductivity_dT +
226 d_phi_S_dT * solid_thermal_conductivity[0] +
227 phi_S * d_solid_thermal_conductivity_dT[0];
228
229 return d_effective_thermal_conductivity_dT;
230 }
231 else
232 {
233 // For 2D/3D, use tensor operations
234
235 // Local coordinate transformation is only applied for the case that the
236 // initial solid thermal conductivity is given with orthotropic
237 // assumption.
239 {
240 solid_thermal_conductivity =
241 local_coordinate_system_->rotateTensor<GlobalDim>(
242 solid_thermal_conductivity, pos);
243 d_solid_thermal_conductivity_dT =
244 local_coordinate_system_->rotateTensor<GlobalDim>(
245 d_solid_thermal_conductivity_dT, pos);
246 }
247
248 auto const I = Eigen::Matrix<double, GlobalDim, GlobalDim>::Identity();
249 Eigen::Matrix<double, GlobalDim, GlobalDim> const
250 d_effective_thermal_conductivity_dT =
251 (d_phi_G_dT * gas_thermal_conductivity +
252 phi_G * d_gas_thermal_conductivity_dT +
253 d_phi_L_dT * liquid_thermal_conductivity +
254 phi_L * d_liquid_thermal_conductivity_dT) *
255 I +
256 d_phi_S_dT * solid_thermal_conductivity +
257 phi_S * d_solid_thermal_conductivity_dT;
258
259 return d_effective_thermal_conductivity_dT;
260 }
261}
265} // namespace MaterialPropertyLib
#define OGS_FATAL(...)
Definition Error.h:19
EffectiveThermalConductivityPorosityMixing(std::string name, ParameterLib::CoordinateSystem const *const local_coordinate_system)
PropertyDataType value(VariableArray const &variable_array, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
PropertyDataType dValue(VariableArray const &variable_array, Variable const variable, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
virtual PropertyDataType value() const
std::variant< Medium *, Phase *, Component * > scale_
constexpr Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
Phase const * getOptionalPhase(Medium const &medium, PhaseName phase_name)
Definition Medium.cpp:110
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.