1313#include "test_comm.h"
1414#include "libmesh_cppunit.h"
1515
16+ #include <regex>
1617
1718using namespace libMesh ;
1819
@@ -29,6 +30,7 @@ public:
2930 CPPUNIT_TEST ( testMesh );
3031 CPPUNIT_TEST ( testRenumber );
3132#ifdef LIBMESH_ENABLE_AMR
33+ CPPUNIT_TEST ( testBoundaryOnChildrenErrors );
3234 CPPUNIT_TEST ( testBoundaryOnChildrenElementsRefineCoarsen );
3335 CPPUNIT_TEST ( testBoundaryOnChildrenBoundaryIDs );
3436 CPPUNIT_TEST ( testBoundaryOnChildrenBoundarySides );
@@ -481,6 +483,101 @@ public:
481483#endif // LIBMESH_ENABLE_DIRICHLET
482484
483485#ifdef LIBMESH_ENABLE_AMR
486+ void testBoundaryOnChildrenErrors ()
487+ {
488+ LOG_UNIT_TEST ;
489+
490+ // We create one cell only. The default boundaries of the cell are below.
491+ // ___2___
492+ // 3 | | 1
493+ // |_____|
494+ // 0
495+
496+ auto mesh = std ::make_unique < Mesh > (* TestCommWorld );
497+ MeshTools ::Generation ::build_square (* mesh ,
498+ 1 , 1 ,
499+ 0. , 1. ,
500+ 0. , 1. ,
501+ QUAD4 );
502+
503+ BoundaryInfo & bi = mesh -> get_boundary_info ();
504+
505+ // We only have one element, but for easy access we use the iterator
506+ for (auto & elem : mesh -> active_element_ptr_range ())
507+ elem -> set_refinement_flag (Elem ::REFINE );
508+ mesh -> prepare_for_use ();
509+
510+ MeshRefinement (* mesh ).refine_elements ();
511+ mesh -> prepare_for_use ();
512+
513+ // Now we try to add boundary id 3 to a child on side 3. This should
514+ // result in a "not implemented" error message
515+ bool threw_desired_exception = false;
516+ try {
517+ for (auto & elem : mesh -> active_element_ptr_range ())
518+ {
519+ const Point c = elem -> vertex_average ();
520+ if (c (0 ) < 0.5 && c (1 ) > 0.5 )
521+ bi .add_side (elem , 3 , 3 );
522+ }
523+ }
524+ catch (libMesh ::NotImplemented & e ) {
525+ std ::regex msg_regex ("Trying to add boundary ID 3 which already exists on the ancestors" );
526+ CPPUNIT_ASSERT (std ::regex_search (e .what (), msg_regex ));
527+ threw_desired_exception = true;
528+ }
529+ // If we have more than 4 processors, or a poor partitioner, we
530+ // might not get an exception on every processor
531+ mesh -> comm ().max (threw_desired_exception );
532+
533+ CPPUNIT_ASSERT (threw_desired_exception );
534+
535+ threw_desired_exception = false;
536+ try {
537+ for (auto & elem : mesh -> active_element_ptr_range ())
538+ {
539+ const Point c = elem -> vertex_average ();
540+ if (c (0 ) < 0.5 && c (1 ) > 0.5 )
541+ bi .add_side (elem , 3 , {3 ,4 });
542+ }
543+ }
544+ catch (libMesh ::NotImplemented & e ) {
545+ std ::regex msg_regex ("Trying to add boundary ID 3 which already exists on the ancestors" );
546+ CPPUNIT_ASSERT (std ::regex_search (e .what (), msg_regex ));
547+ threw_desired_exception = true;
548+ }
549+
550+ // If we have more than 4 processors, or a poor partitioner, we
551+ // might not get an exception on every processor
552+ mesh -> comm ().max (threw_desired_exception );
553+
554+ CPPUNIT_ASSERT (threw_desired_exception );
555+
556+ // We tested the side addition errors, now we move to the removal parts.
557+ // We will attempt the removal of boundary 3 through the child
558+ threw_desired_exception = false;
559+ bi .allow_children_on_boundary_side (true);
560+ try {
561+ for (auto & elem : mesh -> active_element_ptr_range ())
562+ {
563+ const Point c = elem -> vertex_average ();
564+ if (c (0 ) < 0.5 && c (1 ) > 0.5 )
565+ bi .remove_side (elem , 3 , 3 );
566+ }
567+ }
568+ catch (libMesh ::NotImplemented & e ) {
569+ std ::regex msg_regex ("We cannot delete boundary ID 3 using a child because it is inherited from an ancestor" );
570+ CPPUNIT_ASSERT (std ::regex_search (e .what (), msg_regex ));
571+ threw_desired_exception = true;
572+ }
573+
574+ // If we have more than 4 processors, or a poor partitioner, we
575+ // might not get an exception on every processor
576+ mesh -> comm ().max (threw_desired_exception );
577+
578+ CPPUNIT_ASSERT (threw_desired_exception );
579+ }
580+
484581 void testBoundaryOnChildrenElementsRefineCoarsen ()
485582 {
486583 LOG_UNIT_TEST ;
@@ -618,8 +715,6 @@ public:
618715
619716 BoundaryInfo & bi = mesh -> get_boundary_info ();
620717
621- std ::ostringstream mystream ;
622-
623718 // We only have one element, but for easy access we use the iterator
624719 for (auto & elem : mesh -> active_element_ptr_range ())
625720 elem -> set_refinement_flag (Elem ::REFINE );
0 commit comments