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

Public Member Functions

 CPPUNIT_TEST_SUITE (BoundaryRefinedMeshTest)
 The goal of this test is the same as the previous, but now we do a uniform refinement and make sure the result mesh is consistent. More...
 
 CPPUNIT_TEST (testMesh)
 
 CPPUNIT_TEST_SUITE_END ()
 
void setUp ()
 
void testMesh ()
 
 CPPUNIT_TEST_SUITE (BoundaryMeshTest)
 The goal of this test is to ensure that a 2D mesh generates boundary meshes correctly. More...
 
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 282 of file boundary_mesh.C.

Member Function Documentation

◆ build_mesh()

void BoundaryMeshTest::build_mesh ( )
inlineprotectedinherited

Definition at line 35 of file boundary_mesh.C.

36  {
37  _mesh = libmesh_make_unique<Mesh>(*TestCommWorld);
38  _all_boundary_mesh = libmesh_make_unique<Mesh>(*TestCommWorld);
39  _left_boundary_mesh = libmesh_make_unique<Mesh>(*TestCommWorld);
40  _internal_boundary_mesh = libmesh_make_unique<Mesh>(*TestCommWorld);
41 
43  0.2, 0.8, 0.2, 0.7, QUAD9);
44 
45  // We'll need to skip most repartitioning with DistributedMesh for
46  // now; otherwise the boundary meshes' interior parents might get
47  // shuffled off to different processors.
48  if (!_mesh->is_serial())
49  {
50  _mesh->skip_noncritical_partitioning(true);
51  _left_boundary_mesh->skip_noncritical_partitioning(true);
52  _all_boundary_mesh->skip_noncritical_partitioning(true);
53  _internal_boundary_mesh->skip_noncritical_partitioning(true);
54  }
55 
56  // Set subdomain ids for specific elements. This allows us to later
57  // build an internal sideset with respect to a given
58  // subdomain. The element subdomains look like:
59  // ___________________
60  // | 2 | 2 | 2 |
61  // |_____|_____|_____|
62  // | 2 | 2 | 2 |
63  // |_____|_____|_____|
64  // | 2 | 2 | 2 |
65  // |_____|_____|_____|
66  // | 1 | 1 | 2 |
67  // |_____|_____|_____|
68  // | 1 | 1 | 2 |
69  // |_____|_____|_____|
70  //
71  // and we will create an internal sideset along the border between
72  // subdomains 1 and 2.
73 
74  for (auto & elem : _mesh->active_element_ptr_range())
75  {
76  const Point c = elem->centroid();
77  if (c(0) < 0.6 && c(1) < 0.4)
78  elem->subdomain_id() = 1;
79  else
80  elem->subdomain_id() = 2;
81  }
82 
83  // Get the border of the square
84  _mesh->get_boundary_info().sync(*_all_boundary_mesh);
85 
86  std::set<boundary_id_type> left_id, right_id;
87  left_id.insert(3);
88  right_id.insert(1);
89 
90  // Add the right side of the square to the square; this should
91  // make it a mixed dimension mesh
92  _mesh->get_boundary_info().add_elements(right_id, *_mesh);
93  _mesh->prepare_for_use();
94 
95  // Add the left side of the square to its own boundary mesh.
96  _mesh->get_boundary_info().sync(left_id, *_left_boundary_mesh);
97 
98  // We create an internal sideset ID that does not conflict with
99  // sidesets 0-3 that get created by build_square().
100  boundary_id_type bid = 5;
101 
102  // To test the "relative to" feature, we add the same sides to the
103  // same sideset twice, from elements in subdomain 2 the second
104  // time. These should not show up in the BoundaryMesh, i.e. there
105  // should not be overlapped elems in the BoundaryMesh.
106  BoundaryInfo & bi = _mesh->get_boundary_info();
107 
108  for (auto & elem : _mesh->active_element_ptr_range())
109  {
110  const Point c = elem->centroid();
111  if (c(0) < 0.6 && c(1) < 0.4)
112  {
113  if (c(0) > 0.4)
114  bi.add_side(elem, 1, bid);
115  if (c(1) > 0.3)
116  bi.add_side(elem, 2, bid);
117  }
118  else
119  {
120  if (c(0) < 0.75 && c(1) < 0.4)
121  bi.add_side(elem, 3, bid);
122  if (c(0) < 0.6 && c(1) < 0.5)
123  bi.add_side(elem, 0, bid);
124  }
125  }
126 
127 
128  // Create a BoundaryMesh from the internal sideset relative to subdomain 1.
129  {
130  std::set<boundary_id_type> requested_boundary_ids;
131  requested_boundary_ids.insert(bid);
132  std::set<subdomain_id_type> subdomains_relative_to;
133  subdomains_relative_to.insert(1);
134  _mesh->get_boundary_info().sync(requested_boundary_ids,
136  subdomains_relative_to);
137  }
138  }

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

◆ CPPUNIT_TEST()

BoundaryRefinedMeshTest::CPPUNIT_TEST ( testMesh  )

◆ CPPUNIT_TEST_SUITE() [1/2]

BoundaryMeshTest::CPPUNIT_TEST_SUITE ( BoundaryMeshTest  )
inherited

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

◆ CPPUNIT_TEST_SUITE() [2/2]

BoundaryRefinedMeshTest::CPPUNIT_TEST_SUITE ( BoundaryRefinedMeshTest  )

The goal of this test is the same as the previous, but now we do a uniform refinement and make sure the result mesh is consistent.

i.e. the new node shared between the 1D elements is the same as the node shared on the underlying quads, and so on.

◆ CPPUNIT_TEST_SUITE_END()

BoundaryRefinedMeshTest::CPPUNIT_TEST_SUITE_END ( )

◆ sanityCheck()

void BoundaryMeshTest::sanityCheck ( )
inlineinherited

Definition at line 186 of file boundary_mesh.C.

187  {
188  // Sanity check all the elements
189  for (const auto & elem : _mesh->active_element_ptr_range())
190  {
191  const Elem * pip = elem->dim() < 2 ? elem->interior_parent() : nullptr;
192 
193  // On a DistributedMesh we might not be able to see the
194  // interior_parent of a non-local element
195  if (pip == remote_elem)
196  {
197  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
198  continue;
199  }
200 
201  // All the edges should have interior parents; none of the
202  // quads should.
203  if (pip)
204  {
205  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
206  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
207  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
208 
209  // We only added right edges
210  LIBMESH_ASSERT_FP_EQUAL(elem->centroid()(0), 0.8,
212  }
213  else
214  {
215  CPPUNIT_ASSERT_EQUAL(elem->type(), QUAD9);
216  }
217  }
218 
219  for (const auto & elem : _left_boundary_mesh->active_element_ptr_range())
220  {
221  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
222 
223  const Elem * pip = elem->interior_parent();
224 
225  // On a DistributedMesh we might not be able to see the
226  // interior_parent of a non-local element
227  if (pip == remote_elem)
228  {
229  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
230  continue;
231  }
232 
233  // All the edges should have interior parents
234  CPPUNIT_ASSERT(pip);
235  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
236  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
237 
238  // We only added left edges
239  LIBMESH_ASSERT_FP_EQUAL(elem->centroid()(0), 0.2,
241  }
242 
243  for (const auto & elem : _left_boundary_mesh->active_element_ptr_range())
244  {
245  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
246 
247  const Elem * pip = elem->interior_parent();
248 
249  // On a DistributedMesh we might not be able to see the
250  // interior_parent of a non-local element
251  if (pip == remote_elem)
252  {
253  CPPUNIT_ASSERT(elem->processor_id() != TestCommWorld->rank());
254  continue;
255  }
256 
257  // All the edges should have interior parents
258  CPPUNIT_ASSERT(pip);
259  CPPUNIT_ASSERT_EQUAL(pip->type(), QUAD9);
260  CPPUNIT_ASSERT_EQUAL(pip->level(), elem->level());
261  }
262 
263  // Sanity check for the internal sideset mesh.
264  for (const auto & elem : _internal_boundary_mesh->active_element_ptr_range())
265  {
266  CPPUNIT_ASSERT_EQUAL(elem->type(), EDGE3);
267 
268  // All of the elements in the internal sideset mesh should
269  // have the same subdomain id as the parent Elems (i.e. 1)
270  // they came from.
271  CPPUNIT_ASSERT_EQUAL(static_cast<subdomain_id_type>(1),
272  elem->subdomain_id());
273  }
274  }

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

◆ setUp()

void BoundaryRefinedMeshTest::setUp ( )
inline

Definition at line 301 of file boundary_mesh.C.

302  {
303 #if LIBMESH_DIM > 1
304  this->build_mesh();
305 
306  // Need to refine interior mesh before separate boundary meshes,
307  // if we want to get interior_parent links right.
308  MeshRefinement(*_mesh).uniformly_refine(1);
309  MeshRefinement(*_left_boundary_mesh).uniformly_refine(1);
310  MeshRefinement(*_all_boundary_mesh).uniformly_refine(1);
311 #endif
312  }

References libMesh::MeshRefinement::uniformly_refine().

◆ testMesh()

void BoundaryRefinedMeshTest::testMesh ( )
inline

Definition at line 314 of file boundary_mesh.C.

315  {
316  // There'd better be 3*5*4 + 5*2 active elements in the interior
317  // plus right boundary
318  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(70),
319  _mesh->n_active_elem());
320 
321  // Plus the original 20 now-inactive elements
322  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(90),
323  _mesh->n_elem());
324 
325  // There'd better be only 13*21 nodes in the interior
326  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(273),
327  _mesh->n_nodes());
328 
329  // There'd better be only 2*2*(3+5) active elements on the full boundary
330  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(32),
331  _all_boundary_mesh->n_active_elem());
332 
333  // Plus the original 16 now-inactive elements
334  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(48),
335  _all_boundary_mesh->n_elem());
336 
337  // There'd better be only 2*2*2*(3+5) nodes on the full boundary
338  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(64),
339  _all_boundary_mesh->n_nodes());
340 
341  // There'd better be only 2*5 active elements on the left boundary
342  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(10),
343  _left_boundary_mesh->n_active_elem());
344 
345  // Plus the original 5 now-inactive elements
346  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(15),
347  _left_boundary_mesh->n_elem());
348 
349  // There'd better be only 2*2*5+1 nodes on the left boundary
350  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(21),
351  _left_boundary_mesh->n_nodes());
352 
353  this->sanityCheck();
354  }

Member Data Documentation

◆ _all_boundary_mesh

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

Definition at line 31 of file boundary_mesh.C.

◆ _internal_boundary_mesh

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

Definition at line 33 of file boundary_mesh.C.

◆ _left_boundary_mesh

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

Definition at line 32 of file boundary_mesh.C.

◆ _mesh

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

Definition at line 30 of file boundary_mesh.C.


The documentation for this class was generated from the following file:
libMesh::BoundaryInfo
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
Definition: boundary_info.h:57
libMesh::Elem::level
unsigned int level() const
Definition: elem.h:2478
BoundaryMeshTest::build_mesh
void build_mesh()
Definition: boundary_mesh.C:35
libMesh::Elem::dim
virtual unsigned short dim() const =0
libMesh::TOLERANCE
static const Real TOLERANCE
Definition: libmesh_common.h:128
libMesh::boundary_id_type
int8_t boundary_id_type
Definition: id_types.h:51
libMesh::MeshRefinement
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Definition: mesh_refinement.h:61
libMesh::MeshTools::Generation::build_square
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.
Definition: mesh_generation.C:1501
BoundaryMeshTest::_mesh
std::unique_ptr< Mesh > _mesh
Definition: boundary_mesh.C:30
BoundaryMeshTest::_left_boundary_mesh
std::unique_ptr< Mesh > _left_boundary_mesh
Definition: boundary_mesh.C:32
TestCommWorld
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:111
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
BoundaryMeshTest::_all_boundary_mesh
std::unique_ptr< Mesh > _all_boundary_mesh
Definition: boundary_mesh.C:31
libMesh::Elem::interior_parent
const Elem * interior_parent() const
Definition: elem.C:749
libMesh::EDGE3
Definition: enum_elem_type.h:36
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
BoundaryMeshTest::sanityCheck
void sanityCheck()
Definition: boundary_mesh.C:186
libMesh::QUAD9
Definition: enum_elem_type.h:43
BoundaryMeshTest::_internal_boundary_mesh
std::unique_ptr< Mesh > _internal_boundary_mesh
Definition: boundary_mesh.C:33
libMesh::MeshRefinement::uniformly_refine
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
Definition: mesh_refinement.C:1678
libMesh::BoundaryInfo::add_side
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.
Definition: boundary_info.C:886
libMesh::Elem::type
virtual ElemType type() const =0
libMesh::remote_elem
const RemoteElem * remote_elem
Definition: remote_elem.C:57