OGS
AddLayerToMesh.cpp
Go to the documentation of this file.
1 
13 #include "AddLayerToMesh.h"
14 
15 #include <algorithm>
16 #include <map>
17 #include <memory>
18 #include <numeric>
19 #include <vector>
20 
21 #include "BaseLib/Logging.h"
23 #include "MeshLib/Mesh.h"
27 #include "MeshLib/Node.h"
28 
29 namespace MeshLib
30 {
45  std::vector<MeshLib::Node*> const& subsfc_nodes,
46  MeshLib::Element const& sfc_elem,
47  MeshLib::PropertyVector<std::size_t> const& sfc_to_subsfc_id_map,
48  std::map<std::size_t, std::size_t> const& subsfc_sfc_id_map)
49 {
50  if (sfc_elem.getDimension() > 2)
51  {
52  return nullptr;
53  }
54 
55  const unsigned nElemNodes(sfc_elem.getNumberOfBaseNodes());
56  auto new_nodes = std::unique_ptr<MeshLib::Node* []> {
57  new MeshLib::Node*[2 * nElemNodes]
58  };
59 
60  for (unsigned j = 0; j < nElemNodes; ++j)
61  {
62  std::size_t const subsfc_id(
63  sfc_to_subsfc_id_map[sfc_elem.getNode(j)->getID()]);
64  new_nodes[j] = subsfc_nodes[subsfc_id];
65  std::size_t new_idx = (nElemNodes == 2) ? (3 - j) : (nElemNodes + j);
66  new_nodes[new_idx] = subsfc_nodes[subsfc_sfc_id_map.at(subsfc_id)];
67  }
68 
69  if (sfc_elem.getGeomType() == MeshLib::MeshElemType::LINE)
70  {
71  return new MeshLib::Quad(new_nodes.release());
72  }
74  {
75  return new MeshLib::Prism(new_nodes.release());
76  }
77  if (sfc_elem.getGeomType() == MeshLib::MeshElemType::QUAD)
78  {
79  return new MeshLib::Hex(new_nodes.release());
80  }
81 
82  return nullptr;
83 }
84 
85 MeshLib::Mesh* addLayerToMesh(MeshLib::Mesh const& mesh, double thickness,
86  std::string const& name, bool on_top,
87  bool copy_material_ids)
88 {
89  INFO("Extracting top surface of mesh '{:s}' ... ", mesh.getName());
90  double const flag = on_top ? -1.0 : 1.0;
91  Eigen::Vector3d const dir({0, 0, flag});
92  double const angle(90);
93  std::unique_ptr<MeshLib::Mesh> sfc_mesh(nullptr);
94 
95  std::string const prop_name("bulk_node_ids");
96 
97  if (mesh.getDimension() == 3)
98  {
100  mesh, dir, angle, prop_name));
101  }
102  else
103  {
104  sfc_mesh = (on_top) ? std::make_unique<MeshLib::Mesh>(mesh)
105  : std::unique_ptr<MeshLib::Mesh>(
107  // add property storing node ids
108  auto* const pv =
109  sfc_mesh->getProperties().createNewPropertyVector<std::size_t>(
110  prop_name, MeshLib::MeshItemType::Node, 1);
111  if (pv)
112  {
113  pv->resize(sfc_mesh->getNumberOfNodes());
114  std::iota(pv->begin(), pv->end(), 0);
115  }
116  else
117  {
118  ERR("Could not create and initialize property '{%s}'.", prop_name);
119  return nullptr;
120  }
121  }
122  INFO("done.");
123 
124  // *** add new surface nodes
125  std::vector<MeshLib::Node*> subsfc_nodes =
127  std::vector<MeshLib::Element*> subsfc_elements =
128  MeshLib::copyElementVector(mesh.getElements(), subsfc_nodes);
129 
130  std::size_t const n_subsfc_nodes(subsfc_nodes.size());
131 
132  std::vector<MeshLib::Node*> const& sfc_nodes(sfc_mesh->getNodes());
133  std::size_t const n_sfc_nodes(sfc_nodes.size());
134 
135  if (!sfc_mesh->getProperties().existsPropertyVector<std::size_t>(prop_name))
136  {
137  ERR("Need subsurface node ids, but the property '{:s}' is not "
138  "available.",
139  prop_name);
140  return nullptr;
141  }
142  // fetch subsurface node ids PropertyVector
143  auto const* const node_id_pv =
144  sfc_mesh->getProperties().getPropertyVector<std::size_t>(prop_name);
145 
146  // *** copy sfc nodes to subsfc mesh node
147  std::map<std::size_t, std::size_t> subsfc_sfc_id_map;
148  for (std::size_t k(0); k < n_sfc_nodes; ++k)
149  {
150  std::size_t const subsfc_id((*node_id_pv)[k]);
151  std::size_t const sfc_id(k + n_subsfc_nodes);
152  subsfc_sfc_id_map.insert(std::make_pair(subsfc_id, sfc_id));
153  MeshLib::Node const& node(*sfc_nodes[k]);
154  subsfc_nodes.push_back(new MeshLib::Node(
155  node[0], node[1], node[2] - (flag * thickness), sfc_id));
156  }
157 
158  // *** insert new layer elements into subsfc_mesh
159  std::vector<MeshLib::Element*> const& sfc_elements(sfc_mesh->getElements());
160  std::size_t const n_sfc_elements(sfc_elements.size());
161  for (std::size_t k(0); k < n_sfc_elements; ++k)
162  {
163  subsfc_elements.push_back(extrudeElement(
164  subsfc_nodes, *sfc_elements[k], *node_id_pv, subsfc_sfc_id_map));
165  }
166 
167  auto new_mesh = new MeshLib::Mesh(name, subsfc_nodes, subsfc_elements);
168 
169  if (!mesh.getProperties().existsPropertyVector<int>("MaterialIDs"))
170  {
171  ERR("Could not copy the property 'MaterialIDs' since the original mesh "
172  "does not contain such a property.");
173  return new_mesh;
174  }
175  auto const* const materials =
176  mesh.getProperties().getPropertyVector<int>("MaterialIDs");
177 
178  auto* const new_materials =
179  new_mesh->getProperties().createNewPropertyVector<int>(
180  "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
181  if (!new_materials)
182  {
183  ERR("Can not set material properties for new layer");
184  return new_mesh;
185  }
186 
187  new_materials->reserve(subsfc_elements.size());
188  std::copy(materials->cbegin(), materials->cend(),
189  std::back_inserter(*new_materials));
190 
191  if (copy_material_ids &&
192  sfc_mesh->getProperties().existsPropertyVector<int>("MaterialIDs"))
193  {
194  auto const& sfc_material_ids =
195  *sfc_mesh->getProperties().getPropertyVector<int>("MaterialIDs");
196  std::copy(sfc_material_ids.cbegin(), sfc_material_ids.cend(),
197  std::back_inserter(*new_materials));
198  }
199  else
200  {
201  int const new_layer_id(
202  *(std::max_element(materials->cbegin(), materials->cend())) + 1);
203  auto const n_new_props(subsfc_elements.size() -
204  mesh.getNumberOfElements());
205  std::fill_n(std::back_inserter(*new_materials), n_new_props,
206  new_layer_id);
207  }
208 
209  return new_mesh;
210 }
211 
212 } // namespace MeshLib
Definition of AddLayerToMesh class.
Definition of Duplicate functions.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Definition of the MeshSurfaceExtraction class.
Definition of the Mesh class.
Definition of the Node class.
std::size_t getID() const
Definition: Point3dWithID.h:62
virtual MeshElemType getGeomType() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
static MeshLib::Mesh * getMeshSurface(const MeshLib::Mesh &subsfc_mesh, Eigen::Vector3d const &dir, double angle, std::string const &subsfc_node_id_prop_name="", std::string const &subsfc_element_id_prop_name="", std::string const &face_id_prop_name="")
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 getNumberOfElements() const
Get the number of elements.
Definition: Mesh.h:86
PropertyVector< T > const * getPropertyVector(std::string const &name) const
bool existsPropertyVector(std::string const &name) const
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.
MeshLib::Element * extrudeElement(std::vector< MeshLib::Node * > const &subsfc_nodes, MeshLib::Element const &sfc_elem, MeshLib::PropertyVector< std::size_t > const &sfc_to_subsfc_id_map, std::map< std::size_t, std::size_t > const &subsfc_sfc_id_map)
TemplateElement< MeshLib::PrismRule6 > Prism
Definition: Prism.h:25
MeshLib::Mesh * addLayerToMesh(MeshLib::Mesh const &mesh, double thickness, std::string const &name, bool on_top, bool copy_material_ids)
std::unique_ptr< Mesh > createFlippedMesh(Mesh const &mesh)
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)
TemplateElement< MeshLib::HexRule8 > Hex
Definition: Hex.h:25
TemplateElement< MeshLib::QuadRule4 > Quad
Definition: Quad.h:28