OGS
anonymous_namespace{MeshUtils.cpp} Namespace Reference

Classes

struct  ChainWalkResult

Functions

std::vector< MeshLib::Element * > extractOneDimensionalElements (std::vector< MeshLib::Element * > const &elements)
std::vector< int > getUniqueMaterialIds (MeshLib::PropertyVector< int > const &material_ids, std::vector< MeshLib::Element * > const &elements)
std::array< MeshLib::Node *, 2 > getElementEndpoints (MeshLib::Element &element)
std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > buildNodeToElementMap (std::vector< MeshLib::Element * > const &elements)
 Build a node-to-elements adjacency map for a set of BHE elements.
MeshLib::NodefindWellheadNode (std::vector< MeshLib::Node * > const &bhe_nodes, std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > const &node_to_elements)
ChainWalkResult walkChainFromWellhead (std::vector< MeshLib::Element * > const &bhe_elements, std::vector< MeshLib::Node * > const &bhe_nodes)

Function Documentation

◆ buildNodeToElementMap()

std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > anonymous_namespace{MeshUtils.cpp}::buildNodeToElementMap ( std::vector< MeshLib::Element * > const & elements)

Build a node-to-elements adjacency map for a set of BHE elements.

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

60{
61 std::unordered_map<std::size_t, std::vector<MeshLib::Element*>> map;
62 for (auto* element : elements)
63 {
64 auto const [n0, n1] = getElementEndpoints(*element);
65 map[n0->getID()].push_back(element);
66 map[n1->getID()].push_back(element);
67 }
68 return map;
69}
std::array< MeshLib::Node *, 2 > getElementEndpoints(MeshLib::Element &element)

References getElementEndpoints().

Referenced by walkChainFromWellhead().

◆ extractOneDimensionalElements()

std::vector< MeshLib::Element * > anonymous_namespace{MeshUtils.cpp}::extractOneDimensionalElements ( std::vector< MeshLib::Element * > const & elements)

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

22{
23 std::vector<MeshLib::Element*> one_dimensional_elements;
24
25 copy_if(
26 begin(elements), end(elements), back_inserter(one_dimensional_elements),
27 [](MeshLib::Element const* const e) { return e->getDimension() == 1; });
28
29 return one_dimensional_elements;
30}
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.

References MeshLib::Element::getDimension().

◆ findWellheadNode()

MeshLib::Node * anonymous_namespace{MeshUtils.cpp}::findWellheadNode ( std::vector< MeshLib::Node * > const & bhe_nodes,
std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > const & node_to_elements )

Find the wellhead node by filtering BHE nodes. Record the nodes that are connected to only one element. Then verifying that there are exactly two nodes exist, and returning the one with the greater z-coordinate.

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

79{
80 if (bhe_nodes.empty())
81 {
82 OGS_FATAL("BHE node list is empty while constructing mesh data.");
83 }
84
85 std::vector<MeshLib::Node*> endpoints;
86 std::copy_if(
87 bhe_nodes.begin(), bhe_nodes.end(), std::back_inserter(endpoints),
88 [&node_to_elements](MeshLib::Node* node)
89 {
90 auto const it = node_to_elements.find(node->getID());
91 return it != node_to_elements.end() && it->second.size() == 1;
92 });
93
94 if (endpoints.size() != 2)
95 {
97 "The BHE mesh must form a single continuous linear chain with "
98 "exactly 2 endpoints. Found {:d} endpoints.",
99 endpoints.size());
100 }
101
102 auto* a = endpoints[0];
103 auto* b = endpoints[1];
104
105 if ((*a)[2] == (*b)[2])
106 {
107 OGS_FATAL(
108 "Both BHE chain endpoints share the same z-coordinate ({:g}). "
109 "The wellhead choice is ambiguous.",
110 (*a)[2]);
111 }
112
113 return ((*a)[2] > (*b)[2]) ? a : b;
114}
#define OGS_FATAL(...)
Definition Error.h:19

References OGS_FATAL.

Referenced by walkChainFromWellhead().

◆ getElementEndpoints()

std::array< MeshLib::Node *, 2 > anonymous_namespace{MeshUtils.cpp}::getElementEndpoints ( MeshLib::Element & element)

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

45{
47 {
49 "Expected a line element for BHE element id {:d}, but got {:s}.",
50 element.getID(),
52 }
53
54 return {element.getNode(0), element.getNode(1)};
55}
virtual MeshElemType getGeomType() 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
std::string MeshElemType2String(const MeshElemType t)
Given a MeshElemType this returns the appropriate string.
Definition MeshEnums.cpp:10

References MeshLib::Element::getGeomType(), MeshLib::Element::getID(), MeshLib::Element::getNode(), MeshLib::LINE, MeshLib::MeshElemType2String(), and OGS_FATAL.

Referenced by buildNodeToElementMap(), and walkChainFromWellhead().

◆ getUniqueMaterialIds()

std::vector< int > anonymous_namespace{MeshUtils.cpp}::getUniqueMaterialIds ( MeshLib::PropertyVector< int > const & material_ids,
std::vector< MeshLib::Element * > const & elements )

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

35{
36 std::set<int> unique_material_ids;
37 std::transform(begin(elements), end(elements),
38 inserter(unique_material_ids, end(unique_material_ids)),
39 [&material_ids](MeshLib::Element const* const e)
40 { return material_ids[e->getID()]; });
41 return {begin(unique_material_ids), end(unique_material_ids)};
42}

References MeshLib::Element::getID().

◆ walkChainFromWellhead()

ChainWalkResult anonymous_namespace{MeshUtils.cpp}::walkChainFromWellhead ( std::vector< MeshLib::Element * > const & bhe_elements,
std::vector< MeshLib::Node * > const & bhe_nodes )

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

132{
133 if (bhe_elements.empty())
134 {
135 return {};
136 }
137
138 auto const node_to_elements = buildNodeToElementMap(bhe_elements);
139 MeshLib::Node* wellhead = findWellheadNode(bhe_nodes, node_to_elements);
140
141 // The wellhead node must be an endpoint of exactly one element.
142 auto const it = node_to_elements.find(wellhead->getID());
143 if (it == node_to_elements.end() || it->second.empty())
144 {
145 OGS_FATAL("Wellhead node {:d} is not connected to any BHE element.",
146 wellhead->getID());
147 }
148 if (it->second.size() != 1)
149 {
150 OGS_FATAL(
151 "Wellhead node {:d} is connected to {:d} BHE elements; "
152 "expected exactly 1 (chain endpoint).",
153 wellhead->getID(), it->second.size());
154 }
155
156 std::vector<MeshLib::Element*> ordered;
157 ordered.reserve(bhe_elements.size());
158 std::vector<MeshLib::Node*> ordered_nodes;
159 ordered_nodes.reserve(bhe_elements.size() + 1);
160 ordered_nodes.push_back(wellhead);
161 std::unordered_map<std::size_t, double> distances;
162 distances.reserve(bhe_elements.size());
163
164 MeshLib::Node* prev_node = wellhead;
165 MeshLib::Element* current = it->second.front();
166 double accumulated_distance = 0.0;
167
168 while (current != nullptr)
169 {
170 ordered.push_back(current);
171 double const len = current->computeVolume();
172 distances[current->getID()] = accumulated_distance + 0.5 * len;
173 accumulated_distance += len;
174
175 // Find exit node (the endpoint not shared with prev_node).
176 auto const [n0, n1] = getElementEndpoints(*current);
177 MeshLib::Node* exit_node = (n0 == prev_node) ? n1 : n0;
178 ordered_nodes.push_back(exit_node);
179
180 // Find the next element connected to exit_node.
181 auto const exit_it = node_to_elements.find(exit_node->getID());
182 MeshLib::Element* next = nullptr;
183 if (exit_it != node_to_elements.end())
184 {
185 auto const& elems = exit_it->second;
186 auto const next_it =
187 std::find_if(elems.begin(), elems.end(),
188 [current](auto* e) { return e != current; });
189 if (next_it != elems.end())
190 {
191 next = *next_it;
192 }
193 }
194
195 prev_node = exit_node;
196 current = next;
197 }
198
199 if (ordered.size() != bhe_elements.size())
200 {
201 OGS_FATAL(
202 "BHE chain walk visited {:d} elements but the group has {:d}. "
203 "The BHE mesh must form a single continuous linear chain.",
204 ordered.size(), bhe_elements.size());
205 }
206
207 return {std::move(ordered), std::move(ordered_nodes), std::move(distances)};
208}
std::size_t getID() const
virtual double computeVolume()=0
std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > buildNodeToElementMap(std::vector< MeshLib::Element * > const &elements)
Build a node-to-elements adjacency map for a set of BHE elements.
MeshLib::Node * findWellheadNode(std::vector< MeshLib::Node * > const &bhe_nodes, std::unordered_map< std::size_t, std::vector< MeshLib::Element * > > const &node_to_elements)

References buildNodeToElementMap(), MeshLib::Element::computeVolume(), findWellheadNode(), getElementEndpoints(), MathLib::Point3dWithID::getID(), MeshLib::Element::getID(), and OGS_FATAL.