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

Public Member Functions

 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 14 of file boundary_mesh.C.

Member Function Documentation

◆ build_mesh()

void BoundaryMeshTest::build_mesh ( )
inlineprotected

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()

BoundaryMeshTest::CPPUNIT_TEST ( testMesh  )

◆ CPPUNIT_TEST_SUITE()

BoundaryMeshTest::CPPUNIT_TEST_SUITE ( BoundaryMeshTest  )

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

◆ CPPUNIT_TEST_SUITE_END()

BoundaryMeshTest::CPPUNIT_TEST_SUITE_END ( )

◆ sanityCheck()

void BoundaryMeshTest::sanityCheck ( )
inline

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 BoundaryMeshTest::setUp ( )
inline

Definition at line 141 of file boundary_mesh.C.

142  {
143 #if LIBMESH_DIM > 1
144  this->build_mesh();
145 #endif
146  }

◆ testMesh()

void BoundaryMeshTest::testMesh ( )
inline

Definition at line 148 of file boundary_mesh.C.

149  {
150  // There'd better be 3*5 + 5 elements in the interior plus right
151  // boundary
152  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(20),
153  _mesh->n_elem());
154 
155  // There'd better be only 7*11 nodes in the interior
156  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(77),
157  _mesh->n_nodes());
158 
159  // There'd better be only 2*(3+5) elements on the full boundary
160  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(16),
161  _all_boundary_mesh->n_elem());
162 
163  // There'd better be only 2*2*(3+5) nodes on the full boundary
164  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(32),
165  _all_boundary_mesh->n_nodes());
166 
167  // There'd better be only 5 elements on the left boundary
168  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(5),
169  _left_boundary_mesh->n_elem());
170 
171  // There'd better be only 2*5+1 nodes on the left boundary
172  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(11),
173  _left_boundary_mesh->n_nodes());
174 
175  // There are only four elements in the internal sideset mesh.
176  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(4),
177  _internal_boundary_mesh->n_elem());
178 
179  // There are 2*n_elem + 1 nodes in the internal sideset mesh.
180  CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(9),
181  _internal_boundary_mesh->n_nodes());
182 
183  this->sanityCheck();
184  }

Member Data Documentation

◆ _all_boundary_mesh

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

Definition at line 31 of file boundary_mesh.C.

◆ _internal_boundary_mesh

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

Definition at line 33 of file boundary_mesh.C.

◆ _left_boundary_mesh

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

Definition at line 32 of file boundary_mesh.C.

◆ _mesh

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

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::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::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