OGS
BHE_2U.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
4#include "BHE_2U.h"
5
6#include <numbers>
7
9#include "Physics.h"
11
12namespace ProcessLib
13{
14namespace HeatTransportBHE
15{
16namespace BHE
17{
22 PipeConfigurationUType const& pipes,
23 bool const use_python_bcs)
25 pipes, use_python_bcs}
26{
27 _thermal_resistances.fill(std::numeric_limits<double>::quiet_NaN());
28
29 // Initialize thermal resistances.
30 auto values = visit(
31 [&](auto const& control) {
32 return control(refrigerant.reference_temperature,
33 0. /* initial time */);
34 },
36 updateHeatTransferCoefficients(values.flow_rate);
37}
38
39std::array<double, BHE_2U::number_of_unknowns> BHE_2U::pipeHeatCapacities()
40 const
41{
42 double const rho_r = refrigerant.density;
43 double const specific_heat_capacity = refrigerant.specific_heat_capacity;
44 double const rho_g = grout.rho_g;
45 double const porosity_g = grout.porosity_g;
46 double const heat_cap_g = grout.heat_cap_g;
47
48 return {{/*i1*/ rho_r * specific_heat_capacity,
49 /*i2*/ rho_r * specific_heat_capacity,
50 /*o1*/ rho_r * specific_heat_capacity,
51 /*o2*/ rho_r * specific_heat_capacity,
52 /*g1*/ (1.0 - porosity_g) * rho_g * heat_cap_g,
53 /*g2*/ (1.0 - porosity_g) * rho_g * heat_cap_g,
54 /*g3*/ (1.0 - porosity_g) * rho_g * heat_cap_g,
55 /*g4*/ (1.0 - porosity_g) * rho_g * heat_cap_g}};
56}
57
58std::array<double, BHE_2U::number_of_unknowns> BHE_2U::pipeHeatConductions()
59 const
60{
61 double const lambda_r = refrigerant.thermal_conductivity;
62 double const rho_r = refrigerant.density;
63 double const Cp_r = refrigerant.specific_heat_capacity;
64 double const alpha_L = _pipes.longitudinal_dispersion_length;
65 double const porosity_g = grout.porosity_g;
66 double const lambda_g = grout.lambda_g;
67
68 // Here we calculate the laplace coefficients in the governing
69 // equations of BHE. These governing equations can be found in
70 // 1) Diersch (2013) FEFLOW book on page 952, M.120-122, or
71 // 2) Diersch (2011) Comp & Geosci 37:1122-1135, Eq. 19-22.
72 return {{// pipe i1
73 (lambda_r + rho_r * Cp_r * alpha_L * _flow_velocity),
74 // pipe i2
75 (lambda_r + rho_r * Cp_r * alpha_L * _flow_velocity),
76 // pipe o1
77 (lambda_r + rho_r * Cp_r * alpha_L * _flow_velocity),
78 // pipe o2
79 (lambda_r + rho_r * Cp_r * alpha_L * _flow_velocity),
80 // pipe g1
81 (1.0 - porosity_g) * lambda_g,
82 // pipe g2
83 (1.0 - porosity_g) * lambda_g,
84 // pipe g3
85 (1.0 - porosity_g) * lambda_g,
86 // pipe g4
87 (1.0 - porosity_g) * lambda_g}};
88}
89
90std::array<Eigen::Vector3d, BHE_2U::number_of_unknowns>
91BHE_2U::pipeAdvectionVectors(Eigen::Vector3d const& /*elem_direction*/) const
92{
93 double const rho_r = refrigerant.density;
94 double const Cp_r = refrigerant.specific_heat_capacity;
95
96 return {{// pipe i1
97 {0, 0, -rho_r * Cp_r * _flow_velocity},
98 // pipe i2
99 {0, 0, -rho_r * Cp_r * _flow_velocity},
100 // pipe o1
101 {0, 0, rho_r * Cp_r * _flow_velocity},
102 // pipe o2
103 {0, 0, rho_r * Cp_r * _flow_velocity},
104 // grout g1
105 {0, 0, 0},
106 // grout g2
107 {0, 0, 0},
108 // grout g3
109 {0, 0, 0},
110 // grout g4
111 {0, 0, 0}}};
112}
113
114double compute_R_gs_2U(double const chi, double const R_g)
115{
116 return (1 - chi) * R_g;
117}
118
119double compute_R_gg_2U(double const chi, double const R_gs, double const R_ar,
120 double const R_g)
121{
122 double const R_gg = 2.0 * R_gs * (R_ar - 2.0 * chi * R_g) /
123 (2.0 * R_gs - R_ar + 2.0 * chi * R_g);
124 if (!std::isfinite(R_gg))
125 {
126 OGS_FATAL(
127 "Error!!! Grout Thermal Resistance is an infinite number! The "
128 "simulation will be stopped!");
129 }
130
131 return R_gg;
132}
133
139std::array<double, 4> thermalResistancesGroutSoil2U(double const chi,
140 double const R_ar_1,
141 double const R_ar_2,
142 double const R_g)
143{
144 double R_gs = compute_R_gs_2U(chi, R_g);
145 double R_gg_1 = compute_R_gg_2U(chi, R_gs, R_ar_1, R_g);
146 double R_gg_2 = compute_R_gg_2U(chi, R_gs, R_ar_2,
147 R_g); // Resulting thermal resistances.
148 double chi_new = chi;
149
150 auto constraint = [&]()
151 { return 1.0 / ((1.0 / R_gg_1) + (1.0 / (2.0 * R_gs))); };
152
153 std::array<double, 3> const multiplier{chi * 2.0 / 3.0, chi * 1.0 / 3.0,
154 0.0};
155 for (double m_chi : multiplier)
156 {
157 if (constraint() >= 0)
158 {
159 break;
160 }
161 DBUG(
162 "Warning! Correction procedure was applied due to negative thermal "
163 "resistance! Chi = {:f}.\n",
164 m_chi);
165 R_gs = compute_R_gs_2U(m_chi, R_g);
166 R_gg_1 = compute_R_gg_2U(m_chi, R_gs, R_ar_1, R_g);
167 R_gg_2 = compute_R_gg_2U(m_chi, R_gs, R_ar_2, R_g);
168 chi_new = m_chi;
169 }
170
171 return {chi_new, R_gg_1, R_gg_2, R_gs};
172}
173
174void BHE_2U::updateHeatTransferCoefficients(double const flow_rate)
175
176{
177 auto const tm_flow_properties = calculateThermoMechanicalFlowPropertiesPipe(
178 _pipes.inlet, borehole_geometry.length, refrigerant, flow_rate);
179
180 _flow_velocity = tm_flow_properties.velocity;
182 calcThermalResistances(tm_flow_properties.nusselt_number);
183}
184
186std::array<double, BHE_2U::number_of_unknowns> BHE_2U::calcThermalResistances(
187 double const Nu)
188{
189 constexpr double pi = std::numbers::pi;
190
191 double const lambda_r = refrigerant.thermal_conductivity;
192 double const lambda_g = grout.lambda_g;
193 double const lambda_p = _pipes.inlet.wall_thermal_conductivity;
194
195 // thermal resistances due to advective flow of refrigerant in the _pipes
196 // Eq. 36 in Diersch_2011_CG
197 double const R_adv_i = 1.0 / (Nu * lambda_r * pi);
198 double const R_adv_o = 1.0 / (Nu * lambda_r * pi);
199
200 // thermal resistance due to thermal conductivity of the pipe wall material
201 // Eq. 49
202 double const R_con_a =
203 std::log(_pipes.inlet.outsideDiameter() / _pipes.inlet.diameter) /
204 (2.0 * pi * lambda_p);
205
206 // the average outer diameter of the _pipes
207 double const d0 = _pipes.outlet.outsideDiameter();
208 double const D = borehole_geometry.diameter;
209 // Eq. 38
210 double const chi =
211 std::log(std::sqrt(D * D + 4 * d0 * d0) / 2 / std::sqrt(2) / d0) /
212 std::log(D / 2 / d0);
213 // Eq. 39
214 // thermal resistances of the grout
215 double const R_g =
216 std::acosh((D * D + d0 * d0 - 2 * _pipes.distance * _pipes.distance) /
217 (2 * D * d0)) /
218 (2 * pi * lambda_g) *
219 (3.098 - 4.432 * std::sqrt(2) * _pipes.distance / D +
220 2.364 * 2 * _pipes.distance * _pipes.distance / D / D);
221
222 // thermal resistance due to inter-grout exchange
223 double const R_ar_1 =
224 std::acosh((2.0 * _pipes.distance * _pipes.distance - d0 * d0) / d0 /
225 d0) /
226 (2.0 * pi * lambda_g);
227
228 double const R_ar_2 =
229 std::acosh((2.0 * 2.0 * _pipes.distance * _pipes.distance - d0 * d0) /
230 d0 / d0) /
231 (2.0 * pi * lambda_g);
232
233 auto const [chi_new, R_gg_1, R_gg_2, R_gs] =
234 thermalResistancesGroutSoil2U(chi, R_ar_1, R_ar_2, R_g);
235
236 // thermal resistance due to the grout transition.
237 double const R_con_b = chi_new * R_g;
238
239 // Eq. 29 and 30
240 double const R_fig = R_adv_i + R_con_a + R_con_b;
241 double const R_fog = R_adv_o + R_con_a + R_con_b;
242
243 return {{R_fig, R_fog, R_gg_1, R_gg_2, R_gs}};
244
245 // keep the following lines------------------------------------------------
246 // when debugging the code, printing the R and phi values are needed--------
247 // std::cout << "Rfig =" << R_fig << " Rfog =" << R_fog << " Rgg =" <<
248 // R_gg << " Rgs =" << R_gs << "\n"; double phi_fig = 1.0 / (R_fig *
249 // S_i); double phi_fog = 1.0 / (R_fog * S_o); double phi_gg = 1.0 / (R_gg
250 // * S_g1); double phi_gs = 1.0 / (R_gs * S_gs); std::cout << "phi_fig ="
251 // << phi_fig << " phi_fog =" << phi_fog << " phi_gg =" << phi_gg << "
252 // phi_gs =" << phi_gs << "\n";
253 // -------------------------------------------------------------------------
254}
255
256std::array<std::pair<std::size_t /*node_id*/, int /*component*/>, 2>
258 std::size_t const top_node_id,
259 std::size_t const /*bottom_node_id*/,
260 int const in_component_id)
261{
262 return {std::make_pair(top_node_id, in_component_id),
263 std::make_pair(top_node_id, in_component_id + 2)};
264}
265
266std::optional<
267 std::array<std::pair<std::size_t /*node_id*/, int /*component*/>, 2>>
269 std::size_t const bottom_node_id,
270 int const in_component_id,
271 int const out_component_id)
272{
273 return {{std::make_pair(bottom_node_id, in_component_id),
274 std::make_pair(bottom_node_id, out_component_id)}};
275}
276
277std::array<double, BHE_2U::number_of_unknowns> BHE_2U::crossSectionAreas() const
278{
279 return {{
280 _pipes.inlet.area(),
281 _pipes.inlet.area(),
282 _pipes.outlet.area(),
283 _pipes.outlet.area(),
284 borehole_geometry.area() / 4 - _pipes.inlet.outsideArea(),
285 borehole_geometry.area() / 4 - _pipes.inlet.outsideArea(),
286 borehole_geometry.area() / 4 - _pipes.outlet.outsideArea(),
287 borehole_geometry.area() / 4 - _pipes.outlet.outsideArea(),
288 }};
289}
290
291double BHE_2U::updateFlowRateAndTemperature(double const T_out,
292 double const current_time)
293{
294 auto values =
295 visit([&](auto const& control) { return control(T_out, current_time); },
297 updateHeatTransferCoefficients(values.flow_rate);
298 return values.temperature;
299}
300} // namespace BHE
301} // namespace HeatTransportBHE
302} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
BHECommonUType(BoreholeGeometry const &borehole, RefrigerantProperties const &refrigerant, GroutParameters const &grout, FlowAndTemperatureControl const &flowAndTemperatureControl, PipeConfigurationUType const &pipes, bool const use_python_bcs)
double _flow_velocity
Flow velocity inside the pipes. Depends on the flow_rate.
static std::array< std::pair< std::size_t, int >, 2 > getBHEInflowDirichletBCNodesAndComponents(std::size_t const top_node_id, std::size_t const, int const in_component_id)
Definition BHE_2U.cpp:257
std::array< double, number_of_unknowns > calcThermalResistances(double const Nu)
Nu is the Nusselt number.
Definition BHE_2U.cpp:186
void updateHeatTransferCoefficients(double const flow_rate)
Definition BHE_2U.cpp:174
std::array< double, number_of_unknowns > _thermal_resistances
Definition BHE_2U.h:224
std::array< double, number_of_unknowns > pipeHeatConductions() const
Definition BHE_2U.cpp:58
std::array< Eigen::Vector3d, number_of_unknowns > pipeAdvectionVectors(Eigen::Vector3d const &) const
Definition BHE_2U.cpp:91
double updateFlowRateAndTemperature(double T_out, double current_time)
Return the inflow temperature for the boundary condition.
Definition BHE_2U.cpp:291
std::array< double, number_of_unknowns > pipeHeatCapacities() const
Definition BHE_2U.cpp:39
BHE_2U(BoreholeGeometry const &borehole, RefrigerantProperties const &refrigerant, GroutParameters const &grout, FlowAndTemperatureControl const &flowAndTemperatureControl, PipeConfigurationUType const &pipes, bool const use_python_bcs)
Definition BHE_2U.cpp:18
std::array< double, number_of_unknowns > crossSectionAreas() const
Definition BHE_2U.cpp:277
static std::optional< std::array< std::pair< std::size_t, int >, 2 > > getBHEBottomDirichletBCNodesAndComponents(std::size_t const bottom_node_id, int const in_component_id, int const out_component_id)
Definition BHE_2U.cpp:268
std::variant< TemperatureCurveConstantFlow, TemperatureCurveFlowCurve, FixedPowerConstantFlow, FixedPowerFlowCurve, PowerCurveConstantFlow, PowerCurveFlowCurve, BuildingPowerCurveConstantFlow, BuildingPowerCurveHotWaterCurveActiveCoolingCurveFlowCurve, BuildingPowerCurveHotWaterCurvePassiveCoolingCurveFlowCurve, BuildingPowerCurveHotWaterCurveFlowCurve, BuildingPowerCurveActiveCoolingCurveFlowCurve, BuildingPowerCurvePassiveCoolingCurveFlowCurve, BuildingPowerCurveFlowCurve, ActiveCoolingCurveFlowCurve > FlowAndTemperatureControl
double compute_R_gg_2U(double const chi, double const R_gs, double const R_ar, double const R_g)
Definition BHE_2U.cpp:119
double compute_R_gs_2U(double const chi, double const R_g)
Definition BHE_2U.cpp:114
ThermoMechanicalFlowProperties calculateThermoMechanicalFlowPropertiesPipe(Pipe const &pipe, double const length, RefrigerantProperties const &fluid, double const flow_rate)
std::array< double, 4 > thermalResistancesGroutSoil2U(double const chi, double const R_ar_1, double const R_ar_2, double const R_g)
Definition BHE_2U.cpp:139
RefrigerantProperties const refrigerant
Definition BHECommon.h:36
FlowAndTemperatureControl const flowAndTemperatureControl
Definition BHECommon.h:38