From eae3943d29c1dcf1032bafec6b0c4fb36f3e26f8 Mon Sep 17 00:00:00 2001
From: Wenqing Wang <wenqing.wang@ufz.de>
Date: Fri, 14 May 2021 14:52:01 +0200
Subject: [PATCH] [MeshLib] Added a utility of getElementRotationMatrices

---
 MeshLib/Utils/GetElementRotationMatrices.cpp | 48 ++++++++++++++++++++
 MeshLib/Utils/GetElementRotationMatrices.h   | 24 ++++++++++
 MeshLib/Utils/GetSpaceDimension.cpp          | 42 +++++++++++++++++
 MeshLib/Utils/GetSpaceDimension.h            | 45 ++++++++++++++++++
 MeshLib/Utils/SetMeshSpaceDimension.cpp      | 29 +-----------
 5 files changed, 161 insertions(+), 27 deletions(-)
 create mode 100644 MeshLib/Utils/GetElementRotationMatrices.cpp
 create mode 100644 MeshLib/Utils/GetElementRotationMatrices.h
 create mode 100644 MeshLib/Utils/GetSpaceDimension.cpp
 create mode 100644 MeshLib/Utils/GetSpaceDimension.h

diff --git a/MeshLib/Utils/GetElementRotationMatrices.cpp b/MeshLib/Utils/GetElementRotationMatrices.cpp
new file mode 100644
index 00000000000..8ec79cc2380
--- /dev/null
+++ b/MeshLib/Utils/GetElementRotationMatrices.cpp
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ * Created on May 14, 2021, 2:38 PM
+ */
+
+#include "GetElementRotationMatrices.h"
+
+#include "GetSpaceDimension.h"
+#include "MeshLib/ElementCoordinatesMappingLocal.h"
+#include "MeshLib/Elements/Elements.h"
+#include "MeshLib/Mesh.h"
+
+namespace MeshLib
+{
+std::vector<Eigen::MatrixXd> getElementRotationMatrices(
+    int const space_dimension, int const mesh_dimension,
+    std::vector<Element*> const& elements)
+{
+    std::vector<Eigen::MatrixXd> element_rotation_matrices;
+    element_rotation_matrices.reserve(elements.size());
+    for (auto const& element : elements)
+    {
+        int const element_dimension = static_cast<int>(element->getDimension());
+        if (element_dimension == space_dimension)
+        {
+            element_rotation_matrices.emplace_back(Eigen::MatrixXd::Identity(
+                element_dimension, element_dimension));
+        }
+        else
+        {
+            MeshLib::ElementCoordinatesMappingLocal coordinates_mapping(
+                *element, mesh_dimension);
+
+            element_rotation_matrices.emplace_back(
+                coordinates_mapping.getRotationMatrixToGlobal().topLeftCorner(
+                    space_dimension, element_dimension));
+        }
+    }
+
+    return element_rotation_matrices;
+}
+}  // namespace MeshLib
diff --git a/MeshLib/Utils/GetElementRotationMatrices.h b/MeshLib/Utils/GetElementRotationMatrices.h
new file mode 100644
index 00000000000..e09be8c695b
--- /dev/null
+++ b/MeshLib/Utils/GetElementRotationMatrices.h
@@ -0,0 +1,24 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ * Created on May 14, 2021, 2:38 PM
+ */
+
+#pragma once
+
+#include <Eigen/Dense>
+#include <vector>
+
+namespace MeshLib
+{
+class Element;
+
+std::vector<Eigen::MatrixXd> getElementRotationMatrices(
+    int const space_dimension, int const mesh_dimension,
+    std::vector<Element*> const& elements);
+}  // namespace MeshLib
diff --git a/MeshLib/Utils/GetSpaceDimension.cpp b/MeshLib/Utils/GetSpaceDimension.cpp
new file mode 100644
index 00000000000..6ebddd2fa41
--- /dev/null
+++ b/MeshLib/Utils/GetSpaceDimension.cpp
@@ -0,0 +1,42 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ * Created on June 8, 2021, 12:16 PM
+ */
+
+#include "GetSpaceDimension.h"
+
+#include <algorithm>
+#include <array>
+#include <limits>
+
+#include "BaseLib/Error.h"
+#include "MeshLib/Node.h"
+
+namespace MeshLib
+{
+int getSpaceDimension(std::vector<Node*> const& nodes)
+{
+    std::array x_magnitude = {0.0, 0.0, 0.0};
+
+    double const* const x_ref = nodes[0]->getCoords();
+    for (auto const& node : nodes)
+    {
+        auto const x = node->getCoords();
+        for (int i = 0; i < 3; i++)
+        {
+            x_magnitude[i] += std::fabs(x[i] - x_ref[i]);
+        }
+    }
+
+    return static_cast<int>(std::count_if(
+        x_magnitude.begin(), x_magnitude.end(),
+        [](const double x_i_magnitude)
+        { return x_i_magnitude > std::numeric_limits<double>::epsilon(); }));
+}
+};  // namespace MeshLib
diff --git a/MeshLib/Utils/GetSpaceDimension.h b/MeshLib/Utils/GetSpaceDimension.h
new file mode 100644
index 00000000000..abd3fa76234
--- /dev/null
+++ b/MeshLib/Utils/GetSpaceDimension.h
@@ -0,0 +1,45 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ * Created on June 8, 2021, 12:16 PM
+ */
+
+#pragma once
+
+#include <vector>
+
+namespace MeshLib
+{
+class Node;
+
+/**
+ * \brief Computes dimension of the embedding space containing the set of given
+ * points.
+ *
+ * The space dimension is computed by accounting the non-zero norms of
+ *  \f$\mathbf x\f$, \f$\mathbf y\f$, \f$\mathbf z\f$, which are
+ *  the coordinates of all nodes of the mesh. With this concept,
+ *  the space dimension of a mesh is:
+ *    - 1, if the mesh is 1D and and the mesh is parallel either to
+ *         \f$x\f$, \f$y\f$ or to \f$z\f$ axis.
+ *    - 2, if the mesh is 1D but it contains inclined elements on the origin
+ *         coordinate plane of \f$x-y,\, y-z,\, \text{or }\, x-z\f$.
+ *         That means the coordinates of all nodes are
+ *         \f$(x, y, 0)\f$, \f$(x, 0, z)\f$ or \f$(0, y, z)\f$.
+ *    - 3, if the mesh is 1D and but it is not on any origin
+ *         coordinate plane of \f$x-y,\, y-z,\, \text{or }\, x-z\f$.
+ *    - 2, if the mesh is 2D and it is on the origin
+ *         coordinate plane of \f$x-y,\, y-z,\, \text{or }\, x-z\f$.
+ *    - 2, if the mesh is 2D and it is on vertical or horizontal plane
+ *         that is parallel to the the origin coordinate
+ *         plane of \f$x-y,\, y-z,\, \text{or }\, x-z\f$ but with an offset.
+ *    - 3, if the mesh contains inclined 2D elements.
+ *    - 3, if the mesh contains 3D elements.
+ */
+int getSpaceDimension(std::vector<Node*> const& nodes);
+};  // namespace MeshLib
diff --git a/MeshLib/Utils/SetMeshSpaceDimension.cpp b/MeshLib/Utils/SetMeshSpaceDimension.cpp
index 35c908e2f66..ed28a84aad8 100644
--- a/MeshLib/Utils/SetMeshSpaceDimension.cpp
+++ b/MeshLib/Utils/SetMeshSpaceDimension.cpp
@@ -11,41 +11,16 @@
 
 #include "SetMeshSpaceDimension.h"
 
-#include <algorithm>
-#include <array>
-#include <limits>
-
-#include "BaseLib/Error.h"
+#include "GetSpaceDimension.h"
 #include "MeshLib/Elements/Element.h"
 #include "MeshLib/Mesh.h"
-#include "MeshLib/Node.h"
 
 namespace MeshLib
 {
-unsigned getSpaceDimension(Mesh const& mesh)
-{
-    std::array x_magnitude = {0.0, 0.0, 0.0};
-
-    auto const nodes = mesh.getNodes();
-    for (auto const& node : nodes)
-    {
-        auto const x = node->getCoords();
-        for (int i = 0; i < 3; i++)
-        {
-            x_magnitude[i] += std::fabs(x[i]);
-        }
-    }
-
-    return static_cast<unsigned>(std::count_if(
-        x_magnitude.begin(), x_magnitude.end(), [](const double x_i_magnitude) {
-            return x_i_magnitude > std::numeric_limits<double>::epsilon();
-        }));
-}
-
 void setMeshSpaceDimension(std::vector<std::unique_ptr<Mesh>> const& meshes)
 {
     // Get the space dimension from the bulk mesh:
-    auto const space_dimension = getSpaceDimension(*meshes[0]);
+    auto const space_dimension = getSpaceDimension(meshes[0]->getNodes());
     for (auto& mesh : meshes)
     {
         auto elements = mesh->getElements();
-- 
GitLab