libMesh
point_locator_test.C
Go to the documentation of this file.
1 #include <libmesh/mesh.h>
2 #include <libmesh/mesh_generation.h>
3 #include <libmesh/elem.h>
4 #include <libmesh/node.h>
5 #include <libmesh/parallel.h>
6 
7 #include "test_comm.h"
8 #include "libmesh_cppunit.h"
9 
10 #include <regex>
11 
12 using namespace libMesh;
13 
14 
15 
16 class PointLocatorTest : public CppUnit::TestCase {
17 public:
18  LIBMESH_CPPUNIT_TEST_SUITE( PointLocatorTest );
19 
20  CPPUNIT_TEST( testLocatorOnEdge3 );
21 #if LIBMESH_DIM > 1
22  CPPUNIT_TEST( testLocatorOnQuad9 );
23  CPPUNIT_TEST( testLocatorOnTri6 );
24 #endif
25 #if LIBMESH_DIM > 2
26  CPPUNIT_TEST( testLocatorOnHex27 );
27  CPPUNIT_TEST( testPlanar );
28 #endif
29 
30  CPPUNIT_TEST_SUITE_END();
31 
32 private:
33 
34 public:
35  void setUp()
36  {}
37 
38  void tearDown()
39  {}
40 
41  void testLocator(const ElemType elem_type)
42  {
44 
45  const unsigned int n_elem_per_side = 5;
46  const unsigned int dim = Elem::type_to_dim_map[elem_type];
47  const unsigned int ymax = dim > 1;
48  const unsigned int zmax = dim > 2;
49  const unsigned int ny = ymax * n_elem_per_side;
50  const unsigned int nz = zmax * n_elem_per_side;
51 
53  n_elem_per_side,
54  ny,
55  nz,
56  0., 1.,
57  0., ymax,
58  0., zmax,
59  elem_type);
60 
61  std::unique_ptr<PointLocatorBase> locator = mesh.sub_point_locator();
62 
63  // Make sure we throw in default (not out-of-mesh) mode when
64  // debugging and querying a point out of the mesh
65  const Point p{2,0,0};
66 #if defined(LIBMESH_ENABLE_EXCEPTIONS) && !defined(NDEBUG)
67  auto test_exception = [&locator, p]()
68  {
69  bool threw_desired_exception = false;
70  try {
71  locator->operator()(p);
72  }
73  catch (libMesh::LogicError & e) {
74  std::regex msg_regex("out_of_mesh_mode");
75  CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
76  threw_desired_exception = true;
77  }
78  catch (...) {
79  CPPUNIT_ASSERT_MESSAGE("Unexpected exception type thrown", false);
80  }
81  CPPUNIT_ASSERT(threw_desired_exception);
82  };
83  test_exception();
84 #endif
85 
86  if (!mesh.is_serial())
87  locator->enable_out_of_mesh_mode();
88 
89  for (unsigned int i=0; i != n_elem_per_side+1; ++i)
90  {
91  for (unsigned int j=0; j != ny+1; ++j)
92  {
93  for (unsigned int k=0; k != nz+1; ++k)
94  {
95  const libMesh::Real h = libMesh::Real(1)/n_elem_per_side;
96  Point p(i*h, j*h, k*h);
97 
98  const Elem *elem = locator->operator()(p);
99 
100  bool found_elem = elem;
101  if (!mesh.is_serial())
102  mesh.comm().max(found_elem);
103 
104  CPPUNIT_ASSERT(found_elem);
105  if (elem)
106  {
107  CPPUNIT_ASSERT(elem->contains_point(p));
108  }
109 
110  const Node *node = locator->locate_node(p);
111 
112  bool found_node = node;
113  if (!mesh.is_serial())
114  mesh.comm().max(found_node);
115 
116  CPPUNIT_ASSERT(found_node);
117 
118  if (node)
119  {
120  LIBMESH_ASSERT_FP_EQUAL(i*h, (*node)(0),
122  if (LIBMESH_DIM > 1)
123  LIBMESH_ASSERT_FP_EQUAL(j*h, (*node)(1),
125  if (LIBMESH_DIM > 2)
126  LIBMESH_ASSERT_FP_EQUAL(k*h, (*node)(2),
128  }
129  }
130  }
131  }
132 
133  // Make sure we do not throw in out-of-mesh mode when looking for
134  // a point out of the mesh
135  locator->enable_out_of_mesh_mode();
136  const Elem *elem = locator->operator()(p);
137  CPPUNIT_ASSERT(!elem);
138 
139  // Make sure we throw again after disabling out-of-mesh mode again.
140  locator->disable_out_of_mesh_mode();
141 #if defined(LIBMESH_ENABLE_EXCEPTIONS) && !defined(NDEBUG)
142  test_exception();
143 #endif // LIBMESH_ENABLE_EXCEPTIONS
144 
145  locator->clear();
146  CPPUNIT_ASSERT(!locator->initialized());
147 
148  locator->init();
149  CPPUNIT_ASSERT(locator->initialized());
150 
151  locator->set_close_to_point_tol(1e-1);
152  Point p2{1.001,0,0};
153  const Elem *elem2 = locator->operator()(p2);
154  bool found_elem = elem2;
155  if (!mesh.is_serial())
156  mesh.comm().max(found_elem);
157 
158  CPPUNIT_ASSERT(found_elem);
159  }
160 
161  void testPlanar()
162  {
163  LOG_UNIT_TEST;
164 
165  // Here we test locating points in a Mesh which lies slightly above the z-axis
167 
169  /*nx=*/10, /*ny=*/10,
170  /*xmin=*/0., /*xmax=*/1.,
171  /*ymin=*/0., /*ymax=*/1.,
172  TRI3);
173 
174  // Move all nodes a small amount in the +z-direction
175  for (auto & node : mesh.node_ptr_range())
176  (*node)(2) += 3.1e-15;
177 
178  // Construct a PointLocator object
179  std::unique_ptr<PointLocatorBase> locator = mesh.sub_point_locator();
180 
181  // Turn on out-of-mesh-mode to handle parallel testing
182  if (!mesh.is_serial())
183  locator->enable_out_of_mesh_mode();
184 
185  // Test locating a Point which is in the z=0 plane, i.e. slightly
186  // below the plane of the Mesh, but which should otherwise be
187  // found within the Mesh.
188  Point p(0.53, 0.7, 0.0);
189  const Elem *elem = (*locator)(p);
190 
191  bool found_elem = elem;
192  if (!mesh.is_serial())
193  mesh.comm().max(found_elem);
194 
195  CPPUNIT_ASSERT(found_elem);
196 
197  // Note: Tri3::contains_point() returns true for points which are
198  // out-of-plane by less than TOLERANCE by default.
199  if (elem)
200  CPPUNIT_ASSERT(elem->contains_point(p));
201  }
202 
203  void testLocatorOnEdge3() { LOG_UNIT_TEST; testLocator(EDGE3); }
204  void testLocatorOnQuad9() { LOG_UNIT_TEST; testLocator(QUAD9); }
205  void testLocatorOnTri6() { LOG_UNIT_TEST; testLocator(TRI6); }
206  void testLocatorOnHex27() { LOG_UNIT_TEST; testLocator(HEX27); }
207 
208 };
209 
void testLocator(const ElemType elem_type)
ElemType
Defines an enum for geometric element types.
CPPUNIT_TEST_SUITE_REGISTRATION(PointLocatorTest)
A Node is like a Point, but with more information.
Definition: node.h:52
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:218
static constexpr Real TOLERANCE
unsigned int dim
static const unsigned int type_to_dim_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the geometric dimension of the ele...
Definition: elem.h:628
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
const Parallel::Communicator & comm() const
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
The libMesh namespace provides an interface to certain functionality in the library.
virtual bool is_serial() const
Definition: mesh_base.h:347
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2784
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.