OGS
QuadraticMeshGenerator.cpp
Go to the documentation of this file.
1
11
12#include <set>
13
22#include "MeshLib/Mesh.h"
23#include "MeshLib/Node.h"
25
28template <typename QuadraticElement>
29std::unique_ptr<QuadraticElement> convertLinearToQuadratic(
30 MeshLib::Element const& e)
31{
32 int const n_all_nodes = QuadraticElement::n_all_nodes;
33 int const n_base_nodes = QuadraticElement::n_base_nodes;
34 assert(n_base_nodes == e.getNumberOfBaseNodes());
35
36 // Copy base nodes of element to the quadratic element new nodes'.
37 std::array<MeshLib::Node*, n_all_nodes> nodes{};
38 for (int i = 0; i < n_base_nodes; i++)
39 {
40 nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
41 }
42
43 // For each edge create a middle node.
44 int const number_of_edges = e.getNumberOfEdges();
45 for (int i = 0; i < number_of_edges; i++)
46 {
47 auto const& a = *e.getEdgeNode(i, 0);
48 auto const& b = *e.getEdgeNode(i, 1);
49
50 nodes[n_base_nodes + i] = new MeshLib::Node(
51 (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
52 }
53
54 return std::make_unique<QuadraticElement>(nodes, e.getID());
55}
56
58template <>
59std::unique_ptr<MeshLib::Quad9> convertLinearToQuadratic<MeshLib::Quad9>(
60 MeshLib::Element const& e)
61{
62 int const n_all_nodes = MeshLib::Quad9::n_all_nodes;
63 int const n_base_nodes = MeshLib::Quad9::n_base_nodes;
64 assert(n_base_nodes == e.getNumberOfBaseNodes());
65
66 // Copy base nodes of element to the quadratic element new nodes'.
67 std::array<MeshLib::Node*, n_all_nodes> nodes{};
68 for (int i = 0; i < n_base_nodes; i++)
69 {
70 nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
71 }
72
73 // For each edge create a middle node.
74 int const number_of_edges = e.getNumberOfEdges();
75 for (int i = 0; i < number_of_edges; i++)
76 {
77 auto const& a = *e.getEdgeNode(i, 0);
78 auto const& b = *e.getEdgeNode(i, 1);
79
80 nodes[n_base_nodes + i] = new MeshLib::Node(
81 (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
82 }
83
84 // Compute the centre point coordinates.
85 auto* centre_node = new MeshLib::Node(0, 0, 0);
86 for (int i = 0; i < n_base_nodes; i++)
87 {
88 for (int d = 0; d < 3; d++)
89 {
90 (*centre_node)[d] += (*nodes[i])[d] / n_base_nodes;
91 }
92 }
93 nodes[n_all_nodes - 1] = centre_node;
94
95 return std::make_unique<MeshLib::Quad9>(nodes, e.getID());
96}
97
99template <>
100std::unique_ptr<MeshLib::Prism15> convertLinearToQuadratic<MeshLib::Prism15>(
101 MeshLib::Element const& e)
102{
103 int const n_all_nodes = MeshLib::Prism15::n_all_nodes;
104 int const n_base_nodes = MeshLib::Prism15::n_base_nodes;
105 assert(n_base_nodes == e.getNumberOfBaseNodes());
106
107 // Copy base nodes of element to the quadratic element new nodes'.
108 std::array<MeshLib::Node*, n_all_nodes> nodes{};
109 for (int i = 0; i < n_base_nodes; i++)
110 {
111 nodes[i] = const_cast<MeshLib::Node*>(e.getNode(i));
112 }
113
114 // For each edge create a middle node.
115 int const number_of_edges = e.getNumberOfEdges();
116 for (int i = 0; i < 3; i++)
117 {
118 auto const& a = *e.getEdgeNode(i, 0);
119 auto const& b = *e.getEdgeNode(i, 1);
120
121 nodes[n_base_nodes + i] = new MeshLib::Node(
122 (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
123 }
124 for (int i = 3; i < 6; i++)
125 {
126 auto const& a = *e.getEdgeNode(i + 3, 0);
127 auto const& b = *e.getEdgeNode(i + 3, 1);
128
129 nodes[n_base_nodes + i] = new MeshLib::Node(
130 (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
131 }
132 for (int i = 6; i < number_of_edges; i++)
133 {
134 auto const& a = *e.getEdgeNode(i - 3, 0);
135 auto const& b = *e.getEdgeNode(i - 3, 1);
136
137 nodes[n_base_nodes + i] = new MeshLib::Node(
138 (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2);
139 }
140
141 return std::make_unique<MeshLib::Prism15>(nodes, e.getID());
142}
143
145std::unique_ptr<MeshLib::Element> createQuadraticElement(
146 MeshLib::Element const& e, bool const add_centre_node)
147{
149 {
150 return convertLinearToQuadratic<MeshLib::Line3>(e);
151 }
153 {
154 return convertLinearToQuadratic<MeshLib::Tri6>(e);
155 }
157 {
158 return convertLinearToQuadratic<MeshLib::Tet10>(e);
159 }
161 {
162 if (add_centre_node)
163 {
165 }
166 return convertLinearToQuadratic<MeshLib::Quad8>(e);
167 }
169 {
170 return convertLinearToQuadratic<MeshLib::Hex20>(e);
171 }
173 {
175 }
177 {
178 return convertLinearToQuadratic<MeshLib::Pyramid13>(e);
179 }
180
181 OGS_FATAL("Mesh element type {:s} is not supported",
183}
184
186{
187 bool operator()(MeshLib::Node const* a, MeshLib::Node const* b) const
188 {
189 return *a < *b;
190 }
191};
192
193namespace MeshToolsLib
194{
195std::unique_ptr<MeshLib::Mesh> createQuadraticOrderMesh(
196 MeshLib::Mesh const& linear_mesh, bool const add_centre_node)
197{
198 // Clone the linear mesh nodes.
199 auto quadratic_mesh_nodes = MeshLib::copyNodeVector(linear_mesh.getNodes());
200
201 // Temporary container for unique quadratic nodes with O(log(n)) search.
202 std::set<MeshLib::Node*, nodeByCoordinatesComparator> unique_nodes;
203
204 // Create new elements with the quadratic nodes
205 std::vector<MeshLib::Element*> quadratic_elements;
206 auto const& linear_mesh_elements = linear_mesh.getElements();
207 for (MeshLib::Element const* e : linear_mesh_elements)
208 {
209 auto quadratic_element = createQuadraticElement(*e, add_centre_node);
210
211 // Replace the base nodes with cloned linear nodes.
212 int const number_base_nodes = quadratic_element->getNumberOfBaseNodes();
213 for (int i = 0; i < number_base_nodes; ++i)
214 {
215 quadratic_element->setNode(
216 i, quadratic_mesh_nodes[getNodeIndex(*quadratic_element, i)]);
217 }
218
219 // Make the new (middle-edge) nodes unique.
220 int const number_all_nodes = quadratic_element->getNumberOfNodes();
221 for (int i = number_base_nodes; i < number_all_nodes; ++i)
222 {
223 MeshLib::Node* original_node =
224 const_cast<MeshLib::Node*>(quadratic_element->getNode(i));
225
226 auto it = unique_nodes.insert(original_node);
227 if (!it.second) // same node was already inserted before, no
228 // insertion
229 {
230 // Replace the element's node with the unique node.
231 quadratic_element->setNode(i, *it.first);
232 // And delete the original node
233 delete original_node;
234 }
235 }
236
237 quadratic_elements.push_back(quadratic_element.release());
238 }
239
240 // Add the unique quadratic nodes to the cloned linear nodes.
241 quadratic_mesh_nodes.reserve(linear_mesh.getNodes().size() +
242 unique_nodes.size());
243 std::copy(unique_nodes.begin(), unique_nodes.end(),
244 std::back_inserter(quadratic_mesh_nodes));
245
246 return std::make_unique<MeshLib::Mesh>(
247 linear_mesh.getName(), quadratic_mesh_nodes, quadratic_elements,
248 true /* compute_element_neighbors */,
250 std::vector<MeshLib::MeshItemType>(1,
252}
253
254} // namespace MeshToolsLib
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 Prism class.
Definition of the Pyramid 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< MeshLib::Prism15 > convertLinearToQuadratic< MeshLib::Prism15 >(MeshLib::Element const &e)
Special case for Prism15.
std::unique_ptr< QuadraticElement > convertLinearToQuadratic(MeshLib::Element const &e)
std::unique_ptr< MeshLib::Quad9 > convertLinearToQuadratic< MeshLib::Quad9 >(MeshLib::Element const &e)
Special case for Quad-9 adding a centre node too.
Definition of the Tet class.
Definition of the Tri class.
virtual CellType getCellType() const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfEdges() const =0
Get the number of edges for this element.
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:89
virtual Node * getEdgeNode(unsigned edge_id, unsigned node_id) const =0
Return a specific edge node.
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
Properties & getProperties()
Definition Mesh.h:134
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:103
Properties excludeCopyProperties(std::vector< std::size_t > const &exclude_elem_ids, std::vector< std::size_t > const &exclude_node_ids) const
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.
std::vector< Node * > copyNodeVector(const std::vector< Node * > &nodes)
Creates a deep copy of a Node vector.
std::string CellType2String(const CellType t)
Given a MeshElemType this returns the appropriate string.
std::unique_ptr< MeshLib::Mesh > createQuadraticOrderMesh(MeshLib::Mesh const &linear_mesh, bool const add_centre_node)
bool operator()(MeshLib::Node const *a, MeshLib::Node const *b) const