OGS 6.3.0-179-g962fdcd4e.dirty.20200403132553
Mesh.cpp
Go to the documentation of this file.
1 
15 #include "Mesh.h"
16 
17 #include <memory>
18 #include <unordered_map>
19 #include <utility>
20 
21 #include "BaseLib/RunTime.h"
22 
23 #include "Elements/Element.h"
24 #include "Elements/Tri.h"
25 #include "Elements/Quad.h"
26 #include "Elements/Tet.h"
27 #include "Elements/Hex.h"
28 #include "Elements/Pyramid.h"
29 #include "Elements/Prism.h"
30 
31 namespace MeshLib
32 {
33 Mesh::Mesh(std::string name,
34  std::vector<Node*>
35  nodes,
36  std::vector<Element*>
37  elements,
38  Properties const& properties,
39  const std::size_t n_base_nodes)
40  : _id(_counter_value - 1),
41  _mesh_dimension(0),
42  _edge_length(std::numeric_limits<double>::max(), 0),
43  _node_distance(std::numeric_limits<double>::max(), 0),
44  _name(std::move(name)),
45  _nodes(std::move(nodes)),
46  _elements(std::move(elements)),
47  _n_base_nodes(n_base_nodes),
48  _properties(properties)
49 {
50  assert(_n_base_nodes <= _nodes.size());
51  this->resetNodeIDs();
52  this->resetElementIDs();
53  if (_n_base_nodes == 0)
54  {
56  }
57  if ((_n_base_nodes == 0 && hasNonlinearElement()) || isNonlinear())
58  {
59  this->checkNonlinearNodeIDs();
60  }
61  this->setDimension();
64  this->setElementNeighbors();
65 
66  this->calcEdgeLengthRange();
67 }
68 
69 Mesh::Mesh(const Mesh &mesh)
71  _edge_length(mesh._edge_length.first, mesh._edge_length.second),
72  _node_distance(mesh._node_distance.first, mesh._node_distance.second),
76 {
77  const std::vector<Node*>& nodes (mesh.getNodes());
78  const std::size_t nNodes (nodes.size());
79  for (unsigned i = 0; i < nNodes; ++i)
80  {
81  _nodes[i] = new Node(*nodes[i]);
82  }
83 
84  const std::vector<Element*>& elements (mesh.getElements());
85  const std::size_t nElements (elements.size());
86  for (unsigned i=0; i<nElements; ++i)
87  {
88  const std::size_t nElemNodes = elements[i]->getNumberOfNodes();
89  _elements[i] = elements[i]->clone();
90  for (unsigned j = 0; j < nElemNodes; ++j)
91  {
92  _elements[i]->_nodes[j] = _nodes[elements[i]->getNode(j)->getID()];
93  }
94  }
95 
96  if (_mesh_dimension == 0)
97  {
98  this->setDimension();
99  }
101  //this->setNodesConnectedByElements();
102  this->setElementNeighbors();
103 }
104 
106 {
107  const std::size_t nElements (_elements.size());
108  for (std::size_t i = 0; i < nElements; ++i)
109  {
110  delete _elements[i];
111  }
112 
113  const std::size_t nNodes (_nodes.size());
114  for (std::size_t i = 0; i < nNodes; ++i)
115  {
116  delete _nodes[i];
117  }
118 }
119 
121 {
122  _elements.push_back(elem);
123 
124  // add element information to nodes
125  unsigned nNodes (elem->getNumberOfNodes());
126  for (unsigned i = 0; i < nNodes; ++i)
127  {
128  elem->_nodes[i]->addElement(elem);
129  }
130 }
131 
133 {
134  const std::size_t nNodes(_nodes.size());
135  for (std::size_t i = 0; i < nNodes; ++i)
136  {
137  _nodes[i]->setID(i);
138  }
139 }
140 
142 {
143  std::size_t max_basenode_ID = 0;
144  for (Element const* e : _elements)
145  {
146  for (std::size_t i = 0; i < e->getNumberOfBaseNodes(); i++)
147  {
148  max_basenode_ID = std::max(max_basenode_ID, e->getNodeIndex(i));
149  }
150  }
151  _n_base_nodes = max_basenode_ID + 1;
152 }
153 
155 {
156  const std::size_t nElements (this->_elements.size());
157  for (unsigned i = 0; i < nElements; ++i)
158  {
159  _elements[i]->setID(i);
160  }
161 }
162 
164 {
165  const std::size_t nElements (_elements.size());
166  for (unsigned i = 0; i < nElements; ++i)
167  {
169  {
170  _mesh_dimension = _elements[i]->getDimension();
171  }
172  }
173 }
174 
176 {
177  for (auto& element : _elements)
178  {
179  const unsigned nNodes(element->getNumberOfNodes());
180  for (unsigned j = 0; j < nNodes; ++j)
181  {
182  element->_nodes[j]->addElement(element);
183  }
184  }
185 }
186 
188 {
189  this->_edge_length.first = std::numeric_limits<double>::max();
190  this->_edge_length.second = 0;
191  double min_length(0);
192  double max_length(0);
193  const std::size_t nElems (this->getNumberOfElements());
194  for (std::size_t i=0; i<nElems; ++i)
195  {
196  _elements[i]->computeSqrEdgeLengthRange(min_length, max_length);
197  this->_edge_length.first = std::min(this->_edge_length.first, min_length);
198  this->_edge_length.second = std::max(this->_edge_length.second, max_length);
199  }
200  this->_edge_length.first = sqrt(this->_edge_length.first);
201  this->_edge_length.second = sqrt(this->_edge_length.second);
202 }
203 
205 {
206  std::vector<Element*> neighbors;
207  for (auto element : _elements)
208  {
209  // create vector with all elements connected to current element (includes lots of doubles!)
210  const std::size_t nNodes (element->getNumberOfBaseNodes());
211  for (unsigned n(0); n<nNodes; ++n)
212  {
213  std::vector<Element*> const& conn_elems ((element->getNode(n)->getElements()));
214  neighbors.insert(neighbors.end(), conn_elems.begin(), conn_elems.end());
215  }
216  std::sort(neighbors.begin(), neighbors.end());
217  auto const neighbors_new_end = std::unique(neighbors.begin(), neighbors.end());
218 
219  for (auto neighbor = neighbors.begin(); neighbor != neighbors_new_end; ++neighbor)
220  {
221  boost::optional<unsigned> const opposite_face_id = element->addNeighbor(*neighbor);
222  if (opposite_face_id)
223  {
224  (*neighbor)->setNeighbor(element, *opposite_face_id);
225  }
226  }
227  neighbors.clear();
228  }
229 }
230 
232 {
233  // Allocate temporary space for adjacent nodes.
234  std::vector<Node*> adjacent_nodes;
235  for (Node* const node : _nodes)
236  {
237  adjacent_nodes.clear();
238 
239  // Get all elements, to which this node is connected.
240  std::vector<Element*> const& conn_elems = node->getElements();
241 
242  // And collect all elements' nodes.
243  for (Element const* const element : conn_elems)
244  {
245  Node* const* const single_elem_nodes = element->getNodes();
246  std::size_t const nnodes = element->getNumberOfNodes();
247  for (std::size_t n = 0; n < nnodes; n++)
248  {
249  adjacent_nodes.push_back(single_elem_nodes[n]);
250  }
251  }
252 
253  // Make nodes unique and sorted by their ids.
254  // This relies on the node's id being equivalent to it's address.
255  std::sort(adjacent_nodes.begin(), adjacent_nodes.end(),
256  [](Node* a, Node* b) { return a->getID() < b->getID(); });
257  auto const last = std::unique(adjacent_nodes.begin(), adjacent_nodes.end());
258  adjacent_nodes.erase(last, adjacent_nodes.end());
259 
260  node->setConnectedNodes(adjacent_nodes);
261  }
262 }
263 
265 {
266  for (MeshLib::Element const* e : _elements)
267  {
268  for (unsigned i=e->getNumberOfBaseNodes(); i<e->getNumberOfNodes(); i++)
269  {
270  if (e->getNodeIndex(i) >= getNumberOfBaseNodes())
271  {
272  continue;
273  }
274 
275  WARN(
276  "Found a nonlinear node whose ID (%d) is smaller than the "
277  "number of base node IDs (%d). Some functions may not work "
278  "properly.",
279  e->getNodeIndex(i), getNumberOfBaseNodes());
280  return;
281  }
282  }
283 }
284 
286 {
287  return std::any_of(std::begin(_elements), std::end(_elements),
288  [](Element const* const e) {
289  return e->getNumberOfNodes() != e->getNumberOfBaseNodes();
290  });
291 }
292 
294  std::string const& property_name,
295  double factor)
296 {
297  if (!mesh.getProperties().existsPropertyVector<double>(property_name))
298  {
299  WARN("Did not find PropertyVector '%s' for scaling.",
300  property_name.c_str());
301  return;
302  }
303  for (auto& v :
304  *mesh.getProperties().getPropertyVector<double>(property_name))
305  {
306  v *= factor;
307  }
308 }
309 
311 {
312  auto const& properties = mesh.getProperties();
313  return properties.existsPropertyVector<int>("MaterialIDs",
315  ? properties.getPropertyVector<int>(
316  "MaterialIDs", MeshLib::MeshItemType::Cell, 1)
317  : nullptr;
318 }
319 
320 std::unique_ptr<MeshLib::Mesh> createMeshFromElementSelection(
321  std::string mesh_name, std::vector<MeshLib::Element*> const& elements)
322 {
323  DBUG("Found %d elements in the mesh", elements.size());
324 
325  // Store bulk element ids for each of the new elements.
326  std::vector<std::size_t> bulk_element_ids;
327  bulk_element_ids.reserve(elements.size());
328  std::transform(begin(elements), end(elements),
329  std::back_inserter(bulk_element_ids),
330  [&](auto const& e) { return e->getID(); });
331 
332  // original node pointers to newly created nodes.
333  std::unordered_map<const MeshLib::Node*, MeshLib::Node*> nodes_map;
334  nodes_map.reserve(
335  elements.size()); // There will be at least one node per element.
336 
337  for (auto& e : elements)
338  {
339  // For each node find a cloned node in map or create if there is none.
340  unsigned const n_nodes = e->getNumberOfNodes();
341  for (unsigned i = 0; i < n_nodes; ++i)
342  {
343  const MeshLib::Node* n = e->getNode(i);
344  auto const it = nodes_map.find(n);
345  if (it == nodes_map.end())
346  {
347  auto new_node_in_map = nodes_map[n] = new MeshLib::Node(*n);
348  e->setNode(i, new_node_in_map);
349  }
350  else
351  {
352  e->setNode(i, it->second);
353  }
354  }
355  }
356 
357  // Copy the unique nodes pointers.
358  std::vector<MeshLib::Node*> element_nodes;
359  element_nodes.reserve(nodes_map.size());
360  std::transform(begin(nodes_map), end(nodes_map),
361  std::back_inserter(element_nodes),
362  [](auto const& pair) { return pair.second; });
363 
364  // Store bulk node ids for each of the new nodes.
365  std::vector<std::size_t> bulk_node_ids;
366  bulk_node_ids.reserve(nodes_map.size());
367  std::transform(begin(nodes_map), end(nodes_map),
368  std::back_inserter(bulk_node_ids),
369  [](auto const& pair) { return pair.first->getID(); });
370 
371  auto mesh = std::make_unique<MeshLib::Mesh>(
372  std::move(mesh_name), std::move(element_nodes), std::move(elements));
373  assert(mesh != nullptr);
374 
375  addPropertyToMesh(*mesh, "bulk_element_ids", MeshLib::MeshItemType::Cell, 1,
376  bulk_element_ids);
377  addPropertyToMesh(*mesh, "bulk_node_ids", MeshLib::MeshItemType::Node, 1,
378  bulk_node_ids);
379 
380  return mesh;
381 }
382 } // namespace MeshLib
virtual unsigned getNumberOfBaseNodes() const =0
virtual ~Mesh()
Destructor.
Definition: Mesh.cpp:105
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:96
std::pair< double, double > _edge_length
The minimal and maximal edge length over all elements in the mesh.
Definition: Mesh.h:166
std::string _name
Definition: Mesh.h:169
std::vector< Element * > _elements
Definition: Mesh.h:171
std::size_t getNumberOfBaseNodes() const
Get the number of base nodes.
Definition: Mesh.h:123
void setConnectedNodes(std::vector< Node *> &connected_nodes)
Definition: Node.h:94
Definition of the Tet class.
std::vector< Node * > _nodes
Definition: Mesh.h:170
void setNodesConnectedByElements()
Definition: Mesh.cpp:231
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition: Mesh.h:102
MeshLib::Properties & getProperties()
Definition: Mesh.h:131
Definition of the Mesh class.
void resetNodeIDs()
Resets the IDs of all mesh-nodes to their position in the node vector.
Definition: Mesh.cpp:132
std::size_t getID() const
Definition: Point3dWithID.h:61
void scaleMeshPropertyVector(MeshLib::Mesh &mesh, std::string const &property_name, double factor)
Definition: Mesh.cpp:293
void checkNonlinearNodeIDs() const
Check if all the nonlinear nodes are stored at the end of the node vector.
Definition: Mesh.cpp:264
Definition of the Tri class.
Node ** _nodes
Definition: Element.h:215
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties...
Definition: Properties.h:36
Definition of the RunTime class.
const std::string getName() const
Get name of the mesh.
Definition: Mesh.h:99
std::pair< double, double > _node_distance
The minimal and maximal distance of nodes within an element over all elements in the mesh...
Definition: Mesh.h:168
std::unique_ptr< MeshLib::Mesh > createMeshFromElementSelection(std::string mesh_name, std::vector< MeshLib::Element *> const &elements)
Definition: Mesh.cpp:320
void recalculateMaxBaseNodeId()
Finds the maximum id among all of the base nodes.
Definition: Mesh.cpp:141
void addElement(Element *elem)
Definition: Node.h:87
Definition of the Pyramid class.
std::size_t _n_base_nodes
Definition: Mesh.h:172
std::size_t const _id
Definition: Mesh.h:163
unsigned _mesh_dimension
Definition: Mesh.h:164
Interface for heuristic search length strategy.
Definition: ProjectData.h:30
Properties _properties
Definition: Mesh.h:173
bool hasNonlinearElement() const
Check if the mesh contains any nonlinear element.
Definition: Mesh.cpp:285
bool isNonlinear() const
Return true if the mesh has any nonlinear nodes.
Definition: Mesh.h:129
void calcEdgeLengthRange()
Set the minimum and maximum length over the edges of the mesh.
Definition: Mesh.cpp:187
PropertyVector< int > const * materialIDs(Mesh const &mesh)
Definition: Mesh.cpp:310
PropertyVector< T > const * getPropertyVector(std::string const &name) const
Definition: Properties.h:119
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:105
bool existsPropertyVector(std::string const &name) const
Definition: Properties.h:79
Definition of the Quad class.
void addPropertyToMesh(MeshLib::Mesh &mesh, std::string const &name, MeshLib::MeshItemType item_type, std::size_t number_of_components, std::vector< T > const &values)
Definition: Mesh.h:207
void setElementsConnectedToNodes()
Fills in the neighbor-information for nodes (i.e. which element each node belongs to)...
Definition: Mesh.cpp:175
void setDimension()
Sets the dimension of the mesh.
Definition: Mesh.cpp:163
Mesh(std::string name, std::vector< Node *> nodes, std::vector< Element *> elements, Properties const &properties=Properties(), const std::size_t n_base_nodes=0)
Definition: Mesh.cpp:33
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
Definition: Mesh.h:78
std::size_t getNumberOfElements() const
Get the number of elements.
Definition: Mesh.h:93
virtual unsigned getNumberOfNodes() const =0
Returns the number of all nodes including both linear and nonlinear nodes.
void setElementNeighbors()
Definition: Mesh.cpp:204
Definition of the Element class.
static std::size_t _counter_value
Definition: Counter.h:24
Definition of the Prism class.
Definition of the Hex class.
void addElement(Element *elem)
Add an element to the mesh.
Definition: Mesh.cpp:120
void resetElementIDs()
Resets the IDs of all mesh-elements to their position in the element vector.
Definition: Mesh.cpp:154