OGS
BHE_1U.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_1U.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 // Initialize thermal resistances.
28 auto values = visit(
29 [&](auto const& control)
30 {
31 return control(refrigerant.reference_temperature,
32 0. /* initial time */);
33 },
35 updateHeatTransferCoefficients(values.flow_rate);
36}
37
38std::array<double, BHE_1U::number_of_unknowns> BHE_1U::pipeHeatCapacities()
39 const
40{
41 double const rho_r = refrigerant.density;
42 double const specific_heat_capacity = refrigerant.specific_heat_capacity;
43 double const rho_g = grout.rho_g;
44 double const porosity_g = grout.porosity_g;
45 double const heat_cap_g = grout.heat_cap_g;
46
47 return {{/*i1*/ rho_r * specific_heat_capacity,
48 /*o1*/ rho_r * specific_heat_capacity,
49 /*g1*/ (1.0 - porosity_g) * rho_g * heat_cap_g,
50 /*g2*/ (1.0 - porosity_g) * rho_g * heat_cap_g}};
51}
52
53std::array<double, BHE_1U::number_of_unknowns> BHE_1U::pipeHeatConductions(
54 int const section_index) const
55{
56 double const lambda_r = refrigerant.thermal_conductivity;
57 double const rho_r = refrigerant.density;
58 double const Cp_r = refrigerant.specific_heat_capacity;
59 double const alpha_L = _pipes.longitudinal_dispersion_length;
60 double const porosity_g = grout.porosity_g;
61 double const lambda_g = grout.lambda_g;
62
63 double const velocity_norm =
64 std::abs(getClampedFlowVelocity(section_index));
65
66 // Here we calculate the laplace coefficients in the governing
67 // equations of BHE. These governing equations can be found in
68 // 1) Diersch (2013) FEFLOW book on page 952, M.120-122, or
69 // 2) Diersch (2011) Comp & Geosci 37:1122-1135, Eq. 19-22.
70 auto const pipe_conduction =
71 lambda_r + rho_r * Cp_r * alpha_L * velocity_norm;
72 auto const grout_conduction = (1.0 - porosity_g) * lambda_g;
73 return {{pipe_conduction, // i1
74 pipe_conduction, // o1
75 grout_conduction, // g1
76 grout_conduction}}; // g2
77}
78
79std::array<Eigen::Vector3d, BHE_1U::number_of_unknowns>
80BHE_1U::pipeAdvectionVectors(Eigen::Vector3d const& /*elem_direction*/,
81 int const section_index) const
82{
83 double const& rho_r = refrigerant.density;
84 double const& Cp_r = refrigerant.specific_heat_capacity;
85
86 double const velocity = getClampedFlowVelocity(section_index);
87
88 Eigen::Vector3d const advection_downflow{0, 0, -rho_r * Cp_r * velocity};
89 Eigen::Vector3d const advection_upflow{0, 0, rho_r * Cp_r * velocity};
90 return {{advection_downflow, // i1
91 advection_upflow, // o1
92 {0, 0, 0}, // g1
93 {0, 0, 0}}}; // g2
94}
95
101std::array<double, 3> thermalResistancesGroutSoil(double const chi,
102 double const R_ar,
103 double const R_g)
104{
105 double R_gs = computeRgs(chi, R_g);
106 double R_gg = computeRgg(chi, R_gs, R_ar, R_g);
107 double new_chi = chi;
108
109 auto constraint = [&]()
110 { return 1.0 / ((1.0 / R_gg) + (1.0 / (2.0 * R_gs))); };
111
112 std::array<double, 3> const multiplier{chi * 2.0 / 3.0, chi * 1.0 / 3.0,
113 0.0};
114 for (double m_chi : multiplier)
115 {
116 if (constraint() >= 0)
117 {
118 break;
119 }
120 DBUG(
121 "Warning! Correction procedure was applied due to negative thermal "
122 "resistance! Chi = {:f}.\n",
123 m_chi);
124
125 R_gs = computeRgs(m_chi, R_g);
126 R_gg = computeRgg(m_chi, R_gs, R_ar, R_g);
127 new_chi = m_chi;
128 }
129
130 return {new_chi, R_gg, R_gs};
131}
132
133void BHE_1U::updateHeatTransferCoefficients(double const flow_rate)
134{
136 _pipes.inlet, borehole_geometry.length, refrigerant, flow_rate);
137
138 _flow_velocities = {tm_flow.velocity};
139
141 [&](int i)
142 { return calcThermalResistances(tm_flow.nusselt_number, i); });
143}
144
149 double const Nu, int const section_index) const
150{
151 constexpr double pi = std::numbers::pi;
152
153 double const lambda_r = refrigerant.thermal_conductivity;
154 double const lambda_g = grout.lambda_g;
155 double const lambda_p = _pipes.inlet.wall_thermal_conductivity;
156
157 // thermal resistances due to advective flow of refrigerant in the _pipes
158 // Eq. 36 in Diersch_2011_CG
159 double const R_adv_i1 = 1.0 / (Nu * lambda_r * pi);
160 double const R_adv_o1 = 1.0 / (Nu * lambda_r * pi);
161
162 // thermal resistance due to thermal conductivity of the pipe wall material
163 // Eq. 49
164 double const inlet_diameter = _pipes.inlet.diameter;
165 double const inlet_outside_diameter = _pipes.inlet.outsideDiameter();
166 double const R_con_a = std::log(inlet_outside_diameter / inlet_diameter) /
167 (2.0 * pi * lambda_p);
168
169 // the average outer diameter of the _pipes
170 double const d0 = inlet_outside_diameter;
171 double const D =
172 borehole_geometry.sections.diameterAtSection(section_index);
173 // Eq. 51
174 double const chi = std::log(std::sqrt(D * D + 2 * d0 * d0) / 2 / d0) /
175 std::log(D / std::sqrt(2) / d0);
176 // Eq. 52
177 // thermal resistances of the grout
178 double const R_g =
179 std::acosh((D * D + d0 * d0 - _pipes.distance * _pipes.distance) /
180 (2 * D * d0)) /
181 (2 * pi * lambda_g) * (1.601 - 0.888 * _pipes.distance / D);
182
183 // thermal resistance due to inter-grout exchange
184 double const R_ar =
185 std::acosh((2.0 * _pipes.distance * _pipes.distance - d0 * d0) / d0 /
186 d0) /
187 (2.0 * pi * lambda_g);
188
189 auto const [chi_new, R_gg, R_gs] =
190 thermalResistancesGroutSoil(chi, R_ar, R_g);
191
192 // thermal resistance due to the grout transition.
193 double const R_con_b = chi_new * R_g;
194 // Eq. 29 and 30
195 double const R_fig = R_adv_i1 + R_con_a + R_con_b;
196 double const R_fog = R_adv_o1 + R_con_a + R_con_b;
197
198 return {R_fig, R_fog, R_gg, R_gs};
199}
200
201std::array<std::pair<std::size_t /*node_id*/, int /*component*/>, 2>
203 std::size_t const top_node_id,
204 std::size_t const /*bottom_node_id*/,
205 int const in_component_id)
206{
207 return {std::make_pair(top_node_id, in_component_id),
208 std::make_pair(top_node_id, in_component_id + 1)};
209}
210
211std::optional<
212 std::array<std::pair<std::size_t /*node_id*/, int /*component*/>, 2>>
214 std::size_t const bottom_node_id,
215 int const in_component_id,
216 int const out_component_id)
217{
218 return {{std::make_pair(bottom_node_id, in_component_id),
219 std::make_pair(bottom_node_id, out_component_id)}};
220}
221
222std::array<double, BHE_1U::number_of_unknowns> BHE_1U::crossSectionAreas(
223 int const section_index) const
224{
225 double const half_borehole_area =
226 borehole_geometry.sections.areaAtSection(section_index) /
228 return {{_pipes.inlet.area(), _pipes.outlet.area(),
229 checkedGroutArea(half_borehole_area, _pipes.inlet.outsideArea(),
230 section_index),
231 checkedGroutArea(half_borehole_area, _pipes.outlet.outsideArea(),
232 section_index)}};
233}
234
235double BHE_1U::updateFlowRateAndTemperature(double const T_out,
236 double const current_time)
237{
238 auto values =
239 visit([&](auto const& control) { return control(T_out, current_time); },
241 updateHeatTransferCoefficients(values.flow_rate);
242 return values.temperature;
243}
244} // namespace BHE
245} // namespace HeatTransportBHE
246} // namespace ProcessLib
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)
RefrigerantProperties const refrigerant
Definition BHECommon.h:72
void recomputeSectionalResistances(Fn &&calcForSection)
Recompute _sectional_thermal_resistances for all sections.
Definition BHECommon.h:117
FlowAndTemperatureControl const flowAndTemperatureControl
Definition BHECommon.h:74
double getClampedFlowVelocity(int const section_index) const
Get velocity for a section, clamping to last section if index exceeds the number of velocity entries....
Definition BHECommon.h:133
double updateFlowRateAndTemperature(double T_out, double current_time)
Return the inflow temperature for the boundary condition.
Definition BHE_1U.cpp:235
std::array< double, number_of_unknowns > crossSectionAreas(int const section_index=0) const
Definition BHE_1U.cpp:222
std::vector< double > calcThermalResistances(double const Nu, int const section_index=0) const
Definition BHE_1U.cpp:148
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_1U.cpp:213
std::array< double, number_of_unknowns > pipeHeatConductions(int const section_index=0) const
Definition BHE_1U.cpp:53
static constexpr int number_of_grout_zones
Definition BHE_1U.h:53
void updateHeatTransferCoefficients(double const flow_rate)
Definition BHE_1U.cpp:133
BHE_1U(BoreholeGeometry const &borehole, RefrigerantProperties const &refrigerant, GroutParameters const &grout, FlowAndTemperatureControl const &flowAndTemperatureControl, PipeConfigurationUType const &pipes, bool const use_python_bcs)
Definition BHE_1U.cpp:18
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_1U.cpp:202
std::array< Eigen::Vector3d, number_of_unknowns > pipeAdvectionVectors(Eigen::Vector3d const &, int const section_index=0) const
Definition BHE_1U.cpp:80
std::array< double, number_of_unknowns > pipeHeatCapacities() const
Definition BHE_1U.cpp:38
double checkedGroutArea(double const borehole_area_fraction, double const pipe_outside_area, int const section_index)
Definition BHECommon.h:40
std::array< double, 3 > thermalResistancesGroutSoil(double const chi, double const R_ar, double const R_g)
Definition BHE_1U.cpp:101
double computeRgg(double const chi, double const R_gs, double const R_ar, double const R_g)
std::variant< InflowTemperature, Power, BuildingPower, BuildingPowerHotWaterActiveCooling, BuildingPowerHotWaterPassiveCooling, BuildingPowerHotWater, BuildingPowerActiveCooling, BuildingPowerPassiveCooling, ActiveCooling > FlowAndTemperatureControl
double computeRgs(double const chi, double const R_g)
Grout-soil thermal resistance: R_gs = (1 - chi) * R_g.
ThermoMechanicalFlowProperties calculateThermoMechanicalFlowPropertiesPipe(Pipe const &pipe, double const length, RefrigerantProperties const &fluid, double const flow_rate)