OGS
QuadraticMeshGenerator.cpp
Go to the documentation of this file.
1 
10 #include "QuadraticMeshGenerator.h"
11 
12 #include <set>
13 
15 #include "MeshLib/Elements/Hex.h"
16 #include "MeshLib/Elements/Line.h"
17 #include "MeshLib/Elements/Quad.h"
18 #include "MeshLib/Elements/Tet.h"
19 #include "MeshLib/Elements/Tri.h"
20 #include "MeshLib/Mesh.h"
22 #include "MeshLib/Node.h"
23 
26 template <typename QuadraticElement>
27 std::unique_ptr<QuadraticElement> convertLinearToQuadratic(
28  MeshLib::Element const& e)
29 {
30  int const n_all_nodes = QuadraticElement::n_all_nodes;
31  int const n_base_nodes = QuadraticElement::n_base_nodes;
32  assert(n_base_nodes == e.getNumberOfBaseNodes());
33 
34  // Copy base nodes of element to the quadratic element new nodes'.
35  std::array<MeshLib::Node*, n_all_nodes> nodes{};
36  for (int i = 0; i < n_base_nodes; i++)
37  {
38  nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
39  }
40 
41  // For each edge create a middle node.
42  int const number_of_edges = e.getNumberOfEdges();
43  for (int i = 0; i < number_of_edges; i++)
44  {
45  auto const& a = *e.getEdgeNode(i, 0);
46  auto const& b = *e.getEdgeNode(i, 1);
47 
48  nodes[n_base_nodes + i] = new MeshLib::Node(
49  (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
50  }
51 
52  return std::make_unique<QuadraticElement>(nodes, e.getID());
53 }
54 
56 template <>
57 std::unique_ptr<MeshLib::Quad9> convertLinearToQuadratic<MeshLib::Quad9>(
58  MeshLib::Element const& e)
59 {
60  int const n_all_nodes = MeshLib::Quad9::n_all_nodes;
61  int const n_base_nodes = MeshLib::Quad9::n_base_nodes;
62  assert(n_base_nodes == e.getNumberOfBaseNodes());
63 
64  // Copy base nodes of element to the quadratic element new nodes'.
65  std::array<MeshLib::Node*, n_all_nodes> nodes{};
66  for (int i = 0; i < n_base_nodes; i++)
67  {
68  nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
69  }
70 
71  // For each edge create a middle node.
72  int const number_of_edges = e.getNumberOfEdges();
73  for (int i = 0; i < number_of_edges; i++)
74  {
75  auto const& a = *e.getEdgeNode(i, 0);
76  auto const& b = *e.getEdgeNode(i, 1);
77 
78  nodes[n_base_nodes + i] = new MeshLib::Node(
79  (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
80  }
81 
82  // Compute the centre point coordinates.
83  auto* centre_node = new MeshLib::Node(0, 0, 0);
84  for (int i = 0; i < n_base_nodes; i++)
85  {
86  for (int d = 0; d < 3; d++)
87  {
88  (*centre_node)[d] += (*nodes[i])[d] / n_base_nodes;
89  }
90  }
91  nodes[n_all_nodes - 1] = centre_node;
92 
93  return std::make_unique<MeshLib::Quad9>(nodes, e.getID());
94 }
95 
97 std::unique_ptr<MeshLib::Element> createQuadraticElement(
98  MeshLib::Element const& e, bool const add_centre_node)
99 {
101  {
102  return convertLinearToQuadratic<MeshLib::Line3>(e);
103  }
105  {
106  return convertLinearToQuadratic<MeshLib::Tri6>(e);
107  }
109  {
110  return convertLinearToQuadratic<MeshLib::Tet10>(e);
111  }
113  {
114  if (add_centre_node)
115  {
116  return convertLinearToQuadratic<MeshLib::Quad9>(e);
117  }
118  return convertLinearToQuadratic<MeshLib::Quad8>(e);
119  }
121  {
122  return convertLinearToQuadratic<MeshLib::Hex20>(e);
123  }
124 
125  OGS_FATAL("Mesh element type {:s} is not supported",
127 }
128 
130 {
132  {
133  return *a < *b;
134  }
135 };
136 
137 namespace MeshLib
138 {
139 std::unique_ptr<Mesh> createQuadraticOrderMesh(Mesh const& linear_mesh,
140  bool const add_centre_node)
141 {
142  // Clone the linear mesh nodes.
143  auto quadratic_mesh_nodes = MeshLib::copyNodeVector(linear_mesh.getNodes());
144 
145  // Temporary container for unique quadratic nodes with O(log(n)) search.
146  std::set<MeshLib::Node*, nodeByCoordinatesComparator> unique_nodes;
147 
148  // Create new elements with the quadratic nodes
149  std::vector<MeshLib::Element*> quadratic_elements;
150  auto const& linear_mesh_elements = linear_mesh.getElements();
151  for (MeshLib::Element const* e : linear_mesh_elements)
152  {
153  auto quadratic_element = createQuadraticElement(*e, add_centre_node);
154 
155  // Replace the base nodes with cloned linear nodes.
156  int const number_base_nodes = quadratic_element->getNumberOfBaseNodes();
157  for (int i = 0; i < number_base_nodes; ++i)
158  {
159  quadratic_element->setNode(
160  i, quadratic_mesh_nodes[getNodeIndex(*quadratic_element, i)]);
161  }
162 
163  // Make the new (middle-edge) nodes unique.
164  int const number_all_nodes = quadratic_element->getNumberOfNodes();
165  for (int i = number_base_nodes; i < number_all_nodes; ++i)
166  {
167  Node* original_node =
168  const_cast<Node*>(quadratic_element->getNode(i));
169 
170  auto it = unique_nodes.insert(original_node);
171  if (!it.second) // same node was already inserted before, no
172  // insertion
173  {
174  // Replace the element's node with the unique node.
175  quadratic_element->setNode(i, *it.first);
176  // And delete the original node
177  delete original_node;
178  }
179  }
180 
181  quadratic_elements.push_back(quadratic_element.release());
182  }
183 
184  // Add the unique quadratic nodes to the cloned linear nodes.
185  quadratic_mesh_nodes.reserve(linear_mesh.getNodes().size() +
186  unique_nodes.size());
187  std::copy(unique_nodes.begin(), unique_nodes.end(),
188  std::back_inserter(quadratic_mesh_nodes));
189 
190  return std::make_unique<MeshLib::Mesh>(
191  linear_mesh.getName(), quadratic_mesh_nodes, quadratic_elements,
192  linear_mesh.getProperties().excludeCopyProperties(
193  std::vector<MeshLib::MeshItemType>(1,
195 }
196 
197 } // namespace MeshLib
Definition of Duplicate functions.
Definition of the Element class.
#define OGS_FATAL(...)
Definition: Error.h:26
Definition of the Hex class.
Definition of the Line class.
Definition of the Mesh class.
Definition of the Node class.
Definition of the Quad class.
std::unique_ptr< MeshLib::Element > createQuadraticElement(MeshLib::Element const &e, bool const add_centre_node)
Return a new quadratic element corresponding to the linear element's type.
std::unique_ptr< QuadraticElement > convertLinearToQuadratic(MeshLib::Element const &e)
Definition of the Tet class.
Definition of the Tri class.
virtual CellType getCellType() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual Node * getEdgeNode(unsigned edge_id, unsigned node_id) const =0
Return a specific edge node.
virtual unsigned getNumberOfEdges() const =0
Get the number of edges for this element.
virtual std::size_t getID() const final
Returns the ID of the element.
Definition: Element.h:82
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition: Mesh.h:95
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
Properties excludeCopyProperties(std::vector< std::size_t > const &exclude_elem_ids, std::vector< std::size_t > const &exclude_node_ids) const
Definition: Properties.cpp:58
static const unsigned n_all_nodes
Constant: The number of all nodes for this element.
static const unsigned n_base_nodes
Constant: The number of base nodes for this element.
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::string CellType2String(const CellType t)
Given a MeshElemType this returns the appropriate string.
Definition: MeshEnums.cpp:157
std::unique_ptr< Mesh > createQuadraticOrderMesh(Mesh const &linear_mesh, bool const add_centre_node)
bool operator()(MeshLib::Node *a, MeshLib::Node *b) const