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