libMesh
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
libMesh::MeshRefinement Class Reference

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

#include <mesh_refinement.h>

Inheritance diagram for libMesh::MeshRefinement:
[legend]

Classes

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

Public Member Functions

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

Protected Attributes

const Parallel::Communicator_communicator
 

Private Types

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

Private Member Functions

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

Private Attributes

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

Detailed Description

Implements (adaptive) mesh refinement algorithms for a MeshBase.

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

Responsible for mesh refinement algorithms and data.

Definition at line 61 of file mesh_refinement.h.

Member Enumeration Documentation

◆ NeighborType

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

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

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

Definition at line 867 of file mesh_refinement.h.

Constructor & Destructor Documentation

◆ MeshRefinement() [1/2]

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

Constructor.

Definition at line 95 of file mesh_refinement.C.

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

◆ MeshRefinement() [2/2]

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

◆ ~MeshRefinement()

libMesh::MeshRefinement::~MeshRefinement ( )
default

Destructor.

Deletes all the elements that are currently stored.

Member Function Documentation

◆ _coarsen_elements()

bool libMesh::MeshRefinement::_coarsen_elements ( )
private

Coarsens user-requested elements.

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

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

Definition at line 1371 of file mesh_refinement.C.

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

References libMesh::libmesh_assert(), libMesh::MeshCommunication::make_nodes_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), and libMesh::MeshCommunication::send_coarse_ghosts().

◆ _refine_elements()

bool libMesh::MeshRefinement::_refine_elements ( )
private

Refines user-requested elements.

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

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

Definition at line 1504 of file mesh_refinement.C.

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

References libMesh::as_range(), libMesh::libmesh_assert(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshCommunication::make_new_nodes_parallel_consistent(), and libMesh::MeshCommunication::make_p_levels_parallel_consistent().

◆ _smooth_flags()

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

Smooths refinement flags according to current settings.

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

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

Definition at line 1636 of file mesh_refinement.C.

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

References libMesh::libmesh_assert().

◆ absolute_global_tolerance()

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

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

absolute_global_tolerance is 0 by default.

Definition at line 918 of file mesh_refinement.h.

919{
922}

References _absolute_global_tolerance, and _use_member_parameters.

Referenced by main().

◆ add_elem() [1/2]

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

Adds the element elem to the mesh.

Definition at line 208 of file mesh_refinement.C.

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

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

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

◆ add_elem() [2/2]

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

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

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

Definition at line 214 of file mesh_refinement.C.

215{
216 libmesh_assert(elem);
217 return _mesh.add_elem(std::move(elem));
218}

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

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

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

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

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

◆ add_p_to_h_refinement()

void libMesh::MeshRefinement::add_p_to_h_refinement ( )

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

Definition at line 673 of file mesh_refinement_flagging.C.

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

References _mesh.

Referenced by main().

◆ allow_unrefined_patches()

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

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

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

Definition at line 949 of file mesh_refinement.h.

950{
952}

References _allow_unrefined_patches.

◆ clean_refinement_flags()

void libMesh::MeshRefinement::clean_refinement_flags ( )

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

Definition at line 681 of file mesh_refinement_flagging.C.

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

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

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

◆ clear()

void libMesh::MeshRefinement::clear ( )

Deletes all the data that are currently stored.

Definition at line 134 of file mesh_refinement.C.

135{
137}

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

◆ coarsen_by_parents()

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

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

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

coarsen_by_parents is true by default.

Definition at line 882 of file mesh_refinement.h.

883{
885 return _coarsen_by_parents;
886}

References _coarsen_by_parents, and _use_member_parameters.

Referenced by main().

◆ coarsen_elements()

bool libMesh::MeshRefinement::coarsen_elements ( )

Only coarsens the user-requested elements.

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

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

Definition at line 620 of file mesh_refinement.C.

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

References libMesh::libmesh_assert().

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

◆ coarsen_fraction()

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

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

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

Definition at line 894 of file mesh_refinement.h.

895{
897 return _coarsen_fraction;
898}

References _coarsen_fraction, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

◆ coarsen_threshold()

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

The coarsen_threshold provides hysteresis in AMR/C strategies.

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

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

Definition at line 906 of file mesh_refinement.h.

907{
909 return _coarsen_threshold;
910}

References _coarsen_threshold, and _use_member_parameters.

Referenced by main().

◆ comm()

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

Definition at line 97 of file parallel_object.h.

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

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

◆ create_parent_error_vector()

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

Calculates the error on all coarsenable parents.

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

Definition at line 221 of file mesh_refinement.C.

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

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

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

◆ edge_level_mismatch_limit()

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

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

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

edge_level_mismatch_limit is 0 by default.

Definition at line 929 of file mesh_refinement.h.

930{
932}

References _edge_level_mismatch_limit.

◆ eliminate_unrefined_patches()

bool libMesh::MeshRefinement::eliminate_unrefined_patches ( )
private

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

This algorithm will transform this mesh:

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

into this:

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

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

Definition at line 367 of file mesh_refinement_smoothing.C.

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

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

◆ enforce_mismatch_limit_prior_to_refinement() [1/4]

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

Get/set the _enforce_mismatch_limit_prior_to_refinement flag.

The default value for this flag is false.

Definition at line 954 of file mesh_refinement.h.

References _enforce_mismatch_limit_prior_to_refinement.

Referenced by limit_level_mismatch_at_edge(), and limit_level_mismatch_at_node().

◆ enforce_mismatch_limit_prior_to_refinement() [2/4]

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

◆ enforce_mismatch_limit_prior_to_refinement() [3/4]

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

◆ enforce_mismatch_limit_prior_to_refinement() [4/4]

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

Definition at line 547 of file mesh_refinement_smoothing.C.

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

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().

◆ face_level_mismatch_limit()

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

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

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

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

Definition at line 924 of file mesh_refinement.h.

925{
927}

References _face_level_mismatch_limit.

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

◆ flag_elements_by()

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

Flag elements based on a function object.

The class ElementFlagging defines a mechanism for implementing refinement strategies.

Definition at line 647 of file mesh_refinement_flagging.C.

648{
649 element_flagging.flag_elements();
650}

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

◆ flag_elements_by_elem_fraction()

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

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

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

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

Definition at line 445 of file mesh_refinement_flagging.C.

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

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

Referenced by main().

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

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

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

Referenced by assemble_and_solve(), and main().

◆ flag_elements_by_error_tolerance()

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

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

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

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

Definition at line 170 of file mesh_refinement_flagging.C.

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

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

Referenced by main().

◆ flag_elements_by_mean_stddev()

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

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

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

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

Definition at line 583 of file mesh_refinement_flagging.C.

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

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

◆ flag_elements_by_nelem_target()

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

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

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

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

Definition at line 237 of file mesh_refinement_flagging.C.

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

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

Referenced by main().

◆ get_mesh() [1/2]

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

Definition at line 346 of file mesh_refinement.h.

346{ return _mesh; }

References _mesh.

◆ get_mesh() [2/2]

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

Definition at line 340 of file mesh_refinement.h.

340{ return _mesh; }

References _mesh.

◆ has_topological_neighbor()

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

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

Definition at line 1849 of file mesh_refinement.C.

1852{
1853#ifdef LIBMESH_ENABLE_PERIODIC
1855 {
1856 libmesh_assert(point_locator);
1857 return elem->has_topological_neighbor(neighbor, _mesh, *point_locator, _periodic_boundaries);
1858 }
1859#endif
1860 return elem->has_neighbor(neighbor);
1861}

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

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

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

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

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

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

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

◆ limit_overrefined_boundary()

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

Definition at line 254 of file mesh_refinement_smoothing.C.

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

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

◆ limit_underrefined_boundary()

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

Definition at line 308 of file mesh_refinement_smoothing.C.

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

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

◆ make_coarsening_compatible()

bool libMesh::MeshRefinement::make_coarsening_compatible ( )
private

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

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

Definition at line 815 of file mesh_refinement.C.

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

References libMesh::Elem::active(), libMesh::as_range(), libMesh::Elem::child_ref_range(), libMesh::Elem::has_children(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::DofObject::processor_id(), libMesh::Elem::refinement_flag(), libMesh::remote_elem, and libMesh::Elem::set_refinement_flag().

◆ make_flags_parallel_consistent()

bool libMesh::MeshRefinement::make_flags_parallel_consistent ( )

Copy refinement flags on ghost elements from their local processors.

Returns
true if any flags changed.

Definition at line 787 of file mesh_refinement.C.

788{
789 // This function must be run on all processors at once
790 parallel_object_only();
791
792 LOG_SCOPE ("make_flags_parallel_consistent()", "MeshRefinement");
793
794 SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
797 (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), hsync);
798
799 SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
802 (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), psync);
803
804 // If we weren't consistent in both h and p on every processor then
805 // we weren't globally consistent
806 bool parallel_consistent = hsync.parallel_consistent &&
807 psync.parallel_consistent;
808 this->comm().min(parallel_consistent);
809
810 return parallel_consistent;
811}
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition elem.h:3251
RefinementState p_refinement_flag() const
Definition elem.h:3243

References libMesh::SyncRefinementFlags::parallel_consistent.

Referenced by libMesh::HPCoarsenTest::select_refinement().

◆ make_refinement_compatible()

bool libMesh::MeshRefinement::make_refinement_compatible ( )
private

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

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

Definition at line 1195 of file mesh_refinement.C.

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

References libMesh::Elem::active(), libMesh::Elem::child_ref_range(), libMesh::Elem::has_children(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::parent(), libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Elem::set_p_refinement_flag(), and libMesh::Elem::set_refinement_flag().

◆ max_h_level()

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

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

max_h_level is unlimited (libMesh::invalid_uint) by default

Definition at line 900 of file mesh_refinement.h.

901{
903 return _max_h_level;
904}

References _max_h_level, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

◆ n_processors()

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

Definition at line 103 of file parallel_object.h.

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

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

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

◆ nelem_target()

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

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

nelem_target is 0 by default.

Definition at line 912 of file mesh_refinement.h.

913{
915 return _nelem_target;
916}

References _nelem_target, and _use_member_parameters.

Referenced by main().

◆ node_level_mismatch_limit()

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

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

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

node_level_mismatch_limit is 0 by default.

Definition at line 934 of file mesh_refinement.h.

935{
937}

References _node_level_mismatch_limit.

◆ operator=()

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

◆ overrefined_boundary_limit()

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

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

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

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

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

Definition at line 939 of file mesh_refinement.h.

940{
942}

References _overrefined_boundary_limit.

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

◆ processor_id()

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

Definition at line 114 of file parallel_object.h.

115 { return cast_int<processor_id_type>(_communicator.rank()); }
processor_id_type rank() const

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

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

◆ refine_and_coarsen_elements()

bool libMesh::MeshRefinement::refine_and_coarsen_elements ( )

Refines and coarsens user-requested elements.

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

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

Definition at line 482 of file mesh_refinement.C.

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

References libMesh::libmesh_assert().

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

◆ refine_elements()

bool libMesh::MeshRefinement::refine_elements ( )

Only refines the user-requested elements.

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

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

Definition at line 699 of file mesh_refinement.C.

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

References libMesh::libmesh_assert().

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

◆ refine_fraction()

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

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

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

Definition at line 888 of file mesh_refinement.h.

889{
891 return _refine_fraction;
892}

References _refine_fraction, and _use_member_parameters.

Referenced by assemble_and_solve(), and main().

◆ set_periodic_boundaries_ptr()

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

Sets the PeriodicBoundaries pointer.

Referenced by main().

◆ switch_h_to_p_refinement()

void libMesh::MeshRefinement::switch_h_to_p_refinement ( )

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

Definition at line 654 of file mesh_refinement_flagging.C.

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

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

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

◆ test_level_one()

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

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

Definition at line 359 of file mesh_refinement.C.

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

References libMesh::Elem::active(), libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::out, libMesh::Elem::p_level(), and libMesh::remote_elem.

◆ test_unflagged()

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

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

Definition at line 434 of file mesh_refinement.C.

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

References libMesh::libmesh_assert(), and libMesh::out.

◆ topological_neighbor()

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

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

Definition at line 1833 of file mesh_refinement.C.

1836{
1837#ifdef LIBMESH_ENABLE_PERIODIC
1839 {
1840 libmesh_assert(point_locator);
1841 return elem->topological_neighbor(side, _mesh, *point_locator, _periodic_boundaries);
1842 }
1843#endif
1844 return elem->neighbor_ptr(side);
1845}

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

◆ underrefined_boundary_limit()

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

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

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

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

Definition at line 944 of file mesh_refinement.h.

945{
947}

References _underrefined_boundary_limit.

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

◆ uniformly_coarsen()

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

Attempts to uniformly coarsen the mesh n times.

Definition at line 1745 of file mesh_refinement.C.

1746{
1747 // Coarsen n times
1748 for (unsigned int rstep=0; rstep<n; rstep++)
1749 {
1750 // Clean up the refinement flags
1751 this->clean_refinement_flags();
1752
1753 // Flag all the active elements for coarsening.
1754 for (auto & elem : _mesh.active_element_ptr_range())
1755 {
1756 elem->set_refinement_flag(Elem::COARSEN);
1757 if (elem->parent())
1758 elem->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
1759 }
1760
1761 // On a distributed mesh, we may have parent elements with
1762 // remote active children. To keep flags consistent, we'll need
1763 // a communication step.
1764 if (!_mesh.is_replicated())
1765 {
1766 const processor_id_type n_proc = _mesh.n_processors();
1767 const processor_id_type my_proc_id = _mesh.processor_id();
1768
1769 std::vector<std::vector<dof_id_type>>
1770 parents_to_coarsen(n_proc);
1771
1772 for (const auto & elem : as_range(_mesh.ancestor_elements_begin(), _mesh.ancestor_elements_end()))
1773 if (elem->processor_id() != my_proc_id &&
1774 elem->refinement_flag() == Elem::COARSEN_INACTIVE)
1775 parents_to_coarsen[elem->processor_id()].push_back(elem->id());
1776
1777 Parallel::MessageTag
1778 coarsen_tag = this->comm().get_unique_tag();
1779 std::vector<Parallel::Request> coarsen_push_requests(n_proc-1);
1780
1781 for (processor_id_type p = 0; p != n_proc; ++p)
1782 {
1783 if (p == my_proc_id)
1784 continue;
1785
1786 Parallel::Request &request =
1787 coarsen_push_requests[p - (p > my_proc_id)];
1788
1789 _mesh.comm().send
1790 (p, parents_to_coarsen[p], request, coarsen_tag);
1791 }
1792
1793 for (processor_id_type p = 1; p != n_proc; ++p)
1794 {
1795 std::vector<dof_id_type> my_parents_to_coarsen;
1797 (Parallel::any_source, my_parents_to_coarsen,
1798 coarsen_tag);
1799
1800 for (const auto & id : my_parents_to_coarsen)
1801 {
1802 Elem & elem = _mesh.elem_ref(id);
1803 libmesh_assert(elem.refinement_flag() == Elem::INACTIVE ||
1804 elem.refinement_flag() == Elem::COARSEN_INACTIVE);
1805 elem.set_refinement_flag(Elem::COARSEN_INACTIVE);
1806 }
1807 }
1808
1809 Parallel::wait(coarsen_push_requests);
1810
1811 SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
1814 (this->comm(), _mesh.not_local_elements_begin(),
1815 _mesh.not_local_elements_end(),
1816 // We'd like a smaller sync, but this leads to bugs?
1817 // SyncCoarsenInactive(),
1818 hsync);
1819 }
1820
1821 // Coarsen all the elements we just flagged.
1822 this->_coarsen_elements();
1823 }
1824
1825
1826 // Finally, the new mesh probably needs to be prepared for use
1827 if (n > 0)
1829}

References libMesh::as_range(), libMesh::libmesh_assert(), libMesh::Elem::refinement_flag(), and libMesh::Elem::set_refinement_flag().

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

◆ uniformly_p_coarsen()

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

Attempts to uniformly p coarsen the mesh n times.

Definition at line 1705 of file mesh_refinement.C.

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

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

◆ uniformly_p_refine()

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

Uniformly p refines the mesh n times.

Definition at line 1691 of file mesh_refinement.C.

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

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

◆ uniformly_refine()

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

Uniformly refines the mesh n times.

Definition at line 1720 of file mesh_refinement.C.

1721{
1722 // Refine n times
1723 // FIXME - this won't work if n>1 and the mesh
1724 // has already been attached to an equation system
1725 for (unsigned int rstep=0; rstep<n; rstep++)
1726 {
1727 // Clean up the refinement flags
1728 this->clean_refinement_flags();
1729
1730 // Flag all the active elements for refinement.
1731 for (auto & elem : _mesh.active_element_ptr_range())
1732 elem->set_refinement_flag(Elem::REFINE);
1733
1734 // Refine all the elements we just flagged.
1735 this->_refine_elements();
1736 }
1737
1738 // Finally, the new mesh probably needs to be prepared for use
1739 if (n > 0)
1741}

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

◆ update_nodes_map()

void libMesh::MeshRefinement::update_nodes_map ( )
private

Updates the _new_nodes_map.

Definition at line 352 of file mesh_refinement.C.

353{
355}
void init(MeshBase &)

Member Data Documentation

◆ _absolute_global_tolerance

Real libMesh::MeshRefinement::_absolute_global_tolerance
private

◆ _allow_unrefined_patches

bool libMesh::MeshRefinement::_allow_unrefined_patches
private

Definition at line 786 of file mesh_refinement.h.

Referenced by allow_unrefined_patches(), and eliminate_unrefined_patches().

◆ _coarsen_by_parents

bool libMesh::MeshRefinement::_coarsen_by_parents
private

◆ _coarsen_fraction

Real libMesh::MeshRefinement::_coarsen_fraction
private

◆ _coarsen_threshold

Real libMesh::MeshRefinement::_coarsen_threshold
private

◆ _communicator

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

◆ _edge_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_edge_level_mismatch_limit
private

Definition at line 780 of file mesh_refinement.h.

Referenced by edge_level_mismatch_limit().

◆ _enforce_mismatch_limit_prior_to_refinement

bool libMesh::MeshRefinement::_enforce_mismatch_limit_prior_to_refinement
private

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

Applies to all mismatch methods.

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

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

into this:

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

by moving the refinement flag to the indicated element.

Default value is false.

Definition at line 856 of file mesh_refinement.h.

Referenced by enforce_mismatch_limit_prior_to_refinement(), enforce_mismatch_limit_prior_to_refinement(), enforce_mismatch_limit_prior_to_refinement(), 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

Definition at line 779 of file mesh_refinement.h.

Referenced by face_level_mismatch_limit().

◆ _max_h_level

unsigned int libMesh::MeshRefinement::_max_h_level
private

◆ _mesh

MeshBase& libMesh::MeshRefinement::_mesh
private

◆ _nelem_target

dof_id_type libMesh::MeshRefinement::_nelem_target
private

Definition at line 775 of file mesh_refinement.h.

Referenced by flag_elements_by_nelem_target(), and nelem_target().

◆ _new_nodes_map

TopologyMap libMesh::MeshRefinement::_new_nodes_map
private

Data structure that holds the new nodes information.

Definition at line 747 of file mesh_refinement.h.

Referenced by add_node(), and clear().

◆ _node_level_mismatch_limit

unsigned char libMesh::MeshRefinement::_node_level_mismatch_limit
private

Definition at line 781 of file mesh_refinement.h.

Referenced by node_level_mismatch_limit().

◆ _overrefined_boundary_limit

signed char libMesh::MeshRefinement::_overrefined_boundary_limit
private

Definition at line 783 of file mesh_refinement.h.

Referenced by overrefined_boundary_limit().

◆ _periodic_boundaries

PeriodicBoundaries* libMesh::MeshRefinement::_periodic_boundaries
private

Definition at line 873 of file mesh_refinement.h.

◆ _refine_fraction

Real libMesh::MeshRefinement::_refine_fraction
private

◆ _underrefined_boundary_limit

signed char libMesh::MeshRefinement::_underrefined_boundary_limit
private

Definition at line 784 of file mesh_refinement.h.

Referenced by underrefined_boundary_limit().

◆ _use_member_parameters

bool libMesh::MeshRefinement::_use_member_parameters
private

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

Definition at line 759 of file mesh_refinement.h.

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


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