25 #include "libmesh/libmesh_config.h"
28 #ifdef LIBMESH_ENABLE_AMR
30 #include "libmesh/boundary_info.h"
31 #include "libmesh/error_vector.h"
32 #include "libmesh/libmesh_logging.h"
33 #include "libmesh/mesh_base.h"
34 #include "libmesh/mesh_communication.h"
35 #include "libmesh/mesh_refinement.h"
36 #include "libmesh/parallel.h"
37 #include "libmesh/parallel_ghost_sync.h"
38 #include "libmesh/partitioner.h"
39 #include "libmesh/remote_elem.h"
40 #include "libmesh/sync_refinement_flags.h"
41 #include "libmesh/int_range.h"
45 #include "libmesh/mesh_tools.h"
48 #ifdef LIBMESH_ENABLE_PERIODIC
49 #include "libmesh/periodic_boundaries.h"
97 _use_member_parameters(false),
98 _coarsen_by_parents(false),
99 _refine_fraction(0.3),
100 _coarsen_fraction(0.0),
102 _coarsen_threshold(10),
104 _absolute_global_tolerance(0.0),
105 _face_level_mismatch_limit(1),
106 _edge_level_mismatch_limit(0),
107 _node_level_mismatch_limit(0),
108 _overrefined_boundary_limit(0),
109 _underrefined_boundary_limit(0),
110 _enforce_mismatch_limit_prior_to_refinement(false)
111 #ifdef LIBMESH_ENABLE_PERIODIC
112 , _periodic_boundaries(nullptr)
119 #ifdef LIBMESH_ENABLE_PERIODIC
147 LOG_SCOPE(
"add_node()",
"MeshRefinement");
154 const std::vector<std::pair<dof_id_type, dof_id_type>>
188 libmesh_assert_not_equal_to (em_val, 1);
222 Real & parent_error_min,
223 Real & parent_error_max)
226 parallel_object_only();
230 for (
const auto & val : error_per_cell)
232 libmesh_assert_greater_equal (val, 0);
241 std::vector<ErrorVectorReal> & epc = error_per_parent;
243 #endif // #ifdef DEBUG
246 error_per_parent.clear();
247 error_per_parent.resize(error_per_cell.size(), 0.0);
256 error_per_parent[elem->id()] = -1.0;
261 parent = parent->
parent();
265 libmesh_assert_less (parentid, error_per_parent.size());
266 error_per_parent[parentid] = -1.0;
274 std::vector<ErrorVectorReal> & epp = error_per_parent;
275 this->
comm().min(epp);
294 libmesh_assert_less (parentid, error_per_parent.size());
299 if (error_per_parent[parentid] != -1.0)
300 error_per_parent[parentid] += (error_per_cell[elem->id()] *
301 error_per_cell[elem->id()]);
306 this->
comm().sum(
static_cast<std::vector<ErrorVectorReal> &
>(error_per_parent));
309 parent_error_min = std::numeric_limits<double>::max();
310 parent_error_max = 0.;
319 if (error_per_parent[i] < 0.)
321 error_per_parent[i] = -1.;
328 if (error_per_cell[i])
330 error_per_parent[i] = error_per_cell[i];
335 error_per_parent[i] =
std::sqrt(error_per_parent[i]);
337 parent_error_min = std::min (parent_error_min,
338 error_per_parent[i]);
339 parent_error_max = std::max (parent_error_max,
340 error_per_parent[i]);
356 parallel_object_only();
361 std::unique_ptr<PointLocatorBase> point_locator;
363 #ifdef LIBMESH_ENABLE_PERIODIC
364 bool has_periodic_boundaries =
368 if (has_periodic_boundaries)
372 bool failure =
false;
375 Elem * failed_elem =
nullptr;
376 Elem * failed_neighbor =
nullptr;
380 for (
auto n : elem->side_index_range())
385 if (!neighbor || !neighbor->
active() ||
389 if ((neighbor->
level() + 1 < elem->level()) ||
390 (neighbor->
p_level() + 1 < elem->p_level()) ||
391 (neighbor->
p_level() > elem->p_level() + 1))
396 failed_neighbor = neighbor;
403 this->
comm().max(failure);
410 if (libmesh_assert_pass)
412 libMesh::out <<
"MeshRefinement Level one failure, element: "
415 libMesh::out <<
"MeshRefinement Level one failure, neighbor: "
431 parallel_object_only();
433 bool found_flag =
false;
436 Elem * failed_elem =
nullptr;
454 this->
comm().max(found_flag);
459 if (libmesh_assert_pass)
462 "MeshRefinement test_unflagged failure, element: " <<
463 *failed_elem << std::endl;
479 parallel_object_only();
488 bool elements_flagged =
false;
497 if ( !elem->active())
504 else if (!elements_flagged)
507 elements_flagged =
true;
511 elem->p_refinement_flag();
513 elements_flagged =
true;
523 if (!elements_flagged)
539 const bool coarsening_changed_mesh =
562 const bool refining_changed_mesh =
567 if (coarsening_changed_mesh || refining_changed_mesh)
611 parallel_object_only();
646 if (!flags_were_consistent)
648 libMesh::out <<
"Refinement flags were not consistent between processors!\n"
649 <<
"Correcting and continuing.";
656 const bool mesh_changed =
686 parallel_object_only();
722 if (!flags_were_consistent)
724 libMesh::out <<
"Refinement flags were not consistent between processors!\n"
725 <<
"Correcting and continuing.";
733 const bool mesh_changed =
755 parallel_object_only();
757 LOG_SCOPE (
"make_flags_parallel_consistent()",
"MeshRefinement");
772 psync.parallel_consistent;
773 this->
comm().min(parallel_consistent);
775 return parallel_consistent;
783 parallel_object_only();
788 std::unique_ptr<PointLocatorBase> point_locator;
790 #ifdef LIBMESH_ENABLE_PERIODIC
791 bool has_periodic_boundaries =
795 if (has_periodic_boundaries)
799 LOG_SCOPE (
"make_coarsening_compatible()",
"MeshRefinement");
803 bool level_one_satisfied =
true;
808 bool compatible_with_refinement =
true;
813 unsigned int max_p_level = 0;
823 std::max(max_p_level,
824 static_cast<unsigned int>(elem->p_level()));
826 if ((elem->level() == 0) &&
830 if ((elem->p_level() == 0) &&
844 this->
comm().min(compatible_with_refinement);
846 return compatible_with_refinement;
860 level_one_satisfied =
true;
864 level_one_satisfied =
true;
868 bool my_flag_changed =
false;
873 const unsigned int my_level = elem->level();
875 for (
auto n : elem->side_index_range())
877 const Elem * neighbor =
880 if (neighbor !=
nullptr &&
885 if ((neighbor->
level() == my_level) &&
890 my_flag_changed =
true;
900 my_flag_changed =
true;
909 const unsigned int my_p_level = elem->p_level();
911 for (
auto n : elem->side_index_range())
913 const Elem * neighbor =
916 if (neighbor !=
nullptr &&
921 if ((neighbor->
p_level() > my_p_level &&
923 || (neighbor->
p_level() == my_p_level &&
927 my_flag_changed =
true;
944 if ((subneighbor.p_level() > my_p_level &&
946 || (subneighbor.p_level() == my_p_level &&
950 my_flag_changed =
true;
963 level_one_satisfied =
false;
971 for (
auto n : elem->side_index_range())
982 compatible_with_refinement =
false;
993 compatible_with_refinement =
false;
999 while (!level_one_satisfied);
1010 for (
int level =
max_level; level >= 0; level--)
1012 if (elem->ancestor())
1016 bool is_a_candidate =
true;
1017 bool found_remote_child =
false;
1019 for (
auto & child : elem->child_ref_range())
1022 found_remote_child =
true;
1025 is_a_candidate =
false;
1028 if (!is_a_candidate && !found_remote_child)
1032 for (
auto & child : elem->child_ref_range())
1038 level_one_satisfied =
false;
1064 std::vector<std::vector<dof_id_type>>
1065 uncoarsenable_parents(n_proc);
1071 bool all_children_flagged_for_coarsening =
true;
1073 for (
auto & child : elem->child_ref_range())
1078 all_children_flagged_for_coarsening =
false;
1079 if (!distributed_mesh)
1081 if (child.processor_id() != elem->processor_id())
1083 uncoarsenable_parents[elem->processor_id()].push_back(elem->id());
1089 if (all_children_flagged_for_coarsening)
1097 if (distributed_mesh)
1100 parallel_object_only();
1102 Parallel::MessageTag
1103 uncoarsenable_tag = this->
comm().get_unique_tag();
1104 std::vector<Parallel::Request> uncoarsenable_push_requests(n_proc-1);
1108 if (p == my_proc_id)
1111 Parallel::Request &request =
1112 uncoarsenable_push_requests[p - (p > my_proc_id)];
1115 (p, uncoarsenable_parents[p], request, uncoarsenable_tag);
1120 std::vector<dof_id_type> my_uncoarsenable_parents;
1122 (Parallel::any_source, my_uncoarsenable_parents,
1125 for (
const auto &
id : my_uncoarsenable_parents)
1134 Parallel::wait(uncoarsenable_push_requests);
1148 this->
comm().min(compatible_with_refinement);
1150 return compatible_with_refinement;
1163 parallel_object_only();
1168 std::unique_ptr<PointLocatorBase> point_locator;
1170 #ifdef LIBMESH_ENABLE_PERIODIC
1171 bool has_periodic_boundaries =
1175 if (has_periodic_boundaries)
1179 LOG_SCOPE (
"make_refinement_compatible()",
"MeshRefinement");
1183 bool compatible_with_coarsening =
true;
1191 bool level_one_satisfied =
true;
1195 level_one_satisfied =
true;
1199 const unsigned short n_sides = elem->n_sides();
1204 const unsigned int my_level = elem->level();
1206 for (
unsigned short side = 0; side != n_sides;
1212 if (neighbor !=
nullptr &&
1220 if (neighbor->
level() == my_level)
1227 compatible_with_coarsening =
false;
1228 level_one_satisfied =
false;
1239 else if ((neighbor->
level()+1) == my_level)
1246 compatible_with_coarsening =
false;
1247 level_one_satisfied =
false;
1255 libmesh_error_msg(
"ERROR: Neighbor level must be equal or 1 higher than mine.");
1263 const unsigned int my_p_level = elem->p_level();
1265 for (
unsigned int side=0; side != n_sides; side++)
1270 if (neighbor !=
nullptr &&
1275 if (neighbor->
p_level() < my_p_level &&
1279 level_one_satisfied =
false;
1280 compatible_with_coarsening =
false;
1282 if (neighbor->
p_level() == my_p_level &&
1286 level_one_satisfied =
false;
1287 compatible_with_coarsening =
false;
1297 if (subneighbor.p_level() < my_p_level &&
1302 libmesh_assert_greater (subneighbor.p_level() + 2u,
1305 level_one_satisfied =
false;
1306 compatible_with_coarsening =
false;
1308 if (subneighbor.p_level() == my_p_level &&
1312 level_one_satisfied =
false;
1313 compatible_with_coarsening =
false;
1323 while (!level_one_satisfied);
1328 this->
comm().min(compatible_with_coarsening);
1330 return compatible_with_coarsening;
1339 parallel_object_only();
1341 LOG_SCOPE (
"_coarsen_elements()",
"MeshRefinement");
1344 bool mesh_changed =
false;
1345 bool mesh_p_changed =
false;
1362 mesh_changed =
true;
1367 this->
comm().max(mesh_changed);
1381 libmesh_assert_not_equal_to (elem->level(), 0);
1385 elem->nullify_neighbors();
1409 mesh_changed =
true;
1413 if (elem->p_level() > 0)
1416 elem->set_p_level(elem->p_level() - 1);
1417 mesh_p_changed =
true;
1426 this->
comm().max(mesh_p_changed);
1446 MeshTools::libmesh_assert_valid_procids<Node>(
_mesh);
1457 return (mesh_changed || mesh_p_changed);
1467 parallel_object_only();
1473 LOG_SCOPE (
"_refine_elements()",
"MeshRefinement");
1486 std::vector<Elem *> local_copy_of_elements;
1487 local_copy_of_elements.reserve(n_elems_flagged);
1491 bool mesh_p_changed =
false;
1521 local_copy_of_elements.push_back(elem);
1525 elem->set_p_level(elem->p_level()+1);
1527 mesh_p_changed =
true;
1537 local_copy_of_elements.push_back(elem);
1541 elem->set_p_level(elem->p_level()+1);
1543 mesh_p_changed =
true;
1551 for (
auto & elem : local_copy_of_elements)
1552 elem->refine(*
this);
1555 bool mesh_changed = !local_copy_of_elements.empty();
1558 this->
comm().max(mesh_changed);
1559 this->
comm().max(mesh_p_changed);
1590 return (mesh_changed || mesh_p_changed);
1605 bool satisfied =
false;
1610 const bool coarsening_satisfied =
1614 const bool refinement_satisfied =
1618 bool smoothing_satisfied =
1622 smoothing_satisfied = smoothing_satisfied &&
1626 smoothing_satisfied = smoothing_satisfied &&
1630 smoothing_satisfied = smoothing_satisfied &&
1634 smoothing_satisfied = smoothing_satisfied &&
1637 satisfied = (coarsening_satisfied &&
1638 refinement_satisfied &&
1639 smoothing_satisfied);
1652 for (
unsigned int rstep=0; rstep<n; rstep++)
1656 elem->set_p_level(elem->p_level()+1);
1666 for (
unsigned int rstep=0; rstep<n; rstep++)
1668 if (elem->p_level() > 0)
1671 elem->set_p_level(elem->p_level()-1);
1683 for (
unsigned int rstep=0; rstep<n; rstep++)
1706 for (
unsigned int rstep=0; rstep<n; rstep++)
1727 std::vector<std::vector<dof_id_type>>
1728 parents_to_coarsen(n_proc);
1731 if (elem->processor_id() != my_proc_id &&
1733 parents_to_coarsen[elem->processor_id()].push_back(elem->id());
1735 Parallel::MessageTag
1736 coarsen_tag = this->
comm().get_unique_tag();
1737 std::vector<Parallel::Request> coarsen_push_requests(n_proc-1);
1741 if (p == my_proc_id)
1744 Parallel::Request &request =
1745 coarsen_push_requests[p - (p > my_proc_id)];
1748 (p, parents_to_coarsen[p], request, coarsen_tag);
1753 std::vector<dof_id_type> my_parents_to_coarsen;
1755 (Parallel::any_source, my_parents_to_coarsen,
1758 for (
const auto &
id : my_parents_to_coarsen)
1767 Parallel::wait(coarsen_push_requests);
1793 const unsigned int side)
1795 #ifdef LIBMESH_ENABLE_PERIODIC
1809 const Elem * neighbor)
1811 #ifdef LIBMESH_ENABLE_PERIODIC