libMesh::MeshRefinement Class Reference

Responsible for mesh refinement algorithms and data. More...

#include <mesh_refinement.h>

Inheritance diagram for libMesh::MeshRefinement:

Classes

class  ElementFlagging
 

Public Member Functions

 MeshRefinement (MeshBase &mesh)
 
void set_periodic_boundaries_ptr (PeriodicBoundaries *pb_ptr)
 
 ~MeshRefinement ()
 
void clear ()
 
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)
 
void flag_elements_by_error_tolerance (const ErrorVector &error_per_cell)
 
bool flag_elements_by_nelem_target (const ErrorVector &error_per_cell)
 
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)
 
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)
 
void flag_elements_by (ElementFlagging &element_flagging)
 
void switch_h_to_p_refinement ()
 
void add_p_to_h_refinement ()
 
bool refine_and_coarsen_elements ()
 
bool coarsen_elements ()
 
bool refine_elements ()
 
void uniformly_refine (unsigned int n=1)
 
void uniformly_coarsen (unsigned int n=1)
 
void uniformly_p_refine (unsigned int n=1)
 
void uniformly_p_coarsen (unsigned int n=1)
 
void clean_refinement_flags ()
 
bool test_level_one (bool libmesh_assert_yes=false)
 
bool test_unflagged (bool libmesh_assert_yes=false)
 
Nodeadd_node (Elem &parent, unsigned int child, unsigned int node, processor_id_type proc_id)
 
Elemadd_elem (Elem *elem)
 
const MeshBaseget_mesh () const
 
MeshBaseget_mesh ()
 
bool & coarsen_by_parents ()
 
Realrefine_fraction ()
 
Realcoarsen_fraction ()
 
unsigned int & max_h_level ()
 
Realcoarsen_threshold ()
 
dof_id_typenelem_target ()
 
Realabsolute_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 make_flags_parallel_consistent ()
 
bool get_enforce_mismatch_limit_prior_to_refinement ()
 
void set_enforce_mismatch_limit_prior_to_refinement (bool enforce)
 
bool & enforce_mismatch_limit_prior_to_refinement ()
 
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 }
 

Private Member Functions

 MeshRefinement (const MeshRefinement &)
 
MeshRefinementoperator= (const MeshRefinement &)
 
bool _coarsen_elements ()
 
bool _refine_elements ()
 
void _smooth_flags (bool refining, bool coarsening)
 
bool limit_level_mismatch_at_node (const unsigned int max_mismatch)
 
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 ()
 
void create_parent_error_vector (const ErrorVector &error_per_cell, ErrorVector &error_per_parent, Real &parent_error_min, Real &parent_error_max)
 
void update_nodes_map ()
 
bool make_coarsening_compatible ()
 
bool make_refinement_compatible ()
 
Elemtopological_neighbor (Elem *elem, const PointLocatorBase *point_locator, const unsigned int side)
 
bool has_topological_neighbor (const Elem *elem, const PointLocatorBase *point_locator, const Elem *neighbor)
 
bool enforce_mismatch_limit_prior_to_refinement (Elem *elem, NeighborType nt, unsigned max_mismatch)
 

Private Attributes

TopologyMap _new_nodes_map
 
MeshBase_mesh
 
bool _use_member_parameters
 
bool _coarsen_by_parents
 
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 _enforce_mismatch_limit_prior_to_refinement
 
PeriodicBoundaries_periodic_boundaries
 

Detailed Description

Responsible for mesh refinement algorithms and data.

This is the MeshRefinement class. This class implements adaptive mesh refinement algorithms for a MeshBase.

Author
Benjamin S. Kirk
Date
2002-2007

Definition at line 58 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 855 of file mesh_refinement.h.

Constructor & Destructor Documentation

◆ MeshRefinement() [1/2]

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

Constructor.

Definition at line 93 of file mesh_refinement.C.

93  :
94  ParallelObject(m),
95  _mesh(m),
97  _coarsen_by_parents(false),
98  _refine_fraction(0.3),
99  _coarsen_fraction(0.0),
101  _coarsen_threshold(10),
102  _nelem_target(0),
110 #ifdef LIBMESH_ENABLE_PERIODIC
111  , _periodic_boundaries(nullptr)
112 #endif
113 {
114 }
115 
116 
117 
118 #ifdef LIBMESH_ENABLE_PERIODIC
119 void MeshRefinement::set_periodic_boundaries_ptr(PeriodicBoundaries * pb_ptr)
120 {
121  _periodic_boundaries = pb_ptr;
122 }
ParallelObject(const Parallel::Communicator &comm_in)
const unsigned int invalid_uint
Definition: libmesh.h:245
PeriodicBoundaries * _periodic_boundaries
signed char _underrefined_boundary_limit
unsigned char _face_level_mismatch_limit
signed char _overrefined_boundary_limit
bool _enforce_mismatch_limit_prior_to_refinement
unsigned char _node_level_mismatch_limit
unsigned char _edge_level_mismatch_limit
void set_periodic_boundaries_ptr(PeriodicBoundaries *pb_ptr)

◆ MeshRefinement() [2/2]

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

◆ ~MeshRefinement()

libMesh::MeshRefinement::~MeshRefinement ( )

Destructor. Deletes all the elements that are currently stored.

Definition at line 127 of file mesh_refinement.C.

References clear().

128 {
129  this->clear();
130 }

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 1335 of file mesh_refinement.C.

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

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

1336 {
1337  // This function must be run on all processors at once
1338  parallel_object_only();
1339 
1340  LOG_SCOPE ("_coarsen_elements()", "MeshRefinement");
1341 
1342  // Flags indicating if this call actually changes the mesh
1343  bool mesh_changed = false;
1344  bool mesh_p_changed = false;
1345 
1346  // Clear the unused_elements data structure.
1347  // The elements have been packed since it was built,
1348  // so there are _no_ unused elements. We cannot trust
1349  // any iterators currently in this data structure.
1350  // _unused_elements.clear();
1351 
1352  // Loop over the elements first to determine if the mesh will
1353  // undergo h-coarsening. If it will, then we'll need to communicate
1354  // more ghosted elements. We need to communicate them *before* we
1355  // do the coarsening; otherwise it is possible to coarsen away a
1356  // one-element-thick layer partition and leave the partitions on
1357  // either side unable to figure out how to talk to each other.
1358  for (auto & elem : _mesh.element_ptr_range())
1359  if (elem->refinement_flag() == Elem::COARSEN)
1360  {
1361  mesh_changed = true;
1362  break;
1363  }
1364 
1365  // If the mesh changed on any processor, it changed globally
1366  this->comm().max(mesh_changed);
1367 
1368  // And then we may need to widen the ghosting layers.
1369  if (mesh_changed)
1370  MeshCommunication().send_coarse_ghosts(_mesh);
1371 
1372  for (auto & elem : _mesh.element_ptr_range())
1373  {
1374  // active elements flagged for coarsening will
1375  // no longer be deleted until MeshRefinement::contract()
1376  if (elem->refinement_flag() == Elem::COARSEN)
1377  {
1378  // Huh? no level-0 element should be active
1379  // and flagged for coarsening.
1380  libmesh_assert_not_equal_to (elem->level(), 0);
1381 
1382  // Remove this element from any neighbor
1383  // lists that point to it.
1384  elem->nullify_neighbors();
1385 
1386  // Remove any boundary information associated
1387  // with this element
1388  _mesh.get_boundary_info().remove (elem);
1389 
1390  // Add this iterator to the _unused_elements
1391  // data structure so we might fill it.
1392  // The _unused_elements optimization is currently off.
1393  // _unused_elements.push_back (it);
1394 
1395  // Don't delete the element until
1396  // MeshRefinement::contract()
1397  // _mesh.delete_elem(elem);
1398  }
1399 
1400  // inactive elements flagged for coarsening
1401  // will become active
1402  else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1403  {
1404  elem->coarsen();
1405  libmesh_assert (elem->active());
1406 
1407  // the mesh has certainly changed
1408  mesh_changed = true;
1409  }
1410  if (elem->p_refinement_flag() == Elem::COARSEN)
1411  {
1412  if (elem->p_level() > 0)
1413  {
1414  elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1415  elem->set_p_level(elem->p_level() - 1);
1416  mesh_p_changed = true;
1417  }
1418  else
1419  {
1420  elem->set_p_refinement_flag(Elem::DO_NOTHING);
1421  }
1422  }
1423  }
1424 
1425  this->comm().max(mesh_p_changed);
1426 
1427  // And we may need to update DistributedMesh values reflecting the changes
1428  if (mesh_changed)
1430 
1431  // Node processor ids may need to change if an element of that id
1432  // was coarsened away
1433  if (mesh_changed && !_mesh.is_serial())
1434  {
1435  // Update the _new_nodes_map so that processors can
1436  // find requested nodes
1437  this->update_nodes_map ();
1438 
1439  MeshCommunication().make_nodes_parallel_consistent (_mesh);
1440 
1441  // Clear the _new_nodes_map
1442  this->clear();
1443 
1444 #ifdef DEBUG
1445  MeshTools::libmesh_assert_valid_procids<Node>(_mesh);
1446 #endif
1447  }
1448 
1449  // If p levels changed all we need to do is make sure that parent p
1450  // levels changed in sync
1451  if (mesh_p_changed && !_mesh.is_serial())
1452  {
1453  MeshCommunication().make_p_levels_parallel_consistent (_mesh);
1454  }
1455 
1456  return (mesh_changed || mesh_p_changed);
1457 }
void remove(const Node *node)
const Parallel::Communicator & comm() const
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:131
virtual bool is_serial() const
Definition: mesh_base.h:154
virtual SimpleRange< element_iterator > element_ptr_range()=0
virtual void update_parallel_id_counts()=0

◆ _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 1461 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshBase::active_local_element_ptr_range(), libMesh::MeshBase::active_not_local_elements_begin(), libMesh::MeshBase::active_not_local_elements_end(), libMesh::as_range(), clear(), libMesh::ParallelObject::comm(), libMesh::MeshBase::element_ptr_range(), libMesh::MeshBase::is_replicated(), libMesh::Elem::JUST_REFINED, 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(), libMesh::Parallel::Communicator::max(), libMesh::Elem::REFINE, libMesh::Partitioner::set_node_processor_ids(), libMesh::MeshBase::unpartitioned_elements_begin(), libMesh::MeshBase::unpartitioned_elements_end(), update_nodes_map(), and libMesh::MeshBase::update_parallel_id_counts().

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

1462 {
1463  // This function must be run on all processors at once
1464  parallel_object_only();
1465 
1466  // Update the _new_nodes_map so that elements can
1467  // find nodes to connect to.
1468  this->update_nodes_map ();
1469 
1470  LOG_SCOPE ("_refine_elements()", "MeshRefinement");
1471 
1472  // Iterate over the elements, counting the elements
1473  // flagged for h refinement.
1474  dof_id_type n_elems_flagged = 0;
1475 
1476  for (auto & elem : _mesh.element_ptr_range())
1477  if (elem->refinement_flag() == Elem::REFINE)
1478  n_elems_flagged++;
1479 
1480  // Construct a local vector of Elem * which have been
1481  // previously marked for refinement. We reserve enough
1482  // space to allow for every element to be refined.
1483  std::vector<Elem *> local_copy_of_elements;
1484  local_copy_of_elements.reserve(n_elems_flagged);
1485 
1486  // If mesh p levels changed, we might need to synchronize parent p
1487  // levels on a distributed mesh.
1488  bool mesh_p_changed = false;
1489 
1490  // Iterate over the elements, looking for elements flagged for
1491  // refinement.
1492 
1493  // If we are on a ReplicatedMesh, then we just do the refinement in
1494  // the same order on every processor and everything stays in sync.
1495 
1496  // If we are on a DistributedMesh, that's impossible.
1497  //
1498  // If the mesh is distributed, we need to make sure that if we end
1499  // up as the owner of a new node, which might happen if that node is
1500  // attached to one of our own elements, then we have given it a
1501  // legitimate node id and our own processor id. We generate
1502  // legitimate node ids and use our own processor id when we are
1503  // refining our own elements but not when we refine others'
1504  // elements. Therefore we want to refine our own elements *first*,
1505  // thereby generating all nodes which might belong to us, and then
1506  // refine others' elements *after*, thereby generating nodes with
1507  // temporary ids which we know we will discard.
1508  //
1509  // Even if the DistributedMesh is serialized, we can't just treat it
1510  // like a ReplicatedMesh, because DistributedMesh doesn't *trust*
1511  // users to refine partitioned elements in a serialized way, so it
1512  // assigns temporary ids, so we need to synchronize ids afterward to
1513  // be safe anyway, so we might as well use the distributed mesh code
1514  // path.
1516  {
1517  if (elem->refinement_flag() == Elem::REFINE)
1518  local_copy_of_elements.push_back(elem);
1519  if (elem->p_refinement_flag() == Elem::REFINE &&
1520  elem->active())
1521  {
1522  elem->set_p_level(elem->p_level()+1);
1523  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1524  mesh_p_changed = true;
1525  }
1526  }
1527 
1528  if (!_mesh.is_replicated())
1529  {
1530  for (auto & elem : as_range(_mesh.active_not_local_elements_begin(),
1532  {
1533  if (elem->refinement_flag() == Elem::REFINE)
1534  local_copy_of_elements.push_back(elem);
1535  if (elem->p_refinement_flag() == Elem::REFINE &&
1536  elem->active())
1537  {
1538  elem->set_p_level(elem->p_level()+1);
1539  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1540  mesh_p_changed = true;
1541  }
1542  }
1543  }
1544 
1545  // Now iterate over the local copies and refine each one.
1546  // This may resize the mesh's internal container and invalidate
1547  // any existing iterators.
1548 
1549  for (std::size_t e = 0; e != local_copy_of_elements.size(); ++e)
1550  local_copy_of_elements[e]->refine(*this);
1551 
1552  // The mesh changed if there were elements h refined
1553  bool mesh_changed = !local_copy_of_elements.empty();
1554 
1555  // If the mesh changed on any processor, it changed globally
1556  this->comm().max(mesh_changed);
1557  this->comm().max(mesh_p_changed);
1558 
1559  // And we may need to update DistributedMesh values reflecting the changes
1560  if (mesh_changed)
1562 
1563  if (mesh_changed && !_mesh.is_replicated())
1564  {
1565  MeshCommunication().make_elems_parallel_consistent (_mesh);
1566  MeshCommunication().make_new_nodes_parallel_consistent (_mesh);
1567 #ifdef DEBUG
1569 #endif
1570  }
1571 
1572  // If we're refining a ReplicatedMesh, then we haven't yet assigned
1573  // node processor ids. But if we're refining a partitioned
1574  // ReplicatedMesh, then we *need* to assign node processor ids.
1575  if (mesh_changed && _mesh.is_replicated() &&
1579 
1580  if (mesh_p_changed && !_mesh.is_replicated())
1581  {
1582  MeshCommunication().make_p_levels_parallel_consistent (_mesh);
1583  }
1584 
1585  // Clear the _new_nodes_map and _unused_elements data structures.
1586  this->clear();
1587 
1588  return (mesh_changed || mesh_p_changed);
1589 }
static void set_node_processor_ids(MeshBase &mesh)
Definition: partitioner.C:679
virtual element_iterator unpartitioned_elements_begin()=0
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
virtual SimpleRange< element_iterator > element_ptr_range()=0
virtual void update_parallel_id_counts()=0
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
virtual element_iterator active_not_local_elements_end()=0
virtual bool is_replicated() const
Definition: mesh_base.h:176
virtual element_iterator unpartitioned_elements_end()=0
virtual element_iterator active_not_local_elements_begin()=0
virtual void libmesh_assert_valid_parallel_ids() const
Definition: mesh_base.h:1007
uint8_t dof_id_type
Definition: id_types.h:64

◆ _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 1592 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::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().

1593 {
1594  // Smoothing can break in weird ways on a mesh with broken topology
1595 #ifdef DEBUG
1597 #endif
1598 
1599  // Repeat until flag changes match on every processor
1600  do
1601  {
1602  // Repeat until coarsening & refinement flags jive
1603  bool satisfied = false;
1604  do
1605  {
1606  // If we're refining or coarsening, hit the corresponding
1607  // face level test code. Short-circuiting || is our friend
1608  const bool coarsening_satisfied =
1609  !coarsening ||
1611 
1612  const bool refinement_satisfied =
1613  !refining ||
1615 
1616  bool smoothing_satisfied =
1617  !this->eliminate_unrefined_patches();// &&
1618 
1620  smoothing_satisfied = smoothing_satisfied &&
1622 
1624  smoothing_satisfied = smoothing_satisfied &&
1626 
1628  smoothing_satisfied = smoothing_satisfied &&
1630 
1632  smoothing_satisfied = smoothing_satisfied &&
1634 
1635  satisfied = (coarsening_satisfied &&
1636  refinement_satisfied &&
1637  smoothing_satisfied);
1638 
1639  libmesh_assert(this->comm().verify(satisfied));
1640  }
1641  while (!satisfied);
1642  }
1643  while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
1644 }
bool limit_level_mismatch_at_edge(const unsigned int max_mismatch)
bool limit_level_mismatch_at_node(const unsigned int max_mismatch)
bool limit_underrefined_boundary(const signed char max_mismatch)
const Parallel::Communicator & comm() const
bool limit_overrefined_boundary(const signed char max_mismatch)
signed char _underrefined_boundary_limit
virtual bool is_serial() const
Definition: mesh_base.h:154
signed char _overrefined_boundary_limit
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)
Definition: mesh_tools.C:2068

◆ 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 906 of file mesh_refinement.h.

References _absolute_global_tolerance, and _use_member_parameters.

907 {
908  _use_member_parameters = true;
910 }

◆ add_elem()

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

Adds the element elem to the mesh.

Definition at line 210 of file mesh_refinement.C.

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

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

211 {
212  libmesh_assert(elem);
213  _mesh.add_elem (elem);
214  return elem;
215 }
virtual Elem * add_elem(Elem *e)=0

◆ 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::Elem::node_index_range(), libMesh::Elem::node_ptr(), libMesh::MeshBase::node_ptr(), libMesh::Elem::point(), and libMesh::DofObject::processor_id().

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  const dof_id_type new_node_id =
161  _new_nodes_map.find(bracketing_nodes);
162 
163  // Return the node if it already exists.
164  //
165  // We'll leave the processor_id untouched in this case - if we're
166  // repartitioning later or if this is a new unpartitioned node,
167  // we'll update it then, and if not then we don't want to update it.
168  if (new_node_id != DofObject::invalid_id)
169  return _mesh.node_ptr(new_node_id);
170 
171  // Otherwise we need to add a new node.
172  //
173  // Figure out where to add the point:
174 
175  Point p; // defaults to 0,0,0
176 
177  for (auto n : parent.node_index_range())
178  {
179  // The value from the embedding matrix
180  const float em_val = parent.embedding_matrix(child,node,n);
181 
182  if (em_val != 0.)
183  {
184  p.add_scaled (parent.point(n), em_val);
185 
186  // If we'd already found the node we shouldn't be here
187  libmesh_assert_not_equal_to (em_val, 1);
188  }
189  }
190 
191  // Although we're leaving new nodes unpartitioned at first, with a
192  // DistributedMesh we would need a default id based on the numbering
193  // scheme for the requested processor_id.
194  Node * new_node = _mesh.add_point (p, DofObject::invalid_id, proc_id);
195 
196  libmesh_assert(new_node);
197 
198  // But then we'll make sure this node is marked as unpartitioned.
199  new_node->processor_id() = DofObject::invalid_processor_id;
200 
201  // Add the node to the map.
202  _new_nodes_map.add_node(*new_node, bracketing_nodes);
203 
204  // Return the address of the new node
205  return new_node;
206 }
const unsigned int invalid_uint
Definition: libmesh.h:245
void add_scaled(const TypeVector< T2 > &, const T)
Definition: type_vector.h:627
dof_id_type find(dof_id_type bracket_node1, dof_id_type bracket_node2) const
Definition: topology_map.C:118
void add_node(const Node &mid_node, const std::vector< std::pair< dof_id_type, dof_id_type >> &bracketing_nodes)
Definition: topology_map.C:52
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
static const processor_id_type invalid_processor_id
Definition: dof_object.h:358
static const dof_id_type invalid_id
Definition: dof_object.h:347
virtual const Node * node_ptr(const dof_id_type i) const =0
uint8_t dof_id_type
Definition: id_types.h:64

◆ 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 654 of file mesh_refinement_flagging.C.

References _mesh, and libMesh::MeshBase::element_ptr_range().

655 {
656  for (auto & elem : _mesh.element_ptr_range())
657  elem->set_p_refinement_flag(elem->refinement_flag());
658 }
virtual SimpleRange< element_iterator > element_ptr_range()=0

◆ 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 662 of file mesh_refinement_flagging.C.

References _mesh, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_ptr_range(), and libMesh::Elem::INACTIVE.

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

663 {
664  // Possibly clean up the refinement flags from
665  // a previous step
666  for (auto & elem : _mesh.element_ptr_range())
667  {
668  if (elem->active())
669  {
670  elem->set_refinement_flag(Elem::DO_NOTHING);
671  elem->set_p_refinement_flag(Elem::DO_NOTHING);
672  }
673  else
674  {
675  elem->set_refinement_flag(Elem::INACTIVE);
676  elem->set_p_refinement_flag(Elem::INACTIVE);
677  }
678  }
679 }
virtual SimpleRange< element_iterator > element_ptr_range()=0

◆ 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(), _refine_elements(), and ~MeshRefinement().

135 {
137 }

◆ 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 870 of file mesh_refinement.h.

References _coarsen_by_parents, and _use_member_parameters.

871 {
872  _use_member_parameters = true;
873  return _coarsen_by_parents;
874 }

◆ 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.

Definition at line 607 of file mesh_refinement.C.

References _coarsen_elements(), _face_level_mismatch_limit, _mesh, _smooth_flags(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_ptr_range(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, make_coarsening_compatible(), make_flags_parallel_consistent(), libMesh::out, libMesh::MeshBase::prepare_for_use(), and test_level_one().

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

608 {
609  // This function must be run on all processors at once
610  parallel_object_only();
611 
612  // We can't yet turn a non-level-one mesh into a level-one mesh
614  libmesh_assert(test_level_one(true));
615 
616  // Possibly clean up the refinement flags from
617  // a previous step
618  for (auto & elem : _mesh.element_ptr_range())
619  {
620  // Set refinement flag to INACTIVE if the
621  // element isn't active
622  if (!elem->active())
623  {
624  elem->set_refinement_flag(Elem::INACTIVE);
625  elem->set_p_refinement_flag(Elem::INACTIVE);
626  }
627 
628  // This might be left over from the last step
629  if (elem->refinement_flag() == Elem::JUST_REFINED)
630  elem->set_refinement_flag(Elem::DO_NOTHING);
631  }
632 
633  // Parallel consistency has to come first, or coarsening
634  // along processor boundaries might occasionally be falsely
635  // prevented
636  bool flags_were_consistent = this->make_flags_parallel_consistent();
637 
638  // In theory, we should be able to remove the above call, which can
639  // be expensive and should be unnecessary. In practice, doing
640  // consistent flagging in parallel is hard, it's impossible to
641  // verify at the library level if it's being done by user code, and
642  // we don't want to abort large parallel runs in opt mode... but we
643  // do want to warn that they should be fixed.
644  libmesh_assert(flags_were_consistent);
645  if (!flags_were_consistent)
646  {
647  libMesh::out << "Refinement flags were not consistent between processors!\n"
648  << "Correcting and continuing.";
649  }
650 
651  // Smooth coarsening flags
652  _smooth_flags(false, true);
653 
654  // Coarsen the flagged elements.
655  const bool mesh_changed =
656  this->_coarsen_elements ();
657 
659  libmesh_assert(test_level_one(true));
660  libmesh_assert(this->make_coarsening_compatible());
661  // FIXME: This won't pass unless we add a redundant find_neighbors()
662  // call or replace find_neighbors() with on-the-fly neighbor updating
663  // libmesh_assert(!this->eliminate_unrefined_patches());
664 
665  // We can't contract the mesh ourselves anymore - a System might
666  // need to restrict old coefficient vectors first
667  // _mesh.contract();
668 
669  // Finally, the new mesh may need to be prepared for use
670  if (mesh_changed)
671  _mesh.prepare_for_use (/*skip_renumber =*/false);
672 
673  return mesh_changed;
674 }
bool test_level_one(bool libmesh_assert_yes=false)
virtual SimpleRange< element_iterator > element_ptr_range()=0
unsigned char _face_level_mismatch_limit
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:152
void _smooth_flags(bool refining, bool coarsening)
OStreamProxy out(std::cout)

◆ 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 882 of file mesh_refinement.h.

References _coarsen_fraction, and _use_member_parameters.

883 {
884  _use_member_parameters = true;
885  return _coarsen_fraction;
886 }

◆ 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 894 of file mesh_refinement.h.

References _coarsen_threshold, and _use_member_parameters.

895 {
896  _use_member_parameters = true;
897  return _coarsen_threshold;
898 }

◆ comm()

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

Definition at line 89 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::BoundaryInfo::_find_id_maps(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_get_diagonal(), libMesh::SlepcEigenSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult(), libMesh::PetscLinearSolver< T >::_petsc_shell_matrix_mult_add(), libMesh::EquationSystems::_read_impl(), _refine_elements(), _smooth_flags(), libMesh::PetscDMWrapper::add_dofs_helper(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::ImplicitSystem::add_matrix(), libMesh::System::add_vector(), libMesh::UnstructuredMesh::all_second_order(), libMesh::MeshTools::Modification::all_tri(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assemble_qoi(), libMesh::MeshCommunication::assign_global_indices(), libMesh::DofMap::attach_matrix(), libMesh::MeshTools::Generation::build_extrusion(), 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_dims(), libMesh::System::calculate_norm(), libMesh::DofMap::check_dirichlet_bcid_consistency(), libMesh::PetscDMWrapper::check_section_n_dofs(), 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::Problem_Interface::computeF(), libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshTools::create_bounding_box(), libMesh::MeshTools::create_nodal_bounding_box(), create_parent_error_vector(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::MeshTools::create_subdomain_bounding_box(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DofMap::distribute_dofs(), DMlibMeshFunction(), DMlibMeshJacobian(), DMlibMeshSetSystem_libMesh(), DMVariableBounds_libMesh(), eliminate_unrefined_patches(), libMesh::EpetraVector< T >::EpetraVector(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_nelem_target(), libMesh::CondensedEigenSystem::get_eigenpair(), libMesh::DofMap::get_info(), libMesh::ImplicitSystem::get_linear_solver(), libMesh::LocationMap< T >::init(), libMesh::TimeSolver::init(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::EigenSystem::init_data(), libMesh::EigenSystem::init_matrices(), libMesh::OptimizationSystem::initialize_equality_constraints_storage(), libMesh::OptimizationSystem::initialize_inequality_constraints_storage(), 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_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::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_snes_fd_residual(), libMesh::libmesh_petsc_snes_jacobian(), libMesh::libmesh_petsc_snes_mffd_residual(), libMesh::libmesh_petsc_snes_postcheck(), 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(), 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_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::FEMSystem::mesh_position_set(), libMesh::DistributedMesh::n_active_elem(), libMesh::MeshTools::n_active_levels(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::CondensedEigenSystem::n_global_non_condensed_dofs(), libMesh::MeshTools::n_levels(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::MeshTools::n_p_levels(), libMesh::BoundaryInfo::n_shellface_conds(), 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::MeshTools::paranoid_n_levels(), libMesh::petsc_auto_fieldsplit(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::MeshBase::prepare_for_use(), libMesh::Nemesis_IO::read(), libMesh::XdrIO::read(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), 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::MeshBase::recalculate_n_partitions(), refine_and_coarsen_elements(), libMesh::DistributedMesh::renumber_dof_objects(), libMesh::CheckpointIO::select_split_config(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::PetscDiffSolver::setup_petsc_data(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::split_mesh(), libMesh::MeshBase::subdomain_ids(), libMesh::BoundaryInfo::sync(), test_level_one(), test_unflagged(), libMesh::MeshTools::total_weight(), uniformly_coarsen(), libMesh::NameBasedIO::write(), libMesh::XdrIO::write(), 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().

90  { 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 219 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_local_element_ptr_range(), libMesh::ParallelObject::comm(), libMesh::DofObject::id(), std::max(), std::min(), libMesh::Parallel::Communicator::min(), libMesh::Elem::parent(), and libMesh::Parallel::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().

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

◆ 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 917 of file mesh_refinement.h.

References _edge_level_mismatch_limit.

918 {
920 }
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

Definition at line 380 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::Elem::DO_NOTHING, libMesh::Elem::INACTIVE, libMesh::Parallel::Communicator::max(), libMesh::Elem::REFINE, and libMesh::remote_elem.

Referenced by _smooth_flags().

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

◆ enforce_mismatch_limit_prior_to_refinement() [1/2]

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 951 of file mesh_refinement.h.

References _enforce_mismatch_limit_prior_to_refinement.

Referenced by get_enforce_mismatch_limit_prior_to_refinement(), limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), and set_enforce_mismatch_limit_prior_to_refinement().

952 {
954 }
bool _enforce_mismatch_limit_prior_to_refinement

◆ enforce_mismatch_limit_prior_to_refinement() [2/2]

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

Definition at line 551 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().

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

◆ 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 912 of file mesh_refinement.h.

References _face_level_mismatch_limit.

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

913 {
915 }
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 628 of file mesh_refinement_flagging.C.

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

629 {
630  element_flagging.flag_elements();
631 }

◆ 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 434 of file mesh_refinement_flagging.C.

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

438 {
439  parallel_object_only();
440 
441  // The function arguments are currently just there for
442  // backwards_compatibility
444  {
445  // If the user used non-default parameters, lets warn
446  // that they're deprecated
447  if (refine_frac != 0.3 ||
448  coarsen_frac != 0.0 ||
449  max_l != libMesh::invalid_uint)
450  libmesh_deprecated();
451 
452  _refine_fraction = refine_frac;
453  _coarsen_fraction = coarsen_frac;
454  _max_h_level = max_l;
455  }
456 
457  // Check for valid fractions..
458  // The fraction values must be in [0,1]
459  libmesh_assert_greater_equal (_refine_fraction, 0);
460  libmesh_assert_less_equal (_refine_fraction, 1);
461  libmesh_assert_greater_equal (_coarsen_fraction, 0);
462  libmesh_assert_less_equal (_coarsen_fraction, 1);
463 
464  // The number of active elements in the mesh
465  const dof_id_type n_active_elem = _mesh.n_active_elem();
466 
467  // The number of elements to flag for coarsening
468  const dof_id_type n_elem_coarsen =
469  static_cast<dof_id_type>(_coarsen_fraction * n_active_elem);
470 
471  // The number of elements to flag for refinement
472  const dof_id_type n_elem_refine =
473  static_cast<dof_id_type>(_refine_fraction * n_active_elem);
474 
475 
476 
477  // Clean up the refinement flags. These could be left
478  // over from previous refinement steps.
479  this->clean_refinement_flags();
480 
481 
482  // This vector stores the error and element number for all the
483  // active elements. It will be sorted and the top & bottom
484  // elements will then be flagged for coarsening & refinement
485  std::vector<ErrorVectorReal> sorted_error;
486 
487  sorted_error.reserve (n_active_elem);
488 
489  // Loop over the active elements and create the entry
490  // in the sorted_error vector
491  for (auto & elem : _mesh.active_local_element_ptr_range())
492  sorted_error.push_back (error_per_cell[elem->id()]);
493 
494  this->comm().allgather(sorted_error);
495 
496  // Now sort the sorted_error vector
497  std::sort (sorted_error.begin(), sorted_error.end());
498 
499  // If we're coarsening by parents:
500  // Create a sorted error vector with coarsenable parent elements
501  // only, sorted by lowest errors first
502  ErrorVector error_per_parent, sorted_parent_error;
504  {
505  Real parent_error_min, parent_error_max;
506 
507  create_parent_error_vector(error_per_cell,
508  error_per_parent,
509  parent_error_min,
510  parent_error_max);
511 
512  sorted_parent_error = error_per_parent;
513  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
514 
515  // All the other error values will be 0., so get rid of them.
516  sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
517  sorted_parent_error.end(), 0.),
518  sorted_parent_error.end());
519  }
520 
521 
522  ErrorVectorReal top_error= 0., bottom_error = 0.;
523 
524  // Get the maximum error value corresponding to the
525  // bottom n_elem_coarsen elements
526  if (_coarsen_by_parents && n_elem_coarsen)
527  {
528  const unsigned int dim = _mesh.mesh_dimension();
529  unsigned int twotodim = 1;
530  for (unsigned int i=0; i!=dim; ++i)
531  twotodim *= 2;
532 
533  dof_id_type n_parent_coarsen = n_elem_coarsen / (twotodim - 1);
534 
535  if (n_parent_coarsen)
536  bottom_error = sorted_parent_error[n_parent_coarsen - 1];
537  }
538  else if (n_elem_coarsen)
539  {
540  bottom_error = sorted_error[n_elem_coarsen - 1];
541  }
542 
543  if (n_elem_refine)
544  top_error = sorted_error[sorted_error.size() - n_elem_refine];
545 
546  // Finally, let's do the element flagging
547  for (auto & elem : _mesh.active_element_ptr_range())
548  {
549  Elem * parent = elem->parent();
550 
551  if (_coarsen_by_parents && parent && n_elem_coarsen &&
552  error_per_parent[parent->id()] <= bottom_error)
553  elem->set_refinement_flag(Elem::COARSEN);
554 
555  if (!_coarsen_by_parents && n_elem_coarsen &&
556  error_per_cell[elem->id()] <= bottom_error)
557  elem->set_refinement_flag(Elem::COARSEN);
558 
559  if (n_elem_refine &&
560  elem->level() < _max_h_level &&
561  error_per_cell[elem->id()] >= top_error)
562  elem->set_refinement_flag(Elem::REFINE);
563  }
564 }
virtual dof_id_type n_active_elem() const =0
const unsigned int invalid_uint
Definition: libmesh.h:245
void allgather(const T &send, std::vector< T, A > &recv) const
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)
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int mesh_dimension() const
Definition: mesh_base.C:126
uint8_t dof_id_type
Definition: id_types.h:64

◆ 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, libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshBase::active_local_element_ptr_range(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), create_parent_error_vector(), libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, std::max(), libMesh::Parallel::Communicator::max(), std::min(), libMesh::Parallel::Communicator::min(), libMesh::Elem::parent(), libMesh::Real, and libMesh::Elem::REFINE.

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

◆ 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 166 of file mesh_refinement_flagging.C.

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

167 {
168  parallel_object_only();
169 
170  libmesh_assert_greater (_coarsen_threshold, 0);
171 
172  // Check for valid fractions..
173  // The fraction values must be in [0,1]
174  libmesh_assert_greater_equal (_refine_fraction, 0);
175  libmesh_assert_less_equal (_refine_fraction, 1);
176  libmesh_assert_greater_equal (_coarsen_fraction, 0);
177  libmesh_assert_less_equal (_coarsen_fraction, 1);
178 
179  // How much error per cell will we tolerate?
180  const Real local_refinement_tolerance =
181  _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
182  const Real local_coarsening_tolerance =
183  local_refinement_tolerance * _coarsen_threshold;
184 
185  // Prepare another error vector if we need to sum parent errors
186  ErrorVector error_per_parent;
188  {
189  Real parent_error_min, parent_error_max;
190 
191  create_parent_error_vector(error_per_cell_in,
192  error_per_parent,
193  parent_error_min,
194  parent_error_max);
195  }
196 
197  for (auto & elem : _mesh.active_element_ptr_range())
198  {
199  Elem * parent = elem->parent();
200  const dof_id_type elem_number = elem->id();
201  const ErrorVectorReal elem_error = error_per_cell_in[elem_number];
202 
203  if (elem_error > local_refinement_tolerance &&
204  elem->level() < _max_h_level)
205  elem->set_refinement_flag(Elem::REFINE);
206 
207  if (!_coarsen_by_parents && elem_error <
208  local_coarsening_tolerance)
209  elem->set_refinement_flag(Elem::COARSEN);
210 
211  if (_coarsen_by_parents && parent)
212  {
213  ErrorVectorReal parent_error = error_per_parent[parent->id()];
214  if (parent_error >= 0.)
215  {
216  const Real parent_coarsening_tolerance =
217  std::sqrt(parent->n_children() *
218  local_coarsening_tolerance *
219  local_coarsening_tolerance);
220  if (parent_error < parent_coarsening_tolerance)
221  elem->set_refinement_flag(Elem::COARSEN);
222  }
223  }
224  }
225 }
virtual dof_id_type n_active_elem() const =0
void create_parent_error_vector(const ErrorVector &error_per_cell, ErrorVector &error_per_parent, Real &parent_error_min, Real &parent_error_max)
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t dof_id_type
Definition: id_types.h:64

◆ 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 568 of file mesh_refinement_flagging.C.

References _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, libMesh::MeshBase::active_element_ptr_range(), libMesh::Elem::COARSEN, libMesh::ErrorVectorReal, libMesh::invalid_uint, std::max(), libMesh::ErrorVector::mean(), libMesh::Real, libMesh::Elem::REFINE, and libMesh::ErrorVector::variance().

572 {
573  // The function arguments are currently just there for
574  // backwards_compatibility
576  {
577  // If the user used non-default parameters, lets warn
578  // that they're deprecated
579  if (refine_frac != 0.3 ||
580  coarsen_frac != 0.0 ||
581  max_l != libMesh::invalid_uint)
582  libmesh_deprecated();
583 
584  _refine_fraction = refine_frac;
585  _coarsen_fraction = coarsen_frac;
586  _max_h_level = max_l;
587  }
588 
589  // Get the mean value from the error vector
590  const Real mean = error_per_cell.mean();
591 
592  // Get the standard deviation. This equals the
593  // square-root of the variance
594  const Real stddev = std::sqrt (error_per_cell.variance());
595 
596  // Check for valid fractions
597  libmesh_assert_greater_equal (_refine_fraction, 0);
598  libmesh_assert_less_equal (_refine_fraction, 1);
599  libmesh_assert_greater_equal (_coarsen_fraction, 0);
600  libmesh_assert_less_equal (_coarsen_fraction, 1);
601 
602  // The refine and coarsen cutoff
603  const Real refine_cutoff = mean + _refine_fraction * stddev;
604  const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.);
605 
606  // Loop over the elements and flag them for coarsening or
607  // refinement based on the element error
608  for (auto & elem : _mesh.active_element_ptr_range())
609  {
610  const dof_id_type id = elem->id();
611 
612  libmesh_assert_less (id, error_per_cell.size());
613 
614  const ErrorVectorReal elem_error = error_per_cell[id];
615 
616  // Possibly flag the element for coarsening ...
617  if (elem_error <= coarsen_cutoff)
618  elem->set_refinement_flag(Elem::COARSEN);
619 
620  // ... or refinement
621  if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level))
622  elem->set_refinement_flag(Elem::REFINE);
623  }
624 }
const unsigned int invalid_uint
Definition: libmesh.h:245
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
long double max(long double a, double b)
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t dof_id_type
Definition: id_types.h:64

◆ 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 229 of file mesh_refinement_flagging.C.

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

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

◆ get_enforce_mismatch_limit_prior_to_refinement()

bool libMesh::MeshRefinement::get_enforce_mismatch_limit_prior_to_refinement ( )
inline
Returns
The value of the _enforce_mismatch_limit_prior_to_refinement flag, false by default.
Deprecated:
Use enforce_mismatch_limit_prior_to_refinement() instead.

Definition at line 938 of file mesh_refinement.h.

References enforce_mismatch_limit_prior_to_refinement().

939 {
940  libmesh_deprecated();
942 }
bool & enforce_mismatch_limit_prior_to_refinement()

◆ 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 324 of file mesh_refinement.h.

References _mesh.

324 { return _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 330 of file mesh_refinement.h.

References _mesh.

330 { return _mesh; }

◆ has_topological_neighbor()

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

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

Definition at line 1805 of file mesh_refinement.C.

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

Referenced by make_coarsening_compatible(), and make_refinement_compatible().

1808 {
1809 #ifdef LIBMESH_ENABLE_PERIODIC
1810  if (_periodic_boundaries && !_periodic_boundaries->empty())
1811  {
1812  libmesh_assert(point_locator);
1813  return elem->has_topological_neighbor(neighbor, _mesh, *point_locator, _periodic_boundaries);
1814  }
1815 #endif
1816  return elem->has_neighbor(neighbor);
1817 }
PeriodicBoundaries * _periodic_boundaries

◆ 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::MeshBase::active_element_ptr_range(), libMesh::ParallelObject::comm(), EDGE, enforce_mismatch_limit_prior_to_refinement(), std::max(), libMesh::Parallel::Communicator::max(), libMesh::Elem::parent(), libMesh::Elem::REFINE, and swap().

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  // Loop over all the active elements & fill the maps
141  for (auto & elem : _mesh.active_element_ptr_range())
142  {
143  const unsigned char elem_level =
144  cast_int<unsigned char>(elem->level() +
145  ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0));
146  const unsigned char elem_p_level =
147  cast_int<unsigned char>(elem->p_level() +
148  ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
149 
150  // Set the max_level at each edge
151  for (unsigned int n=0; n<elem->n_edges(); n++)
152  {
153  std::unique_ptr<const Elem> edge = elem->build_edge_ptr(n);
154  dof_id_type childnode0 = edge->node_id(0);
155  dof_id_type childnode1 = edge->node_id(1);
156  if (childnode1 < childnode0)
157  std::swap(childnode0, childnode1);
158 
159  for (const Elem * p = elem; p != nullptr; p = p->parent())
160  {
161  std::unique_ptr<const Elem> pedge = p->build_edge_ptr(n);
162  dof_id_type node0 = pedge->node_id(0);
163  dof_id_type node1 = pedge->node_id(1);
164 
165  if (node1 < node0)
166  std::swap(node0, node1);
167 
168  // If elem does not share this edge with its ancestor
169  // p, refinement levels of elements sharing p's edge
170  // are not restricted by refinement levels of elem.
171  // Furthermore, elem will not share this edge with any
172  // of p's ancestors, so we can safely break out of the
173  // for loop early.
174  if (node0 != childnode0 && node1 != childnode1)
175  break;
176 
177  childnode0 = node0;
178  childnode1 = node1;
179 
180  std::pair<unsigned int, unsigned int> edge_key =
181  std::make_pair(node0, node1);
182 
183  if (max_level_at_edge.find(edge_key) ==
184  max_level_at_edge.end())
185  {
186  max_level_at_edge[edge_key] = elem_level;
187  max_p_level_at_edge[edge_key] = elem_p_level;
188  }
189  else
190  {
191  max_level_at_edge[edge_key] =
192  std::max (max_level_at_edge[edge_key], elem_level);
193  max_p_level_at_edge[edge_key] =
194  std::max (max_p_level_at_edge[edge_key], elem_p_level);
195  }
196  }
197  }
198  }
199 
200 
201  // Now loop over the active elements and flag the elements
202  // who violate the requested level mismatch
203  for (auto & elem : _mesh.active_element_ptr_range())
204  {
205  const unsigned int elem_level = elem->level();
206  const unsigned int elem_p_level = elem->p_level();
207 
208  // Skip the element if it is already fully flagged
209  if (elem->refinement_flag() == Elem::REFINE &&
210  elem->p_refinement_flag() == Elem::REFINE
212  continue;
213 
214  // Loop over the nodes, check for possible mismatch
215  for (unsigned int n=0; n<elem->n_edges(); n++)
216  {
217  std::unique_ptr<Elem> edge = elem->build_edge_ptr(n);
218  dof_id_type node0 = edge->node_id(0);
219  dof_id_type node1 = edge->node_id(1);
220  if (node1 < node0)
221  std::swap(node0, node1);
222 
223  std::pair<dof_id_type, dof_id_type> edge_key =
224  std::make_pair(node0, node1);
225 
226  // Flag the element for refinement if it violates
227  // the requested level mismatch
228  if ((elem_level + max_mismatch) < max_level_at_edge[edge_key]
229  && elem->refinement_flag() != Elem::REFINE)
230  {
231  elem->set_refinement_flag (Elem::REFINE);
232  flags_changed = true;
233  }
234 
235  if ((elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
236  && elem->p_refinement_flag() != Elem::REFINE)
237  {
238  elem->set_p_refinement_flag (Elem::REFINE);
239  flags_changed = true;
240  }
241 
242  // Possibly enforce limit mismatch prior to refinement
243  flags_changed |= this->enforce_mismatch_limit_prior_to_refinement(elem, EDGE, max_mismatch);
244  } // loop over edges
245  } // loop over active elements
246 
247  // If flags changed on any processor then they changed globally
248  this->comm().max(flags_changed);
249 
250  return flags_changed;
251 }
bool & enforce_mismatch_limit_prior_to_refinement()
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
long double max(long double a, double b)
bool _enforce_mismatch_limit_prior_to_refinement
void swap(Iterator &lhs, Iterator &rhs)
uint8_t dof_id_type
Definition: id_types.h:64

◆ 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::MeshBase::active_element_ptr_range(), libMesh::ParallelObject::comm(), enforce_mismatch_limit_prior_to_refinement(), std::max(), libMesh::Parallel::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 (unsigned int n=0; n<elem->n_nodes(); n++)
63  {
64  const dof_id_type node_number = elem->node_id(n);
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 (unsigned int n=0; n<elem->n_nodes(); n++)
95  {
96  const dof_id_type node_number = elem->node_id(n);
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()
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
long double max(long double a, double b)
bool _enforce_mismatch_limit_prior_to_refinement
virtual dof_id_type n_nodes() const =0
uint8_t dof_id_type
Definition: id_types.h:64

◆ limit_overrefined_boundary()

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

Definition at line 255 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), libMesh::ParallelObject::comm(), libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), and libMesh::Elem::set_refinement_flag().

Referenced by _smooth_flags().

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

◆ limit_underrefined_boundary()

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

Definition at line 316 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), libMesh::ParallelObject::comm(), libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), and libMesh::Elem::set_refinement_flag().

Referenced by _smooth_flags().

317 {
318  // This function must be run on all processors at once
319  parallel_object_only();
320 
321  bool flags_changed = false;
322 
323  // Loop over all the active elements & look for mismatches to fix.
324  for (auto & elem : _mesh.active_element_ptr_range())
325  {
326  // If we don't have an interior_parent then there's nothing to
327  // be mismatched with.
328  if ((elem->dim() >= LIBMESH_DIM) ||
329  !elem->interior_parent())
330  continue;
331 
332  // get all relevant interior elements
333  std::set<const Elem *> neighbor_set;
334  elem->find_interior_neighbors(neighbor_set);
335 
336  std::set<const Elem *>::iterator n_it = neighbor_set.begin();
337  for (; n_it != neighbor_set.end(); ++n_it)
338  {
339  // FIXME - non-const versions of the Elem set methods
340  // would be nice
341  const Elem * neighbor = *n_it;
342 
343  const unsigned char neighbor_level =
344  cast_int<unsigned char>(neighbor->level() +
345  ((neighbor->refinement_flag() == Elem::REFINE) ? 1 : 0));
346 
347  const unsigned char neighbor_p_level =
348  cast_int<unsigned char>(neighbor->p_level() +
349  ((neighbor->p_refinement_flag() == Elem::REFINE) ? 1 : 0));
350 
351  if (max_mismatch >= 0)
352  {
353  if ((neighbor_level >
354  elem->level() + max_mismatch) &&
355  (elem->refinement_flag() != Elem::REFINE))
356  {
357  elem->set_refinement_flag(Elem::REFINE);
358  flags_changed = true;
359  }
360 
361  if ((neighbor_p_level >
362  elem->p_level() + max_mismatch) &&
363  (elem->p_refinement_flag() != Elem::REFINE))
364  {
365  elem->set_p_refinement_flag(Elem::REFINE);
366  flags_changed = true;
367  }
368  }
369  } // loop over interior neighbors
370  }
371 
372  // If flags changed on any processor then they changed globally
373  this->comm().max(flags_changed);
374 
375  return flags_changed;
376 }
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0

◆ 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 779 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshBase::ancestor_elements_begin(), libMesh::MeshBase::ancestor_elements_end(), libMesh::Parallel::any_source, 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(), libMesh::Parallel::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::MeshBase::level_elements_begin(), libMesh::MeshBase::level_elements_end(), std::max(), libMesh::MeshTools::max_level(), libMesh::Parallel::Communicator::min(), libMesh::ParallelObject::n_processors(), libMesh::MeshBase::not_local_elements_begin(), libMesh::MeshBase::not_local_elements_end(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::receive(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Parallel::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(), topological_neighbor(), and libMesh::Parallel::wait().

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

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

References _mesh, libMesh::ParallelObject::comm(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::Parallel::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().

752 {
753  // This function must be run on all processors at once
754  parallel_object_only();
755 
756  LOG_SCOPE ("make_flags_parallel_consistent()", "MeshRefinement");
757 
758  SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
761  (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), hsync);
762 
763  SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
766  (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), psync);
767 
768  // If we weren't consistent in both h and p on every processor then
769  // we weren't globally consistent
770  bool parallel_consistent = hsync.parallel_consistent &&
771  psync.parallel_consistent;
772  this->comm().min(parallel_consistent);
773 
774  return parallel_consistent;
775 }
RefinementState refinement_flag() const
Definition: elem.h:2638
RefinementState p_refinement_flag() const
Definition: elem.h:2654
void set_refinement_flag(const RefinementState rflag)
Definition: elem.h:2646
const Parallel::Communicator & comm() const
virtual element_iterator elements_begin()=0
virtual element_iterator elements_end()=0
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
void set_p_refinement_flag(const RefinementState pflag)
Definition: elem.h:2662

◆ 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 1159 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::MeshBase::active_element_ptr_range(), 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::Parallel::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(), side, libMesh::MeshBase::sub_point_locator(), and topological_neighbor().

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

1160 {
1161  // This function must be run on all processors at once
1162  parallel_object_only();
1163 
1164  // We may need a PointLocator for topological_neighbor() tests
1165  // later, which we need to make sure gets constructed on all
1166  // processors at once.
1167  std::unique_ptr<PointLocatorBase> point_locator;
1168 
1169 #ifdef LIBMESH_ENABLE_PERIODIC
1170  bool has_periodic_boundaries =
1172  libmesh_assert(this->comm().verify(has_periodic_boundaries));
1173 
1174  if (has_periodic_boundaries)
1175  point_locator = _mesh.sub_point_locator();
1176 #endif
1177 
1178  LOG_SCOPE ("make_refinement_compatible()", "MeshRefinement");
1179 
1180  // Unless we encounter a specific situation we will be compatible
1181  // with any selected coarsening flags
1182  bool compatible_with_coarsening = true;
1183 
1184  // This loop enforces the level-1 rule. We should only
1185  // execute it if the user indeed wants level-1 satisfied!
1187  {
1188  // Unless we encounter a specific situation level-one
1189  // will be satisfied after executing this loop just once
1190  bool level_one_satisfied = true;
1191 
1192  do
1193  {
1194  level_one_satisfied = true;
1195 
1196  for (auto & elem : _mesh.active_element_ptr_range())
1197  {
1198  const unsigned short n_sides = elem->n_sides();
1199 
1200  if (elem->refinement_flag() == Elem::REFINE) // If the element is active and the
1201  // h refinement flag is set
1202  {
1203  const unsigned int my_level = elem->level();
1204 
1205  for (unsigned short side = 0; side != n_sides;
1206  ++side)
1207  {
1208  Elem * neighbor =
1209  topological_neighbor(elem, point_locator.get(), side);
1210 
1211  if (neighbor != nullptr && // I have a
1212  neighbor != remote_elem && // neighbor here
1213  neighbor->active()) // and it is active
1214  {
1215  // Case 1: The neighbor is at the same level I am.
1216  // 1a: The neighbor will be refined -> NO PROBLEM
1217  // 1b: The neighbor won't be refined -> NO PROBLEM
1218  // 1c: The neighbor wants to be coarsened -> PROBLEM
1219  if (neighbor->level() == my_level)
1220  {
1221  if (neighbor->refinement_flag() == Elem::COARSEN)
1222  {
1224  if (neighbor->parent())
1225  neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
1226  compatible_with_coarsening = false;
1227  level_one_satisfied = false;
1228  }
1229  }
1230 
1231 
1232  // Case 2: The neighbor is one level lower than I am.
1233  // The neighbor thus MUST be refined to satisfy
1234  // the level-one rule, regardless of whether it
1235  // was originally flagged for refinement. If it
1236  // wasn't flagged already we need to repeat
1237  // this process.
1238  else if ((neighbor->level()+1) == my_level)
1239  {
1240  if (neighbor->refinement_flag() != Elem::REFINE)
1241  {
1242  neighbor->set_refinement_flag(Elem::REFINE);
1243  if (neighbor->parent())
1244  neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
1245  compatible_with_coarsening = false;
1246  level_one_satisfied = false;
1247  }
1248  }
1249 #ifdef DEBUG
1250  // Note that the only other possibility is that the
1251  // neighbor is already refined, in which case it isn't
1252  // active and we should never get here.
1253  else
1254  libmesh_error_msg("ERROR: Neighbor level must be equal or 1 higher than mine.");
1255 #endif
1256  }
1257  }
1258  }
1259  if (elem->p_refinement_flag() == Elem::REFINE) // If the element is active and the
1260  // p refinement flag is set
1261  {
1262  const unsigned int my_p_level = elem->p_level();
1263 
1264  for (unsigned int side=0; side != n_sides; side++)
1265  {
1266  Elem * neighbor =
1267  topological_neighbor(elem, point_locator.get(), side);
1268 
1269  if (neighbor != nullptr && // I have a
1270  neighbor != remote_elem) // neighbor here
1271  {
1272  if (neighbor->active()) // and it is active
1273  {
1274  if (neighbor->p_level() < my_p_level &&
1275  neighbor->p_refinement_flag() != Elem::REFINE)
1276  {
1278  level_one_satisfied = false;
1279  compatible_with_coarsening = false;
1280  }
1281  if (neighbor->p_level() == my_p_level &&
1282  neighbor->p_refinement_flag() == Elem::COARSEN)
1283  {
1284  neighbor->set_p_refinement_flag(Elem::DO_NOTHING);
1285  level_one_satisfied = false;
1286  compatible_with_coarsening = false;
1287  }
1288  }
1289  else // I have an inactive neighbor
1290  {
1291  libmesh_assert(neighbor->has_children());
1292  for (auto & subneighbor : neighbor->child_ref_range())
1293  if (&subneighbor != remote_elem && subneighbor.active() &&
1294  has_topological_neighbor(&subneighbor, point_locator.get(), elem))
1295  {
1296  if (subneighbor.p_level() < my_p_level &&
1297  subneighbor.p_refinement_flag() != Elem::REFINE)
1298  {
1299  // We should already be level one
1300  // compatible
1301  libmesh_assert_greater (subneighbor.p_level() + 2u,
1302  my_p_level);
1303  subneighbor.set_p_refinement_flag(Elem::REFINE);
1304  level_one_satisfied = false;
1305  compatible_with_coarsening = false;
1306  }
1307  if (subneighbor.p_level() == my_p_level &&
1308  subneighbor.p_refinement_flag() == Elem::COARSEN)
1309  {
1310  subneighbor.set_p_refinement_flag(Elem::DO_NOTHING);
1311  level_one_satisfied = false;
1312  compatible_with_coarsening = false;
1313  }
1314  }
1315  }
1316  }
1317  }
1318  }
1319  }
1320  }
1321 
1322  while (!level_one_satisfied);
1323  } // end if (_face_level_mismatch_limit)
1324 
1325  // If we're not compatible on one processor, we're globally not
1326  // compatible
1327  this->comm().min(compatible_with_coarsening);
1328 
1329  return compatible_with_coarsening;
1330 }
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:496
unsigned short int side
Definition: xdr_io.C:50
void set_refinement_flag(const RefinementState rflag)
Definition: elem.h:2646
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
PeriodicBoundaries * _periodic_boundaries
unsigned char _face_level_mismatch_limit
bool has_topological_neighbor(const Elem *elem, const PointLocatorBase *point_locator, const Elem *neighbor)
void set_p_refinement_flag(const RefinementState pflag)
Definition: elem.h:2662
bool active() const
Definition: elem.h:2390
Elem * topological_neighbor(Elem *elem, const PointLocatorBase *point_locator, const unsigned int side)
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 888 of file mesh_refinement.h.

References _max_h_level, and _use_member_parameters.

889 {
890  _use_member_parameters = true;
891  return _max_h_level;
892 }

◆ n_processors()

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

Definition at line 95 of file parallel_object.h.

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

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::PetscDMWrapper::add_dofs_to_section(), libMesh::DistributedMesh::add_elem(), libMesh::DistributedMesh::add_node(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::FEMSystem::assembly(), libMesh::AztecLinearSolver< T >::AztecLinearSolver(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), libMesh::Nemesis_IO_Helper::compute_border_node_ids(), libMesh::Nemesis_IO_Helper::construct_nemesis_filename(), libMesh::UnstructuredMesh::create_pid_mesh(), libMesh::MeshTools::create_processor_bounding_box(), libMesh::DofMap::distribute_dofs(), libMesh::DofMap::distribute_local_dofs_node_major(), libMesh::DofMap::distribute_local_dofs_var_major(), libMesh::EnsightIO::EnsightIO(), libMesh::MeshBase::get_info(), libMesh::SystemSubsetBySubdomain::init(), libMesh::PetscDMWrapper::init_and_attach_petscdm(), libMesh::Nemesis_IO_Helper::initialize(), libMesh::DistributedMesh::insert_elem(), 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::MeshBase::n_elem_on_proc(), libMesh::MeshBase::n_nodes_on_proc(), libMesh::MeshBase::partition(), libMesh::PetscLinearSolver< T >::PetscLinearSolver(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), 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::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), uniformly_coarsen(), libMesh::DistributedMesh::update_parallel_id_counts(), libMesh::GMVIO::write_binary(), libMesh::GMVIO::write_discontinuous_gmv(), 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().

96  { return cast_int<processor_id_type>(_communicator.size()); }
processor_id_type size() const
Definition: communicator.h:175
const Parallel::Communicator & _communicator

◆ 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 900 of file mesh_refinement.h.

References _nelem_target, and _use_member_parameters.

901 {
902  _use_member_parameters = true;
903  return _nelem_target;
904 }

◆ 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 922 of file mesh_refinement.h.

References _node_level_mismatch_limit.

923 {
925 }
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 927 of file mesh_refinement.h.

References _overrefined_boundary_limit.

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

928 {
930 }
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 101 of file parallel_object.h.

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

Referenced by libMesh::BoundaryInfo::_find_id_maps(), libMesh::EquationSystems::_read_impl(), 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::UnstructuredMesh::all_second_order(), libMesh::MeshTools::Modification::all_tri(), libMesh::FEMSystem::assembly(), libMesh::EquationSystems::build_discontinuous_solution_vector(), libMesh::Nemesis_IO_Helper::build_element_and_node_maps(), libMesh::InfElemBuilder::build_inf_elem(), libMesh::BoundaryInfo::build_node_list_from_side_list(), libMesh::EquationSystems::build_parallel_elemental_solution_vector(), libMesh::DistributedMesh::clear(), 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::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::MeshTools::correct_node_proc_ids(), libMesh::ExodusII_IO_Helper::create(), libMesh::DistributedMesh::delete_elem(), libMesh::DistributedMesh::delete_node(), libMesh::MeshCommunication::delete_remote_elements(), libMesh::DofMap::distribute_dofs(), libMesh::DofMap::distribute_local_dofs_node_major(), libMesh::DofMap::distribute_local_dofs_var_major(), libMesh::DistributedMesh::DistributedMesh(), libMesh::DofMap::end_dof(), libMesh::DofMap::end_old_dof(), libMesh::EnsightIO::EnsightIO(), libMesh::MeshFunction::find_element(), libMesh::MeshFunction::find_elements(), libMesh::UnstructuredMesh::find_neighbors(), libMesh::DofMap::first_dof(), libMesh::DofMap::first_old_dof(), 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::Nemesis_IO_Helper::get_loadbal_param(), 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::SystemSubsetBySubdomain::init(), 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::DofMap::last_dof(), 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(), make_coarsening_compatible(), libMesh::MeshBase::n_active_local_elem(), libMesh::BoundaryInfo::n_boundary_conds(), libMesh::BoundaryInfo::n_edge_conds(), libMesh::DofMap::n_local_dofs(), libMesh::System::n_local_dofs(), libMesh::MeshBase::n_local_elem(), libMesh::MeshBase::n_local_nodes(), libMesh::BoundaryInfo::n_nodeset_conds(), libMesh::BoundaryInfo::n_shellface_conds(), libMesh::SparsityPattern::Build::operator()(), libMesh::DistributedMesh::own_node(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), 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::ExodusII_IO_Helper::read_elem_num_map(), libMesh::ExodusII_IO_Helper::read_global_values(), libMesh::CheckpointIO::read_header(), libMesh::XdrIO::read_header(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::ExodusII_IO_Helper::read_node_num_map(), libMesh::System::read_parallel_data(), 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::DistributedMesh::renumber_dof_objects(), libMesh::CheckpointIO::select_split_config(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::PetscDMWrapper::set_point_range_in_section(), libMesh::LaplaceMeshSmoother::smooth(), libMesh::MeshTools::total_weight(), uniformly_coarsen(), libMesh::Parallel::Packing< T >::unpack(), libMesh::DistributedMesh::update_parallel_id_counts(), 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_elements(), 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::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::ExodusII_IO_Helper::write_nodal_values(), libMesh::Nemesis_IO_Helper::write_nodesets(), libMesh::ExodusII_IO_Helper::write_nodesets(), libMesh::System::write_parallel_data(), 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::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().

102  { return cast_int<processor_id_type>(_communicator.rank()); }
const Parallel::Communicator & _communicator
processor_id_type rank() const
Definition: communicator.h:173

◆ 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 475 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_ptr_range(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, libMesh::MeshBase::libmesh_assert_valid_parallel_ids(), make_coarsening_compatible(), make_flags_parallel_consistent(), make_refinement_compatible(), libMesh::Parallel::Communicator::max(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::REFINE, test_level_one(), and test_unflagged().

476 {
477  // This function must be run on all processors at once
478  parallel_object_only();
479 
480  // We can't yet turn a non-level-one mesh into a level-one mesh
482  libmesh_assert(test_level_one(true));
483 
484  // Possibly clean up the refinement flags from
485  // a previous step. While we're at it, see if this method should be
486  // a no-op.
487  bool elements_flagged = false;
488 
489  for (auto & elem : _mesh.element_ptr_range())
490  {
491  // This might be left over from the last step
492  const Elem::RefinementState flag = elem->refinement_flag();
493 
494  // Set refinement flag to INACTIVE if the
495  // element isn't active
496  if ( !elem->active())
497  {
498  elem->set_refinement_flag(Elem::INACTIVE);
499  elem->set_p_refinement_flag(Elem::INACTIVE);
500  }
501  else if (flag == Elem::JUST_REFINED)
502  elem->set_refinement_flag(Elem::DO_NOTHING);
503  else if (!elements_flagged)
504  {
505  if (flag == Elem::REFINE || flag == Elem::COARSEN)
506  elements_flagged = true;
507  else
508  {
509  const Elem::RefinementState pflag =
510  elem->p_refinement_flag();
511  if (pflag == Elem::REFINE || pflag == Elem::COARSEN)
512  elements_flagged = true;
513  }
514  }
515  }
516 
517  // Did *any* processor find elements flagged for AMR/C?
518  _mesh.comm().max(elements_flagged);
519 
520  // If we have nothing to do, let's not bother verifying that nothing
521  // is compatible with nothing.
522  if (!elements_flagged)
523  return false;
524 
525  // Parallel consistency has to come first, or coarsening
526  // along processor boundaries might occasionally be falsely
527  // prevented
528 #ifdef DEBUG
529  bool flags_were_consistent = this->make_flags_parallel_consistent();
530 
531  libmesh_assert (flags_were_consistent);
532 #endif
533 
534  // Smooth refinement and coarsening flags
535  _smooth_flags(true, true);
536 
537  // First coarsen the flagged elements.
538  const bool coarsening_changed_mesh =
539  this->_coarsen_elements ();
540 
541  // First coarsen the flagged elements.
542  // FIXME: test_level_one now tests consistency across periodic
543  // boundaries, which requires a point_locator, which just got
544  // invalidated by _coarsen_elements() and hasn't yet been cleared by
545  // prepare_for_use().
546 
547  // libmesh_assert(this->make_coarsening_compatible());
548  // libmesh_assert(this->make_refinement_compatible());
549 
550  // FIXME: This won't pass unless we add a redundant find_neighbors()
551  // call or replace find_neighbors() with on-the-fly neighbor updating
552  // libmesh_assert(!this->eliminate_unrefined_patches());
553 
554  // We can't contract the mesh ourselves anymore - a System might
555  // need to restrict old coefficient vectors first
556  // _mesh.contract();
557 
558  // First coarsen the flagged elements.
559  // Now refine the flagged elements. This will
560  // take up some space, maybe more than what was freed.
561  const bool refining_changed_mesh =
562  this->_refine_elements();
563 
564  // First coarsen the flagged elements.
565  // Finally, the new mesh needs to be prepared for use
566  if (coarsening_changed_mesh || refining_changed_mesh)
567  {
568 #ifdef DEBUG
570 #endif
571 
572  _mesh.prepare_for_use (/*skip_renumber =*/false);
573 
575  libmesh_assert(test_level_one(true));
576  libmesh_assert(test_unflagged(true));
577  libmesh_assert(this->make_coarsening_compatible());
578  libmesh_assert(this->make_refinement_compatible());
579  // FIXME: This won't pass unless we add a redundant find_neighbors()
580  // call or replace find_neighbors() with on-the-fly neighbor updating
581  // libmesh_assert(!this->eliminate_unrefined_patches());
582 
583  return true;
584  }
585  else
586  {
588  libmesh_assert(test_level_one(true));
589  libmesh_assert(test_unflagged(true));
590  libmesh_assert(this->make_coarsening_compatible());
591  libmesh_assert(this->make_refinement_compatible());
592  }
593 
594  // Otherwise there was no change in the mesh,
595  // let the user know. Also, there is no need
596  // to prepare the mesh for use since it did not change.
597  return false;
598 
599 }
const Parallel::Communicator & comm() const
bool test_level_one(bool libmesh_assert_yes=false)
virtual SimpleRange< element_iterator > element_ptr_range()=0
unsigned char _face_level_mismatch_limit
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:152
bool test_unflagged(bool libmesh_assert_yes=false)
void _smooth_flags(bool refining, bool coarsening)
virtual void libmesh_assert_valid_parallel_ids() const
Definition: mesh_base.h:1007

◆ 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 682 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _refine_elements(), _smooth_flags(), libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_ptr_range(), libMesh::Elem::INACTIVE, libMesh::Elem::JUST_REFINED, make_flags_parallel_consistent(), make_refinement_compatible(), libMesh::out, libMesh::MeshBase::prepare_for_use(), and test_level_one().

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

683 {
684  // This function must be run on all processors at once
685  parallel_object_only();
686 
688  libmesh_assert(test_level_one(true));
689 
690  // Possibly clean up the refinement flags from
691  // a previous step
692  for (auto & elem : _mesh.element_ptr_range())
693  {
694  // Set refinement flag to INACTIVE if the
695  // element isn't active
696  if (!elem->active())
697  {
698  elem->set_refinement_flag(Elem::INACTIVE);
699  elem->set_p_refinement_flag(Elem::INACTIVE);
700  }
701 
702  // This might be left over from the last step
703  if (elem->refinement_flag() == Elem::JUST_REFINED)
704  elem->set_refinement_flag(Elem::DO_NOTHING);
705  }
706 
707 
708 
709  // Parallel consistency has to come first, or coarsening
710  // along processor boundaries might occasionally be falsely
711  // prevented
712  bool flags_were_consistent = this->make_flags_parallel_consistent();
713 
714  // In theory, we should be able to remove the above call, which can
715  // be expensive and should be unnecessary. In practice, doing
716  // consistent flagging in parallel is hard, it's impossible to
717  // verify at the library level if it's being done by user code, and
718  // we don't want to abort large parallel runs in opt mode... but we
719  // do want to warn that they should be fixed.
720  libmesh_assert(flags_were_consistent);
721  if (!flags_were_consistent)
722  {
723  libMesh::out << "Refinement flags were not consistent between processors!\n"
724  << "Correcting and continuing.";
725  }
726 
727  // Smooth refinement flags
728  _smooth_flags(true, false);
729 
730  // Now refine the flagged elements. This will
731  // take up some space, maybe more than what was freed.
732  const bool mesh_changed =
733  this->_refine_elements();
734 
736  libmesh_assert(test_level_one(true));
737  libmesh_assert(this->make_refinement_compatible());
738  // FIXME: This won't pass unless we add a redundant find_neighbors()
739  // call or replace find_neighbors() with on-the-fly neighbor updating
740  // libmesh_assert(!this->eliminate_unrefined_patches());
741 
742  // Finally, the new mesh needs to be prepared for use
743  if (mesh_changed)
744  _mesh.prepare_for_use (/*skip_renumber =*/false);
745 
746  return mesh_changed;
747 }
bool test_level_one(bool libmesh_assert_yes=false)
virtual SimpleRange< element_iterator > element_ptr_range()=0
unsigned char _face_level_mismatch_limit
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:152
void _smooth_flags(bool refining, bool coarsening)
OStreamProxy out(std::cout)

◆ 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 876 of file mesh_refinement.h.

References _refine_fraction, and _use_member_parameters.

877 {
878  _use_member_parameters = true;
879  return _refine_fraction;
880 }

◆ set_enforce_mismatch_limit_prior_to_refinement()

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

Set _enforce_mismatch_limit_prior_to_refinement option. Defaults to false.

Deprecated:
Use enforce_mismatch_limit_prior_to_refinement() instead.

Definition at line 944 of file mesh_refinement.h.

References enforce_mismatch_limit_prior_to_refinement().

945 {
946  libmesh_deprecated();
948 }
bool & enforce_mismatch_limit_prior_to_refinement()

◆ set_periodic_boundaries_ptr()

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

Sets the PeriodicBoundaries pointer.

◆ 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 635 of file mesh_refinement_flagging.C.

References _mesh, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::element_ptr_range(), and libMesh::Elem::INACTIVE.

636 {
637  for (auto & elem : _mesh.element_ptr_range())
638  {
639  if (elem->active())
640  {
641  elem->set_p_refinement_flag(elem->refinement_flag());
642  elem->set_refinement_flag(Elem::DO_NOTHING);
643  }
644  else
645  {
646  elem->set_p_refinement_flag(elem->refinement_flag());
647  elem->set_refinement_flag(Elem::INACTIVE);
648  }
649  }
650 }
virtual SimpleRange< element_iterator > element_ptr_range()=0

◆ test_level_one()

bool libMesh::MeshRefinement::test_level_one ( bool  libmesh_assert_yes = false)
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 352 of file mesh_refinement.C.

References _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::MeshBase::active_local_element_ptr_range(), libMesh::ParallelObject::comm(), libMesh::Elem::level(), libMesh::Parallel::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().

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

◆ test_unflagged()

bool libMesh::MeshRefinement::test_unflagged ( bool  libmesh_assert_yes = false)
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 427 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_local_element_ptr_range(), libMesh::Elem::COARSEN, libMesh::ParallelObject::comm(), libMesh::Parallel::Communicator::max(), libMesh::out, and libMesh::Elem::REFINE.

Referenced by refine_and_coarsen_elements().

428 {
429  // This function must be run on all processors at once
430  parallel_object_only();
431 
432  bool found_flag = false;
433 
434 #ifndef NDEBUG
435  Elem * failed_elem = nullptr;
436 #endif
437 
438  // Search for local flags
439  for (auto & elem : _mesh.active_local_element_ptr_range())
440  if (elem->refinement_flag() == Elem::REFINE ||
441  elem->refinement_flag() == Elem::COARSEN ||
442  elem->p_refinement_flag() == Elem::REFINE ||
443  elem->p_refinement_flag() == Elem::COARSEN)
444  {
445  found_flag = true;
446 #ifndef NDEBUG
447  failed_elem = elem;
448 #endif
449  break;
450  }
451 
452  // If we found a flag on any processor, it counts
453  this->comm().max(found_flag);
454 
455  if (found_flag)
456  {
457 #ifndef NDEBUG
458  if (libmesh_assert_pass)
459  {
460  libMesh::out <<
461  "MeshRefinement test_unflagged failure, element: " <<
462  *failed_elem << std::endl;
463  }
464 #endif
465  // We didn't pass the "elements are unflagged" test,
466  // so libmesh_assert that we're allowed not to
467  libmesh_assert(!libmesh_assert_pass);
468  return false;
469  }
470  return true;
471 }
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
OStreamProxy out(std::cout)

◆ topological_neighbor()

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

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

Definition at line 1789 of file mesh_refinement.C.

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

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

1792 {
1793 #ifdef LIBMESH_ENABLE_PERIODIC
1794  if (_periodic_boundaries && !_periodic_boundaries->empty())
1795  {
1796  libmesh_assert(point_locator);
1797  return elem->topological_neighbor(side, _mesh, *point_locator, _periodic_boundaries);
1798  }
1799 #endif
1800  return elem->neighbor_ptr(side);
1801 }
unsigned short int side
Definition: xdr_io.C:50
PeriodicBoundaries * _periodic_boundaries

◆ 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 932 of file mesh_refinement.h.

References _underrefined_boundary_limit.

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

933 {
935 }
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 1701 of file mesh_refinement.C.

References _coarsen_elements(), _mesh, libMesh::MeshBase::active_element_ptr_range(), libMesh::MeshBase::ancestor_elements_begin(), libMesh::MeshBase::ancestor_elements_end(), libMesh::Parallel::any_source, libMesh::as_range(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::ParallelObject::comm(), libMesh::MeshBase::elem_ref(), libMesh::Parallel::Communicator::get_unique_tag(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_replicated(), libMesh::ParallelObject::n_processors(), libMesh::MeshBase::not_local_elements_begin(), libMesh::MeshBase::not_local_elements_end(), libMesh::MeshBase::prepare_for_use(), libMesh::ParallelObject::processor_id(), libMesh::Parallel::Communicator::receive(), libMesh::Elem::refinement_flag(), libMesh::Parallel::Communicator::send(), libMesh::Elem::set_refinement_flag(), libMesh::Parallel::sync_dofobject_data_by_id(), and libMesh::Parallel::wait().

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

1702 {
1703  // Coarsen n times
1704  for (unsigned int rstep=0; rstep<n; rstep++)
1705  {
1706  // Clean up the refinement flags
1707  this->clean_refinement_flags();
1708 
1709  // Flag all the active elements for coarsening.
1710  for (auto & elem : _mesh.active_element_ptr_range())
1711  {
1712  elem->set_refinement_flag(Elem::COARSEN);
1713  if (elem->parent())
1714  elem->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
1715  }
1716 
1717  // On a distributed mesh, we may have parent elements with
1718  // remote active children. To keep flags consistent, we'll need
1719  // a communication step.
1720  if (!_mesh.is_replicated())
1721  {
1722  const processor_id_type n_proc = _mesh.n_processors();
1723  const processor_id_type my_proc_id = _mesh.processor_id();
1724 
1725  std::vector<std::vector<dof_id_type>>
1726  parents_to_coarsen(n_proc);
1727 
1728  for (const auto & elem : as_range(_mesh.ancestor_elements_begin(), _mesh.ancestor_elements_end()))
1729  if (elem->processor_id() != my_proc_id &&
1730  elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1731  parents_to_coarsen[elem->processor_id()].push_back(elem->id());
1732 
1733  Parallel::MessageTag
1734  coarsen_tag = this->comm().get_unique_tag(271);
1735  std::vector<Parallel::Request> coarsen_push_requests(n_proc-1);
1736 
1737  for (processor_id_type p = 0; p != n_proc; ++p)
1738  {
1739  if (p == my_proc_id)
1740  continue;
1741 
1742  Parallel::Request &request =
1743  coarsen_push_requests[p - (p > my_proc_id)];
1744 
1745  _mesh.comm().send
1746  (p, parents_to_coarsen[p], request, coarsen_tag);
1747  }
1748 
1749  for (processor_id_type p = 1; p != n_proc; ++p)
1750  {
1751  std::vector<dof_id_type> my_parents_to_coarsen;
1752  _mesh.comm().receive
1753  (Parallel::any_source, my_parents_to_coarsen,
1754  coarsen_tag);
1755 
1756  for (const auto & id : my_parents_to_coarsen)
1757  {
1758  Elem & elem = _mesh.elem_ref(id);
1759  libmesh_assert(elem.refinement_flag() == Elem::INACTIVE ||
1760  elem.refinement_flag() == Elem::COARSEN_INACTIVE);
1762  }
1763  }
1764 
1765  Parallel::wait(coarsen_push_requests);
1766 
1767  SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
1770  (this->comm(), _mesh.not_local_elements_begin(),
1772  // We'd like a smaller sync, but this leads to bugs?
1773  // SyncCoarsenInactive(),
1774  hsync);
1775  }
1776 
1777  // Coarsen all the elements we just flagged.
1778  this->_coarsen_elements();
1779  }
1780 
1781 
1782  // Finally, the new mesh probably needs to be prepared for use
1783  if (n > 0)
1784  _mesh.prepare_for_use (/*skip_renumber =*/false);
1785 }
RefinementState refinement_flag() const
Definition: elem.h:2638
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
virtual element_iterator ancestor_elements_begin()=0
void wait(std::vector< Request > &r)
Definition: request.C:213
virtual element_iterator not_local_elements_end()=0
const unsigned int any_source
Definition: communicator.h:70
virtual element_iterator ancestor_elements_end()=0
uint8_t processor_id_type
Definition: id_types.h:99
MPI_Request request
Definition: request.h:40
void set_refinement_flag(const RefinementState rflag)
Definition: elem.h:2646
const Parallel::Communicator & comm() const
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
MessageTag get_unique_tag(int tagvalue) const
Definition: communicator.C:201
processor_id_type n_processors() const
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:152
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
virtual bool is_replicated() const
Definition: mesh_base.h:176
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:504
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
virtual element_iterator not_local_elements_begin()=0
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 1661 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), and libMesh::Elem::JUST_COARSENED.

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

1662 {
1663  // Coarsen p times
1664  for (unsigned int rstep=0; rstep<n; rstep++)
1665  for (auto & elem : _mesh.active_element_ptr_range())
1666  if (elem->p_level() > 0)
1667  {
1668  // P coarsen all the active elements
1669  elem->set_p_level(elem->p_level()-1);
1670  elem->set_p_refinement_flag(Elem::JUST_COARSENED);
1671  }
1672 }
virtual SimpleRange< element_iterator > active_element_ptr_range()=0

◆ uniformly_p_refine()

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

Uniformly p refines the mesh n times.

Definition at line 1647 of file mesh_refinement.C.

References _mesh, libMesh::MeshBase::active_element_ptr_range(), and libMesh::Elem::JUST_REFINED.

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

1648 {
1649  // Refine n times
1650  for (unsigned int rstep=0; rstep<n; rstep++)
1651  for (auto & elem : _mesh.active_element_ptr_range())
1652  {
1653  // P refine all the active elements
1654  elem->set_p_level(elem->p_level()+1);
1655  elem->set_p_refinement_flag(Elem::JUST_REFINED);
1656  }
1657 }
virtual SimpleRange< element_iterator > active_element_ptr_range()=0

◆ uniformly_refine()

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

Uniformly refines the mesh n times.

Definition at line 1676 of file mesh_refinement.C.

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

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

1677 {
1678  // Refine n times
1679  // FIXME - this won't work if n>1 and the mesh
1680  // has already been attached to an equation system
1681  for (unsigned int rstep=0; rstep<n; rstep++)
1682  {
1683  // Clean up the refinement flags
1684  this->clean_refinement_flags();
1685 
1686  // Flag all the active elements for refinement.
1687  for (auto & elem : _mesh.active_element_ptr_range())
1688  elem->set_refinement_flag(Elem::REFINE);
1689 
1690  // Refine all the elements we just flagged.
1691  this->_refine_elements();
1692  }
1693 
1694  // Finally, the new mesh probably needs to be prepared for use
1695  if (n > 0)
1696  _mesh.prepare_for_use (/*skip_renumber =*/false);
1697 }
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:152

◆ update_nodes_map()

void libMesh::MeshRefinement::update_nodes_map ( )
private

Updates the _new_nodes_map

Definition at line 345 of file mesh_refinement.C.

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

Referenced by _coarsen_elements(), and _refine_elements().

346 {
347  this->_new_nodes_map.init(_mesh);
348 }
void init(MeshBase &)
Definition: topology_map.C:35

Member Data Documentation

◆ _absolute_global_tolerance

Real libMesh::MeshRefinement::_absolute_global_tolerance
private

◆ _coarsen_by_parents

bool libMesh::MeshRefinement::_coarsen_by_parents
private

◆ _coarsen_fraction

◆ _coarsen_threshold

Real libMesh::MeshRefinement::_coarsen_threshold
private

◆ _communicator

◆ _edge_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_edge_level_mismatch_limit
private

Definition at line 770 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 844 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

◆ _mesh

◆ _nelem_target

dof_id_type libMesh::MeshRefinement::_nelem_target
private

Definition at line 765 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 737 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 771 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 773 of file mesh_refinement.h.

Referenced by _smooth_flags(), and overrefined_boundary_limit().

◆ _periodic_boundaries

PeriodicBoundaries* libMesh::MeshRefinement::_periodic_boundaries
private

◆ _refine_fraction

◆ _underrefined_boundary_limit

signed char libMesh::MeshRefinement::_underrefined_boundary_limit
private

Definition at line 774 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 749 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: