OGS
PostUtils.cpp
Go to the documentation of this file.
1
10#include "PostUtils.h"
11
13#include "MeshLib/Node.h"
16
17namespace ProcessLib
18{
19namespace LIE
20{
21namespace
22{
23bool includesNodeID(std::vector<MeshLib::Node*> const& vec_nodes,
24 std::size_t node_id)
25{
26 return std::any_of(vec_nodes.begin(), vec_nodes.end(),
27 [&](MeshLib::Node const* node)
28 { return node->getID() == node_id; });
29}
30
31std::vector<int> const& getMaterialIdsForNode(
32 std::vector<std::pair<std::size_t, std::vector<int>>> const&
33 vec_nodeID_matIDs,
34 std::size_t nodeID)
35{
36 auto itr =
37 std::find_if(vec_nodeID_matIDs.begin(), vec_nodeID_matIDs.end(),
38 [&](std::pair<std::size_t, std::vector<int>> const& entry)
39 { return entry.first == nodeID; });
40 assert(itr != vec_nodeID_matIDs.end());
41 return itr->second;
42};
43} // namespace
44
46 MeshLib::Mesh const& org_mesh,
47 std::vector<int> const& vec_fracture_mat_IDs,
48 std::vector<std::vector<MeshLib::Node*>> const& vec_vec_fracture_nodes,
49 std::vector<std::vector<MeshLib::Element*>> const&
50 vec_vec_fracture_matrix_elements,
51 std::vector<std::pair<std::size_t, std::vector<int>>> const&
52 vec_branch_nodeID_matIDs,
53 std::vector<std::pair<std::size_t, std::vector<int>>> const&
54 vec_junction_nodeID_matIDs)
55 : _org_mesh(org_mesh)
56{
57 if (!org_mesh.getProperties().hasPropertyVector("displacement") ||
58 !org_mesh.getProperties().hasPropertyVector("displacement_jump1") ||
59 !org_mesh.getProperties().hasPropertyVector("levelset1"))
60 {
61 OGS_FATAL("The given mesh does not have relevant properties");
62 }
63
64 // clone nodes and elements
65 std::vector<MeshLib::Node*> new_nodes(
67 std::vector<MeshLib::Element*> new_eles(
68 MeshLib::copyElementVector(org_mesh.getElements(), new_nodes));
69
70 // duplicate fracture nodes (two dup. nodes created at a branch)
71 for (auto const& vec_fracture_nodes : vec_vec_fracture_nodes)
72 {
73 for (auto const* org_node : vec_fracture_nodes)
74 {
75 auto duplicated_node =
76 new MeshLib::Node(org_node->data(), new_nodes.size());
77 new_nodes.push_back(duplicated_node);
78 _map_dup_newNodeIDs[org_node->getID()].push_back(
79 duplicated_node->getID());
80 }
81 }
82 // at a junction, generate one more duplicated node (total 4 nodes)
83 for (auto const& entry : vec_junction_nodeID_matIDs)
84 {
85 auto* org_node = org_mesh.getNode(entry.first);
86 auto duplicated_node =
87 new MeshLib::Node(org_node->data(), new_nodes.size());
88 new_nodes.push_back(duplicated_node);
89 _map_dup_newNodeIDs[org_node->getID()].push_back(
90 duplicated_node->getID());
91 }
92
93 // split elements using the new duplicated nodes
94 for (unsigned fracture_id = 0;
95 fracture_id < vec_vec_fracture_matrix_elements.size();
96 fracture_id++)
97 {
98 auto const frac_matid = vec_fracture_mat_IDs[fracture_id];
99 auto const& vec_fracture_matrix_elements =
100 vec_vec_fracture_matrix_elements[fracture_id];
101 auto const& vec_fracture_nodes = vec_vec_fracture_nodes[fracture_id];
102 auto prop_levelset = org_mesh.getProperties().getPropertyVector<double>(
103 "levelset" + std::to_string(fracture_id + 1));
104 for (auto const* org_e : vec_fracture_matrix_elements)
105 {
106 // only matrix elements
107 if (org_e->getDimension() != org_mesh.getDimension())
108 {
109 continue;
110 }
111
112 auto const eid = org_e->getID();
113 // keep original if the element has levelset<=0
114 if ((*prop_levelset)[eid] <= 0)
115 {
116 continue;
117 }
118
119 // replace fracture nodes with duplicated ones
120 MeshLib::Element* e = new_eles[eid];
121 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
122 {
123 const auto node_id = getNodeIndex(*e, i);
124 if (!includesNodeID(vec_fracture_nodes, node_id))
125 {
126 continue;
127 }
128
129 // list of duplicated node IDs
130 auto itr = _map_dup_newNodeIDs.find(node_id);
131 if (itr == _map_dup_newNodeIDs.end())
132 {
133 continue;
134 }
135 const auto& dup_newNodeIDs = itr->second;
136
137 // choose new node id
138 unsigned new_node_id = 0;
139 if (dup_newNodeIDs.size() == 1)
140 {
141 // non-intersected nodes
142 new_node_id = dup_newNodeIDs[0];
143 }
144 else if (dup_newNodeIDs.size() == 2)
145 {
146 // branch nodes
147 const auto& br_matids = getMaterialIdsForNode(
148 vec_branch_nodeID_matIDs, node_id);
149 auto const frac2_matid = BaseLib::findFirstNotEqualElement(
150 br_matids, frac_matid);
151 assert(frac2_matid);
152 auto const frac2_id =
153 BaseLib::findIndex(vec_fracture_mat_IDs, *frac2_matid);
154 assert(frac2_id != std::numeric_limits<std::size_t>::max());
155 auto prop_levelset2 =
156 org_mesh.getProperties().getPropertyVector<double>(
157 "levelset" + std::to_string(frac2_id + 1));
158 std::size_t pos = 0;
159 if ((*prop_levelset2)[eid] <= 0)
160 {
161 // index of this fracture
162 pos = BaseLib::findIndex(br_matids, frac_matid);
163 }
164 else
165 {
166 // index of the other fracture
167 pos = BaseLib::findIndex(br_matids, *frac2_matid);
168 }
169 assert(pos != std::numeric_limits<std::size_t>::max());
170 new_node_id = dup_newNodeIDs[pos];
171 }
172 else
173 {
174 // junction nodes
175 const auto& jct_matids = getMaterialIdsForNode(
176 vec_junction_nodeID_matIDs, node_id);
177 auto const frac2_matid = BaseLib::findFirstNotEqualElement(
178 jct_matids, frac_matid);
179 assert(frac2_matid);
180 auto const frac2_id =
181 BaseLib::findIndex(vec_fracture_mat_IDs, *frac2_matid);
182 assert(frac2_id != std::numeric_limits<std::size_t>::max());
183 auto prop_levelset2 =
184 org_mesh.getProperties().getPropertyVector<double>(
185 "levelset" + std::to_string(frac2_id + 1));
186
187 //
188 if ((*prop_levelset2)[eid] <= 0)
189 {
190 // index of this frac
191 auto const pos =
192 BaseLib::findIndex(jct_matids, frac_matid);
193 assert(pos != std::numeric_limits<std::size_t>::max());
194 new_node_id = dup_newNodeIDs[pos];
195 }
196 else
197 {
198 // set the last duplicated node
199 new_node_id = dup_newNodeIDs.back();
200 }
201 }
202
203 // replace node
204 e->setNode(i, new_nodes[new_node_id]);
205 }
206 }
207 }
208
209 // new mesh
210 _output_mesh = std::make_unique<MeshLib::Mesh>(org_mesh.getName(),
211 new_nodes, new_eles);
212
213 for (auto [name, property] : _org_mesh.getProperties())
214 {
215 if (auto const* p =
216 dynamic_cast<MeshLib::PropertyVector<double>*>(property))
217 {
219 }
220 else if (auto const* p =
221 dynamic_cast<MeshLib::PropertyVector<float>*>(property))
222 {
224 }
225 else if (auto const* p =
226 dynamic_cast<MeshLib::PropertyVector<int>*>(property))
227 {
229 }
230 else if (auto const* p =
231 dynamic_cast<MeshLib::PropertyVector<unsigned>*>(property))
232 {
234 }
235 else if (auto const* p =
236 dynamic_cast<MeshLib::PropertyVector<long>*>(property))
237 {
239 }
240 else if (auto const* p =
242 property))
243 {
245 }
246 else if (auto const* p =
248 property))
249 {
251 }
252 else if (auto const* p =
254 property))
255 {
257 }
258 else if (auto const* p =
260 property))
261 {
263 }
264 else if (auto const* p =
265 dynamic_cast<MeshLib::PropertyVector<char>*>(property))
266 {
268 }
269 else
270 {
271 OGS_FATAL(
272 "Mesh property '{:s}' of unhandled data type '{:s}'. Please "
273 "check the data type of the mesh properties. The available "
274 "data types are:"
275 "\n\t double,"
276 "\n\t float,"
277 "\n\t int,"
278 "\n\t unsigned,"
279 "\n\t long,"
280 "\n\t long long,"
281 "\n\t unsigned long,"
282 "\n\t unsigned long long,"
283 "\n\t char.",
284 property->getPropertyName(),
285 typeid(*property).name());
286 }
287 }
288 calculateTotalDisplacement(vec_vec_fracture_nodes.size(),
289 vec_junction_nodeID_matIDs.size());
290}
291
292template <typename T>
294 MeshLib::PropertyVector<T> const& property)
295{
296 auto const item_type = property.getMeshItemType();
297 auto const n_src_comp = property.getNumberOfGlobalComponents();
298 // convert 2D vector to 3D. Otherwise Paraview Calculator filter does
299 // not recognize it as a vector
300 auto const n_dest_comp = (n_src_comp == 2) ? 3 : n_src_comp;
301
302 auto new_property = MeshLib::getOrCreateMeshProperty<T>(
303 *_output_mesh, property.getPropertyName(), item_type, n_dest_comp);
304
305 if (item_type == MeshLib::MeshItemType::Node)
306 {
307 assert(new_property->size() ==
308 _output_mesh->getNumberOfNodes() * n_dest_comp);
309 }
310 else if (item_type == MeshLib::MeshItemType::Cell)
311 {
312 assert(new_property->size() ==
313 _output_mesh->getNumberOfElements() * n_dest_comp);
314 }
315 else
316 {
317 WARN(
318 "Property '{:s}' cannot be created because its mesh item type "
319 "'{:s}' is not supported.",
320 property.getPropertyName(), toString(item_type));
321 _output_mesh->getProperties().removePropertyVector(
322 std::string(new_property->getPropertyName()));
323 return nullptr;
324 }
325 return new_property;
326}
327
328template <typename T>
330 MeshLib::PropertyVector<T> const& source_property,
331 MeshLib::PropertyVector<T>* const destination_property)
332{
333 if (destination_property == nullptr)
334 {
335 // skip the copy, because the destination wasn't created.
336 return;
337 }
338
339 auto const item_type = source_property.getMeshItemType();
340 if (item_type == MeshLib::MeshItemType::Node)
341 {
342 auto const n_src_comp = source_property.getNumberOfGlobalComponents();
343 auto const n_dest_comp =
344 destination_property->getNumberOfGlobalComponents();
345 // copy existing
346 for (unsigned i = 0; i < _org_mesh.getNumberOfNodes(); i++)
347 {
348 auto last = std::copy_n(&source_property[i * n_src_comp],
349 n_src_comp,
350 &(*destination_property)[i * n_dest_comp]);
351 // set zero for components not existing in the original
352 std::fill_n(last, n_dest_comp - n_src_comp, T{0});
353 }
354 // copy duplicated
355 for (auto itr : _map_dup_newNodeIDs)
356 {
357 for (unsigned k = 0; k < itr.second.size(); k++)
358 {
359 std::copy_n(
360 &(*destination_property)[itr.first * n_dest_comp],
361 n_dest_comp,
362 &(*destination_property)[itr.second[k] * n_dest_comp]);
363 }
364 }
365 }
366 else if (item_type == MeshLib::MeshItemType::Cell)
367 {
368 assert(source_property.size() == destination_property->size());
369 std::copy(source_property.begin(), source_property.end(),
370 destination_property->begin());
371 }
372 else
373 {
374 OGS_FATAL(
375 "Property '{:s}' values cannot be copied because its mesh item "
376 "type '{:s}' is not supported. Unexpected error, because the "
377 "destination property was created.",
378 source_property.getPropertyName(), toString(item_type));
379 }
380}
381
382void PostProcessTool::calculateTotalDisplacement(unsigned const n_fractures,
383 unsigned const n_junctions)
384{
385 auto const& u = *_output_mesh->getProperties().getPropertyVector<double>(
386 "displacement");
387 auto const n_u_comp = u.getNumberOfGlobalComponents();
388 assert(u.size() == _output_mesh->getNodes().size() * 3);
389 auto& total_u =
390 *_output_mesh->getProperties().createNewPropertyVector<double>(
391 "u", MeshLib::MeshItemType::Node, n_u_comp);
392 total_u.resize(u.size());
393 std::copy(cbegin(u), cend(u), begin(total_u));
394
395 for (unsigned enrich_id = 0; enrich_id < n_fractures + n_junctions;
396 enrich_id++)
397 {
398 // nodal value of levelset
399 std::vector<double> nodal_levelset(
400 _output_mesh->getNodes().size(),
401 std::numeric_limits<double>::quiet_NaN());
402
403 auto const& ele_levelset =
404 *_output_mesh->getProperties().getPropertyVector<double>(
405 "levelset" + std::to_string(enrich_id + 1));
406 for (MeshLib::Element const* e : _output_mesh->getElements())
407 {
408 if (e->getDimension() != _output_mesh->getDimension())
409 {
410 continue;
411 }
412 const double e_levelset = ele_levelset[e->getID()];
413
414 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
415 {
416 nodal_levelset[getNodeIndex(*e, i)] = e_levelset;
417 }
418 }
419
420 // update total displacements
421 auto const& g =
422 *_output_mesh->getProperties().getPropertyVector<double>(
423 "displacement_jump" + std::to_string(enrich_id + 1));
424 for (unsigned i = 0; i < _output_mesh->getNodes().size(); i++)
425 {
426 for (int j = 0; j < n_u_comp; j++)
427 {
428 total_u[i * n_u_comp + j] +=
429 nodal_levelset[i] * g[i * n_u_comp + j];
430 }
431 }
432 }
433}
434
435} // namespace LIE
436} // namespace ProcessLib
Definition of Duplicate functions.
Definition of the Element class.
#define OGS_FATAL(...)
Definition Error.h:26
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of the Node class.
virtual unsigned getNumberOfNodes() const =0
virtual void setNode(unsigned idx, Node *node)=0
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition Mesh.h:106
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:109
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
Definition Mesh.h:88
const Node * getNode(std::size_t idx) const
Get the node with the given index.
Definition Mesh.h:91
Properties & getProperties()
Definition Mesh.h:134
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:103
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition Mesh.h:100
bool hasPropertyVector(std::string_view name) const
PropertyVector< T > const * getPropertyVector(std::string_view name) const
MeshItemType getMeshItemType() const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const
std::size_t size() const
void copyPropertyValues(MeshLib::PropertyVector< T > const &source_property, MeshLib::PropertyVector< T > *const destination_property)
MeshLib::Mesh const & _org_mesh
Definition PostUtils.h:57
std::map< std::size_t, std::vector< std::size_t > > _map_dup_newNodeIDs
Definition PostUtils.h:59
void calculateTotalDisplacement(unsigned const n_fractures, unsigned const n_junctions)
MeshLib::PropertyVector< T > * createProperty(MeshLib::PropertyVector< T > const &property)
std::unique_ptr< MeshLib::Mesh > _output_mesh
Definition PostUtils.h:58
PostProcessTool(MeshLib::Mesh const &org_mesh, std::vector< int > const &vec_fracture_mat_IDs, std::vector< std::vector< MeshLib::Node * > > const &vec_vec_fracture_nodes, std::vector< std::vector< MeshLib::Element * > > const &vec_vec_fracture_matrix_elements, std::vector< std::pair< std::size_t, std::vector< int > > > const &vec_branch_nodeID_matIDs, std::vector< std::pair< std::size_t, std::vector< int > > > const &vec_junction_nodeID_matIDs)
Definition PostUtils.cpp:45
std::size_t findIndex(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:238
std::optional< typename Container::value_type > findFirstNotEqualElement(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:222
std::vector< Node * > copyNodeVector(const std::vector< Node * > &nodes)
Creates a deep copy of a Node vector.
std::vector< Element * > copyElementVector(std::vector< Element * > const &elements, std::vector< Node * > const &new_nodes, std::vector< std::size_t > const *const node_id_map)
bool includesNodeID(std::vector< MeshLib::Node * > const &vec_nodes, std::size_t node_id)
Definition PostUtils.cpp:23
std::vector< int > const & getMaterialIdsForNode(std::vector< std::pair< std::size_t, std::vector< int > > > const &vec_nodeID_matIDs, std::size_t nodeID)
Definition PostUtils.cpp:31