117 const std::vector<MeshLib::Node*>& nodes,
118 unsigned const i,
unsigned const j)
124 auto order_nodes_quadratic_quad =
126 const std::vector<MeshLib::Node*>& nodes)
128 swap_nodes_i_j(element, nodes, 1, 3);
129 swap_nodes_i_j(element, nodes, 5, 6);
130 swap_nodes_i_j(element, nodes, 4, 7);
141 const std::vector<MeshLib::Node*>& nodes)
142 { swap_nodes_i_j(element, nodes, 0, 1); });
148 const std::vector<MeshLib::Node*>& nodes)
149 { swap_nodes_i_j(element, nodes, 0, 1); });
153 {1.0 / 3.0, 1.0 / 3.0},
155 const std::vector<MeshLib::Node*>& nodes)
156 { swap_nodes_i_j(element, nodes, 1, 2); });
160 {1.0 / 3.0, 1.0 / 3.0},
162 const std::vector<MeshLib::Node*>& nodes)
164 swap_nodes_i_j(element, nodes, 1, 2);
165 swap_nodes_i_j(element, nodes, 3, 5);
172 const std::vector<MeshLib::Node*>& nodes)
173 { swap_nodes_i_j(element, nodes, 0, 2); });
178 [&order_nodes_quadratic_quad](
180 const std::vector<MeshLib::Node*>& nodes)
181 { order_nodes_quadratic_quad(element, nodes); });
185 [&order_nodes_quadratic_quad](
187 const std::vector<MeshLib::Node*>& nodes)
188 { order_nodes_quadratic_quad(element, nodes); });
193 const std::vector<MeshLib::Node*>& nodes)
194 { swap_nodes_i_j(element, nodes, 1, 2); });
200 const std::vector<MeshLib::Node*>& nodes)
202 swap_nodes_i_j(element, nodes, 1, 2);
203 swap_nodes_i_j(element, nodes, 4, 6);
204 swap_nodes_i_j(element, nodes, 8, 9);
208 {1.0 / 3.0, 1.0 / 3.0, 0.5},
210 const std::vector<MeshLib::Node*>& nodes)
212 swap_nodes_i_j(element, nodes, 1, 2);
213 swap_nodes_i_j(element, nodes, 4, 5);
218 {1.0 / 3.0, 1.0 / 3., 0.5},
220 const std::vector<MeshLib::Node*>& nodes)
222 swap_nodes_i_j(element, nodes, 0, 3);
223 swap_nodes_i_j(element, nodes, 1, 4);
224 swap_nodes_i_j(element, nodes, 2, 5);
225 swap_nodes_i_j(element, nodes, 6, 9);
226 swap_nodes_i_j(element, nodes, 7, 10);
227 swap_nodes_i_j(element, nodes, 8, 11);
234 const std::vector<MeshLib::Node*>& nodes)
235 { swap_nodes_i_j(element, nodes, 0, 2); });
241 const std::vector<MeshLib::Node*>& nodes)
243 swap_nodes_i_j(element, nodes, 0, 2);
244 swap_nodes_i_j(element, nodes, 9, 11);
245 swap_nodes_i_j(element, nodes, 5, 6);
246 swap_nodes_i_j(element, nodes, 7, 8);
252 const std::vector<MeshLib::Node*>& nodes)
254 swap_nodes_i_j(element, nodes, 0, 2);
255 swap_nodes_i_j(element, nodes, 4, 6);
262 const std::vector<MeshLib::Node*>& nodes)
264 swap_nodes_i_j(element, nodes, 0, 2);
265 swap_nodes_i_j(element, nodes, 4, 6);
266 swap_nodes_i_j(element, nodes, 16, 18);
267 swap_nodes_i_j(element, nodes, 8, 9);
268 swap_nodes_i_j(element, nodes, 10, 11);
269 swap_nodes_i_j(element, nodes, 12, 13);
270 swap_nodes_i_j(element, nodes, 14, 15);
310 int const mesh_space_dimension,
bool const forced,
311 bool const volume_check)
313 std::size_t n_corrected_elements = 0;
315 for (
auto* element : elements)
317 auto const cell_type = element->getCellType();
321 OGS_FATAL(
"Element type `{:s}' does not exist.",
329 OGS_FATAL(
"Element type `{:s}' is not supported in OGS.",
338 const auto& element_config =
341 if (element_config.is_node_ordering_correct(
342 *element, mesh_space_dimension,
false ))
348 const unsigned nElemNodes = element->getNumberOfNodes();
349 std::vector<MeshLib::Node*> nodes(element->getNodes(),
350 element->getNodes() + nElemNodes);
354 double const element_volume_origin = element->computeVolume();
356 element_config.reorder_element_nodes(*element, nodes);
359 double const element_volume = element->computeVolume();
366 element_config.reorder_element_nodes(*element, nodes);
375 element_config.is_node_ordering_correct(
376 *element, mesh_space_dimension,
true );
379 ++n_corrected_elements;
382 INFO(
"Corrected {:d} elements.", n_corrected_elements);
447int main(
int argc,
char* argv[])
449 enum class ExpectedCellType
473 constexpr bool are_expected_cell_types =
474 static_cast<int>(ExpectedCellType::enum_length) ==
476 static_cast<int>(ExpectedCellType::INVALID) ==
478 static_cast<int>(ExpectedCellType::POINT1) ==
480 static_cast<int>(ExpectedCellType::LINE2) ==
482 static_cast<int>(ExpectedCellType::LINE3) ==
484 static_cast<int>(ExpectedCellType::TRI3) ==
486 static_cast<int>(ExpectedCellType::TRI6) ==
488 static_cast<int>(ExpectedCellType::QUAD4) ==
490 static_cast<int>(ExpectedCellType::QUAD8) ==
492 static_cast<int>(ExpectedCellType::QUAD9) ==
494 static_cast<int>(ExpectedCellType::TET4) ==
496 static_cast<int>(ExpectedCellType::TET10) ==
498 static_cast<int>(ExpectedCellType::HEX8) ==
500 static_cast<int>(ExpectedCellType::HEX20) ==
502 static_cast<int>(ExpectedCellType::HEX27) ==
504 static_cast<int>(ExpectedCellType::PRISM6) ==
506 static_cast<int>(ExpectedCellType::PRISM15) ==
508 static_cast<int>(ExpectedCellType::PRISM18) ==
510 static_cast<int>(ExpectedCellType::PYRAMID5) ==
512 static_cast<int>(ExpectedCellType::PYRAMID13) ==
517 if (!are_expected_cell_types)
520 "The enum class MeshLib::CellType has changed. Please adapt the "
521 "array 'element_configs_array' in NodeReordering.cpp accordingly.");
525 "Reorders mesh nodes in elements to make old or incorrectly ordered "
526 "meshes compatible with OGS6.\n"
527 "Three options are available:\n"
528 "Method 0: Reversing order of nodes and checking again for all "
530 "Method 1: Reversing order of nodes unless it's perceived correct by "
531 "OGS6 standards. This is the default selection.\n"
532 "Method 2: Fixing node ordering issues between VTK and OGS6 (only "
533 "applies to prism-elements)\n"
534 "Method 3: Re-ordering of mesh node vector such that all base nodes "
535 "are sorted before all nonlinear nodes.\n\n"
536 "OpenGeoSys-6 software, version " +
539 "Copyright (c) 2012-2026, OpenGeoSys Community "
540 "(http://www.opengeosys.org)",
543 TCLAP::SwitchArg no_volume_check_arg(
544 "",
"no_volume_check",
545 "By default the volumes of original and reordered elements are "
546 "compared if they are numerically equal, i.e., relative volume "
547 "difference is smaller than a threshold. This switch disables the "
548 "volume comparison.");
549 cmd.add(no_volume_check_arg);
551 std::vector<int> method_ids{0, 1, 2, 3};
552 TCLAP::ValuesConstraint<int> allowed_values(method_ids);
553 TCLAP::ValueArg<int> method_arg(
"m",
"method",
554 "reordering method selection",
false, 1,
557 TCLAP::ValueArg<std::string> output_mesh_arg(
558 "o",
"output_mesh",
"Output (.vtu). The name of the output mesh file",
559 true,
"",
"OUTPUT_FILE");
560 cmd.add(output_mesh_arg);
561 TCLAP::ValueArg<std::string> input_mesh_arg(
563 "Input (.vtu | .vtk | .msh). The name of the input mesh file",
true,
"",
565 cmd.add(input_mesh_arg);
567 cmd.add(log_level_arg);
568 cmd.parse(argc, argv);
573 std::unique_ptr<MeshLib::Mesh> mesh(
581 INFO(
"Reordering nodes... ");
582 if (!method_arg.isSet() || method_arg.getValue() < 2)
584 bool const forced = (method_arg.getValue() == 0);
588 INFO(
"Method 0: Reversing order of nodes will be checked again.");
591 "Method: Reversing order of nodes unless it is considered correct "
592 "by the OGS6 standard, i.e. such that det(J) > 0, where J is the "
593 "Jacobian of the global-to-local coordinate transformation.");
594 int const mesh_space_dimension =
597 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()),
598 mesh_space_dimension, forced, !no_volume_check_arg.isSet());
600 else if (method_arg.getValue() == 2)
603 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()));
605 else if (method_arg.getValue() == 3)
614 INFO(
"VTU file written.");