12#include <tclap/CmdLine.h>
51template <
typename GradShapeFunction,
int Dim>
53 int const mesh_space_dimension,
54 std::array<double, Dim>
const& xi,
55 bool const check_reordered =
false)
57 Eigen::Matrix<double, GradShapeFunction::DIM, GradShapeFunction::NPOINTS,
60 Eigen::Map<Eigen::VectorXd> dN_vec(dNdxi.data(), dNdxi.size());
61 GradShapeFunction::computeGradShapeFunction(xi.data(), dN_vec);
63 e, mesh_space_dimension);
65 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(Dim, Dim);
66 for (
unsigned k = 0; k < GradShapeFunction::NPOINTS; k++)
75 return !(J.determinant() < 0);
78 if (J.determinant() < 0)
81 "Element {:d} has negative Jacobian determinant {:g}. "
82 "NodeReordering fails.",
83 e.
getID(), J.determinant());
90concept ShapeFunction =
requires(
double* xi, Eigen::Map<Eigen::VectorXd> dN) {
91 { T::DIM } -> std::convertible_to<int>;
92 { T::NPOINTS } -> std::convertible_to<int>;
93 T::computeGradShapeFunction(xi, dN);
103template <ShapeFunction ShapeFunc,
int Dim>
105 std::array<double, Dim> xi,
111 bool check_reordered)
114 e, mesh_space_dimension, xi, check_reordered);
124 auto reverse_nodes_non_3d =
127 const unsigned nElemNodes = nodes.size();
128 for (std::size_t j = 0; j < nElemNodes; ++j)
130 element.
setNode(j, nodes[nElemNodes - j - 1]);
141 const std::vector<MeshLib::Node*>& nodes)
142 { reverse_nodes_non_3d(element, nodes); });
146 {1.0 / 3.0, 1.0 / 3.0},
148 const std::vector<MeshLib::Node*>& nodes)
149 { reverse_nodes_non_3d(element, nodes); });
155 const std::vector<MeshLib::Node*>& nodes)
156 { reverse_nodes_non_3d(element, nodes); });
162 const std::vector<MeshLib::Node*>& nodes)
164 for (std::size_t j = 0; j < 4; ++j)
166 element.
setNode(j, nodes[(j + 1) % 4]);
172 {1.0 / 3.0, 1.0 / 3.0, 0.5},
174 const std::vector<MeshLib::Node*>& nodes)
176 for (std::size_t j = 0; j < 3; ++j)
178 element.
setNode(j, nodes[j + 3]);
179 element.
setNode(j + 3, nodes[j]);
187 const std::vector<MeshLib::Node*>& nodes)
199 const std::vector<MeshLib::Node*>& nodes)
201 for (std::size_t j = 0; j < 4; ++j)
203 element.
setNode(j, nodes[j + 4]);
204 element.
setNode(j + 4, nodes[j]);
221 int const mesh_space_dimension,
bool const forced)
223 std::size_t n_corrected_elements = 0;
225 for (
auto* element : elements)
227 auto const cell_type = element->getCellType();
231 OGS_FATAL(
"Element type `{:s}' does not exist.",
240 const auto& element_config =
243 if (element_config.is_node_ordering_correct(
244 *element, mesh_space_dimension,
false ))
250 const unsigned nElemNodes = element->getNumberOfBaseNodes();
251 std::vector<MeshLib::Node*> nodes(element->getNodes(),
252 element->getNodes() + nElemNodes);
254 element_config.reorder_element_nodes(*element, nodes);
259 element_config.is_node_ordering_correct(
260 *element, mesh_space_dimension,
true );
263 ++n_corrected_elements;
266 INFO(
"Corrected {:d} elements.", n_corrected_elements);
275 for (
auto*
const element : elements)
277 const unsigned nElemNodes(element->getNumberOfBaseNodes());
278 std::vector<MeshLib::Node*> nodes(element->getNodes(),
279 element->getNodes() + nElemNodes);
281 for (std::size_t j = 0; j < nElemNodes; ++j)
285 for (std::size_t k = 0; k < 3; ++k)
287 element->setNode(k, nodes[k + 3]);
288 element->setNode(k + 3, nodes[k]);
299 std::vector<MeshLib::Node*> base_nodes;
300 std::vector<MeshLib::Node*> nonlinear_nodes;
303 for (
unsigned i = 0; i < e->getNumberOfBaseNodes(); i++)
305 base_nodes.push_back(
const_cast<MeshLib::Node*
>(e->getNode(i)));
307 for (
unsigned i = e->getNumberOfBaseNodes(); i < e->getNumberOfNodes();
310 nonlinear_nodes.push_back(
320 std::vector<MeshLib::Node*>& allnodes =
321 const_cast<std::vector<MeshLib::Node*>&
>(mesh.
getNodes());
324 allnodes.insert(allnodes.end(), base_nodes.begin(), base_nodes.end());
325 allnodes.insert(allnodes.end(), nonlinear_nodes.begin(),
326 nonlinear_nodes.end());
331int main(
int argc,
char* argv[])
334 "Reorders mesh nodes in elements to make old or incorrectly ordered "
335 "meshes compatible with OGS6.\n"
336 "Three options are available:\n"
337 "Method 0: Reversing order of nodes and checking again for all "
339 "Method 1: Reversing order of nodes unless it's perceived correct by "
340 "OGS6 standards. This is the default selection.\n"
341 "Method 2: Fixing node ordering issues between VTK and OGS6 (only "
342 "applies to prism-elements)\n"
343 "Method 3: Re-ordering of mesh node vector such that all base nodes "
344 "are sorted before all nonlinear nodes.\n\n"
345 "OpenGeoSys-6 software, version " +
348 "Copyright (c) 2012-2025, OpenGeoSys Community "
349 "(http://www.opengeosys.org)",
352 std::vector<int> method_ids{0, 1, 2, 3};
353 TCLAP::ValuesConstraint<int> allowed_values(method_ids);
354 TCLAP::ValueArg<int> method_arg(
"m",
"method",
355 "reordering method selection",
false, 1,
358 TCLAP::ValueArg<std::string> output_mesh_arg(
359 "o",
"output_mesh",
"Output (.vtu). The name of the output mesh file",
360 true,
"",
"OUTPUT_FILE");
361 cmd.add(output_mesh_arg);
362 TCLAP::ValueArg<std::string> input_mesh_arg(
364 "Input (.vtu | .vtk | .msh). The name of the input mesh file",
true,
"",
366 cmd.add(input_mesh_arg);
368 cmd.add(log_level_arg);
369 cmd.parse(argc, argv);
374 std::unique_ptr<MeshLib::Mesh> mesh(
382 INFO(
"Reordering nodes... ");
383 if (!method_arg.isSet() || method_arg.getValue() < 2)
385 bool const forced = (method_arg.getValue() == 0);
389 INFO(
"Method 0: Reversing order of nodes will be checked again.");
392 "Method: Reversing order of nodes unless it is considered correct "
393 "by the OGS6 standard, i.e. such that det(J) > 0, where J is the "
394 "Jacobian of the global-to-local coordinate transformation.");
395 int const mesh_space_dimension =
398 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()),
399 mesh_space_dimension, forced);
401 else if (method_arg.getValue() == 2)
404 const_cast<std::vector<MeshLib::Element*>&
>(mesh->getElements()));
406 else if (method_arg.getValue() == 3)
413 INFO(
"VTU file written.");
Definition of the Element class.
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition of mesh-related Enumerations.
Definition of the Mesh class.
int main(int argc, char *argv[])
bool checkJacobianDeterminant(MeshLib::Element const &e, int const mesh_space_dimension, std::array< double, Dim > const &xi, bool const check_reordered=false)
static const std::array< ElementReorderConfigBase, static_cast< int >(MeshLib::CellType::enum_length)> element_configs_array
void reverseNodeOrder(std::vector< MeshLib::Element * > &elements, int const mesh_space_dimension, bool const forced)
Reverses order of nodes. In particular, this fixes issues between (Gmsh or OGS5) and OGS6 meshes.
void fixVtkInconsistencies(std::vector< MeshLib::Element * > &elements)
void reorderNonlinearNodes(MeshLib::Mesh &mesh)
Orders the base nodes of each elements before its non-linear nodes.
ElementReorderConfigBase makeElementConfig(std::array< double, Dim > xi, std::function< void(MeshLib::Element &, const std::vector< MeshLib::Node * > &)> reorder)
Definition of the Node class.
Eigen::Vector3d const & asEigenVector3d() const
MathLib::Point3d const & getMappedCoordinates(std::size_t node_id) const
return mapped coordinates of the node
virtual void setNode(unsigned idx, Node *node)=0
std::size_t getID() const
Returns the ID of the element.
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
void resetNodeIDs()
Resets the IDs of all mesh-nodes to their position in the node vector.
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
void makeVectorUnique(std::vector< T > &v)
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)
bool idsComparator(T const a, T const b)
std::string CellType2String(const CellType t)
Given a MeshElemType this returns the appropriate string.
int getSpaceDimension(std::vector< Node * > const &nodes)
Computes dimension of the embedding space containing the set of given points.
Definition of readMeshFromFile function.
std::function< bool(MeshLib::Element &, int, bool)> is_node_ordering_correct
std::function< void(MeshLib::Element &, const std::vector< MeshLib::Node * > &)> reorder_element_nodes