libMesh
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
BoundaryMeshTest Class Reference
Inheritance diagram for BoundaryMeshTest:
[legend]

Public Member Functions

 LIBMESH_CPPUNIT_TEST_SUITE (BoundaryMeshTest)
 The goal of this test is to ensure that a 2D mesh generates boundary meshes correctly. More...
 
 CPPUNIT_TEST (testMesh)
 
 CPPUNIT_TEST_SUITE_END ()
 
void setUp ()
 
void testMesh ()
 
void sanityCheck ()
 

Protected Member Functions

void build_mesh ()
 

Protected Attributes

std::unique_ptr< Mesh_mesh
 
std::unique_ptr< Mesh_all_boundary_mesh
 
std::unique_ptr< Mesh_left_boundary_mesh
 
std::unique_ptr< Mesh_internal_boundary_mesh
 

Detailed Description

Definition at line 15 of file boundary_mesh.C.

Member Function Documentation

◆ build_mesh()

void BoundaryMeshTest::build_mesh ( )
inlineprotected

Definition at line 36 of file boundary_mesh.C.

References libMesh::BoundaryInfo::add_side(), libMesh::MeshTools::Generation::build_square(), and libMesh::QUAD9.

37  {
38  _mesh = std::make_unique<Mesh>(*TestCommWorld);
39  _all_boundary_mesh = std::make_unique<Mesh>(*TestCommWorld);
40  _left_boundary_mesh = std::make_unique<Mesh>(*TestCommWorld);
41  _internal_boundary_mesh = std::make_unique<Mesh>(*TestCommWorld);
42 
44  0.2, 0.8, 0.2, 0.7, QUAD9);
45 
46  // We'll need to skip most repartitioning with DistributedMesh for
47  // now; otherwise the boundary meshes' interior parents might get
48  // shuffled off to different processors.
49  if (!_mesh->is_serial())
50  {
51  _mesh->skip_noncritical_partitioning(true);
52  _left_boundary_mesh->skip_noncritical_partitioning(true);
53  _all_boundary_mesh->skip_noncritical_partitioning(true);
54  _internal_boundary_mesh->skip_noncritical_partitioning(true);
55  }
56 
57  // Set subdomain ids for specific elements. This allows us to later
58  // build an internal sideset with respect to a given
59  // subdomain. The element subdomains look like:
60  // ___________________
61  // | 2 | 2 | 2 |
62  // |_____|_____|_____|
63  // | 2 | 2 | 2 |
64  // |_____|_____|_____|
65  // | 2 | 2 | 2 |
66  // |_____|_____|_____|
67  // | 1 | 1 | 2 |
68  // |_____|_____|_____|
69  // | 1 | 1 | 2 |
70  // |_____|_____|_____|
71  //
72  // and we will create an internal sideset along the border between
73  // subdomains 1 and 2.
74 
75  for (auto & elem : _mesh->active_element_ptr_range())
76  {
77  const Point c = elem->vertex_average();
78  if (c(0) < 0.6 && c(1) < 0.4)
79  elem->subdomain_id() = 1;
80  else
81  elem->subdomain_id() = 2;
82  }
83 
84  // Get the border of the square
85  _mesh->get_boundary_info().sync(*_all_boundary_mesh);
86 
87  // Check that the interior_parent side indices that we set on the
88  // BoundaryMesh as extra integers agree with the side returned
89  // by which_side_am_i().
90  unsigned int parent_side_index_tag =
91  _all_boundary_mesh->get_elem_integer_index("parent_side_index");
92 
93  for (const auto & belem : _all_boundary_mesh->element_ptr_range())
94  {
95  dof_id_type parent_side_index =
96  belem->get_extra_integer(parent_side_index_tag);
97 
98  CPPUNIT_ASSERT_EQUAL
99  (static_cast<dof_id_type>(belem->interior_parent()->which_side_am_i(belem)),
100  parent_side_index);
101  }
102 
103  std::set<boundary_id_type> left_id, right_id;
104  left_id.insert(3);
105  right_id.insert(1);
106 
107  // Add the right side of the square to the square; this should
108  // make it a mixed dimension mesh. We skip storing the parent
109  // side ids (which is the default) since they are not needed
110  // in this particular test.
111  _mesh->get_boundary_info().add_elements
112  (right_id, *_mesh, /*store_parent_side_ids=*/false);
113  _mesh->prepare_for_use();
114 
115  // Add the left side of the square to its own boundary mesh.
116  _mesh->get_boundary_info().sync(left_id, *_left_boundary_mesh);
117 
118  // We create an internal sideset ID that does not conflict with
119  // sidesets 0-3 that get created by build_square().
120  boundary_id_type bid = 5;
121 
122  // To test the "relative to" feature, we add the same sides to the
123  // same sideset twice, from elements in subdomain 2 the second
124  // time. These should not show up in the BoundaryMesh, i.e. there
125  // should not be overlapped elems in the BoundaryMesh.
126  BoundaryInfo & bi = _mesh->get_boundary_info();
127 
128  for (auto & elem : _mesh->active_element_ptr_range())
129  {
130  const Point c = elem->vertex_average();
131  if (c(0) < 0.6 && c(1) < 0.4)
132  {
133  if (c(0) > 0.4)
134  bi.add_side(elem, 1, bid);
135  if (c(1) > 0.3)
136  bi.add_side(elem, 2, bid);
137  }
138  else
139  {
140  if (c(0) < 0.75 && c(1) < 0.4)
141  bi.add_side(elem, 3, bid);
142  if (c(0) < 0.6 && c(1) < 0.5)
143  bi.add_side(elem, 0, bid);
144  }
145  }
146 
147 
148  // Create a BoundaryMesh from the internal sideset relative to subdomain 1.
149  {
150  std::set<boundary_id_type> requested_boundary_ids;
151  requested_boundary_ids.insert(bid);
152  std::set<subdomain_id_type> subdomains_relative_to;
153  subdomains_relative_to.insert(1);
154  _mesh->get_boundary_info().sync(requested_boundary_ids,
156  subdomains_relative_to);
157  }
158  }
std::unique_ptr< Mesh > _internal_boundary_mesh
Definition: boundary_mesh.C:34
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.
std::unique_ptr< Mesh > _mesh
Definition: boundary_mesh.C:31
int8_t boundary_id_type
Definition: id_types.h:51
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
std::unique_ptr< Mesh > _left_boundary_mesh
Definition: boundary_mesh.C:33
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
uint8_t dof_id_type
Definition: id_types.h:67
std::unique_ptr< Mesh > _all_boundary_mesh
Definition: boundary_mesh.C:32

◆ CPPUNIT_TEST()

BoundaryMeshTest::CPPUNIT_TEST ( testMesh  )

◆ CPPUNIT_TEST_SUITE_END()

BoundaryMeshTest::CPPUNIT_TEST_SUITE_END ( )

◆ LIBMESH_CPPUNIT_TEST_SUITE()

BoundaryMeshTest::LIBMESH_CPPUNIT_TEST_SUITE ( BoundaryMeshTest  )

The goal of this test is to ensure that a 2D mesh generates boundary meshes correctly.

◆ sanityCheck()

void BoundaryMeshTest::sanityCheck ( )
inline

Definition at line 208 of file boundary_mesh.C.

References libMesh::Elem::dim(), libMesh::EDGE3, libMesh::Elem::interior_parent(), libMesh::Elem::level(), libMesh::QUAD9, TIMPI::Communicator::rank(), libMesh::remote_elem, TestCommWorld, libMesh::TOLERANCE, and libMesh::Elem::type().

209  {
210  // Sanity check all the elements
211  for (const auto & elem : _mesh->active_element_ptr_range())
212  {
213  const Elem * pip = elem->dim() < 2 ? elem->interior_parent() : nullptr;
214 
215  // On a DistributedMesh we might not be able to see the
216  // interior_parent of a non-local element
217  if (pip == remote_elem)
218  {
219  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
220  continue;
221  }
222 
223  // All the edges should have interior parents; none of the
224  // quads should.
225  if (pip)
226  {
227  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
228  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
229  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
230 
231  // We only added right edges
232  LIBMESH_ASSERT_FP_EQUAL(0.8, elem->vertex_average()(0),
234  }
235  else
236  {
237  CPPUNIT_ASSERT_EQUAL(elem->type(), QUAD9);
238  }
239  }
240 
241  for (const auto & elem : _left_boundary_mesh->active_element_ptr_range())
242  {
243  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
244 
245  const Elem * pip = elem->interior_parent();
246 
247  // On a DistributedMesh we might not be able to see the
248  // interior_parent of a non-local element
249  if (pip == remote_elem)
250  {
251  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
252  continue;
253  }
254 
255  // All the edges should have interior parents
256  CPPUNIT_ASSERT(pip);
257  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
258  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
259 
260  // We only added left edges
261  LIBMESH_ASSERT_FP_EQUAL(0.2, elem->vertex_average()(0),
263  }
264 
265  for (const auto & elem : _left_boundary_mesh->active_element_ptr_range())
266  {
267  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
268 
269  const Elem * pip = elem->interior_parent();
270 
271  // On a DistributedMesh we might not be able to see the
272  // interior_parent of a non-local element
273  if (pip == remote_elem)
274  {
275  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
276  continue;
277  }
278 
279  // All the edges should have interior parents
280  CPPUNIT_ASSERT(pip);
281  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
282  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
283  }
284 
285  // Sanity check for the internal sideset mesh.
286  for (const auto & elem : _internal_boundary_mesh->active_element_ptr_range())
287  {
288  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
289 
290  // All of the elements in the internal sideset mesh should
291  // have the same subdomain id as the parent Elems (i.e. 1)
292  // they came from.
293  CPPUNIT_ASSERT_EQUAL(static_cast<subdomain_id_type>(1),
294  elem->subdomain_id());
295  }
296  }
std::unique_ptr< Mesh > _internal_boundary_mesh
Definition: boundary_mesh.C:34
const Elem * interior_parent() const
Definition: elem.C:994
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:159
static constexpr Real TOLERANCE
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
processor_id_type rank() const
std::unique_ptr< Mesh > _mesh
Definition: boundary_mesh.C:31
std::unique_ptr< Mesh > _left_boundary_mesh
Definition: boundary_mesh.C:33
unsigned int level() const
Definition: elem.h:2911
virtual unsigned short dim() const =0
virtual ElemType type() const =0
const RemoteElem * remote_elem
Definition: remote_elem.C:54

◆ setUp()

void BoundaryMeshTest::setUp ( )
inline

Definition at line 161 of file boundary_mesh.C.

162  {
163 #if LIBMESH_DIM > 1
164  this->build_mesh();
165 #endif
166  }

◆ testMesh()

void BoundaryMeshTest::testMesh ( )
inline

Definition at line 168 of file boundary_mesh.C.

169  {
170  LOG_UNIT_TEST;
171 
172  // There'd better be 3*5 + 5 elements in the interior plus right
173  // boundary
174  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(20),
175  _mesh->n_elem());
176 
177  // There'd better be only 7*11 nodes in the interior
178  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(77),
179  _mesh->n_nodes());
180 
181  // There'd better be only 2*(3+5) elements on the full boundary
182  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(16),
183  _all_boundary_mesh->n_elem());
184 
185  // There'd better be only 2*2*(3+5) nodes on the full boundary
186  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(32),
187  _all_boundary_mesh->n_nodes());
188 
189  // There'd better be only 5 elements on the left boundary
190  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(5),
191  _left_boundary_mesh->n_elem());
192 
193  // There'd better be only 2*5+1 nodes on the left boundary
194  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(11),
195  _left_boundary_mesh->n_nodes());
196 
197  // There are only four elements in the internal sideset mesh.
198  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(4),
199  _internal_boundary_mesh->n_elem());
200 
201  // There are 2*n_elem + 1 nodes in the internal sideset mesh.
202  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(9),
203  _internal_boundary_mesh->n_nodes());
204 
205  this->sanityCheck();
206  }
std::unique_ptr< Mesh > _internal_boundary_mesh
Definition: boundary_mesh.C:34
std::unique_ptr< Mesh > _mesh
Definition: boundary_mesh.C:31
std::unique_ptr< Mesh > _left_boundary_mesh
Definition: boundary_mesh.C:33
std::unique_ptr< Mesh > _all_boundary_mesh
Definition: boundary_mesh.C:32

Member Data Documentation

◆ _all_boundary_mesh

std::unique_ptr<Mesh> BoundaryMeshTest::_all_boundary_mesh
protected

Definition at line 32 of file boundary_mesh.C.

◆ _internal_boundary_mesh

std::unique_ptr<Mesh> BoundaryMeshTest::_internal_boundary_mesh
protected

Definition at line 34 of file boundary_mesh.C.

◆ _left_boundary_mesh

std::unique_ptr<Mesh> BoundaryMeshTest::_left_boundary_mesh
protected

Definition at line 33 of file boundary_mesh.C.

◆ _mesh

std::unique_ptr<Mesh> BoundaryMeshTest::_mesh
protected

Definition at line 31 of file boundary_mesh.C.


The documentation for this class was generated from the following file: