OGS
ProcessLib::HeatTransportBHE Namespace Reference

Namespaces

namespace  BHE
namespace  detail

Classes

struct  AlgebraicBCSetting
class  BHEBottomDirichletBoundaryCondition
struct  BHEEndpoints
class  BHEInflowDirichletBoundaryCondition
struct  BHEMeshData
class  HeatTransportBHELocalAssemblerBHE
class  HeatTransportBHELocalAssemblerInterface
class  HeatTransportBHELocalAssemblerSoil
class  HeatTransportBHEProcess
struct  HeatTransportBHEProcessData
struct  IntegrationPointDataBHE
struct  IntegrationPointDataSoil
class  LocalDataInitializer
struct  SecondaryData

Typedefs

using BHECreatorFunc

Functions

BHEMeshData getBHEDataInMesh (MeshLib::Mesh const &mesh)
BHEEndpoints findBHEEndpointsFromElementOrdering (std::vector< MeshLib::Element * > const &bhe_elements)
std::unique_ptr< BHEBottomDirichletBoundaryConditioncreateBHEBottomDirichletBoundaryCondition (std::pair< GlobalIndexType, GlobalIndexType > &&in_out_global_indices)
template<typename BHEUpdateCallback>
std::unique_ptr< BHEInflowDirichletBoundaryCondition< BHEUpdateCallback > > createBHEInflowDirichletBoundaryCondition (std::pair< GlobalIndexType, GlobalIndexType > &&in_out_global_indices, BHEUpdateCallback bhe_update_callback)
void createAndInsertBHE (const std::string &bhe_type, const std::vector< int > &bhe_ids_of_this_bhe, const BaseLib::ConfigTree &bhe_config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, BHEMeshData const &bhe_mesh_data, std::map< int, BHE::BHETypes > &bhes_map)
std::unique_ptr< ProcesscreateHeatTransportBHEProcess (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 > > &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)
template<template< typename > class LocalAssemblerSoilImplementation, template< typename, typename > class LocalAssemblerBHEImplementation, typename LocalAssemblerInterface, typename... ExtraCtorArgs>
void createLocalAssemblers (std::vector< MeshLib::Element * > const &mesh_elements, NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::unique_ptr< LocalAssemblerInterface > > &local_assemblers, NumLib::IntegrationOrder const integration_order, ExtraCtorArgs &&... extra_ctor_args)

Variables

std::map< std::string_view, BHECreatorFuncbheCreators

Typedef Documentation

◆ BHECreatorFunc

Initial value:
std::function<BHE::BHETypes(
std::vector<std::unique_ptr<ParameterLib::ParameterBase>>&,
std::map<std::string,
std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&)>
std::variant< BHE_1U, BHE_CXA, BHE_CXC, BHE_2U, BHE_1P > BHETypes
Definition BHETypes.h:19

Definition at line 29 of file CreateHeatTransportBHEProcess.cpp.

Function Documentation

◆ createAndInsertBHE()

void ProcessLib::HeatTransportBHE::createAndInsertBHE ( const std::string & bhe_type,
const std::vector< int > & bhe_ids_of_this_bhe,
const BaseLib::ConfigTree & bhe_config,
std::vector< std::unique_ptr< ParameterLib::ParameterBase > > & parameters,
std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const & curves,
BHEMeshData const & bhe_mesh_data,
std::map< int, BHE::BHETypes > & bhes_map )

Definition at line 66 of file CreateHeatTransportBHEProcess.cpp.

76{
77 auto bhe_creator_it = bheCreators.find(bhe_type);
78 if (bhe_creator_it == bheCreators.end())
79 {
80 OGS_FATAL("Unknown BHE type: {:s}", bhe_type);
81 }
82 for (auto const& id : bhe_ids_of_this_bhe)
83 {
84 if (id < 0 || id >= static_cast<int>(bhe_mesh_data.BHE_nodes.size()))
85 {
87 "BHE id {:d} is out of range. The mesh contains {:d} "
88 "BHE(s) (valid ids: 0 to {:d}).",
89 id, bhe_mesh_data.BHE_nodes.size(),
90 static_cast<int>(bhe_mesh_data.BHE_nodes.size()) - 1);
91 }
92 std::pair<std::map<int, BHE::BHETypes>::iterator, bool> result;
93 if (id == bhe_ids_of_this_bhe[0])
94 {
95 result = bhes_map.try_emplace(
96 id, bhe_creator_it->second(bhe_config, parameters, curves));
97 }
98 else
99 {
100 // Grouped BHEs share all configuration including parameter
101 // references. Spatial variation comes from the SpatialPosition
102 // set per-element in the assembler, so a plain copy suffices.
103 auto const& first_bhe =
104 bhes_map.find(bhe_ids_of_this_bhe[0])->second;
105 result = bhes_map.try_emplace(id, first_bhe);
106 }
107 if (!result.second)
108 {
109 OGS_FATAL(
110 "BHE with id '{:d}' is already present in the list! Check for "
111 "duplicate definitions of BHE ids.",
112 id);
113 }
114 }
115}
#define OGS_FATAL(...)
Definition Error.h:10
std::map< std::string_view, BHECreatorFunc > bheCreators

References ProcessLib::HeatTransportBHE::BHEMeshData::BHE_nodes, bheCreators, and OGS_FATAL.

Referenced by createHeatTransportBHEProcess().

◆ createBHEBottomDirichletBoundaryCondition()

std::unique_ptr< BHEBottomDirichletBoundaryCondition > ProcessLib::HeatTransportBHE::createBHEBottomDirichletBoundaryCondition ( std::pair< GlobalIndexType, GlobalIndexType > && in_out_global_indices)

Definition at line 25 of file BHEBottomDirichletBoundaryCondition.cpp.

27{
28 DBUG("Constructing BHEBottomDirichletBoundaryCondition.");
29
30 // In case of partitioned mesh the boundary could be empty, i.e. there is no
31 // boundary condition.
32#ifdef USE_PETSC
33 // For this special boundary condition the boundary condition is not empty
34 // if the global indices are non-negative.
35 if (in_out_global_indices.first < 0 && in_out_global_indices.second < 0)
36 {
37 return nullptr;
38 }
39 // If only one of the global indices (in or out) is negative the
40 // implementation is not valid.
41 if (in_out_global_indices.first < 0 || in_out_global_indices.second < 0)
42 {
44 "The partition cuts the BHE into two independent parts. This "
45 "behaviour is not implemented.");
46 }
47#endif // USE_PETSC
48
49 return std::make_unique<BHEBottomDirichletBoundaryCondition>(
50 std::move(in_out_global_indices));
51}
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22

References DBUG(), and OGS_FATAL.

Referenced by ProcessLib::HeatTransportBHE::HeatTransportBHEProcess::createBHEEndpointBoundaryConditions().

◆ createBHEInflowDirichletBoundaryCondition()

template<typename BHEUpdateCallback>
std::unique_ptr< BHEInflowDirichletBoundaryCondition< BHEUpdateCallback > > ProcessLib::HeatTransportBHE::createBHEInflowDirichletBoundaryCondition ( std::pair< GlobalIndexType, GlobalIndexType > && in_out_global_indices,
BHEUpdateCallback bhe_update_callback )

Definition at line 45 of file BHEInflowDirichletBoundaryCondition.h.

48{
49 DBUG("Constructing BHEInflowDirichletBoundaryCondition.");
50
51 // In case of partitioned mesh the boundary could be empty, i.e. there is no
52 // boundary condition.
53#ifdef USE_PETSC
54 // For this special boundary condition the boundary condition is not empty
55 // if the global indices are non-negative.
56 if (in_out_global_indices.first < 0 && in_out_global_indices.second < 0)
57 {
58 return nullptr;
59 }
60 // If only one of the global indices (in or out) is negative the
61 // implementation is not valid.
62 if (in_out_global_indices.first < 0 || in_out_global_indices.second < 0)
63 {
65 "The partition cuts the BHE into two independent parts. This "
66 "behaviour is not implemented.");
67 }
68#endif // USE_PETSC
69
70 return std::make_unique<
71 BHEInflowDirichletBoundaryCondition<BHEUpdateCallback>>(
72 std::move(in_out_global_indices), bhe_update_callback);
73}

References DBUG(), and OGS_FATAL.

Referenced by ProcessLib::HeatTransportBHE::HeatTransportBHEProcess::createBHEEndpointBoundaryConditions().

◆ createHeatTransportBHEProcess()

std::unique_ptr< Process > ProcessLib::HeatTransportBHE::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 > > & 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 )
Input File Parameter
prj__processes__process__type

Process Variables

Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__process_variables

Primary process variables as they appear in the global component vector:

Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__process_variables__process_variable

Process Parameters

Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__borehole_heat_exchangers
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__use_server_communication
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__mass_lumping
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__use_algebraic_bc
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__weighting_factor
Input File Parameter
prj__processes__process__linear
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__borehole_heat_exchangers__borehole_heat_exchanger
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__borehole_heat_exchangers__borehole_heat_exchanger__id
Input File Parameter
prj__processes__process__HEAT_TRANSPORT_BHE__borehole_heat_exchangers__borehole_heat_exchanger__type

Python object computing BC values.

Definition at line 117 of file CreateHeatTransportBHEProcess.cpp.

129{
131 config.checkConfigParameter("type", "HEAT_TRANSPORT_BHE");
132
133 DBUG("Create HeatTransportBHE Process.");
134
136
138 auto const pv_config = config.getConfigSubtree("process_variables");
139 std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
140 process_variables;
141
142 // reading primary variables for each
143 // BHE----------------------------------------------------------
145 auto range =
147 pv_config.getConfigParameterList<std::string>("process_variable");
148 std::vector<std::reference_wrapper<ProcessVariable>> per_process_variables;
149
150 for (std::string const& pv_name : range)
151 {
152 if (pv_name != "temperature_soil" &&
153 pv_name.find("temperature_BHE") == std::string::npos)
154 {
155 OGS_FATAL(
156 "Found a process variable name '{}'. It should be "
157 "'temperature_soil' or 'temperature_BHE_X'",
158 pv_name);
159 }
160 auto variable = std::find_if(variables.cbegin(), variables.cend(),
161 [&pv_name](ProcessVariable const& v)
162 { return v.getName() == pv_name; });
163
164 if (variable == variables.end())
165 {
166 OGS_FATAL(
167 "Could not find process variable '{:s}' in the provided "
168 "variables list for config tag <{:s}>.",
169 pv_name, "process_variable");
170 }
171 DBUG("Found process variable '{:s}' for config tag <{:s}>.",
172 variable->getName(), "process_variable");
173
174 per_process_variables.emplace_back(
175 const_cast<ProcessVariable&>(*variable));
176 }
177 process_variables.push_back(std::move(per_process_variables));
178 // end of reading primary variables for each
179 // BHE----------------------------------------------------------
180
182 // reading BHE parameters --------------------------------------------------
183
184 auto bhe_mesh_data = getBHEDataInMesh(mesh);
185
186 auto const& bhe_configs =
188 config.getConfigSubtree("borehole_heat_exchangers");
189
190 auto const using_server_communication =
192 config.getConfigParameter<bool>("use_server_communication", false);
193
194 auto const mass_lumping =
196 config.getConfigParameter<bool>("mass_lumping", false);
197
198 auto const using_algebraic_bc =
200 config.getConfigParameter<bool>("use_algebraic_bc", false);
201
202 auto const weighting_factor =
204 config.getConfigParameter<float>("weighting_factor", 1000.0);
205
206 auto const is_linear =
208 config.getConfigParameter<bool>("linear", false);
209 if (is_linear)
210 {
211 if (!using_algebraic_bc)
212 {
213 WARN(
214 "You specified that the process simulated by OGS is linear. "
215 "With that optimization the process will be assembled only "
216 "once and the non-linear solver will only do iterations per "
217 "time step to fulfill the BHE boundary conditions. No other "
218 "non-linearities will be resolved and OGS will not detect if "
219 "there are any non-linearities. It is your responsibility to "
220 "ensure that the assembled equation systems are linear, "
221 "indeed! There is no safety net!");
222 }
223 else
224 {
225 WARN(
226 "You specified that the process simulated by OGS is linear. "
227 "With that optimization the process will be assembled only "
228 "once and the non-linear solver will do only one iteration per "
229 "time step. No non-linearities will be resolved and OGS will "
230 "not detect if there are any non-linearities. It is your "
231 "responsibility to ensure that the assembled equation systems "
232 "are linear, indeed! There is no safety net!");
233 }
234 }
235
236 std::map<int, BHE::BHETypes> bhes_map;
237
238 int bhe_iterator = 0;
239
240 for (
241 auto const& bhe_config :
243 bhe_configs.getConfigSubtreeList("borehole_heat_exchanger"))
244 {
245 auto const bhe_id_string =
247 bhe_config.getConfigAttribute<std::string>(
248 "id", std::to_string(bhe_iterator));
249
250 std::vector<int> bhe_ids_of_this_bhe;
251
252 if (bhe_id_string == "*")
253 {
254 int const size = static_cast<int>(bhe_mesh_data.BHE_mat_IDs.size());
255 bhe_ids_of_this_bhe.resize(size);
256 std::iota(bhe_ids_of_this_bhe.begin(), bhe_ids_of_this_bhe.end(),
257 0);
258 }
259 else
260 {
261 bhe_ids_of_this_bhe =
263 }
264
265 // read in the parameters
266 const std::string bhe_type =
268 bhe_config.getConfigParameter<std::string>("type");
269
270 createAndInsertBHE(bhe_type, bhe_ids_of_this_bhe, bhe_config,
271 parameters, curves, bhe_mesh_data, bhes_map);
272 bhe_iterator++;
273 }
274
275 if (static_cast<int>(bhes_map.size()) - 1 != bhes_map.rbegin()->first)
276 {
277 OGS_FATAL(
278 "The maximum given BHE id '{:d}' did not match the number of given "
279 "BHE definitions '{:d}'. The BHE ids needs to be defined starting "
280 "from 0, so the maximum BHE id needs to be number of BHE "
281 "definitions minus 1. After all definitions there are no gaps "
282 "allowed between the given ids.",
283 bhes_map.rbegin()->first, bhes_map.size());
284 }
285
286 std::vector<BHE::BHETypes> bhes;
287 bhes.reserve(bhes_map.size());
288 std::ranges::copy(bhes_map | std::views::values, std::back_inserter(bhes));
289 // end of reading BHE parameters
290 // -------------------------------------------
291
292 auto media_map =
294
295 // find if bhe uses python boundary condition
296 auto const using_tespy =
297 visit([](auto const& bhe) { return bhe.use_python_bcs; }, bhes[0]);
298
300 BHEInflowPythonBoundaryConditionPythonSideInterface* py_object = nullptr;
301 // create a pythonBoundaryCondition object
302 if (using_tespy || using_server_communication)
303 {
304 // Evaluate Python code in scope of main module
305 pybind11::object scope =
306 pybind11::module::import("__main__").attr("__dict__");
307
308 if (!scope.contains("bc_bhe"))
309 OGS_FATAL(
310 "Function 'bc_bhe' is not defined in the python script file, "
311 "or there was no python script file specified.");
312
313 py_object =
314 scope["bc_bhe"]
315 .cast<BHEInflowPythonBoundaryConditionPythonSideInterface*>();
316
317 if (py_object == nullptr)
318 OGS_FATAL(
319 "Not able to access the correct bc pointer from python script "
320 "file specified.");
321
322 // create BHE network dataframe from Python
323 py_object->dataframe_network = py_object->initializeDataContainer();
324 if (!py_object->isOverriddenEssential())
325 {
326 DBUG(
327 "Method `initializeDataContainer' not overridden in Python "
328 "script.");
329 }
330 // clear ogs bc_node_id memory in dataframe
331 std::get<3>(py_object->dataframe_network).clear(); // ogs_bc_node_id
332
333 // here calls the tespyHydroSolver to get the pipe flow velocity in bhe
334 // network
335 /* for 2U type the flowrate initialization process below causes conflict
336 // replace the value in flow velocity Matrix _u
337 auto const tespy_flow_rate = std::get<4>(py_object->dataframe_network);
338 const std::size_t n_bhe = tespy_flow_rate.size();
339 if (bhes.size() != n_bhe)
340 OGS_FATAL(
341 "The number of BHEs defined in OGS and TESPy are not the "
342 "same!");
343
344 for (std::size_t idx_bhe = 0; idx_bhe < n_bhe; idx_bhe++)
345 {
346 // the flow_rate in OGS should be updated from the flow_rate
347 // computed by TESPy.
348 auto update_flow_rate = [&](auto& bhe) {
349 bhe.updateHeatTransferCoefficients(tespy_flow_rate[idx_bhe]);
350 };
351 visit(update_flow_rate, bhes[idx_bhe]);
352 }
353 */
354 }
355
356 HeatTransportBHEProcessData process_data(
357 std::move(media_map), std::move(bhes), py_object, using_tespy,
358 using_server_communication, mass_lumping,
359 {using_algebraic_bc, weighting_factor}, is_linear);
360
361 SecondaryVariableCollection secondary_variables;
362
363 ProcessLib::createSecondaryVariables(config, secondary_variables);
364
365 return std::make_unique<HeatTransportBHEProcess>(
366 std::move(name), mesh, std::move(jacobian_assembler), parameters,
367 integration_order, std::move(process_variables),
368 std::move(process_data), std::move(secondary_variables),
369 std::move(bhe_mesh_data));
370}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::vector< int > splitMaterialIdString(std::string const &material_id_string, char const separator)
MaterialSpatialDistributionMap createMaterialSpatialDistributionMap(std::map< int, std::shared_ptr< Medium > > const &media, MeshLib::Mesh const &mesh)
constexpr int size(int const displacement_dim)
Vectorized tensor size for given displacement dimension.
void createAndInsertBHE(const std::string &bhe_type, const std::vector< int > &bhe_ids_of_this_bhe, const BaseLib::ConfigTree &bhe_config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, BHEMeshData const &bhe_mesh_data, std::map< int, BHE::BHETypes > &bhes_map)
BHEMeshData getBHEDataInMesh(MeshLib::Mesh const &mesh)
void createSecondaryVariables(BaseLib::ConfigTree const &config, SecondaryVariableCollection &secondary_variables)

References BaseLib::ConfigTree::checkConfigParameter(), createAndInsertBHE(), MaterialPropertyLib::createMaterialSpatialDistributionMap(), ProcessLib::createSecondaryVariables(), DBUG(), getBHEDataInMesh(), BaseLib::ConfigTree::getConfigParameter(), BaseLib::ConfigTree::getConfigParameterList(), BaseLib::ConfigTree::getConfigSubtree(), OGS_FATAL, MaterialLib::splitMaterialIdString(), and WARN().

Referenced by ProjectData::parseProcesses().

◆ createLocalAssemblers()

template<template< typename > class LocalAssemblerSoilImplementation, template< typename, typename > class LocalAssemblerBHEImplementation, typename LocalAssemblerInterface, typename... ExtraCtorArgs>
void ProcessLib::HeatTransportBHE::createLocalAssemblers ( std::vector< MeshLib::Element * > const & mesh_elements,
NumLib::LocalToGlobalIndexMap const & dof_table,
std::vector< std::unique_ptr< LocalAssemblerInterface > > & local_assemblers,
NumLib::IntegrationOrder const integration_order,
ExtraCtorArgs &&... extra_ctor_args )

Creates local assemblers for each element of the given mesh.

Template Parameters
LocalAssemblerImplementationthe individual local assembler type
LocalAssemblerInterfacethe general local assembler interface
ExtraCtorArgstypes of additional constructor arguments. Those arguments will be passed to the constructor of LocalAssemblerImplementation.

The first two template parameters cannot be deduced from the arguments. Therefore they always have to be provided manually.

Definition at line 68 of file HeatTransportBHE/LocalAssemblers/CreateLocalAssemblers.h.

74{
75 DBUG("Create local assemblers for the HeatTransportBHE process.");
76
77 detail::createLocalAssemblers<LocalAssemblerSoilImplementation,
78 LocalAssemblerBHEImplementation>(
79 dof_table, mesh_elements, local_assemblers, integration_order,
80 std::forward<ExtraCtorArgs>(extra_ctor_args)...);
81}
void createLocalAssemblers(NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< MeshLib::Element * > const &mesh_elements, std::vector< std::unique_ptr< LocalAssemblerInterface > > &local_assemblers, NumLib::IntegrationOrder const integration_order, std::unordered_map< std::size_t, BHE::BHETypes * > const &element_to_bhe_map, ExtraCtorArgs &&... extra_ctor_args)

References createLocalAssemblers(), ProcessLib::HeatTransportBHE::detail::createLocalAssemblers(), and DBUG().

Referenced by createLocalAssemblers(), and ProcessLib::HeatTransportBHE::HeatTransportBHEProcess::initializeConcreteProcess().

◆ findBHEEndpointsFromElementOrdering()

BHEEndpoints ProcessLib::HeatTransportBHE::findBHEEndpointsFromElementOrdering ( std::vector< MeshLib::Element * > const & bhe_elements)

Derive the inlet/outlet endpoint nodes of a BHE from the line-element chain's local node ordering. Also validates that the elements form a single connected chain with a consistent orientation (every element's node 0 equals the previous element's node 1); calls OGS_FATAL with a diagnostic message naming the offending node on inconsistency.

Definition at line 109 of file HeatTransportBHE/BHE/MeshUtils.cpp.

111{
112 if (bhe_elements.empty())
113 {
114 OGS_FATAL(
115 "findBHEEndpointsFromElementOrdering called with an empty BHE "
116 "element list.");
117 }
118
119 // Adjacency: node id -> list of (element index, local-node-index 0 or 1)
120 // that reference it. For a well-formed BHE chain every node appears in
121 // either 1 (endpoint) or 2 (interior) such records.
122 std::unordered_map<std::size_t, std::vector<std::pair<std::size_t, int>>>
123 adjacency;
124 for (std::size_t ei = 0; ei < bhe_elements.size(); ++ei)
125 {
126 auto const* e = bhe_elements[ei];
127 if (e->getNumberOfNodes() != 2)
128 {
129 OGS_FATAL(
130 "BHE element {:d} has {:d} nodes; expected a 2-node line "
131 "element.",
132 e->getID(), e->getNumberOfNodes());
133 }
134 for (int local = 0; local < 2; ++local)
135 {
136 adjacency[e->getNode(local)->getID()].emplace_back(ei, local);
137 }
138 }
139
140 // Endpoints are nodes connected to exactly one BHE line element. Any
141 // node connected to more than 2 elements means the BHE is branching and
142 // is not a simple chain.
143 std::vector<std::size_t> endpoint_node_ids;
144 for (auto const& [nid, refs] : adjacency)
145 {
146 if (refs.size() == 1)
147 {
148 endpoint_node_ids.push_back(nid);
149 }
150 else if (refs.size() > 2)
151 {
152 OGS_FATAL(
153 "BHE element chain has a branching junction at node {:d} "
154 "(connected to {:d} elements). Expected a simple line chain.",
155 nid, refs.size());
156 }
157 }
158
159 if (endpoint_node_ids.size() != 2)
160 {
161 OGS_FATAL(
162 "BHE elements do not form a single connected line chain (found "
163 "{:d} endpoints; expected 2). Check that all line elements with "
164 "the same BHE material ID share endpoints node-to-node.",
165 endpoint_node_ids.size());
166 }
167
168 // The inlet is the endpoint that appears as local node 0 of its element;
169 // the outlet is the endpoint that appears as local node 1 of its
170 // element. If neither endpoint is at local node 0 (or both are), the
171 // chain-start or chain-end element is reversed.
172 MeshLib::Node const* inlet = nullptr;
173 MeshLib::Node const* outlet = nullptr;
174 for (std::size_t const nid : endpoint_node_ids)
175 {
176 auto const& [ei, local] = adjacency[nid].front();
177 if (local == 0)
178 {
179 if (inlet != nullptr)
180 {
181 OGS_FATAL(
182 "Both BHE chain endpoints (nodes {:d} and {:d}) appear "
183 "as local node 0 of their connected element; chain "
184 "orientation is ambiguous. Reorder element nodes so the "
185 "chain runs node 0 -> node 1 from inlet to outlet.",
186 inlet->getID(), nid);
187 }
188 inlet = bhe_elements[ei]->getNode(0);
189 }
190 else
191 {
192 outlet = bhe_elements[ei]->getNode(1);
193 }
194 }
195
196 if (inlet == nullptr || outlet == nullptr)
197 {
198 OGS_FATAL(
199 "BHE chain endpoints are not consistent with the elements' "
200 "node-0 -> node-1 ordering. Reorder element nodes so that the "
201 "intended inlet endpoint is node 0 of the chain-start element "
202 "and the intended outlet endpoint is node 1 of the chain-end "
203 "element.");
204 }
205
206 // Walk the chain from the inlet: at each step, the unused element whose
207 // node 0 equals the current node must exist, otherwise some interior
208 // element is reversed.
209 std::vector<bool> used(bhe_elements.size(), false);
210 MeshLib::Node const* cur = inlet;
211 for (std::size_t step = 0; step < bhe_elements.size(); ++step)
212 {
213 auto const& refs = adjacency[cur->getID()];
214 bool advanced = false;
215 for (auto const& [ei, local] : refs)
216 {
217 if (!used[ei] && local == 0)
218 {
219 used[ei] = true;
220 cur = bhe_elements[ei]->getNode(1);
221 advanced = true;
222 break;
223 }
224 }
225 if (!advanced)
226 {
227 OGS_FATAL(
228 "BHE element chain is inconsistently oriented at node {:d}: "
229 "an interior element does not have this node as its node 0. "
230 "Reorder the element's nodes so the chain runs node 0 -> "
231 "node 1 from inlet to outlet.",
232 cur->getID());
233 }
234 }
235
236 if (cur != outlet)
237 {
238 OGS_FATAL(
239 "BHE chain walk did not terminate at the expected outlet "
240 "endpoint (expected node {:d}, reached node {:d}).",
241 outlet->getID(), cur->getID());
242 }
243
244 return {inlet, outlet};
245}
std::size_t getID() const

References MathLib::Point3dWithID::getID(), and OGS_FATAL.

Referenced by ProcessLib::HeatTransportBHE::HeatTransportBHEProcess::createBHEEndpointBoundaryConditions().

◆ getBHEDataInMesh()

BHEMeshData ProcessLib::HeatTransportBHE::getBHEDataInMesh ( MeshLib::Mesh const & mesh)

get data about fracture and matrix elements/nodes from a mesh

Parameters
meshA mesh which includes BHE elements, i.e. 1-dimensional elements. It is assumed that elements forming a BHE have a distinct material ID.

Definition at line 49 of file HeatTransportBHE/BHE/MeshUtils.cpp.

50{
51 std::vector<MeshLib::Element*> const all_bhe_elements =
52 extractOneDimensionalElements(mesh.getElements());
53
54 // finally counting two types of elements
55 // They are (i) soil, and (ii) BHE type of elements
56 DBUG("-> found total {:d} soil elements and {:d} BHE elements",
57 mesh.getNumberOfElements() - all_bhe_elements.size(),
58 all_bhe_elements.size());
59
60 // get BHE material IDs
61 auto const* const opt_material_ids = MeshLib::materialIDs(mesh);
62 if (opt_material_ids == nullptr)
63 {
64 OGS_FATAL("Not able to get material IDs! ");
65 }
66 auto const& material_ids = *opt_material_ids;
67
68 auto const& bhe_material_ids =
69 getUniqueMaterialIds(material_ids, all_bhe_elements);
70 DBUG("-> found {:d} BHE material groups", bhe_material_ids.size());
71
72 // create a vector of BHE elements for each group
73 std::vector<std::vector<MeshLib::Element*>> bhe_elements;
74 bhe_elements.resize(bhe_material_ids.size());
75 for (unsigned bhe_id = 0; bhe_id < bhe_material_ids.size(); bhe_id++)
76 {
77 const auto bhe_mat_id = bhe_material_ids[bhe_id];
78 std::vector<MeshLib::Element*>& vec_elements = bhe_elements[bhe_id];
79 copy_if(begin(all_bhe_elements), end(all_bhe_elements),
80 back_inserter(vec_elements),
81 [&](MeshLib::Element const* const e)
82 { return material_ids[e->getID()] == bhe_mat_id; });
83 DBUG("-> found {:d} elements on the BHE_{:d}", vec_elements.size(),
84 bhe_id);
85 }
86
87 // get a vector of BHE nodes
88 std::vector<std::vector<MeshLib::Node*>> bhe_nodes;
89 bhe_nodes.resize(bhe_material_ids.size());
90 for (unsigned bhe_id = 0; bhe_id < bhe_material_ids.size(); bhe_id++)
91 {
92 std::vector<MeshLib::Node*>& vec_nodes = bhe_nodes[bhe_id];
93 for (MeshLib::Element* e : bhe_elements[bhe_id])
94 {
95 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
96 {
97 vec_nodes.push_back(const_cast<MeshLib::Node*>(e->getNode(i)));
98 }
99 }
102
103 DBUG("-> found {:d} nodes on the BHE_{:d}", vec_nodes.size(), bhe_id);
104 }
105
106 return {bhe_material_ids, bhe_elements, bhe_nodes};
107}
virtual unsigned getNumberOfNodes() const =0
virtual const Node * getNode(unsigned idx) const =0
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:80
void makeVectorUnique(std::vector< T > &v)
Definition Algorithm.h:198
bool idsComparator(T const a, T const b)
Definition Mesh.h:204
PropertyVector< int > const * materialIDs(Mesh const &mesh)
Definition Mesh.cpp:260

References DBUG(), MeshLib::Mesh::getElements(), MeshLib::Element::getID(), MeshLib::Mesh::getNumberOfElements(), MeshLib::idsComparator(), BaseLib::makeVectorUnique(), MeshLib::materialIDs(), and OGS_FATAL.

Referenced by createHeatTransportBHEProcess().

Variable Documentation

◆ bheCreators

std::map<std::string_view, BHECreatorFunc> ProcessLib::HeatTransportBHE::bheCreators
Initial value:
= {
{"1U",
[](auto& config, auto& parameters, auto& curves)
{
return BHE::BHE_1U(
BHE::createBHEUType<BHE::BHE_1U>(config, parameters, curves));
}},
{"2U",
[](auto& config, auto& parameters, auto& curves)
{
return BHE::BHE_2U(
BHE::createBHEUType<BHE::BHE_2U>(config, parameters, curves));
}},
{"CXA",
[](auto& config, auto& parameters, auto& curves)
{
return BHE::BHE_CXA(
BHE::createBHECoaxial<BHE::BHE_CXA>(config, parameters, curves));
}},
{"CXC",
[](auto& config, auto& parameters, auto& curves)
{
return BHE::BHE_CXC(
BHE::createBHECoaxial<BHE::BHE_CXC>(config, parameters, curves));
}},
{"1P", [](auto& config, auto& parameters, auto& curves)
{
return BHE::BHE_1P(
BHE::createBHE1PType<BHE::BHE_1P>(config, parameters, curves));
}}}
T_BHE createBHE1PType(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
T_BHE createBHEUType(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
T_BHE createBHECoaxial(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)

Definition at line 35 of file CreateHeatTransportBHEProcess.cpp.

35 {
36 {"1U",
37 [](auto& config, auto& parameters, auto& curves)
38 {
39 return BHE::BHE_1U(
40 BHE::createBHEUType<BHE::BHE_1U>(config, parameters, curves));
41 }},
42 {"2U",
43 [](auto& config, auto& parameters, auto& curves)
44 {
45 return BHE::BHE_2U(
46 BHE::createBHEUType<BHE::BHE_2U>(config, parameters, curves));
47 }},
48 {"CXA",
49 [](auto& config, auto& parameters, auto& curves)
50 {
51 return BHE::BHE_CXA(
52 BHE::createBHECoaxial<BHE::BHE_CXA>(config, parameters, curves));
53 }},
54 {"CXC",
55 [](auto& config, auto& parameters, auto& curves)
56 {
57 return BHE::BHE_CXC(
58 BHE::createBHECoaxial<BHE::BHE_CXC>(config, parameters, curves));
59 }},
60 {"1P", [](auto& config, auto& parameters, auto& curves)
61 {
62 return BHE::BHE_1P(
63 BHE::createBHE1PType<BHE::BHE_1P>(config, parameters, curves));
64 }}};

Referenced by createAndInsertBHE().