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"
22#include "FlipElements.h"
24#include "MeshLib/Mesh.h"
25#include "MeshLib/Node.h"
28
29namespace MeshToolsLib
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 =
57 std::unique_ptr<MeshLib::Node*[]>{new MeshLib::Node*[2 * nElemNodes]};
58
59 for (unsigned j = 0; j < nElemNodes; ++j)
60 {
61 std::size_t const subsfc_id(
62 sfc_to_subsfc_id_map[sfc_elem.getNode(j)->getID()]);
63 new_nodes[j] = subsfc_nodes[subsfc_id];
64 std::size_t new_idx = (nElemNodes == 2) ? (3 - j) : (nElemNodes + j);
65 new_nodes[new_idx] = subsfc_nodes[subsfc_sfc_id_map.at(subsfc_id)];
66 }
67
69 {
70 return new MeshLib::Quad(new_nodes.release());
71 }
73 {
74 return new MeshLib::Prism(new_nodes.release());
75 }
77 {
78 return new MeshLib::Hex(new_nodes.release());
79 }
80
81 return nullptr;
82}
83
84MeshLib::Mesh* addLayerToMesh(MeshLib::Mesh const& mesh, double thickness,
85 std::string const& name, bool on_top,
86 bool copy_material_ids)
87{
88 INFO("Extracting top surface of mesh '{:s}' ... ", mesh.getName());
89 double const flag = on_top ? -1.0 : 1.0;
90 Eigen::Vector3d const dir({0, 0, flag});
91 double const angle(90);
92 std::unique_ptr<MeshLib::Mesh> sfc_mesh(nullptr);
93
94 auto const prop_name =
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 '{}'.", 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 true /* compute_element_neighbors */);
169
170 if (!mesh.getProperties().existsPropertyVector<int>("MaterialIDs"))
171 {
172 ERR("Could not copy the property 'MaterialIDs' since the original mesh "
173 "does not contain such a property.");
174 return new_mesh;
175 }
176 auto const* const materials =
177 mesh.getProperties().getPropertyVector<int>("MaterialIDs");
178
179 auto* const new_materials =
180 new_mesh->getProperties().createNewPropertyVector<int>(
181 "MaterialIDs", MeshLib::MeshItemType::Cell, 1);
182 if (!new_materials)
183 {
184 ERR("Can not set material properties for new layer");
185 return new_mesh;
186 }
187
188 new_materials->reserve(subsfc_elements.size());
189 std::copy(materials->cbegin(), materials->cend(),
190 std::back_inserter(*new_materials));
191
192 if (copy_material_ids &&
193 sfc_mesh->getProperties().existsPropertyVector<int>("MaterialIDs"))
194 {
195 auto const& sfc_material_ids =
196 *sfc_mesh->getProperties().getPropertyVector<int>("MaterialIDs");
197 std::copy(sfc_material_ids.cbegin(), sfc_material_ids.cend(),
198 std::back_inserter(*new_materials));
199 }
200 else
201 {
202 int const new_layer_id(
203 *(std::max_element(materials->cbegin(), materials->cend())) + 1);
204 auto const n_new_props(subsfc_elements.size() -
205 mesh.getNumberOfElements());
206 std::fill_n(std::back_inserter(*new_materials), n_new_props,
207 new_layer_id);
208 }
209
210 return new_mesh;
211}
212
213} // namespace MeshToolsLib
Definition of AddLayerToMesh class.
Definition of Duplicate functions.
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
Definition of the MeshSurfaceExtraction class.
Definition of the Mesh class.
Definition of the Node class.
std::size_t getID() const
virtual MeshElemType getGeomType() const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
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
Properties & getProperties()
Definition Mesh.h:134
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:103
std::size_t getNumberOfElements() const
Get the number of elements.
Definition Mesh.h:97
bool existsPropertyVector(std::string_view name) const
PropertyVector< T > const * getPropertyVector(std::string_view name) const
static MeshLib::Mesh * getMeshSurface(const MeshLib::Mesh &subsfc_mesh, Eigen::Vector3d const &dir, double angle, std::string_view subsfc_node_id_prop_name="", std::string_view subsfc_element_id_prop_name="", std::string_view face_id_prop_name="")
std::vector< Node * > copyNodeVector(const std::vector< Node * > &nodes)
Creates a deep copy of a Node vector.
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
Definition Properties.h:188
TemplateElement< MeshLib::QuadRule4 > Quad
Definition Quad.h:28
TemplateElement< MeshLib::PrismRule6 > Prism
Definition Prism.h:25
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
std::unique_ptr< MeshLib::Mesh > createFlippedMesh(MeshLib::Mesh const &mesh)
MeshLib::Mesh * addLayerToMesh(MeshLib::Mesh const &mesh, double thickness, std::string const &name, bool on_top, bool copy_material_ids)
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)