libMesh
boundary_info.C
Go to the documentation of this file.
1 #include <libmesh/mesh.h>
2 #include <libmesh/mesh_generation.h>
3 #include <libmesh/boundary_info.h>
4 #include <libmesh/elem.h>
5 #include <libmesh/face_quad4_shell.h>
6 #include <libmesh/equation_systems.h>
7 #include <libmesh/zero_function.h>
8 #include <libmesh/dirichlet_boundaries.h>
9 #include <libmesh/dof_map.h>
10 #include <libmesh/parallel.h>
11 #include <libmesh/mesh_refinement.h>
12 
13 #include "test_comm.h"
14 #include "libmesh_cppunit.h"
15 
16 #include <regex>
17 
18 using namespace libMesh;
19 
20 class BoundaryInfoTest : public CppUnit::TestCase {
24 public:
25  LIBMESH_CPPUNIT_TEST_SUITE( BoundaryInfoTest );
26 
27  CPPUNIT_TEST( testNameCopying );
28 
29 #if LIBMESH_DIM > 1
30  CPPUNIT_TEST( testMesh );
31  CPPUNIT_TEST( testRenumber );
32 # if LIBMESH_DIM > 2
33  CPPUNIT_TEST( testSelectiveRenumber );
34 # endif
35 # ifdef LIBMESH_ENABLE_AMR
36 # ifdef LIBMESH_ENABLE_EXCEPTIONS
37  CPPUNIT_TEST( testBoundaryOnChildrenErrors );
38 # endif
39  CPPUNIT_TEST( testBoundaryIDs );
40  CPPUNIT_TEST( testBoundaryOnChildrenElementsRefineCoarsen );
41  CPPUNIT_TEST( testBoundaryOnChildrenBoundaryIDs );
42  CPPUNIT_TEST( testBoundaryOnChildrenBoundarySides );
43 # endif
44  CPPUNIT_TEST( testBuildNodeListFromSideList );
45  CPPUNIT_TEST( testBuildSideListFromNodeList );
46 # ifdef LIBMESH_ENABLE_DIRICHLET
47  CPPUNIT_TEST( testShellFaceConstraints );
48 # endif
49 #endif
50 #if LIBMESH_DIM > 2
51  CPPUNIT_TEST( testEdgeBoundaryConditions );
52 #endif
53 
54  CPPUNIT_TEST_SUITE_END();
55 
56 protected:
57 
58 public:
59  void setUp()
60  {
61  }
62 
63  void tearDown()
64  {
65  }
66 
67  void testMesh()
68  {
69  LOG_UNIT_TEST;
70 
72 
74  2, 2,
75  0., 1.,
76  0., 1.,
77  QUAD4);
78 
80 
81  // Side lists should be cleared and refilled by each call
82 #ifdef LIBMESH_ENABLE_DEPRECATED
83  std::vector<dof_id_type> element_id_list;
84  std::vector<unsigned short int> side_list;
85  std::vector<boundary_id_type> bc_id_list;
86 #endif
87 
88  // build_square adds boundary_ids 0,1,2,3 for the bottom, right,
89  // top, and left sides, respectively.
90 
91  // On a ReplicatedMesh, we should see all 4 ids on each processor
92  if (mesh.is_serial())
93  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(4), bi.n_boundary_ids());
94 
95  // On any mesh, we should see each id on *some* processor
96  {
97  const std::set<boundary_id_type> & bc_ids = bi.get_boundary_ids();
98  for (boundary_id_type i = 0 ; i != 4; ++i)
99  {
100  bool has_bcid = bc_ids.count(i);
101  mesh.comm().max(has_bcid);
102  CPPUNIT_ASSERT(has_bcid);
103  }
104  }
105 
106  // Build the side list
107 #ifdef LIBMESH_ENABLE_DEPRECATED
108  bi.build_side_list (element_id_list, side_list, bc_id_list);
109 #endif
110 
111  // Test that the new vector-of-tuples API works equivalently.
112  auto bc_triples = bi.build_side_list();
113 
114  // Check that there are exactly 8 sides in the BoundaryInfo for a
115  // replicated mesh
116  if (mesh.is_serial())
117  {
118 #ifdef LIBMESH_ENABLE_DEPRECATED
119  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(8), element_id_list.size());
120 #endif
121  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(8), bc_triples.size());
122  }
123 
124  // Let's test that they are preserved (in a relative sense) when
125  // we clone a mesh.
126  std::unique_ptr<MeshBase> mesh_clone = mesh.clone();
127  CPPUNIT_ASSERT(mesh_clone->get_boundary_info() ==
129 
130  // Let's test that we can remove them successfully.
131  bi.remove_id(0);
132 
133  CPPUNIT_ASSERT(mesh_clone->get_boundary_info() !=
135 
136  // Check that there are now only 3 boundary ids total on the Mesh.
137  if (mesh.is_serial())
138  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), bi.n_boundary_ids());
139 
140  {
141  const std::set<boundary_id_type> & bc_ids = bi.get_boundary_ids();
142  CPPUNIT_ASSERT(!bc_ids.count(0));
143  for (boundary_id_type i = 1 ; i != 4; ++i)
144  {
145  bool has_bcid = bc_ids.count(i);
146  mesh.comm().max(has_bcid);
147  CPPUNIT_ASSERT(has_bcid);
148  }
149  }
150 
151  // Build the side list again
152 #ifdef LIBMESH_ENABLE_DEPRECATED
153  bi.build_side_list (element_id_list, side_list, bc_id_list);
154 #endif
155  bc_triples = bi.build_side_list();
156 
157  // Check that there are now exactly 6 sides left in the
158  // BoundaryInfo on a replicated mesh
159  if (mesh.is_serial())
160  {
161 #ifdef LIBMESH_ENABLE_DEPRECATED
162  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(6), element_id_list.size());
163 #endif
164  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(6), bc_triples.size());
165  }
166 
167  // Check that the removed ID is really removed
168 #ifdef LIBMESH_ENABLE_DEPRECATED
169  CPPUNIT_ASSERT(std::find(bc_id_list.begin(), bc_id_list.end(), 0) == bc_id_list.end());
170 #endif
171  typedef std::tuple<dof_id_type, unsigned short int, boundary_id_type> Tuple;
172  CPPUNIT_ASSERT(std::find_if(bc_triples.begin(), bc_triples.end(),
173  [](const Tuple & t)->bool { return std::get<2>(t) == 0; }) == bc_triples.end());
174 
175  // Remove the same id again, make sure nothing changes.
176  bi.remove_id(0);
177  if (mesh.is_serial())
178  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), bi.n_boundary_ids());
179 
180  // Remove the remaining IDs, verify that we have no sides left and
181  // that we can safely reuse the same vectors in the
182  // build_side_list() call.
183  bi.remove_id(1);
184  bi.remove_id(2);
185  bi.remove_id(3);
186 #ifdef LIBMESH_ENABLE_DEPRECATED
187  bi.build_side_list (element_id_list, side_list, bc_id_list);
188 #endif
189  bc_triples = bi.build_side_list();
190 
191  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), bi.n_boundary_ids());
192 #ifdef LIBMESH_ENABLE_DEPRECATED
193  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), element_id_list.size());
194 #endif
195  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), bc_triples.size());
196  }
197 
198 
200  {
201  LOG_UNIT_TEST;
202 
204 
206  2, 2,
207  0., 1.,
208  0., 1.,
209  QUAD4);
210 
212 
213  // Side lists should be cleared and refilled by each call
214 #ifdef LIBMESH_ENABLE_DEPRECATED
215  std::vector<dof_id_type> element_id_list;
216  std::vector<unsigned short int> side_list;
217  std::vector<boundary_id_type> bc_id_list;
218 #endif
219 
220  // build_square adds boundary_ids 0,1,2,3 for the bottom, right,
221  // top, and left sides, respectively. Let's remap those, not 1-1.
222  bi.renumber_id(0, 4);
223  bi.renumber_id(1, 5);
224  bi.renumber_id(2, 6);
225  bi.renumber_id(3, 6);
226 
227  const std::map<boundary_id_type, std::string> expected_names =
228  {{4,"bottom"}, {5,"right"}, {6,"left"}};
229 
230  // On a ReplicatedMesh, we should see ids 4,5,6 on each processor
231  if (mesh.is_serial())
232  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), bi.n_boundary_ids());
233 
234  // On any mesh, we should see each new id on *some* processor, and
235  // shouldn't see old ids on *any* processor
236  {
237  const std::set<boundary_id_type> & bc_ids = bi.get_boundary_ids();
238  for (boundary_id_type i = 0 ; i != 4; ++i)
239  {
240  bool has_bcid = bc_ids.count(i);
241  mesh.comm().max(has_bcid);
242  CPPUNIT_ASSERT(!has_bcid);
243  }
244  for (boundary_id_type i = 4 ; i != 7; ++i)
245  {
246  bool has_bcid = bc_ids.count(i);
247 
248  bool bad_name = false;
249  if (has_bcid)
250  {
251  const std::string & current_name = bi.sideset_name(i);
252 
253  bad_name = (current_name != libmesh_map_find(expected_names, i));
254  }
255 
256  // At least one proc should have each of these BCs
257  mesh.comm().max(has_bcid);
258  CPPUNIT_ASSERT(has_bcid);
259 
260  // No proc should have the wrong name for a BC it has
261  mesh.comm().max(bad_name);
262  CPPUNIT_ASSERT(!bad_name);
263  }
264  }
265 
266  // Check that there are still exactly 8 sides in the BoundaryInfo
267  // for a replicated mesh
268  auto bc_triples = bi.build_side_list();
269 
270  if (mesh.is_serial())
271  {
272  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(8), bc_triples.size());
273  }
274 
275  // Remove the new IDs, verify that we have no sides left
276  bi.remove_id(4);
277  bi.remove_id(5);
278  bi.remove_id(6);
279  bc_triples = bi.build_side_list();
280 
281  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), bi.n_boundary_ids());
282  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), bc_triples.size());
283  }
284 
285 
287  {
288  LOG_UNIT_TEST;
289 
291 
293  2, 2, 2,
294  0., 1.,
295  0., 1.,
296  0., 1.,
297  HEX8);
298 
300 
301  // build_cube adds boundary_ids 0-5 for "back", "bottom", "right",
302  // "top", "left", and "front" (as viewed facing the usual XY plane
303  // with the Z axis pointing toward the viewer) respectively.
304  // Let's scramble those, and scramble them differently on nodes vs
305  // sides.
306  bi.renumber_side_id(0, 6);
307  bi.renumber_side_id(5, 7);
308  bi.renumber_node_id(0, 7);
309  bi.renumber_node_id(5, 6);
310 
311  Elem * elem = mesh.query_elem_ptr(0);
312 
313  if (elem)
314  {
315  // Let's add a couple edges
316  bi.add_edge(elem, 2, 1);
317  bi.add_edge(elem, 3, 2);
318  bi.edgeset_name(1) = "firstedge";
319  bi.edgeset_name(2) = "secondedge";
320  // And scramble them
321  bi.renumber_edge_id(1, 3);
322  bi.renumber_edge_id(2, 4);
323  }
324 
325  // We should get global ids squared away
327 
328  const std::map<boundary_id_type, std::string> expected_basic_names =
329  {{1,"bottom"}, {2,"right"}, {3,"top"}, {4,"left"}};
330 
331  std::map<boundary_id_type, std::string> expected_side_names =
332  expected_basic_names;
333  expected_side_names.insert({{6,"back"}, {7,"front"}});
334 
335  std::map<boundary_id_type, std::string> expected_node_names =
336  expected_basic_names;
337  expected_node_names.insert({{6,"front"}, {7,"back"}});
338 
339  const std::map<boundary_id_type, std::string> expected_edge_names =
340  {{3,"firstedge"}, {4,"secondedge"}};
341 
342  // On a ReplicatedMesh, we should see ids 1-4,6,7 on each processor
343  if (mesh.is_serial())
344  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(6), bi.n_boundary_ids());
345 
346  // On any mesh, we should see each new id on *some* processor, and
347  // shouldn't see old ids on *any* processor
348  {
349  auto & bc_ids = bi.get_boundary_ids();
350  auto & side_bc_ids = bi.get_side_boundary_ids();
351  auto & edge_bc_ids = bi.get_edge_boundary_ids();
352  auto & node_bc_ids = bi.get_node_boundary_ids();
353 
354  for (boundary_id_type noid : {0, 5})
355  {
356  bool has_bcid = bc_ids.count(noid) ||
357  side_bc_ids.count(noid) ||
358  edge_bc_ids.count(noid) ||
359  node_bc_ids.count(noid);
360  mesh.comm().max(has_bcid);
361  CPPUNIT_ASSERT(!has_bcid);
362  }
363 
364  for (boundary_id_type id : {1, 2, 3, 4, 6, 7})
365  {
366  bool has_bcid = bc_ids.count(id),
367  has_side_id = side_bc_ids.count(id),
368  has_edge_id = edge_bc_ids.count(id),
369  has_node_id = node_bc_ids.count(id);
370 
371  bool bad_name = false;
372  if (has_side_id)
373  {
374  const std::string & side_name = bi.sideset_name(id);
375  bad_name = bad_name || (side_name != libmesh_map_find(expected_side_names, id));
376  }
377 
378  if (has_edge_id)
379  {
380  const std::string & edge_name = bi.edgeset_name(id);
381  bad_name = bad_name || (edge_name != libmesh_map_find(expected_edge_names, id));
382  }
383 
384  if (has_node_id)
385  {
386  const std::string & node_name = bi.nodeset_name(id);
387  bad_name = bad_name || (node_name != libmesh_map_find(expected_node_names, id));
388  }
389 
390  // At least one proc should have each the BCs we expect
391  mesh.comm().max(has_bcid);
392  CPPUNIT_ASSERT(has_bcid);
393 
394  mesh.comm().max(has_side_id);
395  CPPUNIT_ASSERT(has_side_id);
396 
397  mesh.comm().max(has_edge_id);
398  if (id == 3 || id == 4)
399  CPPUNIT_ASSERT(has_edge_id);
400  else
401  CPPUNIT_ASSERT(!has_edge_id);
402 
403  mesh.comm().max(has_node_id);
404  CPPUNIT_ASSERT(has_node_id);
405 
406  // No proc should have the wrong name for a BC it has
407  mesh.comm().max(bad_name);
408  CPPUNIT_ASSERT(!bad_name);
409  }
410  }
411  }
412 
413 
415  {
416  LOG_UNIT_TEST;
417 
418  const unsigned int n_elem = 5;
419  const std::string mesh_filename = "cube_mesh.xda";
420 
421  {
424  n_elem, n_elem, n_elem,
425  0., 1.,
426  0., 1.,
427  0., 1.,
428  HEX8);
429 
431 
432  // build_cube does not add any edge boundary IDs
433  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), bi.n_edge_conds());
434 
435  // Let's now add some edge boundary IDs.
436  // We loop over all elements (not just local elements) so that
437  // all processors know about the boundary IDs
438  const boundary_id_type BOUNDARY_ID_MAX_X = 2;
439  const boundary_id_type BOUNDARY_ID_MIN_Y = 1;
440  const boundary_id_type EDGE_BOUNDARY_ID = 20;
441 
442  for (const auto & elem : mesh.element_ptr_range())
443  {
444  unsigned short side_max_x = 0, side_min_y = 0;
445  bool found_side_max_x = false, found_side_min_y = false;
446 
447  for (unsigned short side=0; side<elem->n_sides(); side++)
448  {
449  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_X))
450  {
451  side_max_x = side;
452  found_side_max_x = true;
453  }
454 
455  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MIN_Y))
456  {
457  side_min_y = side;
458  found_side_min_y = true;
459  }
460  }
461 
462  // If elem has sides on boundaries
463  // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Y
464  // then let's set an edge boundary condition
465  if (found_side_max_x && found_side_min_y)
466  for (unsigned short e=0; e<elem->n_edges(); e++)
467  if (elem->is_edge_on_side(e, side_max_x) &&
468  elem->is_edge_on_side(e, side_min_y))
469  bi.add_edge(elem, e, EDGE_BOUNDARY_ID);
470  }
471 
472  // Check that we have the expected number of edge boundary IDs after
473  // updating bi
474  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(n_elem), bi.n_edge_conds());
475 
476  // Let's test that edge BCIDs are preserved (in a relative
477  // sense) when we clone a mesh.
478  std::unique_ptr<MeshBase> mesh_clone = mesh.clone();
479  CPPUNIT_ASSERT(mesh_clone->get_boundary_info() ==
481 
482  mesh.write(mesh_filename);
483  }
484 
485  // Make sure all processors are done writing before we try to
486  // start reading
488 
490  mesh.read(mesh_filename);
491 
492  // Check that writing and reading preserves the edge boundary IDs
494  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(n_elem), bi.n_edge_conds());
495  }
496 
498  {
499  LOG_UNIT_TEST;
500 
503  8,
504  0., 1.,
505  EDGE2);
506 
507  Mesh mesh2(mesh);
508 
510  bi.sideset_name(0) = "zero";
511  bi.sideset_name(1) = "one";
512  bi.sideset_name(2) = "two";
513  bi.sideset_name(3) = "three";
514  bi.nodeset_name(0) = "ZERO";
515  bi.nodeset_name(1) = "ONE";
516 
517  BoundaryInfo bi2 {bi};
518  CPPUNIT_ASSERT_EQUAL(bi2.get_sideset_name(0), std::string("zero"));
519  CPPUNIT_ASSERT_EQUAL(bi2.get_sideset_name(1), std::string("one"));
520  CPPUNIT_ASSERT_EQUAL(bi2.get_sideset_name(2), std::string("two"));
521  CPPUNIT_ASSERT_EQUAL(bi2.get_sideset_name(3), std::string("three"));
522  CPPUNIT_ASSERT_EQUAL(bi2.get_nodeset_name(0), std::string("ZERO"));
523  CPPUNIT_ASSERT_EQUAL(bi2.get_nodeset_name(1), std::string("ONE"));
524 
525  BoundaryInfo & bi3 = mesh2.get_boundary_info();
526  bi3 = bi;
527  CPPUNIT_ASSERT_EQUAL(bi3.get_sideset_name(0), std::string("zero"));
528  CPPUNIT_ASSERT_EQUAL(bi3.get_sideset_name(1), std::string("one"));
529  CPPUNIT_ASSERT_EQUAL(bi3.get_sideset_name(2), std::string("two"));
530  CPPUNIT_ASSERT_EQUAL(bi3.get_sideset_name(3), std::string("three"));
531  CPPUNIT_ASSERT_EQUAL(bi3.get_nodeset_name(0), std::string("ZERO"));
532  CPPUNIT_ASSERT_EQUAL(bi3.get_nodeset_name(1), std::string("ONE"));
533  }
534 
535 #ifdef LIBMESH_ENABLE_DIRICHLET
537  {
538  LOG_UNIT_TEST;
539 
540  // Make a simple two element mesh that we can use to test constraints
542 
543  // (0,1) (1,1)
544  // x---------------x
545  // | |
546  // | |
547  // | |
548  // | |
549  // | |
550  // x---------------x
551  // (0,0) (1,0)
552  // | |
553  // | |
554  // | |
555  // | |
556  // x---------------x
557  // (0,-1) (1,-1)
558 
559  mesh.add_point( Point(0.0,-1.0), 4 );
560  mesh.add_point( Point(1.0,-1.0), 5 );
561  mesh.add_point( Point(1.0, 0.0), 1 );
562  mesh.add_point( Point(1.0, 1.0), 2 );
563  mesh.add_point( Point(0.0, 1.0), 3 );
564  mesh.add_point( Point(0.0, 0.0), 0 );
565 
566  Elem * elem_top = mesh.add_elem(Elem::build(QUADSHELL4));
567  elem_top->set_node(0, mesh.node_ptr(0));
568  elem_top->set_node(1, mesh.node_ptr(1));
569  elem_top->set_node(2, mesh.node_ptr(2));
570  elem_top->set_node(3, mesh.node_ptr(3));
571 
572  Elem * elem_bottom = mesh.add_elem(Elem::build(QUADSHELL4));
573  elem_bottom->set_node(0, mesh.node_ptr(4));
574  elem_bottom->set_node(1, mesh.node_ptr(5));
575  elem_bottom->set_node(2, mesh.node_ptr(1));
576  elem_bottom->set_node(3, mesh.node_ptr(0));
577 
579  bi.add_shellface(elem_top, 0, 10);
580  bi.add_shellface(elem_bottom, 1, 20);
581 
582  mesh.allow_renumbering(true);
584 
585  // Let's test that shellface BCIDs are preserved (in a relative
586  // sense) when we clone a mesh.
587  std::unique_ptr<MeshBase> mesh_clone = mesh.clone();
588  CPPUNIT_ASSERT(mesh_clone->get_boundary_info() ==
590 
591  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), bi.n_shellface_conds());
592 
593  EquationSystems es(mesh);
594  System & system = es.add_system<System> ("SimpleSystem");
595  system.add_variable("u", FIRST);
596 
597  // Add a Dirichlet constraint to check that we impose constraints
598  // correctly on shell faces.
599  std::vector<unsigned int> variables;
600  variables.push_back(0);
601  std::set<boundary_id_type> shellface_ids;
602  shellface_ids.insert(20);
603  ZeroFunction<> zf;
604  DirichletBoundary dirichlet_bc(shellface_ids,
605  variables,
606  &zf);
607  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
608  es.init();
609 
610  // Find elem_bottom again if we have it (it may have been deleted
611  // in a DistributedMesh or renumbered in theory)
612  elem_bottom = nullptr;
613  for (unsigned int e = 0; e != mesh.max_elem_id(); ++e)
614  {
615  Elem *elem = mesh.query_elem_ptr(e);
616  if (elem && elem->point(3) == Point(0,0))
617  elem_bottom = elem;
618  }
619 
620  // We expect to have a dof constraint on all four dofs of
621  // elem_bottom
622  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(4), static_cast<std::size_t>(system.n_constrained_dofs()));
623 
624  // But we may only know the details of that
625  // constraint on the processor which owns elem_bottom.
626  if (elem_bottom &&
627  elem_bottom->processor_id() == mesh.processor_id())
628  {
629  std::vector<dof_id_type> dof_indices;
630  system.get_dof_map().dof_indices(elem_bottom, dof_indices);
631  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(4), dof_indices.size());
632 
633  for(unsigned int i=0; i<dof_indices.size(); i++)
634  {
635  dof_id_type dof_id = dof_indices[i];
636  CPPUNIT_ASSERT( system.get_dof_map().is_constrained_dof(dof_id) );
637  }
638  }
639  }
640 #endif // LIBMESH_ENABLE_DIRICHLET
641 
642 #if LIBMESH_ENABLE_AMR
643 # if LIBMESH_ENABLE_EXCEPTIONS
645  {
646  LOG_UNIT_TEST;
647 
648  // We create one cell only. The default boundaries of the cell are below.
649  // ___2___
650  // 3 | | 1
651  // |_____|
652  // 0
653 
654  auto mesh = std::make_unique<Mesh>(*TestCommWorld);
656  1, 1,
657  0., 1.,
658  0., 1.,
659  QUAD4);
660 
662 
663  // We only have one element, but for easy access we use the iterator
664  for (auto & elem : mesh->active_element_ptr_range())
665  elem->set_refinement_flag(Elem::REFINE);
667 
670 
671  // Now we try to add boundary id 3 to a child on side 3. This should
672  // result in a "not implemented" error message
673  bool threw_desired_exception = false;
674  try {
675  for (auto & elem : mesh->active_element_ptr_range())
676  {
677  const Point c = elem->vertex_average();
678  if (c(0) < 0.5 && c(1) > 0.5)
679  bi.add_side(elem, 3, 3);
680  }
681  }
682  catch (libMesh::NotImplemented & e) {
683  std::regex msg_regex("Trying to add boundary ID 3 which already exists on the ancestors");
684  CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
685  threw_desired_exception = true;
686  }
687  // If we have more than 4 processors, or a poor partitioner, we
688  // might not get an exception on every processor
689  mesh->comm().max(threw_desired_exception);
690 
691  CPPUNIT_ASSERT(threw_desired_exception);
692 
693  threw_desired_exception = false;
694  try {
695  for (auto & elem : mesh->active_element_ptr_range())
696  {
697  const Point c = elem->vertex_average();
698  if (c(0) < 0.5 && c(1) > 0.5)
699  bi.add_side(elem, 3, {3,4});
700  }
701  }
702  catch (libMesh::NotImplemented & e) {
703  std::regex msg_regex("Trying to add boundary ID 3 which already exists on the ancestors");
704  CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
705  threw_desired_exception = true;
706  }
707 
708  // If we have more than 4 processors, or a poor partitioner, we
709  // might not get an exception on every processor
710  mesh->comm().max(threw_desired_exception);
711 
712  CPPUNIT_ASSERT(threw_desired_exception);
713 
714  // We tested the side addition errors, now we move to the removal parts.
715  // We will attempt the removal of boundary 3 through the child
716  threw_desired_exception = false;
718  try {
719  for (auto & elem : mesh->active_element_ptr_range())
720  {
721  const Point c = elem->vertex_average();
722  if (c(0) < 0.5 && c(1) > 0.5)
723  bi.remove_side(elem, 3, 3);
724  }
725  }
726  catch (libMesh::NotImplemented & e) {
727  std::regex msg_regex("We cannot delete boundary ID 3 using a child because it is inherited from an ancestor");
728  CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
729  threw_desired_exception = true;
730  }
731 
732  // If we have more than 4 processors, or a poor partitioner, we
733  // might not get an exception on every processor
734  mesh->comm().max(threw_desired_exception);
735 
736  CPPUNIT_ASSERT(threw_desired_exception);
737  }
738 # endif // LIBMESH_ENABLE_EXCEPTIONS
739 
740 
742  {
743  LOG_UNIT_TEST;
744 
745  // We create one cell only. The default boundaries of the cell are below.
746  // ___2___
747  // 3 | | 1
748  // |_____|
749  // 0
750 
751  auto mesh = std::make_unique<Mesh>(*TestCommWorld);
753  1, 1,
754  0., 1.,
755  0., 1.,
756  QUAD4);
757 
759 
760  // Now we add the extra boundary ID (5) to the element on side 3
761  auto elem = mesh->query_elem_ptr(0);
762  if (elem)
763  bi.add_side(elem, 3, 5);
765 
766  // Check the element now
767  if (elem && elem->processor_id() == mesh->processor_id())
768  {
769  std::vector<boundary_id_type> container;
770  bi.boundary_ids(elem, 3, container);
771 
772  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), container.size());
773  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(3), container[0]);
774  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(5), container[1]);
775 
776  std::vector<std::vector<boundary_id_type>> all_bids_container;
777  bi.side_boundary_ids(elem, all_bids_container);
778  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(elem->n_sides()), all_bids_container.size());
779  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), all_bids_container[3].size());
780  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(3), all_bids_container[3][0]);
781  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(5), all_bids_container[3][1]);
782  // Check other sides
783  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[0].size());
784  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(0), all_bids_container[0][0]);
785  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[1].size());
786  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(1), all_bids_container[1][0]);
787  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[1].size());
788  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(2), all_bids_container[2][0]);
789  }
790  }
791 
793  {
794  LOG_UNIT_TEST;
795 
796  // Set subdomain ids for specific elements, we will refine/coarsen
797  // the cell on subdomain 1
798  // _____________
799  // | 1 | 2 |
800  // |_____|_____|
801 
802  auto mesh = std::make_unique<Mesh>(*TestCommWorld);
804  2, 1,
805  0., 2.,
806  0., 1.,
807  QUAD4);
808 
810 
811  for (auto & elem : mesh->active_element_ptr_range())
812  {
813  const Point c = elem->vertex_average();
814  if (c(0) < 1)
815  {
816  elem->subdomain_id() = 1;
817  elem->set_refinement_flag(Elem::REFINE);
818  }
819  else
820  elem->subdomain_id() = 2;
821  }
823 
824  // Refine the elements once in subdomain 1, and
825  // add the right side subdomain 1 as boundary 5
828 
829  for (auto & elem : mesh->active_element_ptr_range())
830  {
831  const Point c = elem->vertex_average();
832  if (c(0) < 1 && c(0) > 0.5)
833  bi.add_side(elem, 1, 5);
834  }
836 
837  // Check the middle boundary, we expect to have two sides in boundary 5
838  unsigned int count = 0;
839  for (auto & elem : mesh->active_element_ptr_range())
840  if (bi.has_boundary_id(elem, 1, 5))
841  count++;
842 
843  if (mesh->n_active_local_elem())
844  {
845  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(2), count);
846  CPPUNIT_ASSERT(bi.is_children_on_boundary_side());
847  }
848 
849  // First, we will coarsen the the elements on subdomain 1. This
850  // is to check if the boundary information propagates upward upon
851  // coarsening.
852  for (auto & elem : mesh->active_element_ptr_range())
853  {
854  const Point c = elem->vertex_average();
855  if (c(0) < 1)
856  elem->set_refinement_flag(Elem::COARSEN);
857  }
859 
860  // The coarsened element should have its side on boundary 5
861  // This is boundary info transferred from this child element
864 
865  for (auto & elem : mesh->active_element_ptr_range())
866  {
867  const Point c = elem->vertex_average();
868  if (c(0) < 1)
869  {
870  CPPUNIT_ASSERT(bi.has_boundary_id(elem, 1, 5));
871  // We clean up this boundary ID for the next round of tests
872  bi.remove_side(elem, 1, 5);
873  // we will refine this element again
874  elem->set_refinement_flag(Elem::REFINE);
875  }
876  }
877 
880 
881  // This time we remove boundary 5 from one of the children. We expect
882  // the boundary not to propagate to the next level. Furthermore we
883  // expect boundary 5 to be deleted from the parent's boundaries
884  for (auto & elem : mesh->active_element_ptr_range())
885  {
886  const Point c = elem->vertex_average();
887  if (c(0) < 1)
888  elem->set_refinement_flag(Elem::COARSEN);
889  if (c(0) > 0.5 && c(0) < 1 && c(1) < 0.5)
890  bi.add_side(elem, 1, 5);
891  }
893 
895 
897 
898  // The parent element should not have any side associated with boundary 5
899  for (auto & elem : mesh->active_element_ptr_range())
900  {
901  const Point c = elem->vertex_average();
902  if (c(0) < 1)
903  CPPUNIT_ASSERT(!bi.has_boundary_id(elem, 1, 5));
904  }
905  }
906 
908  {
909  LOG_UNIT_TEST;
910 
911  // We create one cell only. The default boundaries of the cell are below.
912  // We will refine the mesh and add a new boundary id to the left side (side 3).
913  // Then will query the available boundary ids on the added side. It should return
914  // both the parent's and the child's boundaries.
915  // ___2___
916  // 3 | | 1
917  // |_____|
918  // 0
919 
920  auto mesh = std::make_unique<Mesh>(*TestCommWorld);
922  1, 1,
923  0., 1.,
924  0., 1.,
925  QUAD4);
926 
928 
929  // We only have one element, but for easy access we use the iterator
930  for (auto & elem : mesh->active_element_ptr_range())
931  elem->set_refinement_flag(Elem::REFINE);
933 
935 
936  // Now we add the extra boundary ID (5) to the element in the top
937  // left corner
938  for (auto & elem : mesh->active_element_ptr_range())
939  {
940  const Point c = elem->vertex_average();
941  if (c(0) < 0.5 && c(1) > 0.5)
942  bi.add_side(elem, 3, 5);
943  }
945 
946  // Okay, now we query the boundary ids on side 3 of the child and check if it has
947  // the right elements
948  for (auto & elem : mesh->active_element_ptr_range())
949  {
950  const Point c = elem->vertex_average();
951  if (c(0) < 0.5 && c(1) > 0.5)
952  {
953  std::vector<boundary_id_type> container;
954  bi.boundary_ids(elem, 3, container);
955 
956  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), container.size());
957  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(5), container[0]);
958  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(3), container[1]);
959 
960  std::vector<std::vector<boundary_id_type>> all_bids_container;
961  bi.side_boundary_ids(elem, all_bids_container);
962  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(elem->n_sides()), all_bids_container.size());
963  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), all_bids_container[3].size());
964  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(5), all_bids_container[3][0]);
965  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(3), all_bids_container[3][1]);
966  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[2].size());
967  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(2), all_bids_container[2][0]);
968  // Check other sides
969  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), all_bids_container[0].size());
970  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), all_bids_container[1].size());
971 
972  // This is against the spirit of the test, and undefined behavior which
973  // may be changed later. Setting allow_children_on_boundary_side(false) could
974  // be actively doing a transfer_boundary_ids_from_children() and then deleting the
975  // children's data, not leaving the children's data there-but-ignored.
977  bi.side_boundary_ids(elem, all_bids_container);
978  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(elem->n_sides()), all_bids_container.size());
979  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[3].size());
980  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(3), all_bids_container[3][0]);
981  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), all_bids_container[2].size());
982  CPPUNIT_ASSERT_EQUAL(static_cast<boundary_id_type>(2), all_bids_container[2][0]);
983  }
984  }
985  }
986 
988  {
989  LOG_UNIT_TEST;
990 
991  // We create one cell only. The default boundaries of the cell are below.
992  // We will refine mesh and see if we can get back the correct sides
993  // for a given boundary id on an internal boundary.
994  // ___2___
995  // 3 | | 1
996  // |_____|
997  // 0
998 
999  auto mesh = std::make_unique<Mesh>(*TestCommWorld);
1001  1, 1,
1002  0., 1.,
1003  0., 1.,
1004  QUAD4);
1005 
1007 
1008 
1009  // We only have one element, but for easy access we use the iterator
1010  for (auto & elem : mesh->active_element_ptr_range())
1011  elem->set_refinement_flag(Elem::REFINE);
1012  mesh->prepare_for_use();
1014 
1015  // Now we add the extra boundary ID (5) to two sides of
1016  // the element in the bottom left corner. then we refine again
1017  for (auto & elem : mesh->active_element_ptr_range())
1018  {
1019  const Point c = elem->vertex_average();
1020  if (c(0) < 0.5 && c(1) < 0.5)
1021  {
1022  bi.add_side(elem, 1, 5);
1023  bi.add_side(elem, 2, 5);
1024  elem->set_refinement_flag(Elem::REFINE);
1025  }
1026  }
1027  mesh->prepare_for_use();
1029 
1030  // Okay, now we add another boundary id (6) to the cell which is in the bottom
1031  // right corner of the refined element
1032  for (auto & elem : mesh->active_element_ptr_range())
1033  {
1034  const Point c = elem->vertex_average();
1035  if (c(0) < 0.5 && c(0) > 0.25 && c(1) < 0.25)
1036  bi.add_side(elem, 1, 6);
1037  }
1038 
1039  // Time to test if we can get back the boundary sides, first we
1040  // check if we can get back boundary from the ancestors of (5) on
1041  // the cell which only has boundary (6) registered. We also check
1042  // if we can get boundary (6) back.
1043 
1044  for (auto & elem : mesh->active_element_ptr_range())
1045  {
1046  const Point c = elem->vertex_average();
1047  if (c(0) < 0.5 && c(0) > 0.25 && c(1) < 0.25)
1048  {
1049  const auto side_5 = bi.side_with_boundary_id(elem, 5);
1050  const auto side_6 = bi.side_with_boundary_id(elem, 6);
1051  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(1), side_5);
1052  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(1), side_6);
1053  }
1054  }
1055 
1056  // Now we go and try to query the sides with boundary id (5) using
1057  // the element which is at the top right corner of the bottom
1058  // right parent.
1059  for (auto & elem : mesh->active_element_ptr_range())
1060  {
1061  const Point c = elem->vertex_average();
1062  if (c(0) < 0.5 && c(0) > 0.25 && c(1) > 0.25 && c(1) < 0.5)
1063  {
1064  const auto sides = bi.sides_with_boundary_id(elem, 5);
1065  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long>(2), sides.size());
1066  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(1), sides[0]);
1067  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(2), sides[1]);
1068  }
1069  }
1070  }
1071 #endif //LIBMESH_ENABLE_AMR
1072 
1073 
1075  {
1076  LOG_UNIT_TEST;
1077 
1079 
1081  2, 2,
1082  0., 1.,
1083  0., 1.,
1084  QUAD4);
1085 
1087 
1088  // build_square gave us ids 0-3 as both side sets and node sets
1089  bi.remove_node_id(0);
1090  bi.remove_node_id(1);
1091  bi.remove_node_id(2);
1092  bi.remove_node_id(3);
1093 
1094  CPPUNIT_ASSERT(bi.build_node_list().empty());
1095 
1097 
1098  for (const auto & elem : mesh.element_ptr_range())
1099  {
1100  for (auto n : elem->node_index_range())
1101  {
1102  const Node * node = elem->node_ptr(n);
1103  for (auto s : {0,2})
1104  if (elem->is_node_on_side(n, s) && !elem->neighbor_ptr(s))
1105  CPPUNIT_ASSERT(bi.has_boundary_id(node, s));
1106  for (auto s : {1,3})
1107  CPPUNIT_ASSERT(!bi.has_boundary_id(node, s));
1108  }
1109  }
1110  }
1111 
1112 
1114  {
1115  LOG_UNIT_TEST;
1116 
1118 
1120  2, 2,
1121  0., 1.,
1122  0., 1.,
1123  QUAD4);
1124 
1126 
1127  // build_square gave us ids 0-3 as both side sets and node sets
1128  bi.remove_side_id(0);
1129  bi.remove_side_id(1);
1130  bi.remove_side_id(2);
1131  bi.remove_side_id(3);
1132 
1133  CPPUNIT_ASSERT(bi.build_side_list().empty());
1134 
1136 
1137  for (const auto & elem : mesh.element_ptr_range())
1138  {
1139  for (auto s : {0,2})
1140  {
1141  if (!elem->neighbor_ptr(s))
1142  {
1143  CPPUNIT_ASSERT(bi.has_boundary_id(elem, s, s));
1144  CPPUNIT_ASSERT_EQUAL(bi.n_boundary_ids(elem, s), 1u);
1145  }
1146  else
1147  CPPUNIT_ASSERT(!bi.n_boundary_ids(elem, s));
1148  }
1149  for (auto s : {1,3})
1150  {
1151  CPPUNIT_ASSERT(!bi.has_boundary_id(elem, s, s));
1152  CPPUNIT_ASSERT(!bi.n_boundary_ids(elem, s));
1153  }
1154  }
1155  }
1156 
1157 };
1158 
void remove_id(boundary_id_type id, bool global=false)
Removes all entities (nodes, sides, edges, shellfaces) with boundary id id from their respective cont...
A class to stub for features that should be in libMesh, but haven&#39;t been written yet, to be thrown by "libmesh_not_implemented();".
void allow_children_on_boundary_side(const bool children_on_boundary)
Whether or not to allow directly setting boundary sides on child elements.
This is the EquationSystems class.
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
const std::set< boundary_id_type > & get_side_boundary_ids() const
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2559
A Node is like a Point, but with more information.
Definition: node.h:52
std::string & nodeset_name(boundary_id_type id)
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
ConstFunction that simply returns 0.
Definition: zero_function.h:38
std::vector< unsigned int > sides_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
void testShellFaceConstraints()
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
Definition: mesh_base.h:1196
void synchronize_global_id_set()
Synchronizes the boundary_ids set on each processor to determine global_boundary_ids.
std::size_t n_edge_conds() const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2197
void side_boundary_ids(const Elem *const elem, std::vector< std::vector< boundary_id_type >> &vec_to_fill) const
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:976
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
bool refine_elements()
Only refines the user-requested elements.
std::size_t n_shellface_conds() const
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
Definition: mesh_base.C:759
void build_node_list_from_side_list(const std::set< boundary_id_type > &sideset_list={})
Adds nodes with boundary ids based on the side&#39;s boundary ids they are connected to.
CPPUNIT_TEST_SUITE_REGISTRATION(BoundaryInfoTest)
void remove_side_id(boundary_id_type id, bool global=false)
Removes all sides with boundary id id from the BoundaryInfo object, removes it from the set of side b...
void barrier() const
unsigned int side_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
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.
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:165
void renumber_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all entities (nodes, sides, edges, shellfaces) with boundary id old_id to instead be labeled ...
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
std::size_t n_boundary_ids() const
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of element numbers, sides, and ids for those sides.
void build_side_list_from_node_list(const std::set< boundary_id_type > &nodeset_list={})
Adds sides to a sideset if every node on that side are in the same sideset.
bool coarsen_elements()
Only coarsens the user-requested elements.
const std::set< boundary_id_type > & get_node_boundary_ids() const
void renumber_side_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all sides with boundary id old_id to instead be labeled by boundary id new_id.
void testBoundaryOnChildrenBoundaryIDs()
dof_id_type n_active_local_elem() const
Definition: mesh_base.h:565
virtual bool is_serial() const
Definition: mesh_base.h:211
void testEdgeBoundaryConditions()
void build_node_list(std::vector< dof_id_type > &node_id_list, std::vector< boundary_id_type > &bc_id_list) const
Creates a list of nodes and ids for those nodes.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
int8_t boundary_id_type
Definition: id_types.h:51
void testSelectiveRenumber()
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:97
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:442
virtual dof_id_type max_elem_id() const =0
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
bool is_constrained_dof(const dof_id_type dof) const
Definition: dof_map.h:2424
void testBoundaryOnChildrenErrors()
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1342
std::string & sideset_name(boundary_id_type id)
void renumber_node_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all nodes with boundary id old_id to instead be labeled by boundary id new_id.
virtual void write(const std::string &name) const =0
const std::set< boundary_id_type > & get_boundary_ids() const
void remove_side(const Elem *elem, const unsigned short int side)
Removes all boundary conditions associated with side side of element elem, if any exist...
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
void max(const T &r, T &o, Request &req) const
const std::set< boundary_id_type > & get_edge_boundary_ids() const
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...
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
Add shell face shellface of element number elem with boundary id id to the boundary information data ...
void testBuildNodeListFromSideList()
std::string & edgeset_name(boundary_id_type id)
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
void renumber_edge_id(boundary_id_type old_id, boundary_id_type new_id)
Changes all edges with boundary id old_id to instead be labeled by boundary id new_id.
bool is_children_on_boundary_side() const
void testBoundaryOnChildrenBoundarySides()
void testBuildSideListFromNodeList()
virtual const Node * node_ptr(const dof_id_type i) const =0
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
void remove_node_id(boundary_id_type id, bool global=false)
Removes all nodes with boundary id id from the BoundaryInfo object, removes it from the set of node b...
const DofMap & get_dof_map() const
Definition: system.h:2375
processor_id_type processor_id() const
Definition: dof_object.h:905
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
const Point & point(const unsigned int i) const
Definition: elem.h:2454
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.
void testBoundaryOnChildrenElementsRefineCoarsen()
dof_id_type n_constrained_dofs() const
Definition: system.C:126
uint8_t dof_id_type
Definition: id_types.h:67
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...