OGS
Element.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "Element.h"
5
6#include "BaseLib/Logging.h"
7#include "Line.h"
9#include "MathLib/MathTools.h"
10#include "MeshLib/Node.h"
11
12namespace MeshLib
13{
14Element::Element(std::size_t id) : _id(id), _neighbors(nullptr) {}
15
17{
18 delete[] this->_neighbors;
19}
20
21void Element::setNeighbor(Element* neighbor, unsigned const face_id)
22{
23 if (neighbor == this)
24 {
25 return;
26 }
27
28 this->_neighbors[face_id] = neighbor;
29}
30
31std::optional<unsigned> Element::addNeighbor(Element* e)
32{
33 const unsigned dim(this->getDimension());
34 if (e == this || e == nullptr || e->getDimension() != dim)
35 {
36 return std::optional<unsigned>();
37 }
38
39 if (areNeighbors(this, e))
40 {
41 return std::optional<unsigned>();
42 }
43
44 Node const* face_nodes[3];
45 const unsigned nNodes(this->getNumberOfBaseNodes());
46 const unsigned eNodes(e->getNumberOfBaseNodes());
47 const Node* const* e_nodes = e->getNodes();
48 unsigned count(0);
49 for (unsigned i(0); i < nNodes; i++)
50 {
51 for (unsigned j(0); j < eNodes; j++)
52 {
53 if (getNode(i) == e_nodes[j])
54 {
55 face_nodes[count] = getNode(i);
56 // increment shared nodes counter and check if enough nodes are
57 // similar to be sure e is a neighbour of this
58 if ((++count) >= dim)
59 {
60 auto const this_face_id = this->identifyFace(face_nodes);
61 if (this_face_id == std::numeric_limits<unsigned>::max())
62 {
64 "Could not find face of {} for the face nodes [{}, "
65 "{}, {}].",
66 *this, *face_nodes[0], *face_nodes[1],
67 *face_nodes[2]);
68 }
69 _neighbors[this_face_id] = e;
70 auto const neighbors_face_id = e->identifyFace(face_nodes);
71 if (neighbors_face_id ==
72 std::numeric_limits<unsigned>::max())
73 {
75 "Could not find face of the neighbour {} for the "
76 "face nodes [{}, {}, {}].\n"
77 "For the {} the face id {} was identified.",
78 *e, *face_nodes[0], *face_nodes[1], *face_nodes[2],
79 *this, this_face_id);
80 }
81 return neighbors_face_id;
82 }
83 }
84 }
85 }
86
87 return std::optional<unsigned>();
88}
89
91{
92 return std::any_of(_neighbors, _neighbors + this->getNumberOfNeighbors(),
93 [](MeshLib::Element const* const e)
94 { return e == nullptr; });
95}
96
97std::ostream& operator<<(std::ostream& os, Element const& e)
98{
99 os << "element #" << e._id << " @ " << &e << " with "
100 << e.getNumberOfNeighbors() << " neighbours\n";
101
102 unsigned const nnodes = e.getNumberOfNodes();
103 MeshLib::Node* const* const nodes = e.getNodes();
104 os << "MeshElemType: " << MeshLib::MeshElemType2String(e.getGeomType())
105 << " with " << nnodes << " nodes: {\n";
106 for (unsigned n = 0; n < nnodes; ++n)
107 {
108 os << " " << *nodes[n] << " @ " << nodes[n] << '\n';
109 }
110 return os << '}';
111}
112
113bool areNeighbors(Element const* const element, Element const* const other)
114{
115 unsigned nNeighbors(element->getNumberOfNeighbors());
116 for (unsigned i = 0; i < nNeighbors; i++)
117 {
118 if (element->getNeighbor(i) == other)
119 {
120 return true;
121 }
122 }
123 return false;
124}
125
126bool hasZeroVolume(MeshLib::Element const& element)
127{
128 return element.getContent() < std::numeric_limits<double>::epsilon();
129}
130
132{
133 const unsigned nNodes(element.getNumberOfBaseNodes());
134 MathLib::Point3d center{{0, 0, 0}};
135 for (unsigned i = 0; i < nNodes; ++i)
136 {
137 center.asEigenVector3d() += element.getNode(i)->asEigenVector3d();
138 }
139 center.asEigenVector3d() /= nNodes;
140 return center;
141}
142
143std::pair<double, double> computeSqrNodeDistanceRange(
144 MeshLib::Element const& element, bool const check_allnodes)
145{
146 double min = std::numeric_limits<double>::max();
147 double max = 0;
148 const unsigned nnodes = check_allnodes ? element.getNumberOfNodes()
149 : element.getNumberOfBaseNodes();
150 for (unsigned i = 0; i < nnodes; i++)
151 {
152 for (unsigned j = i + 1; j < nnodes; j++)
153 {
154 const double dist(
155 MathLib::sqrDist(*element.getNode(i), *element.getNode(j)));
156 min = std::min(dist, min);
157 max = std::max(dist, max);
158 }
159 }
160 return {min, max};
161}
162
163std::pair<double, double> computeSqrEdgeLengthRange(Element const& element)
164{
165 double min = std::numeric_limits<double>::max();
166 double max = 0;
167 const unsigned nEdges(element.getNumberOfEdges());
168 for (unsigned i = 0; i < nEdges; i++)
169 {
170 const double dist(MathLib::sqrDist(*element.getEdgeNode(i, 0),
171 *element.getEdgeNode(i, 1)));
172 min = std::min(dist, min);
173 max = std::max(dist, max);
174 }
175 return {min, max};
176}
177
179{
180 for (std::size_t i(0); i < e.getNumberOfBaseNodes(); ++i)
181 {
182 if (MathLib::sqrDist2d(p, *e.getNode(i)) <
183 std::numeric_limits<double>::epsilon())
184 {
185 return true;
186 }
187 }
188
190 {
191 MathLib::Point3d const& n0(*e.getNode(0));
192 MathLib::Point3d const& n1(*e.getNode(1));
193 MathLib::Point3d const& n2(*e.getNode(2));
194
195 return MathLib::isPointInTriangleXY(p, n0, n1, n2);
196 }
198 {
199 MathLib::Point3d const& n0(*e.getNode(0));
200 MathLib::Point3d const& n1(*e.getNode(1));
201 MathLib::Point3d const& n2(*e.getNode(2));
202 MathLib::Point3d const& n3(*e.getNode(3));
203
204 return MathLib::isPointInTriangleXY(p, n0, n1, n2) ||
205 MathLib::isPointInTriangleXY(p, n0, n2, n3);
206 }
207
208 WARN("isPointInElementXY: element type '{:s}' is not supported.",
210 return false;
211}
212
213unsigned getNodeIDinElement(Element const& element, const MeshLib::Node* node)
214{
215 const unsigned nNodes(element.getNumberOfNodes());
216 for (unsigned i(0); i < nNodes; i++)
217 {
218 if (node == element.getNode(i))
219 {
220 return i;
221 }
222 }
223 return std::numeric_limits<unsigned>::max();
224}
225
226std::size_t getNodeIndex(Element const& element, unsigned const idx)
227{
228#ifndef NDEBUG
229 if (idx >= element.getNumberOfNodes())
230 {
231 ERR("Error in MeshLib::getNodeIndex() - Index does not "
232 "exist.");
233 return std::numeric_limits<std::size_t>::max();
234 }
235#endif
236 return element.getNode(idx)->getID();
237}
238
239} // namespace MeshLib
#define OGS_FATAL(...)
Definition Error.h:19
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::size_t getID() const
Eigen::Vector3d const & asEigenVector3d() const
Definition Point3d.h:55
virtual MeshElemType getGeomType() const =0
void setNeighbor(Element *neighbor, unsigned const face_id)
Definition Element.cpp:21
virtual ~Element()
Destructor.
Definition Element.cpp:16
virtual unsigned getNumberOfNodes() const =0
virtual double getContent() const =0
Returns the length, area or volume of a 1D, 2D or 3D element.
Element ** _neighbors
Definition Element.h:193
Element(std::size_t id)
Definition Element.cpp:14
virtual unsigned getNumberOfBaseNodes() const =0
virtual bool isBoundaryElement() const
Definition Element.cpp:90
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfNeighbors() const =0
Get the number of neighbors for this element.
std::size_t _id
Definition Element.h:191
virtual unsigned getNumberOfEdges() const =0
Get the number of edges for this element.
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
std::optional< unsigned > addNeighbor(Element *e)
Tries to add an element e as neighbour to this element. If the elements really are neighbours,...
Definition Element.cpp:31
constexpr std::span< Node *const > nodes() const
Span of element's nodes, their pointers actually.
Definition Element.h:63
virtual Node *const * getNodes() const =0
Get array of element nodes.
virtual const Element * getNeighbor(unsigned i) const =0
Get the specified neighbor.
virtual Node * getEdgeNode(unsigned edge_id, unsigned node_id) const =0
Return a specific edge node.
virtual unsigned identifyFace(Node const *nodes[3]) const =0
Returns the ID of a face given an array of nodes.
double sqrDist2d(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition Point3d.h:114
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition Point3d.cpp:19
bool isPointInTriangleXY(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c)
std::pair< double, double > computeSqrNodeDistanceRange(MeshLib::Element const &element, bool const check_allnodes)
Compute the minimum and maximum node distances for this element.
Definition Element.cpp:143
bool isPointInElementXY(MathLib::Point3d const &p, Element const &e)
Definition Element.cpp:178
bool hasZeroVolume(MeshLib::Element const &element)
Returns true if the element has zero length/area/volume.
Definition Element.cpp:126
std::string MeshElemType2String(const MeshElemType t)
Given a MeshElemType this returns the appropriate string.
Definition MeshEnums.cpp:10
std::pair< double, double > computeSqrEdgeLengthRange(Element const &element)
Compute the minimum and maximum squared edge length for this element.
Definition Element.cpp:163
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition Element.cpp:226
unsigned getNodeIDinElement(Element const &element, const MeshLib::Node *node)
Returns the position of the given node in the node array of this element.
Definition Element.cpp:213
MathLib::Point3d getCenterOfGravity(Element const &element)
Calculates the center of gravity for the mesh element.
Definition Element.cpp:131
std::ostream & operator<<(std::ostream &os, Element const &e)
Definition Element.cpp:97
bool areNeighbors(Element const *const element, Element const *const other)
Returns true if elem is a neighbour of this element and false otherwise.
Definition Element.cpp:113