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