OGS
CreateHeatTransportBHEProcess.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 <pybind11/pybind11.h>
7
8#include <algorithm>
9#include <map>
10#include <ranges>
11#include <vector>
12
13#include "BHE/BHETypes.h"
14#include "BHE/CreateBHE1PType.h"
16#include "BHE/CreateBHEUType.h"
20#include "ParameterLib/Utils.h"
23
24namespace ProcessLib
25{
26namespace HeatTransportBHE
27{
28std::map<std::string_view,
29 std::function<BHE::BHETypes(
30 BaseLib::ConfigTree const&,
31 std::map<std::string,
32 std::unique_ptr<
33 MathLib::PiecewiseLinearInterpolation>> const&)>>
34 bheCreators = {{"1U",
35 [](auto& config, auto& curves) {
36 return BHE::BHE_1U(
37 BHE::createBHEUType<BHE::BHE_1U>(config, curves));
38 }},
39 {"2U",
40 [](auto& config, auto& curves) {
41 return BHE::BHE_2U(
42 BHE::createBHEUType<BHE::BHE_2U>(config, curves));
43 }},
44 {"CXA",
45 [](auto& config, auto& curves) {
47 config, curves));
48 }},
49 {"CXC",
50 [](auto& config, auto& curves) {
52 config, curves));
53 }},
54 {"1P", [](auto& config, auto& curves) {
55 return BHE::BHE_1P(
56 BHE::createBHE1PType<BHE::BHE_1P>(config, curves));
57 }}};
58
60 const std::string& bhe_type, const std::vector<int>& bhe_ids_of_this_bhe,
61 const BaseLib::ConfigTree& bhe_config,
62 std::map<std::string,
63 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
64 curves,
65 std::map<int, BHE::BHETypes>& bhes_map)
66{
67 auto bhe_creator_it = bheCreators.find(bhe_type);
68 if (bhe_creator_it == bheCreators.end())
69 {
70 OGS_FATAL("Unknown BHE type: {:s}", bhe_type);
71 }
72 for (auto const& id : bhe_ids_of_this_bhe)
73 {
74 std::pair<std::map<int, BHE::BHETypes>::iterator, bool> result;
75 if (id == bhe_ids_of_this_bhe[0])
76 {
77 result = bhes_map.try_emplace(
78 id, bhe_creator_it->second(bhe_config, curves));
79 }
80 else
81 {
82 result = bhes_map.try_emplace(
83 id, bhes_map.find(bhe_ids_of_this_bhe[0])->second);
84 }
85 if (!result.second)
86 {
88 "BHE with id '{:d}' is already present in the list! Check for "
89 "duplicate definitions of BHE ids.",
90 id);
91 }
92 }
93}
94
95std::unique_ptr<Process> createHeatTransportBHEProcess(
96 std::string const& name,
97 MeshLib::Mesh& mesh,
98 std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
99 std::vector<ProcessVariable> const& variables,
100 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
101 unsigned const integration_order,
102 BaseLib::ConfigTree const& config,
103 std::map<std::string,
104 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
105 curves,
106 std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media)
107{
109 config.checkConfigParameter("type", "HEAT_TRANSPORT_BHE");
110
111 DBUG("Create HeatTransportBHE Process.");
112
114
116 auto const pv_config = config.getConfigSubtree("process_variables");
117 std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
118 process_variables;
119
120 // reading primary variables for each
121 // BHE----------------------------------------------------------
123 auto range =
125 pv_config.getConfigParameterList<std::string>("process_variable");
126 std::vector<std::reference_wrapper<ProcessVariable>> per_process_variables;
127
128 for (std::string const& pv_name : range)
129 {
130 if (pv_name != "temperature_soil" &&
131 pv_name.find("temperature_BHE") == std::string::npos)
132 {
133 OGS_FATAL(
134 "Found a process variable name '{}'. It should be "
135 "'temperature_soil' or 'temperature_BHE_X'",
136 pv_name);
137 }
138 auto variable = std::find_if(variables.cbegin(), variables.cend(),
139 [&pv_name](ProcessVariable const& v)
140 { return v.getName() == pv_name; });
141
142 if (variable == variables.end())
143 {
144 OGS_FATAL(
145 "Could not find process variable '{:s}' in the provided "
146 "variables list for config tag <{:s}>.",
147 pv_name, "process_variable");
148 }
149 DBUG("Found process variable '{:s}' for config tag <{:s}>.",
150 variable->getName(), "process_variable");
151
152 per_process_variables.emplace_back(
153 const_cast<ProcessVariable&>(*variable));
154 }
155 process_variables.push_back(std::move(per_process_variables));
156 // end of reading primary variables for each
157 // BHE----------------------------------------------------------
158
160 // reading BHE parameters --------------------------------------------------
161
162 auto bhe_mesh_data = getBHEDataInMesh(mesh);
163
164 auto const& bhe_configs =
166 config.getConfigSubtree("borehole_heat_exchangers");
167
168 auto const using_server_communication =
170 config.getConfigParameter<bool>("use_server_communication", false);
171
172 auto const mass_lumping =
174 config.getConfigParameter<bool>("mass_lumping", false);
175
176 auto const using_algebraic_bc =
178 config.getConfigParameter<bool>("use_algebraic_bc", false);
179
180 auto const weighting_factor =
182 config.getConfigParameter<float>("weighting_factor", 1000.0);
183
184 auto const is_linear =
186 config.getConfigParameter<bool>("linear", false);
187 if (is_linear)
188 {
189 if (!using_algebraic_bc)
190 {
191 WARN(
192 "You specified that the process simulated by OGS is linear. "
193 "With that optimization the process will be assembled only "
194 "once and the non-linear solver will only do iterations per "
195 "time step to fulfill the BHE boundary conditions. No other "
196 "non-linearities will be resolved and OGS will not detect if "
197 "there are any non-linearities. It is your responsibility to "
198 "ensure that the assembled equation systems are linear, "
199 "indeed! There is no safety net!");
200 }
201 else
202 {
203 WARN(
204 "You specified that the process simulated by OGS is linear. "
205 "With that optimization the process will be assembled only "
206 "once and the non-linear solver will do only one iteration per "
207 "time step. No non-linearities will be resolved and OGS will "
208 "not detect if there are any non-linearities. It is your "
209 "responsibility to ensure that the assembled equation systems "
210 "are linear, indeed! There is no safety net!");
211 }
212 }
213
214 std::map<int, BHE::BHETypes> bhes_map;
215
216 int bhe_iterator = 0;
217
218 for (
219 auto const& bhe_config :
221 bhe_configs.getConfigSubtreeList("borehole_heat_exchanger"))
222 {
223 auto bhe_id_string =
225 bhe_config.getConfigAttribute<std::string>(
226 "id", std::to_string(bhe_iterator));
227
228 std::vector<int> bhe_ids_of_this_bhe;
229
230 if (bhe_id_string == "*")
231 {
232 int size = static_cast<int>(bhe_mesh_data.BHE_mat_IDs.size());
233 bhe_ids_of_this_bhe.resize(size);
234 std::iota(bhe_ids_of_this_bhe.begin(), bhe_ids_of_this_bhe.end(),
235 0);
236 }
237 else
238 {
239 bhe_ids_of_this_bhe =
241 }
242
243 // read in the parameters
244 const std::string bhe_type =
246 bhe_config.getConfigParameter<std::string>("type");
247
248 createAndInsertBHE(bhe_type, bhe_ids_of_this_bhe, bhe_config, curves,
249 bhes_map);
250 bhe_iterator++;
251 }
252
253 if (static_cast<int>(bhes_map.size()) - 1 != bhes_map.rbegin()->first)
254 {
255 OGS_FATAL(
256 "The maximum given BHE id '{:d}' did not match the number of given "
257 "BHE definitions '{:d}'. The BHE ids needs to be defined starting "
258 "from 0, so the maximum BHE id needs to be number of BHE "
259 "definitions minus 1. After all definitions there are no gaps "
260 "allowed between the given ids.",
261 bhes_map.rbegin()->first, bhes_map.size());
262 }
263
264 std::vector<BHE::BHETypes> bhes;
265 bhes.reserve(bhes_map.size());
266 std::ranges::copy(bhes_map | std::views::values, std::back_inserter(bhes));
267 // end of reading BHE parameters
268 // -------------------------------------------
269
270 auto media_map =
272
273 // find if bhe uses python boundary condition
274 auto const using_tespy =
275 visit([](auto const& bhe) { return bhe.use_python_bcs; }, bhes[0]);
276
279 // create a pythonBoundaryCondition object
280 if (using_tespy || using_server_communication)
281 {
282 // Evaluate Python code in scope of main module
283 pybind11::object scope =
284 pybind11::module::import("__main__").attr("__dict__");
285
286 if (!scope.contains("bc_bhe"))
287 OGS_FATAL(
288 "Function 'bc_bhe' is not defined in the python script file, "
289 "or there was no python script file specified.");
290
291 py_object =
292 scope["bc_bhe"]
294
295 if (py_object == nullptr)
296 OGS_FATAL(
297 "Not able to access the correct bc pointer from python script "
298 "file specified.");
299
300 // create BHE network dataframe from Python
301 py_object->dataframe_network = py_object->initializeDataContainer();
302 if (!py_object->isOverriddenEssential())
303 {
304 DBUG(
305 "Method `initializeDataContainer' not overridden in Python "
306 "script.");
307 }
308 // clear ogs bc_node_id memory in dataframe
309 std::get<3>(py_object->dataframe_network).clear(); // ogs_bc_node_id
310
311 // here calls the tespyHydroSolver to get the pipe flow velocity in bhe
312 // network
313 /* for 2U type the flowrate initialization process below causes conflict
314 // replace the value in flow velocity Matrix _u
315 auto const tespy_flow_rate = std::get<4>(py_object->dataframe_network);
316 const std::size_t n_bhe = tespy_flow_rate.size();
317 if (bhes.size() != n_bhe)
318 OGS_FATAL(
319 "The number of BHEs defined in OGS and TESPy are not the "
320 "same!");
321
322 for (std::size_t idx_bhe = 0; idx_bhe < n_bhe; idx_bhe++)
323 {
324 // the flow_rate in OGS should be updated from the flow_rate
325 // computed by TESPy.
326 auto update_flow_rate = [&](auto& bhe) {
327 bhe.updateHeatTransferCoefficients(tespy_flow_rate[idx_bhe]);
328 };
329 visit(update_flow_rate, bhes[idx_bhe]);
330 }
331 */
332 }
333
334 HeatTransportBHEProcessData process_data(
335 std::move(media_map), std::move(bhes), py_object, using_tespy,
336 using_server_communication, mass_lumping,
337 {using_algebraic_bc, weighting_factor}, is_linear);
338
339 SecondaryVariableCollection secondary_variables;
340
341 ProcessLib::createSecondaryVariables(config, secondary_variables);
342
343 return std::make_unique<HeatTransportBHEProcess>(
344 std::move(name), mesh, std::move(jacobian_assembler), parameters,
345 integration_order, std::move(process_variables),
346 std::move(process_data), std::move(secondary_variables),
347 std::move(bhe_mesh_data));
348}
349} // namespace HeatTransportBHE
350} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
T getConfigParameter(std::string const &param) const
ConfigTree getConfigSubtree(std::string const &root) const
Range< ValueIterator< T > > getConfigParameterList(std::string const &param) const
void checkConfigParameter(std::string const &param, std::string_view const value) const
Handles configuration of several secondary variables from the project file.
std::vector< int > splitMaterialIdString(std::string const &material_id_string)
MaterialSpatialDistributionMap createMaterialSpatialDistributionMap(std::map< int, std::shared_ptr< Medium > > const &media, MeshLib::Mesh const &mesh)
std::variant< BHE_1U, BHE_CXA, BHE_CXC, BHE_2U, BHE_1P > BHETypes
Definition BHETypes.h:19
T_BHE createBHE1PType(BaseLib::ConfigTree const &config, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
T_BHE createBHEUType(BaseLib::ConfigTree const &config, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
T_BHE createBHECoaxial(BaseLib::ConfigTree const &config, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
std::unique_ptr< Process > createHeatTransportBHEProcess(std::string const &name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, unsigned const integration_order, BaseLib::ConfigTree const &config, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, std::map< int, std::shared_ptr< MaterialPropertyLib::Medium > > const &media)
void createAndInsertBHE(const std::string &bhe_type, const std::vector< int > &bhe_ids_of_this_bhe, const BaseLib::ConfigTree &bhe_config, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, std::map< int, BHE::BHETypes > &bhes_map)
std::map< std::string_view, std::function< BHE::BHETypes(BaseLib::ConfigTree const &, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &)> > bheCreators
BHEMeshData getBHEDataInMesh(MeshLib::Mesh const &mesh)
void createSecondaryVariables(BaseLib::ConfigTree const &config, SecondaryVariableCollection &secondary_variables)