OGS
NodeReordering.cpp File Reference

Detailed Description

2013/13/06 KR Initial implementation

Definition in file NodeReordering.cpp.

Include dependency graph for NodeReordering.cpp:

Go to the source code of this file.

Classes

struct  ElementReorderConfigBase
 

Functions

template<typename GradShapeFunction , int Dim>
bool checkJacobianDeterminant (MeshLib::Element const &e, int const mesh_space_dimension, std::array< double, Dim > const &xi, bool const check_reordered=false)
 
template<ShapeFunction ShapeFunc, int Dim>
ElementReorderConfigBase makeElementConfig (std::array< double, Dim > xi, std::function< void(MeshLib::Element &, const std::vector< MeshLib::Node * > &)> reorder)
 
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.
 
int main (int argc, char *argv[])
 

Variables

static const std::array< ElementReorderConfigBase, static_cast< int >(MeshLib::CellType::enum_length)> element_configs_array
 

Function Documentation

◆ checkJacobianDeterminant()

template<typename GradShapeFunction , int Dim>
bool checkJacobianDeterminant ( MeshLib::Element const & e,
int const mesh_space_dimension,
std::array< double, Dim > const & xi,
bool const check_reordered = false )

Definition at line 52 of file NodeReordering.cpp.

56{
57 Eigen::Matrix<double, GradShapeFunction::DIM, GradShapeFunction::NPOINTS,
58 Eigen::RowMajor>
59 dNdxi;
60 Eigen::Map<Eigen::VectorXd> dN_vec(dNdxi.data(), dNdxi.size());
61 GradShapeFunction::computeGradShapeFunction(xi.data(), dN_vec);
63 e, mesh_space_dimension);
64
65 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(Dim, Dim);
66 for (unsigned k = 0; k < GradShapeFunction::NPOINTS; k++)
67 {
68 const MathLib::Point3d& mapped_pt =
69 ele_local_coord.getMappedCoordinates(k);
70 J += dNdxi.col(k) * mapped_pt.asEigenVector3d().head(Dim).transpose();
71 }
72
73 if (!check_reordered)
74 {
75 return !(J.determinant() < 0);
76 }
77
78 if (J.determinant() < 0)
79 {
81 "Element {:d} has negative Jacobian determinant {:g}. "
82 "NodeReordering fails.",
83 e.getID(), J.determinant());
84 }
85
86 return true;
87}
#define OGS_FATAL(...)
Definition Error.h:26
Eigen::Vector3d const & asEigenVector3d() const
Definition Point3d.h:64

References MathLib::Point3d::asEigenVector3d(), MeshLib::Element::getID(), MeshLib::ElementCoordinatesMappingLocal::getMappedCoordinates(), and OGS_FATAL.

Referenced by makeElementConfig().

◆ fixVtkInconsistencies()

void fixVtkInconsistencies ( std::vector< MeshLib::Element * > & elements)

Fixes inconsistencies between VTK's and OGS' node order for prism elements. In particular, this fixes issues between OGS6 meshes with and without InSitu-Lib

Definition at line 273 of file NodeReordering.cpp.

274{
275 for (auto* const element : elements)
276 {
277 const unsigned nElemNodes(element->getNumberOfBaseNodes());
278 std::vector<MeshLib::Node*> nodes(element->getNodes(),
279 element->getNodes() + nElemNodes);
280
281 for (std::size_t j = 0; j < nElemNodes; ++j)
282 {
283 if (element->getGeomType() == MeshLib::MeshElemType::PRISM)
284 {
285 for (std::size_t k = 0; k < 3; ++k)
286 {
287 element->setNode(k, nodes[k + 3]);
288 element->setNode(k + 3, nodes[k]);
289 }
290 break;
291 }
292 }
293 }
294}

References MeshLib::PRISM.

Referenced by main().

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 331 of file NodeReordering.cpp.

332{
333 TCLAP::CmdLine cmd(
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 "
338 "elements.\n"
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 " +
347 ".\n"
348 "Copyright (c) 2012-2025, OpenGeoSys Community "
349 "(http://www.opengeosys.org)",
351
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,
356 &allowed_values);
357 cmd.add(method_arg);
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(
363 "i", "input_mesh",
364 "Input (.vtu | .vtk | .msh). The name of the input mesh file", true, "",
365 "INPUT_FILE");
366 cmd.add(input_mesh_arg);
367 auto log_level_arg = BaseLib::makeLogLevelArg();
368 cmd.add(log_level_arg);
369 cmd.parse(argc, argv);
370
371 BaseLib::MPI::Setup mpi_setup(argc, argv);
372 BaseLib::initOGSLogger(log_level_arg.getValue());
373
374 std::unique_ptr<MeshLib::Mesh> mesh(
375 MeshLib::IO::readMeshFromFile(input_mesh_arg.getValue()));
376
377 if (!mesh)
378 {
379 return EXIT_FAILURE;
380 }
381
382 INFO("Reordering nodes... ");
383 if (!method_arg.isSet() || method_arg.getValue() < 2)
384 {
385 bool const forced = (method_arg.getValue() == 0);
386
387 if (forced)
388 {
389 INFO("Method 0: Reversing order of nodes will be checked again.");
390 }
391 INFO(
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 =
396 MeshLib::getSpaceDimension(mesh->getNodes());
398 const_cast<std::vector<MeshLib::Element*>&>(mesh->getElements()),
399 mesh_space_dimension, forced);
400 }
401 else if (method_arg.getValue() == 2)
402 {
404 const_cast<std::vector<MeshLib::Element*>&>(mesh->getElements()));
405 }
406 else if (method_arg.getValue() == 3)
407 {
409 }
410
411 MeshLib::IO::writeMeshToFile(*mesh, output_mesh_arg.getValue());
412
413 INFO("VTU file written.");
414
415 return EXIT_SUCCESS;
416}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:36
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.
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:64
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)
int getSpaceDimension(std::vector< Node * > const &nodes)
Computes dimension of the embedding space containing the set of given points.

References fixVtkInconsistencies(), MeshLib::getSpaceDimension(), INFO(), BaseLib::initOGSLogger(), BaseLib::makeLogLevelArg(), GitInfoLib::GitInfo::ogs_version, MeshLib::IO::readMeshFromFile(), reorderNonlinearNodes(), reverseNodeOrder(), and MeshLib::IO::writeMeshToFile().

◆ makeElementConfig()

template<ShapeFunction ShapeFunc, int Dim>
ElementReorderConfigBase makeElementConfig ( std::array< double, Dim > xi,
std::function< void(MeshLib::Element &, const std::vector< MeshLib::Node * > &)> reorder )

Definition at line 104 of file NodeReordering.cpp.

108{
110 [xi](MeshLib::Element& e, int mesh_space_dimension,
111 bool check_reordered)
112 {
114 e, mesh_space_dimension, xi, check_reordered);
115 },
116 reorder};
117}
bool checkJacobianDeterminant(MeshLib::Element const &e, int const mesh_space_dimension, std::array< double, Dim > const &xi, bool const check_reordered=false)

References checkJacobianDeterminant().

◆ reorderNonlinearNodes()

void reorderNonlinearNodes ( MeshLib::Mesh & mesh)

Orders the base nodes of each elements before its non-linear nodes.

Definition at line 297 of file NodeReordering.cpp.

298{
299 std::vector<MeshLib::Node*> base_nodes;
300 std::vector<MeshLib::Node*> nonlinear_nodes;
301 for (MeshLib::Element const* e : mesh.getElements())
302 {
303 for (unsigned i = 0; i < e->getNumberOfBaseNodes(); i++)
304 {
305 base_nodes.push_back(const_cast<MeshLib::Node*>(e->getNode(i)));
306 }
307 for (unsigned i = e->getNumberOfBaseNodes(); i < e->getNumberOfNodes();
308 i++)
309 {
310 nonlinear_nodes.push_back(
311 const_cast<MeshLib::Node*>(e->getNode(i)));
312 }
313 }
314
315 BaseLib::makeVectorUnique(base_nodes,
317 BaseLib::makeVectorUnique(nonlinear_nodes,
319
320 std::vector<MeshLib::Node*>& allnodes =
321 const_cast<std::vector<MeshLib::Node*>&>(mesh.getNodes());
322 allnodes.clear();
323
324 allnodes.insert(allnodes.end(), base_nodes.begin(), base_nodes.end());
325 allnodes.insert(allnodes.end(), nonlinear_nodes.begin(),
326 nonlinear_nodes.end());
327
328 mesh.resetNodeIDs();
329}
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition Mesh.h:108
void resetNodeIDs()
Resets the IDs of all mesh-nodes to their position in the node vector.
Definition Mesh.cpp:160
void makeVectorUnique(std::vector< T > &v)
Definition Algorithm.h:180
bool idsComparator(T const a, T const b)
Definition Mesh.h:208

References MeshLib::Mesh::getElements(), MeshLib::Mesh::getNodes(), MeshLib::idsComparator(), BaseLib::makeVectorUnique(), and MeshLib::Mesh::resetNodeIDs().

Referenced by main().

◆ reverseNodeOrder()

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.

Parameters
elementsMesh elements whose nodes should be reordered
forcedIf true, nodes are reordered for all elements, if false it is first checked if the node order is correct according to OGS6 element definitions.

Definition at line 220 of file NodeReordering.cpp.

222{
223 std::size_t n_corrected_elements = 0;
224
225 for (auto* element : elements)
226 {
227 auto const cell_type = element->getCellType();
228
229 if (cell_type == MeshLib::CellType::INVALID)
230 {
231 OGS_FATAL("Element type `{:s}' does not exist.",
232 MeshLib::CellType2String(cell_type));
233 }
234
235 if (cell_type == MeshLib::CellType::POINT1)
236 {
237 continue;
238 }
239
240 const auto& element_config =
241 element_configs_array[static_cast<int>(cell_type)];
242
243 if (element_config.is_node_ordering_correct(
244 *element, mesh_space_dimension, false /*check_reordered*/))
245 {
246 continue;
247 }
248
249 // Save nodes before reordering
250 const unsigned nElemNodes = element->getNumberOfBaseNodes();
251 std::vector<MeshLib::Node*> nodes(element->getNodes(),
252 element->getNodes() + nElemNodes);
253
254 element_config.reorder_element_nodes(*element, nodes);
255
256 // Verify reordering again if forced
257 if (forced)
258 {
259 element_config.is_node_ordering_correct(
260 *element, mesh_space_dimension, true /*check_reordered*/);
261 }
262
263 ++n_corrected_elements;
264 }
265
266 INFO("Corrected {:d} elements.", n_corrected_elements);
267}
static const std::array< ElementReorderConfigBase, static_cast< int >(MeshLib::CellType::enum_length)> element_configs_array
std::string CellType2String(const CellType t)
Given a MeshElemType this returns the appropriate string.

References MeshLib::CellType2String(), element_configs_array, INFO(), MeshLib::INVALID, OGS_FATAL, and MeshLib::POINT1.

Referenced by main().

Variable Documentation

◆ element_configs_array

const std::array<ElementReorderConfigBase, static_cast<int>(MeshLib::CellType::enum_length)> element_configs_array
static

Definition at line 121 of file NodeReordering.cpp.

122{
123 // Generic node reversal for 1D/2D elements
124 auto reverse_nodes_non_3d =
125 [](MeshLib::Element& element, const std::vector<MeshLib::Node*>& nodes)
126 {
127 const unsigned nElemNodes = nodes.size();
128 for (std::size_t j = 0; j < nElemNodes; ++j)
129 {
130 element.setNode(j, nodes[nElemNodes - j - 1]);
131 }
132 };
133 std::array<ElementReorderConfigBase,
134 static_cast<int>(MeshLib::CellType::enum_length)>
135 arr{};
136
137 arr[static_cast<int>(MeshLib::CellType::LINE2)] =
139 {0.5},
140 [&reverse_nodes_non_3d](MeshLib::Element& element,
141 const std::vector<MeshLib::Node*>& nodes)
142 { reverse_nodes_non_3d(element, nodes); });
143
144 arr[static_cast<int>(MeshLib::CellType::TRI3)] =
146 {1.0 / 3.0, 1.0 / 3.0},
147 [&reverse_nodes_non_3d](MeshLib::Element& element,
148 const std::vector<MeshLib::Node*>& nodes)
149 { reverse_nodes_non_3d(element, nodes); });
150
151 arr[static_cast<int>(MeshLib::CellType::QUAD4)] =
153 {0.0, 0.0},
154 [&reverse_nodes_non_3d](MeshLib::Element& element,
155 const std::vector<MeshLib::Node*>& nodes)
156 { reverse_nodes_non_3d(element, nodes); });
157
158 arr[static_cast<int>(MeshLib::CellType::TET4)] =
160 {0.25, 0.25, 0.25},
161 [](MeshLib::Element& element,
162 const std::vector<MeshLib::Node*>& nodes)
163 {
164 for (std::size_t j = 0; j < 4; ++j)
165 {
166 element.setNode(j, nodes[(j + 1) % 4]);
167 }
168 });
169
170 arr[static_cast<int>(MeshLib::CellType::PRISM6)] =
172 {1.0 / 3.0, 1.0 / 3.0, 0.5},
173 [](MeshLib::Element& element,
174 const std::vector<MeshLib::Node*>& nodes)
175 {
176 for (std::size_t j = 0; j < 3; ++j)
177 {
178 element.setNode(j, nodes[j + 3]);
179 element.setNode(j + 3, nodes[j]);
180 }
181 });
182
183 arr[static_cast<int>(MeshLib::CellType::PYRAMID5)] =
185 {0.25, 0.25, 0.5},
186 [](MeshLib::Element& element,
187 const std::vector<MeshLib::Node*>& nodes)
188 {
189 element.setNode(0, nodes[1]);
190 element.setNode(1, nodes[0]);
191 element.setNode(2, nodes[3]);
192 element.setNode(3, nodes[2]);
193 });
194
195 arr[static_cast<int>(MeshLib::CellType::HEX8)] =
197 {0.5, 0.5, 0.5},
198 [](MeshLib::Element& element,
199 const std::vector<MeshLib::Node*>& nodes)
200 {
201 for (std::size_t j = 0; j < 4; ++j)
202 {
203 element.setNode(j, nodes[j + 4]);
204 element.setNode(j + 4, nodes[j]);
205 }
206 });
207
208 return arr;
209}();
ElementReorderConfigBase makeElementConfig(std::array< double, Dim > xi, std::function< void(MeshLib::Element &, const std::vector< MeshLib::Node * > &)> reorder)
virtual void setNode(unsigned idx, Node *node)=0

Referenced by reverseNodeOrder().