libMesh
Classes | Public Member Functions | Protected Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
libMesh::MeshRefinement Class Reference

Implements (adaptive) mesh refinement algorithms for a MeshBase. More...

#include <mesh_refinement.h>

Inheritance diagram for libMesh::MeshRefinement:
[legend]

Classes

class  ElementFlagging
 Abstract base class to be used for user-specified element flagging. More...
 

Public Member Functions

 MeshRefinement (MeshBase &mesh)
 Constructor. More...
 
void set_periodic_boundaries_ptr (PeriodicBoundaries *pb_ptr)
 Sets the PeriodicBoundaries pointer. More...
 
 ~MeshRefinement ()
 Destructor. More...
 
void clear ()
 Deletes all the data that are currently stored. More...
 
void flag_elements_by_error_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
 Flags elements for coarsening and refinement based on the computed error passed in error_per_cell. More...
 
void flag_elements_by_error_tolerance (const ErrorVector &error_per_cell)
 Flags elements for coarsening and refinement based on the computed error passed in error_per_cell. More...
 
bool flag_elements_by_nelem_target (const ErrorVector &error_per_cell)
 Flags elements for coarsening and refinement based on the computed error passed in error_per_cell. More...
 
void flag_elements_by_elem_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
 Flags elements for coarsening and refinement based on the computed error passed in error_per_cell. More...
 
void flag_elements_by_mean_stddev (const ErrorVector &error_per_cell, const Real refine_fraction=1.0, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
 Flags elements for coarsening and refinement based on the computed error passed in error_per_cell. More...
 
void flag_elements_by (ElementFlagging &element_flagging)
 Flag elements based on a function object. More...
 
void switch_h_to_p_refinement ()
 Takes a mesh whose elements are flagged for h refinement and coarsening, and switches those flags to request p refinement and coarsening instead. More...
 
void add_p_to_h_refinement ()
 Takes a mesh whose elements are flagged for h refinement and coarsening, and adds flags to request p refinement and coarsening of the same elements. More...
 
bool refine_and_coarsen_elements ()
 Refines and coarsens user-requested elements. More...
 
bool coarsen_elements ()
 Only coarsens the user-requested elements. More...
 
bool refine_elements ()
 Only refines the user-requested elements. More...
 
void uniformly_refine (unsigned int n=1)
 Uniformly refines the mesh n times. More...
 
void uniformly_coarsen (unsigned int n=1)
 Attempts to uniformly coarsen the mesh n times. More...
 
void uniformly_p_refine (unsigned int n=1)
 Uniformly p refines the mesh n times. More...
 
void uniformly_p_coarsen (unsigned int n=1)
 Attempts to uniformly p coarsen the mesh n times. More...
 
void clean_refinement_flags ()
 Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh. More...
 
bool test_level_one (bool libmesh_assert_yes=false) const
 
bool test_unflagged (bool libmesh_assert_yes=false) const
 
Nodeadd_node (Elem &parent, unsigned int child, unsigned int node, processor_id_type proc_id)
 Add a node to the mesh. More...
 
Elemadd_elem (Elem *elem)
 Adds the element elem to the mesh. More...
 
Elemadd_elem (std::unique_ptr< Elem > elem)
 Same as the function above, but makes it clear that the MeshRefinement object (actually, its Mesh) takes ownership of the Elem which is passed in, so the user is not responsible for deleting it. More...
 
const MeshBaseget_mesh () const
 
MeshBaseget_mesh ()
 
bool & coarsen_by_parents ()
 If coarsen_by_parents is true, complete groups of sibling elements (elements with the same parent) will be flagged for coarsening. More...
 
Realrefine_fraction ()
 The refine_fraction sets either a desired target or a desired maximum number of elements to flag for refinement, depending on which flag_elements_by method is called. More...
 
Realcoarsen_fraction ()
 The coarsen_fraction sets either a desired target or a desired maximum number of elements to flag for coarsening, depending on which flag_elements_by method is called. More...
 
unsigned intmax_h_level ()
 The max_h_level is the greatest refinement level an element should reach. More...
 
Realcoarsen_threshold ()
 The coarsen_threshold provides hysteresis in AMR/C strategies. More...
 
dof_id_typenelem_target ()
 If nelem_target is set to a nonzero value, methods like flag_elements_by_nelem_target() will attempt to keep the number of active elements in the mesh close to nelem_target. More...
 
Realabsolute_global_tolerance ()
 If absolute_global_tolerance is set to a nonzero value, methods like flag_elements_by_global_tolerance() will attempt to reduce the global error of the mesh (defined as the square root of the sum of the squares of the errors on active elements) to below this tolerance. More...
 
unsigned char & face_level_mismatch_limit ()
 If face_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two face neighbors will not differ by more than that limit. More...
 
unsigned char & edge_level_mismatch_limit ()
 If edge_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two edge neighbors will not differ by more than that limit. More...
 
unsigned char & node_level_mismatch_limit ()
 If node_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two nodal neighbors will not differ by more than that limit. More...
 
signed char & overrefined_boundary_limit ()
 If overrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will produce meshes in which the refinement level of a boundary element is no more than that many levels greater than the level of any of its interior neighbors. More...
 
signed char & underrefined_boundary_limit ()
 If underrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will produce meshes in which the refinement level of an element is no more than that many levels greater than the level of any boundary elements on its sides. More...
 
bool & allow_unrefined_patches ()
 This flag defaults to false in order to maintain the original behavior of the code, which was to always eliminate unrefined element patches. More...
 
bool make_flags_parallel_consistent ()
 Copy refinement flags on ghost elements from their local processors. More...
 
bool & enforce_mismatch_limit_prior_to_refinement ()
 Get/set the _enforce_mismatch_limit_prior_to_refinement flag. More...
 
bool enforce_mismatch_limit_prior_to_refinement () const
 
void enforce_mismatch_limit_prior_to_refinement (bool enforce)
 
const Parallel::Communicatorcomm () const
 
processor_id_type n_processors () const
 
processor_id_type processor_id () const
 

Protected Attributes

const Parallel::Communicator_communicator
 

Private Types

enum  NeighborType { POINT, EDGE }
 This helper function enforces the desired mismatch limits prior to refinement. More...
 

Private Member Functions

 MeshRefinement (const MeshRefinement &)
 
MeshRefinementoperator= (const MeshRefinement &)
 
bool _coarsen_elements ()
 Coarsens user-requested elements. More...
 
bool _refine_elements ()
 Refines user-requested elements. More...
 
void _smooth_flags (bool refining, bool coarsening)
 Smooths refinement flags according to current settings. More...
 
bool limit_level_mismatch_at_node (const unsigned int max_mismatch)
 
This algorithm restricts the maximum level mismatch at any node in the mesh. More...
 
bool limit_level_mismatch_at_edge (const unsigned int max_mismatch)
 
bool limit_overrefined_boundary (const signed char max_mismatch)
 
bool limit_underrefined_boundary (const signed char max_mismatch)
 
bool eliminate_unrefined_patches ()
 
This algorithm selects an element for refinement if all of its neighbors are (or will be) refined. More...
 
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. More...
 
void update_nodes_map ()
 Updates the _new_nodes_map. More...
 
bool make_coarsening_compatible ()
 Take user-specified coarsening flags and augment them so that level-one dependency is satisfied. More...
 
bool make_refinement_compatible ()
 Take user-specified refinement flags and augment them so that level-one dependency is satisfied. More...
 
Elemtopological_neighbor (Elem *elem, const PointLocatorBase *point_locator, const unsigned int side) const
 Local dispatch function for getting the correct topological neighbor from the Elem class. More...
 
bool has_topological_neighbor (const Elem *elem, const PointLocatorBase *point_locator, const Elem *neighbor) const
 Local dispatch function for checking the correct has_neighbor function from the Elem class. More...
 
bool enforce_mismatch_limit_prior_to_refinement (Elem *elem, NeighborType nt, unsigned max_mismatch)
 

Private Attributes

TopologyMap _new_nodes_map
 Data structure that holds the new nodes information. More...
 
MeshBase_mesh
 Reference to the mesh. More...
 
bool _use_member_parameters
 For backwards compatibility, we initialize this as false and then set it to true if the user uses any of the refinement parameter accessor functions. More...
 
bool _coarsen_by_parents
 Refinement parameter values. More...
 
Real _refine_fraction
 
Real _coarsen_fraction
 
unsigned int _max_h_level
 
Real _coarsen_threshold
 
dof_id_type _nelem_target
 
Real _absolute_global_tolerance
 
unsigned char _face_level_mismatch_limit
 
unsigned char _edge_level_mismatch_limit
 
unsigned char _node_level_mismatch_limit
 
signed char _overrefined_boundary_limit
 
signed char _underrefined_boundary_limit
 
bool _allow_unrefined_patches
 
bool _enforce_mismatch_limit_prior_to_refinement
 
This option enforces the mismatch level prior to refinement by checking if refining any element marked for refinement would cause a mismatch greater than the limit. More...
 
PeriodicBoundaries_periodic_boundaries
 

Detailed Description

Implements (adaptive) mesh refinement algorithms for a MeshBase.

Note
Before using any of the algorithms in this class on a distributed mesh, the user needs to make sure that the mesh is prepared (MeshBase::prepare_for_use).
Author
Benjamin S. Kirk
Date
2002-2007 Responsible for mesh refinement algorithms and data.

Definition at line 61 of file mesh_refinement.h.

Member Enumeration Documentation

◆ NeighborType

This helper function enforces the desired mismatch limits prior to refinement.

It is called from the MeshRefinement::limit_level_mismatch_at_edge() and MeshRefinement::limit_level_mismatch_at_node() functions.

Returns
true if this enforcement caused the refinement flags for elem to change, false otherwise.
Enumerator
POINT 
EDGE 

Definition at line 867 of file mesh_refinement.h.

Constructor & Destructor Documentation

◆ MeshRefinement() [1/2]

libMesh::MeshRefinement::MeshRefinement ( MeshBase mesh)
explicit

Constructor.

Definition at line 95 of file mesh_refinement.C.

95  :
96  ParallelObject(m),
97  _mesh(m),
99  _coarsen_by_parents(false),
100  _refine_fraction(0.3),
101  _coarsen_fraction(0.0),
103  _coarsen_threshold(10),
104  _nelem_target(0),
113 #ifdef LIBMESH_ENABLE_PERIODIC
114  , _periodic_boundaries(nullptr)
115 #endif
116 {
117 }
118 
119 
120 
121 #ifdef LIBMESH_ENABLE_PERIODIC
122 void MeshRefinement::set_periodic_boundaries_ptr(PeriodicBoundaries * pb_ptr)
123 {
124  _periodic_boundaries = pb_ptr;
125 }
ParallelObject(const Parallel::Communicator &comm_in)
Constructor.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
MeshBase & _mesh
Reference to the mesh.
PeriodicBoundaries * _periodic_boundaries
signed char _underrefined_boundary_limit
unsigned char _face_level_mismatch_limit
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...
signed char _overrefined_boundary_limit
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...
unsigned char _node_level_mismatch_limit
unsigned char _edge_level_mismatch_limit
void set_periodic_boundaries_ptr(PeriodicBoundaries *pb_ptr)
Sets the PeriodicBoundaries pointer.
bool _coarsen_by_parents
Refinement parameter values.

◆ MeshRefinement() [2/2]

libMesh::MeshRefinement::MeshRefinement ( const MeshRefinement )
private

◆ ~MeshRefinement()

libMesh::MeshRefinement::~MeshRefinement ( )
default

Destructor.

Deletes all the elements that are currently stored.

Member Function Documentation

◆ _coarsen_elements()

bool libMesh::MeshRefinement::_coarsen_elements ( )
private

Coarsens user-requested elements.

Both coarsen_elements and refine_elements used to be in the public interface for the MeshRefinement object. Unfortunately, without proper preparation (make_refinement_compatible, make_coarsening_compatible) at least coarsen_elements() did not work alone. By making them private, we signal to the user that they are not part of the interface. It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the mesh actually changed (hence data needs to be projected) and false otherwise.

Definition at line 1371 of file mesh_refinement.C.

References _mesh, clear(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::get_boundary_info(), libMesh::BoundaryInfo::is_children_on_boundary_side(), libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_COARSENED, libMesh::libmesh_assert(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), TIMPI::Communicator::max(), libMesh::BoundaryInfo::remove(), libMesh::MeshCommunication::send_coarse_ghosts(), libMesh::BoundaryInfo::transfer_boundary_ids_from_children(), update_nodes_map(), and libMesh::MeshBase::update_parallel_id_counts().

Referenced by coarsen_elements(), refine_and_coarsen_elements(), and uniformly_coarsen().

1372 {
1373  // This function must be run on all processors at once
1374  parallel_object_only();
1375 
1376  LOG_SCOPE ("_coarsen_elements()", "MeshRefinement");
1377 
1378  // Flags indicating if this call actually changes the mesh
1379  bool mesh_changed = false;
1380  bool mesh_p_changed = false;
1381 
1382  // Clear the unused_elements data structure.
1383  // The elements have been packed since it was built,
1384  // so there are _no_ unused elements. We cannot trust
1385  // any iterators currently in this data structure.
1386  // _unused_elements.clear();
1387 
1388  // Loop over the elements first to determine if the mesh will
1389  // undergo h-coarsening. If it will, then we'll need to communicate
1390  // more ghosted elements. We need to communicate them *before* we
1391  // do the coarsening; otherwise it is possible to coarsen away a
1392  // one-element-thick layer partition and leave the partitions on
1393  // either side unable to figure out how to talk to each other.
1394  for (auto & elem : _mesh.element_ptr_range())
1395  if (elem->refinement_flag() == Elem::COARSEN)
1396  {
1397  mesh_changed = true;
1398  break;
1399  }
1400 
1401  // If the mesh changed on any processor, it changed globally
1402  this->comm().max(mesh_changed);
1403 
1404  // And then we may need to widen the ghosting layers.
1405  if (mesh_changed)
1406  MeshCommunication().send_coarse_ghosts(_mesh);
1407 
1408  for (auto & elem : _mesh.element_ptr_range())
1409  {
1410  // Make sure we transfer the children's boundary id(s)
1411  // up to its parent when necessary before coarsening.
1413 
1414  // active elements flagged for coarsening will
1415  // no longer be deleted until MeshRefinement::contract()
1416  if (elem->refinement_flag() == Elem::COARSEN)
1417  {
1418  // Huh? no level-0 element should be active
1419  // and flagged for coarsening.
1420  libmesh_assert_not_equal_to (elem->level(), 0);
1421 
1422  // Remove this element from any neighbor
1423  // lists that point to it.
1424  elem->nullify_neighbors();
1425 
1426  // Remove any boundary information associated
1427  // with this element if we do not allow children to have boundary info.
1428  // Otherwise, we will do the removal in `transfer_boundary_ids_from_children`
1429  // to make sure we don't delete the information before it is transferred
1431  _mesh.get_boundary_info().remove (elem);
1432 
1433  // Add this iterator to the _unused_elements
1434  // data structure so we might fill it.
1435  // The _unused_elements optimization is currently off.
1436  // _unused_elements.push_back (it);
1437 
1438  // Don't delete the element until
1439  // MeshRefinement::contract()
1440  // _mesh.delete_elem(elem);
1441  }
1442 
1443  // inactive elements flagged for coarsening
1444  // will become active
1445  else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1446  {
1447  elem->coarsen();
1448  libmesh_assert (elem->active());
1449 
1450  // the mesh has certainly changed
1451  mesh_changed = true;
1452  }
1453  if (elem->p_refinement_flag() == Elem::COARSEN)
1454  {
1455  if (elem->p_level() > 0)
1456  {
1457  elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1458  elem->set_p_level(elem->p_level() - 1);
1459  mesh_p_changed = true;
1460  }
1461  else
1462  {
1463  elem->set_p_refinement_flag(Elem::DO_NOTHING);
1464  }
1465  }
1466  }
1467 
1468  this->comm().max(mesh_p_changed);
1469 
1470  // And we may need to update DistributedMesh values reflecting the changes
1471  if (mesh_changed)
1473 
1474  // Node processor ids may need to change if an element of that id
1475  // was coarsened away
1476  if (mesh_changed && !_mesh.is_serial())
1477  {
1478  // Update the _new_nodes_map so that processors can
1479  // find requested nodes
1480  this->update_nodes_map ();
1481 
1482  MeshCommunication().make_nodes_parallel_consistent (_mesh);
1483 
1484  // Clear the _new_nodes_map
1485  this->clear();
1486 
1487 #ifdef DEBUG
1488  MeshTools::libmesh_assert_valid_procids<Node>(_mesh);
1489 #endif
1490  }
1491 
1492  // If p levels changed all we need to do is make sure that parent p
1493  // levels changed in sync
1494  if (mesh_p_changed && !_mesh.is_serial())
1495  {
1496  MeshCommunication().make_p_levels_parallel_consistent (_mesh);
1497  }
1498 
1499  return (mesh_changed || mesh_p_changed);
1500 }
void update_nodes_map()
Updates the _new_nodes_map.
MeshBase & _mesh
Reference to the mesh.
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:170
virtual bool is_serial() const
Definition: mesh_base.h:347
virtual void update_parallel_id_counts()=0
Updates parallel caches so that methods like n_elem() accurately reflect changes on other processors...
libmesh_assert(ctx)
void max(const T &r, T &o, Request &req) const
void clear()
Deletes all the data that are currently stored.
bool is_children_on_boundary_side() const
void transfer_boundary_ids_from_children(const Elem *const parent)
Update parent&#39;s boundary id list so that this information is consistent with its children.

◆ _refine_elements()

bool libMesh::MeshRefinement::_refine_elements ( )
private

Refines user-requested elements.

It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the mesh actually changed (hence data needs to be projected) and false otherwise.

Definition at line 1504 of file mesh_refinement.C.

References _mesh, libMesh::as_range(), clear(), libMesh::ParallelObject::comm(), libMesh::MeshBase::is_prepared(), libMesh::MeshBase::is_replicated(), libMesh::Elem::JUST_REFINED, libMesh::libmesh_assert(), libMesh::MeshBase::libmesh_assert_valid_parallel_ids(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), TIMPI::Communicator::max(), libMesh::Elem::REFINE, libMesh::Partitioner::set_node_processor_ids(), update_nodes_map(), and libMesh::MeshBase::update_parallel_id_counts().

Referenced by refine_and_coarsen_elements(), refine_elements(), and uniformly_refine().

1505 {
1507 
1508  // This function must be run on all processors at once
1509  parallel_object_only();
1510 
1511  // Update the _new_nodes_map so that elements can
1512  // find nodes to connect to.
1513  this->update_nodes_map ();
1514 
1515  LOG_SCOPE ("_refine_elements()", "MeshRefinement");
1516 
1517  // Iterate over the elements, counting the elements
1518  // flagged for h refinement.
1519  dof_id_type n_elems_flagged = 0;
1520 
1521  for (auto & elem : _mesh.element_ptr_range())
1522  if (elem->refinement_flag() == Elem::REFINE)
1523  n_elems_flagged++;
1524 
1525  // Construct a local vector of Elem * which have been
1526  // previously marked for refinement. We reserve enough
1527  // space to allow for every element to be refined.
1528  std::vector<Elem *> local_copy_of_elements;
1529  local_copy_of_elements.reserve(n_elems_flagged);
1530 
1531  // If mesh p levels changed, we might need to synchronize parent p
1532  // levels on a distributed mesh.
1533  bool mesh_p_changed = false;
1534 
1535  // Iterate over the elements, looking for elements flagged for
1536  // refinement.
1537 
1538  // If we are on a ReplicatedMesh, then we just do the refinement in
1539  // the same order on every processor and everything stays in sync.
1540 
1541  // If we are on a DistributedMesh, that's impossible.
1542  //
1543  // If the mesh is distributed, we need to make sure that if we end
1544  // up as the owner of a new node, which might happen if that node is
1545  // attached to one of our own elements, then we have given it a
1546  // legitimate node id and our own processor id. We generate
1547  // legitimate node ids and use our own processor id when we are
1548  // refining our own elements but not when we refine others'
1549  // elements. Therefore we want to refine our own elements *first*,
1550  // thereby generating all nodes which might belong to us, and then
1551  // refine others' elements *after*, thereby generating nodes with
1552  // temporary ids which we know we will discard.
1553  //
1554  // Even if the DistributedMesh is serialized, we can't just treat it
1555  // like a ReplicatedMesh, because DistributedMesh doesn't *trust*
1556  // users to refine partitioned elements in a serialized way, so it
1557  // assigns temporary ids, so we need to synchronize ids afterward to
1558  // be safe anyway, so we might as well use the distributed mesh code
1559  // path.
1560  for (auto & elem : _mesh.is_replicated() ? _mesh.active_element_ptr_range() : _mesh.active_local_element_ptr_range())
1561  {
1562  if (elem->refinement_flag() == Elem::REFINE)
1563  local_copy_of_elements.push_back(elem);
1564  if (elem->p_refinement_flag() == Elem::REFINE &&
1565  elem->active())
1566  {
1567  elem->set_p_level(elem->p_level()+1);
1568  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1569  mesh_p_changed = true;
1570  }
1571  }
1572 
1573  if (!_mesh.is_replicated())
1574  {
1575  for (auto & elem : as_range(_mesh.active_not_local_elements_begin(),
1576  _mesh.active_not_local_elements_end()))
1577  {
1578  if (elem->refinement_flag() == Elem::REFINE)
1579  local_copy_of_elements.push_back(elem);
1580  if (elem->p_refinement_flag() == Elem::REFINE &&
1581  elem->active())
1582  {
1583  elem->set_p_level(elem->p_level()+1);
1584  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1585  mesh_p_changed = true;
1586  }
1587  }
1588  }
1589 
1590  // Now iterate over the local copies and refine each one.
1591  // This may resize the mesh's internal container and invalidate
1592  // any existing iterators.
1593  for (auto & elem : local_copy_of_elements)
1594  elem->refine(*this);
1595 
1596  // The mesh changed if there were elements h refined
1597  bool mesh_changed = !local_copy_of_elements.empty();
1598 
1599  // If the mesh changed on any processor, it changed globally
1600  this->comm().max(mesh_changed);
1601  this->comm().max(mesh_p_changed);
1602 
1603  // And we may need to update DistributedMesh values reflecting the changes
1604  if (mesh_changed)
1606 
1607  if (mesh_changed && !_mesh.is_replicated())
1608  {
1609  MeshCommunication().make_elems_parallel_consistent (_mesh);
1610  MeshCommunication().make_new_nodes_parallel_consistent (_mesh);
1611 #ifdef DEBUG
1613 #endif
1614  }
1615 
1616  // If we're refining a ReplicatedMesh, then we haven't yet assigned
1617  // node processor ids. But if we're refining a partitioned
1618  // ReplicatedMesh, then we *need* to assign node processor ids.
1619  if (mesh_changed && _mesh.is_replicated() &&
1620  (_mesh.unpartitioned_elements_begin() ==
1621  _mesh.unpartitioned_elements_end()))
1623 
1624  if (mesh_p_changed && !_mesh.is_replicated())
1625  {
1626  MeshCommunication().make_p_levels_parallel_consistent (_mesh);
1627  }
1628 
1629  // Clear the _new_nodes_map and _unused_elements data structures.
1630  this->clear();
1631 
1632  return (mesh_changed || mesh_p_changed);
1633 }
bool is_prepared() const
Definition: mesh_base.C:1057
void update_nodes_map()
Updates the _new_nodes_map.
MeshBase & _mesh
Reference to the mesh.
static void set_node_processor_ids(MeshBase &mesh)
This function is called after partitioning to set the processor IDs for the nodes.
Definition: partitioner.C:852
const Parallel::Communicator & comm() const
virtual void update_parallel_id_counts()=0
Updates parallel caches so that methods like n_elem() accurately reflect changes on other processors...
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libmesh_assert(ctx)
void max(const T &r, T &o, Request &req) const
virtual bool is_replicated() const
Definition: mesh_base.h:369
void clear()
Deletes all the data that are currently stored.
virtual void libmesh_assert_valid_parallel_ids() const
Verify id and processor_id consistency of our elements and nodes containers.
Definition: mesh_base.h:1688
uint8_t dof_id_type
Definition: id_types.h:67

◆ _smooth_flags()

void libMesh::MeshRefinement::_smooth_flags ( bool  refining,
bool  coarsening 
)
private

Smooths refinement flags according to current settings.

It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the flags actually changed (hence data needs to be projected) and false otherwise.

Definition at line 1636 of file mesh_refinement.C.

References _edge_level_mismatch_limit, _mesh, _node_level_mismatch_limit, _overrefined_boundary_limit, _underrefined_boundary_limit, libMesh::ParallelObject::comm(), eliminate_unrefined_patches(), libMesh::MeshBase::is_serial(), libMesh::libmesh_assert(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), limit_overrefined_boundary(), limit_underrefined_boundary(), make_coarsening_compatible(), make_flags_parallel_consistent(), and make_refinement_compatible().

Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().

1637 {
1638  // Smoothing can break in weird ways on a mesh with broken topology
1639 #ifdef DEBUG
1641 #endif
1642 
1643  // Repeat until flag changes match on every processor
1644  do
1645  {
1646  // Repeat until coarsening & refinement flags jive
1647  bool satisfied = false;
1648  do
1649  {
1650  // If we're refining or coarsening, hit the corresponding
1651  // face level test code. Short-circuiting || is our friend
1652  const bool coarsening_satisfied =
1653  !coarsening ||
1655 
1656  const bool refinement_satisfied =
1657  !refining ||
1659 
1660  bool smoothing_satisfied =
1661  !this->eliminate_unrefined_patches();// &&
1662 
1664  smoothing_satisfied = smoothing_satisfied &&
1666 
1668  smoothing_satisfied = smoothing_satisfied &&
1670 
1672  smoothing_satisfied = smoothing_satisfied &&
1674 
1676  smoothing_satisfied = smoothing_satisfied &&
1678 
1679  satisfied = (coarsening_satisfied &&
1680  refinement_satisfied &&
1681  smoothing_satisfied);
1682 
1683  libmesh_assert(this->comm().verify(satisfied));
1684  }
1685  while (!satisfied);
1686  }
1687  while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
1688 }
bool limit_level_mismatch_at_edge(const unsigned int max_mismatch)
bool limit_level_mismatch_at_node(const unsigned int max_mismatch)
This algorithm restricts the maximum level mismatch at any node in the mesh.
bool limit_underrefined_boundary(const signed char max_mismatch)
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
bool limit_overrefined_boundary(const signed char max_mismatch)
signed char _underrefined_boundary_limit
bool make_refinement_compatible()
Take user-specified refinement flags and augment them so that level-one dependency is satisfied...
virtual bool is_serial() const
Definition: mesh_base.h:347
libmesh_assert(ctx)
bool make_flags_parallel_consistent()
Copy refinement flags on ghost elements from their local processors.
signed char _overrefined_boundary_limit
bool make_coarsening_compatible()
Take user-specified coarsening flags and augment them so that level-one dependency is satisfied...
unsigned char _node_level_mismatch_limit
unsigned char _edge_level_mismatch_limit
void libmesh_assert_valid_neighbors(const MeshBase &mesh, bool assert_valid_remote_elems=true)
A function for verifying that neighbor connectivity is correct (each element is a neighbor of or desc...
Definition: mesh_tools.C:2320
bool eliminate_unrefined_patches()
This algorithm selects an element for refinement if all of its neighbors are (or will be) refined...

◆ absolute_global_tolerance()

Real & libMesh::MeshRefinement::absolute_global_tolerance ( )
inline

If absolute_global_tolerance is set to a nonzero value, methods like flag_elements_by_global_tolerance() will attempt to reduce the global error of the mesh (defined as the square root of the sum of the squares of the errors on active elements) to below this tolerance.

absolute_global_tolerance is 0 by default.

Definition at line 918 of file mesh_refinement.h.

References _absolute_global_tolerance, and _use_member_parameters.

Referenced by main().

919 {
920  _use_member_parameters = true;
922 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ add_elem() [1/2]

Elem * libMesh::MeshRefinement::add_elem ( Elem elem)

Adds the element elem to the mesh.

Definition at line 208 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::add_elem(), and libMesh::libmesh_assert().

Referenced by libMesh::Elem::refine().

209 {
210  libmesh_assert(elem);
211  return _mesh.add_elem (elem);
212 }
MeshBase & _mesh
Reference to the mesh.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
libmesh_assert(ctx)

◆ add_elem() [2/2]

Elem * libMesh::MeshRefinement::add_elem ( std::unique_ptr< Elem elem)

Same as the function above, but makes it clear that the MeshRefinement object (actually, its Mesh) takes ownership of the Elem which is passed in, so the user is not responsible for deleting it.

The version of add_elem() taking a dumb pointer will eventually be deprecated in favor of this version.

Definition at line 214 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::add_elem(), and libMesh::libmesh_assert().

215 {
216  libmesh_assert(elem);
217  return _mesh.add_elem(std::move(elem));
218 }
MeshBase & _mesh
Reference to the mesh.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
libmesh_assert(ctx)

◆ add_node()

Node * libMesh::MeshRefinement::add_node ( Elem parent,
unsigned int  child,
unsigned int  node,
processor_id_type  proc_id 
)

Add a node to the mesh.

The node should be node n of child c of parent Elem parent. The processor id proc_id is used if necessary to help determine numbering of newly created nodes, but newly created nodes are left unpartitioned until a node partitionining sweep is done later.

Returns
A pointer to a suitable existing or newly-created node.

Definition at line 141 of file mesh_refinement.C.

References _mesh, _new_nodes_map, libMesh::TopologyMap::add_node(), libMesh::MeshBase::add_point(), libMesh::TypeVector< T >::add_scaled(), libMesh::Elem::as_parent_node(), libMesh::Elem::bracketing_nodes(), libMesh::Elem::embedding_matrix(), libMesh::TopologyMap::find(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::invalid_uint, libMesh::libmesh_assert(), libMesh::Elem::node_index_range(), libMesh::Elem::node_ptr(), libMesh::MeshBase::node_ptr(), libMesh::Elem::point(), libMesh::DofObject::processor_id(), and libMesh::Real.

Referenced by libMesh::Elem::refine().

145 {
146  LOG_SCOPE("add_node()", "MeshRefinement");
147 
148  unsigned int parent_n = parent.as_parent_node(child, node);
149 
150  if (parent_n != libMesh::invalid_uint)
151  return parent.node_ptr(parent_n);
152 
153  const std::vector<std::pair<dof_id_type, dof_id_type>>
154  bracketing_nodes = parent.bracketing_nodes(child, node);
155 
156  // If we're not a parent node, we *must* be bracketed by at least
157  // one pair of parent nodes
158  libmesh_assert(bracketing_nodes.size());
159 
160  // Return the node if it already exists.
161  //
162  // We'll leave the processor_id untouched in this case - if we're
163  // repartitioning later or if this is a new unpartitioned node,
164  // we'll update it then, and if not then we don't want to update it.
165  if (const auto new_node_id = _new_nodes_map.find(bracketing_nodes);
166  new_node_id != DofObject::invalid_id)
167  return _mesh.node_ptr(new_node_id);
168 
169  // Otherwise we need to add a new node.
170  //
171  // Figure out where to add the point:
172 
173  Point p; // defaults to 0,0,0
174 
175  for (auto n : parent.node_index_range())
176  {
177  // The value from the embedding matrix
178  const Real em_val = parent.embedding_matrix(child,node,n);
179 
180  if (em_val != 0.)
181  {
182  p.add_scaled (parent.point(n), em_val);
183 
184  // If we'd already found the node we shouldn't be here
185  libmesh_assert_not_equal_to (em_val, 1);
186  }
187  }
188 
189  // Although we're leaving new nodes unpartitioned at first, with a
190  // DistributedMesh we would need a default id based on the numbering
191  // scheme for the requested processor_id.
192  Node * new_node = _mesh.add_point (p, DofObject::invalid_id, proc_id);
193 
194  libmesh_assert(new_node);
195 
196  // But then we'll make sure this node is marked as unpartitioned.
197  new_node->processor_id() = DofObject::invalid_processor_id;
198 
199  // Add the node to the map.
200  _new_nodes_map.add_node(*new_node, bracketing_nodes);
201 
202  // Return the address of the new node
203  return new_node;
204 }
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition: dof_object.h:484
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
TopologyMap _new_nodes_map
Data structure that holds the new nodes information.
MeshBase & _mesh
Reference to the mesh.
dof_id_type find(dof_id_type bracket_node1, dof_id_type bracket_node2) const
Definition: topology_map.C:115
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.
Definition: topology_map.C:53
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.
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:473
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Node * node_ptr(const dof_id_type i) const =0

◆ add_p_to_h_refinement()

void libMesh::MeshRefinement::add_p_to_h_refinement ( )

Takes a mesh whose elements are flagged for h refinement and coarsening, and adds flags to request p refinement and coarsening of the same elements.

Definition at line 673 of file mesh_refinement_flagging.C.

References _mesh.

Referenced by main().

674 {
675  for (auto & elem : _mesh.element_ptr_range())
676  elem->set_p_refinement_flag(elem->refinement_flag());
677 }
MeshBase & _mesh
Reference to the mesh.

◆ allow_unrefined_patches()

bool & libMesh::MeshRefinement::allow_unrefined_patches ( )
inline

This flag defaults to false in order to maintain the original behavior of the code, which was to always eliminate unrefined element patches.

If you set this flag to true, then the MeshRefinement::eliminate_unrefined_patches() function essentially does nothing, allowing such patches to persist. This may be particularly useful in e.g. 1D meshes where having unrefined patches does not introduce additional hanging nodes.

Definition at line 949 of file mesh_refinement.h.

References _allow_unrefined_patches.

950 {
952 }

◆ clean_refinement_flags()

void libMesh::MeshRefinement::clean_refinement_flags ( )

Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.

Definition at line 681 of file mesh_refinement_flagging.C.

References _mesh, libMesh::Elem::DO_NOTHING, and libMesh::Elem::INACTIVE.

Referenced by flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_nelem_target(), libMesh::EquationSystems::read(), uniformly_coarsen(), and uniformly_refine().

682 {
683  // Possibly clean up the refinement flags from
684  // a previous step
685  for (auto & elem : _mesh.element_ptr_range())
686  {
687  if (elem->active())
688  {
689  elem->set_refinement_flag(Elem::DO_NOTHING);
690  elem->set_p_refinement_flag(Elem::DO_NOTHING);
691  }
692  else
693  {
694  elem->set_refinement_flag(Elem::INACTIVE);
695  elem->set_p_refinement_flag(Elem::INACTIVE);
696  }
697  }
698 }
MeshBase & _mesh
Reference to the mesh.

◆ clear()

void libMesh::MeshRefinement::clear ( )

Deletes all the data that are currently stored.

Definition at line 134 of file mesh_refinement.C.

References _new_nodes_map, and libMesh::TopologyMap::clear().

Referenced by _coarsen_elements(), and _refine_elements().

135 {
137 }
TopologyMap _new_nodes_map
Data structure that holds the new nodes information.

◆ coarsen_by_parents()

bool & libMesh::MeshRefinement::coarsen_by_parents ( )
inline

If coarsen_by_parents is true, complete groups of sibling elements (elements with the same parent) will be flagged for coarsening.

This should make the coarsening more likely to occur as requested.

coarsen_by_parents is true by default.

Definition at line 882 of file mesh_refinement.h.

References _coarsen_by_parents, and _use_member_parameters.

Referenced by main().

883 {
884  _use_member_parameters = true;
885  return _coarsen_by_parents;
886 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...
bool _coarsen_by_parents
Refinement parameter values.

◆ coarsen_elements()

bool libMesh::MeshRefinement::coarsen_elements ( )

Only coarsens the user-requested elements.

Some elements will not be coarsened to satisfy the level one rule. It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the mesh actually changed (hence data needs to be projected) and false otherwise.
Note
This function used to take an argument, maintain_level_one, new code should use face_level_mismatch_limit() instead.
When we allow boundaries to be directly associated with child elements, i.e., _children_on_boundary = true. A child's boundary ID may be lost during coarsening if it differs from its siblings on that parent side.

Definition at line 620 of file mesh_refinement.C.

References _coarsen_elements(), _face_level_mismatch_limit, _mesh, _smooth_flags(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_stored_range(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, libMesh::libmesh_assert(), make_coarsening_compatible(), make_flags_parallel_consistent(), libMesh::Threads::parallel_for(), libMesh::MeshBase::prepare_for_use(), and test_level_one().

Referenced by libMesh::EquationSystems::reinit_solutions(), and BoundaryInfoTest::testBoundaryOnChildrenElementsRefineCoarsen().

621 {
622  // This function must be run on all processors at once
623  parallel_object_only();
624 
625  // We can't yet turn a non-level-one mesh into a level-one mesh
628 
629  // Possibly clean up the refinement flags from
630  // a previous step
633  [](const ElemRange & range)
634  {
635  for (Elem * elem : range)
636  {
637  // Set refinement flag to INACTIVE if the
638  // element isn't active
639  if (!elem->active())
640  {
641  elem->set_refinement_flag(Elem::INACTIVE);
642  elem->set_p_refinement_flag(Elem::INACTIVE);
643  }
644 
645  // This might be left over from the last step
646  if (elem->refinement_flag() == Elem::JUST_REFINED)
647  elem->set_refinement_flag(Elem::DO_NOTHING);
648  }
649  });
650 
651  // Parallel consistency has to come first, or coarsening
652  // along processor boundaries might occasionally be falsely
653  // prevented
654  bool flags_were_consistent = this->make_flags_parallel_consistent();
655 
656  // In theory, we should be able to remove the above call, which can
657  // be expensive and should be unnecessary. In practice, doing
658  // consistent flagging in parallel is hard, it's impossible to
659  // verify at the library level if it's being done by user code, and
660  // we don't want to abort large parallel runs in opt mode... but we
661  // do want to warn that they should be fixed.
662  libmesh_assert(flags_were_consistent);
663 
664  if (!flags_were_consistent)
665  libmesh_warning("Warning: Refinement flags were not consistent between processors! "
666  "Correcting and continuing.\n");
667 
668  // Smooth coarsening flags
669  _smooth_flags(false, true);
670 
671  // Coarsen the flagged elements.
672  const bool mesh_changed =
673  this->_coarsen_elements ();
674 
678  // FIXME: This won't pass unless we add a redundant find_neighbors()
679  // call or replace find_neighbors() with on-the-fly neighbor updating
680  // libmesh_assert(!this->eliminate_unrefined_patches());
681 
682  // We can't contract the mesh ourselves anymore - a System might
683  // need to restrict old coefficient vectors first
684  // _mesh.contract();
685 
686  // Finally, the new mesh may need to be prepared for use
687  if (mesh_changed)
689 
690  return mesh_changed;
691 }
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.
Definition: threads_none.h:73
StoredRange< MeshBase::element_iterator, Elem * > ElemRange
Definition: elem_range.h:31
bool test_level_one(bool libmesh_assert_yes=false) const
MeshBase & _mesh
Reference to the mesh.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
unsigned char _face_level_mismatch_limit
const ElemRange & element_stored_range()
Definition: mesh_base.C:1913
libmesh_assert(ctx)
bool make_flags_parallel_consistent()
Copy refinement flags on ghost elements from their local processors.
bool make_coarsening_compatible()
Take user-specified coarsening flags and augment them so that level-one dependency is satisfied...
void _smooth_flags(bool refining, bool coarsening)
Smooths refinement flags according to current settings.
bool _coarsen_elements()
Coarsens user-requested elements.

◆ coarsen_fraction()

Real & libMesh::MeshRefinement::coarsen_fraction ( )
inline

The coarsen_fraction sets either a desired target or a desired maximum number of elements to flag for coarsening, depending on which flag_elements_by method is called.

coarsen_fraction must be in \( [0,1] \), and is 0 by default.

Definition at line 894 of file mesh_refinement.h.

References _coarsen_fraction, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

895 {
896  _use_member_parameters = true;
897  return _coarsen_fraction;
898 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ coarsen_threshold()

Real & libMesh::MeshRefinement::coarsen_threshold ( )
inline

The coarsen_threshold provides hysteresis in AMR/C strategies.

Refinement of elements with error estimate E will be done even at the expense of coarsening elements whose children's accumulated error does not exceed coarsen_threshold * E.

coarsen_threshold must be in \( [0,1] \), and is 0.1 by default.

Definition at line 906 of file mesh_refinement.h.

References _coarsen_threshold, and _use_member_parameters.

Referenced by main().

907 {
908  _use_member_parameters = true;
909  return _coarsen_threshold;
910 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ comm()

const Parallel::Communicator& libMesh::ParallelObject::comm ( ) const
inlineinherited
Returns
A reference to the Parallel::Communicator object used by this mesh.

Definition at line 97 of file parallel_object.h.

References libMesh::ParallelObject::_communicator.

Referenced by libMesh::__libmesh_petsc_diff_solver_jacobian(), libMesh::__libmesh_petsc_diff_solver_monitor(), libMesh::__libmesh_petsc_diff_solver_residual(), libMesh::__libmesh_tao_equality_constraints(), libMesh::__libmesh_tao_equality_constraints_jacobian(), libMesh::__libmesh_tao_gradient(), libMesh::__libmesh_tao_hessian(), libMesh::__libmesh_tao_inequality_constraints(), libMesh::__libmesh_tao_inequality_constraints_jacobian(), libMesh::__libmesh_tao_objective(), _coarsen_elements(), libMesh::ExactSolution::_compute_error(), libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscLinearSolver< Number >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< libMesh::Number >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< Number >::_petsc_shell_matrix_mult(), libMesh::SlepcEigenSolver< libMesh::Number >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< Number >::_petsc_shell_matrix_mult_add(), _refine_elements(), _smooth_flags(), libMesh::DofMap::add_constraints_to_send_list(), add_cube_convex_hull_to_mesh(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::TransientRBConstruction::add_IC_to_RB_space(), libMesh::RBEIMEvaluation::add_interpolation_data(), libMesh::CondensedEigenSystem::add_matrices(), libMesh::EigenSystem::add_matrices(), libMesh::System::add_matrix(), libMesh::RBConstruction::add_scaled_matrix_and_vector(), libMesh::DofMap::add_variable(), libMesh::DofMap::add_variables(), libMesh::System::add_vector(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::TransientRBConstruction::allocate_data_structures(), libMesh::RBConstruction::allocate_data_structures(), libMesh::TransientRBConstruction::assemble_affine_expansion(), libMesh::AdvectionSystem::assemble_claw_rhs(), libMesh::FEMSystem::assemble_qoi(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::MeshCommunication::assign_global_indices(), libMesh::Partitioner::assign_partitioning(), libMesh::MeshTools::Generation::build_extrusion(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::PetscDMWrapper::build_section(), libMesh::PetscDMWrapper::build_sf(), libMesh::MeshBase::cache_elem_data(), libMesh::System::calculate_norm(), libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::MeshTetInterface::check_hull_integrity(), libMesh::MeshBase::complete_preparation(), libMesh::RBConstruction::compute_Fq_representor_innerprods(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::RBConstruction::compute_output_dual_innerprods(), libMesh::RBConstruction::compute_residual_dual_norm_slow(), libMesh::RBSCMConstruction::compute_SCM_bounds_on_training_set(), libMesh::DofMap::computed_sparsity_already(), libMesh::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), libMesh::ContinuationSystem::ContinuationSystem(), libMesh::MeshBase::copy_constraint_rows(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::CondensedEigenSystem::copy_super_to_sub(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshTools::create_bounding_box(), libMesh::DofMap::create_dof_constraints(), libMesh::MeshTools::create_nodal_bounding_box(), create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::PetscMatrix< T >::create_submatrix_nosort(), create_wrapped_function(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::RBEIMEvaluation::distribute_bfs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), libMesh::DTKSolutionTransfer::DTKSolutionTransfer(), eliminate_unrefined_patches(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_interiors(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_nodes(), libMesh::RBEIMConstruction::enrich_eim_approximation_on_sides(), libMesh::TransientRBConstruction::enrich_RB_space(), libMesh::EpetraVector< T >::EpetraVector(), AssembleOptimization::equality_constraints(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::SmoothnessEstimator::estimate_smoothness(), flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_error_tolerance(), flag_elements_by_mean_stddev(), flag_elements_by_nelem_target(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::DofMap::gather_constraints(), libMesh::MeshfreeInterpolation::gather_remote_data(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::RBEIMEvaluation::get_eim_basis_function_node_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_side_value(), libMesh::RBEIMEvaluation::get_eim_basis_function_value(), libMesh::System::get_info(), libMesh::MeshBase::get_info(), libMesh::DofMap::get_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::RBEIMConstruction::get_max_abs_value(), libMesh::RBEIMConstruction::get_node_max_abs_value(), libMesh::RBEIMEvaluation::get_parametrized_function_node_value(), libMesh::RBEIMEvaluation::get_parametrized_function_side_value(), libMesh::RBEIMEvaluation::get_parametrized_function_value(), libMesh::RBEIMConstruction::get_random_point(), libMesh::MeshTetInterface::improve_hull_integrity(), AssembleOptimization::inequality_constraints(), AssembleOptimization::inequality_constraints_jacobian(), libMesh::LocationMap< T >::init(), libMesh::TimeSolver::init(), libMesh::StaticCondensation::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::AdvectionSystem::init_data(), libMesh::ClawSystem::init_data(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), libMesh::RBEIMConstruction::initialize_parametrized_functions_in_training_set(), libMesh::RBEIMConstruction::inner_product(), integrate_function(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_equal_connectivity(), libMesh::MeshTools::libmesh_assert_equal_points(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_constraint_rows(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::MeshTools::libmesh_assert_valid_unique_ids(), libMesh::libmesh_petsc_linesearch_shellfunc(), libMesh::libmesh_petsc_preconditioner_apply(), libMesh::libmesh_petsc_recalculate_monitor(), libMesh::libmesh_petsc_snes_fd_residual(), libMesh::libmesh_petsc_snes_jacobian(), libMesh::libmesh_petsc_snes_mffd_interface(), libMesh::libmesh_petsc_snes_mffd_residual(), libMesh::libmesh_petsc_snes_postcheck(), libMesh::libmesh_petsc_snes_precheck(), libMesh::libmesh_petsc_snes_residual(), libMesh::libmesh_petsc_snes_residual_helper(), limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), limit_overrefined_boundary(), limit_underrefined_boundary(), libMesh::LinearImplicitSystem::LinearImplicitSystem(), main(), make_coarsening_compatible(), libMesh::MeshCommunication::make_elems_parallel_consistent(), make_flags_parallel_consistent(), libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), libMesh::MeshCommunication::make_node_bcids_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), make_refinement_compatible(), libMesh::TransientRBConstruction::mass_matrix_scaled_matvec(), libMesh::FEMSystem::mesh_position_set(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), LinearElasticityWithContact::move_mesh(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::DofMap::n_constrained_dofs(), libMesh::MeshBase::n_constraint_rows(), libMesh::DofMap::n_dofs(), libMesh::DofMap::n_dofs_per_processor(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), MixedOrderTest::n_neighbor_links(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::SparsityPattern::Build::n_nonzeros(), libMesh::MeshTools::n_p_levels(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_distribute_bfs(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::RBEIMConstruction::node_inner_product(), libMesh::PetscVector< libMesh::Number >::operator=(), libMesh::MeshBase::operator==(), libMesh::DistributedMesh::parallel_max_elem_id(), libMesh::DistributedMesh::parallel_max_node_id(), libMesh::ReplicatedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_max_unique_id(), libMesh::DistributedMesh::parallel_n_elem(), libMesh::DistributedMesh::parallel_n_nodes(), libMesh::SparsityPattern::Build::parallel_sync(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::MeshTools::paranoid_n_levels(), libMesh::Partitioner::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::petsc_auto_fieldsplit(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Partitioner::processor_pairs_to_interface_nodes(), libMesh::InterMeshProjection::project_system_vectors(), FEMParameters::read(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::EquationSystems::read(), libMesh::ExodusII_IO::read_header(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::RBEIMEvaluation::read_in_interior_basis_functions(), libMesh::RBEIMEvaluation::read_in_node_basis_functions(), libMesh::RBEIMEvaluation::read_in_side_basis_functions(), libMesh::RBEvaluation::read_in_vectors_from_multiple_files(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), MeshFunctionTest::read_variable_info_from_output_data(), libMesh::MeshBase::recalculate_n_partitions(), refine_and_coarsen_elements(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::BoundaryInfo::remove_edge_id(), libMesh::BoundaryInfo::remove_node_id(), libMesh::BoundaryInfo::remove_shellface_id(), libMesh::BoundaryInfo::remove_side_id(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), LinearElasticityWithContact::residual_and_jacobian(), OverlappingAlgebraicGhostingTest::run_ghosting_test(), OverlappingCouplingGhostingTest::run_sparsity_pattern_test(), scale_mesh_and_plot(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::send_and_insert_dof_values(), libMesh::TransientRBConstruction::set_error_temporal_data(), libMesh::Partitioner::set_interface_node_processor_ids_BFS(), libMesh::Partitioner::set_interface_node_processor_ids_linear(), libMesh::Partitioner::set_interface_node_processor_ids_petscpartitioner(), libMesh::Partitioner::set_node_processor_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::RBEIMEvaluation::side_distribute_bfs(), libMesh::RBEIMEvaluation::side_gather_bfs(), libMesh::RBEIMConstruction::side_inner_product(), libMesh::Partitioner::single_partition(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::VariationalMeshSmoother::smooth(), libMesh::ClawSystem::solve_conservation_law(), libMesh::split_mesh(), libMesh::RBEIMConstruction::store_eim_solutions_for_training_set(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), libMesh::MeshBase::sync_subdomain_name_map(), ConstraintOperatorTest::test1DCoarseningNewNodes(), ConstraintOperatorTest::test1DCoarseningOperator(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), test_level_one(), MeshfunctionDFEM::test_mesh_function_dfem(), MeshfunctionDFEM::test_mesh_function_dfem_grad(), MeshFunctionTest::test_p_level(), test_unflagged(), DofMapTest::testBadElemFECombo(), SystemsTest::testBlockRestrictedVarNDofs(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), VolumeTest::testC0PolygonMethods(), VolumeTest::testC0PolyhedronMethods(), ConstraintOperatorTest::testCoreform(), ConnectedComponentsTest::testEdge(), MeshInputTest::testExodusIGASidesets(), MeshTriangulationTest::testFoundCenters(), PointLocatorTest::testLocator(), BoundaryInfoTest::testMesh(), PointLocatorTest::testPlanar(), MeshTriangulationTest::testPoly2TriRefinementBase(), SystemsTest::testProjectCubeWithMeshFunction(), BoundaryInfoTest::testRenumber(), BoundaryInfoTest::testSelectiveRenumber(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshTriangulationTest::testTriangulatorInterp(), MeshTriangulationTest::testTriangulatorMeshedHoles(), MeshTriangulationTest::testTriangulatorRoundHole(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::RBConstruction::train_reduced_basis_with_POD(), libMesh::MeshFunctionSolutionTransfer::transfer(), libMesh::MeshfreeSolutionTransfer::transfer(), libMesh::Poly2TriTriangulator::triangulate(), libMesh::TransientRBConstruction::truth_assembly(), libMesh::RBConstruction::truth_assembly(), uniformly_coarsen(), update_current_local_solution(), libMesh::TransientRBConstruction::update_RB_initial_condition_all_N(), libMesh::TransientRBConstruction::update_RB_system_matrices(), libMesh::RBConstruction::update_RB_system_matrices(), libMesh::TransientRBConstruction::update_residual_terms(), libMesh::RBConstruction::update_residual_terms(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), libMesh::VTKIO::write_nodal_data(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), libMesh::RBEvaluation::write_out_vectors(), libMesh::TransientRBConstruction::write_riesz_representors_to_files(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::RBDataSerialization::RBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::TransientRBEvaluationSerialization::write_to_file(), libMesh::RBDataSerialization::RBEIMEvaluationSerialization::write_to_file(), and libMesh::RBDataSerialization::RBSCMEvaluationSerialization::write_to_file().

98  { return _communicator; }
const Parallel::Communicator & _communicator

◆ create_parent_error_vector()

void libMesh::MeshRefinement::create_parent_error_vector ( const ErrorVector error_per_cell,
ErrorVector error_per_parent,
Real parent_error_min,
Real parent_error_max 
)
private

Calculates the error on all coarsenable parents.

error_per_parent[parent_id] stores this error if parent_id corresponds to a coarsenable parent, and stores -1 otherwise.

Definition at line 221 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_local_element_stored_range(), libMesh::ParallelObject::comm(), libMesh::DofObject::id(), libMesh::index_range(), libMesh::libmesh_assert(), TIMPI::Communicator::min(), libMesh::Threads::parallel_for(), libMesh::Elem::parent(), and TIMPI::Communicator::sum().

Referenced by flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_error_tolerance(), and flag_elements_by_nelem_target().

225 {
226  // This function must be run on all processors at once
227  parallel_object_only();
228 
229  // Make sure the input error vector is valid
230 #ifdef DEBUG
231  for (const auto & val : error_per_cell)
232  {
233  libmesh_assert_greater_equal (val, 0);
234  // isnan() isn't standard C++ yet
235 #ifdef isnan
236  libmesh_assert(!isnan(val));
237 #endif
238  }
239 
240  // Use a reference to std::vector to avoid confusing
241  // this->comm().verify
242  std::vector<ErrorVectorReal> & epc = error_per_parent;
243  libmesh_assert(this->comm().verify(epc));
244 #endif // #ifdef DEBUG
245 
246  // error values on uncoarsenable elements will be left at -1
247  error_per_parent.clear();
248  error_per_parent.resize(error_per_cell.size(), 0.0);
249 
250  {
251  // Find which elements are uncoarsenable
252  for (auto & elem : _mesh.active_local_element_ptr_range())
253  {
254  Elem * parent = elem->parent();
255 
256  // Active elements are uncoarsenable
257  error_per_parent[elem->id()] = -1.0;
258 
259  // Grandparents and up are uncoarsenable
260  while (parent)
261  {
262  parent = parent->parent();
263  if (parent)
264  {
265  const dof_id_type parentid = parent->id();
266  libmesh_assert_less (parentid, error_per_parent.size());
267  error_per_parent[parentid] = -1.0;
268  }
269  }
270  }
271 
272  // Sync between processors.
273  // Use a reference to std::vector to avoid confusing
274  // this->comm().min
275  std::vector<ErrorVectorReal> & epp = error_per_parent;
276  this->comm().min(epp);
277  }
278 
279  // The parent's error is defined as the square root of the
280  // sum of the children's errors squared, so errors that are
281  // Hilbert norms remain Hilbert norms.
282  //
283  // Because the children may be on different processors, we
284  // calculate local contributions to the parents' errors squared
285  // first, then sum across processors and take the square roots
286  // second.
289  [&error_per_cell, &error_per_parent](const ConstElemRange & range)
290  {
291  for (const Elem * elem : range)
292  {
293  const Elem * parent = elem->parent();
294 
295  // Calculate each contribution to parent cells
296  if (parent)
297  {
298  const dof_id_type parentid = parent->id();
299  libmesh_assert_less (parentid, error_per_parent.size());
300 
301  // If the parent has grandchildren we won't be able to
302  // coarsen it, so forget it. Otherwise, add this child's
303  // contribution to the sum of the squared child errors
304  if (error_per_parent[parentid] != -1.0)
305  error_per_parent[parentid] += (error_per_cell[elem->id()] *
306  error_per_cell[elem->id()]);
307  }
308  }
309  });
310 
311  // Sum the vector across all processors
312  this->comm().sum(static_cast<std::vector<ErrorVectorReal> &>(error_per_parent));
313 
314  // Calculate the min and max as we loop
315  parent_error_min = std::numeric_limits<double>::max();
316  parent_error_max = 0.;
317 
318  for (auto i : index_range(error_per_parent))
319  {
320  // If this element isn't a coarsenable parent with error, we
321  // have nothing to do. Just flag it as -1 and move on
322  // Note that this->comm().sum might have left uncoarsenable
323  // elements with error_per_parent=-n_proc, so reset it to
324  // error_per_parent=-1
325  if (error_per_parent[i] < 0.)
326  {
327  error_per_parent[i] = -1.;
328  continue;
329  }
330 
331  // The error estimator might have already given us an
332  // estimate on the coarsenable parent elements; if so then
333  // we want to retain that estimate
334  if (error_per_cell[i])
335  {
336  error_per_parent[i] = error_per_cell[i];
337  continue;
338  }
339  // if not, then e_parent = sqrt(sum(e_child^2))
340  else
341  error_per_parent[i] = std::sqrt(error_per_parent[i]);
342 
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]);
347  }
348 }
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.
Definition: threads_none.h:73
MeshBase & _mesh
Reference to the mesh.
void sum(T &r) const
const Parallel::Communicator & comm() const
StoredRange< MeshBase::const_element_iterator, const Elem * > ConstElemRange
Definition: elem_range.h:34
void min(const T &r, T &o, Request &req) const
libmesh_assert(ctx)
const ConstElemRange & active_local_element_stored_range() const
Definition: mesh_base.C:1928
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:153
uint8_t dof_id_type
Definition: id_types.h:67

◆ edge_level_mismatch_limit()

unsigned char & libMesh::MeshRefinement::edge_level_mismatch_limit ( )
inline

If edge_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two edge neighbors will not differ by more than that limit.

If edge_level_mismatch_limit is 0, then level differences will be unlimited.

edge_level_mismatch_limit is 0 by default.

Definition at line 929 of file mesh_refinement.h.

References _edge_level_mismatch_limit.

930 {
932 }
unsigned char _edge_level_mismatch_limit

◆ eliminate_unrefined_patches()

bool libMesh::MeshRefinement::eliminate_unrefined_patches ( )
private


This algorithm selects an element for refinement if all of its neighbors are (or will be) refined.

This algorithm will transform this mesh:

* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |       |   |   |
* |   |   |       |   |   |
* o---o---o       o---o---o
* |   |   |       |   |   |
* |   |   |       |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* 

into this:

* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |   :   |   |   |
* |   |   |   :   |   |   |
* o---o---o...o...o---o---o
* |   |   |   :   |   |   |
* |   |   |   :   |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* |   |   |   |   |   |   |
* |   |   |   |   |   |   |
* o---o---o---o---o---o---o
* 

by refining the indicated element. If the _allow_unrefined_patches flag (default false) is set to true, then this function simpy returns false (indicating that no changes were made).

Definition at line 367 of file mesh_refinement_smoothing.C.

References _allow_unrefined_patches, _mesh, libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::Elem::INACTIVE, int, libMesh::libmesh_assert(), TIMPI::Communicator::max(), libMesh::Elem::REFINE, and libMesh::remote_elem.

Referenced by _smooth_flags().

368 {
369  // This function must be run on all processors at once
370  parallel_object_only();
371 
372  bool flags_changed = false;
373 
374  // Quick return: if unrefined patches are allowed, then we are not
375  // going to do anything here and can simply return that the flags
376  // haven't changed.
378  return flags_changed;
379 
380  // Note: we *cannot* use a reference to the real pointer here, since
381  // the pointer may be reseated below and we don't want to reseat
382  // pointers held by the Mesh.
383  for (Elem * elem : _mesh.active_element_ptr_range())
384  {
385  // First, see if there's any possibility we might have to flag
386  // this element for h and p refinement - do we have any visible
387  // neighbors? Next we'll check to see if any of those neighbors
388  // are as coarse or coarser than us.
389  bool h_flag_me = false,
390  p_flag_me = false;
391  for (auto neighbor : elem->neighbor_ptr_range())
392  {
393  // Quit if the element is not a local boundary
394  if (neighbor != nullptr && neighbor != remote_elem)
395  {
396  h_flag_me = true;
397  p_flag_me = true;
398  break;
399  }
400  }
401 
402  // Skip the element if it is already fully flagged for refinement
403  if (elem->p_refinement_flag() == Elem::REFINE)
404  p_flag_me = false;
405  if (elem->refinement_flag() == Elem::REFINE)
406  {
407  h_flag_me = false;
408  if (!p_flag_me)
409  continue;
410  }
411  // Test the parent if that is already flagged for coarsening
412  else if (elem->refinement_flag() == Elem::COARSEN)
413  {
414  libmesh_assert(elem->parent());
415  elem = elem->parent();
416  // FIXME - this doesn't seem right - RHS
417  if (elem->refinement_flag() != Elem::COARSEN_INACTIVE)
418  continue;
419  p_flag_me = false;
420  }
421 
422  const unsigned int my_level = elem->level();
423  int my_p_adjustment = 0;
424  if (elem->p_refinement_flag() == Elem::REFINE)
425  my_p_adjustment = 1;
426  else if (elem->p_refinement_flag() == Elem::COARSEN)
427  {
428  libmesh_assert_greater (elem->p_level(), 0);
429  my_p_adjustment = -1;
430  }
431  const unsigned int my_new_p_level =
432  cast_int<unsigned int>(int(elem->p_level()) +
433  my_p_adjustment);
434 
435  // Check all the element neighbors
436  for (auto neighbor : elem->neighbor_ptr_range())
437  {
438  // Quit if the element is on a local boundary
439  if (neighbor == nullptr || neighbor == remote_elem)
440  {
441  h_flag_me = false;
442  p_flag_me = false;
443  break;
444  }
445  // if the neighbor will be equally or less refined than
446  // we are, then we will not become an unrefined island.
447  // So if we are still considering h refinement:
448  if (h_flag_me &&
449  // If our neighbor is already at a lower level,
450  // it can't end up at a higher level even if it
451  // is flagged for refinement once
452  ((neighbor->level() < my_level) ||
453  // If our neighbor is at the same level but isn't
454  // flagged for refinement, it won't end up at a
455  // higher level
456  ((neighbor->active()) &&
457  (neighbor->refinement_flag() != Elem::REFINE)) ||
458  // If our neighbor is currently more refined but is
459  // a parent flagged for coarsening, it will end up
460  // at the same level.
461  (neighbor->refinement_flag() == Elem::COARSEN_INACTIVE)))
462  {
463  // We've proven we won't become an unrefined island,
464  // so don't h refine to avoid that.
465  h_flag_me = false;
466 
467  // If we've also proven we don't need to p refine,
468  // we don't need to check more neighbors
469  if (!p_flag_me)
470  break;
471  }
472  if (p_flag_me)
473  {
474  // if active neighbors will have a p level
475  // equal to or lower than ours, then we do not need to p
476  // refine ourselves.
477  if (neighbor->active())
478  {
479  int p_adjustment = 0;
480  if (neighbor->p_refinement_flag() == Elem::REFINE)
481  p_adjustment = 1;
482  else if (neighbor->p_refinement_flag() == Elem::COARSEN)
483  {
484  libmesh_assert_greater (neighbor->p_level(), 0);
485  p_adjustment = -1;
486  }
487  if (my_new_p_level >=
488  cast_int<unsigned int>(int(neighbor->p_level())
489  + p_adjustment))
490  {
491  p_flag_me = false;
492  if (!h_flag_me)
493  break;
494  }
495  }
496  // If we have inactive neighbors, we need to
497  // test all their active descendants which neighbor us
498  else if (neighbor->ancestor())
499  {
500  if (neighbor->min_new_p_level_by_neighbor(elem,
501  my_new_p_level + 2) <= my_new_p_level)
502  {
503  p_flag_me = false;
504  if (!h_flag_me)
505  break;
506  }
507  }
508  }
509  }
510 
511  if (h_flag_me)
512  {
513  // Parents that would create islands should no longer
514  // coarsen
515  if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
516  {
517  for (auto & child : elem->child_ref_range())
518  {
519  libmesh_assert_equal_to (child.refinement_flag(),
520  Elem::COARSEN);
521  child.set_refinement_flag(Elem::DO_NOTHING);
522  }
523  elem->set_refinement_flag(Elem::INACTIVE);
524  }
525  else
526  elem->set_refinement_flag(Elem::REFINE);
527  flags_changed = true;
528  }
529  if (p_flag_me)
530  {
531  if (elem->p_refinement_flag() == Elem::COARSEN)
532  elem->set_p_refinement_flag(Elem::DO_NOTHING);
533  else
534  elem->set_p_refinement_flag(Elem::REFINE);
535  flags_changed = true;
536  }
537  }
538 
539  // If flags changed on any processor then they changed globally
540  this->comm().max(flags_changed);
541 
542  return flags_changed;
543 }
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
libmesh_assert(ctx)
void max(const T &r, T &o, Request &req) const
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ enforce_mismatch_limit_prior_to_refinement() [1/4]

bool & libMesh::MeshRefinement::enforce_mismatch_limit_prior_to_refinement ( )
inline

Get/set the _enforce_mismatch_limit_prior_to_refinement flag.

The default value for this flag is false.

Definition at line 954 of file mesh_refinement.h.

References _enforce_mismatch_limit_prior_to_refinement.

Referenced by limit_level_mismatch_at_edge(), and limit_level_mismatch_at_node().

955 {
957 }
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...

◆ enforce_mismatch_limit_prior_to_refinement() [2/4]

bool libMesh::MeshRefinement::enforce_mismatch_limit_prior_to_refinement ( ) const
inline

Definition at line 960 of file mesh_refinement.h.

References _enforce_mismatch_limit_prior_to_refinement.

961 {
963 }
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...

◆ enforce_mismatch_limit_prior_to_refinement() [3/4]

void libMesh::MeshRefinement::enforce_mismatch_limit_prior_to_refinement ( bool  enforce)
inline

Definition at line 966 of file mesh_refinement.h.

References _enforce_mismatch_limit_prior_to_refinement.

967 {
969 }
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...

◆ enforce_mismatch_limit_prior_to_refinement() [4/4]

bool libMesh::MeshRefinement::enforce_mismatch_limit_prior_to_refinement ( Elem elem,
NeighborType  nt,
unsigned  max_mismatch 
)
private

Definition at line 547 of file mesh_refinement_smoothing.C.

References _enforce_mismatch_limit_prior_to_refinement, libMesh::Elem::DO_NOTHING, EDGE, libMesh::Elem::find_edge_neighbors(), libMesh::Elem::find_point_neighbors(), libMesh::Elem::level(), libMesh::Elem::p_level(), POINT, libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), and libMesh::Elem::set_refinement_flag().

550 {
551  // Eventual return value
552  bool flags_changed = false;
553 
554  // If we are enforcing the limit prior to refinement then we
555  // need to remove flags from any elements marked for refinement that
556  // would cause a mismatch
558  && elem->refinement_flag() == Elem::REFINE)
559  {
560  // get all the relevant neighbors since we may have to refine
561  // elements off edges or corners as well
562  std::set<const Elem *> neighbor_set;
563 
564  if (nt == POINT)
565  elem->find_point_neighbors(neighbor_set);
566  else if (nt == EDGE)
567  elem->find_edge_neighbors(neighbor_set);
568  else
569  libmesh_error_msg("Unrecognized NeighborType: " << nt);
570 
571  // Loop over the neighbors of element e
572  for (const auto & neighbor : neighbor_set)
573  {
574  if ((elem->level() + 1 - max_mismatch) > neighbor->level())
575  {
576  elem->set_refinement_flag(Elem::DO_NOTHING);
577  flags_changed = true;
578  }
579  if ((elem->p_level() + 1 - max_mismatch) > neighbor->p_level())
580  {
581  elem->set_p_refinement_flag(Elem::DO_NOTHING);
582  flags_changed = true;
583  }
584  } // loop over edge/point neighbors
585  } // if _enforce_mismatch_limit_prior_to_refinement
586 
587  return flags_changed;
588 }
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...

◆ face_level_mismatch_limit()

unsigned char & libMesh::MeshRefinement::face_level_mismatch_limit ( )
inline

If face_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two face neighbors will not differ by more than that limit.

If face_level_mismatch_limit is 0, then level differences will be unlimited.

face_level_mismatch_limit is 1 by default. Currently the only supported options are 0 and 1.

Definition at line 924 of file mesh_refinement.h.

References _face_level_mismatch_limit.

Referenced by libMesh::EquationSystems::reinit_solutions().

925 {
927 }
unsigned char _face_level_mismatch_limit

◆ flag_elements_by()

void libMesh::MeshRefinement::flag_elements_by ( ElementFlagging element_flagging)

Flag elements based on a function object.

The class ElementFlagging defines a mechanism for implementing refinement strategies.

Definition at line 647 of file mesh_refinement_flagging.C.

References libMesh::MeshRefinement::ElementFlagging::flag_elements().

648 {
649  element_flagging.flag_elements();
650 }

◆ flag_elements_by_elem_fraction()

void libMesh::MeshRefinement::flag_elements_by_elem_fraction ( const ErrorVector error_per_cell,
const Real  refine_fraction = 0.3,
const Real  coarsen_fraction = 0.0,
const unsigned int  max_level = libMesh::invalid_uint 
)

Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.

This method picks the top refine_fraction * n_elem elements for refinement and the bottom coarsen_fraction * n_elem elements for coarsening. The two fractions refine_fraction and coarsen_fraction must be in \( [0,1] \).

All the function arguments except error_per_cell have been deprecated, and will be removed in future libMesh releases - to control these parameters, set the corresponding member variables.

Definition at line 445 of file mesh_refinement_flagging.C.

References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, TIMPI::Communicator::allgather(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), create_parent_error_vector(), dim, libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, libMesh::libmesh_assert(), libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_active_elem(), libMesh::Elem::parent(), libMesh::Real, libMesh::Elem::REFINE, and libMesh::Elem::set_refinement_flag().

Referenced by main().

449 {
450  parallel_object_only();
451 
452  // Verify that our error vector is consistent, using std::vector to
453  // avoid confusing this->comm().verify
454  libmesh_assert(this->comm().verify(dynamic_cast<const std::vector<ErrorVectorReal> &>(error_per_cell)));
455 
456  // The function arguments are currently just there for
457  // backwards_compatibility
459  {
460  // If the user used non-default parameters, lets warn
461  // that they're deprecated
462  if (refine_frac != 0.3 ||
463  coarsen_frac != 0.0 ||
464  max_l != libMesh::invalid_uint)
465  libmesh_deprecated();
466 
467  _refine_fraction = refine_frac;
468  _coarsen_fraction = coarsen_frac;
469  _max_h_level = max_l;
470  }
471 
472  // Check for valid fractions..
473  // The fraction values must be in [0,1]
474  libmesh_assert_greater_equal (_refine_fraction, 0);
475  libmesh_assert_less_equal (_refine_fraction, 1);
476  libmesh_assert_greater_equal (_coarsen_fraction, 0);
477  libmesh_assert_less_equal (_coarsen_fraction, 1);
478 
479  // The number of active elements in the mesh
480  const dof_id_type n_active_elem = _mesh.n_active_elem();
481 
482  // The number of elements to flag for coarsening
483  const dof_id_type n_elem_coarsen =
484  static_cast<dof_id_type>(_coarsen_fraction * n_active_elem);
485 
486  // The number of elements to flag for refinement
487  const dof_id_type n_elem_refine =
488  static_cast<dof_id_type>(_refine_fraction * n_active_elem);
489 
490 
491 
492  // Clean up the refinement flags. These could be left
493  // over from previous refinement steps.
494  this->clean_refinement_flags();
495 
496 
497  // This vector stores the error and element number for all the
498  // active elements. It will be sorted and the top & bottom
499  // elements will then be flagged for coarsening & refinement
500  std::vector<ErrorVectorReal> sorted_error;
501 
502  sorted_error.reserve (n_active_elem);
503 
504  // Loop over the active elements and create the entry
505  // in the sorted_error vector
506  for (auto & elem : _mesh.active_local_element_ptr_range())
507  sorted_error.push_back (error_per_cell[elem->id()]);
508 
509  this->comm().allgather(sorted_error);
510 
511  // Now sort the sorted_error vector
512  std::sort (sorted_error.begin(), sorted_error.end());
513 
514  // If we're coarsening by parents:
515  // Create a sorted error vector with coarsenable parent elements
516  // only, sorted by lowest errors first
517  ErrorVector error_per_parent, sorted_parent_error;
519  {
520  Real parent_error_min, parent_error_max;
521 
522  create_parent_error_vector(error_per_cell,
523  error_per_parent,
524  parent_error_min,
525  parent_error_max);
526 
527  sorted_parent_error = error_per_parent;
528  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
529 
530  // All the other error values will be 0., so get rid of them.
531  sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
532  sorted_parent_error.end(), 0.),
533  sorted_parent_error.end());
534  }
535 
536 
537  ErrorVectorReal top_error= 0., bottom_error = 0.;
538 
539  // Get the maximum error value corresponding to the
540  // bottom n_elem_coarsen elements
541  if (_coarsen_by_parents && n_elem_coarsen)
542  {
543  const unsigned int dim = _mesh.mesh_dimension();
544  unsigned int twotodim = 1;
545  for (unsigned int i=0; i!=dim; ++i)
546  twotodim *= 2;
547 
548  dof_id_type n_parent_coarsen = n_elem_coarsen / (twotodim - 1);
549 
550  if (n_parent_coarsen)
551  bottom_error = sorted_parent_error[n_parent_coarsen - 1];
552  }
553  else if (n_elem_coarsen)
554  {
555  bottom_error = sorted_error[n_elem_coarsen - 1];
556  }
557 
558  if (n_elem_refine)
559  top_error = sorted_error[sorted_error.size() - n_elem_refine];
560 
561  // Finally, let's do the element flagging
562  for (auto & elem : _mesh.active_element_ptr_range())
563  {
564  Elem * parent = elem->parent();
565 
566  if (_coarsen_by_parents && parent && n_elem_coarsen &&
567  error_per_parent[parent->id()] <= bottom_error)
568  elem->set_refinement_flag(Elem::COARSEN);
569 
570  if (!_coarsen_by_parents && n_elem_coarsen &&
571  error_per_cell[elem->id()] <= bottom_error)
572  elem->set_refinement_flag(Elem::COARSEN);
573 
574  if (n_elem_refine &&
575  elem->level() < _max_h_level &&
576  error_per_cell[elem->id()] >= top_error)
577  elem->set_refinement_flag(Elem::REFINE);
578  }
579 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
virtual dof_id_type n_active_elem() const =0
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
MeshBase & _mesh
Reference to the mesh.
unsigned int dim
const Parallel::Communicator & comm() const
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.
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.
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int mesh_dimension() const
Definition: mesh_base.C:430
bool _coarsen_by_parents
Refinement parameter values.
uint8_t dof_id_type
Definition: id_types.h:67

◆ flag_elements_by_error_fraction()

void libMesh::MeshRefinement::flag_elements_by_error_fraction ( const ErrorVector error_per_cell,
const Real  refine_fraction = 0.3,
const Real  coarsen_fraction = 0.0,
const unsigned int  max_level = libMesh::invalid_uint 
)

Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.

The two fractions refine_fraction and coarsen_fraction must be in \( [0,1] \).

All the function arguments except error_per_cell have been deprecated, and will be removed in future libMesh releases - to control these parameters, set the corresponding member variables.

Definition at line 44 of file mesh_refinement_flagging.C.

References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), create_parent_error_vector(), libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, libMesh::libmesh_assert(), TIMPI::Communicator::max(), TIMPI::Communicator::min(), libMesh::Elem::parent(), libMesh::Real, and libMesh::Elem::REFINE.

Referenced by assemble_and_solve(), and main().

48 {
49  parallel_object_only();
50 
51  // Verify that our error vector is consistent, using std::vector to
52  // avoid confusing this->comm().verify
53  libmesh_assert(this->comm().verify(dynamic_cast<const std::vector<ErrorVectorReal> &>(error_per_cell)));
54 
55  // The function arguments are currently just there for
56  // backwards_compatibility
58  {
59  // If the user used non-default parameters, lets warn
60  // that they're deprecated
61  if (refine_frac != 0.3 ||
62  coarsen_frac != 0.0 ||
63  max_l != libMesh::invalid_uint)
64  libmesh_deprecated();
65 
66  _refine_fraction = refine_frac;
67  _coarsen_fraction = coarsen_frac;
68  _max_h_level = max_l;
69  }
70 
71  // Check for valid fractions..
72  // The fraction values must be in [0,1]
73  libmesh_assert_greater_equal (_refine_fraction, 0);
74  libmesh_assert_less_equal (_refine_fraction, 1);
75  libmesh_assert_greater_equal (_coarsen_fraction, 0);
76  libmesh_assert_less_equal (_coarsen_fraction, 1);
77 
78  // Clean up the refinement flags. These could be left
79  // over from previous refinement steps.
80  this->clean_refinement_flags();
81 
82  // We're getting the minimum and maximum error values
83  // for the ACTIVE elements
84  Real error_min = 1.e30;
85  Real error_max = 0.;
86 
87  // And, if necessary, for their parents
88  Real parent_error_min = 1.e30;
89  Real parent_error_max = 0.;
90 
91  // Prepare another error vector if we need to sum parent errors
92  ErrorVector error_per_parent;
94  {
95  create_parent_error_vector(error_per_cell,
96  error_per_parent,
97  parent_error_min,
98  parent_error_max);
99  }
100 
101  // We need to loop over all active elements to find the minimum
102  for (auto & elem : _mesh.active_local_element_ptr_range())
103  {
104  const dof_id_type id = elem->id();
105  libmesh_assert_less (id, error_per_cell.size());
106 
107  error_max = std::max (error_max, error_per_cell[id]);
108  error_min = std::min (error_min, error_per_cell[id]);
109  }
110  this->comm().max(error_max);
111  this->comm().min(error_min);
112 
113  // Compute the cutoff values for coarsening and refinement
114  const Real error_delta = (error_max - error_min);
115  const Real parent_error_delta = parent_error_max - parent_error_min;
116 
117  const Real refine_cutoff = (1.- _refine_fraction)*error_max;
118  const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min;
119  const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min;
120 
121  // // Print information about the error
122  // libMesh::out << " Error Information:" << std::endl
123  // << " ------------------" << std::endl
124  // << " min: " << error_min << std::endl
125  // << " max: " << error_max << std::endl
126  // << " delta: " << error_delta << std::endl
127  // << " refine_cutoff: " << refine_cutoff << std::endl
128  // << " coarsen_cutoff: " << coarsen_cutoff << std::endl;
129 
130 
131 
132  // Loop over the elements and flag them for coarsening or
133  // refinement based on the element error
134  for (auto & elem : _mesh.active_element_ptr_range())
135  {
136  const dof_id_type id = elem->id();
137 
138  libmesh_assert_less (id, error_per_cell.size());
139 
140  const ErrorVectorReal elem_error = error_per_cell[id];
141 
143  {
144  Elem * parent = elem->parent();
145  if (parent)
146  {
147  const dof_id_type parentid = parent->id();
148  if (error_per_parent[parentid] >= 0. &&
149  error_per_parent[parentid] <= parent_cutoff)
150  elem->set_refinement_flag(Elem::COARSEN);
151  }
152  }
153  // Flag the element for coarsening if its error
154  // is <= coarsen_fraction*delta + error_min
155  else if (elem_error <= coarsen_cutoff)
156  {
157  elem->set_refinement_flag(Elem::COARSEN);
158  }
159 
160  // Flag the element for refinement if its error
161  // is >= refinement_cutoff.
162  if (elem_error >= refine_cutoff)
163  if (elem->level() < _max_h_level)
164  elem->set_refinement_flag(Elem::REFINE);
165  }
166 }
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.
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.
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
void min(const T &r, T &o, Request &req) const
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
bool _coarsen_by_parents
Refinement parameter values.
uint8_t dof_id_type
Definition: id_types.h:67

◆ flag_elements_by_error_tolerance()

void libMesh::MeshRefinement::flag_elements_by_error_tolerance ( const ErrorVector error_per_cell)

Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.

This method refines the worst elements with errors greater than absolute_global_tolerance / n_active_elem, flagging at most refine_fraction * n_active_elem It coarsens elements with errors less than coarsen_threshold * global_tolerance / n_active_elem, flagging at most coarsen_fraction * n_active_elem

The three fractions refine_fraction coarsen_fraction and coarsen_threshold should be in \( [0,1] \).

Definition at line 170 of file mesh_refinement_flagging.C.

References _absolute_global_tolerance, _coarsen_by_parents, _coarsen_fraction, _coarsen_threshold, _max_h_level, _mesh, _refine_fraction, libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), create_parent_error_vector(), libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::libmesh_assert(), libMesh::MeshBase::n_active_elem(), libMesh::Elem::n_children(), libMesh::Elem::parent(), libMesh::Real, and libMesh::Elem::REFINE.

Referenced by main().

171 {
172  parallel_object_only();
173 
174  // Verify that our error vector is consistent, using std::vector to
175  // avoid confusing this->comm().verify
176  libmesh_assert(this->comm().verify(dynamic_cast<const std::vector<ErrorVectorReal> &>(error_per_cell_in)));
177 
178  libmesh_assert_greater (_coarsen_threshold, 0);
179 
180  // Check for valid fractions..
181  // The fraction values must be in [0,1]
182  libmesh_assert_greater_equal (_refine_fraction, 0);
183  libmesh_assert_less_equal (_refine_fraction, 1);
184  libmesh_assert_greater_equal (_coarsen_fraction, 0);
185  libmesh_assert_less_equal (_coarsen_fraction, 1);
186 
187  // How much error per cell will we tolerate?
188  const Real local_refinement_tolerance =
189  _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
190  const Real local_coarsening_tolerance =
191  local_refinement_tolerance * _coarsen_threshold;
192 
193  // Prepare another error vector if we need to sum parent errors
194  ErrorVector error_per_parent;
196  {
197  Real parent_error_min, parent_error_max;
198 
199  create_parent_error_vector(error_per_cell_in,
200  error_per_parent,
201  parent_error_min,
202  parent_error_max);
203  }
204 
205  for (auto & elem : _mesh.active_element_ptr_range())
206  {
207  Elem * parent = elem->parent();
208  const dof_id_type elem_number = elem->id();
209  const ErrorVectorReal elem_error = error_per_cell_in[elem_number];
210 
211  if (elem_error > local_refinement_tolerance &&
212  elem->level() < _max_h_level)
213  elem->set_refinement_flag(Elem::REFINE);
214 
215  if (!_coarsen_by_parents && elem_error <
216  local_coarsening_tolerance)
217  elem->set_refinement_flag(Elem::COARSEN);
218 
219  if (_coarsen_by_parents && parent)
220  {
221  ErrorVectorReal parent_error = error_per_parent[parent->id()];
222  if (parent_error >= 0.)
223  {
224  const Real parent_coarsening_tolerance =
225  std::sqrt(parent->n_children() *
226  local_coarsening_tolerance *
227  local_coarsening_tolerance);
228  if (parent_error < parent_coarsening_tolerance)
229  elem->set_refinement_flag(Elem::COARSEN);
230  }
231  }
232  }
233 }
virtual dof_id_type n_active_elem() const =0
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
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.
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool _coarsen_by_parents
Refinement parameter values.
uint8_t dof_id_type
Definition: id_types.h:67

◆ flag_elements_by_mean_stddev()

void libMesh::MeshRefinement::flag_elements_by_mean_stddev ( const ErrorVector error_per_cell,
const Real  refine_fraction = 1.0,
const Real  coarsen_fraction = 0.0,
const unsigned int  max_level = libMesh::invalid_uint 
)

Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.

This method picks the top refine_fraction * stddev + mean elements for refinement and the bottom mean - coarsen_fraction * stddev elements for coarsening. The two fractions refine_fraction and coarsen_fraction must be in \( [0,1] \).

All the function arguments except error_per_cell have been deprecated, and will be removed in future libMesh releases - to control these parameters, set the corresponding member variables.

Definition at line 583 of file mesh_refinement_flagging.C.

References _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), libMesh::ErrorVectorReal, libMesh::invalid_uint, libMesh::libmesh_assert(), libMesh::ErrorVector::mean(), libMesh::Real, libMesh::Elem::REFINE, and libMesh::ErrorVector::variance().

587 {
588  // Verify that our error vector is consistent, using std::vector to
589  // avoid confusing this->comm().verify
590  libmesh_assert(this->comm().verify(dynamic_cast<const std::vector<ErrorVectorReal> &>(error_per_cell)));
591 
592  // The function arguments are currently just there for
593  // backwards_compatibility
595  {
596  // If the user used non-default parameters, lets warn
597  // that they're deprecated
598  if (refine_frac != 0.3 ||
599  coarsen_frac != 0.0 ||
600  max_l != libMesh::invalid_uint)
601  libmesh_deprecated();
602 
603  _refine_fraction = refine_frac;
604  _coarsen_fraction = coarsen_frac;
605  _max_h_level = max_l;
606  }
607 
608  // Get the mean value from the error vector
609  const Real mean = error_per_cell.mean();
610 
611  // Get the standard deviation. This equals the
612  // square-root of the variance
613  const Real stddev = std::sqrt (error_per_cell.variance());
614 
615  // Check for valid fractions
616  libmesh_assert_greater_equal (_refine_fraction, 0);
617  libmesh_assert_less_equal (_refine_fraction, 1);
618  libmesh_assert_greater_equal (_coarsen_fraction, 0);
619  libmesh_assert_less_equal (_coarsen_fraction, 1);
620 
621  // The refine and coarsen cutoff
622  const Real refine_cutoff = mean + _refine_fraction * stddev;
623  const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.);
624 
625  // Loop over the elements and flag them for coarsening or
626  // refinement based on the element error
627  for (auto & elem : _mesh.active_element_ptr_range())
628  {
629  const dof_id_type id = elem->id();
630 
631  libmesh_assert_less (id, error_per_cell.size());
632 
633  const ErrorVectorReal elem_error = error_per_cell[id];
634 
635  // Possibly flag the element for coarsening ...
636  if (elem_error <= coarsen_cutoff)
637  elem->set_refinement_flag(Elem::COARSEN);
638 
639  // ... or refinement
640  if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level))
641  elem->set_refinement_flag(Elem::REFINE);
642  }
643 }
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t dof_id_type
Definition: id_types.h:67

◆ flag_elements_by_nelem_target()

bool libMesh::MeshRefinement::flag_elements_by_nelem_target ( const ErrorVector error_per_cell)

Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.

This method attempts to produce a mesh with slightly more than nelem_target active elements, trading element refinement for element coarsening when their error ratios exceed coarsen_threshold. It flags no more than refine_fraction * n_elem elements for refinement and flags no more than coarsen_fraction * n_elem elements for coarsening.

Returns
true if it has done all the AMR/C it can do in a single step, or false if further adaptive steps may be required to produce a mesh with a narrow error distribution and the right number of elements.

Definition at line 237 of file mesh_refinement_flagging.C.

References _coarsen_by_parents, _coarsen_fraction, _coarsen_threshold, _max_h_level, _mesh, _nelem_target, _refine_fraction, TIMPI::Communicator::allgather(), libMesh::Elem::child_ref_range(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), create_parent_error_vector(), dim, libMesh::Elem::has_children(), libMesh::index_range(), libMesh::Elem::level(), libMesh::libmesh_assert(), TIMPI::Communicator::max(), libMesh::MeshBase::max_elem_id(), libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_active_elem(), libMesh::MeshBase::query_elem_ptr(), libMesh::Real, libMesh::Elem::REFINE, libMesh::remote_elem, and libMesh::Elem::set_refinement_flag().

Referenced by main().

238 {
239  parallel_object_only();
240 
241  // Verify that our error vector is consistent, using std::vector to
242  // avoid confusing this->comm().verify
243  libmesh_assert(this->comm().verify(dynamic_cast<const std::vector<ErrorVectorReal> &>(error_per_cell)));
244 
245  // Check for valid fractions..
246  // The fraction values must be in [0,1]
247  libmesh_assert_greater_equal (_refine_fraction, 0);
248  libmesh_assert_less_equal (_refine_fraction, 1);
249  libmesh_assert_greater_equal (_coarsen_fraction, 0);
250  libmesh_assert_less_equal (_coarsen_fraction, 1);
251 
252  // This function is currently only coded to work when coarsening by
253  // parents - it's too hard to guess how many coarsenings will be
254  // performed otherwise.
256 
257  // The number of active elements in the mesh - hopefully less than
258  // 2 billion on 32 bit machines
259  const dof_id_type n_active_elem = _mesh.n_active_elem();
260 
261  // The maximum number of active elements to flag for coarsening
262  const dof_id_type max_elem_coarsen =
263  static_cast<dof_id_type>(_coarsen_fraction * n_active_elem) + 1;
264 
265  // The maximum number of elements to flag for refinement
266  const dof_id_type max_elem_refine =
267  static_cast<dof_id_type>(_refine_fraction * n_active_elem) + 1;
268 
269  // Clean up the refinement flags. These could be left
270  // over from previous refinement steps.
271  this->clean_refinement_flags();
272 
273  // The target number of elements to add or remove
274  const std::ptrdiff_t n_elem_new =
275  std::ptrdiff_t(_nelem_target) - std::ptrdiff_t(n_active_elem);
276 
277  // Create an vector with active element errors and ids,
278  // sorted by highest errors first
279  const dof_id_type max_elem_id = _mesh.max_elem_id();
280  std::vector<std::pair<ErrorVectorReal, dof_id_type>> sorted_error;
281 
282  sorted_error.reserve (n_active_elem);
283 
284  // On a DistributedMesh, we need to communicate to know which remote ids
285  // correspond to active elements.
286  {
287  std::vector<bool> is_active(max_elem_id, false);
288 
289  for (auto & elem : _mesh.active_local_element_ptr_range())
290  {
291  const dof_id_type eid = elem->id();
292  is_active[eid] = true;
293  libmesh_assert_less (eid, error_per_cell.size());
294  sorted_error.emplace_back(error_per_cell[eid], eid);
295  }
296 
297  this->comm().max(is_active);
298 
299  this->comm().allgather(sorted_error);
300  }
301 
302  // Default sort works since pairs are sorted lexicographically
303  std::sort (sorted_error.begin(), sorted_error.end());
304  std::reverse (sorted_error.begin(), sorted_error.end());
305 
306  // Create a sorted error vector with coarsenable parent elements
307  // only, sorted by lowest errors first
308  ErrorVector error_per_parent;
309  std::vector<std::pair<ErrorVectorReal, dof_id_type>> sorted_parent_error;
310  Real parent_error_min, parent_error_max;
311 
312  create_parent_error_vector(error_per_cell,
313  error_per_parent,
314  parent_error_min,
315  parent_error_max);
316 
317  // create_parent_error_vector sets values for non-parents and
318  // non-coarsenable parents to -1. Get rid of them.
319  for (auto i : index_range(error_per_parent))
320  if (error_per_parent[i] != -1)
321  sorted_parent_error.emplace_back(error_per_parent[i], i);
322 
323  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
324 
325  // Keep track of how many elements we plan to coarsen & refine
326  dof_id_type coarsen_count = 0;
327  dof_id_type refine_count = 0;
328 
329  const unsigned int dim = _mesh.mesh_dimension();
330  unsigned int twotodim = 1;
331  for (unsigned int i=0; i!=dim; ++i)
332  twotodim *= 2;
333 
334  // First, let's try to get our element count to target_nelem
335  if (n_elem_new >= 0)
336  {
337  // Every element refinement creates at least
338  // 2^dim-1 new elements
339  refine_count =
340  std::min(cast_int<dof_id_type>(n_elem_new / (twotodim-1)),
341  max_elem_refine);
342  }
343  else
344  {
345  // Every successful element coarsening is likely to destroy
346  // 2^dim-1 net elements.
347  coarsen_count =
348  std::min(cast_int<dof_id_type>(-n_elem_new / (twotodim-1)),
349  max_elem_coarsen);
350  }
351 
352  // Next, let's see if we can trade any refinement for coarsening
353  while (coarsen_count < max_elem_coarsen &&
354  refine_count < max_elem_refine &&
355  coarsen_count < sorted_parent_error.size() &&
356  refine_count < sorted_error.size() &&
357  sorted_error[refine_count].first >
358  sorted_parent_error[coarsen_count].first * _coarsen_threshold)
359  {
360  coarsen_count++;
361  refine_count++;
362  }
363 
364  // On a DistributedMesh, we need to communicate to know which remote ids
365  // correspond to refinable elements
366  dof_id_type successful_refine_count = 0;
367  {
368  std::vector<bool> is_refinable(max_elem_id, false);
369 
370  for (const auto & pr : sorted_error)
371  {
372  dof_id_type eid = pr.second;
373  Elem * elem = _mesh.query_elem_ptr(eid);
374  if (elem && elem->level() < _max_h_level)
375  is_refinable[eid] = true;
376  }
377  this->comm().max(is_refinable);
378 
379  if (refine_count > max_elem_refine)
380  refine_count = max_elem_refine;
381  for (const auto & pr : sorted_error)
382  {
383  if (successful_refine_count >= refine_count)
384  break;
385 
386  dof_id_type eid = pr.second;
387  Elem * elem = _mesh.query_elem_ptr(eid);
388  if (is_refinable[eid])
389  {
390  if (elem)
392  successful_refine_count++;
393  }
394  }
395  }
396 
397  // If we couldn't refine enough elements, don't coarsen too many
398  // either
399  if (coarsen_count < (refine_count - successful_refine_count))
400  coarsen_count = 0;
401  else
402  coarsen_count -= (refine_count - successful_refine_count);
403 
404  if (coarsen_count > max_elem_coarsen)
405  coarsen_count = max_elem_coarsen;
406 
407  dof_id_type successful_coarsen_count = 0;
408  if (coarsen_count)
409  {
410  for (const auto & pr : sorted_parent_error)
411  {
412  if (successful_coarsen_count >= coarsen_count * twotodim)
413  break;
414 
415  dof_id_type parent_id = pr.second;
416  Elem * parent = _mesh.query_elem_ptr(parent_id);
417 
418  // On a DistributedMesh we skip remote elements
419  if (!parent)
420  continue;
421 
422  libmesh_assert(parent->has_children());
423  for (auto & elem : parent->child_ref_range())
424  {
425  if (&elem != remote_elem)
426  {
427  libmesh_assert(elem.active());
428  elem.set_refinement_flag(Elem::COARSEN);
429  successful_coarsen_count++;
430  }
431  }
432  }
433  }
434 
435  // Return true if we've done all the AMR/C we can
436  if (!successful_coarsen_count &&
437  !successful_refine_count)
438  return true;
439  // And false if there may still be more to do.
440  return false;
441 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
virtual dof_id_type n_active_elem() const =0
MeshBase & _mesh
Reference to the mesh.
unsigned int dim
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
const Parallel::Communicator & comm() const
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.
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.
virtual dof_id_type max_elem_id() const =0
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
void max(const T &r, T &o, Request &req) const
unsigned int mesh_dimension() const
Definition: mesh_base.C:430
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:153
bool _coarsen_by_parents
Refinement parameter values.
uint8_t dof_id_type
Definition: id_types.h:67
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ get_mesh() [1/2]

const MeshBase& libMesh::MeshRefinement::get_mesh ( ) const
inline
Returns
A constant reference to the MeshBase object associated with this object.

Definition at line 340 of file mesh_refinement.h.

References _mesh.

340 { return _mesh; }
MeshBase & _mesh
Reference to the mesh.

◆ get_mesh() [2/2]

MeshBase& libMesh::MeshRefinement::get_mesh ( )
inline
Returns
A writable reference to the MeshBase object associated with this object.

Definition at line 346 of file mesh_refinement.h.

References _mesh.

346 { return _mesh; }
MeshBase & _mesh
Reference to the mesh.

◆ has_topological_neighbor()

bool libMesh::MeshRefinement::has_topological_neighbor ( const Elem elem,
const PointLocatorBase point_locator,
const Elem neighbor 
) const
private

Local dispatch function for checking the correct has_neighbor function from the Elem class.

Definition at line 1849 of file mesh_refinement.C.

References _mesh, _periodic_boundaries, libMesh::Elem::has_neighbor(), libMesh::Elem::has_topological_neighbor(), and libMesh::libmesh_assert().

Referenced by make_coarsening_compatible(), and make_refinement_compatible().

1852 {
1853 #ifdef LIBMESH_ENABLE_PERIODIC
1854  if (_periodic_boundaries && !_periodic_boundaries->empty())
1855  {
1856  libmesh_assert(point_locator);
1857  return elem->has_topological_neighbor(neighbor, _mesh, *point_locator, _periodic_boundaries);
1858  }
1859 #endif
1860  return elem->has_neighbor(neighbor);
1861 }
MeshBase & _mesh
Reference to the mesh.
PeriodicBoundaries * _periodic_boundaries
libmesh_assert(ctx)

◆ limit_level_mismatch_at_edge()

bool libMesh::MeshRefinement::limit_level_mismatch_at_edge ( const unsigned int  max_mismatch)
private

Definition at line 126 of file mesh_refinement_smoothing.C.

References _enforce_mismatch_limit_prior_to_refinement, _mesh, libMesh::ParallelObject::comm(), EDGE, enforce_mismatch_limit_prior_to_refinement(), TIMPI::Communicator::max(), libMesh::Elem::parent(), and libMesh::Elem::REFINE.

Referenced by _smooth_flags().

127 {
128  // This function must be run on all processors at once
129  parallel_object_only();
130 
131  bool flags_changed = false;
132 
133 
134  // Maps holding the maximum element level that touches an edge
135  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
136  max_level_at_edge;
137  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
138  max_p_level_at_edge;
139 
140  std::unique_ptr<const Elem> edge, pedge;
141  // Loop over all the active elements & fill the maps
142  for (auto & elem : _mesh.active_element_ptr_range())
143  {
144  const unsigned char elem_level =
145  cast_int<unsigned char>(elem->level() +
146  ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0));
147  const unsigned char elem_p_level =
148  cast_int<unsigned char>(elem->p_level() +
149  ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
150 
151  // Set the max_level at each edge
152  for (auto n : elem->edge_index_range())
153  {
154  elem->build_edge_ptr(edge, n);
155  dof_id_type childnode0 = edge->node_id(0);
156  dof_id_type childnode1 = edge->node_id(1);
157  if (childnode1 < childnode0)
158  std::swap(childnode0, childnode1);
159 
160  for (const Elem * p = elem; p != nullptr; p = p->parent())
161  {
162  p->build_edge_ptr(pedge, n);
163  dof_id_type node0 = pedge->node_id(0);
164  dof_id_type node1 = pedge->node_id(1);
165 
166  if (node1 < node0)
167  std::swap(node0, node1);
168 
169  // If elem does not share this edge with its ancestor
170  // p, refinement levels of elements sharing p's edge
171  // are not restricted by refinement levels of elem.
172  // Furthermore, elem will not share this edge with any
173  // of p's ancestors, so we can safely break out of the
174  // for loop early.
175  if (node0 != childnode0 && node1 != childnode1)
176  break;
177 
178  childnode0 = node0;
179  childnode1 = node1;
180 
181  std::pair<unsigned int, unsigned int> edge_key =
182  std::make_pair(node0, node1);
183 
184  // Try emplacing (edge_key, elem_level) into max_level_at_edge map.
185  // If emplacing fails, it means the edge_key already existed, so
186  // we need to take the max of the previous and current values.
187  if (auto [it, emplaced] = max_level_at_edge.emplace(edge_key, elem_level);
188  !emplaced)
189  it->second = std::max(it->second, elem_level);
190 
191  // Same thing for p_level
192  if (auto [it, emplaced] = max_p_level_at_edge.emplace(edge_key, elem_p_level);
193  !emplaced)
194  it->second = std::max(it->second, elem_p_level);
195  }
196  }
197  }
198 
199 
200  // Now loop over the active elements and flag the elements
201  // who violate the requested level mismatch
202  for (auto & elem : _mesh.active_element_ptr_range())
203  {
204  const unsigned int elem_level = elem->level();
205  const unsigned int elem_p_level = elem->p_level();
206 
207  // Skip the element if it is already fully flagged
208  if (elem->refinement_flag() == Elem::REFINE &&
209  elem->p_refinement_flag() == Elem::REFINE
211  continue;
212 
213  // Loop over the nodes, check for possible mismatch
214  for (auto n : elem->edge_index_range())
215  {
216  elem->build_edge_ptr(edge, n);
217  dof_id_type node0 = edge->node_id(0);
218  dof_id_type node1 = edge->node_id(1);
219  if (node1 < node0)
220  std::swap(node0, node1);
221 
222  std::pair<dof_id_type, dof_id_type> edge_key =
223  std::make_pair(node0, node1);
224 
225  // Flag the element for refinement if it violates
226  // the requested level mismatch
227  if ((elem_level + max_mismatch) < max_level_at_edge[edge_key]
228  && elem->refinement_flag() != Elem::REFINE)
229  {
230  elem->set_refinement_flag (Elem::REFINE);
231  flags_changed = true;
232  }
233 
234  if ((elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
235  && elem->p_refinement_flag() != Elem::REFINE)
236  {
237  elem->set_p_refinement_flag (Elem::REFINE);
238  flags_changed = true;
239  }
240 
241  // Possibly enforce limit mismatch prior to refinement
242  flags_changed |= this->enforce_mismatch_limit_prior_to_refinement(elem, EDGE, max_mismatch);
243  } // loop over edges
244  } // loop over active elements
245 
246  // If flags changed on any processor then they changed globally
247  this->comm().max(flags_changed);
248 
249  return flags_changed;
250 }
bool & enforce_mismatch_limit_prior_to_refinement()
Get/set the _enforce_mismatch_limit_prior_to_refinement flag.
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...
void max(const T &r, T &o, Request &req) const
uint8_t dof_id_type
Definition: id_types.h:67

◆ limit_level_mismatch_at_node()

bool libMesh::MeshRefinement::limit_level_mismatch_at_node ( const unsigned int  max_mismatch)
private


This algorithm restricts the maximum level mismatch at any node in the mesh.

Calling this with max_mismatch equal to 1 would transform this mesh:

* o---o---o---o---o-------o-------o
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o       |       |
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o-------o-------o
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o       |       |
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o-------o-------o
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* o-------o-------o               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* o-------o-------o---------------o
* 

into this:

* o---o---o---o---o-------o-------o
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o       |       |
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o-------o-------o
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o       |       |
* |   |   |   |   |       |       |
* |   |   |   |   |       |       |
* o---o---o---o---o-------o-------o
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* o-------o-------o.......o.......o
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* o-------o-------o-------o-------o
* 

by refining the indicated element

Definition at line 39 of file mesh_refinement_smoothing.C.

References _enforce_mismatch_limit_prior_to_refinement, _mesh, libMesh::ParallelObject::comm(), enforce_mismatch_limit_prior_to_refinement(), TIMPI::Communicator::max(), libMesh::MeshBase::n_nodes(), POINT, and libMesh::Elem::REFINE.

Referenced by _smooth_flags().

40 {
41  // This function must be run on all processors at once
42  parallel_object_only();
43 
44  bool flags_changed = false;
45 
46 
47  // Vector holding the maximum element level that touches a node.
48  std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0);
49  std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0);
50 
51  // Loop over all the active elements & fill the vector
52  for (auto & elem : _mesh.active_element_ptr_range())
53  {
54  const unsigned char elem_level =
55  cast_int<unsigned char>(elem->level() +
56  ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0));
57  const unsigned char elem_p_level =
58  cast_int<unsigned char>(elem->p_level() +
59  ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
60 
61  // Set the max_level at each node
62  for (const Node & node : elem->node_ref_range())
63  {
64  const dof_id_type node_number = node.id();
65 
66  libmesh_assert_less (node_number, max_level_at_node.size());
67 
68  max_level_at_node[node_number] =
69  std::max (max_level_at_node[node_number], elem_level);
70  max_p_level_at_node[node_number] =
71  std::max (max_p_level_at_node[node_number], elem_p_level);
72  }
73  }
74 
75 
76  // Now loop over the active elements and flag the elements
77  // who violate the requested level mismatch. Alternatively, if
78  // _enforce_mismatch_limit_prior_to_refinement is true, swap refinement flags
79  // accordingly.
80  for (auto & elem : _mesh.active_element_ptr_range())
81  {
82  const unsigned int elem_level = elem->level();
83  const unsigned int elem_p_level = elem->p_level();
84 
85  // Skip the element if it is already fully flagged
86  // unless we are enforcing mismatch prior to refinement and may need to
87  // remove the refinement flag(s)
88  if (elem->refinement_flag() == Elem::REFINE &&
89  elem->p_refinement_flag() == Elem::REFINE
91  continue;
92 
93  // Loop over the nodes, check for possible mismatch
94  for (const Node & node : elem->node_ref_range())
95  {
96  const dof_id_type node_number = node.id();
97 
98  // Flag the element for refinement if it violates
99  // the requested level mismatch
100  if ((elem_level + max_mismatch) < max_level_at_node[node_number]
101  && elem->refinement_flag() != Elem::REFINE)
102  {
103  elem->set_refinement_flag (Elem::REFINE);
104  flags_changed = true;
105  }
106  if ((elem_p_level + max_mismatch) < max_p_level_at_node[node_number]
107  && elem->p_refinement_flag() != Elem::REFINE)
108  {
109  elem->set_p_refinement_flag (Elem::REFINE);
110  flags_changed = true;
111  }
112 
113  // Possibly enforce limit mismatch prior to refinement
114  flags_changed |= this->enforce_mismatch_limit_prior_to_refinement(elem, POINT, max_mismatch);
115  }
116  }
117 
118  // If flags changed on any processor then they changed globally
119  this->comm().max(flags_changed);
120 
121  return flags_changed;
122 }
bool & enforce_mismatch_limit_prior_to_refinement()
Get/set the _enforce_mismatch_limit_prior_to_refinement flag.
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
bool _enforce_mismatch_limit_prior_to_refinement
This option enforces the mismatch level prior to refinement by checking if refining any element mar...
void max(const T &r, T &o, Request &req) const
virtual dof_id_type n_nodes() const =0
uint8_t dof_id_type
Definition: id_types.h:67

◆ limit_overrefined_boundary()

bool libMesh::MeshRefinement::limit_overrefined_boundary ( const signed char  max_mismatch)
private

Definition at line 254 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::ParallelObject::comm(), TIMPI::Communicator::max(), and libMesh::Elem::REFINE.

Referenced by _smooth_flags().

255 {
256  // This function must be run on all processors at once
257  parallel_object_only();
258 
259  bool flags_changed = false;
260 
261  // Loop over all the active elements & look for mismatches to fix.
262  for (auto & elem : _mesh.active_element_ptr_range())
263  {
264  // If we don't have an interior_parent then there's nothing to
265  // be mismatched with.
266  if ((elem->dim() >= LIBMESH_DIM) ||
267  !elem->interior_parent())
268  continue;
269 
270  const unsigned char elem_level =
271  cast_int<unsigned char>(elem->level() +
272  ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0));
273  const unsigned char elem_p_level =
274  cast_int<unsigned char>(elem->p_level() +
275  ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
276 
277  // get all relevant interior elements
278  std::set<Elem *> neighbor_set;
279  elem->find_interior_neighbors(neighbor_set);
280 
281  for (auto & neighbor : neighbor_set)
282  if (max_mismatch >= 0)
283  {
284  if ((elem_level > neighbor->level() + max_mismatch) &&
285  (neighbor->refinement_flag() != Elem::REFINE))
286  {
287  neighbor->set_refinement_flag(Elem::REFINE);
288  flags_changed = true;
289  }
290 
291  if ((elem_p_level > neighbor->p_level() + max_mismatch) &&
292  (neighbor->p_refinement_flag() != Elem::REFINE))
293  {
294  neighbor->set_p_refinement_flag(Elem::REFINE);
295  flags_changed = true;
296  }
297  }
298  }
299 
300  // If flags changed on any processor then they changed globally
301  this->comm().max(flags_changed);
302 
303  return flags_changed;
304 }
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
void max(const T &r, T &o, Request &req) const

◆ limit_underrefined_boundary()

bool libMesh::MeshRefinement::limit_underrefined_boundary ( const signed char  max_mismatch)
private

Definition at line 308 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::ParallelObject::comm(), TIMPI::Communicator::max(), and libMesh::Elem::REFINE.

Referenced by _smooth_flags().

309 {
310  // This function must be run on all processors at once
311  parallel_object_only();
312 
313  bool flags_changed = false;
314 
315  // Loop over all the active elements & look for mismatches to fix.
316  for (auto & elem : _mesh.active_element_ptr_range())
317  {
318  // If we don't have an interior_parent then there's nothing to
319  // be mismatched with.
320  if ((elem->dim() >= LIBMESH_DIM) ||
321  !elem->interior_parent())
322  continue;
323 
324  // get all relevant interior elements
325  std::set<const Elem *> neighbor_set;
326  elem->find_interior_neighbors(neighbor_set);
327 
328  for (const Elem * neighbor : neighbor_set)
329  {
330  const unsigned char neighbor_level =
331  cast_int<unsigned char>(neighbor->level() +
332  ((neighbor->refinement_flag() == Elem::REFINE) ? 1 : 0));
333 
334  const unsigned char neighbor_p_level =
335  cast_int<unsigned char>(neighbor->p_level() +
336  ((neighbor->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
337 
338  if (max_mismatch >= 0)
339  {
340  if ((neighbor_level >
341  elem->level() + max_mismatch) &&
342  (elem->refinement_flag() != Elem::REFINE))
343  {
344  elem->set_refinement_flag(Elem::REFINE);
345  flags_changed = true;
346  }
347 
348  if ((neighbor_p_level >
349  elem->p_level() + max_mismatch) &&
350  (elem->p_refinement_flag() != Elem::REFINE))
351  {
352  elem->set_p_refinement_flag(Elem::REFINE);
353  flags_changed = true;
354  }
355  }
356  } // loop over interior neighbors
357  }
358 
359  // If flags changed on any processor then they changed globally
360  this->comm().max(flags_changed);
361 
362  return flags_changed;
363 }
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
void max(const T &r, T &o, Request &req) const

◆ make_coarsening_compatible()

bool libMesh::MeshRefinement::make_coarsening_compatible ( )
private

Take user-specified coarsening flags and augment them so that level-one dependency is satisfied.

This function used to take an argument, maintain_level_one - new code should use face_level_mismatch_limit() instead.

Definition at line 815 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::as_range(), libMesh::Elem::child_ref_range(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elem_ref(), TIMPI::Communicator::get_unique_tag(), libMesh::Elem::has_children(), has_topological_neighbor(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_replicated(), libMesh::MeshBase::is_serial(), libMesh::Elem::level(), libMesh::libmesh_assert(), TIMPI::Communicator::min(), libMesh::ParallelObject::n_processors(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), TIMPI::Communicator::receive(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, TIMPI::Communicator::send(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), libMesh::MeshBase::sub_point_locator(), libMesh::Parallel::sync_dofobject_data_by_id(), and topological_neighbor().

Referenced by _smooth_flags(), coarsen_elements(), and refine_and_coarsen_elements().

816 {
817  // This function must be run on all processors at once
818  parallel_object_only();
819 
820  // We may need a PointLocator for topological_neighbor() tests
821  // later, which we need to make sure gets constructed on all
822  // processors at once.
823  std::unique_ptr<PointLocatorBase> point_locator;
824 
825 #ifdef LIBMESH_ENABLE_PERIODIC
826  bool has_periodic_boundaries =
828  libmesh_assert(this->comm().verify(has_periodic_boundaries));
829 
830  if (has_periodic_boundaries)
831  point_locator = _mesh.sub_point_locator();
832 #endif
833 
834  LOG_SCOPE ("make_coarsening_compatible()", "MeshRefinement");
835 
836  // Unless we encounter a specific situation level-one
837  // will be satisfied after executing this loop just once
838  bool level_one_satisfied = true;
839 
840 
841  // Unless we encounter a specific situation we will be compatible
842  // with any selected refinement flags
843  bool compatible_with_refinement = true;
844 
845 
846  // find the maximum h and p levels in the mesh
847  unsigned int max_level = 0;
848  unsigned int max_p_level = 0;
849 
850  {
851  // First we look at all the active level-0 elements. Since it doesn't make
852  // sense to coarsen them we must un-set their coarsen flags if
853  // they are set.
854  for (auto & elem : _mesh.active_element_ptr_range())
855  {
856  max_level = std::max(max_level, elem->level());
857  max_p_level =
858  std::max(max_p_level,
859  static_cast<unsigned int>(elem->p_level()));
860 
861  if ((elem->level() == 0) &&
862  (elem->refinement_flag() == Elem::COARSEN))
863  elem->set_refinement_flag(Elem::DO_NOTHING);
864 
865  if ((elem->p_level() == 0) &&
866  (elem->p_refinement_flag() == Elem::COARSEN))
867  elem->set_p_refinement_flag(Elem::DO_NOTHING);
868  }
869  }
870 
871  // Even if there are no refined elements on this processor then
872  // there may still be work for us to do on e.g. ancestor elements.
873  // At the very least we need to be in the loop if a distributed mesh
874  // needs to synchronize data.
875 #if 0
876  if (max_level == 0 && max_p_level == 0)
877  {
878  // But we still have to check with other processors
879  this->comm().min(compatible_with_refinement);
880 
881  return compatible_with_refinement;
882  }
883 #endif
884 
885  // Loop over all the active elements. If an element is marked
886  // for coarsening we better check its neighbors. If ANY of these neighbors
887  // are marked for refinement AND are at the same level then there is a
888  // conflict. By convention refinement wins, so we un-mark the element for
889  // coarsening. Level-one would be violated in this case so we need to re-run
890  // the loop.
892  {
893 
894  repeat:
895  level_one_satisfied = true;
896 
897  do
898  {
899  level_one_satisfied = true;
900 
901  for (auto & elem : _mesh.active_element_ptr_range())
902  {
903  bool my_flag_changed = false;
904 
905  if (elem->refinement_flag() == Elem::COARSEN) // If the element is active and
906  // the coarsen flag is set
907  {
908  const unsigned int my_level = elem->level();
909 
910  for (auto n : elem->side_index_range())
911  {
912  const Elem * neighbor =
913  topological_neighbor(elem, point_locator.get(), n);
914 
915  if (neighbor != nullptr && // I have a
916  neighbor != remote_elem) // neighbor here
917  {
918  if (neighbor->active()) // and it is active
919  {
920  if ((neighbor->level() == my_level) &&
921  (neighbor->refinement_flag() == Elem::REFINE)) // the neighbor is at my level
922  // and wants to be refined
923  {
925  my_flag_changed = true;
926  break;
927  }
928  }
929  else // I have a neighbor and it is not active. That means it has children.
930  { // While it _may_ be possible to coarsen us if all the children of
931  // that element want to be coarsened, it is impossible to know at this
932  // stage. Forget about it for the moment... This can be handled in
933  // two steps.
934  elem->set_refinement_flag(Elem::DO_NOTHING);
935  my_flag_changed = true;
936  break;
937  }
938  }
939  }
940  }
941  if (elem->p_refinement_flag() == Elem::COARSEN) // If
942  // the element is active and the order reduction flag is set
943  {
944  const unsigned int my_p_level = elem->p_level();
945 
946  for (auto n : elem->side_index_range())
947  {
948  const Elem * neighbor =
949  topological_neighbor(elem, point_locator.get(), n);
950 
951  if (neighbor != nullptr && // I have a
952  neighbor != remote_elem) // neighbor here
953  {
954  if (neighbor->active()) // and it is active
955  {
956  if ((neighbor->p_level() > my_p_level &&
957  neighbor->p_refinement_flag() != Elem::COARSEN)
958  || (neighbor->p_level() == my_p_level &&
959  neighbor->p_refinement_flag() == Elem::REFINE))
960  {
962  my_flag_changed = true;
963  break;
964  }
965  }
966  else // I have a neighbor and it is not active.
967  { // We need to find which of its children
968  // have me as a neighbor, and maintain
969  // level one p compatibility with them.
970  // Because we currently have level one h
971  // compatibility, we don't need to check
972  // grandchildren
973 
974  libmesh_assert(neighbor->has_children());
975  for (auto & subneighbor : neighbor->child_ref_range())
976  if (&subneighbor != remote_elem &&
977  subneighbor.active() &&
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))
983  {
984  elem->set_p_refinement_flag(Elem::DO_NOTHING);
985  my_flag_changed = true;
986  break;
987  }
988  if (my_flag_changed)
989  break;
990  }
991  }
992  }
993  }
994 
995  // If the current element's flag changed, we hadn't
996  // satisfied the level one rule.
997  if (my_flag_changed)
998  level_one_satisfied = false;
999 
1000  // Additionally, if it has non-local neighbors, and
1001  // we're not in serial, then we'll eventually have to
1002  // return compatible_with_refinement = false, because
1003  // our change has to propagate to neighboring
1004  // processors.
1005  if (my_flag_changed && !_mesh.is_serial())
1006  for (auto n : elem->side_index_range())
1007  {
1008  Elem * neigh =
1009  topological_neighbor(elem, point_locator.get(), n);
1010 
1011  if (!neigh)
1012  continue;
1013  if (neigh == remote_elem ||
1014  neigh->processor_id() !=
1015  this->processor_id())
1016  {
1017  compatible_with_refinement = false;
1018  break;
1019  }
1020  // FIXME - for non-level one meshes we should
1021  // test all descendants
1022  if (neigh->has_children())
1023  for (auto & child : neigh->child_ref_range())
1024  if (&child == remote_elem ||
1025  child.processor_id() !=
1026  this->processor_id())
1027  {
1028  compatible_with_refinement = false;
1029  break;
1030  }
1031  }
1032  }
1033  }
1034  while (!level_one_satisfied);
1035 
1036  } // end if (_face_level_mismatch_limit)
1037 
1038 
1039  // Next we look at all of the ancestor cells.
1040  // If there is a parent cell with all of its children
1041  // wanting to be unrefined then the element is a candidate
1042  // for unrefinement. If all the children don't
1043  // all want to be unrefined then ALL of them need to have their
1044  // unrefinement flags cleared.
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())
1048  {
1049  // right now the element hasn't been disqualified
1050  // as a candidate for unrefinement
1051  bool is_a_candidate = true;
1052  bool found_remote_child = false;
1053 
1054  for (auto & child : elem->child_ref_range())
1055  {
1056  if (&child == remote_elem)
1057  found_remote_child = true;
1058  else if ((child.refinement_flag() != Elem::COARSEN) ||
1059  !child.active() )
1060  is_a_candidate = false;
1061  }
1062 
1063  if (!is_a_candidate && !found_remote_child)
1064  {
1066 
1067  for (auto & child : elem->child_ref_range())
1068  {
1069  if (&child == remote_elem)
1070  continue;
1071  if (child.refinement_flag() == Elem::COARSEN)
1072  {
1073  level_one_satisfied = false;
1074  child.set_refinement_flag(Elem::DO_NOTHING);
1075  }
1076  }
1077  }
1078  }
1079 
1080  if (!level_one_satisfied && _face_level_mismatch_limit) goto repeat;
1081 
1082 
1083  // If all the children of a parent are set to be coarsened
1084  // then flag the parent so that they can kill their kids.
1085 
1086  // On a distributed mesh, we won't always be able to determine this
1087  // on parent elements with remote children, even if we own the
1088  // parent, without communication.
1089  //
1090  // We'll first communicate *to* parents' owners when we determine
1091  // they cannot be coarsened, then we'll sync the final refinement
1092  // flag *from* the parents.
1093 
1094  // uncoarsenable_parents[p] live on processor id p
1095  const processor_id_type n_proc = _mesh.n_processors();
1096  const processor_id_type my_proc_id = _mesh.processor_id();
1097  const bool distributed_mesh = !_mesh.is_replicated();
1098 
1099  std::vector<std::vector<dof_id_type>>
1100  uncoarsenable_parents(n_proc);
1101 
1102  for (auto & elem : as_range(_mesh.ancestor_elements_begin(), _mesh.ancestor_elements_end()))
1103  {
1104  // Presume all the children are flagged for coarsening and
1105  // then look for a contradiction
1106  bool all_children_flagged_for_coarsening = true;
1107 
1108  for (auto & child : elem->child_ref_range())
1109  {
1110  if (&child != remote_elem &&
1111  child.refinement_flag() != Elem::COARSEN)
1112  {
1113  all_children_flagged_for_coarsening = false;
1114  if (!distributed_mesh)
1115  break;
1116  if (child.processor_id() != elem->processor_id())
1117  {
1118  uncoarsenable_parents[elem->processor_id()].push_back(elem->id());
1119  break;
1120  }
1121  }
1122  }
1123 
1124  if (all_children_flagged_for_coarsening)
1125  elem->set_refinement_flag(Elem::COARSEN_INACTIVE);
1126  else
1127  elem->set_refinement_flag(Elem::INACTIVE);
1128  }
1129 
1130  // If we have a distributed mesh, we might need to sync up
1131  // INACTIVE vs. COARSEN_INACTIVE flags.
1132  if (distributed_mesh)
1133  {
1134  // We'd better still be in sync here
1135  parallel_object_only();
1136 
1137  Parallel::MessageTag
1138  uncoarsenable_tag = this->comm().get_unique_tag();
1139  std::vector<Parallel::Request> uncoarsenable_push_requests(n_proc-1);
1140 
1141  for (processor_id_type p = 0; p != n_proc; ++p)
1142  {
1143  if (p == my_proc_id)
1144  continue;
1145 
1146  Parallel::Request &request =
1147  uncoarsenable_push_requests[p - (p > my_proc_id)];
1148 
1149  _mesh.comm().send
1150  (p, uncoarsenable_parents[p], request, uncoarsenable_tag);
1151  }
1152 
1153  for (processor_id_type p = 1; p != n_proc; ++p)
1154  {
1155  std::vector<dof_id_type> my_uncoarsenable_parents;
1156  _mesh.comm().receive
1157  (Parallel::any_source, my_uncoarsenable_parents,
1158  uncoarsenable_tag);
1159 
1160  for (const auto & id : my_uncoarsenable_parents)
1161  {
1162  Elem & elem = _mesh.elem_ref(id);
1163  libmesh_assert(elem.refinement_flag() == Elem::INACTIVE ||
1164  elem.refinement_flag() == Elem::COARSEN_INACTIVE);
1165  elem.set_refinement_flag(Elem::INACTIVE);
1166  }
1167  }
1168 
1169  Parallel::wait(uncoarsenable_push_requests);
1170 
1171  SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
1174  (this->comm(), _mesh.not_local_elements_begin(),
1175  _mesh.not_local_elements_end(),
1176  // We'd like a smaller sync, but this leads to bugs?
1177  // SyncCoarsenInactive(),
1178  hsync);
1179  }
1180 
1181  // If one processor finds an incompatibility, we're globally
1182  // incompatible
1183  this->comm().min(compatible_with_refinement);
1184 
1185  return compatible_with_refinement;
1186 }
RefinementState refinement_flag() const
Definition: elem.h:3224
MPI_Request request
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
bool has_topological_neighbor(const Elem *elem, const PointLocatorBase *point_locator, const Elem *neighbor) const
Local dispatch function for checking the correct has_neighbor function from the Elem class...
MeshBase & _mesh
Reference to the mesh.
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
const Parallel::Communicator & comm() const
PeriodicBoundaries * _periodic_boundaries
uint8_t processor_id_type
processor_id_type n_processors() const
virtual bool is_serial() const
Definition: mesh_base.h:347
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
void min(const T &r, T &o, Request &req) const
unsigned char _face_level_mismatch_limit
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libmesh_assert(ctx)
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
virtual bool is_replicated() const
Definition: mesh_base.h:369
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:778
Elem * topological_neighbor(Elem *elem, const PointLocatorBase *point_locator, const unsigned int side) const
Local dispatch function for getting the correct topological neighbor from the Elem class...
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:3248
processor_id_type processor_id() const
bool active() const
Definition: elem.h:2955
processor_id_type processor_id() const
Definition: dof_object.h:881
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ make_flags_parallel_consistent()

bool libMesh::MeshRefinement::make_flags_parallel_consistent ( )

Copy refinement flags on ghost elements from their local processors.

Returns
true if any flags changed.

Definition at line 787 of file mesh_refinement.C.

References _mesh, libMesh::ParallelObject::comm(), TIMPI::Communicator::min(), libMesh::Elem::p_refinement_flag(), libMesh::SyncRefinementFlags::parallel_consistent, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), and libMesh::Parallel::sync_dofobject_data_by_id().

Referenced by _smooth_flags(), coarsen_elements(), refine_and_coarsen_elements(), refine_elements(), and libMesh::HPCoarsenTest::select_refinement().

788 {
789  // This function must be run on all processors at once
790  parallel_object_only();
791 
792  LOG_SCOPE ("make_flags_parallel_consistent()", "MeshRefinement");
793 
794  SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
797  (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), hsync);
798 
799  SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
802  (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), psync);
803 
804  // If we weren't consistent in both h and p on every processor then
805  // we weren't globally consistent
806  bool parallel_consistent = hsync.parallel_consistent &&
807  psync.parallel_consistent;
808  this->comm().min(parallel_consistent);
809 
810  return parallel_consistent;
811 }
RefinementState refinement_flag() const
Definition: elem.h:3224
MeshBase & _mesh
Reference to the mesh.
RefinementState p_refinement_flag() const
Definition: elem.h:3240
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
const Parallel::Communicator & comm() const
void min(const T &r, T &o, Request &req) const
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:3248

◆ make_refinement_compatible()

bool libMesh::MeshRefinement::make_refinement_compatible ( )
private

Take user-specified refinement flags and augment them so that level-one dependency is satisfied.

This function used to take an argument, maintain_level_one - new code should use face_level_mismatch_limit() instead.

Definition at line 1195 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::Elem::child_ref_range(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::Elem::has_children(), has_topological_neighbor(), libMesh::Elem::INACTIVE, libMesh::Elem::level(), libMesh::libmesh_assert(), TIMPI::Communicator::min(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::parent(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), libMesh::MeshBase::sub_point_locator(), and topological_neighbor().

Referenced by _smooth_flags(), refine_and_coarsen_elements(), and refine_elements().

1196 {
1197  // This function must be run on all processors at once
1198  parallel_object_only();
1199 
1200  // We may need a PointLocator for topological_neighbor() tests
1201  // later, which we need to make sure gets constructed on all
1202  // processors at once.
1203  std::unique_ptr<PointLocatorBase> point_locator;
1204 
1205 #ifdef LIBMESH_ENABLE_PERIODIC
1206  bool has_periodic_boundaries =
1208  libmesh_assert(this->comm().verify(has_periodic_boundaries));
1209 
1210  if (has_periodic_boundaries)
1211  point_locator = _mesh.sub_point_locator();
1212 #endif
1213 
1214  LOG_SCOPE ("make_refinement_compatible()", "MeshRefinement");
1215 
1216  // Unless we encounter a specific situation we will be compatible
1217  // with any selected coarsening flags
1218  bool compatible_with_coarsening = true;
1219 
1220  // This loop enforces the level-1 rule. We should only
1221  // execute it if the user indeed wants level-1 satisfied!
1223  {
1224  // Unless we encounter a specific situation level-one
1225  // will be satisfied after executing this loop just once
1226  bool level_one_satisfied = true;
1227 
1228  do
1229  {
1230  level_one_satisfied = true;
1231 
1232  for (auto & elem : _mesh.active_element_ptr_range())
1233  {
1234  const unsigned short n_sides = elem->n_sides();
1235 
1236  if (elem->refinement_flag() == Elem::REFINE) // If the element is active and the
1237  // h refinement flag is set
1238  {
1239  const unsigned int my_level = elem->level();
1240 
1241  for (unsigned short side = 0; side != n_sides;
1242  ++side)
1243  {
1244  Elem * neighbor =
1245  topological_neighbor(elem, point_locator.get(), side);
1246 
1247  if (neighbor != nullptr && // I have a
1248  neighbor != remote_elem && // neighbor here
1249  neighbor->active()) // and it is active
1250  {
1251  // Case 1: The neighbor is at the same level I am.
1252  // 1a: The neighbor will be refined -> NO PROBLEM
1253  // 1b: The neighbor won't be refined -> NO PROBLEM
1254  // 1c: The neighbor wants to be coarsened -> PROBLEM
1255  if (neighbor->level() == my_level)
1256  {
1257  if (neighbor->refinement_flag() == Elem::COARSEN)
1258  {
1260  if (neighbor->parent())
1261  neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
1262  compatible_with_coarsening = false;
1263  level_one_satisfied = false;
1264  }
1265  }
1266 
1267 
1268  // Case 2: The neighbor is one level lower than I am.
1269  // The neighbor thus MUST be refined to satisfy
1270  // the level-one rule, regardless of whether it
1271  // was originally flagged for refinement. If it
1272  // wasn't flagged already we need to repeat
1273  // this process.
1274  else if ((neighbor->level()+1) == my_level)
1275  {
1276  if (neighbor->refinement_flag() != Elem::REFINE)
1277  {
1278  neighbor->set_refinement_flag(Elem::REFINE);
1279  if (neighbor->parent())
1280  neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
1281  compatible_with_coarsening = false;
1282  level_one_satisfied = false;
1283  }
1284  }
1285 #ifdef DEBUG
1286  // Note that the only other possibility is that the
1287  // neighbor is already refined, in which case it isn't
1288  // active and we should never get here.
1289  else
1290  libmesh_error_msg("ERROR: Neighbor level must be equal or 1 higher than mine.");
1291 #endif
1292  }
1293  }
1294  }
1295  if (elem->p_refinement_flag() == Elem::REFINE) // If the element is active and the
1296  // p refinement flag is set
1297  {
1298  const unsigned int my_p_level = elem->p_level();
1299 
1300  for (unsigned int side=0; side != n_sides; side++)
1301  {
1302  Elem * neighbor =
1303  topological_neighbor(elem, point_locator.get(), side);
1304 
1305  if (neighbor != nullptr && // I have a
1306  neighbor != remote_elem) // neighbor here
1307  {
1308  if (neighbor->active()) // and it is active
1309  {
1310  if (neighbor->p_level() < my_p_level &&
1311  neighbor->p_refinement_flag() != Elem::REFINE)
1312  {
1314  level_one_satisfied = false;
1315  compatible_with_coarsening = false;
1316  }
1317  if (neighbor->p_level() == my_p_level &&
1318  neighbor->p_refinement_flag() == Elem::COARSEN)
1319  {
1320  neighbor->set_p_refinement_flag(Elem::DO_NOTHING);
1321  level_one_satisfied = false;
1322  compatible_with_coarsening = false;
1323  }
1324  }
1325  else // I have an inactive neighbor
1326  {
1327  libmesh_assert(neighbor->has_children());
1328  for (auto & subneighbor : neighbor->child_ref_range())
1329  if (&subneighbor != remote_elem && subneighbor.active() &&
1330  has_topological_neighbor(&subneighbor, point_locator.get(), elem))
1331  {
1332  if (subneighbor.p_level() < my_p_level &&
1333  subneighbor.p_refinement_flag() != Elem::REFINE)
1334  {
1335  // We should already be level one
1336  // compatible
1337  libmesh_assert_greater (subneighbor.p_level() + 2u,
1338  my_p_level);
1339  subneighbor.set_p_refinement_flag(Elem::REFINE);
1340  level_one_satisfied = false;
1341  compatible_with_coarsening = false;
1342  }
1343  if (subneighbor.p_level() == my_p_level &&
1344  subneighbor.p_refinement_flag() == Elem::COARSEN)
1345  {
1346  subneighbor.set_p_refinement_flag(Elem::DO_NOTHING);
1347  level_one_satisfied = false;
1348  compatible_with_coarsening = false;
1349  }
1350  }
1351  }
1352  }
1353  }
1354  }
1355  }
1356  }
1357 
1358  while (!level_one_satisfied);
1359  } // end if (_face_level_mismatch_limit)
1360 
1361  // If we're not compatible on one processor, we're globally not
1362  // compatible
1363  this->comm().min(compatible_with_coarsening);
1364 
1365  return compatible_with_coarsening;
1366 }
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
bool has_topological_neighbor(const Elem *elem, const PointLocatorBase *point_locator, const Elem *neighbor) const
Local dispatch function for checking the correct has_neighbor function from the Elem class...
MeshBase & _mesh
Reference to the mesh.
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
const Parallel::Communicator & comm() const
PeriodicBoundaries * _periodic_boundaries
void min(const T &r, T &o, Request &req) const
unsigned char _face_level_mismatch_limit
libmesh_assert(ctx)
Elem * topological_neighbor(Elem *elem, const PointLocatorBase *point_locator, const unsigned int side) const
Local dispatch function for getting the correct topological neighbor from the Elem class...
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:3248
bool active() const
Definition: elem.h:2955
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ max_h_level()

unsigned int & libMesh::MeshRefinement::max_h_level ( )
inline

The max_h_level is the greatest refinement level an element should reach.

max_h_level is unlimited (libMesh::invalid_uint) by default

Definition at line 900 of file mesh_refinement.h.

References _max_h_level, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

901 {
902  _use_member_parameters = true;
903  return _max_h_level;
904 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ n_processors()

processor_id_type libMesh::ParallelObject::n_processors ( ) const
inlineinherited
Returns
The number of processors in the group.

Definition at line 103 of file parallel_object.h.

References libMesh::ParallelObject::_communicator, libMesh::libmesh_assert(), and TIMPI::Communicator::size().

Referenced by libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::BoundaryInfo::_find_id_maps(), libMesh::DofMap::add_constraints_to_send_list(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DofMap::add_neighbors_to_send_list(), libMesh::DistributedMesh::add_node(), libMesh::System::add_vector(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::Partitioner::build_graph(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::copy_nodes_and_elements(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::DofMap::distribute_dofs(), libMesh::DofMap::distribute_scalar_dofs(), libMesh::DistributedMesh::DistributedMesh(), libMesh::EnsightIO::EnsightIO(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::MeshBase::get_info(), libMesh::StaticCondensation::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_petscdm(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), libMesh::NumericVector< Number >::is_effectively_ghosted(), libMesh::NumericVector< Number >::is_effectively_serial(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >(), libMesh::MeshTools::libmesh_assert_valid_boundary_ids(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::MeshTools::libmesh_assert_valid_refinement_flags(), libMesh::DofMap::local_variable_indices(), make_coarsening_compatible(), libMesh::MeshBase::n_active_elem_on_proc(), libMesh::DofMap::n_dofs_per_processor(), libMesh::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::Partitioner::partition(), libMesh::MeshBase::partition(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::DofMap::prepare_send_list(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::CheckpointIO::read(), libMesh::CheckpointIO::read_connectivity(), libMesh::XdrIO::read_header(), libMesh::CheckpointIO::read_nodes(), libMesh::System::read_parallel_data(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::System::read_serialized_vector(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::Partitioner::repartition(), OverlappingFunctorTest::run_partitioner_test(), libMesh::DofMap::scatter_constraints(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), WriteVecAndScalar::setupTests(), libMesh::RBEIMEvaluation::side_gather_bfs(), DistributedMeshTest::testRemoteElemError(), CheckpointIOTest::testSplitter(), uniformly_coarsen(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::VTKIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::System::write_parallel_data(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

104  {
105  processor_id_type returnval =
106  cast_int<processor_id_type>(_communicator.size());
107  libmesh_assert(returnval); // We never have an empty comm
108  return returnval;
109  }
const Parallel::Communicator & _communicator
processor_id_type size() const
uint8_t processor_id_type
libmesh_assert(ctx)

◆ nelem_target()

dof_id_type & libMesh::MeshRefinement::nelem_target ( )
inline

If nelem_target is set to a nonzero value, methods like flag_elements_by_nelem_target() will attempt to keep the number of active elements in the mesh close to nelem_target.

nelem_target is 0 by default.

Definition at line 912 of file mesh_refinement.h.

References _nelem_target, and _use_member_parameters.

Referenced by main().

913 {
914  _use_member_parameters = true;
915  return _nelem_target;
916 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ node_level_mismatch_limit()

unsigned char & libMesh::MeshRefinement::node_level_mismatch_limit ( )
inline

If node_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce meshes in which the refinement level of two nodal neighbors will not differ by more than that limit.

If node_level_mismatch_limit is 0, then level differences will be unlimited.

node_level_mismatch_limit is 0 by default.

Definition at line 934 of file mesh_refinement.h.

References _node_level_mismatch_limit.

935 {
937 }
unsigned char _node_level_mismatch_limit

◆ operator=()

MeshRefinement& libMesh::MeshRefinement::operator= ( const MeshRefinement )
private

◆ overrefined_boundary_limit()

signed char & libMesh::MeshRefinement::overrefined_boundary_limit ( )
inline

If overrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will produce meshes in which the refinement level of a boundary element is no more than that many levels greater than the level of any of its interior neighbors.

This may be counter-intuitive in the 1D-embedded-in-3D case: an edge has more interior neighbors than a face containing that edge.

If overrefined_boundary_limit is negative, then level differences will be unlimited.

overrefined_boundary_limit is 0 by default. This implies that adaptive coarsening can only be done on an interior element if any boundary elements on its sides are simultaneously coarsened.

Definition at line 939 of file mesh_refinement.h.

References _overrefined_boundary_limit.

Referenced by libMesh::EquationSystems::reinit_solutions().

940 {
942 }
signed char _overrefined_boundary_limit

◆ processor_id()

processor_id_type libMesh::ParallelObject::processor_id ( ) const
inlineinherited
Returns
The rank of this processor in the group.

Definition at line 114 of file parallel_object.h.

References libMesh::ParallelObject::_communicator, and TIMPI::Communicator::rank().

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::BoundaryInfo::add_elements(), libMesh::DofMap::add_neighbors_to_send_list(), libMesh::DistributedMesh::add_node(), libMesh::MeshTools::Modification::all_tri(), libMesh::DofMap::allgather_recursive_constraints(), libMesh::FEMSystem::assembly(), libMesh::Nemesis_IO::assert_symmetric_cmaps(), libMesh::Partitioner::assign_partitioning(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::Partitioner::build_graph(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::EquationSystems::build_parallel_solution_vector(), libMesh::MeshFunction::check_found_elem(), libMesh::DistributedMesh::clear(), libMesh::DistributedMesh::clear_elems(), libMesh::ExodusII_IO_Helper::close(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::compute_communication_map_parameters(), libMesh::Nemesis_IO_Helper::compute_internal_and_border_elems_and_internal_nodes(), libMesh::RBConstruction::compute_max_error_bound(), libMesh::Nemesis_IO_Helper::compute_node_communication_maps(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::Nemesis_IO::copy_scalar_solution(), libMesh::ExodusII_IO::copy_scalar_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::create(), libMesh::DistributedMesh::delete_elem(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DofMap::distribute_dofs(), libMesh::DofMap::distribute_scalar_dofs(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DofMapBase::end_dof(), libMesh::DofMapBase::end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send(), libMesh::UnstructuredMesh::find_neighbors(), libMesh::DofMapBase::first_dof(), libMesh::DofMapBase::first_old_dof(), libMesh::RBEIMEvaluation::gather_bfs(), libMesh::Nemesis_IO_Helper::get_cmap_params(), libMesh::Nemesis_IO_Helper::get_eb_info_global(), libMesh::Nemesis_IO_Helper::get_elem_cmap(), libMesh::Nemesis_IO_Helper::get_elem_map(), libMesh::MeshBase::get_info(), libMesh::DofMap::get_info(), libMesh::Nemesis_IO_Helper::get_init_global(), libMesh::Nemesis_IO_Helper::get_init_info(), libMesh::RBEIMEvaluation::get_interior_basis_functions_as_vecs(), libMesh::Nemesis_IO_Helper::get_loadbal_param(), libMesh::DofMap::get_local_constraints(), libMesh::MeshBase::get_local_constraints(), libMesh::Nemesis_IO_Helper::get_node_cmap(), libMesh::Nemesis_IO_Helper::get_node_map(), libMesh::Nemesis_IO_Helper::get_ns_param_global(), libMesh::Nemesis_IO_Helper::get_ss_param_global(), libMesh::SparsityPattern::Build::handle_vi_vj(), libMesh::LaplaceMeshSmoother::init(), libMesh::SystemSubsetBySubdomain::init(), HeatSystem::init_data(), libMesh::ExodusII_IO_Helper::initialize(), libMesh::ExodusII_IO_Helper::initialize_element_variables(), libMesh::ExodusII_IO_Helper::initialize_global_variables(), libMesh::ExodusII_IO_Helper::initialize_nodal_variables(), libMesh::DistributedMesh::insert_elem(), libMesh::DofMap::is_evaluable(), libMesh::SparsityPattern::Build::join(), libMesh::TransientRBEvaluation::legacy_write_offline_data_to_files(), libMesh::RBSCMEvaluation::legacy_write_offline_data_to_files(), libMesh::RBEvaluation::legacy_write_offline_data_to_files(), libMesh::MeshTools::libmesh_assert_consistent_distributed(), libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes(), libMesh::MeshTools::libmesh_assert_contiguous_dof_ids(), libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_neighbors(), libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids(), libMesh::DofMap::local_variable_indices(), main(), make_coarsening_compatible(), AugmentSparsityOnInterface::mesh_reinit(), libMesh::TriangulatorInterface::MeshedHole::MeshedHole(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::MeshTools::n_connected_components(), libMesh::MeshBase::n_constraint_rows(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::DofMapBase::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::RBEIMEvaluation::node_gather_bfs(), libMesh::DistributedMesh::own_node(), libMesh::BoundaryInfo::parallel_sync_node_ids(), libMesh::BoundaryInfo::parallel_sync_side_ids(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::print_constraint_rows(), libMesh::DofMap::print_dof_constraints(), libMesh::DofMap::process_mesh_constraint_rows(), libMesh::Nemesis_IO_Helper::put_cmap_params(), libMesh::Nemesis_IO_Helper::put_elem_cmap(), libMesh::Nemesis_IO_Helper::put_elem_map(), libMesh::Nemesis_IO_Helper::put_loadbal_param(), libMesh::Nemesis_IO_Helper::put_node_cmap(), libMesh::Nemesis_IO_Helper::put_node_map(), libMesh::NameBasedIO::read(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::CheckpointIO::read(), libMesh::EquationSystems::read(), libMesh::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::ExodusII_IO::read_header(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::DynaIO::read_mesh(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_data(), libMesh::TransientRBConstruction::read_riesz_representors_from_files(), libMesh::RBConstruction::read_riesz_representors_from_files(), libMesh::System::read_SCALAR_dofs(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs_helper(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::System::read_serialized_data(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::System::read_serialized_vectors(), libMesh::Nemesis_IO_Helper::read_var_names_impl(), libMesh::SimplexRefiner::refine_via_edges(), libMesh::StaticCondensationDofMap::reinit(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::DistributedMesh::renumber_nodes_and_elements(), libMesh::DofMap::scatter_constraints(), libMesh::CheckpointIO::select_split_config(), libMesh::DistributedMesh::set_next_unique_id(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::RBEIMEvaluation::side_gather_bfs(), MeshFunctionTest::test_bad_gradient_var_with_out_of_mesh_value(), MeshFunctionTest::test_bad_hessian_var_with_out_of_mesh_value(), ExodusTest< elem_type >::test_read_gold(), ExodusTest< elem_type >::test_write(), MeshInputTest::testAbaqusRead(), MeshInputTest::testBadGmsh(), BoundaryInfoTest::testBoundaryIDs(), MeshInputTest::testCopyElementSolutionImpl(), MeshInputTest::testCopyElementVectorImpl(), MeshInputTest::testCopyNodalSolutionImpl(), DefaultCouplingTest::testCoupling(), PointNeighborCouplingTest::testCoupling(), MeshInputTest::testDynaFileMappings(), MeshInputTest::testDynaNoSplines(), MeshInputTest::testDynaReadElem(), MeshInputTest::testDynaReadPatch(), MeshInputTest::testExodusFileMappings(), MeshInputTest::testExodusIGASidesets(), MeshInputTest::testExodusWriteElementDataFromDiscontinuousNodalData(), MeshInputTest::testGmshBCIDOverlap(), MeshInputTest::testGoodGmsh(), MeshInputTest::testGoodSTL(), MeshInputTest::testGoodSTLBinary(), BoundaryInfoTest::testInternalBoundary(), MeshInputTest::testLowOrderEdgeBlocks(), SystemsTest::testProjectMatrix3D(), BoundaryInfoTest::testShellFaceConstraints(), MeshInputTest::testSingleElementImpl(), WriteVecAndScalar::testSolution(), CheckpointIOTest::testSplitter(), MeshInputTest::testTetgenIO(), MeshSmootherTest::testVariationalSmoother(), libMesh::MeshTools::total_weight(), libMesh::NetGenMeshInterface::triangulate(), uniformly_coarsen(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::DTKAdapter::update_variable_values(), libMesh::MeshTools::volume(), libMesh::STLIO::write(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), libMesh::CheckpointIO::write(), libMesh::EquationSystems::write(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::ExodusII_IO_Helper::write_element_values(), libMesh::ExodusII_IO_Helper::write_element_values_element_major(), libMesh::ExodusII_IO_Helper::write_elements(), libMesh::ExodusII_IO_Helper::write_elemset_data(), libMesh::ExodusII_IO_Helper::write_elemsets(), libMesh::ExodusII_IO::write_global_data(), libMesh::ExodusII_IO_Helper::write_global_values(), libMesh::System::write_header(), libMesh::ExodusII_IO::write_information_records(), libMesh::ExodusII_IO_Helper::write_information_records(), libMesh::ExodusII_IO_Helper::write_nodal_coordinates(), libMesh::UCDIO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::ExodusII_IO_Helper::write_nodeset_data(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::RBEIMEvaluation::write_out_interior_basis_functions(), libMesh::RBEIMEvaluation::write_out_node_basis_functions(), libMesh::RBEIMEvaluation::write_out_side_basis_functions(), write_output_solvedata(), libMesh::System::write_parallel_data(), libMesh::RBConstruction::write_riesz_representors_to_files(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bc_names(), libMesh::XdrIO::write_serialized_bcs_helper(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::System::write_serialized_data(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::System::write_serialized_vector(), libMesh::System::write_serialized_vectors(), libMesh::ExodusII_IO_Helper::write_sideset_data(), libMesh::Nemesis_IO_Helper::write_sidesets(), libMesh::ExodusII_IO_Helper::write_sidesets(), libMesh::ExodusII_IO::write_timestep(), libMesh::ExodusII_IO_Helper::write_timestep(), and libMesh::ExodusII_IO::write_timestep_discontinuous().

115  { return cast_int<processor_id_type>(_communicator.rank()); }
processor_id_type rank() const
const Parallel::Communicator & _communicator

◆ refine_and_coarsen_elements()

bool libMesh::MeshRefinement::refine_and_coarsen_elements ( )

Refines and coarsens user-requested elements.

Will also refine/coarsen additional elements to satisfy level-one rule. It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the mesh actually changed (hence data needs to be projected) and false otherwise.
Note
This function used to take an argument, maintain_level_one. New code should use face_level_mismatch_limit() instead.

Definition at line 482 of file mesh_refinement.C.

References _coarsen_elements(), _face_level_mismatch_limit, _mesh, _refine_elements(), _smooth_flags(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_stored_range(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, libMesh::libmesh_assert(), libMesh::MeshBase::libmesh_assert_valid_parallel_ids(), make_coarsening_compatible(), make_flags_parallel_consistent(), make_refinement_compatible(), TIMPI::Communicator::max(), libMesh::Threads::parallel_for(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::REFINE, test_level_one(), and test_unflagged().

Referenced by assemble_and_solve(), MixedDimensionNonUniformRefinement::build_mesh(), MixedDimensionNonUniformRefinementTriangle::build_mesh(), MixedDimensionNonUniformRefinement3D::build_mesh(), and main().

483 {
484  // This function must be run on all processors at once
485  parallel_object_only();
486 
487  // We can't yet turn a non-level-one mesh into a level-one mesh
490 
491  // Possibly clean up the refinement flags from
492  // a previous step. While we're at it, see if this method should be
493  // a no-op.
494  std::atomic<bool> elements_flagged{false};
495 
498  [&elements_flagged](const ElemRange & range)
499  {
500  for (Elem * elem : range)
501  {
502  // This might be left over from the last step
503  const Elem::RefinementState flag = elem->refinement_flag();
504 
505  // Set refinement flag to INACTIVE if the
506  // element isn't active
507  if (!elem->active())
508  {
509  elem->set_refinement_flag(Elem::INACTIVE);
510  elem->set_p_refinement_flag(Elem::INACTIVE);
511  }
512  else if (flag == Elem::JUST_REFINED)
513  elem->set_refinement_flag(Elem::DO_NOTHING);
514  else if (!elements_flagged)
515  {
516  if (flag == Elem::REFINE || flag == Elem::COARSEN)
517  elements_flagged = true;
518  else
519  {
520  const Elem::RefinementState pflag =
521  elem->p_refinement_flag();
522  if (pflag == Elem::REFINE || pflag == Elem::COARSEN)
523  elements_flagged = true;
524  }
525  }
526  }
527  });
528 
529  // Did *any* processor find elements flagged for AMR/C?
530  bool any_elements_flagged = elements_flagged;
531  _mesh.comm().max(any_elements_flagged);
532 
533  // If we have nothing to do, let's not bother verifying that nothing
534  // is compatible with nothing.
535  if (!any_elements_flagged)
536  return false;
537 
538  // Parallel consistency has to come first, or coarsening
539  // along processor boundaries might occasionally be falsely
540  // prevented
541 #ifdef DEBUG
542  bool flags_were_consistent = this->make_flags_parallel_consistent();
543 
544  libmesh_assert (flags_were_consistent);
545 #endif
546 
547  // Smooth refinement and coarsening flags
548  _smooth_flags(true, true);
549 
550  // First coarsen the flagged elements.
551  const bool coarsening_changed_mesh =
552  this->_coarsen_elements ();
553 
554  // First coarsen the flagged elements.
555  // FIXME: test_level_one now tests consistency across periodic
556  // boundaries, which requires a point_locator, which just got
557  // invalidated by _coarsen_elements() and hasn't yet been cleared by
558  // prepare_for_use().
559 
560  // libmesh_assert(this->make_coarsening_compatible());
561  // libmesh_assert(this->make_refinement_compatible());
562 
563  // FIXME: This won't pass unless we add a redundant find_neighbors()
564  // call or replace find_neighbors() with on-the-fly neighbor updating
565  // libmesh_assert(!this->eliminate_unrefined_patches());
566 
567  // We can't contract the mesh ourselves anymore - a System might
568  // need to restrict old coefficient vectors first
569  // _mesh.contract();
570 
571  // First coarsen the flagged elements.
572  // Now refine the flagged elements. This will
573  // take up some space, maybe more than what was freed.
574  const bool refining_changed_mesh =
575  this->_refine_elements();
576 
577  // First coarsen the flagged elements.
578  // Finally, the new mesh needs to be prepared for use
579  if (coarsening_changed_mesh || refining_changed_mesh)
580  {
581 #ifdef DEBUG
583 #endif
584 
586 
592  // FIXME: This won't pass unless we add a redundant find_neighbors()
593  // call or replace find_neighbors() with on-the-fly neighbor updating
594  // libmesh_assert(!this->eliminate_unrefined_patches());
595 
596  return true;
597  }
598  else
599  {
605  }
606 
607  // Otherwise there was no change in the mesh,
608  // let the user know. Also, there is no need
609  // to prepare the mesh for use since it did not change.
610  return false;
611 
612 }
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.
Definition: threads_none.h:73
StoredRange< MeshBase::element_iterator, Elem * > ElemRange
Definition: elem_range.h:31
bool _refine_elements()
Refines user-requested elements.
bool test_level_one(bool libmesh_assert_yes=false) const
MeshBase & _mesh
Reference to the mesh.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
RefinementState
Enumeration of possible element refinement states.
Definition: elem.h:1443
const Parallel::Communicator & comm() const
bool make_refinement_compatible()
Take user-specified refinement flags and augment them so that level-one dependency is satisfied...
unsigned char _face_level_mismatch_limit
const ElemRange & element_stored_range()
Definition: mesh_base.C:1913
libmesh_assert(ctx)
bool test_unflagged(bool libmesh_assert_yes=false) const
bool make_flags_parallel_consistent()
Copy refinement flags on ghost elements from their local processors.
bool make_coarsening_compatible()
Take user-specified coarsening flags and augment them so that level-one dependency is satisfied...
void max(const T &r, T &o, Request &req) const
void _smooth_flags(bool refining, bool coarsening)
Smooths refinement flags according to current settings.
virtual void libmesh_assert_valid_parallel_ids() const
Verify id and processor_id consistency of our elements and nodes containers.
Definition: mesh_base.h:1688
bool _coarsen_elements()
Coarsens user-requested elements.

◆ refine_elements()

bool libMesh::MeshRefinement::refine_elements ( )

Only refines the user-requested elements.

It is possible that for a given set of refinement flags there is actually no change upon calling this member function.

Returns
true if the mesh actually changed (hence data needs to be projected) and false otherwise.
Note
This function used to take an argument, maintain_level_one, new code should use face_level_mismatch_limit() instead.

Definition at line 699 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _refine_elements(), _smooth_flags(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_stored_range(), libMesh::MeshBase::get_disjoint_neighbor_boundary_pairs(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, libMesh::libmesh_assert(), make_flags_parallel_consistent(), make_refinement_compatible(), libMesh::Threads::parallel_for(), libMesh::MeshBase::prepare_for_use(), and test_level_one().

Referenced by DisjointNeighborTest::build_split_mesh_with_interface(), main(), libMesh::EquationSystems::reinit_solutions(), BoundaryInfoTest::testBoundaryOnChildrenBoundaryIDs(), BoundaryInfoTest::testBoundaryOnChildrenBoundarySides(), BoundaryInfoTest::testBoundaryOnChildrenElementsRefineCoarsen(), BoundaryInfoTest::testBoundaryOnChildrenErrors(), InfFERadialTest::testRefinement(), EquationSystemsTest::testRefineThenReinitPreserveFlags(), and EquationSystemsTest::testSelectivePRefine().

700 {
701  // This function must be run on all processors at once
702  parallel_object_only();
703 
704  // Prevent refinement when the mesh has disjoint neighbor boundary pairs.
705  //
706  // Disjoint neighbor boundary interfaces violate the topological continuity
707  // assumed by the refinement algorithm. Refinement on such meshes can
708  // produce invalid neighbor relationships (for example reverse indices
709  // equal to invalid_uint), which may trigger assertions like
710  // `rev < neigh->n_neighbors()` or corrupt neighbor data.
711  //
712  // For safety, refinement is disabled while disjoint neighbor boundary pairs are
713  // present.
715  {
716  libmesh_not_implemented_msg(
717  "Mesh refinement is not yet implemented for meshes with disjoint neighbor boundary interfaces.\n");
718  }
719 
722 
723  // Possibly clean up the refinement flags from
724  // a previous step
727  [](const ElemRange & range)
728  {
729  for (Elem * elem : range)
730  {
731  // Set refinement flag to INACTIVE if the
732  // element isn't active
733  if (!elem->active())
734  {
735  elem->set_refinement_flag(Elem::INACTIVE);
736  elem->set_p_refinement_flag(Elem::INACTIVE);
737  }
738 
739  // This might be left over from the last step
740  if (elem->refinement_flag() == Elem::JUST_REFINED)
741  elem->set_refinement_flag(Elem::DO_NOTHING);
742  }
743  });
744 
745  // Parallel consistency has to come first, or coarsening
746  // along processor boundaries might occasionally be falsely
747  // prevented
748  bool flags_were_consistent = this->make_flags_parallel_consistent();
749 
750  // In theory, we should be able to remove the above call, which can
751  // be expensive and should be unnecessary. In practice, doing
752  // consistent flagging in parallel is hard, it's impossible to
753  // verify at the library level if it's being done by user code, and
754  // we don't want to abort large parallel runs in opt mode... but we
755  // do want to warn that they should be fixed.
756  libmesh_assert(flags_were_consistent);
757 
758  if (!flags_were_consistent)
759  libmesh_warning("Warning: Refinement flags were not consistent between processors! "
760  "Correcting and continuing.\n");
761 
762  // Smooth refinement flags
763  _smooth_flags(true, false);
764 
765  // Now refine the flagged elements. This will
766  // take up some space, maybe more than what was freed.
767  const bool mesh_changed =
768  this->_refine_elements();
769 
773 
774  // FIXME: This won't pass unless we add a redundant find_neighbors()
775  // call or replace find_neighbors() with on-the-fly neighbor updating
776  // libmesh_assert(!this->eliminate_unrefined_patches());
777 
778  // Finally, the new mesh needs to be prepared for use
779  if (mesh_changed)
781 
782  return mesh_changed;
783 }
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.
Definition: threads_none.h:73
StoredRange< MeshBase::element_iterator, Elem * > ElemRange
Definition: elem_range.h:31
bool _refine_elements()
Refines user-requested elements.
bool test_level_one(bool libmesh_assert_yes=false) const
MeshBase & _mesh
Reference to the mesh.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
bool make_refinement_compatible()
Take user-specified refinement flags and augment them so that level-one dependency is satisfied...
unsigned char _face_level_mismatch_limit
const ElemRange & element_stored_range()
Definition: mesh_base.C:1913
PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs()
Definition: mesh_base.C:2256
libmesh_assert(ctx)
bool make_flags_parallel_consistent()
Copy refinement flags on ghost elements from their local processors.
void _smooth_flags(bool refining, bool coarsening)
Smooths refinement flags according to current settings.

◆ refine_fraction()

Real & libMesh::MeshRefinement::refine_fraction ( )
inline

The refine_fraction sets either a desired target or a desired maximum number of elements to flag for refinement, depending on which flag_elements_by method is called.

refine_fraction must be in \( [0,1] \), and is 0.3 by default.

Definition at line 888 of file mesh_refinement.h.

References _refine_fraction, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

889 {
890  _use_member_parameters = true;
891  return _refine_fraction;
892 }
bool _use_member_parameters
For backwards compatibility, we initialize this as false and then set it to true if the user uses any...

◆ set_periodic_boundaries_ptr()

void libMesh::MeshRefinement::set_periodic_boundaries_ptr ( PeriodicBoundaries pb_ptr)

Sets the PeriodicBoundaries pointer.

Referenced by main().

◆ switch_h_to_p_refinement()

void libMesh::MeshRefinement::switch_h_to_p_refinement ( )

Takes a mesh whose elements are flagged for h refinement and coarsening, and switches those flags to request p refinement and coarsening instead.

Definition at line 654 of file mesh_refinement_flagging.C.

References _mesh, libMesh::Elem::DO_NOTHING, and libMesh::Elem::INACTIVE.

Referenced by main(), and EquationSystemsTest::testSelectivePRefine().

655 {
656  for (auto & elem : _mesh.element_ptr_range())
657  {
658  if (elem->active())
659  {
660  elem->set_p_refinement_flag(elem->refinement_flag());
661  elem->set_refinement_flag(Elem::DO_NOTHING);
662  }
663  else
664  {
665  elem->set_p_refinement_flag(elem->refinement_flag());
666  elem->set_refinement_flag(Elem::INACTIVE);
667  }
668  }
669 }
MeshBase & _mesh
Reference to the mesh.

◆ test_level_one()

bool libMesh::MeshRefinement::test_level_one ( bool  libmesh_assert_yes = false) const
Returns
true if the mesh satisfies the level one restriction, and false otherwise.

Aborts the program if libmesh_assert_yes is true and the mesh does not satisfy the level one restriction.

Definition at line 359 of file mesh_refinement.C.

References _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::ParallelObject::comm(), libMesh::Elem::level(), libMesh::libmesh_assert(), TIMPI::Communicator::max(), libMesh::out, libMesh::Elem::p_level(), libMesh::remote_elem, libMesh::MeshBase::sub_point_locator(), and topological_neighbor().

Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().

360 {
361  // This function must be run on all processors at once
362  parallel_object_only();
363 
364  // We may need a PointLocator for topological_neighbor() tests
365  // later, which we need to make sure gets constructed on all
366  // processors at once.
367  std::unique_ptr<PointLocatorBase> point_locator;
368 
369 #ifdef LIBMESH_ENABLE_PERIODIC
370  bool has_periodic_boundaries =
372  libmesh_assert(this->comm().verify(has_periodic_boundaries));
373 
374  if (has_periodic_boundaries)
375  point_locator = _mesh.sub_point_locator();
376 #endif
377 
378  bool failure = false;
379 
380 #ifndef NDEBUG
381  Elem * failed_elem = nullptr;
382  Elem * failed_neighbor = nullptr;
383 #endif // !NDEBUG
384 
385  for (auto & elem : _mesh.active_local_element_ptr_range())
386  for (auto n : elem->side_index_range())
387  {
388  Elem * neighbor =
389  topological_neighbor(elem, point_locator.get(), n);
390 
391  if (!neighbor || !neighbor->active() ||
392  neighbor == remote_elem)
393  continue;
394 
395  if ((neighbor->level() + 1 < elem->level()) ||
396  (neighbor->p_level() + 1 < elem->p_level()) ||
397  (neighbor->p_level() > elem->p_level() + 1))
398  {
399  failure = true;
400 #ifndef NDEBUG
401  failed_elem = elem;
402  failed_neighbor = neighbor;
403 #endif // !NDEBUG
404  break;
405  }
406  }
407 
408  // If any processor failed, we failed globally
409  this->comm().max(failure);
410 
411  if (failure)
412  {
413  // We didn't pass the level one test, so libmesh_assert that
414  // we're allowed not to
415 #ifndef NDEBUG
416  if (libmesh_assert_pass)
417  {
418  libMesh::out << "MeshRefinement Level one failure, element: "
419  << *failed_elem
420  << std::endl;
421  libMesh::out << "MeshRefinement Level one failure, neighbor: "
422  << *failed_neighbor
423  << std::endl;
424  }
425 #endif // !NDEBUG
426  libmesh_assert(!libmesh_assert_pass);
427  return false;
428  }
429  return true;
430 }
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
PeriodicBoundaries * _periodic_boundaries
libmesh_assert(ctx)
void max(const T &r, T &o, Request &req) const
OStreamProxy out
Elem * topological_neighbor(Elem *elem, const PointLocatorBase *point_locator, const unsigned int side) const
Local dispatch function for getting the correct topological neighbor from the Elem class...
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ test_unflagged()

bool libMesh::MeshRefinement::test_unflagged ( bool  libmesh_assert_yes = false) const
Returns
true if the mesh has no elements flagged to be coarsened or refined, and false otherwise.

Aborts the program if libmesh_assert_yes is true and the mesh has flagged elements.

Definition at line 434 of file mesh_refinement.C.

References _mesh, libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), libMesh::libmesh_assert(), TIMPI::Communicator::max(), libMesh::out, and libMesh::Elem::REFINE.

Referenced by refine_and_coarsen_elements().

435 {
436  // This function must be run on all processors at once
437  parallel_object_only();
438 
439  bool found_flag = false;
440 
441 #ifndef NDEBUG
442  Elem * failed_elem = nullptr;
443 #endif
444 
445  // Search for local flags
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)
451  {
452  found_flag = true;
453 #ifndef NDEBUG
454  failed_elem = elem;
455 #endif
456  break;
457  }
458 
459  // If we found a flag on any processor, it counts
460  this->comm().max(found_flag);
461 
462  if (found_flag)
463  {
464 #ifndef NDEBUG
465  if (libmesh_assert_pass)
466  {
467  libMesh::out <<
468  "MeshRefinement test_unflagged failure, element: " <<
469  *failed_elem << std::endl;
470  }
471 #endif
472  // We didn't pass the "elements are unflagged" test,
473  // so libmesh_assert that we're allowed not to
474  libmesh_assert(!libmesh_assert_pass);
475  return false;
476  }
477  return true;
478 }
MeshBase & _mesh
Reference to the mesh.
const Parallel::Communicator & comm() const
libmesh_assert(ctx)
void max(const T &r, T &o, Request &req) const
OStreamProxy out

◆ topological_neighbor()

Elem * libMesh::MeshRefinement::topological_neighbor ( Elem elem,
const PointLocatorBase point_locator,
const unsigned int  side 
) const
private

Local dispatch function for getting the correct topological neighbor from the Elem class.

Definition at line 1833 of file mesh_refinement.C.

References _mesh, _periodic_boundaries, libMesh::libmesh_assert(), libMesh::Elem::neighbor_ptr(), and libMesh::Elem::topological_neighbor().

Referenced by make_coarsening_compatible(), make_refinement_compatible(), and test_level_one().

1836 {
1837 #ifdef LIBMESH_ENABLE_PERIODIC
1838  if (_periodic_boundaries && !_periodic_boundaries->empty())
1839  {
1840  libmesh_assert(point_locator);
1841  return elem->topological_neighbor(side, _mesh, *point_locator, _periodic_boundaries);
1842  }
1843 #endif
1844  return elem->neighbor_ptr(side);
1845 }
MeshBase & _mesh
Reference to the mesh.
PeriodicBoundaries * _periodic_boundaries
libmesh_assert(ctx)

◆ underrefined_boundary_limit()

signed char & libMesh::MeshRefinement::underrefined_boundary_limit ( )
inline

If underrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will produce meshes in which the refinement level of an element is no more than that many levels greater than the level of any boundary elements on its sides.

If underrefined_boundary_limit is negative, then level differences will be unlimited.

underrefined_boundary_limit is 0 by default. This implies that adaptive coarsening can only be done on a boundary element if any interior elements it is on the side of are simultaneously coarsened.

Definition at line 944 of file mesh_refinement.h.

References _underrefined_boundary_limit.

Referenced by libMesh::EquationSystems::reinit_solutions().

945 {
947 }
signed char _underrefined_boundary_limit

◆ uniformly_coarsen()

void libMesh::MeshRefinement::uniformly_coarsen ( unsigned int  n = 1)

Attempts to uniformly coarsen the mesh n times.

Definition at line 1745 of file mesh_refinement.C.

References _coarsen_elements(), _mesh, libMesh::as_range(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::MeshBase::elem_ref(), TIMPI::Communicator::get_unique_tag(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_replicated(), libMesh::libmesh_assert(), libMesh::ParallelObject::n_processors(), libMesh::MeshBase::prepare_for_use(), libMesh::ParallelObject::processor_id(), TIMPI::Communicator::receive(), libMesh::Elem::refinement_flag(), TIMPI::Communicator::send(), libMesh::Elem::set_refinement_flag(), and libMesh::Parallel::sync_dofobject_data_by_id().

Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), and libMesh::PetscDMWrapper::init_petscdm().

1746 {
1747  // Coarsen n times
1748  for (unsigned int rstep=0; rstep<n; rstep++)
1749  {
1750  // Clean up the refinement flags
1751  this->clean_refinement_flags();
1752 
1753  // Flag all the active elements for coarsening.
1754  for (auto & elem : _mesh.active_element_ptr_range())
1755  {
1756  elem->set_refinement_flag(Elem::COARSEN);
1757  if (elem->parent())
1758  elem->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
1759  }
1760 
1761  // On a distributed mesh, we may have parent elements with
1762  // remote active children. To keep flags consistent, we'll need
1763  // a communication step.
1764  if (!_mesh.is_replicated())
1765  {
1766  const processor_id_type n_proc = _mesh.n_processors();
1767  const processor_id_type my_proc_id = _mesh.processor_id();
1768 
1769  std::vector<std::vector<dof_id_type>>
1770  parents_to_coarsen(n_proc);
1771 
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());
1776 
1777  Parallel::MessageTag
1778  coarsen_tag = this->comm().get_unique_tag();
1779  std::vector<Parallel::Request> coarsen_push_requests(n_proc-1);
1780 
1781  for (processor_id_type p = 0; p != n_proc; ++p)
1782  {
1783  if (p == my_proc_id)
1784  continue;
1785 
1786  Parallel::Request &request =
1787  coarsen_push_requests[p - (p > my_proc_id)];
1788 
1789  _mesh.comm().send
1790  (p, parents_to_coarsen[p], request, coarsen_tag);
1791  }
1792 
1793  for (processor_id_type p = 1; p != n_proc; ++p)
1794  {
1795  std::vector<dof_id_type> my_parents_to_coarsen;
1796  _mesh.comm().receive
1797  (Parallel::any_source, my_parents_to_coarsen,
1798  coarsen_tag);
1799 
1800  for (const auto & id : my_parents_to_coarsen)
1801  {
1802  Elem & elem = _mesh.elem_ref(id);
1803  libmesh_assert(elem.refinement_flag() == Elem::INACTIVE ||
1804  elem.refinement_flag() == Elem::COARSEN_INACTIVE);
1805  elem.set_refinement_flag(Elem::COARSEN_INACTIVE);
1806  }
1807  }
1808 
1809  Parallel::wait(coarsen_push_requests);
1810 
1811  SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
1814  (this->comm(), _mesh.not_local_elements_begin(),
1815  _mesh.not_local_elements_end(),
1816  // We'd like a smaller sync, but this leads to bugs?
1817  // SyncCoarsenInactive(),
1818  hsync);
1819  }
1820 
1821  // Coarsen all the elements we just flagged.
1822  this->_coarsen_elements();
1823  }
1824 
1825 
1826  // Finally, the new mesh probably needs to be prepared for use
1827  if (n > 0)
1829 }
RefinementState refinement_flag() const
Definition: elem.h:3224
MPI_Request request
MeshBase & _mesh
Reference to the mesh.
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
const Parallel::Communicator & comm() const
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.
uint8_t processor_id_type
processor_id_type n_processors() const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libmesh_assert(ctx)
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
virtual bool is_replicated() const
Definition: mesh_base.h:369
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:778
bool _coarsen_elements()
Coarsens user-requested elements.
processor_id_type processor_id() const

◆ uniformly_p_coarsen()

void libMesh::MeshRefinement::uniformly_p_coarsen ( unsigned int  n = 1)

Attempts to uniformly p coarsen the mesh n times.

Definition at line 1705 of file mesh_refinement.C.

References _mesh, and libMesh::Elem::JUST_COARSENED.

Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), and libMesh::AdjointRefinementEstimator::estimate_error().

1706 {
1707  // Coarsen p times
1708  for (unsigned int rstep=0; rstep<n; rstep++)
1709  for (auto & elem : _mesh.active_element_ptr_range())
1710  if (elem->p_level() > 0)
1711  {
1712  // P coarsen all the active elements
1713  elem->set_p_level(elem->p_level()-1);
1714  elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1715  }
1716 }
MeshBase & _mesh
Reference to the mesh.

◆ uniformly_p_refine()

void libMesh::MeshRefinement::uniformly_p_refine ( unsigned int  n = 1)

Uniformly p refines the mesh n times.

Definition at line 1691 of file mesh_refinement.C.

References _mesh, and libMesh::Elem::JUST_REFINED.

Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), and main().

1692 {
1693  // Refine n times
1694  for (unsigned int rstep=0; rstep<n; rstep++)
1695  for (auto & elem : _mesh.active_element_ptr_range())
1696  {
1697  // P refine all the active elements
1698  elem->set_p_level(elem->p_level()+1);
1699  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1700  }
1701 }
MeshBase & _mesh
Reference to the mesh.

◆ uniformly_refine()

void libMesh::MeshRefinement::uniformly_refine ( unsigned int  n = 1)

Uniformly refines the mesh n times.

Definition at line 1720 of file mesh_refinement.C.

References _mesh, _refine_elements(), clean_refinement_flags(), libMesh::MeshBase::prepare_for_use(), and libMesh::Elem::REFINE.

Referenced by libMesh::UniformRefinementEstimator::_estimate_error(), OverlappingTestBase::build_quad_mesh(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::PetscDMWrapper::init_petscdm(), main(), OverlappingFunctorTest::run_coupling_functor_test(), OverlappingFunctorTest::run_partitioner_test(), MixedDimensionRefinedMeshTest::setUp(), SlitMeshRefinedMeshTest::setUp(), SlitMeshRefinedSystemTest::setUp(), BoundaryRefinedMeshTest::setUp(), BoundaryOfRefinedMeshTest::setUp(), ExtraIntegersTest::test_helper(), ElemTest< elem_type >::test_n_refinements(), SystemsTest::testProjectMatrix1D(), SystemsTest::testProjectMatrix2D(), and SystemsTest::testProjectMatrix3D().

1721 {
1722  // Refine n times
1723  // FIXME - this won't work if n>1 and the mesh
1724  // has already been attached to an equation system
1725  for (unsigned int rstep=0; rstep<n; rstep++)
1726  {
1727  // Clean up the refinement flags
1728  this->clean_refinement_flags();
1729 
1730  // Flag all the active elements for refinement.
1731  for (auto & elem : _mesh.active_element_ptr_range())
1732  elem->set_refinement_flag(Elem::REFINE);
1733 
1734  // Refine all the elements we just flagged.
1735  this->_refine_elements();
1736  }
1737 
1738  // Finally, the new mesh probably needs to be prepared for use
1739  if (n > 0)
1741 }
bool _refine_elements()
Refines user-requested elements.
MeshBase & _mesh
Reference to the mesh.
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.

◆ update_nodes_map()

void libMesh::MeshRefinement::update_nodes_map ( )
private

Updates the _new_nodes_map.

Definition at line 352 of file mesh_refinement.C.

References _mesh, _new_nodes_map, and libMesh::TopologyMap::init().

Referenced by _coarsen_elements(), and _refine_elements().

353 {
354  this->_new_nodes_map.init(_mesh);
355 }
TopologyMap _new_nodes_map
Data structure that holds the new nodes information.
MeshBase & _mesh
Reference to the mesh.
void init(MeshBase &)
Definition: topology_map.C:36

Member Data Documentation

◆ _absolute_global_tolerance

Real libMesh::MeshRefinement::_absolute_global_tolerance
private

◆ _allow_unrefined_patches

bool libMesh::MeshRefinement::_allow_unrefined_patches
private

Definition at line 786 of file mesh_refinement.h.

Referenced by allow_unrefined_patches(), and eliminate_unrefined_patches().

◆ _coarsen_by_parents

bool libMesh::MeshRefinement::_coarsen_by_parents
private

◆ _coarsen_fraction

Real libMesh::MeshRefinement::_coarsen_fraction
private

◆ _coarsen_threshold

Real libMesh::MeshRefinement::_coarsen_threshold
private

◆ _communicator

const Parallel::Communicator& libMesh::ParallelObject::_communicator
protectedinherited

◆ _edge_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_edge_level_mismatch_limit
private

Definition at line 780 of file mesh_refinement.h.

Referenced by _smooth_flags(), and edge_level_mismatch_limit().

◆ _enforce_mismatch_limit_prior_to_refinement

bool libMesh::MeshRefinement::_enforce_mismatch_limit_prior_to_refinement
private


This option enforces the mismatch level prior to refinement by checking if refining any element marked for refinement would cause a mismatch greater than the limit.

Applies to all mismatch methods.

Calling this with node_level_mismatch_limit() = 1 would transform this mesh:

* o-------o-------o-------o-------o
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* o-------o---o---o-------o-------o
* |       |   :   |       |       |
* |       |   :   |       |       |
* |       o...o...o       |       |
* |       |   :   |       |       |
* |       |   :   |       |       |
* o-------o---o---o-------o-------o
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* o-------o-------o               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* |       |       |               |
* o-------o-------o---------------o
* 

into this:

* o-------o-------o-------o-------o
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* o-------o-------o-------o-------o
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* |       |       |       |       |
* o-------o-------o-------o-------o
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* o-------o-------o.......o.......o
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* |       |       |       :       |
* o-------o-------o-------o-------o
* 

by moving the refinement flag to the indicated element.

Default value is false.

Definition at line 856 of file mesh_refinement.h.

Referenced by enforce_mismatch_limit_prior_to_refinement(), limit_level_mismatch_at_edge(), and limit_level_mismatch_at_node().

◆ _face_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_face_level_mismatch_limit
private

◆ _max_h_level

unsigned int libMesh::MeshRefinement::_max_h_level
private

◆ _mesh

MeshBase& libMesh::MeshRefinement::_mesh
private

◆ _nelem_target

dof_id_type libMesh::MeshRefinement::_nelem_target
private

Definition at line 775 of file mesh_refinement.h.

Referenced by flag_elements_by_nelem_target(), and nelem_target().

◆ _new_nodes_map

TopologyMap libMesh::MeshRefinement::_new_nodes_map
private

Data structure that holds the new nodes information.

Definition at line 747 of file mesh_refinement.h.

Referenced by add_node(), clear(), and update_nodes_map().

◆ _node_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_node_level_mismatch_limit
private

Definition at line 781 of file mesh_refinement.h.

Referenced by _smooth_flags(), and node_level_mismatch_limit().

◆ _overrefined_boundary_limit

signed char libMesh::MeshRefinement::_overrefined_boundary_limit
private

Definition at line 783 of file mesh_refinement.h.

Referenced by _smooth_flags(), and overrefined_boundary_limit().

◆ _periodic_boundaries

PeriodicBoundaries* libMesh::MeshRefinement::_periodic_boundaries
private

◆ _refine_fraction

Real libMesh::MeshRefinement::_refine_fraction
private

◆ _underrefined_boundary_limit

signed char libMesh::MeshRefinement::_underrefined_boundary_limit
private

Definition at line 784 of file mesh_refinement.h.

Referenced by _smooth_flags(), and underrefined_boundary_limit().

◆ _use_member_parameters

bool libMesh::MeshRefinement::_use_member_parameters
private

For backwards compatibility, we initialize this as false and then set it to true if the user uses any of the refinement parameter accessor functions.

Definition at line 759 of file mesh_refinement.h.

Referenced by absolute_global_tolerance(), coarsen_by_parents(), coarsen_fraction(), coarsen_threshold(), flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_mean_stddev(), max_h_level(), nelem_target(), and refine_fraction().


The documentation for this class was generated from the following files: