Skip to content

Commit ac2fdf7

Browse files
committed
Add ElemCorner
1 parent d7c6fba commit ac2fdf7

5 files changed

Lines changed: 397 additions & 15 deletions

File tree

include/geom/elem.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include <algorithm>
4040
#include <cstddef>
4141
#include <iostream>
42-
#include <limits.h> // CHAR_BIT
42+
#include <limits.h> // CHAR_BIT, std::numeric_limits
4343
#include <set>
4444
#include <vector>
4545
#include <memory>
@@ -224,18 +224,13 @@ class Elem : public ReferenceCountedObject<Elem>,
224224
/**
225225
* A static integral constant representing an invalid subdomain id.
226226
* See also DofObject::{invalid_id, invalid_unique_id, invalid_processor_id}.
227-
*
228-
* \note We don't use the static_cast(-1) trick here since
229-
* \p subdomain_id_type is sometimes a *signed* integer for
230-
* compatibility reasons (see libmesh/id_types.h).
231-
*
232-
* \note Normally you can declare static const integral types
233-
* directly in the header file (C++ standard, 9.4.2/4) but
234-
* std::numeric_limits<T>::max() is not considered a "constant
235-
* expression". This one is therefore defined in elem.C.
236-
* http://stackoverflow.com/questions/2738435/using-numeric-limitsmax-in-constant-expressions
237227
*/
238-
static const subdomain_id_type invalid_subdomain_id;
228+
static constexpr subdomain_id_type invalid_subdomain_id = std::numeric_limits<subdomain_id_type>::max();
229+
230+
/**
231+
* A static integral constant representing an invalid index to a vertex.
232+
*/
233+
static constexpr unsigned short invalid_vertex = std::numeric_limits<unsigned short>::max();
239234

240235
/**
241236
* \returns A pointer to the "reference element" associated

include/geom/elem_corner.h

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// The libMesh Finite Element Library.
2+
// Copyright (C) 2002-2022 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3+
4+
// This library is free software; you can redistribute it and/or
5+
// modify it under the terms of the GNU Lesser General Public
6+
// License as published by the Free Software Foundation; either
7+
// version 2.1 of the License, or (at your option) any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
// Lesser General Public License for more details.
13+
14+
// You should have received a copy of the GNU Lesser General Public
15+
// License along with this library; if not, write to the Free Software
16+
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
18+
19+
20+
#ifndef LIBMESH_ELEMCORNER_H
21+
#define LIBMESH_ELEMCORNER_H
22+
23+
#include "libmesh/libmesh_common.h"
24+
25+
#if LIBMESH_DIM > 1
26+
27+
#include "libmesh/elem.h"
28+
29+
#include <utility> // std::pair
30+
31+
namespace libMesh
32+
{
33+
34+
/**
35+
* The \p ElemCorner is a helper class for defining whether or not
36+
* _something_ is at an element vertex or edge. In this context,
37+
* we define corner as a vertex in 2D and as a vertex or an edge
38+
* in 3D.
39+
*
40+
* This class is typically used in intersection algorithms, in which
41+
* it should be interfaced with by using the \p at_corner(),
42+
* \p at_edge(), and \p at_vertex() methods.
43+
*
44+
* Internally, it keeps track of whether or not at one of these
45+
* "corners" by storing a set of indicies that denote vertex indices.
46+
* If the first is valid and the second is not, it implies
47+
* being at the vertex with said index. If both are valid, it implies
48+
* being at the edge defined by the verticies with said indices.
49+
*/
50+
class ElemCorner : public std::pair<unsigned short, unsigned short>
51+
{
52+
public:
53+
/**
54+
* Default constructor: sets entires to invalid (not at vertex or edge)
55+
*/
56+
ElemCorner()
57+
: std::pair<unsigned short, unsigned short>(Elem::invalid_vertex,
58+
Elem::invalid_vertex) { }
59+
60+
/**
61+
* Constructor with given vertex indices \p v1 and \p v2.
62+
*/
63+
ElemCorner(const unsigned short v1, const unsigned short v2)
64+
: std::pair<unsigned short, unsigned short>(v1, v2) { }
65+
66+
/**
67+
* @returns true if at the corner (edge or vertex)
68+
*/
69+
bool at_corner() const { return first != Elem::invalid_vertex; }
70+
71+
/**
72+
* @returns true if the vertex index data is invalid
73+
*/
74+
bool is_invalid() const
75+
{ return first == Elem::invalid_vertex && second == Elem::invalid_vertex; }
76+
77+
/**
78+
* @returns true if at a vertex
79+
*/
80+
bool at_vertex() const
81+
{ return first != Elem::invalid_vertex && second == Elem::invalid_vertex; }
82+
/**
83+
* @returns true if at vertex \p v
84+
*/
85+
bool at_vertex(const unsigned short v) const
86+
{ return first == v && second == Elem::invalid_vertex; }
87+
88+
/**
89+
* Invalidates the current state
90+
*/
91+
void invalidate()
92+
{
93+
first = Elem::invalid_vertex;
94+
second = Elem::invalid_vertex;
95+
}
96+
97+
/**
98+
* @returns The vertex ID when at a vertex
99+
*/
100+
unsigned short vertex() const
101+
{ libmesh_assert(at_vertex()); return first; }
102+
103+
/**
104+
* Prints the current state (at edge, at vertex, not at either)
105+
*/
106+
std::string print() const;
107+
108+
/**
109+
* Sets the "at vertex" state
110+
*/
111+
void set_vertex(const unsigned short v)
112+
{
113+
libmesh_assert_not_equal_to(v, Elem::invalid_vertex);
114+
first = v;
115+
second = Elem::invalid_vertex;
116+
}
117+
118+
#if LIBMESH_DIM > 2
119+
/**
120+
* @returns true if at an edge
121+
*/
122+
bool at_edge() const
123+
{ return first != Elem::invalid_vertex && second != Elem::invalid_vertex; }
124+
/**
125+
* @returns true if at the edge defined by vertices \p v1 and \p v2
126+
*/
127+
bool at_edge(const unsigned short v1, const unsigned short v2) const
128+
{
129+
libmesh_assert_not_equal_to(v1, Elem::invalid_vertex);
130+
libmesh_assert_not_equal_to(v2, Elem::invalid_vertex);
131+
return (first == v1 && second == v2) || (first == v2 && second == v1);
132+
}
133+
/**
134+
* @returns true if at the edge with index \p e on element \p
135+
*/
136+
bool at_edge(const Elem & elem, const unsigned short e) const;
137+
138+
/**
139+
* @returns The vertices that contain the edge when at an edge
140+
*/
141+
const std::pair<unsigned short, unsigned short> & edge_vertices() const
142+
{ libmesh_assert(at_edge()); return *this; }
143+
144+
/**
145+
* Sets the "at edge" state
146+
*/
147+
void set_edge(const unsigned short v1, const unsigned short v2)
148+
{
149+
libmesh_assert_not_equal_to(v1, Elem::invalid_vertex);
150+
libmesh_assert_not_equal_to(v2, Elem::invalid_vertex);
151+
first = v1;
152+
second = v2;
153+
}
154+
/**
155+
* Sets the "at edge" state
156+
*/
157+
void set_edge(const std::pair<unsigned short, unsigned short> & vs)
158+
{ set_edge(vs.first, vs.second); }
159+
160+
/**
161+
* @returns The edge when at an edge
162+
*/
163+
std::unique_ptr<const Elem> build_edge(const Elem & elem) const;
164+
#endif
165+
166+
/**
167+
* @returns The vertex point when at a vertex
168+
*/
169+
const Point & vertex_point(const Elem & elem) const
170+
{ return elem.point(vertex()); }
171+
172+
/**
173+
* @returns Whether or not the current state (at vertex/edge) is valid
174+
* for the given \p elem and \p point. \p tol is used as the tolerance
175+
* to pass to the equality checks.
176+
*
177+
* This ONLY checks for validity when at_corner().
178+
*/
179+
bool is_valid(const Elem & elem, const Point & point, const Real tol = TOLERANCE) const;
180+
};
181+
182+
} // namespace libMesh
183+
184+
std::ostream & operator<<(std::ostream & os, const libMesh::ElemCorner & elem_corner);
185+
186+
#endif // LIBMESH_DIM > 1
187+
188+
#endif // LIBMESH_ELEMCORNER_H

src/geom/elem.C

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
#include <array>
8383
#include <iterator> // for std::ostream_iterator
8484
#include <sstream>
85-
#include <limits> // for std::numeric_limits<>
8685
#include <cmath> // for std::sqrt()
8786
#include <memory>
8887

@@ -93,8 +92,6 @@ namespace libMesh
9392
Threads::spin_mutex parent_indices_mutex;
9493
Threads::spin_mutex parent_bracketing_nodes_mutex;
9594

96-
const subdomain_id_type Elem::invalid_subdomain_id = std::numeric_limits<subdomain_id_type>::max();
97-
9895
// Initialize static member variables
9996
const unsigned int Elem::max_n_nodes;
10097

src/geom/elem_corner.C

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// The libMesh Finite Element Library.
2+
// Copyright (C) 2002-2022 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3+
4+
// This library is free software; you can redistribute it and/or
5+
// modify it under the terms of the GNU Lesser General Public
6+
// License as published by the Free Software Foundation; either
7+
// version 2.1 of the License, or (at your option) any later version.
8+
9+
// This library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
// Lesser General Public License for more details.
13+
14+
// You should have received a copy of the GNU Lesser General Public
15+
// License along with this library; if not, write to the Free Software
16+
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
18+
19+
// Local includes
20+
#include "libmesh/elem_corner.h"
21+
22+
#if LIBMESH_DIM > 1
23+
24+
namespace libMesh
25+
{
26+
27+
#if LIBMESH_DIM > 2
28+
bool ElemCorner::at_edge(const Elem & elem, const unsigned short e) const
29+
{
30+
libmesh_assert_less(e, elem.n_edges());
31+
if (!at_edge())
32+
return false;
33+
const unsigned int * nodes_on_edge_ptr = elem.nodes_on_edge_ptr(e);
34+
return at_edge(nodes_on_edge_ptr[0], nodes_on_edge_ptr[1]);
35+
}
36+
37+
std::unique_ptr<const Elem> ElemCorner::build_edge(const Elem & elem) const
38+
{
39+
libmesh_assert(at_edge());
40+
libmesh_assert_less(first, elem.n_vertices());
41+
libmesh_assert_less(second, elem.n_vertices());
42+
43+
for (const auto e : elem.edge_index_range())
44+
if (elem.is_node_on_edge(first, e) && elem.is_node_on_edge(second, e))
45+
return elem.build_edge_ptr(e);
46+
47+
libmesh_error_msg("Element does not contain vertices in ElemCorner");
48+
}
49+
#endif
50+
51+
std::string ElemCorner::print() const
52+
{
53+
std::stringstream oss;
54+
if (at_vertex())
55+
oss << "at vertex " << vertex();
56+
#if LIBMESH_DIM > 2
57+
else if (at_edge())
58+
oss << "at edge with vertices " << first << " and " << second;
59+
#endif
60+
else
61+
oss << "not at corner";
62+
return oss.str();
63+
}
64+
65+
bool ElemCorner::is_valid(const Elem & elem, const Point & point, const Real tol) const
66+
{
67+
libmesh_assert(first == Elem::invalid_vertex || first < elem.n_vertices());
68+
libmesh_assert(second == Elem::invalid_vertex || second < elem.n_vertices());
69+
70+
if (at_vertex())
71+
return vertex_point(elem).absolute_fuzzy_equals(point, tol);
72+
#if LIBMESH_DIM > 2
73+
if (elem.dim() == 3 && at_edge())
74+
return build_edge(elem)->contains_point(point, tol);
75+
#endif
76+
77+
return true;
78+
}
79+
80+
} // namespace libMesh
81+
82+
std::ostream &
83+
operator<<(std::ostream & os, const libMesh::ElemCorner & elem_corner)
84+
{
85+
os << elem_corner.print();
86+
return os;
87+
}
88+
89+
#endif // LIBMESH_DIM > 1

0 commit comments

Comments
 (0)