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 =
43 medium->hasPhase("Gas") ? &medium->phase("Gas") : nullptr;
44 auto const liquid_phase = medium->hasPhase("AqueousLiquid")
45 ? &medium->phase("AqueousLiquid")
46 : nullptr;
47 // Assuming there is always a solid phase.
48 auto const& solid_phase = medium->phase("Solid");
49
50 auto const gas_thermal_conductivity =
51 gas_phase
52 ? gas_phase
53 ->property(
55 .template value<double>(variable_array, pos, t, dt)
56 : 0.;
57
58 auto const liquid_thermal_conductivity =
59 liquid_phase
60 ? liquid_phase
61 ->property(
63 .template value<double>(variable_array, pos, t, dt)
64 : 0.;
65
66 auto solid_thermal_conductivity = formEigenTensor<GlobalDim>(
67 solid_phase
69 .value(variable_array, pos, t, dt));
70
71 auto const porosity = variable_array.porosity;
72
73 auto const S_L = variable_array.liquid_saturation;
74 auto const S_G = 1. - S_L;
75
76 auto const phi_G = porosity * S_G;
77 auto const phi_L = porosity * S_L;
78 auto const phi_S = 1. - porosity;
79
80 if constexpr (GlobalDim == 1)
81 {
82 // For 1D, return scalar value
83 double const effective_thermal_conductivity =
84 phi_G * gas_thermal_conductivity +
85 phi_L * liquid_thermal_conductivity +
86 phi_S * solid_thermal_conductivity[0];
87
88 return effective_thermal_conductivity;
89 }
90 else
91 {
92 // For 2D/3D, use tensor operations
93
94 // Local coordinate transformation is only applied for the case that the
95 // initial solid thermal conductivity is given with orthotropic
96 // assumption.
98 {
99 solid_thermal_conductivity =
100 local_coordinate_system_->rotateTensor<GlobalDim>(
101 solid_thermal_conductivity, pos);
102 }
103 auto const I = Eigen::Matrix<double, GlobalDim, GlobalDim>::Identity();
104 Eigen::Matrix<double, GlobalDim, GlobalDim> const
105 effective_thermal_conductivity =
106 (phi_G * gas_thermal_conductivity +
107 phi_L * liquid_thermal_conductivity) *
108 I +
109 phi_S * solid_thermal_conductivity;
110 return effective_thermal_conductivity;
111 }
112}
113
114template <int GlobalDim>
116 VariableArray const& variable_array, Variable const variable,
117 ParameterLib::SpatialPosition const& pos, double const t,
118 double const dt) const
119{
120 if (variable != Variable::temperature)
121 {
122 OGS_FATAL(
123 "The derivative of the "
124 "EffectiveThermalConductivityPorosityMixing is implemented only "
125 "w.r.t. temperature.");
126 }
127
128 auto const& medium = std::get<Medium*>(scale_);
129 // Assuming there is either a gas phase or a liquid phase or both.
130 auto const gas_phase =
131 medium->hasPhase("Gas") ? &medium->phase("Gas") : nullptr;
132 auto const liquid_phase = medium->hasPhase("AqueousLiquid")
133 ? &medium->phase("AqueousLiquid")
134 : nullptr;
135 // Assuming there is always a solid phase.
136 auto const& solid_phase = medium->phase("Solid");
137
138 auto const gas_thermal_conductivity =
139 gas_phase
140 ? gas_phase
141 ->property(
143 .template value<double>(variable_array, pos, t, dt)
144 : 0.;
145
146 auto const liquid_thermal_conductivity =
147 liquid_phase
148 ? liquid_phase
149 ->property(
151 .template value<double>(variable_array, pos, t, dt)
152 : 0.;
153
154 auto const porosity = variable_array.porosity;
155
156 auto const S_L = variable_array.liquid_saturation;
157 auto const S_G = 1. - S_L;
158
159 auto const phi_G = porosity * S_G;
160 auto const phi_L = porosity * S_L;
161 auto const phi_S = 1. - porosity;
162
163 // Derivatives of thermal conductivities w.r.t. temperature
164 auto const d_gas_thermal_conductivity_dT =
165 gas_phase
166 ? gas_phase
167 ->property(
169 .template dValue<double>(variable_array,
170 Variable::temperature, pos, t, dt)
171 : 0.;
172
173 auto const d_liquid_thermal_conductivity_dT =
174 liquid_phase
175 ? liquid_phase
176 ->property(
178 .template dValue<double>(variable_array,
179 Variable::temperature, pos, t, dt)
180 : 0.;
181
182 // For volume fractions, we need to consider derivatives w.r.t. porosity and
183 // saturation. Assuming porosity and saturation may depend on temperature
184 // d(phi_G)/dT =
185 // = d(porosity * S_G)/dT
186 // = d(porosity)/dT * S_G + porosity * d(S_G)/dT
187 // = d(porosity)/dT * S_G - porosity * d(S_L)/dT
188 // d(phi_L)/dT =
189 // = d(porosity * S_L)/dT
190 // = d(porosity)/dT * S_L + porosity * d(S_L)/dT
191 // d(phi_S)/dT =
192 // = d(1 - porosity)/dT
193 // = -d(porosity)/dT.
194 double const d_porosity_dT =
196 .template dValue<double>(variable_array, Variable::temperature, pos,
197 t, dt);
198 double const d_S_L_dT =
199 // Some processes might not have saturation property (like THM) and
200 // saturation passed in the variable_array is always 1.
203 .template dValue<double>(variable_array,
204 Variable::temperature, pos, t, dt)
205 : 0.;
206
207 auto const d_phi_G_dT = d_porosity_dT * S_G - porosity * d_S_L_dT;
208 auto const d_phi_L_dT = d_porosity_dT * S_L + porosity * d_S_L_dT;
209 auto const d_phi_S_dT = -d_porosity_dT;
210
211 auto solid_thermal_conductivity = formEigenTensor<GlobalDim>(
212 solid_phase
214 .value(variable_array, pos, t, dt));
215
216 auto d_solid_thermal_conductivity_dT = formEigenTensor<GlobalDim>(
217 solid_phase
219 .dValue(variable_array, Variable::temperature, pos, t, dt));
220
221 if constexpr (GlobalDim == 1)
222 {
223 // For 1D, return scalar derivative
224 // Total derivative of effective thermal conductivity w.r.t. temperature
225 double const d_effective_thermal_conductivity_dT =
226 d_phi_G_dT * gas_thermal_conductivity +
227 phi_G * d_gas_thermal_conductivity_dT +
228 d_phi_L_dT * liquid_thermal_conductivity +
229 phi_L * d_liquid_thermal_conductivity_dT +
230 d_phi_S_dT * solid_thermal_conductivity[0] +
231 phi_S * d_solid_thermal_conductivity_dT[0];
232
233 return d_effective_thermal_conductivity_dT;
234 }
235 else
236 {
237 // For 2D/3D, use tensor operations
238
239 // Local coordinate transformation is only applied for the case that the
240 // initial solid thermal conductivity is given with orthotropic
241 // assumption.
243 {
244 solid_thermal_conductivity =
245 local_coordinate_system_->rotateTensor<GlobalDim>(
246 solid_thermal_conductivity, pos);
247 d_solid_thermal_conductivity_dT =
248 local_coordinate_system_->rotateTensor<GlobalDim>(
249 d_solid_thermal_conductivity_dT, pos);
250 }
251
252 auto const I = Eigen::Matrix<double, GlobalDim, GlobalDim>::Identity();
253 Eigen::Matrix<double, GlobalDim, GlobalDim> const
254 d_effective_thermal_conductivity_dT =
255 (d_phi_G_dT * gas_thermal_conductivity +
256 phi_G * d_gas_thermal_conductivity_dT +
257 d_phi_L_dT * liquid_thermal_conductivity +
258 phi_L * d_liquid_thermal_conductivity_dT) *
259 I +
260 d_phi_S_dT * solid_thermal_conductivity +
261 phi_S * d_solid_thermal_conductivity_dT;
262
263 return d_effective_thermal_conductivity_dT;
264 }
265}
269} // 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)
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.