From 4107ae26c386358f395cbf5cf8ff8fc58ee6cb3a Mon Sep 17 00:00:00 2001 From: Dmitri Naumov <dmitri.naumov@ufz.de> Date: Fri, 14 Jul 2023 19:01:32 +0200 Subject: [PATCH] [MeL] Extract common HexRule subclass --- MeshLib/Elements/HexRule.cpp | 72 +++++++++++++++++++++++++++++++ MeshLib/Elements/HexRule.h | 80 +++++++++++++++++++++++++++++++++++ MeshLib/Elements/HexRule20.h | 12 ++++-- MeshLib/Elements/HexRule8.cpp | 78 ---------------------------------- MeshLib/Elements/HexRule8.h | 45 +++----------------- 5 files changed, 167 insertions(+), 120 deletions(-) create mode 100644 MeshLib/Elements/HexRule.cpp create mode 100644 MeshLib/Elements/HexRule.h diff --git a/MeshLib/Elements/HexRule.cpp b/MeshLib/Elements/HexRule.cpp new file mode 100644 index 00000000000..6210426f4a9 --- /dev/null +++ b/MeshLib/Elements/HexRule.cpp @@ -0,0 +1,72 @@ +/** + * \file + * \copyright + * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + */ + +#include "HexRule.h" + +#include "MathLib/GeometricBasics.h" +#include "MeshLib/Node.h" +#include "Quad.h" + +namespace MeshLib +{ +double HexRule::computeVolume(Node const* const* _nodes) +{ + return MathLib::calcTetrahedronVolume( + *_nodes[4], *_nodes[7], *_nodes[5], *_nodes[0]) + + MathLib::calcTetrahedronVolume( + *_nodes[5], *_nodes[3], *_nodes[1], *_nodes[0]) + + MathLib::calcTetrahedronVolume( + *_nodes[5], *_nodes[7], *_nodes[3], *_nodes[0]) + + MathLib::calcTetrahedronVolume( + *_nodes[5], *_nodes[7], *_nodes[6], *_nodes[2]) + + MathLib::calcTetrahedronVolume( + *_nodes[1], *_nodes[3], *_nodes[5], *_nodes[2]) + + MathLib::calcTetrahedronVolume( + *_nodes[3], *_nodes[7], *_nodes[5], *_nodes[2]); +} + +bool HexRule::isPntInElement(Node const* const* nodes, + MathLib::Point3d const& pnt, + double eps) +{ + return (MathLib::isPointInTetrahedron( + pnt, *nodes[4], *nodes[7], *nodes[5], *nodes[0], eps) || + MathLib::isPointInTetrahedron( + pnt, *nodes[5], *nodes[3], *nodes[1], *nodes[0], eps) || + MathLib::isPointInTetrahedron( + pnt, *nodes[5], *nodes[7], *nodes[3], *nodes[0], eps) || + MathLib::isPointInTetrahedron( + pnt, *nodes[5], *nodes[7], *nodes[6], *nodes[2], eps) || + MathLib::isPointInTetrahedron( + pnt, *nodes[1], *nodes[3], *nodes[5], *nodes[2], eps) || + MathLib::isPointInTetrahedron( + pnt, *nodes[3], *nodes[7], *nodes[5], *nodes[2], eps)); +} + +ElementErrorCode HexRule::validate(const Element* e) +{ + ElementErrorCode error_code; + error_code[ElementErrorFlag::ZeroVolume] = hasZeroVolume(*e); + + for (unsigned i = 0; i < 6; ++i) + { + if (error_code.all()) + { + break; + } + + const MeshLib::Element* quad(e->getFace(i)); + error_code |= quad->validate(); + delete quad; + } + error_code[ElementErrorFlag::NodeOrder] = !e->testElementNodeOrder(); + return error_code; +} + +} // end namespace MeshLib diff --git a/MeshLib/Elements/HexRule.h b/MeshLib/Elements/HexRule.h new file mode 100644 index 00000000000..203c3b9c3a6 --- /dev/null +++ b/MeshLib/Elements/HexRule.h @@ -0,0 +1,80 @@ +/** + * \file + * \copyright + * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include "CellRule.h" +#include "Element.h" +#include "MeshLib/MeshEnums.h" + +namespace MeshLib +{ +class HexRule : public CellRule +{ +public: + /// Constant: The number of base nodes for this element + static const unsigned n_base_nodes = 8u; + + /// Constant: The geometric type of the element + static const MeshElemType mesh_elem_type = MeshElemType::HEXAHEDRON; + + /// Constant: The number of faces + static const unsigned n_faces = 6; + + /// Constant: The number of edges + static const unsigned n_edges = 12; + + /// Constant: The number of neighbors + static const unsigned n_neighbors = 6; + + /** + * \copydoc MeshLib::Element::isPntInElement() + * \param nodes the nodes of the element. + */ + static bool isPntInElement(Node const* const* nodes, + MathLib::Point3d const& pnt, double eps); + + /** + * Tests if the element is geometrically valid. + */ + static ElementErrorCode validate(const Element* e); + + /// Calculates the volume of a convex hexahedron by partitioning it into six + /// tetrahedra. + static double computeVolume(Node const* const* _nodes); + +protected: + template <std::size_t N> + static unsigned identifyFace(Node const* const* _nodes, + Node const* nodes[3], + unsigned const face_nodes[6][N]) + { + for (unsigned i = 0; i < 6; i++) + { + unsigned flag(0); + for (unsigned j = 0; j < 4; j++) + { + for (unsigned k = 0; k < 3; k++) + { + if (_nodes[face_nodes[i][j]] == nodes[k]) + { + flag++; + } + } + } + if (flag == 3) + { + return i; + } + } + return std::numeric_limits<unsigned>::max(); + } +}; +} // namespace MeshLib diff --git a/MeshLib/Elements/HexRule20.h b/MeshLib/Elements/HexRule20.h index 19bb18bacb9..b5024f5aaa9 100644 --- a/MeshLib/Elements/HexRule20.h +++ b/MeshLib/Elements/HexRule20.h @@ -10,10 +10,8 @@ #pragma once -#include "MeshLib/MeshEnums.h" -#include "Element.h" #include "EdgeReturn.h" -#include "HexRule8.h" +#include "HexRule.h" namespace MeshLib { @@ -43,7 +41,7 @@ namespace MeshLib * * \endcode */ -class HexRule20 : public HexRule8 +class HexRule20 : public HexRule { public: /// Constant: The number of all nodes for this element @@ -64,6 +62,12 @@ public: /// Returns the i-th face of the element. static const Element* getFace(const Element* e, unsigned i); + /// Returns the ID of a face given an array of nodes. + static unsigned identifyFace(Node const* const* _nodes, + Node const* nodes[3]) + { + return HexRule::identifyFace(_nodes, nodes, face_nodes); + } }; /* class */ } // namespace MeshLib diff --git a/MeshLib/Elements/HexRule8.cpp b/MeshLib/Elements/HexRule8.cpp index 1144c14a71e..52d31ad4d1e 100644 --- a/MeshLib/Elements/HexRule8.cpp +++ b/MeshLib/Elements/HexRule8.cpp @@ -58,82 +58,4 @@ const Element* HexRule8::getFace(const Element* e, unsigned i) ERR("Error in MeshLib::Element::getFace() - Index {:d} does not exist.", i); return nullptr; } - -double HexRule8::computeVolume(Node const* const* _nodes) -{ - return MathLib::calcTetrahedronVolume( - *_nodes[4], *_nodes[7], *_nodes[5], *_nodes[0]) + - MathLib::calcTetrahedronVolume( - *_nodes[5], *_nodes[3], *_nodes[1], *_nodes[0]) + - MathLib::calcTetrahedronVolume( - *_nodes[5], *_nodes[7], *_nodes[3], *_nodes[0]) + - MathLib::calcTetrahedronVolume( - *_nodes[5], *_nodes[7], *_nodes[6], *_nodes[2]) + - MathLib::calcTetrahedronVolume( - *_nodes[1], *_nodes[3], *_nodes[5], *_nodes[2]) + - MathLib::calcTetrahedronVolume( - *_nodes[3], *_nodes[7], *_nodes[5], *_nodes[2]); -} - -bool HexRule8::isPntInElement(Node const* const* nodes, - MathLib::Point3d const& pnt, - double eps) -{ - return (MathLib::isPointInTetrahedron( - pnt, *nodes[4], *nodes[7], *nodes[5], *nodes[0], eps) || - MathLib::isPointInTetrahedron( - pnt, *nodes[5], *nodes[3], *nodes[1], *nodes[0], eps) || - MathLib::isPointInTetrahedron( - pnt, *nodes[5], *nodes[7], *nodes[3], *nodes[0], eps) || - MathLib::isPointInTetrahedron( - pnt, *nodes[5], *nodes[7], *nodes[6], *nodes[2], eps) || - MathLib::isPointInTetrahedron( - pnt, *nodes[1], *nodes[3], *nodes[5], *nodes[2], eps) || - MathLib::isPointInTetrahedron( - pnt, *nodes[3], *nodes[7], *nodes[5], *nodes[2], eps)); -} - -unsigned HexRule8::identifyFace(Node const* const* _nodes, Node const* nodes[3]) -{ - for (unsigned i = 0; i < 6; i++) - { - unsigned flag(0); - for (unsigned j = 0; j < 4; j++) - { - for (unsigned k = 0; k < 3; k++) - { - if (_nodes[face_nodes[i][j]] == nodes[k]) - { - flag++; - } - } - } - if (flag == 3) - { - return i; - } - } - return std::numeric_limits<unsigned>::max(); -} - -ElementErrorCode HexRule8::validate(const Element* e) -{ - ElementErrorCode error_code; - error_code[ElementErrorFlag::ZeroVolume] = hasZeroVolume(*e); - - for (unsigned i = 0; i < 6; ++i) - { - if (error_code.all()) - { - break; - } - - const MeshLib::Element* quad(e->getFace(i)); - error_code |= quad->validate(); - delete quad; - } - error_code[ElementErrorFlag::NodeOrder] = !e->testElementNodeOrder(); - return error_code; -} - } // end namespace MeshLib diff --git a/MeshLib/Elements/HexRule8.h b/MeshLib/Elements/HexRule8.h index d1501fbfb49..d1bb1ef2c79 100644 --- a/MeshLib/Elements/HexRule8.h +++ b/MeshLib/Elements/HexRule8.h @@ -10,14 +10,11 @@ #pragma once -#include "MeshLib/MeshEnums.h" -#include "Element.h" #include "EdgeReturn.h" -#include "CellRule.h" +#include "HexRule.h" namespace MeshLib { - /** * A 8-nodes Hexahedron Element. * \code @@ -43,30 +40,15 @@ namespace MeshLib * * \endcode */ -class HexRule8 : public CellRule +class HexRule8 : public HexRule { public: - /// Constant: The number of base nodes for this element - static const unsigned n_base_nodes = 8u; - /// Constant: The number of all nodes for this element static const unsigned n_all_nodes = 8u; - /// Constant: The geometric type of the element - static const MeshElemType mesh_elem_type = MeshElemType::HEXAHEDRON; - /// Constant: The FEM type of the element static const CellType cell_type = CellType::HEX8; - /// Constant: The number of faces - static const unsigned n_faces = 6; - - /// Constant: The number of edges - static const unsigned n_edges = 12; - - /// Constant: The number of neighbors - static const unsigned n_neighbors = 6; - /// Constant: Local node index table for faces static const unsigned face_nodes[6][4]; @@ -79,25 +61,12 @@ public: /// Returns the i-th face of the element. static const Element* getFace(const Element* e, unsigned i); - /** - * \copydoc MeshLib::Element::isPntInElement() - * \param nodes the nodes of the element. - */ - static bool isPntInElement(Node const* const* nodes, - MathLib::Point3d const& pnt, double eps); - - /** - * Tests if the element is geometrically valid. - */ - static ElementErrorCode validate(const Element* e); - /// Returns the ID of a face given an array of nodes. - static unsigned identifyFace(Node const* const* /*_nodes*/, - Node const* nodes[3]); - - /// Calculates the volume of a convex hexahedron by partitioning it into six tetrahedra. - static double computeVolume(Node const* const* _nodes); - + static unsigned identifyFace(Node const* const* _nodes, + Node const* nodes[3]) + { + return HexRule::identifyFace(_nodes, nodes, face_nodes); + } }; /* class */ } // namespace MeshLib -- GitLab