#include <mesh_refinement.h>
MeshRefinement (MeshBase &mesh)
~MeshRefinement ()
void clear ()
void flag_elements_by_error_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void flag_elements_by_error_tolerance (const ErrorVector &error_per_cell)
bool flag_elements_by_nelem_target (const ErrorVector &error_per_cell)
void flag_elements_by_elem_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void flag_elements_by_mean_stddev (const ErrorVector &error_per_cell, const Real refine_fraction=1.0, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void switch_h_to_p_refinement ()
void add_p_to_h_refinement ()
bool refine_and_coarsen_elements (const bool maintain_level_one=true)
bool coarsen_elements (const bool maintain_level_one=true)
bool refine_elements (const bool maintain_level_one=true)
void uniformly_refine (unsigned int n=1)
void uniformly_coarsen (unsigned int n=1)
void uniformly_p_refine (unsigned int n=1)
void uniformly_p_coarsen (unsigned int n=1)
bool test_level_one (bool libmesh_assert_yes=false)
bool test_unflagged (bool libmesh_assert_yes=false)
Node * add_point (const Point &p, const unsigned int processor_id, const Real tol)
Elem * add_elem (Elem *elem)
const MeshBase & get_mesh () const
MeshBase & get_mesh ()
bool & coarsen_by_parents ()
Real & refine_fraction ()
Real & coarsen_fraction ()
unsigned int & max_h_level ()
Real & coarsen_threshold ()
unsigned int & nelem_target ()
Real & absolute_global_tolerance ()
unsigned char & face_level_mismatch_limit ()
unsigned char & edge_level_mismatch_limit ()
unsigned char & node_level_mismatch_limit ()
MeshRefinement (const MeshRefinement &)
MeshRefinement & operator= (const MeshRefinement &)
bool _coarsen_elements ()
bool _refine_elements ()
bool limit_level_mismatch_at_node (const unsigned int max_mismatch)
bool limit_level_mismatch_at_edge (const unsigned int max_mismatch)
bool eliminate_unrefined_patches ()
void create_parent_error_vector (const ErrorVector &error_per_cell, ErrorVector &error_per_parent, Real &parent_error_min, Real &parent_error_max)
void update_nodes_map ()
void clean_refinement_flags ()
bool make_coarsening_compatible (const bool)
bool make_refinement_compatible (const bool)
bool make_flags_parallel_consistent ()
LocationMap< Node > _new_nodes_map
MeshBase & _mesh
bool _use_member_parameters
bool _coarsen_by_parents
Real _refine_fraction
Real _coarsen_fraction
unsigned int _max_h_level
Real _coarsen_threshold
unsigned int _nelem_target
Real _absolute_global_tolerance
unsigned char _face_level_mismatch_limit
unsigned char _edge_level_mismatch_limit
unsigned char _node_level_mismatch_limit
This is the MeshRefinement class. This class implements adaptive mesh refinement algorithms for a MeshBase.
Author:
Definition at line 58 of file mesh_refinement.h.
Definition at line 51 of file mesh_refinement.C.
:
_mesh(m),
_use_member_parameters(false),
_coarsen_by_parents(false),
_refine_fraction(0.3),
_coarsen_fraction(0.0),
_max_h_level(libMesh::invalid_uint),
_coarsen_threshold(10),
_nelem_target(0),
_absolute_global_tolerance(0.0),
_face_level_mismatch_limit(1),
_edge_level_mismatch_limit(0),
_node_level_mismatch_limit(0)
{
}
Definition at line 69 of file mesh_refinement.C.
References clear().
{
this->clear();
}
It is possible that for a given set of refinement flags there is actually no change upon calling this member function. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.
Definition at line 1358 of file mesh_refinement.C.
References _mesh, _new_nodes_map, Elem::active(), MeshBase::boundary_info, clear(), Elem::coarsen(), Elem::COARSEN, Elem::COARSEN_INACTIVE, Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), MeshBase::is_serial(), Elem::JUST_COARSENED, Elem::level(), MeshTools::libmesh_assert_valid_node_procids(), MeshCommunication::make_nodes_parallel_consistent(), std::max(), Elem::nullify_neighbors(), Elem::p_level(), Elem::p_refinement_flag(), Elem::refinement_flag(), Elem::set_p_level(), Elem::set_p_refinement_flag(), update_nodes_map(), and MeshBase::update_parallel_id_counts().
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and uniformly_coarsen().
{
// This function must be run on all processors at once
parallel_only();
START_LOG ('_coarsen_elements()', 'MeshRefinement');
// Flag indicating if this call actually changes the mesh
bool mesh_changed = false;
// Clear the unused_elements data structure.
// The elements have been packed since it was built,
// so there are _no_ unused elements. We cannot trust
// any iterators currently in this data structure.
// _unused_elements.clear();
MeshBase::element_iterator it = _mesh.elements_begin();
const MeshBase::element_iterator end = _mesh.elements_end();
// Loop over the elements.
for ( ; it != end; ++it)
{
Elem* elem = *it;
// Not necessary when using elem_iterator
// libmesh_assert (elem != NULL);
// active elements flagged for coarsening will
// no longer be deleted until MeshRefinement::contract()
if (elem->refinement_flag() == Elem::COARSEN)
{
// Huh? no level-0 element should be active
// and flagged for coarsening.
libmesh_assert (elem->level() != 0);
// Remove this element from any neighbor
// lists that point to it.
elem->nullify_neighbors();
// Remove any boundary information associated
// with this element
_mesh.boundary_info->remove (elem);
// Add this iterator to the _unused_elements
// data structure so we might fill it.
// The _unused_elements optimization is currently off.
// _unused_elements.push_back (it);
// Don't delete the element until
// MeshRefinement::contract()
// _mesh.delete_elem(elem);
// the mesh has certainly changed
mesh_changed = true;
}
// inactive elements flagged for coarsening
// will become active
else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
{
elem->coarsen();
libmesh_assert (elem->active());
// the mesh has certainly changed
mesh_changed = true;
}
if (elem->p_refinement_flag() == Elem::COARSEN)
{
if (elem->p_level() > 0)
{
elem->set_p_refinement_flag(Elem::JUST_COARSENED);
elem->set_p_level(elem->p_level() - 1);
mesh_changed = true;
}
else
{
elem->set_p_refinement_flag(Elem::DO_NOTHING);
}
}
}
// If the mesh changed on any processor, it changed globally
Parallel::max(mesh_changed);
// And we may need to update ParallelMesh values reflecting the changes
if (mesh_changed)
_mesh.update_parallel_id_counts();
// Node processor ids may need to change if an element of that id
// was coarsened away
if (mesh_changed && !_mesh.is_serial())
{
// Update the _new_nodes_map so that processors can
// find requested nodes
this->update_nodes_map ();
MeshCommunication().make_nodes_parallel_consistent
(_mesh, _new_nodes_map);
// Clear the _new_nodes_map
this->clear();
#ifdef DEBUG
MeshTools::libmesh_assert_valid_node_procids(_mesh);
#endif
}
STOP_LOG ('_coarsen_elements()', 'MeshRefinement');
return mesh_changed;
}
It is possible that for a given set of refinement flags there is actually no change upon calling this member function. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.
Definition at line 1471 of file mesh_refinement.C.
References _mesh, _new_nodes_map, Elem::active(), clear(), MeshBase::elements_begin(), MeshBase::elements_end(), MeshBase::is_serial(), Elem::JUST_REFINED, ParallelMesh::libmesh_assert_valid_parallel_ids(), MeshCommunication::make_elems_parallel_consistent(), MeshCommunication::make_nodes_parallel_consistent(), std::max(), Elem::p_level(), Elem::p_refinement_flag(), Elem::REFINE, Elem::refinement_flag(), Elem::set_p_level(), Elem::set_p_refinement_flag(), update_nodes_map(), and MeshBase::update_parallel_id_counts().
Referenced by refine_and_coarsen_elements(), refine_elements(), and uniformly_refine().
{
// This function must be run on all processors at once
parallel_only();
// Update the _new_nodes_map so that elements can
// find nodes to connect to.
this->update_nodes_map ();
START_LOG ('_refine_elements()', 'MeshRefinement');
// Iterate over the elements, counting the elements
// flagged for h refinement.
unsigned int n_elems_flagged = 0;
MeshBase::element_iterator it = _mesh.elements_begin();
const MeshBase::element_iterator end = _mesh.elements_end();
for (; it != end; ++it)
{
Elem* elem = *it;
if (elem->refinement_flag() == Elem::REFINE)
n_elems_flagged++;
}
// Construct a local vector of Elem* which have been
// previously marked for refinement. We reserve enough
// space to allow for every element to be refined.
std::vector<Elem*> local_copy_of_elements;
local_copy_of_elements.reserve(n_elems_flagged);
// Iterate over the elements, looking for elements
// flagged for refinement.
for (it = _mesh.elements_begin(); it != end; ++it)
{
Elem* elem = *it;
if (elem->refinement_flag() == Elem::REFINE)
local_copy_of_elements.push_back(elem);
if (elem->p_refinement_flag() == Elem::REFINE &&
elem->active())
{
elem->set_p_level(elem->p_level()+1);
elem->set_p_refinement_flag(Elem::JUST_REFINED);
}
}
// Now iterate over the local copies and refine each one.
// This may resize the mesh's internal container and invalidate
// any existing iterators.
for (unsigned int e = 0; e != local_copy_of_elements.size(); ++e)
local_copy_of_elements[e]->refine(*this);
// The mesh changed if there were elements h refined
bool mesh_changed = !local_copy_of_elements.empty();
// If the mesh changed on any processor, it changed globally
Parallel::max(mesh_changed);
// And we may need to update ParallelMesh values reflecting the changes
if (mesh_changed)
_mesh.update_parallel_id_counts();
if (mesh_changed && !_mesh.is_serial())
{
MeshCommunication().make_elems_parallel_consistent (_mesh);
MeshCommunication().make_nodes_parallel_consistent
(_mesh, _new_nodes_map);
#ifdef DEBUG
ParallelMesh *pmesh = dynamic_cast<ParallelMesh *>(&_mesh);
if (pmesh)
pmesh->libmesh_assert_valid_parallel_ids();
#endif
}
// Clear the _new_nodes_map and _unused_elements data structures.
this->clear();
STOP_LOG ('_refine_elements()', 'MeshRefinement');
return mesh_changed;
}
absolute_global_tolerance is 0 by default.
Definition at line 667 of file mesh_refinement.h.
References _absolute_global_tolerance, and _use_member_parameters.
{
_use_member_parameters = true;
return _absolute_global_tolerance;
}
Definition at line 113 of file mesh_refinement.C.
References _mesh, and MeshBase::add_elem().
Referenced by Elem::refine().
{
libmesh_assert (elem != NULL);
// // If the unused_elements has any iterators from
// // old elements, take the first one
// if (!_unused_elements.empty())
// {
// std::vector<Elem*>::iterator it = _unused_elements.front();
// *it = elem;
// _unused_elements.pop_front();
// }
// // Otherwise, use the conventional add method
// else
// {
// _mesh.add_elem (elem);
// }
// The _unused_elements optimization has been turned off.
_mesh.add_elem (elem);
return elem;
}
Definition at line 644 of file mesh_refinement_flagging.C.
References _mesh, MeshBase::elements_begin(), and MeshBase::elements_end().
{
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
(*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
}
Definition at line 83 of file mesh_refinement.C.
References _mesh, _new_nodes_map, MeshBase::add_point(), LocationMap< T >::find(), LocationMap< T >::insert(), and DofObject::invalid_id.
Referenced by Elem::refine().
{
START_LOG('add_point()', 'MeshRefinement');
// Return the node if it already exists
Node *node = _new_nodes_map.find(p, tol);
if (node)
{
STOP_LOG('add_point()', 'MeshRefinement');
return node;
}
// Add the node, with a default id and the requested
// processor_id
node = _mesh.add_point (p, DofObject::invalid_id, processor_id);
libmesh_assert (node != NULL);
// Add the node to the map.
_new_nodes_map.insert(*node);
// Return the address of the new node
STOP_LOG('add_point()', 'MeshRefinement');
return node;
}
Definition at line 655 of file mesh_refinement_flagging.C.
References _mesh, Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), and Elem::INACTIVE.
Referenced by flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_nelem_target(), uniformly_coarsen(), and uniformly_refine().
{
// Possibly clean up the refinement flags from
// a previous step
// elem_iterator elem_it (_mesh.elements_begin());
// const elem_iterator elem_end(_mesh.elements_end());
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
if ((*elem_it)->active())
{
(*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
(*elem_it)->set_p_refinement_flag(Elem::DO_NOTHING);
}
else
{
(*elem_it)->set_refinement_flag(Elem::INACTIVE);
(*elem_it)->set_p_refinement_flag(Elem::INACTIVE);
}
}
}
Definition at line 76 of file mesh_refinement.C.
References _new_nodes_map, and LocationMap< T >::clear().
Referenced by _coarsen_elements(), _refine_elements(), and ~MeshRefinement().
{
_new_nodes_map.clear();
}
coarsen_by_parents is true by default.
Definition at line 631 of file mesh_refinement.h.
References _coarsen_by_parents, and _use_member_parameters.
{
_use_member_parameters = true;
return _coarsen_by_parents;
}
The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.
Definition at line 515 of file mesh_refinement.C.
References _coarsen_elements(), _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, Elem::active(), Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), eliminate_unrefined_patches(), Elem::INACTIVE, MeshBase::is_serial(), Elem::JUST_REFINED, limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_coarsening_compatible(), make_flags_parallel_consistent(), std::max(), std::min(), MeshBase::prepare_for_use(), Elem::refinement_flag(), Elem::set_p_refinement_flag(), Elem::set_refinement_flag(), and test_level_one().
Referenced by EquationSystems::reinit().
{
// This function must be run on all processors at once
parallel_only();
bool _maintain_level_one = maintain_level_one;
// If the user used non-default parameters, let's warn that they're
// deprecated
if (!maintain_level_one)
{
libmesh_deprecated();
}
else
_maintain_level_one = _face_level_mismatch_limit;
// We can't yet turn a non-level-one mesh into a level-one mesh
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
// Possibly clean up the refinement flags from
// a previous step
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Pointer to the element
Elem* elem = *elem_it;
// Set refinement flag to INACTIVE if the
// element isn't active
if ( !elem->active())
{
elem->set_refinement_flag(Elem::INACTIVE);
elem->set_p_refinement_flag(Elem::INACTIVE);
}
// This might be left over from the last step
if (elem->refinement_flag() == Elem::JUST_REFINED)
elem->set_refinement_flag(Elem::DO_NOTHING);
}
// Parallel consistency has to come first, or coarsening
// along processor boundaries might occasionally be falsely
// prevented
if (!_mesh.is_serial())
this->make_flags_parallel_consistent();
// Repeat until flag changes match on every processor
do
{
// Repeat until the flags form a conforming mesh.
bool satisfied = false;
do
{
const bool coarsening_satisfied =
this->make_coarsening_compatible(maintain_level_one);
bool smoothing_satisfied =
!this->eliminate_unrefined_patches();// &&
if (_edge_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
if (_node_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
satisfied = (coarsening_satisfied &&
smoothing_satisfied);
#ifdef DEBUG
bool max_satisfied = satisfied,
min_satisfied = satisfied;
Parallel::max(max_satisfied);
Parallel::min(min_satisfied);
libmesh_assert (satisfied == max_satisfied);
libmesh_assert (satisfied == min_satisfied);
#endif
}
while (!satisfied);
}
while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
// Coarsen the flagged elements.
const bool mesh_changed =
this->_coarsen_elements ();
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
// FIXME: This won't pass unless we add a redundant find_neighbors()
// call or replace find_neighbors() with on-the-fly neighbor updating
// libmesh_assert(!this->eliminate_unrefined_patches());
// We can't contract the mesh ourselves anymore - a System might
// need to restrict old coefficient vectors first
// _mesh.contract();
// Finally, the new mesh may need to be prepared for use
if (mesh_changed)
_mesh.prepare_for_use ();
return mesh_changed;
}
coarsen_fraction must be in $ [0,1] $, and is 0 by default.
Definition at line 643 of file mesh_refinement.h.
References _coarsen_fraction, and _use_member_parameters.
{
_use_member_parameters = true;
return _coarsen_fraction;
}
coarsen_threshold must be in $ [0,1] $, and is 0.1 by default.
Definition at line 655 of file mesh_refinement.h.
References _coarsen_threshold, and _use_member_parameters.
{
_use_member_parameters = true;
return _coarsen_threshold;
}
Definition at line 144 of file mesh_refinement.C.
References DofObject::id(), std::max(), std::min(), and 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().
{
// This function must be run on all processors at once
parallel_only();
// Make sure the input error vector is valid
#ifdef DEBUG
for (unsigned int i=0; i != error_per_cell.size(); ++i)
{
libmesh_assert(error_per_cell[i] >= 0);
// isnan() isn't standard C++ yet
#ifdef isnan
libmesh_assert(!isnan(error_per_cell[i]));
#endif
}
#endif // #ifdef DEBUG
// error values on uncoarsenable elements will be left at -1
error_per_parent.clear();
error_per_parent.resize(error_per_cell.size(), 0.0);
{
// Find which elements are uncoarsenable
MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
Elem* parent = elem->parent();
// Active elements are uncoarsenable
error_per_parent[elem->id()] = -1.0;
// Grandparents and up are uncoarsenable
while (parent)
{
parent = parent->parent();
if (parent)
{
const unsigned int parentid = parent->id();
libmesh_assert (parentid < error_per_parent.size());
error_per_parent[parentid] = -1.0;
}
}
}
// Sync between processors.
// Use a reference to std::vector to avoid confusing
// Parallel::min
std::vector<ErrorVectorReal> &epp = error_per_parent;
Parallel::min(epp);
}
// The parent's error is defined as the square root of the
// sum of the children's errors squared, so errors that are
// Hilbert norms remain Hilbert norms.
//
// Because the children may be on different processors, we
// calculate local contributions to the parents' errors squared
// first, then sum across processors and take the square roots
// second.
{
MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
Elem* parent = elem->parent();
// Calculate each contribution to parent cells
if (parent)
{
const unsigned int parentid = parent->id();
libmesh_assert (parentid < error_per_parent.size());
// If the parent has grandchildren we won't be able to
// coarsen it, so forget it. Otherwise, add this child's
// contribution to the sum of the squared child errors
if (error_per_parent[parentid] != -1.0)
error_per_parent[parentid] += (error_per_cell[elem->id()] *
error_per_cell[elem->id()]);
}
}
}
// Sum the vector across all processors
Parallel::sum(static_cast<std::vector<ErrorVectorReal>&>(error_per_parent));
// Calculate the min and max as we loop
parent_error_min = std::numeric_limits<double>::max();
parent_error_max = 0.;
for (unsigned int i = 0; i != error_per_parent.size(); ++i)
{
// If this element isn't a coarsenable parent with error, we
// have nothing to do. Just flag it as -1 and move on
// Note that Parallel::sum might have left uncoarsenable
// elements with error_per_parent=-n_proc, so reset it to
// error_per_parent=-1
if (error_per_parent[i] < 0.)
{
error_per_parent[i] = -1.;
continue;
}
// The error estimator might have already given us an
// estimate on the coarsenable parent elements; if so then
// we want to retain that estimate
if (error_per_cell[i])
{
error_per_parent[i] = error_per_cell[i];
continue;
}
// if not, then e_parent = sqrt(sum(e_child^2))
else
error_per_parent[i] = std::sqrt(error_per_parent[i]);
parent_error_min = std::min (parent_error_min,
error_per_parent[i]);
parent_error_max = std::max (parent_error_max,
error_per_parent[i]);
}
}
edge_level_mismatch_limit is 0 by default.
Definition at line 678 of file mesh_refinement.h.
References _edge_level_mismatch_limit.
{
return _edge_level_mismatch_limit;
}
o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | o---o---o o---o---o | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o
into this:
o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | : | | | | | | : | | | o---o---o...o...o---o---o | | | : | | | | | | : | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o | | | | | | | | | | | | | | o---o---o---o---o---o---o
by refining the indicated element
Definition at line 265 of file mesh_refinement_smoothing.C.
References _mesh, Elem::active(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::ancestor(), Elem::child(), Elem::COARSEN, Elem::COARSEN_INACTIVE, Elem::DO_NOTHING, Elem::INACTIVE, Elem::level(), std::max(), Elem::min_new_p_level_by_neighbor(), Elem::n_children(), Elem::n_neighbors(), Elem::neighbor(), Elem::p_level(), Elem::p_refinement_flag(), Elem::parent(), Elem::REFINE, Elem::refinement_flag(), remote_elem, Elem::set_p_refinement_flag(), and Elem::set_refinement_flag().
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
bool flags_changed = false;
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
// First assume that we'll have to flag this element for both h
// and p refinement, then change our minds if we see any
// neighbors that are as coarse or coarser than us.
bool h_flag_me = true,
p_flag_me = true;
// Skip the element if it is already fully flagged for refinement
if (elem->p_refinement_flag() == Elem::REFINE)
p_flag_me = false;
if (elem->refinement_flag() == Elem::REFINE)
{
h_flag_me = false;
if (!p_flag_me)
continue;
}
// Test the parent if that is already flagged for coarsening
else if (elem->refinement_flag() == Elem::COARSEN)
{
libmesh_assert(elem->parent());
elem = elem->parent();
// FIXME - this doesn't seem right - RHS
if (elem->refinement_flag() != Elem::COARSEN_INACTIVE)
continue;
p_flag_me = false;
}
const unsigned int my_level = elem->level();
int my_p_adjustment = 0;
if (elem->p_refinement_flag() == Elem::REFINE)
my_p_adjustment = 1;
else if (elem->p_refinement_flag() == Elem::COARSEN)
{
libmesh_assert(elem->p_level() > 0);
my_p_adjustment = -1;
}
const unsigned int my_new_p_level = elem->p_level() +
my_p_adjustment;
// Check all the element neighbors
for (unsigned int n=0; n<elem->n_neighbors(); n++)
{
const Elem *neighbor = elem->neighbor(n);
// Quit if the element is on a local boundary
if (neighbor == NULL || neighbor == remote_elem)
{
h_flag_me = false;
p_flag_me = false;
break;
}
// if the neighbor will be equally or less refined than
// we are, then we will not become an unrefined island.
// So if we are still considering h refinement:
if (h_flag_me &&
// If our neighbor is already at a lower level,
// it can't end up at a higher level even if it
// is flagged for refinement once
((neighbor->level() < my_level) ||
// If our neighbor is at the same level but isn't
// flagged for refinement, it won't end up at a
// higher level
((neighbor->active()) &&
(neighbor->refinement_flag() != Elem::REFINE)) ||
// If our neighbor is currently more refined but is
// a parent flagged for coarsening, it will end up
// at the same level.
(neighbor->refinement_flag() == Elem::COARSEN_INACTIVE)))
{
// We've proven we won't become an unrefined island,
// so don't h refine to avoid that.
h_flag_me = false;
// If we've also proven we don't need to p refine,
// we don't need to check more neighbors
if (!p_flag_me)
break;
}
if (p_flag_me)
{
// if active neighbors will have a p level
// equal to or lower than ours, then we do not need to p
// refine ourselves.
if (neighbor->active())
{
int p_adjustment = 0;
if (neighbor->p_refinement_flag() == Elem::REFINE)
p_adjustment = 1;
else if (neighbor->p_refinement_flag() == Elem::COARSEN)
{
libmesh_assert(neighbor->p_level() > 0);
p_adjustment = -1;
}
if (my_new_p_level >= neighbor->p_level() + p_adjustment)
{
p_flag_me = false;
if (!h_flag_me)
break;
}
}
// If we have inactive neighbors, we need to
// test all their active descendants which neighbor us
else if (neighbor->ancestor())
{
if (neighbor->min_new_p_level_by_neighbor(elem,
my_new_p_level + 2) <= my_new_p_level)
{
p_flag_me = false;
if (!h_flag_me)
break;
}
}
}
}
if (h_flag_me)
{
// Parents that would create islands should no longer
// coarsen
if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
{
for (unsigned int c=0; c<elem->n_children(); c++)
{
libmesh_assert(elem->child(c)->refinement_flag() ==
Elem::COARSEN);
elem->child(c)->set_refinement_flag(Elem::DO_NOTHING);
}
elem->set_refinement_flag(Elem::INACTIVE);
}
else
elem->set_refinement_flag(Elem::REFINE);
flags_changed = true;
}
if (p_flag_me)
{
if (elem->p_refinement_flag() == Elem::COARSEN)
elem->set_p_refinement_flag(Elem::DO_NOTHING);
else
elem->set_p_refinement_flag(Elem::REFINE);
flags_changed = true;
}
}
// If flags changed on any processor then they changed globally
Parallel::max(flags_changed);
return flags_changed;
}
face_level_mismatch_limit is 1 by default. Currently the only supported options are 0 and 1.
Definition at line 673 of file mesh_refinement.h.
References _face_level_mismatch_limit.
Referenced by EquationSystems::reinit().
{
return _face_level_mismatch_limit;
}
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 409 of file mesh_refinement_flagging.C.
References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), clean_refinement_flags(), Elem::COARSEN, create_parent_error_vector(), DofObject::id(), libMesh::invalid_uint, MeshBase::is_serial(), Elem::level(), MeshBase::mesh_dimension(), MeshBase::n_elem(), Elem::parent(), libMesh::processor_id(), Elem::REFINE, and Elem::set_refinement_flag().
{
// FIXME - this won't work on a non-serialized mesh yet
if (!_mesh.is_serial())
{
if (libMesh::processor_id() == 0)
std::cerr << 'flag_elements_by_elem_fraction does not yet '
<< 'work on a parallel mesh.' << std::endl;
libmesh_error();
}
// The function arguments are currently just there for
// backwards_compatibility
if (!_use_member_parameters)
{
// If the user used non-default parameters, lets warn
// that they're deprecated
if (refine_frac != 0.3 ||
coarsen_frac != 0.0 ||
max_l != libMesh::invalid_uint)
libmesh_deprecated();
_refine_fraction = refine_frac;
_coarsen_fraction = coarsen_frac;
_max_h_level = max_l;
}
// Check for valid fractions..
// The fraction values must be in [0,1]
libmesh_assert (_refine_fraction >= 0. && _refine_fraction <= 1.);
libmesh_assert (_coarsen_fraction >= 0. && _coarsen_fraction <= 1.);
// The number of active elements in the mesh
const unsigned int n_active_elem = _mesh.n_elem();
// The number of elements to flag for coarsening
const unsigned int n_elem_coarsen =
static_cast<unsigned int>(_coarsen_fraction * n_active_elem);
// The number of elements to flag for refinement
const unsigned int n_elem_refine =
static_cast<unsigned int>(_refine_fraction * n_active_elem);
// Clean up the refinement flags. These could be left
// over from previous refinement steps.
this->clean_refinement_flags();
// This vector stores the error and element number for all the
// active elements. It will be sorted and the top & bottom
// elements will then be flagged for coarsening & refinement
std::vector<float> sorted_error;
sorted_error.reserve (n_active_elem);
// Loop over the active elements and create the entry
// in the sorted_error vector
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
sorted_error.push_back (error_per_cell[(*elem_it)->id()]);
// Now sort the sorted_error vector
std::sort (sorted_error.begin(), sorted_error.end());
// If we're coarsening by parents:
// Create a sorted error vector with coarsenable parent elements
// only, sorted by lowest errors first
ErrorVector error_per_parent, sorted_parent_error;
if (_coarsen_by_parents)
{
Real parent_error_min, parent_error_max;
create_parent_error_vector(error_per_cell,
error_per_parent,
parent_error_min,
parent_error_max);
sorted_parent_error = error_per_parent;
std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
// All the other error values will be 0., so get rid of them.
sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
sorted_parent_error.end(), 0.),
sorted_parent_error.end());
}
float top_error= 0., bottom_error = 0.;
// Get the maximum error value corresponding to the
// bottom n_elem_coarsen elements
if (_coarsen_by_parents && n_elem_coarsen)
{
const unsigned int dim = _mesh.mesh_dimension();
unsigned int twotodim = 1;
for (unsigned int i=0; i!=dim; ++i)
twotodim *= 2;
unsigned int n_parent_coarsen = n_elem_coarsen / (twotodim - 1);
if (n_parent_coarsen)
bottom_error = sorted_parent_error[n_parent_coarsen - 1];
}
else if (n_elem_coarsen)
{
bottom_error = sorted_error[n_elem_coarsen - 1];
}
if (n_elem_refine)
top_error = sorted_error[sorted_error.size() - n_elem_refine + 1];
// Finally, let's do the element flagging
elem_it = _mesh.active_elements_begin();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
Elem* parent = elem->parent();
if (_coarsen_by_parents && parent && n_elem_coarsen &&
error_per_parent[parent->id()] <= bottom_error)
elem->set_refinement_flag(Elem::COARSEN);
if (!_coarsen_by_parents && n_elem_coarsen &&
error_per_cell[elem->id()] <= bottom_error)
elem->set_refinement_flag(Elem::COARSEN);
if (n_elem_refine &&
elem->level() < _max_h_level &&
error_per_cell[elem->id()] >= top_error)
elem->set_refinement_flag(Elem::REFINE);
}
}
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 43 of file mesh_refinement_flagging.C.
References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), clean_refinement_flags(), Elem::COARSEN, create_parent_error_vector(), DofObject::id(), libMesh::invalid_uint, Elem::level(), std::max(), std::min(), Elem::parent(), Elem::REFINE, and Elem::set_refinement_flag().
Referenced by Adaptive< T >::solve().
{
// The function arguments are currently just there for
// backwards_compatibility
if (!_use_member_parameters)
{
// If the user used non-default parameters, lets warn
// that they're deprecated
if (refine_frac != 0.3 ||
coarsen_frac != 0.0 ||
max_l != libMesh::invalid_uint)
libmesh_deprecated();
_refine_fraction = refine_frac;
_coarsen_fraction = coarsen_frac;
_max_h_level = max_l;
}
// Check for valid fractions..
// The fraction values must be in [0,1]
libmesh_assert (_refine_fraction >= 0. && _refine_fraction <= 1.);
libmesh_assert (_coarsen_fraction >= 0. && _coarsen_fraction <= 1.);
// Clean up the refinement flags. These could be left
// over from previous refinement steps.
this->clean_refinement_flags();
// We're getting the minimum and maximum error values
// for the ACTIVE elements
Real error_min = 1.e30;
Real error_max = 0.;
// And, if necessary, for their parents
Real parent_error_min = 1.e30;
Real parent_error_max = 0.;
// Prepare another error vector if we need to sum parent errors
ErrorVector error_per_parent;
if (_coarsen_by_parents)
{
create_parent_error_vector(error_per_cell,
error_per_parent,
parent_error_min,
parent_error_max);
}
// We need to loop over all active elements to find the minimum
MeshBase::element_iterator el_it =
_mesh.active_local_elements_begin();
const MeshBase::element_iterator el_end =
_mesh.active_local_elements_end();
for (; el_it != el_end; ++el_it)
{
const unsigned int id = (*el_it)->id();
libmesh_assert (id < error_per_cell.size());
error_max = std::max (error_max, error_per_cell[id]);
error_min = std::min (error_min, error_per_cell[id]);
}
Parallel::max(error_max);
Parallel::min(error_min);
// Compute the cutoff values for coarsening and refinement
const Real error_delta = (error_max - error_min);
const Real parent_error_delta = parent_error_max - parent_error_min;
const Real refine_cutoff = (1.- _refine_fraction)*error_max;
const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min;
const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min;
// // Print information about the error
// std::cout << ' Error Information:' << std::endl
// << ' ------------------' << std::endl
// << ' min: ' << error_min << std::endl
// << ' max: ' << error_max << std::endl
// << ' delta: ' << error_delta << std::endl
// << ' refine_cutoff: ' << refine_cutoff << std::endl
// << ' coarsen_cutoff: ' << coarsen_cutoff << std::endl;
// Loop over the elements and flag them for coarsening or
// refinement based on the element error
MeshBase::element_iterator e_it =
_mesh.active_elements_begin();
const MeshBase::element_iterator e_end =
_mesh.active_elements_end();
for (; e_it != e_end; ++e_it)
{
Elem* elem = *e_it;
const unsigned int id = elem->id();
libmesh_assert (id < error_per_cell.size());
const float elem_error = error_per_cell[id];
if (_coarsen_by_parents)
{
Elem* parent = elem->parent();
if (parent)
{
const unsigned int parentid = parent->id();
if (error_per_parent[parentid] >= 0. &&
error_per_parent[parentid] <= parent_cutoff)
elem->set_refinement_flag(Elem::COARSEN);
}
}
// Flag the element for coarsening if its error
// is <= coarsen_fraction*delta + error_min
else if (elem_error <= coarsen_cutoff)
{
elem->set_refinement_flag(Elem::COARSEN);
}
// Flag the element for refinement if its error
// is >= refinement_cutoff.
if (elem_error >= refine_cutoff)
if (elem->level() < _max_h_level)
elem->set_refinement_flag(Elem::REFINE);
}
}
The three fractions refine_fraction coarsen_fraction and coarsen_threshold should be in $ [0,1] $.
Definition at line 172 of file mesh_refinement_flagging.C.
References _absolute_global_tolerance, _coarsen_by_parents, _coarsen_fraction, _coarsen_threshold, _max_h_level, _mesh, _refine_fraction, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::COARSEN, create_parent_error_vector(), DofObject::id(), Elem::level(), MeshBase::n_active_elem(), Elem::n_children(), Elem::parent(), Elem::REFINE, and Elem::set_refinement_flag().
{
// Check for valid fractions..
// The fraction values must be in [0,1]
libmesh_assert (_coarsen_threshold >= 0. && _refine_fraction <= 1.);
libmesh_assert (_refine_fraction >= 0. && _refine_fraction <= 1.);
libmesh_assert (_coarsen_fraction >= 0. && _coarsen_fraction <= 1.);
// How much error per cell will we tolerate?
const Real local_refinement_tolerance =
_absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
const Real local_coarsening_tolerance =
local_refinement_tolerance * _coarsen_threshold;
// Prepare another error vector if we need to sum parent errors
ErrorVector error_per_parent;
if (_coarsen_by_parents)
{
Real parent_error_min, parent_error_max;
create_parent_error_vector(error_per_cell_in,
error_per_parent,
parent_error_min,
parent_error_max);
}
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
Elem* parent = elem->parent();
const unsigned int elem_number = elem->id();
const float elem_error = error_per_cell_in[elem_number];
if (elem_error > local_refinement_tolerance &&
elem->level() < _max_h_level)
elem->set_refinement_flag(Elem::REFINE);
if (!_coarsen_by_parents && elem_error <
local_coarsening_tolerance)
elem->set_refinement_flag(Elem::COARSEN);
if (_coarsen_by_parents && parent)
{
float parent_error = error_per_parent[parent->id()];
if (parent_error >= 0.)
{
const Real parent_coarsening_tolerance =
std::sqrt(parent->n_children() *
local_coarsening_tolerance *
local_coarsening_tolerance);
if (parent_error < parent_coarsening_tolerance)
elem->set_refinement_flag(Elem::COARSEN);
}
}
}
}
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 551 of file mesh_refinement_flagging.C.
References _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::COARSEN, DofObject::id(), libMesh::invalid_uint, MeshBase::is_serial(), Elem::level(), std::max(), ErrorVector::mean(), libMesh::processor_id(), Elem::REFINE, Elem::set_refinement_flag(), and ErrorVector::variance().
{
// FIXME - this won't work on a non-serialized mesh yet
if (!_mesh.is_serial())
{
if (libMesh::processor_id() == 0)
std::cerr << 'flag_elements_by_mean_stddev does not yet '
<< 'work on a parallel mesh.' << std::endl;
libmesh_error();
}
// The function arguments are currently just there for
// backwards_compatibility
if (!_use_member_parameters)
{
// If the user used non-default parameters, lets warn
// that they're deprecated
if (refine_frac != 0.3 ||
coarsen_frac != 0.0 ||
max_l != libMesh::invalid_uint)
libmesh_deprecated();
_refine_fraction = refine_frac;
_coarsen_fraction = coarsen_frac;
_max_h_level = max_l;
}
// Get the mean value from the error vector
const Real mean = error_per_cell.mean();
// Get the standard deviation. This equals the
// square-root of the variance
const Real stddev = std::sqrt (error_per_cell.variance());
// Check for valid fractions
libmesh_assert (_refine_fraction >= 0. && _refine_fraction <= 1.);
libmesh_assert (_coarsen_fraction >= 0. && _coarsen_fraction <= 1.);
// The refine and coarsen cutoff
const Real refine_cutoff = mean + _refine_fraction * stddev;
const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.);
// Loop over the elements and flag them for coarsening or
// refinement based on the element error
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
const unsigned int id = elem->id();
libmesh_assert (id < error_per_cell.size());
const float elem_error = error_per_cell[id];
// Possibly flag the element for coarsening ...
if (elem_error <= coarsen_cutoff)
elem->set_refinement_flag(Elem::COARSEN);
// ... or refinement
if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level))
elem->set_refinement_flag(Elem::REFINE);
}
}
Definition at line 234 of file mesh_refinement_flagging.C.
References _coarsen_by_parents, _coarsen_fraction, _coarsen_threshold, _max_h_level, _mesh, _nelem_target, _refine_fraction, Elem::active(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::child(), clean_refinement_flags(), Elem::COARSEN, create_parent_error_vector(), MeshBase::elem(), Elem::has_children(), MeshBase::is_serial(), Elem::level(), MeshBase::mesh_dimension(), std::min(), MeshBase::n_active_elem(), Elem::n_children(), libMesh::processor_id(), Elem::REFINE, and Elem::set_refinement_flag().
{
// Check for valid fractions..
// The fraction values must be in [0,1]
libmesh_assert (_refine_fraction >= 0. && _refine_fraction <= 1.);
libmesh_assert (_coarsen_fraction >= 0. && _coarsen_fraction <= 1.);
// This function is currently only coded to work when coarsening by
// parents - it's too hard to guess how many coarsenings will be
// performed otherwise.
libmesh_assert (_coarsen_by_parents);
// The number of active elements in the mesh - hopefully less than
// 2 billion on 32 bit machines
const unsigned int n_active_elem = _mesh.n_active_elem();
// The maximum number of active elements to flag for coarsening
const unsigned int max_elem_coarsen =
static_cast<unsigned int>(_coarsen_fraction * n_active_elem) + 1;
// The maximum number of elements to flag for refinement
const unsigned int max_elem_refine =
static_cast<unsigned int>(_refine_fraction * n_active_elem) + 1;
// Clean up the refinement flags. These could be left
// over from previous refinement steps.
this->clean_refinement_flags();
// The target number of elements to add or remove
const int n_elem_new = _nelem_target - n_active_elem;
// Create an vector with active element errors and ids,
// sorted by highest errors first
std::vector<std::pair<float, unsigned int> > sorted_error;
sorted_error.reserve (n_active_elem);
// FIXME - this won't work on a non-serialized mesh yet
if (!_mesh.is_serial())
{
if (libMesh::processor_id() == 0)
std::cerr << 'flag_elements_by_nelem_target does not yet '
<< 'work on a parallel mesh.' << std::endl;
libmesh_error();
}
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
unsigned int eid = (*elem_it)->id();
libmesh_assert(eid < error_per_cell.size());
sorted_error.push_back
(std::make_pair(error_per_cell[eid], eid));
}
// Default sort works since pairs are sorted lexicographically
std::sort (sorted_error.begin(), sorted_error.end());
std::reverse (sorted_error.begin(), sorted_error.end());
// Create a sorted error vector with coarsenable parent elements
// only, sorted by lowest errors first
ErrorVector error_per_parent;
std::vector<std::pair<float, unsigned int> > sorted_parent_error;
Real parent_error_min, parent_error_max;
create_parent_error_vector(error_per_cell,
error_per_parent,
parent_error_min,
parent_error_max);
// create_parent_error_vector sets values for non-parents and
// non-coarsenable parents to -1. Get rid of them.
for (unsigned int i=0; i != error_per_parent.size(); ++i)
if (error_per_parent[i] != -1)
sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i));
std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
// Keep track of how many elements we plan to coarsen & refine
unsigned int coarsen_count = 0;
unsigned int refine_count = 0;
const unsigned int dim = _mesh.mesh_dimension();
unsigned int twotodim = 1;
for (unsigned int i=0; i!=dim; ++i)
twotodim *= 2;
// First, let's try to get our element count to target_nelem
if (n_elem_new >= 0)
{
// Every element refinement creates at least
// 2^dim-1 new elements
refine_count =
std::min(static_cast<unsigned int>(n_elem_new / (twotodim-1)),
max_elem_refine);
}
else
{
// Every successful element coarsening is likely to destroy
// 2^dim-1 net elements.
coarsen_count =
std::min(static_cast<unsigned int>(-n_elem_new / (twotodim-1)),
max_elem_coarsen);
}
// Next, let's see if we can trade any refinement for coarsening
while (coarsen_count < max_elem_coarsen &&
refine_count < max_elem_refine &&
coarsen_count < sorted_parent_error.size() &&
refine_count < sorted_error.size() &&
sorted_error[refine_count].first >
sorted_parent_error[coarsen_count].first * _coarsen_threshold)
{
coarsen_count++;
refine_count++;
}
if (refine_count > max_elem_refine)
refine_count = max_elem_refine;
unsigned int successful_refine_count = 0;
for (unsigned int i=0; i != sorted_error.size(); ++i)
{
if (successful_refine_count >= refine_count)
break;
unsigned int eid = sorted_error[i].second;
Elem *elem = _mesh.elem(eid);
if (elem->level() < _max_h_level)
{
elem->set_refinement_flag(Elem::REFINE);
successful_refine_count++;
}
}
// If we couldn't refine enough elements, don't coarsen too many
// either
if (coarsen_count < (refine_count - successful_refine_count))
coarsen_count = 0;
else
coarsen_count -= (refine_count - successful_refine_count);
if (coarsen_count > max_elem_coarsen)
coarsen_count = max_elem_coarsen;
unsigned int successful_coarsen_count = 0;
for (unsigned int i=0; i != sorted_parent_error.size(); ++i)
{
if (successful_coarsen_count >= coarsen_count * twotodim)
break;
unsigned int parent_id = sorted_parent_error[i].second;
Elem *parent = _mesh.elem(parent_id);
libmesh_assert(parent->has_children());
for (unsigned int c=0; c != parent->n_children(); ++c)
{
Elem *elem = parent->child(c);
if (elem->active())
{
elem->set_refinement_flag(Elem::COARSEN);
successful_coarsen_count++;
}
}
}
// Return true if we've done all the AMR/C we can
if (!successful_coarsen_count &&
!successful_refine_count)
return true;
// And false if there may still be more to do.
return false;
}
Definition at line 276 of file mesh_refinement.h.
References _mesh.
{ return _mesh; }
Definition at line 282 of file mesh_refinement.h.
References _mesh.
{ return _mesh; }
Definition at line 130 of file mesh_refinement_smoothing.C.
References _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::build_edge(), Elem::level(), std::max(), Elem::n_edges(), Elem::p_level(), Elem::p_refinement_flag(), Elem::parent(), Elem::REFINE, Elem::refinement_flag(), Elem::set_p_refinement_flag(), and Elem::set_refinement_flag().
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
bool flags_changed = false;
// Maps holding the maximum element level that touches an edge
std::map<std::pair<unsigned int, unsigned int>, unsigned char>
max_level_at_edge;
std::map<std::pair<unsigned int, unsigned int>, unsigned char>
max_p_level_at_edge;
// Loop over all the active elements & fill the maps
{
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
const Elem* elem = *elem_it;
const unsigned char elem_level =
elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
const unsigned char elem_p_level =
elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);
// Set the max_level at each edge
for (unsigned int n=0; n<elem->n_edges(); n++)
{
AutoPtr<Elem> edge = elem->build_edge(n);
unsigned int childnode0 = edge->node(0);
unsigned int childnode1 = edge->node(1);
if (childnode1 < childnode0)
std::swap(childnode0, childnode1);
for (const Elem *p = elem; p != NULL; p = p->parent())
{
AutoPtr<Elem> pedge = p->build_edge(n);
unsigned int node0 = pedge->node(0);
unsigned int node1 = pedge->node(1);
if (node1 < node0)
std::swap(node0, node1);
// If elem does not share this edge with its ancestor
// p, refinement levels of elements sharing p's edge
// are not restricted by refinement levels of elem.
// Furthermore, elem will not share this edge with any
// of p's ancestors, so we can safely break out of the
// for loop early.
if (node0 != childnode0 && node1 != childnode1)
break;
childnode0 = node0;
childnode1 = node1;
std::pair<unsigned int, unsigned int> edge_key =
std::make_pair(node0, node1);
if (max_level_at_edge.find(edge_key) ==
max_level_at_edge.end())
{
max_level_at_edge[edge_key] = elem_level;
max_p_level_at_edge[edge_key] = elem_p_level;
}
else
{
max_level_at_edge[edge_key] =
std::max (max_level_at_edge[edge_key], elem_level);
max_p_level_at_edge[edge_key] =
std::max (max_p_level_at_edge[edge_key], elem_p_level);
}
}
}
}
}
// Now loop over the active elements and flag the elements
// who violate the requested level mismatch
{
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
const unsigned int elem_level = elem->level();
const unsigned int elem_p_level = elem->p_level();
// Skip the element if it is already fully flagged
if (elem->refinement_flag() == Elem::REFINE &&
elem->p_refinement_flag() == Elem::REFINE)
continue;
// Loop over the nodes, check for possible mismatch
for (unsigned int n=0; n<elem->n_edges(); n++)
{
AutoPtr<Elem> edge = elem->build_edge(n);
unsigned int node0 = edge->node(0);
unsigned int node1 = edge->node(1);
if (node1 < node0)
std::swap(node0, node1);
std::pair<unsigned int, unsigned int> edge_key =
std::make_pair(node0, node1);
// Flag the element for refinement if it violates
// the requested level mismatch
if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key]
&& elem->refinement_flag() != Elem::REFINE)
{
elem->set_refinement_flag (Elem::REFINE);
flags_changed = true;
}
if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
&& elem->p_refinement_flag() != Elem::REFINE)
{
elem->set_p_refinement_flag (Elem::REFINE);
flags_changed = true;
}
}
}
}
// If flags changed on any processor then they changed globally
Parallel::max(flags_changed);
return flags_changed;
}
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
.fi
by refining the indicated element
Definition at line 38 of file mesh_refinement_smoothing.C.
References _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::level(), std::max(), Elem::n_nodes(), MeshBase::n_nodes(), Elem::node(), Elem::p_level(), Elem::p_refinement_flag(), Elem::REFINE, Elem::refinement_flag(), Elem::set_p_refinement_flag(), and Elem::set_refinement_flag().
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
bool flags_changed = false;
// Vector holding the maximum element level that touches a node.
std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0);
std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0);
// Loop over all the active elements & fill the vector
{
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
const Elem* elem = *elem_it;
const unsigned char elem_level =
elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
const unsigned char elem_p_level =
elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);
// Set the max_level at each node
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
const unsigned int node_number = elem->node(n);
libmesh_assert (node_number < max_level_at_node.size());
max_level_at_node[node_number] =
std::max (max_level_at_node[node_number], elem_level);
max_p_level_at_node[node_number] =
std::max (max_p_level_at_node[node_number], elem_p_level);
}
}
}
// Now loop over the active elements and flag the elements
// who violate the requested level mismatch
{
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for (; elem_it != elem_end; ++elem_it)
{
Elem* elem = *elem_it;
const unsigned int elem_level = elem->level();
const unsigned int elem_p_level = elem->p_level();
// Skip the element if it is already fully flagged
if (elem->refinement_flag() == Elem::REFINE &&
elem->p_refinement_flag() == Elem::REFINE)
continue;
// Loop over the nodes, check for possible mismatch
for (unsigned int n=0; n<elem->n_nodes(); n++)
{
const unsigned int node_number = elem->node(n);
// Flag the element for refinement if it violates
// the requested level mismatch
if ( (elem_level + max_mismatch) < max_level_at_node[node_number]
&& elem->refinement_flag() != Elem::REFINE)
{
elem->set_refinement_flag (Elem::REFINE);
flags_changed = true;
}
if ( (elem_p_level + max_mismatch) < max_p_level_at_node[node_number]
&& elem->p_refinement_flag() != Elem::REFINE)
{
elem->set_p_refinement_flag (Elem::REFINE);
flags_changed = true;
}
}
}
}
// If flags changed on any processor then they changed globally
Parallel::max(flags_changed);
return flags_changed;
}
Definition at line 840 of file mesh_refinement.C.
References _face_level_mismatch_limit, _mesh, Elem::active(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::ancestor(), Elem::child(), Elem::COARSEN, Elem::COARSEN_INACTIVE, Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), Elem::has_children(), Elem::has_neighbor(), Elem::INACTIVE, MeshBase::is_serial(), Elem::level(), MeshBase::level_elements_begin(), MeshBase::level_elements_end(), std::max(), MeshTools::max_level(), std::min(), Elem::n_children(), Elem::n_neighbors(), Elem::neighbor(), Elem::p_level(), Elem::p_refinement_flag(), libMesh::processor_id(), DofObject::processor_id(), Elem::REFINE, Elem::refinement_flag(), remote_elem, Elem::set_p_refinement_flag(), and Elem::set_refinement_flag().
Referenced by coarsen_elements(), and refine_and_coarsen_elements().
{
// This function must be run on all processors at once
parallel_only();
START_LOG ('make_coarsening_compatible()', 'MeshRefinement');
bool _maintain_level_one = maintain_level_one;
// If the user used non-default parameters, let's warn that they're
// deprecated
if (!maintain_level_one)
{
libmesh_deprecated();
}
else
_maintain_level_one = _face_level_mismatch_limit;
// Unless we encounter a specific situation level-one
// will be satisfied after executing this loop just once
bool level_one_satisfied = true;
// Unless we encounter a specific situation we will be compatible
// with any selected refinement flags
bool compatible_with_refinement = true;
// find the maximum h and p levels in the mesh
unsigned int max_level = 0;
unsigned int max_p_level = 0;
// First we look at all the active level-0 elements. Since it doesn't make
// sense to coarsen them we must un-set their coarsen flags if
// they are set.
MeshBase::element_iterator el = _mesh.active_elements_begin();
const MeshBase::element_iterator end_el = _mesh.active_elements_end();
for (; el != end_el; ++el)
{
Elem *elem = *el;
max_level = std::max(max_level, elem->level());
max_p_level =
std::max(max_p_level,
static_cast<unsigned int>(elem->p_level()));
if ((elem->level() == 0) &&
(elem->refinement_flag() == Elem::COARSEN))
elem->set_refinement_flag(Elem::DO_NOTHING);
if ((elem->p_level() == 0) &&
(elem->p_refinement_flag() == Elem::COARSEN))
elem->set_p_refinement_flag(Elem::DO_NOTHING);
}
// if there are no refined elements on this processor then
// there is no work for us to do
if (max_level == 0 && max_p_level == 0)
{
STOP_LOG ('make_coarsening_compatible()', 'MeshRefinement');
// But we still have to check with other processors
Parallel::min(compatible_with_refinement);
return compatible_with_refinement;
}
// Loop over all the active elements. If an element is marked
// for coarsening we better check its neighbors. If ANY of these neighbors
// are marked for refinement AND are at the same level then there is a
// conflict. By convention refinement wins, so we un-mark the element for
// coarsening. Level-one would be violated in this case so we need to re-run
// the loop.
if (_maintain_level_one)
{
repeat:
level_one_satisfied = true;
do
{
level_one_satisfied = true;
MeshBase::element_iterator el = _mesh.active_elements_begin();
const MeshBase::element_iterator end_el = _mesh.active_elements_end();
for (; el != end_el; ++el)
{
Elem* elem = *el;
bool my_flag_changed = false;
if (elem->refinement_flag() == Elem::COARSEN) // If the element is active and
// the coarsen flag is set
{
const unsigned int my_level = elem->level();
for (unsigned int n=0; n<elem->n_neighbors(); n++)
if (elem->neighbor(n) != NULL && // I have a
elem->neighbor(n) != remote_elem) // neighbor here
{
if (elem->neighbor(n)->active()) // and it is active
{
const Elem* neighbor = elem->neighbor(n);
if ((neighbor->level() == my_level) &&
(neighbor->refinement_flag() == Elem::REFINE)) // the neighbor is at my level
// and wants to be refined
{
elem->set_refinement_flag(Elem::DO_NOTHING);
my_flag_changed = true;
break;
}
}
else // I have a neighbor and it is not active. That means it has children.
{ // While it _may_ be possible to coarsen us if all the children of
// that element want to be coarsened, it is impossible to know at this
// stage. Forget about it for the moment... This can be handled in
// two steps.
elem->set_refinement_flag(Elem::DO_NOTHING);
my_flag_changed = true;
break;
}
}
}
if (elem->p_refinement_flag() == Elem::COARSEN) // If
// the element is active and the order reduction flag is set
{
const unsigned int my_p_level = elem->p_level();
for (unsigned int n=0; n<elem->n_neighbors(); n++)
if (elem->neighbor(n) != NULL && // I have a
elem->neighbor(n) != remote_elem) // neighbor here
{
if (elem->neighbor(n)->active()) // and it is active
{
const Elem* neighbor = elem->neighbor(n);
if ((neighbor->p_level() > my_p_level &&
neighbor->p_refinement_flag() != Elem::COARSEN)
|| (neighbor->p_level() == my_p_level &&
neighbor->p_refinement_flag() == Elem::REFINE))
{
elem->set_p_refinement_flag(Elem::DO_NOTHING);
my_flag_changed = true;
break;
}
}
else // I have a neighbor and it is not active.
{ // We need to find which of its children
// have me as a neighbor, and maintain
// level one p compatibility with them.
// Because we currently have level one h
// compatibility, we don't need to check
// grandchildren
const Elem* neighbor = elem->neighbor(n);
libmesh_assert(neighbor->has_children());
for (unsigned int c=0; c!=neighbor->n_children(); c++)
{
Elem *subneighbor = neighbor->child(c);
if (subneighbor != remote_elem &&
subneighbor->active() &&
subneighbor->has_neighbor(elem))
if ((subneighbor->p_level() > my_p_level &&
subneighbor->p_refinement_flag() != Elem::COARSEN)
|| (subneighbor->p_level() == my_p_level &&
subneighbor->p_refinement_flag() == Elem::REFINE))
{
elem->set_p_refinement_flag(Elem::DO_NOTHING);
my_flag_changed = true;
break;
}
}
if (my_flag_changed)
break;
}
}
}
// If the current element's flag changed, we hadn't
// satisfied the level one rule.
if (my_flag_changed)
level_one_satisfied = false;
// Additionally, if it has non-local neighbors, and
// we're not in serial, then we'll eventually have to
// return compatible_with_refinement = false, because
// our change has to propagate to neighboring
// processors.
if (my_flag_changed && !_mesh.is_serial())
for (unsigned int n=0; n != elem->n_neighbors(); ++n)
{
Elem *neigh = elem->neighbor(n);
if (!neigh)
continue;
if (neigh == remote_elem ||
neigh->processor_id() !=
libMesh::processor_id())
{
compatible_with_refinement = false;
break;
}
// FIXME - for non-level one meshes we should
// test all descendants
if (neigh->has_children())
for (unsigned int c=0; c != neigh->n_children(); ++c)
if (neigh->child(c) == remote_elem ||
neigh->child(c)->processor_id() !=
libMesh::processor_id())
{
compatible_with_refinement = false;
break;
}
}
}
}
while (!level_one_satisfied);
} // end if (_maintain_level_one)
// Next we look at all of the ancestor cells.
// If there is a parent cell with all of its children
// wanting to be unrefined then the element is a candidate
// for unrefinement. If all the children don't
// all want to be unrefined then ALL of them need to have their
// unrefinement flags cleared.
for (int level=(max_level); level >= 0; level--)
{
MeshBase::element_iterator el = _mesh.level_elements_begin(level);
const MeshBase::element_iterator end_el = _mesh.level_elements_end(level);
for (; el != end_el; ++el)
{
Elem *elem = *el;
if (elem->ancestor())
{
// right now the element hasn't been disqualified
// as a candidate for unrefinement
bool is_a_candidate = true;
bool found_remote_child = false;
for (unsigned int c=0; c<elem->n_children(); c++)
{
Elem *child = elem->child(c);
if (child == remote_elem)
found_remote_child = true;
else if ((child->refinement_flag() != Elem::COARSEN) ||
!child->active() )
is_a_candidate = false;
}
if (!is_a_candidate && !found_remote_child)
{
elem->set_refinement_flag(Elem::INACTIVE);
for (unsigned int c=0; c<elem->n_children(); c++)
{
Elem *child = elem->child(c);
if (child == remote_elem)
continue;
if (child->refinement_flag() == Elem::COARSEN)
{
level_one_satisfied = false;
child->set_refinement_flag(Elem::DO_NOTHING);
}
}
}
}
}
}
if (!level_one_satisfied && _maintain_level_one) goto repeat;
// If all the children of a parent are set to be coarsened
// then flag the parent so that they can kill thier kids...
MeshBase::element_iterator all_el = _mesh.elements_begin();
const MeshBase::element_iterator all_el_end = _mesh.elements_end();
for (; all_el != all_el_end; ++all_el)
{
Elem *elem = *all_el;
if (elem->ancestor())
{
// Presume all the children are local and flagged for
// coarsening and then look for a contradiction
bool all_children_flagged_for_coarsening = true;
bool found_remote_child = false;
for (unsigned int c=0; c<elem->n_children(); c++)
{
Elem *child = elem->child(c);
if (child == remote_elem)
found_remote_child = true;
else if (child->refinement_flag() != Elem::COARSEN)
all_children_flagged_for_coarsening = false;
}
if (!found_remote_child &&
all_children_flagged_for_coarsening)
elem->set_refinement_flag(Elem::COARSEN_INACTIVE);
else if (!found_remote_child)
elem->set_refinement_flag(Elem::INACTIVE);
}
}
STOP_LOG ('make_coarsening_compatible()', 'MeshRefinement');
// If one processor finds an incompatibility, we're globally
// incompatible
Parallel::min(compatible_with_refinement);
return compatible_with_refinement;
}
Definition at line 810 of file mesh_refinement.C.
References _mesh, MeshBase::elements_begin(), MeshBase::elements_end(), std::min(), Elem::p_refinement_flag(), Elem::refinement_flag(), Elem::set_p_refinement_flag(), Elem::set_refinement_flag(), and Parallel::sync_dofobject_data_by_id().
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
START_LOG ('make_flags_parallel_consistent()', 'MeshRefinement');
SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
&Elem::set_refinement_flag);
Parallel::sync_dofobject_data_by_id
(_mesh.elements_begin(), _mesh.elements_end(), hsync);
SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
&Elem::set_p_refinement_flag);
Parallel::sync_dofobject_data_by_id
(_mesh.elements_begin(), _mesh.elements_end(), psync);
// If we weren't consistent in both h and p on every processor then
// we weren't globally consistent
bool parallel_consistent = hsync.parallel_consistent &&
psync.parallel_consistent;
Parallel::min(parallel_consistent);
STOP_LOG ('make_flags_parallel_consistent()', 'MeshRefinement');
return parallel_consistent;
}
Definition at line 1167 of file mesh_refinement.C.
References _face_level_mismatch_limit, _mesh, Elem::active(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Elem::child(), Elem::COARSEN, Elem::DO_NOTHING, Elem::has_children(), Elem::has_neighbor(), Elem::INACTIVE, Elem::level(), std::min(), Elem::n_children(), Elem::n_sides(), Elem::neighbor(), Elem::p_level(), Elem::p_refinement_flag(), Elem::parent(), Elem::REFINE, Elem::refinement_flag(), remote_elem, Elem::set_p_refinement_flag(), and Elem::set_refinement_flag().
Referenced by refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
START_LOG ('make_refinement_compatible()', 'MeshRefinement');
bool _maintain_level_one = maintain_level_one;
// If the user used non-default parameters, let's warn that they're
// deprecated
if (!maintain_level_one)
{
libmesh_deprecated();
}
else
_maintain_level_one = _face_level_mismatch_limit;
// Unless we encounter a specific situation level-one
// will be satisfied after executing this loop just once
bool level_one_satisfied = true;
// Unless we encounter a specific situation we will be compatible
// with any selected coarsening flags
bool compatible_with_coarsening = true;
// This loop enforces the level-1 rule. We should only
// execute it if the user indeed wants level-1 satisfied!
if (_maintain_level_one)
{
do
{
level_one_satisfied = true;
MeshBase::element_iterator el = _mesh.active_elements_begin();
const MeshBase::element_iterator end_el = _mesh.active_elements_end();
for (; el != end_el; ++el)
{
Elem *elem = *el;
if (elem->refinement_flag() == Elem::REFINE) // If the element is active and the
// h refinement flag is set
{
const unsigned int my_level = elem->level();
for (unsigned int side=0; side != elem->n_sides(); side++)
{
Elem* neighbor = elem->neighbor(side);
if (neighbor != NULL && // I have a
neighbor != remote_elem && // neighbor here
neighbor->active()) // and it is active
{
// Case 1: The neighbor is at the same level I am.
// 1a: The neighbor will be refined -> NO PROBLEM
// 1b: The neighbor won't be refined -> NO PROBLEM
// 1c: The neighbor wants to be coarsened -> PROBLEM
if (neighbor->level() == my_level)
{
if (neighbor->refinement_flag() == Elem::COARSEN)
{
neighbor->set_refinement_flag(Elem::DO_NOTHING);
if (neighbor->parent())
neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
compatible_with_coarsening = false;
level_one_satisfied = false;
}
}
// Case 2: The neighbor is one level lower than I am.
// The neighbor thus MUST be refined to satisfy
// the level-one rule, regardless of whether it
// was originally flagged for refinement. If it
// wasn't flagged already we need to repeat
// this process.
else if ((neighbor->level()+1) == my_level)
{
if (neighbor->refinement_flag() != Elem::REFINE)
{
neighbor->set_refinement_flag(Elem::REFINE);
if (neighbor->parent())
neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
compatible_with_coarsening = false;
level_one_satisfied = false;
}
}
#ifdef DEBUG
// Sanity check. We should never get into a
// case when our neighbot is more than one
// level away.
else if ((neighbor->level()+1) < my_level)
{
libmesh_error();
}
// Note that the only other possibility is that the
// neighbor is already refined, in which case it isn't
// active and we should never get here.
else
{
libmesh_error();
}
#endif
}
}
}
if (elem->p_refinement_flag() == Elem::REFINE) // If the element is active and the
// p refinement flag is set
{
const unsigned int my_p_level = elem->p_level();
for (unsigned int side=0; side != elem->n_sides(); side++)
{
Elem *neighbor = elem->neighbor(side);
if (neighbor != NULL && // I have a
neighbor != remote_elem) // neighbor here
{
if (neighbor->active()) // and it is active
{
if (neighbor->p_level() < my_p_level &&
neighbor->p_refinement_flag() != Elem::REFINE)
{
neighbor->set_p_refinement_flag(Elem::REFINE);
level_one_satisfied = false;
compatible_with_coarsening = false;
}
if (neighbor->p_level() == my_p_level &&
neighbor->p_refinement_flag() == Elem::COARSEN)
{
neighbor->set_p_refinement_flag(Elem::DO_NOTHING);
level_one_satisfied = false;
compatible_with_coarsening = false;
}
}
else // I have an inactive neighbor
{
libmesh_assert(neighbor->has_children());
for (unsigned int c=0; c!=neighbor->n_children(); c++)
{
Elem *subneighbor = neighbor->child(c);
if (subneighbor == remote_elem)
continue;
if (subneighbor->active() &&
subneighbor->has_neighbor(elem))
{
if (subneighbor->p_level() < my_p_level &&
subneighbor->p_refinement_flag() != Elem::REFINE)
{
// We should already be level one
// compatible
libmesh_assert(subneighbor->p_level() + 2u >
my_p_level);
subneighbor->set_p_refinement_flag(Elem::REFINE);
level_one_satisfied = false;
compatible_with_coarsening = false;
}
if (subneighbor->p_level() == my_p_level &&
subneighbor->p_refinement_flag() == Elem::COARSEN)
{
subneighbor->set_p_refinement_flag(Elem::DO_NOTHING);
level_one_satisfied = false;
compatible_with_coarsening = false;
}
}
}
}
}
}
}
}
}
while (!level_one_satisfied);
} // end if (_maintain_level_one)
// If we're not compatible on one processor, we're globally not
// compatible
Parallel::min(compatible_with_coarsening);
STOP_LOG ('make_refinement_compatible()', 'MeshRefinement');
return compatible_with_coarsening;
}
max_h_level is unlimited (libMesh::invalid_uint) by default
Definition at line 649 of file mesh_refinement.h.
References _max_h_level, and _use_member_parameters.
{
_use_member_parameters = true;
return _max_h_level;
}
nelem_target is 0 by default.
Definition at line 661 of file mesh_refinement.h.
References _nelem_target, and _use_member_parameters.
{
_use_member_parameters = true;
return _nelem_target;
}
node_level_mismatch_limit is 0 by default.
Definition at line 683 of file mesh_refinement.h.
References _node_level_mismatch_limit.
{
return _node_level_mismatch_limit;
}
The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.
Definition at line 370 of file mesh_refinement.C.
References _coarsen_elements(), _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, _refine_elements(), Elem::active(), Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), eliminate_unrefined_patches(), Elem::INACTIVE, MeshBase::is_serial(), Elem::JUST_REFINED, ParallelMesh::libmesh_assert_valid_parallel_ids(), limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_coarsening_compatible(), make_flags_parallel_consistent(), make_refinement_compatible(), std::max(), std::min(), MeshBase::prepare_for_use(), Elem::refinement_flag(), Elem::set_p_refinement_flag(), Elem::set_refinement_flag(), test_level_one(), and test_unflagged().
Referenced by Adaptive< T >::solve().
{
// This function must be run on all processors at once
parallel_only();
bool _maintain_level_one = maintain_level_one;
// If the user used non-default parameters, let's warn that they're
// deprecated
if (!maintain_level_one)
{
libmesh_deprecated();
}
else
_maintain_level_one = _face_level_mismatch_limit;
// We can't yet turn a non-level-one mesh into a level-one mesh
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
// Possibly clean up the refinement flags from
// a previous step
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Pointer to the element
Elem *elem = *elem_it;
// Set refinement flag to INACTIVE if the
// element isn't active
if ( !elem->active())
{
elem->set_refinement_flag(Elem::INACTIVE);
elem->set_p_refinement_flag(Elem::INACTIVE);
}
// This might be left over from the last step
if (elem->refinement_flag() == Elem::JUST_REFINED)
elem->set_refinement_flag(Elem::DO_NOTHING);
}
// Parallel consistency has to come first, or coarsening
// along processor boundaries might occasionally be falsely
// prevented
if (!_mesh.is_serial())
this->make_flags_parallel_consistent();
// Repeat until flag changes match on every processor
do
{
// Repeat until coarsening & refinement flags jive
bool satisfied = false;
do
{
const bool coarsening_satisfied =
this->make_coarsening_compatible(maintain_level_one);
const bool refinement_satisfied =
this->make_refinement_compatible(maintain_level_one);
bool smoothing_satisfied =
!this->eliminate_unrefined_patches();
if (_edge_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
if (_node_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
satisfied = (coarsening_satisfied &&
refinement_satisfied &&
smoothing_satisfied);
#ifdef DEBUG
bool max_satisfied = satisfied,
min_satisfied = satisfied;
Parallel::max(max_satisfied);
Parallel::min(min_satisfied);
libmesh_assert (satisfied == max_satisfied);
libmesh_assert (satisfied == min_satisfied);
#endif
}
while (!satisfied);
}
while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
// First coarsen the flagged elements.
const bool coarsening_changed_mesh =
this->_coarsen_elements ();
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
libmesh_assert(this->make_refinement_compatible(maintain_level_one));
// FIXME: This won't pass unless we add a redundant find_neighbors()
// call or replace find_neighbors() with on-the-fly neighbor updating
// libmesh_assert(!this->eliminate_unrefined_patches());
// We can't contract the mesh ourselves anymore - a System might
// need to restrict old coefficient vectors first
// _mesh.contract();
// Now refine the flagged elements. This will
// take up some space, maybe more than what was freed.
const bool refining_changed_mesh =
this->_refine_elements();
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
libmesh_assert(test_unflagged(true));
libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
libmesh_assert(this->make_refinement_compatible(maintain_level_one));
// FIXME: This won't pass unless we add a redundant find_neighbors()
// call or replace find_neighbors() with on-the-fly neighbor updating
// libmesh_assert(!this->eliminate_unrefined_patches());
// Finally, the new mesh needs to be prepared for use
if (coarsening_changed_mesh || refining_changed_mesh)
{
#ifdef DEBUG
ParallelMesh *pmesh = dynamic_cast<ParallelMesh *>(&_mesh);
if (pmesh)
pmesh->libmesh_assert_valid_parallel_ids();
#endif
_mesh.prepare_for_use ();
return true;
}
// Otherwise there was no change in the mesh,
// let the user know. Also, there is no need
// to prepare the mesh for use since it did not change.
return false;
}
The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.
Definition at line 628 of file mesh_refinement.C.
References _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, _refine_elements(), Elem::active(), Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), eliminate_unrefined_patches(), Elem::INACTIVE, MeshBase::is_serial(), Elem::JUST_REFINED, limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_flags_parallel_consistent(), make_refinement_compatible(), std::max(), std::min(), MeshBase::prepare_for_use(), Elem::refinement_flag(), Elem::set_p_refinement_flag(), Elem::set_refinement_flag(), and test_level_one().
Referenced by EquationSystems::reinit().
{
// This function must be run on all processors at once
parallel_only();
bool _maintain_level_one = maintain_level_one;
// If the user used non-default parameters, let's warn that they're
// deprecated
if (!maintain_level_one)
{
libmesh_deprecated();
}
else
_maintain_level_one = _face_level_mismatch_limit;
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
// Possibly clean up the refinement flags from
// a previous step
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Pointer to the element
Elem *elem = *elem_it;
// Set refinement flag to INACTIVE if the
// element isn't active
if ( !elem->active())
{
elem->set_refinement_flag(Elem::INACTIVE);
elem->set_p_refinement_flag(Elem::INACTIVE);
}
// This might be left over from the last step
if (elem->refinement_flag() == Elem::JUST_REFINED)
elem->set_refinement_flag(Elem::DO_NOTHING);
}
// Parallel consistency has to come first, or coarsening
// along processor boundaries might occasionally be falsely
// prevented
if (!_mesh.is_serial())
this->make_flags_parallel_consistent();
// Repeat until flag changes match on every processor
do
{
// Repeat until coarsening & refinement flags jive
bool satisfied = false;
do
{
const bool refinement_satisfied =
this->make_refinement_compatible(maintain_level_one);
bool smoothing_satisfied =
!this->eliminate_unrefined_patches();// &&
if (_edge_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
if (_node_level_mismatch_limit)
smoothing_satisfied = smoothing_satisfied &&
!this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
satisfied = (refinement_satisfied &&
smoothing_satisfied);
#ifdef DEBUG
bool max_satisfied = satisfied,
min_satisfied = satisfied;
Parallel::max(max_satisfied);
Parallel::min(min_satisfied);
libmesh_assert (satisfied == max_satisfied);
libmesh_assert (satisfied == min_satisfied);
#endif
}
while (!satisfied);
}
while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
// Now refine the flagged elements. This will
// take up some space, maybe more than what was freed.
const bool mesh_changed =
this->_refine_elements();
if (_maintain_level_one)
libmesh_assert(test_level_one(true));
libmesh_assert(this->make_refinement_compatible(maintain_level_one));
// FIXME: This won't pass unless we add a redundant find_neighbors()
// call or replace find_neighbors() with on-the-fly neighbor updating
// libmesh_assert(!this->eliminate_unrefined_patches());
// Finally, the new mesh needs to be prepared for use
if (mesh_changed)
_mesh.prepare_for_use ();
return mesh_changed;
}
refine_fraction must be in $ [0,1] $, and is 0.3 by default.
Definition at line 637 of file mesh_refinement.h.
References _refine_fraction, and _use_member_parameters.
{
_use_member_parameters = true;
return _refine_fraction;
}
Definition at line 622 of file mesh_refinement_flagging.C.
References _mesh, Elem::DO_NOTHING, MeshBase::elements_begin(), MeshBase::elements_end(), and Elem::INACTIVE.
{
MeshBase::element_iterator elem_it = _mesh.elements_begin();
const MeshBase::element_iterator elem_end = _mesh.elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
if ((*elem_it)->active())
{
(*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
(*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
}
else
{
(*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
(*elem_it)->set_refinement_flag(Elem::INACTIVE);
}
}
}
Definition at line 281 of file mesh_refinement.C.
References _mesh, Elem::active(), MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), Elem::level(), std::max(), Elem::n_neighbors(), Elem::neighbor(), Elem::p_level(), and remote_elem.
Referenced by coarsen_elements(), refine_and_coarsen_elements(), and refine_elements().
{
// This function must be run on all processors at once
parallel_only();
MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
bool failure = false;
for ( ; elem_it != elem_end && !failure; ++elem_it)
{
// Pointer to the element
Elem *elem = *elem_it;
for (unsigned int n=0; n<elem->n_neighbors(); n++)
{
Elem *neighbor = elem->neighbor(n);
if (!neighbor || !neighbor->active() ||
neighbor == remote_elem)
continue;
if ((neighbor->level() + 1 < elem->level()) ||
(neighbor->p_level() + 1 < elem->p_level()) ||
(neighbor->p_level() > elem->p_level() + 1))
{
failure = true;
break;
}
}
}
// If any processor failed, we failed globally
Parallel::max(failure);
if (failure)
{
// We didn't pass the level one test, so libmesh_assert that
// we're allowed not to
libmesh_assert(!libmesh_assert_pass);
return false;
}
return true;
}
Definition at line 329 of file mesh_refinement.C.
References _mesh, MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), Elem::COARSEN, std::max(), Elem::p_refinement_flag(), Elem::REFINE, and Elem::refinement_flag().
Referenced by refine_and_coarsen_elements().
{
// This function must be run on all processors at once
parallel_only();
bool found_flag = false;
// Search for local flags
MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
// Pointer to the element
Elem *elem = *elem_it;
if (elem->refinement_flag() == Elem::REFINE ||
elem->refinement_flag() == Elem::COARSEN ||
elem->p_refinement_flag() == Elem::REFINE ||
elem->p_refinement_flag() == Elem::COARSEN)
{
found_flag = true;
break;
}
}
// If we found a flag on any processor, it counts
Parallel::max(found_flag);
if (found_flag)
{
// We didn't pass the 'elements are unflagged' test,
// so libmesh_assert that we're allowed not to
libmesh_assert(!libmesh_assert_pass);
return false;
}
return true;
}
Definition at line 1624 of file mesh_refinement.C.
References _coarsen_elements(), _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), clean_refinement_flags(), Elem::COARSEN, Elem::COARSEN_INACTIVE, and MeshBase::prepare_for_use().
Referenced by UniformRefinementEstimator::_estimate_error().
{
// Coarsen n times
for (unsigned int rstep=0; rstep<n; rstep++)
{
// Clean up the refinement flags
this->clean_refinement_flags();
// Flag all the active elements for coarsening
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
(*elem_it)->set_refinement_flag(Elem::COARSEN);
if ((*elem_it)->parent())
(*elem_it)->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
}
// Coarsen all the elements we just flagged.
this->_coarsen_elements();
}
// Finally, the new mesh needs to be prepared for use
_mesh.prepare_for_use ();
}
Definition at line 1575 of file mesh_refinement.C.
References _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), and Elem::JUST_COARSENED.
Referenced by UniformRefinementEstimator::_estimate_error().
{
// Coarsen p times
for (unsigned int rstep=0; rstep<n; rstep++)
{
// P coarsen all the active elements
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
if ((*elem_it)->p_level() > 0)
{
(*elem_it)->set_p_level((*elem_it)->p_level()-1);
(*elem_it)->set_p_refinement_flag(Elem::JUST_COARSENED);
}
}
}
}
Definition at line 1556 of file mesh_refinement.C.
References _mesh, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), and Elem::JUST_REFINED.
Referenced by UniformRefinementEstimator::_estimate_error().
{
// Refine n times
for (unsigned int rstep=0; rstep<n; rstep++)
{
// P refine all the active elements
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
{
(*elem_it)->set_p_level((*elem_it)->p_level()+1);
(*elem_it)->set_p_refinement_flag(Elem::JUST_REFINED);
}
}
}
Definition at line 1597 of file mesh_refinement.C.
References _mesh, _refine_elements(), MeshBase::active_elements_begin(), MeshBase::active_elements_end(), clean_refinement_flags(), MeshBase::prepare_for_use(), and Elem::REFINE.
Referenced by UniformRefinementEstimator::_estimate_error().
{
// Refine n times
// FIXME - this won't work if n>1 and the mesh
// has already been attached to an equation system
for (unsigned int rstep=0; rstep<n; rstep++)
{
// Clean up the refinement flags
this->clean_refinement_flags();
// Flag all the active elements for refinement.
MeshBase::element_iterator elem_it = _mesh.active_elements_begin();
const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
for ( ; elem_it != elem_end; ++elem_it)
(*elem_it)->set_refinement_flag(Elem::REFINE);
// Refine all the elements we just flagged.
this->_refine_elements();
}
// Finally, the new mesh needs to be prepared for use
_mesh.prepare_for_use ();
}
Definition at line 274 of file mesh_refinement.C.
References _mesh, _new_nodes_map, and LocationMap< T >::init().
Referenced by _coarsen_elements(), and _refine_elements().
{
this->_new_nodes_map.init(_mesh);
}
Definition at line 620 of file mesh_refinement.h.
Referenced by absolute_global_tolerance(), and flag_elements_by_error_tolerance().
Definition at line 608 of file mesh_refinement.h.
Referenced by coarsen_by_parents(), flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_error_tolerance(), and flag_elements_by_nelem_target().
Definition at line 612 of file mesh_refinement.h.
Referenced by coarsen_fraction(), flag_elements_by_elem_fraction(), flag_elements_by_error_fraction(), flag_elements_by_error_tolerance(), flag_elements_by_mean_stddev(), and flag_elements_by_nelem_target().
Definition at line 616 of file mesh_refinement.h.
Referenced by coarsen_threshold(), flag_elements_by_error_tolerance(), and flag_elements_by_nelem_target().
Definition at line 622 of file mesh_refinement.h.
Referenced by coarsen_elements(), edge_level_mismatch_limit(), refine_and_coarsen_elements(), and refine_elements().
Definition at line 622 of file mesh_refinement.h.
Referenced by coarsen_elements(), face_level_mismatch_limit(), make_coarsening_compatible(), make_refinement_compatible(), refine_and_coarsen_elements(), and refine_elements().
Definition at line 614 of file mesh_refinement.h.
Referenced by 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(), and max_h_level().
Definition at line 595 of file mesh_refinement.h.
Referenced by _coarsen_elements(), _refine_elements(), add_elem(), add_p_to_h_refinement(), add_point(), clean_refinement_flags(), coarsen_elements(), eliminate_unrefined_patches(), 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(), get_mesh(), limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_coarsening_compatible(), make_flags_parallel_consistent(), make_refinement_compatible(), refine_and_coarsen_elements(), refine_elements(), switch_h_to_p_refinement(), test_level_one(), test_unflagged(), uniformly_coarsen(), uniformly_p_coarsen(), uniformly_p_refine(), uniformly_refine(), and update_nodes_map().
Definition at line 618 of file mesh_refinement.h.
Referenced by flag_elements_by_nelem_target(), and nelem_target().
Definition at line 590 of file mesh_refinement.h.
Referenced by _coarsen_elements(), _refine_elements(), add_point(), clear(), and update_nodes_map().
Definition at line 622 of file mesh_refinement.h.
Referenced by coarsen_elements(), node_level_mismatch_limit(), refine_and_coarsen_elements(), and refine_elements().
Definition at line 610 of file mesh_refinement.h.
Referenced by 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(), and refine_fraction().
Definition at line 602 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().
Generated automatically by Doxygen for libMesh from the source code.