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 30 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 45 of file PostUtils.cpp.

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(
66 MeshLib::copyNodeVector(org_mesh.getNodes()));
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}
#define OGS_FATAL(...)
Definition Error.h:26
virtual unsigned getNumberOfNodes() const =0
virtual void setNode(unsigned idx, Node *node)=0
Properties & getProperties()
Definition Mesh.h:134
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
std::size_t findIndex(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:239
std::optional< typename Container::value_type > findFirstNotEqualElement(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:223
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:219
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

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, and MeshLib::Element::setNode().

Member Function Documentation

◆ calculateTotalDisplacement()

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

Definition at line 382 of file PostUtils.cpp.

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}
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 329 of file PostUtils.cpp.

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}
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition Mesh.h:100
MeshItemType getMeshItemType() const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const
std::size_t size() const
const char * toString(mgis::behaviour::Behaviour::Kinematic kin)

References _map_dup_newNodeIDs, _org_mesh, MeshLib::Cell, MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::Mesh::getNumberOfNodes(), 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 293 of file PostUtils.cpp.

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}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
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 44 of file PostUtils.h.

44{ 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 59 of file PostUtils.h.

Referenced by PostProcessTool(), and copyPropertyValues().

◆ _org_mesh

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

Definition at line 57 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: