Revision 911b54edbd517a4f19fd83b75a940d1c58a78584 authored by Julian Heinze on 13 June 2023, 14:28:53 UTC, committed by Dmitri Naumov on 13 June 2023, 16:34:52 UTC
1 parent 2bfe60b
TemplateElement.h
/**
* \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 <array>
#include <limits>
#include "MathLib/Point3d.h"
#include "MeshLib/Node.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Elements/FaceRule.h"
#include "MeshLib/Elements/CellRule.h"
#include "MeshLib/Elements/ElementErrorCode.h"
namespace MeshLib
{
/**
* Template for implementing mesh element classes
*
* \tparam T_BASE Base element class, e.g. Face, Cell
* \tparam ELEMENT_RULE Geometrical and topological rules of the element
*/
template <class ELEMENT_RULE>
class TemplateElement : public Element
{
public:
/// Constant: The number of all nodes for this element
static const unsigned n_all_nodes = ELEMENT_RULE::n_all_nodes;
/// Constant: The number of base nodes for this element
static const unsigned n_base_nodes = ELEMENT_RULE::n_base_nodes;
/// Constant: The dimension of this element
static const unsigned dimension = ELEMENT_RULE::dimension;
/**
* Constructor with an array of mesh nodes.
*
* @param nodes an array of pointers of mesh nodes which form this element
* @param id element id
*/
explicit TemplateElement(
Node* nodes[n_all_nodes],
std::size_t id = std::numeric_limits<std::size_t>::max());
/**
* Constructor with an array of mesh nodes
*
* @param nodes an array of pointers of mesh nodes which form this element
* @param id element id
*/
explicit TemplateElement(
std::array<Node*, n_all_nodes> const& nodes,
std::size_t id = std::numeric_limits<std::size_t>::max());
/// Copy constructor
explicit TemplateElement(const TemplateElement& e);
/// Returns a copy of this object.
Element* clone() const override { return new TemplateElement(*this); }
Element* clone(Node** nodes, std::size_t id) const override
{
return new TemplateElement(nodes, id);
}
/// Get dimension of the mesh element.
constexpr unsigned getDimension() const override { return dimension; }
/// Returns the edge i of the element.
const Element* getEdge(unsigned i) const override
{
return ELEMENT_RULE::EdgeReturn::getEdge(this, i);
}
/// Returns the face i of the element.
const Element* getFace(unsigned i) const override
{
return ELEMENT_RULE::getFace(this, i);
}
/// Returns the boundary i of the element.
const Element* getBoundary(unsigned i) const override
{
if constexpr (std::is_convertible<ELEMENT_RULE, FaceRule>::value)
{
return ELEMENT_RULE::EdgeReturn::getEdge(this, i);
}
if constexpr (std::is_convertible<ELEMENT_RULE, CellRule>::value)
{
return ELEMENT_RULE::getFace(this, i);
}
OGS_FATAL("TemplateElement::getBoundary for boundary {:d} failed.", i);
}
/// Returns the number of boundaries of the element.
unsigned getNumberOfBoundaries() const override
{
if constexpr (std::is_convertible<ELEMENT_RULE, FaceRule>::value)
{
return ELEMENT_RULE::n_edges;
}
else
{
return ELEMENT_RULE::n_faces;
}
}
/// Get the number of edges for this element.
unsigned getNumberOfEdges() const override { return ELEMENT_RULE::n_edges; }
/// Get the number of faces for this element.
unsigned getNumberOfFaces() const override { return ELEMENT_RULE::n_faces; }
/// Get the number of neighbors for this element.
unsigned getNumberOfNeighbors() const override
{
return ELEMENT_RULE::n_neighbors;
}
const Element* getNeighbor(unsigned i) const override
{
#ifndef NDEBUG
if (i < ELEMENT_RULE::n_neighbors)
#endif
{
return _neighbors[i];
}
#ifndef NDEBUG
ERR("Error in MeshLib::TemplateElement::getNeighbor() - Index {:d} "
"does not exist.",
i);
return nullptr;
#endif
}
/// Get the number of linear nodes for this element.
unsigned getNumberOfBaseNodes() const override { return n_base_nodes; }
/// Get the number of all nodes for this element.
unsigned getNumberOfNodes() const override { return n_all_nodes; }
/// Get the type of this element.
MeshElemType getGeomType() const override
{
return ELEMENT_RULE::mesh_elem_type;
}
/// Get the FEM type of this element.
CellType getCellType() const override { return ELEMENT_RULE::cell_type; }
/// Returns true if these two indices form an edge and false otherwise
bool isEdge(unsigned idx1, unsigned idx2) const override;
/**
* \copydoc MeshLib::Element::isPntInElement()
*
* This is actually calling the correct implementation of this function
* passing the element's nodes.
*/
bool isPntInElement(
MathLib::Point3d const& pnt,
double eps = std::numeric_limits<double>::epsilon()) const override
{
return ELEMENT_RULE::isPntInElement(_nodes.data(), pnt, eps);
}
/**
* Tests if the element is geometrically valid.
*/
ElementErrorCode validate() const override
{
return ELEMENT_RULE::validate(this);
}
/// Returns the ID of a face given an array of nodes.
unsigned identifyFace(Node const* nodes[3]) const override
{
return ELEMENT_RULE::identifyFace(_nodes.data(), nodes);
}
/// Calculates the volume of a convex hexahedron by partitioning it into six tetrahedra.
double computeVolume() override
{
return ELEMENT_RULE::computeVolume(_nodes.data());
}
const Node* getNode(unsigned idx) const override;
Node* getNode(unsigned idx) override;
void setNode(unsigned idx, Node* node) override;
Node* const* getNodes() const override { return _nodes.data(); }
/// Return a specific edge node.
inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const override
{
if (getNumberOfEdges() > 0)
{
return const_cast<Node*>(
_nodes[ELEMENT_RULE::edge_nodes[edge_id][node_id]]);
}
return nullptr;
}
/**
* Checks if the node order of an element is correct by testing surface normals.
* For 1D elements this always returns true.
*/
bool testElementNodeOrder() const override
{
return ELEMENT_RULE::testElementNodeOrder(*this);
}
double getContent() const override final;
std::array<Node*, n_all_nodes> _nodes;
};
} // namespace MeshLib
#include "TemplateElement-impl.h"
Computing file changes ...