OGS
ProcessLib::LIE::PostProcessTool Class Referencefinal

Detailed Description

A tool for post-processing results from the LIE approach

The tool creates a new mesh containing duplicated fracture nodes to represent geometric discontinuities in visualization.

Definition at line 24 of file PostUtils.h.

#include <PostUtils.h>

Collaboration diagram for ProcessLib::LIE::PostProcessTool:
[legend]

Public Member Functions

 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)
MeshLib::Mesh const & getOutputMesh () const

Private Member Functions

template<typename T>
MeshLib::PropertyVector< T > * createProperty (MeshLib::PropertyVector< T > const &property)
template<typename T>
void copyPropertyValues (MeshLib::PropertyVector< T > const &source_property, MeshLib::PropertyVector< T > *const destination_property)
void calculateTotalDisplacement (unsigned const n_fractures, unsigned const n_junctions)

Private Attributes

MeshLib::Mesh const & _org_mesh
std::unique_ptr< MeshLib::Mesh_output_mesh
std::map< std::size_t, std::vector< std::size_t > > _map_dup_newNodeIDs

Constructor & Destructor Documentation

◆ PostProcessTool()

ProcessLib::LIE::PostProcessTool::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 at line 40 of file PostUtils.cpp.

50 : _org_mesh(org_mesh)
51{
52 if (!org_mesh.getProperties().hasPropertyVector("displacement") ||
53 !org_mesh.getProperties().hasPropertyVector("displacement_jump1") ||
54 !org_mesh.getProperties().hasPropertyVector("levelset1"))
55 {
56 OGS_FATAL("The given mesh does not have relevant properties");
57 }
58
59 // clone nodes and elements
60 std::vector<MeshLib::Node*> new_nodes(
61 MeshLib::copyNodeVector(org_mesh.getNodes()));
62 std::vector<MeshLib::Element*> new_eles(
63 MeshLib::copyElementVector(org_mesh.getElements(), new_nodes));
64
65 // duplicate fracture nodes (two dup. nodes created at a branch)
66 for (auto const& vec_fracture_nodes : vec_vec_fracture_nodes)
67 {
68 for (auto const* org_node : vec_fracture_nodes)
69 {
70 auto duplicated_node =
71 new MeshLib::Node(org_node->data(), new_nodes.size());
72 new_nodes.push_back(duplicated_node);
73 _map_dup_newNodeIDs[org_node->getID()].push_back(
74 duplicated_node->getID());
75 }
76 }
77 // at a junction, generate one more duplicated node (total 4 nodes)
78 for (auto const& entry : vec_junction_nodeID_matIDs)
79 {
80 auto* org_node = org_mesh.getNode(entry.first);
81 auto duplicated_node =
82 new MeshLib::Node(org_node->data(), new_nodes.size());
83 new_nodes.push_back(duplicated_node);
84 _map_dup_newNodeIDs[org_node->getID()].push_back(
85 duplicated_node->getID());
86 }
87
88 // split elements using the new duplicated nodes
89 for (unsigned fracture_id = 0;
90 fracture_id < vec_vec_fracture_matrix_elements.size();
91 fracture_id++)
92 {
93 auto const frac_matid = vec_fracture_mat_IDs[fracture_id];
94 auto const& vec_fracture_matrix_elements =
95 vec_vec_fracture_matrix_elements[fracture_id];
96 auto const& vec_fracture_nodes = vec_vec_fracture_nodes[fracture_id];
97 auto prop_levelset = org_mesh.getProperties().getPropertyVector<double>(
98 "levelset" + std::to_string(fracture_id + 1));
99 for (auto const* org_e : vec_fracture_matrix_elements)
100 {
101 // only matrix elements
102 if (org_e->getDimension() != org_mesh.getDimension())
103 {
104 continue;
105 }
106
107 auto const eid = org_e->getID();
108 // keep original if the element has levelset<=0
109 if ((*prop_levelset)[eid] <= 0)
110 {
111 continue;
112 }
113
114 // replace fracture nodes with duplicated ones
115 MeshLib::Element* e = new_eles[eid];
116 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
117 {
118 const auto node_id = getNodeIndex(*e, i);
119 if (!includesNodeID(vec_fracture_nodes, node_id))
120 {
121 continue;
122 }
123
124 // list of duplicated node IDs
125 auto itr = _map_dup_newNodeIDs.find(node_id);
126 if (itr == _map_dup_newNodeIDs.end())
127 {
128 continue;
129 }
130 const auto& dup_newNodeIDs = itr->second;
131
132 // choose new node id
133 unsigned new_node_id = 0;
134 if (dup_newNodeIDs.size() == 1)
135 {
136 // non-intersected nodes
137 new_node_id = dup_newNodeIDs[0];
138 }
139 else if (dup_newNodeIDs.size() == 2)
140 {
141 // branch nodes
142 const auto& br_matids = getMaterialIdsForNode(
143 vec_branch_nodeID_matIDs, node_id);
144 auto const frac2_matid = BaseLib::findFirstNotEqualElement(
145 br_matids, frac_matid);
146 assert(frac2_matid);
147 auto const frac2_id =
148 BaseLib::findIndex(vec_fracture_mat_IDs, *frac2_matid);
149 assert(frac2_id != std::numeric_limits<std::size_t>::max());
150 auto prop_levelset2 =
151 org_mesh.getProperties().getPropertyVector<double>(
152 "levelset" + std::to_string(frac2_id + 1));
153 std::size_t pos = 0;
154 if ((*prop_levelset2)[eid] <= 0)
155 {
156 // index of this fracture
157 pos = BaseLib::findIndex(br_matids, frac_matid);
158 }
159 else
160 {
161 // index of the other fracture
162 pos = BaseLib::findIndex(br_matids, *frac2_matid);
163 }
164 assert(pos != std::numeric_limits<std::size_t>::max());
165 new_node_id = dup_newNodeIDs[pos];
166 }
167 else
168 {
169 // junction nodes
170 const auto& jct_matids = getMaterialIdsForNode(
171 vec_junction_nodeID_matIDs, node_id);
172 auto const frac2_matid = BaseLib::findFirstNotEqualElement(
173 jct_matids, frac_matid);
174 assert(frac2_matid);
175 auto const frac2_id =
176 BaseLib::findIndex(vec_fracture_mat_IDs, *frac2_matid);
177 assert(frac2_id != std::numeric_limits<std::size_t>::max());
178 auto prop_levelset2 =
179 org_mesh.getProperties().getPropertyVector<double>(
180 "levelset" + std::to_string(frac2_id + 1));
181
182 //
183 if ((*prop_levelset2)[eid] <= 0)
184 {
185 // index of this frac
186 auto const pos =
187 BaseLib::findIndex(jct_matids, frac_matid);
188 assert(pos != std::numeric_limits<std::size_t>::max());
189 new_node_id = dup_newNodeIDs[pos];
190 }
191 else
192 {
193 // set the last duplicated node
194 new_node_id = dup_newNodeIDs.back();
195 }
196 }
197
198 // replace node
199 e->setNode(i, new_nodes[new_node_id]);
200 }
201 }
202 }
203
204 // new mesh
205 _output_mesh = std::make_unique<MeshLib::Mesh>(org_mesh.getName(),
206 new_nodes, new_eles);
207
208 for (auto [name, property] : _org_mesh.getProperties())
209 {
210 if (auto const* p =
211 dynamic_cast<MeshLib::PropertyVector<double>*>(property))
212 {
214 }
215 else if (auto const* p =
216 dynamic_cast<MeshLib::PropertyVector<float>*>(property))
217 {
219 }
220 else if (auto const* p =
221 dynamic_cast<MeshLib::PropertyVector<int>*>(property))
222 {
224 }
225 else if (auto const* p =
226 dynamic_cast<MeshLib::PropertyVector<unsigned>*>(property))
227 {
229 }
230 else if (auto const* p =
231 dynamic_cast<MeshLib::PropertyVector<long>*>(property))
232 {
234 }
235 else if (auto const* p =
236 dynamic_cast<MeshLib::PropertyVector<long long>*>(
237 property))
238 {
240 }
241 else if (auto const* p =
242 dynamic_cast<MeshLib::PropertyVector<unsigned long>*>(
243 property))
244 {
246 }
247 else if (auto const* p =
248 dynamic_cast<MeshLib::PropertyVector<unsigned long long>*>(
249 property))
250 {
252 }
253 else if (auto const* p =
254 dynamic_cast<MeshLib::PropertyVector<std::size_t>*>(
255 property))
256 {
258 }
259 else if (auto const* p =
260 dynamic_cast<MeshLib::PropertyVector<char>*>(property))
261 {
263 }
264 else
265 {
266 OGS_FATAL(
267 "Mesh property '{:s}' of unhandled data type '{:s}'. Please "
268 "check the data type of the mesh properties. The available "
269 "data types are:"
270 "\n\t double,"
271 "\n\t float,"
272 "\n\t int,"
273 "\n\t unsigned,"
274 "\n\t long,"
275 "\n\t long long,"
276 "\n\t unsigned long,"
277 "\n\t unsigned long long,"
278 "\n\t char.",
279 property->getPropertyName(),
280 BaseLib::typeToString(*property));
281 }
282 }
283 calculateTotalDisplacement(vec_vec_fracture_nodes.size(),
284 vec_junction_nodeID_matIDs.size());
285}
#define OGS_FATAL(...)
Definition Error.h:19
virtual unsigned getNumberOfNodes() const =0
virtual void setNode(unsigned idx, Node *node)=0
void copyPropertyValues(MeshLib::PropertyVector< T > const &source_property, MeshLib::PropertyVector< T > *const destination_property)
MeshLib::Mesh const & _org_mesh
Definition PostUtils.h:51
std::map< std::size_t, std::vector< std::size_t > > _map_dup_newNodeIDs
Definition PostUtils.h:53
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:52
std::size_t findIndex(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:236
std::string typeToString()
std::optional< typename Container::value_type > findFirstNotEqualElement(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:220
std::vector< Node * > copyNodeVector(const std::vector< Node * > &nodes)
Creates a deep copy of a Node vector.
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition Element.cpp:226
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:18
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:26

References _map_dup_newNodeIDs, _org_mesh, _output_mesh, calculateTotalDisplacement(), MeshLib::copyElementVector(), MeshLib::copyNodeVector(), copyPropertyValues(), createProperty(), BaseLib::findFirstNotEqualElement(), BaseLib::findIndex(), MeshLib::Mesh::getDimension(), MeshLib::Mesh::getElements(), MeshLib::Mesh::getName(), MeshLib::Mesh::getNode(), MeshLib::Mesh::getNodes(), MeshLib::Element::getNumberOfNodes(), MeshLib::Mesh::getProperties(), MeshLib::Properties::getPropertyVector(), MeshLib::Properties::hasPropertyVector(), MeshLib::Node, OGS_FATAL, MeshLib::Element::setNode(), and BaseLib::typeToString().

Member Function Documentation

◆ calculateTotalDisplacement()

void ProcessLib::LIE::PostProcessTool::calculateTotalDisplacement ( unsigned const n_fractures,
unsigned const n_junctions )
private

Definition at line 377 of file PostUtils.cpp.

379{
380 auto const& u = *_output_mesh->getProperties().getPropertyVector<double>(
381 "displacement");
382 auto const n_u_comp = u.getNumberOfGlobalComponents();
383 assert(u.size() == _output_mesh->getNodes().size() * 3);
384 auto& total_u =
385 *_output_mesh->getProperties().createNewPropertyVector<double>(
386 "u", MeshLib::MeshItemType::Node, n_u_comp);
387 total_u.resize(u.size());
388 ranges::copy(u, total_u.begin());
389
390 for (unsigned enrich_id = 0; enrich_id < n_fractures + n_junctions;
391 enrich_id++)
392 {
393 // nodal value of levelset
394 std::vector<double> nodal_levelset(
395 _output_mesh->getNodes().size(),
396 std::numeric_limits<double>::quiet_NaN());
397
398 auto const& ele_levelset =
399 *_output_mesh->getProperties().getPropertyVector<double>(
400 "levelset" + std::to_string(enrich_id + 1));
401 for (MeshLib::Element const* e : _output_mesh->getElements())
402 {
403 if (e->getDimension() != _output_mesh->getDimension())
404 {
405 continue;
406 }
407 const double e_levelset = ele_levelset[e->getID()];
408
409 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
410 {
411 nodal_levelset[getNodeIndex(*e, i)] = e_levelset;
412 }
413 }
414
415 // update total displacements
416 auto const& g =
417 *_output_mesh->getProperties().getPropertyVector<double>(
418 "displacement_jump" + std::to_string(enrich_id + 1));
419 for (unsigned i = 0; i < _output_mesh->getNodes().size(); i++)
420 {
421 for (int j = 0; j < n_u_comp; j++)
422 {
423 total_u[i * n_u_comp + j] +=
424 nodal_levelset[i] * g[i * n_u_comp + j];
425 }
426 }
427 }
428}
constexpr int size(int const displacement_dim)
Vectorized tensor size for given displacement dimension.

References _output_mesh, and MeshLib::Node.

Referenced by PostProcessTool().

◆ copyPropertyValues()

template<typename T>
void ProcessLib::LIE::PostProcessTool::copyPropertyValues ( MeshLib::PropertyVector< T > const & source_property,
MeshLib::PropertyVector< T > *const destination_property )
private

Definition at line 324 of file PostUtils.cpp.

327{
328 if (destination_property == nullptr)
329 {
330 // skip the copy, because the destination wasn't created.
331 return;
332 }
333
334 auto const item_type = source_property.getMeshItemType();
335 if (item_type == MeshLib::MeshItemType::Node)
336 {
337 auto const n_src_comp = source_property.getNumberOfGlobalComponents();
338 auto const n_dest_comp =
339 destination_property->getNumberOfGlobalComponents();
340 // copy existing
341 for (unsigned i = 0; i < _org_mesh.getNumberOfNodes(); i++)
342 {
343 auto last = std::copy_n(&source_property[i * n_src_comp],
344 n_src_comp,
345 &(*destination_property)[i * n_dest_comp]);
346 // set zero for components not existing in the original
347 std::fill_n(last, n_dest_comp - n_src_comp, T{0});
348 }
349 // copy duplicated
350 for (auto itr : _map_dup_newNodeIDs)
351 {
352 for (unsigned k = 0; k < itr.second.size(); k++)
353 {
354 std::copy_n(
355 &(*destination_property)[itr.first * n_dest_comp],
356 n_dest_comp,
357 &(*destination_property)[itr.second[k] * n_dest_comp]);
358 }
359 }
360 }
361 else if (item_type == MeshLib::MeshItemType::Cell)
362 {
363 assert(source_property.size() == destination_property->size());
364 std::copy(source_property.begin(), source_property.end(),
365 destination_property->begin());
366 }
367 else
368 {
369 OGS_FATAL(
370 "Property '{:s}' values cannot be copied because its mesh item "
371 "type '{:s}' is not supported. Unexpected error, because the "
372 "destination property was created.",
373 source_property.getPropertyName(), toString(item_type));
374 }
375}
MeshItemType getMeshItemType() const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const
constexpr PROP_VAL_TYPE * begin()
constexpr std::size_t size() const
constexpr PROP_VAL_TYPE * end()
const char * toString(mgis::behaviour::Behaviour::Kinematic kin)

References _map_dup_newNodeIDs, _org_mesh, MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::Cell, MeshLib::PropertyVector< PROP_VAL_TYPE >::end(), MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), MeshLib::Node, OGS_FATAL, and MeshLib::PropertyVector< PROP_VAL_TYPE >::size().

Referenced by PostProcessTool().

◆ createProperty()

template<typename T>
MeshLib::PropertyVector< T > * ProcessLib::LIE::PostProcessTool::createProperty ( MeshLib::PropertyVector< T > const & property)
private

Definition at line 288 of file PostUtils.cpp.

290{
291 auto const item_type = property.getMeshItemType();
292 auto const n_src_comp = property.getNumberOfGlobalComponents();
293 // convert 2D vector to 3D. Otherwise Paraview Calculator filter does
294 // not recognize it as a vector
295 auto const n_dest_comp = (n_src_comp == 2) ? 3 : n_src_comp;
296
297 auto new_property = MeshLib::getOrCreateMeshProperty<T>(
298 *_output_mesh, property.getPropertyName(), item_type, n_dest_comp);
299
300 if (item_type == MeshLib::MeshItemType::Node)
301 {
302 assert(new_property->size() ==
303 _output_mesh->getNumberOfNodes() * n_dest_comp);
304 }
305 else if (item_type == MeshLib::MeshItemType::Cell)
306 {
307 assert(new_property->size() ==
308 _output_mesh->getNumberOfElements() * n_dest_comp);
309 }
310 else
311 {
312 WARN(
313 "Property '{:s}' cannot be created because its mesh item type "
314 "'{:s}' is not supported.",
315 property.getPropertyName(), toString(item_type));
316 _output_mesh->getProperties().removePropertyVector(
317 std::string(new_property->getPropertyName()));
318 return nullptr;
319 }
320 return new_property;
321}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
PropertyVector< T > * getOrCreateMeshProperty(Mesh &mesh, std::string const &property_name, MeshItemType const item_type, int const number_of_components)

References _output_mesh, MeshLib::Cell, MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::getOrCreateMeshProperty(), MeshLib::PropertyVectorBase::getPropertyName(), MeshLib::Node, and WARN().

Referenced by PostProcessTool().

◆ getOutputMesh()

MeshLib::Mesh const & ProcessLib::LIE::PostProcessTool::getOutputMesh ( ) const
inline

Definition at line 38 of file PostUtils.h.

38{ return *_output_mesh; }

References _output_mesh.

Referenced by anonymous_namespace{postLIE.cpp}::postVTU().

Member Data Documentation

◆ _map_dup_newNodeIDs

std::map<std::size_t, std::vector<std::size_t> > ProcessLib::LIE::PostProcessTool::_map_dup_newNodeIDs
private

Definition at line 53 of file PostUtils.h.

Referenced by PostProcessTool(), and copyPropertyValues().

◆ _org_mesh

MeshLib::Mesh const& ProcessLib::LIE::PostProcessTool::_org_mesh
private

Definition at line 51 of file PostUtils.h.

Referenced by PostProcessTool(), and copyPropertyValues().

◆ _output_mesh

std::unique_ptr<MeshLib::Mesh> ProcessLib::LIE::PostProcessTool::_output_mesh
private

The documentation for this class was generated from the following files: