From 37d27f636a4c7772e95b9339c86c20a6df16c95c Mon Sep 17 00:00:00 2001 From: Wenqing Wang <wenqing.wang@ufz.de> Date: Tue, 18 May 2021 17:10:16 +0200 Subject: [PATCH] [UnitTest] Added a test for getElementRotationMatrices with 3D mesh --- .../TestGetElementRotationMatrices.cpp | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 Tests/MeshLib/TestGetElementRotationMatrices.cpp diff --git a/Tests/MeshLib/TestGetElementRotationMatrices.cpp b/Tests/MeshLib/TestGetElementRotationMatrices.cpp new file mode 100644 index 00000000000..685f3b082f4 --- /dev/null +++ b/Tests/MeshLib/TestGetElementRotationMatrices.cpp @@ -0,0 +1,133 @@ +/** + * \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 18, 2021, 12:31 PM + */ + +#include <gtest/gtest.h> + +#include <array> +#include <memory> +#include <string> +#include <vector> + +#include "MeshLib/Elements/Element.h" +#include "MeshLib/Elements/Elements.h" +#include "MeshLib/Mesh.h" +#include "MeshLib/MeshEnums.h" +#include "MeshLib/Node.h" +#include "MeshLib/Utils/GetElementRotationMatrices.h" +#include "MeshLib/Utils/GetSpaceDimension.h" + +TEST(MeshLib, GetElementRotationMatrices3DMesh) +{ + // The memory of the nodes are allocated by new operator, and it is released + // in the destructor of MeshLib::Mesh. + + // Construct a 3D mesh, which contains two inclined 2D triangle elements + // and an inclined line element. + std::vector<MeshLib::Node*> nodes(10); + nodes[0] = new MeshLib::Node(0.0, 0.0, 0.0, 0); + nodes[1] = new MeshLib::Node(1.0, 0.0, 0.0, 1); + nodes[2] = new MeshLib::Node(1.0, 1.0, 0.0, 2); + nodes[3] = new MeshLib::Node(0.0, 1.0, 0.0, 3); + + nodes[4] = new MeshLib::Node(0.0, 0.0, 1.0, 4); + nodes[5] = new MeshLib::Node(1.0, 0.0, 1.0, 5); + nodes[6] = new MeshLib::Node(1.0, 1.0, 1.0, 6); + nodes[7] = new MeshLib::Node(0.0, 1.0, 1.0, 7); + + nodes[8] = new MeshLib::Node(0.0, 0.5, 1.5, 8); + nodes[9] = new MeshLib::Node(1.0, 0.5, 1.5, 9); + + std::vector<MeshLib::Element*> elements; + + // One hexahedral element: + std::array<MeshLib::Node*, 8> hex_element_nodes; + std::copy_n(nodes.begin(), 8, hex_element_nodes.begin()); + elements.push_back(new MeshLib::Hex(hex_element_nodes)); + + // Two inclined triangle elements: + std::array<MeshLib::Node*, 3> tri_element_nodes{nodes[6], nodes[7], + nodes[8]}; + elements.push_back(new MeshLib::Tri(tri_element_nodes)); + tri_element_nodes[0] = nodes[6]; + tri_element_nodes[1] = nodes[8]; + tri_element_nodes[2] = nodes[9]; + elements.push_back(new MeshLib::Tri(tri_element_nodes)); + + // One inclined line element: + std::array<MeshLib::Node*, 2> line_element_nodes{nodes[6], nodes[8]}; + elements.push_back(new MeshLib::Line(line_element_nodes)); + + std::vector<std::unique_ptr<MeshLib::Mesh>> meshes; + meshes.push_back( + std::make_unique<MeshLib::Mesh>("a_mesh", nodes, elements)); + + int const space_dimension = MeshLib::getSpaceDimension(nodes); + auto const element_rotation_matrices = MeshLib::getElementRotationMatrices( + space_dimension, meshes[0]->getDimension(), meshes[0]->getElements()); + + // First element, the hexahedral element has identity matrix: + EXPECT_EQ(9, element_rotation_matrices[0].size()); + + // Second and third elements, the inclined triangle elements on the + // same plane: + auto const& rotation_matrix_tri1 = element_rotation_matrices[1]; + auto const& rotation_matrix_tri2 = element_rotation_matrices[2]; + + double const diff = (rotation_matrix_tri1 - rotation_matrix_tri2).norm(); + ASSERT_LE(diff, 1e-10); + + Eigen::VectorXd b(3); + b[0] = 0.0; + b[1] = 0.0; + b[2] = 1.0; + + // Projection test + Eigen::VectorXd const b_local = rotation_matrix_tri1.transpose() * b; + EXPECT_EQ(elements[1]->getDimension(), b_local.size()); + EXPECT_EQ(0.0, b_local[0]); + double const expected_b_local1 = -std::sqrt(2.0) / 2.0; + EXPECT_LE(std::fabs(b_local[1] - expected_b_local1), 1.e-16); + + // Forth element, the inclined line element: + Eigen::VectorXd const b_local_1D = + element_rotation_matrices[3].transpose() * b; + EXPECT_EQ(elements[3]->getDimension(), b_local_1D.size()); + + double const* const x_6 = nodes[6]->getCoords(); + double const* const x_8 = nodes[8]->getCoords(); + // b_local_1D = |b| (x_8-x_6) * b/(|(x_8-x_6)| |b|) + double dx[3]; + for (int i = 0; i < 3; i++) + { + dx[i] = x_8[i] - x_6[i]; + } + + double const dx_norm = + std::sqrt(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]); + double const expected_b_local_1D = dx[2] / dx_norm; + EXPECT_LE(std::fabs(expected_b_local_1D - b_local_1D[0]), 1.e-16); + + // Test of rotation of a local vector to the global system + Eigen::VectorXd const local_1D_to_global = + element_rotation_matrices[3] * b_local_1D; + EXPECT_EQ(meshes[0]->getDimension(), local_1D_to_global.size()); + + double const local_1D_to_global_norm = + std::sqrt(local_1D_to_global[0] * local_1D_to_global[0] + + local_1D_to_global[1] * local_1D_to_global[1] + + local_1D_to_global[2] * local_1D_to_global[2]); + for (int i = 0; i < 3; i++) + { + EXPECT_LE(std::fabs(dx[i] / dx_norm - + local_1D_to_global[i] / local_1D_to_global_norm), + 1.e-15); + } +} -- GitLab