125 const std::vector<MeshLib::Node*>& nodes,
126 unsigned const i,
unsigned const j)
132 auto order_nodes_quadratic_quad =
134 const std::vector<MeshLib::Node*>& nodes)
136 swap_nodes_i_j(element, nodes, 1, 3);
137 swap_nodes_i_j(element, nodes, 5, 6);
138 swap_nodes_i_j(element, nodes, 4, 7);
149 const std::vector<MeshLib::Node*>& nodes)
150 { swap_nodes_i_j(element, nodes, 0, 1); });
156 const std::vector<MeshLib::Node*>& nodes)
157 { swap_nodes_i_j(element, nodes, 0, 1); });
161 {1.0 / 3.0, 1.0 / 3.0},
163 const std::vector<MeshLib::Node*>& nodes)
164 { swap_nodes_i_j(element, nodes, 1, 2); });
168 {1.0 / 3.0, 1.0 / 3.0},
170 const std::vector<MeshLib::Node*>& nodes)
172 swap_nodes_i_j(element, nodes, 1, 2);
173 swap_nodes_i_j(element, nodes, 3, 5);
180 const std::vector<MeshLib::Node*>& nodes)
181 { swap_nodes_i_j(element, nodes, 0, 2); });
186 [&order_nodes_quadratic_quad](
188 const std::vector<MeshLib::Node*>& nodes)
189 { order_nodes_quadratic_quad(element, nodes); });
193 [&order_nodes_quadratic_quad](
195 const std::vector<MeshLib::Node*>& nodes)
196 { order_nodes_quadratic_quad(element, nodes); });
201 const std::vector<MeshLib::Node*>& nodes)
202 { swap_nodes_i_j(element, nodes, 1, 2); });
208 const std::vector<MeshLib::Node*>& nodes)
210 swap_nodes_i_j(element, nodes, 1, 2);
211 swap_nodes_i_j(element, nodes, 4, 6);
212 swap_nodes_i_j(element, nodes, 8, 9);
216 {1.0 / 3.0, 1.0 / 3.0, 0.5},
218 const std::vector<MeshLib::Node*>& nodes)
220 swap_nodes_i_j(element, nodes, 1, 2);
221 swap_nodes_i_j(element, nodes, 4, 5);
226 {1.0 / 3.0, 1.0 / 3., 0.5},
228 const std::vector<MeshLib::Node*>& nodes)
230 swap_nodes_i_j(element, nodes, 0, 3);
231 swap_nodes_i_j(element, nodes, 1, 4);
232 swap_nodes_i_j(element, nodes, 2, 5);
233 swap_nodes_i_j(element, nodes, 6, 9);
234 swap_nodes_i_j(element, nodes, 7, 10);
235 swap_nodes_i_j(element, nodes, 8, 11);
242 const std::vector<MeshLib::Node*>& nodes)
243 { swap_nodes_i_j(element, nodes, 0, 2); });
249 const std::vector<MeshLib::Node*>& nodes)
251 swap_nodes_i_j(element, nodes, 0, 2);
252 swap_nodes_i_j(element, nodes, 9, 11);
253 swap_nodes_i_j(element, nodes, 5, 6);
254 swap_nodes_i_j(element, nodes, 7, 8);
260 const std::vector<MeshLib::Node*>& nodes)
262 swap_nodes_i_j(element, nodes, 0, 2);
263 swap_nodes_i_j(element, nodes, 4, 6);
270 const std::vector<MeshLib::Node*>& nodes)
272 swap_nodes_i_j(element, nodes, 0, 2);
273 swap_nodes_i_j(element, nodes, 4, 6);
274 swap_nodes_i_j(element, nodes, 16, 18);
275 swap_nodes_i_j(element, nodes, 8, 9);
276 swap_nodes_i_j(element, nodes, 10, 11);
277 swap_nodes_i_j(element, nodes, 12, 13);
278 swap_nodes_i_j(element, nodes, 14, 15);
293 int const mesh_space_dimension,
bool const forced)
295 std::size_t n_corrected_elements = 0;
297 for (
auto* element : elements)
299 auto const cell_type = element->getCellType();
303 OGS_FATAL(
"Element type `{:s}' does not exist.",
311 OGS_FATAL(
"Element type `{:s}' is not supported in OGS.",
320 const auto& element_config =
323 if (element_config.is_node_ordering_correct(
324 *element, mesh_space_dimension,
false ))
330 const unsigned nElemNodes = element->getNumberOfNodes();
331 std::vector<MeshLib::Node*> nodes(element->getNodes(),
332 element->getNodes() + nElemNodes);
334 double const element_volume_origin = element->computeVolume();
336 element_config.reorder_element_nodes(*element, nodes);
339 double const element_volume = element->computeVolume();
342 if (std::fabs(element_volume - element_volume_origin) > 1e-14)
345 "Reordering of element {:d} nodes failed as its volume changed "
346 "from {:.12e} to {:.12e}.",
347 element->getID(), element_volume_origin, element_volume);
355 element_config.is_node_ordering_correct(
356 *element, mesh_space_dimension,
true );
359 ++n_corrected_elements;
362 INFO(
"Corrected {:d} elements.", n_corrected_elements);
427int main(
int argc,
char* argv[])
429 enum class ExpectedCellType
453 constexpr bool are_expected_cell_types =
454 static_cast<int>(ExpectedCellType::enum_length) ==
456 static_cast<int>(ExpectedCellType::INVALID) ==
458 static_cast<int>(ExpectedCellType::POINT1) ==
460 static_cast<int>(ExpectedCellType::LINE2) ==
462 static_cast<int>(ExpectedCellType::LINE3) ==
464 static_cast<int>(ExpectedCellType::TRI3) ==
466 static_cast<int>(ExpectedCellType::TRI6) ==
468 static_cast<int>(ExpectedCellType::QUAD4) ==
470 static_cast<int>(ExpectedCellType::QUAD8) ==
472 static_cast<int>(ExpectedCellType::QUAD9) ==
474 static_cast<int>(ExpectedCellType::TET4) ==
476 static_cast<int>(ExpectedCellType::TET10) ==
478 static_cast<int>(ExpectedCellType::HEX8) ==
480 static_cast<int>(ExpectedCellType::HEX20) ==
482 static_cast<int>(ExpectedCellType::HEX27) ==
484 static_cast<int>(ExpectedCellType::PRISM6) ==
486 static_cast<int>(ExpectedCellType::PRISM15) ==
488 static_cast<int>(ExpectedCellType::PRISM18) ==
490 static_cast<int>(ExpectedCellType::PYRAMID5) ==
492 static_cast<int>(ExpectedCellType::PYRAMID13) ==
497 if (!are_expected_cell_types)
500 "The enum class MeshLib::CellType has changed. Please adapt the "
501 "array 'element_configs_array' in NodeReordering.cpp accordingly.");
505 "Reorders mesh nodes in elements to make old or incorrectly ordered "
506 "meshes compatible with OGS6.\n"
507 "Three options are available:\n"
508 "Method 0: Reversing order of nodes and checking again for all "
510 "Method 1: Reversing order of nodes unless it's perceived correct by "
511 "OGS6 standards. This is the default selection.\n"
512 "Method 2: Fixing node ordering issues between VTK and OGS6 (only "
513 "applies to prism-elements)\n"
514 "Method 3: Re-ordering of mesh node vector such that all base nodes "
515 "are sorted before all nonlinear nodes.\n\n"
516 "OpenGeoSys-6 software, version " +
519 "Copyright (c) 2012-2025, OpenGeoSys Community "
520 "(http://www.opengeosys.org)",
523 std::vector<int> method_ids{0, 1, 2, 3};
524 TCLAP::ValuesConstraint<int> allowed_values(method_ids);
525 TCLAP::ValueArg<int> method_arg(
"m",
"method",
526 "reordering method selection",
false, 1,
529 TCLAP::ValueArg<std::string> output_mesh_arg(
530 "o",
"output_mesh",
"Output (.vtu). The name of the output mesh file",
531 true,
"",
"OUTPUT_FILE");
532 cmd.add(output_mesh_arg);
533 TCLAP::ValueArg<std::string> input_mesh_arg(
535 "Input (.vtu | .vtk | .msh). The name of the input mesh file",
true,
"",
537 cmd.add(input_mesh_arg);
539 cmd.add(log_level_arg);
540 cmd.parse(argc, argv);
545 std::unique_ptr<MeshLib::Mesh> mesh(
553 INFO(
"Reordering nodes... ");
554 if (!method_arg.isSet() || method_arg.getValue() < 2)
556 bool const forced = (method_arg.getValue() == 0);
560 INFO(
"Method 0: Reversing order of nodes will be checked again.");
563 "Method: Reversing order of nodes unless it is considered correct "
564 "by the OGS6 standard, i.e. such that det(J) > 0, where J is the "
565 "Jacobian of the global-to-local coordinate transformation.");
566 int const mesh_space_dimension =
569 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()),
570 mesh_space_dimension, forced);
572 else if (method_arg.getValue() == 2)
575 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()));
577 else if (method_arg.getValue() == 3)
584 INFO(
"VTU file written.");