OGS
ReorderMesh.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
4#include <tclap/CmdLine.h>
5
6#include <memory>
7#include <string>
8
9#include "BaseLib/Logging.h"
10#include "BaseLib/MPI.h"
12#include "InfoLib/GitInfo.h"
16#include "MeshLib/Mesh.h"
17#include "MeshLib/Node.h"
18
19std::vector<std::size_t> generateBulkIDsReverseMapping(
20 std::span<std::size_t const> bulk_ids)
21{
22 std::vector<std::size_t> parallel_to_sequential_node_ids(bulk_ids.size());
23
24 std::size_t pos = 0;
25 for (auto const id : bulk_ids)
26 {
27 parallel_to_sequential_node_ids[id] = pos;
28 pos++;
29 }
30 return parallel_to_sequential_node_ids;
31}
32
33template <typename T>
35 std::span<std::size_t const>
36 bulk_ids,
37 MeshLib::PropertyVector<T>& reordered_pv)
38{
39 if (original_pv.getNumberOfGlobalComponents() !=
40 reordered_pv.getNumberOfGlobalComponents())
41 {
43 "Could not reorder property {} since the number of components "
44 "isn't equal ({} != {}).",
45 original_pv.getPropertyName(),
46 original_pv.getNumberOfGlobalComponents(),
47 reordered_pv.getNumberOfGlobalComponents());
48 }
49
50 auto const number_of_components = original_pv.getNumberOfGlobalComponents();
51 std::size_t pos = 0;
52 for (auto const& id : bulk_ids)
53 {
54 for (int c = 0; c < number_of_components; c++)
55 {
56 reordered_pv.getComponent(id, c) = original_pv.getComponent(pos, c);
57 }
58 pos++;
59 }
60 return true;
61}
62
63template <typename T>
64bool reorderProperty(MeshLib::Properties const& original_properties,
65 std::span<std::size_t const>
66 bulk_ids,
67 std::string const& property_name,
68 MeshLib::Properties& reordered_properties)
69{
70 if (!reordered_properties.existsPropertyVector<T>(property_name))
71 {
72 return false;
73 }
74 auto const& original_property =
75 *original_properties.getPropertyVector<T>(property_name);
76 auto& reordered_property =
77 *reordered_properties.getPropertyVector<T>(property_name);
78 return reorderProperty(original_property, bulk_ids, reordered_property);
79}
80
81void reorderProperties(MeshLib::Properties const& original_properties,
82 std::span<std::size_t const>
83 bulk_ids,
84 std::vector<std::string> const& property_names,
85 MeshLib::Properties& reordered_properties)
86{
87 for (auto const& property_name : property_names)
88 {
89 bool const success =
90 reorderProperty<double>(original_properties, bulk_ids,
91 property_name, reordered_properties) ||
92 reorderProperty<float>(original_properties, bulk_ids, property_name,
93 reordered_properties) ||
94 reorderProperty<int>(original_properties, bulk_ids, property_name,
95 reordered_properties) ||
96 reorderProperty<long>(original_properties, bulk_ids, property_name,
97 reordered_properties) ||
98 reorderProperty<unsigned>(original_properties, bulk_ids,
99 property_name, reordered_properties) ||
100 reorderProperty<unsigned long>(original_properties, bulk_ids,
101 property_name,
102 reordered_properties) ||
103 reorderProperty<std::size_t>(original_properties, bulk_ids,
104 property_name, reordered_properties) ||
105 reorderProperty<char>(original_properties, bulk_ids, property_name,
106 reordered_properties) ||
107 reorderProperty<unsigned char>(original_properties, bulk_ids,
108 property_name, reordered_properties);
109 if (!success)
110 {
111 OGS_FATAL("Could not reorder PropertyVector '{}'.", property_name);
112 }
113 }
114}
115
116int main(int argc, char* argv[])
117{
118 TCLAP::CmdLine cmd(
119 "Reorder mesh nodes and cells.\n\n"
120 "OpenGeoSys-6 software, version " +
122 ".\n"
123 "Copyright (c) 2012-2026, OpenGeoSys Community "
124 "(http://www.opengeosys.org)",
126 TCLAP::ValueArg<std::string> mesh_in_arg(
127 "i", "input", "Input (.vtu). Name of the input mesh file", true, "",
128 "INPUT_FILE");
129 cmd.add(mesh_in_arg);
130 TCLAP::ValueArg<std::string> mesh_out_arg(
131 "o", "output", "Output (.vtu). Name of the output mesh file", true, "",
132 "OUTPUT_FILE");
133 cmd.add(mesh_out_arg);
134
135 auto log_level_arg = BaseLib::makeLogLevelArg();
136 cmd.add(log_level_arg);
137 cmd.parse(argc, argv);
138
139 BaseLib::MPI::Setup mpi_setup(argc, argv);
140 BaseLib::initOGSLogger(log_level_arg.getValue());
141
142 const std::string filename(mesh_in_arg.getValue());
143
144 // read the mesh file
145 auto const mesh =
146 std::unique_ptr<MeshLib::Mesh>(MeshLib::IO::readMeshFromFile(filename));
147 if (!mesh)
148 {
149 return EXIT_FAILURE;
150 }
151
152 auto const* bulk_node_ids = MeshLib::bulkNodeIDs(*mesh);
153 if (!bulk_node_ids)
154 {
155 OGS_FATAL("Property / data array '{}' has not been found in the mesh.",
157 }
158
159 auto const& nodes = mesh->getNodes();
160 auto const node_ids_reverse_mapping(
161 generateBulkIDsReverseMapping(*bulk_node_ids));
162
163 std::vector<MeshLib::Node*> reordered_nodes(nodes.size());
164 std::size_t pos = 0;
165 for (auto const id : node_ids_reverse_mapping)
166 {
167 auto const& n = *(nodes[id]);
168 reordered_nodes[pos] = new MeshLib::Node(n[0], n[1], n[2], pos);
169 pos++;
170 }
171
172 auto const bulk_element_ids_string =
174 if (!mesh->getProperties().existsPropertyVector<std::size_t>(
175 bulk_element_ids_string))
176 {
177 OGS_FATAL("Property / data array '{}' has not been found in the mesh.",
178 bulk_element_ids_string);
179 }
180 auto const& bulk_element_ids =
181 *mesh->getProperties().getPropertyVector<std::size_t>(
182 bulk_element_ids_string);
183
184 std::vector<std::size_t> element_ids_reverse_mapping(
185 generateBulkIDsReverseMapping(bulk_element_ids));
186
187 auto const& elements = mesh->getElements();
188 std::vector<MeshLib::Element*> reordered_elements(elements.size());
189 pos = 0;
190 for (auto const id : element_ids_reverse_mapping)
191 {
192 auto const& e = *elements[id];
193 auto* reordered_element =
194 e.clone(); // use clone to have the same element type
195 // reset the nodes to the reordered nodes
196 auto const number_of_nodes = reordered_element->getNumberOfNodes();
197 for (std::size_t node_number = 0; node_number < number_of_nodes;
198 node_number++)
199 {
200 reordered_element->setNode(
201 node_number,
202 reordered_nodes[(
203 *bulk_node_ids)[e.getNode(node_number)->getID()]]);
204 }
205 reordered_elements[pos] = reordered_element;
206 pos++;
207 }
208 auto const& original_properties = mesh->getProperties();
209 // reordering of PropertyVector with following MeshItemTypes isn't supported
210 std::vector<MeshLib::MeshItemType> const exclude_property_vectors{
213 // Create reordered mesh - only the PropertyVectors for which the reordering
214 // is implemented are copied
215 MeshLib::Mesh reordered_mesh{
216 "reordered_mesh", reordered_nodes, reordered_elements,
217 false /* compute_element_neighbors */,
218 original_properties.excludeCopyProperties(exclude_property_vectors)};
219 auto& properties = reordered_mesh.getProperties();
220
221 // node based properties
222 auto const node_property_names =
223 mesh->getProperties().getPropertyVectorNames(
225 reorderProperties(original_properties, std::span{*bulk_node_ids},
226 node_property_names, properties);
227
228 // element based properties
229 auto const element_property_names =
230 mesh->getProperties().getPropertyVectorNames(
232 reorderProperties(original_properties, bulk_element_ids,
233 element_property_names, properties);
234 MeshLib::IO::writeMeshToFile(reordered_mesh, mesh_out_arg.getValue());
235
236 auto const number_of_properties =
237 mesh->getProperties().getPropertyVectorNames().size();
238 if (node_property_names.size() + element_property_names.size() <
239 number_of_properties)
240 {
241 WARN(
242 "Properties that are not assigened to nodes or elements are not "
243 "transferred to the reordered mesh.");
244 }
245
246 return EXIT_SUCCESS;
247}
#define OGS_FATAL(...)
Definition Error.h:19
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
int main(int argc, char *argv[])
void reorderProperties(MeshLib::Properties const &original_properties, std::span< std::size_t const > bulk_ids, std::vector< std::string > const &property_names, MeshLib::Properties &reordered_properties)
std::vector< std::size_t > generateBulkIDsReverseMapping(std::span< std::size_t const > bulk_ids)
bool reorderProperty(MeshLib::PropertyVector< T > const &original_pv, std::span< std::size_t const > bulk_ids, MeshLib::PropertyVector< T > &reordered_pv)
Properties & getProperties()
Definition Mesh.h:125
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
std::vector< std::string > getPropertyVectorNames() const
bool existsPropertyVector(std::string_view name) const
PropertyVector< T > const * getPropertyVector(std::string_view name) const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const
PROP_VAL_TYPE & getComponent(std::size_t tuple_index, int component)
Returns the value for the given component stored in the given tuple.
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, std::set< std::string > variable_output_names)
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
PropertyVector< std::size_t > const * bulkNodeIDs(Mesh const &mesh)
Definition Mesh.cpp:282