20#include "libmesh/libmesh_config.h"
23#ifdef LIBMESH_ENABLE_AMR
25#include "libmesh/boundary_info.h"
26#include "libmesh/elem_range.h"
27#include "libmesh/error_vector.h"
28#include "libmesh/libmesh_logging.h"
29#include "libmesh/mesh_base.h"
30#include "libmesh/mesh_communication.h"
31#include "libmesh/mesh_refinement.h"
32#include "libmesh/parallel.h"
33#include "libmesh/parallel_ghost_sync.h"
34#include "libmesh/partitioner.h"
35#include "libmesh/remote_elem.h"
36#include "libmesh/sync_refinement_flags.h"
37#include "libmesh/int_range.h"
41#include "libmesh/mesh_tools.h"
44#ifdef LIBMESH_ENABLE_PERIODIC
45#include "libmesh/periodic_boundaries.h"
98 _use_member_parameters(false),
99 _coarsen_by_parents(false),
100 _refine_fraction(0.3),
101 _coarsen_fraction(0.0),
103 _coarsen_threshold(10),
105 _absolute_global_tolerance(0.0),
106 _face_level_mismatch_limit(1),
107 _edge_level_mismatch_limit(0),
108 _node_level_mismatch_limit(0),
109 _overrefined_boundary_limit(0),
110 _underrefined_boundary_limit(0),
111 _allow_unrefined_patches(false),
112 _enforce_mismatch_limit_prior_to_refinement(false)
113#ifdef LIBMESH_ENABLE_PERIODIC
114 , _periodic_boundaries(nullptr)
121#ifdef LIBMESH_ENABLE_PERIODIC
146 LOG_SCOPE(
"add_node()",
"MeshRefinement");
153 const std::vector<std::pair<dof_id_type, dof_id_type>>
185 libmesh_assert_not_equal_to (em_val, 1);
223 Real & parent_error_min,
224 Real & parent_error_max)
227 parallel_object_only();
231 for (
const auto & val : error_per_cell)
233 libmesh_assert_greater_equal (val, 0);
242 std::vector<ErrorVectorReal> & epc = error_per_parent;
247 error_per_parent.clear();
248 error_per_parent.resize(error_per_cell.size(), 0.0);
252 for (
auto & elem :
_mesh.active_local_element_ptr_range())
257 error_per_parent[elem->id()] = -1.0;
262 parent = parent->
parent();
266 libmesh_assert_less (parentid, error_per_parent.size());
267 error_per_parent[parentid] = -1.0;
275 std::vector<ErrorVectorReal> & epp = error_per_parent;
289 [&error_per_cell, &error_per_parent](
const ConstElemRange & range)
291 for (const Elem * elem : range)
293 const Elem * parent = elem->parent();
298 const dof_id_type parentid = parent->id();
299 libmesh_assert_less (parentid, error_per_parent.size());
304 if (error_per_parent[parentid] != -1.0)
305 error_per_parent[parentid] += (error_per_cell[elem->id()] *
306 error_per_cell[elem->id()]);
312 this->comm().sum(
static_cast<std::vector<ErrorVectorReal> &
>(error_per_parent));
315 parent_error_min = std::numeric_limits<double>::max();
316 parent_error_max = 0.;
325 if (error_per_parent[i] < 0.)
327 error_per_parent[i] = -1.;
334 if (error_per_cell[i])
336 error_per_parent[i] = error_per_cell[i];
341 error_per_parent[i] = std::sqrt(error_per_parent[i]);
343 parent_error_min = std::min (parent_error_min,
344 error_per_parent[i]);
345 parent_error_max = std::max (parent_error_max,
346 error_per_parent[i]);
352void MeshRefinement::update_nodes_map ()
354 this->_new_nodes_map.init(_mesh);
359bool MeshRefinement::test_level_one (
bool libmesh_dbg_var(libmesh_assert_pass))
const
362 parallel_object_only();
367 std::unique_ptr<PointLocatorBase> point_locator;
369#ifdef LIBMESH_ENABLE_PERIODIC
370 bool has_periodic_boundaries =
371 _periodic_boundaries && !_periodic_boundaries->empty();
374 if (has_periodic_boundaries)
375 point_locator = _mesh.sub_point_locator();
378 bool failure =
false;
381 Elem * failed_elem =
nullptr;
382 Elem * failed_neighbor =
nullptr;
385 for (
auto & elem : _mesh.active_local_element_ptr_range())
386 for (
auto n : elem->side_index_range())
389 topological_neighbor(elem, point_locator.get(), n);
391 if (!neighbor || !neighbor->
active() ||
395 if ((neighbor->
level() + 1 < elem->level()) ||
396 (neighbor->
p_level() + 1 < elem->p_level()) ||
397 (neighbor->
p_level() > elem->p_level() + 1))
402 failed_neighbor = neighbor;
409 this->comm().max(failure);
416 if (libmesh_assert_pass)
418 libMesh::out <<
"MeshRefinement Level one failure, element: "
421 libMesh::out <<
"MeshRefinement Level one failure, neighbor: "
434bool MeshRefinement::test_unflagged (
bool libmesh_dbg_var(libmesh_assert_pass))
const
437 parallel_object_only();
439 bool found_flag =
false;
442 Elem * failed_elem =
nullptr;
446 for (
auto & elem : _mesh.active_local_element_ptr_range())
447 if (elem->refinement_flag() == Elem::REFINE ||
448 elem->refinement_flag() == Elem::COARSEN ||
449 elem->p_refinement_flag() == Elem::REFINE ||
450 elem->p_refinement_flag() == Elem::COARSEN)
460 this->comm().max(found_flag);
465 if (libmesh_assert_pass)
468 "MeshRefinement test_unflagged failure, element: " <<
469 *failed_elem << std::endl;
482bool MeshRefinement::refine_and_coarsen_elements ()
485 parallel_object_only();
488 if (_face_level_mismatch_limit)
494 std::atomic<bool> elements_flagged{
false};
496 Threads::parallel_for
497 (_mesh.element_stored_range(),
498 [&elements_flagged](
const ElemRange & range)
500 for (Elem * elem : range)
503 const Elem::RefinementState flag = elem->refinement_flag();
509 elem->set_refinement_flag(Elem::INACTIVE);
510 elem->set_p_refinement_flag(Elem::INACTIVE);
512 else if (flag == Elem::JUST_REFINED)
513 elem->set_refinement_flag(Elem::DO_NOTHING);
514 else if (!elements_flagged)
516 if (flag == Elem::REFINE || flag == Elem::COARSEN)
517 elements_flagged = true;
520 const Elem::RefinementState pflag =
521 elem->p_refinement_flag();
522 if (pflag == Elem::REFINE || pflag == Elem::COARSEN)
523 elements_flagged = true;
530 bool any_elements_flagged = elements_flagged;
531 _mesh.comm().max(any_elements_flagged);
535 if (!any_elements_flagged)
542 bool flags_were_consistent = this->make_flags_parallel_consistent();
548 _smooth_flags(
true,
true);
551 const bool coarsening_changed_mesh =
552 this->_coarsen_elements ();
574 const bool refining_changed_mesh =
575 this->_refine_elements();
579 if (coarsening_changed_mesh || refining_changed_mesh)
582 _mesh.libmesh_assert_valid_parallel_ids();
585 _mesh.prepare_for_use ();
587 if (_face_level_mismatch_limit)
600 if (_face_level_mismatch_limit)
601 libmesh_assert(test_level_one(
true));
602 libmesh_assert(test_unflagged(
true));
603 libmesh_assert(this->make_coarsening_compatible());
604 libmesh_assert(this->make_refinement_compatible());
620bool MeshRefinement::coarsen_elements ()
623 parallel_object_only();
626 if (_face_level_mismatch_limit)
631 Threads::parallel_for
632 (_mesh.element_stored_range(),
635 for (Elem * elem : range)
641 elem->set_refinement_flag(Elem::INACTIVE);
642 elem->set_p_refinement_flag(Elem::INACTIVE);
646 if (elem->refinement_flag() == Elem::JUST_REFINED)
647 elem->set_refinement_flag(Elem::DO_NOTHING);
654 bool flags_were_consistent = this->make_flags_parallel_consistent();
664 if (!flags_were_consistent)
665 libmesh_warning(
"Warning: Refinement flags were not consistent between processors! "
666 "Correcting and continuing.\n");
669 _smooth_flags(
false,
true);
672 const bool mesh_changed =
673 this->_coarsen_elements ();
675 if (_face_level_mismatch_limit)
688 _mesh.prepare_for_use ();
699bool MeshRefinement::refine_elements ()
702 parallel_object_only();
714 if (_mesh.get_disjoint_neighbor_boundary_pairs())
716 libmesh_not_implemented_msg(
717 "Mesh refinement is not yet implemented for meshes with disjoint neighbor boundary interfaces.\n");
720 if (_face_level_mismatch_limit)
725 Threads::parallel_for
726 (_mesh.element_stored_range(),
729 for (Elem * elem : range)
735 elem->set_refinement_flag(Elem::INACTIVE);
736 elem->set_p_refinement_flag(Elem::INACTIVE);
740 if (elem->refinement_flag() == Elem::JUST_REFINED)
741 elem->set_refinement_flag(Elem::DO_NOTHING);
748 bool flags_were_consistent = this->make_flags_parallel_consistent();
758 if (!flags_were_consistent)
759 libmesh_warning(
"Warning: Refinement flags were not consistent between processors! "
760 "Correcting and continuing.\n");
763 _smooth_flags(
true,
false);
767 const bool mesh_changed =
768 this->_refine_elements();
770 if (_face_level_mismatch_limit)
780 _mesh.prepare_for_use ();
787bool MeshRefinement::make_flags_parallel_consistent()
790 parallel_object_only();
792 LOG_SCOPE (
"make_flags_parallel_consistent()",
"MeshRefinement");
795 &Elem::set_refinement_flag);
796 Parallel::sync_dofobject_data_by_id
797 (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), hsync);
800 &Elem::set_p_refinement_flag);
801 Parallel::sync_dofobject_data_by_id
802 (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), psync);
808 this->comm().min(parallel_consistent);
810 return parallel_consistent;
815bool MeshRefinement::make_coarsening_compatible()
818 parallel_object_only();
823 std::unique_ptr<PointLocatorBase> point_locator;
825#ifdef LIBMESH_ENABLE_PERIODIC
826 bool has_periodic_boundaries =
827 _periodic_boundaries && !_periodic_boundaries->empty();
830 if (has_periodic_boundaries)
831 point_locator = _mesh.sub_point_locator();
834 LOG_SCOPE (
"make_coarsening_compatible()",
"MeshRefinement");
838 bool level_one_satisfied =
true;
843 bool compatible_with_refinement =
true;
847 unsigned int max_level = 0;
848 unsigned int max_p_level = 0;
854 for (
auto & elem : _mesh.active_element_ptr_range())
856 max_level = std::max(max_level, elem->level());
858 std::max(max_p_level,
859 static_cast<unsigned int>(elem->p_level()));
861 if ((elem->level() == 0) &&
862 (elem->refinement_flag() == Elem::COARSEN))
863 elem->set_refinement_flag(Elem::DO_NOTHING);
865 if ((elem->p_level() == 0) &&
866 (elem->p_refinement_flag() == Elem::COARSEN))
867 elem->set_p_refinement_flag(Elem::DO_NOTHING);
876 if (max_level == 0 && max_p_level == 0)
879 this->comm().min(compatible_with_refinement);
881 return compatible_with_refinement;
891 if (_face_level_mismatch_limit)
895 level_one_satisfied =
true;
899 level_one_satisfied =
true;
901 for (
auto & elem : _mesh.active_element_ptr_range())
903 bool my_flag_changed =
false;
905 if (elem->refinement_flag() == Elem::COARSEN)
908 const unsigned int my_level = elem->level();
910 for (
auto n : elem->side_index_range())
912 const Elem * neighbor =
913 topological_neighbor(elem, point_locator.get(), n);
915 if (neighbor !=
nullptr &&
920 if ((neighbor->
level() == my_level) &&
924 elem->set_refinement_flag(Elem::DO_NOTHING);
925 my_flag_changed =
true;
934 elem->set_refinement_flag(Elem::DO_NOTHING);
935 my_flag_changed =
true;
941 if (elem->p_refinement_flag() == Elem::COARSEN)
944 const unsigned int my_p_level = elem->p_level();
946 for (
auto n : elem->side_index_range())
948 const Elem * neighbor =
949 topological_neighbor(elem, point_locator.get(), n);
951 if (neighbor !=
nullptr &&
956 if ((neighbor->
p_level() > my_p_level &&
958 || (neighbor->
p_level() == my_p_level &&
961 elem->set_p_refinement_flag(Elem::DO_NOTHING);
962 my_flag_changed =
true;
978 has_topological_neighbor(&subneighbor, point_locator.get(), elem))
979 if ((subneighbor.p_level() > my_p_level &&
980 subneighbor.p_refinement_flag() != Elem::COARSEN)
981 || (subneighbor.p_level() == my_p_level &&
982 subneighbor.p_refinement_flag() == Elem::REFINE))
984 elem->set_p_refinement_flag(Elem::DO_NOTHING);
985 my_flag_changed =
true;
998 level_one_satisfied =
false;
1005 if (my_flag_changed && !_mesh.is_serial())
1006 for (
auto n : elem->side_index_range())
1009 topological_neighbor(elem, point_locator.get(), n);
1015 this->processor_id())
1017 compatible_with_refinement =
false;
1026 this->processor_id())
1028 compatible_with_refinement =
false;
1034 while (!level_one_satisfied);
1045 for (
int level = max_level; level >= 0; level--)
1046 for (
auto & elem :
as_range(_mesh.level_elements_begin(level), _mesh.level_elements_end(level)))
1047 if (elem->ancestor())
1051 bool is_a_candidate =
true;
1052 bool found_remote_child =
false;
1054 for (
auto & child : elem->child_ref_range())
1057 found_remote_child =
true;
1058 else if ((child.refinement_flag() != Elem::COARSEN) ||
1060 is_a_candidate =
false;
1063 if (!is_a_candidate && !found_remote_child)
1065 elem->set_refinement_flag(Elem::INACTIVE);
1067 for (
auto & child : elem->child_ref_range())
1071 if (child.refinement_flag() == Elem::COARSEN)
1073 level_one_satisfied =
false;
1074 child.set_refinement_flag(Elem::DO_NOTHING);
1080 if (!level_one_satisfied && _face_level_mismatch_limit)
goto repeat;
1097 const bool distributed_mesh = !_mesh.is_replicated();
1099 std::vector<std::vector<dof_id_type>>
1100 uncoarsenable_parents(n_proc);
1102 for (
auto & elem :
as_range(_mesh.ancestor_elements_begin(), _mesh.ancestor_elements_end()))
1106 bool all_children_flagged_for_coarsening =
true;
1108 for (
auto & child : elem->child_ref_range())
1113 all_children_flagged_for_coarsening =
false;
1114 if (!distributed_mesh)
1116 if (child.processor_id() != elem->processor_id())
1118 uncoarsenable_parents[elem->processor_id()].push_back(elem->id());
1124 if (all_children_flagged_for_coarsening)
1125 elem->set_refinement_flag(Elem::COARSEN_INACTIVE);
1127 elem->set_refinement_flag(Elem::INACTIVE);
1132 if (distributed_mesh)
1135 parallel_object_only();
1138 uncoarsenable_tag = this->comm().get_unique_tag();
1139 std::vector<Parallel::Request> uncoarsenable_push_requests(n_proc-1);
1143 if (p == my_proc_id)
1147 uncoarsenable_push_requests[p - (p > my_proc_id)];
1150 (p, uncoarsenable_parents[p], request, uncoarsenable_tag);
1155 std::vector<dof_id_type> my_uncoarsenable_parents;
1156 _mesh.comm().receive
1157 (Parallel::any_source, my_uncoarsenable_parents,
1160 for (
const auto &
id : my_uncoarsenable_parents)
1162 Elem & elem = _mesh.elem_ref(
id);
1169 Parallel::wait(uncoarsenable_push_requests);
1172 &Elem::set_refinement_flag);
1173 sync_dofobject_data_by_id
1174 (this->comm(), _mesh.not_local_elements_begin(),
1175 _mesh.not_local_elements_end(),
1183 this->comm().min(compatible_with_refinement);
1185 return compatible_with_refinement;
1195bool MeshRefinement::make_refinement_compatible()
1198 parallel_object_only();
1203 std::unique_ptr<PointLocatorBase> point_locator;
1205#ifdef LIBMESH_ENABLE_PERIODIC
1206 bool has_periodic_boundaries =
1207 _periodic_boundaries && !_periodic_boundaries->empty();
1210 if (has_periodic_boundaries)
1211 point_locator = _mesh.sub_point_locator();
1214 LOG_SCOPE (
"make_refinement_compatible()",
"MeshRefinement");
1218 bool compatible_with_coarsening =
true;
1222 if (_face_level_mismatch_limit)
1226 bool level_one_satisfied =
true;
1230 level_one_satisfied =
true;
1232 for (
auto & elem : _mesh.active_element_ptr_range())
1234 const unsigned short n_sides = elem->n_sides();
1236 if (elem->refinement_flag() == Elem::REFINE)
1239 const unsigned int my_level = elem->level();
1241 for (
unsigned short side = 0; side != n_sides;
1245 topological_neighbor(elem, point_locator.get(), side);
1247 if (neighbor !=
nullptr &&
1255 if (neighbor->
level() == my_level)
1262 compatible_with_coarsening =
false;
1263 level_one_satisfied =
false;
1274 else if ((neighbor->
level()+1) == my_level)
1281 compatible_with_coarsening =
false;
1282 level_one_satisfied =
false;
1290 libmesh_error_msg(
"ERROR: Neighbor level must be equal or 1 higher than mine.");
1295 if (elem->p_refinement_flag() == Elem::REFINE)
1298 const unsigned int my_p_level = elem->p_level();
1300 for (
unsigned int side=0; side != n_sides; side++)
1303 topological_neighbor(elem, point_locator.get(), side);
1305 if (neighbor !=
nullptr &&
1310 if (neighbor->
p_level() < my_p_level &&
1314 level_one_satisfied =
false;
1315 compatible_with_coarsening =
false;
1317 if (neighbor->
p_level() == my_p_level &&
1321 level_one_satisfied =
false;
1322 compatible_with_coarsening =
false;
1330 has_topological_neighbor(&subneighbor, point_locator.get(), elem))
1332 if (subneighbor.p_level() < my_p_level &&
1333 subneighbor.p_refinement_flag() != Elem::REFINE)
1337 libmesh_assert_greater (subneighbor.p_level() + 2u,
1339 subneighbor.set_p_refinement_flag(Elem::REFINE);
1340 level_one_satisfied =
false;
1341 compatible_with_coarsening =
false;
1343 if (subneighbor.p_level() == my_p_level &&
1344 subneighbor.p_refinement_flag() == Elem::COARSEN)
1346 subneighbor.set_p_refinement_flag(Elem::DO_NOTHING);
1347 level_one_satisfied =
false;
1348 compatible_with_coarsening =
false;
1358 while (!level_one_satisfied);
1363 this->comm().min(compatible_with_coarsening);
1365 return compatible_with_coarsening;
1371bool MeshRefinement::_coarsen_elements ()
1374 parallel_object_only();
1376 LOG_SCOPE (
"_coarsen_elements()",
"MeshRefinement");
1379 bool mesh_changed =
false;
1380 bool mesh_p_changed =
false;
1394 for (
auto & elem : _mesh.element_ptr_range())
1395 if (elem->refinement_flag() == Elem::COARSEN)
1397 mesh_changed =
true;
1402 this->comm().max(mesh_changed);
1408 for (
auto & elem : _mesh.element_ptr_range())
1412 _mesh.get_boundary_info().transfer_boundary_ids_from_children(elem);
1416 if (elem->refinement_flag() == Elem::COARSEN)
1420 libmesh_assert_not_equal_to (elem->level(), 0);
1424 elem->nullify_neighbors();
1430 if (!_mesh.get_boundary_info().is_children_on_boundary_side())
1431 _mesh.get_boundary_info().remove (elem);
1445 else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1451 mesh_changed =
true;
1453 if (elem->p_refinement_flag() == Elem::COARSEN)
1455 if (elem->p_level() > 0)
1457 elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1458 elem->set_p_level(elem->p_level() - 1);
1459 mesh_p_changed =
true;
1463 elem->set_p_refinement_flag(Elem::DO_NOTHING);
1468 this->comm().max(mesh_p_changed);
1472 _mesh.update_parallel_id_counts();
1476 if (mesh_changed && !_mesh.is_serial())
1480 this->update_nodes_map ();
1488 MeshTools::libmesh_assert_valid_procids<Node>(_mesh);
1494 if (mesh_p_changed && !_mesh.is_serial())
1499 return (mesh_changed || mesh_p_changed);
1504bool MeshRefinement::_refine_elements ()
1509 parallel_object_only();
1513 this->update_nodes_map ();
1515 LOG_SCOPE (
"_refine_elements()",
"MeshRefinement");
1521 for (
auto & elem : _mesh.element_ptr_range())
1522 if (elem->refinement_flag() == Elem::REFINE)
1528 std::vector<Elem *> local_copy_of_elements;
1529 local_copy_of_elements.reserve(n_elems_flagged);
1533 bool mesh_p_changed =
false;
1560 for (
auto & elem : _mesh.is_replicated() ? _mesh.active_element_ptr_range() : _mesh.active_local_element_ptr_range())
1562 if (elem->refinement_flag() == Elem::REFINE)
1563 local_copy_of_elements.push_back(elem);
1564 if (elem->p_refinement_flag() == Elem::REFINE &&
1567 elem->set_p_level(elem->p_level()+1);
1568 elem->set_p_refinement_flag(Elem::JUST_REFINED);
1569 mesh_p_changed =
true;
1573 if (!_mesh.is_replicated())
1575 for (
auto & elem :
as_range(_mesh.active_not_local_elements_begin(),
1576 _mesh.active_not_local_elements_end()))
1578 if (elem->refinement_flag() == Elem::REFINE)
1579 local_copy_of_elements.push_back(elem);
1580 if (elem->p_refinement_flag() == Elem::REFINE &&
1583 elem->set_p_level(elem->p_level()+1);
1584 elem->set_p_refinement_flag(Elem::JUST_REFINED);
1585 mesh_p_changed =
true;
1593 for (
auto & elem : local_copy_of_elements)
1594 elem->refine(*
this);
1597 bool mesh_changed = !local_copy_of_elements.empty();
1600 this->comm().max(mesh_changed);
1601 this->comm().max(mesh_p_changed);
1605 _mesh.update_parallel_id_counts();
1607 if (mesh_changed && !_mesh.is_replicated())
1612 _mesh.libmesh_assert_valid_parallel_ids();
1619 if (mesh_changed && _mesh.is_replicated() &&
1620 (_mesh.unpartitioned_elements_begin() ==
1621 _mesh.unpartitioned_elements_end()))
1622 Partitioner::set_node_processor_ids(_mesh);
1624 if (mesh_p_changed && !_mesh.is_replicated())
1632 return (mesh_changed || mesh_p_changed);
1636void MeshRefinement::_smooth_flags(
bool refining,
bool coarsening)
1640 MeshTools::libmesh_assert_valid_neighbors(_mesh);
1647 bool satisfied =
false;
1652 const bool coarsening_satisfied =
1654 this->make_coarsening_compatible();
1656 const bool refinement_satisfied =
1658 this->make_refinement_compatible();
1660 bool smoothing_satisfied =
1661 !this->eliminate_unrefined_patches();
1663 if (_edge_level_mismatch_limit)
1664 smoothing_satisfied = smoothing_satisfied &&
1665 !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
1667 if (_node_level_mismatch_limit)
1668 smoothing_satisfied = smoothing_satisfied &&
1669 !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
1671 if (_overrefined_boundary_limit>=0)
1672 smoothing_satisfied = smoothing_satisfied &&
1673 !this->limit_overrefined_boundary(_overrefined_boundary_limit);
1675 if (_underrefined_boundary_limit>=0)
1676 smoothing_satisfied = smoothing_satisfied &&
1677 !this->limit_underrefined_boundary(_underrefined_boundary_limit);
1679 satisfied = (coarsening_satisfied &&
1680 refinement_satisfied &&
1681 smoothing_satisfied);
1687 while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
1691void MeshRefinement::uniformly_p_refine (
unsigned int n)
1694 for (
unsigned int rstep=0; rstep<n; rstep++)
1695 for (
auto & elem : _mesh.active_element_ptr_range())
1698 elem->set_p_level(elem->p_level()+1);
1699 elem->set_p_refinement_flag(Elem::JUST_REFINED);
1705void MeshRefinement::uniformly_p_coarsen (
unsigned int n)
1708 for (
unsigned int rstep=0; rstep<n; rstep++)
1709 for (
auto & elem : _mesh.active_element_ptr_range())
1710 if (elem->p_level() > 0)
1713 elem->set_p_level(elem->p_level()-1);
1714 elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1720void MeshRefinement::uniformly_refine (
unsigned int n)
1725 for (
unsigned int rstep=0; rstep<n; rstep++)
1728 this->clean_refinement_flags();
1731 for (
auto & elem : _mesh.active_element_ptr_range())
1732 elem->set_refinement_flag(Elem::REFINE);
1735 this->_refine_elements();
1740 _mesh.prepare_for_use ();
1745void MeshRefinement::uniformly_coarsen (
unsigned int n)
1748 for (
unsigned int rstep=0; rstep<n; rstep++)
1751 this->clean_refinement_flags();
1754 for (
auto & elem : _mesh.active_element_ptr_range())
1756 elem->set_refinement_flag(Elem::COARSEN);
1758 elem->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
1764 if (!_mesh.is_replicated())
1769 std::vector<std::vector<dof_id_type>>
1770 parents_to_coarsen(n_proc);
1772 for (
const auto & elem :
as_range(_mesh.ancestor_elements_begin(), _mesh.ancestor_elements_end()))
1773 if (elem->processor_id() != my_proc_id &&
1774 elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1775 parents_to_coarsen[elem->processor_id()].push_back(elem->id());
1778 coarsen_tag = this->comm().get_unique_tag();
1779 std::vector<Parallel::Request> coarsen_push_requests(n_proc-1);
1783 if (p == my_proc_id)
1787 coarsen_push_requests[p - (p > my_proc_id)];
1790 (p, parents_to_coarsen[p], request, coarsen_tag);
1795 std::vector<dof_id_type> my_parents_to_coarsen;
1796 _mesh.comm().receive
1797 (Parallel::any_source, my_parents_to_coarsen,
1800 for (
const auto &
id : my_parents_to_coarsen)
1802 Elem & elem = _mesh.elem_ref(
id);
1809 Parallel::wait(coarsen_push_requests);
1812 &Elem::set_refinement_flag);
1813 sync_dofobject_data_by_id
1814 (this->comm(), _mesh.not_local_elements_begin(),
1815 _mesh.not_local_elements_end(),
1822 this->_coarsen_elements();
1828 _mesh.prepare_for_use ();
1833Elem * MeshRefinement::topological_neighbor(
Elem * elem,
1835 const unsigned int side)
const
1837#ifdef LIBMESH_ENABLE_PERIODIC
1838 if (_periodic_boundaries && !_periodic_boundaries->empty())
1849bool MeshRefinement::has_topological_neighbor(
const Elem * elem,
1851 const Elem * neighbor)
const
1853#ifdef LIBMESH_ENABLE_PERIODIC
1854 if (_periodic_boundaries && !_periodic_boundaries->empty())
void min(const T &r, T &o, Request &req) const
processor_id_type processor_id() const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
This is the base class from which all geometric element types are derived.
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
RefinementState refinement_flag() const
bool has_neighbor(const Elem *elem) const
const Point & point(const unsigned int i) const
bool has_children() const
const Elem * parent() const
virtual const std::vector< std::pair< dof_id_type, dof_id_type > > bracketing_nodes(unsigned int c, unsigned int n) const
bool has_topological_neighbor(const Elem *elem, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
unsigned int level() const
const Node * node_ptr(const unsigned int i) const
virtual unsigned int as_parent_node(unsigned int c, unsigned int n) const
IntRange< unsigned short > node_index_range() const
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
unsigned int p_level() const
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
RefinementState p_refinement_flag() const
const Elem * neighbor_ptr(unsigned int i) const
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
This is the MeshBase class.
virtual const Node * node_ptr(const dof_id_type i) const =0
const ConstElemRange & active_local_element_stored_range() const
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.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
This is the MeshCommunication class.
void make_elems_parallel_consistent(MeshBase &)
Copy ids of ghost elements from their local processors.
void send_coarse_ghosts(MeshBase &) const
Examine a just-coarsened mesh, and for any newly-coarsened elements, send the associated ghosted elem...
void make_p_levels_parallel_consistent(MeshBase &)
Copy p levels of ghost elements from their local processors.
void make_nodes_parallel_consistent(MeshBase &)
Copy processor_ids and ids on ghost nodes from their local processors.
void make_new_nodes_parallel_consistent(MeshBase &)
Copy processor_ids and ids on new nodes from their local processors.
Elem * add_elem(Elem *elem)
Adds the element elem to the mesh.
PeriodicBoundaries * _periodic_boundaries
TopologyMap _new_nodes_map
Data structure that holds the new nodes information.
MeshBase & _mesh
Reference to the mesh.
void set_periodic_boundaries_ptr(PeriodicBoundaries *pb_ptr)
Sets the PeriodicBoundaries pointer.
Node * add_node(Elem &parent, unsigned int child, unsigned int node, processor_id_type proc_id)
Add a node to the mesh.
MeshRefinement(MeshBase &mesh)
Constructor.
void create_parent_error_vector(const ErrorVector &error_per_cell, ErrorVector &error_per_parent, Real &parent_error_min, Real &parent_error_max)
Calculates the error on all coarsenable parents.
~MeshRefinement()
Destructor.
void clear()
Deletes all the data that are currently stored.
A Node is like a Point, but with more information.
An object whose state is distributed along a set of processors.
const Parallel::Communicator & comm() const
We're using a class instead of a typedef to allow forward declarations and future flexibility.
This is the base class for point locators.
A Point defines a location in LIBMESH_DIM dimensional Real space.
The StoredRange class defines a contiguous, divisible set of objects.
dof_id_type find(dof_id_type bracket_node1, dof_id_type bracket_node2) const
void add_node(const Node &mid_node, const std::vector< std::pair< dof_id_type, dof_id_type > > &bracketing_nodes)
Add a node to the map, between each pair of specified bracketing nodes.
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
bool isnan(std::complex< T > a)
const RemoteElem * remote_elem
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type