libMesh::MeshRefinement Class Reference

#include <mesh_refinement.h>

List of all members.

Public Member Functions

 MeshRefinement (MeshBase &mesh)
void set_periodic_boundaries_ptr (PeriodicBoundaries *pb_ptr)
 ~MeshRefinement ()
void clear ()
void flag_elements_by_error_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void flag_elements_by_error_tolerance (const ErrorVector &error_per_cell)
bool flag_elements_by_nelem_target (const ErrorVector &error_per_cell)
void flag_elements_by_elem_fraction (const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void flag_elements_by_mean_stddev (const ErrorVector &error_per_cell, const Real refine_fraction=1.0, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
void 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)
void clean_refinement_flags ()
bool test_level_one (bool libmesh_assert_yes=false)
bool test_unflagged (bool libmesh_assert_yes=false)
Nodeadd_point (const Point &p, const processor_id_type processor_id, const Real tol)
Elemadd_elem (Elem *elem)
const MeshBaseget_mesh () const
MeshBaseget_mesh ()
bool & coarsen_by_parents ()
Realrefine_fraction ()
Realcoarsen_fraction ()
unsigned int & max_h_level ()
Realcoarsen_threshold ()
dof_id_typenelem_target ()
Realabsolute_global_tolerance ()
unsigned char & face_level_mismatch_limit ()
unsigned char & edge_level_mismatch_limit ()
unsigned char & node_level_mismatch_limit ()

Private Member Functions

 MeshRefinement (const MeshRefinement &)
MeshRefinementoperator= (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 ()
bool make_coarsening_compatible (const bool)
bool make_refinement_compatible (const bool)
bool make_flags_parallel_consistent ()
Elemtopological_neighbor (Elem *elem, const PointLocatorBase *point_locator, const unsigned int side)
bool has_topological_neighbor (Elem *elem, const PointLocatorBase *point_locator, Elem *neighbor)

Private Attributes

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
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
PeriodicBoundaries_periodic_boundaries

Detailed Description

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

Author:
Benjamin S. Kirk, 2002-2007.

Definition at line 61 of file mesh_refinement.h.


Constructor & Destructor Documentation

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

Constructor.

Definition at line 55 of file mesh_refinement.C.

00055                                            :
00056   _mesh(m),
00057   _use_member_parameters(false),
00058   _coarsen_by_parents(false),
00059   _refine_fraction(0.3),
00060   _coarsen_fraction(0.0),
00061   _max_h_level(libMesh::invalid_uint),
00062   _coarsen_threshold(10),
00063   _nelem_target(0),
00064   _absolute_global_tolerance(0.0),
00065   _face_level_mismatch_limit(1),
00066   _edge_level_mismatch_limit(0),
00067   _node_level_mismatch_limit(0)
00068 #ifdef LIBMESH_ENABLE_PERIODIC
00069   , _periodic_boundaries(NULL)
00070 #endif
00071 {
00072 }

libMesh::MeshRefinement::MeshRefinement ( const MeshRefinement  )  [private]
libMesh::MeshRefinement::~MeshRefinement (  ) 

Destructor. Deletes all the elements that are currently stored.

Definition at line 85 of file mesh_refinement.C.

References clear().

00086 {
00087   this->clear();
00088 }


Member Function Documentation

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. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.

Definition at line 1476 of file mesh_refinement.C.

References _mesh, _new_nodes_map, libMesh::Elem::active(), libMesh::MeshBase::boundary_info, clear(), libMesh::Elem::coarsen(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), end, libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::level(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::Parallel::Communicator::max(), libMesh::Elem::nullify_neighbors(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_level(), libMesh::Elem::set_p_refinement_flag(), update_nodes_map(), and libMesh::MeshBase::update_parallel_id_counts().

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

01477 {
01478   // This function must be run on all processors at once
01479   parallel_only();
01480 
01481   START_LOG ("_coarsen_elements()", "MeshRefinement");
01482 
01483   // Flag indicating if this call actually changes the mesh
01484   bool mesh_changed = false;
01485 
01486   // Clear the unused_elements data structure.
01487   // The elements have been packed since it was built,
01488   // so there are _no_ unused elements.  We cannot trust
01489   // any iterators currently in this data structure.
01490   // _unused_elements.clear();
01491 
01492   MeshBase::element_iterator       it  = _mesh.elements_begin();
01493   const MeshBase::element_iterator end = _mesh.elements_end();
01494 
01495   // Loop over the elements.
01496   for ( ; it != end; ++it)
01497     {
01498       Elem* elem = *it;
01499 
01500       // Not necessary when using elem_iterator
01501       // libmesh_assert(elem);
01502 
01503       // active elements flagged for coarsening will
01504       // no longer be deleted until MeshRefinement::contract()
01505       if (elem->refinement_flag() == Elem::COARSEN)
01506         {
01507           // Huh?  no level-0 element should be active
01508           // and flagged for coarsening.
01509           libmesh_assert_not_equal_to (elem->level(), 0);
01510 
01511           // Remove this element from any neighbor
01512           // lists that point to it.
01513           elem->nullify_neighbors();
01514 
01515           // Remove any boundary information associated
01516           // with this element
01517           _mesh.boundary_info->remove (elem);
01518 
01519           // Add this iterator to the _unused_elements
01520           // data structure so we might fill it.
01521           // The _unused_elements optimization is currently off.
01522           // _unused_elements.push_back (it);
01523 
01524           // Don't delete the element until
01525           // MeshRefinement::contract()
01526           // _mesh.delete_elem(elem);
01527 
01528           // the mesh has certainly changed
01529           mesh_changed = true;
01530         }
01531 
01532       // inactive elements flagged for coarsening
01533       // will become active
01534       else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
01535         {
01536           elem->coarsen();
01537           libmesh_assert (elem->active());
01538 
01539           // the mesh has certainly changed
01540           mesh_changed = true;
01541         }
01542       if (elem->p_refinement_flag() == Elem::COARSEN)
01543         {
01544           if (elem->p_level() > 0)
01545             {
01546               elem->set_p_refinement_flag(Elem::JUST_COARSENED);
01547               elem->set_p_level(elem->p_level() - 1);
01548               mesh_changed = true;
01549             }
01550           else
01551             {
01552               elem->set_p_refinement_flag(Elem::DO_NOTHING);
01553             }
01554         }
01555     }
01556 
01557   // If the mesh changed on any processor, it changed globally
01558   CommWorld.max(mesh_changed);
01559   // And we may need to update ParallelMesh values reflecting the changes
01560   if (mesh_changed)
01561     _mesh.update_parallel_id_counts();
01562 
01563   // Node processor ids may need to change if an element of that id
01564   // was coarsened away
01565   if (mesh_changed && !_mesh.is_serial())
01566     {
01567       // Update the _new_nodes_map so that processors can
01568       // find requested nodes
01569       this->update_nodes_map ();
01570 
01571       MeshCommunication().make_nodes_parallel_consistent
01572         (_mesh, _new_nodes_map);
01573 
01574       // Clear the _new_nodes_map
01575       this->clear();
01576 
01577 #ifdef DEBUG
01578       MeshTools::libmesh_assert_valid_procids<Node>(_mesh);
01579 #endif
01580     }
01581 
01582   STOP_LOG ("_coarsen_elements()", "MeshRefinement");
01583 
01584   return mesh_changed;
01585 }

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. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.

Definition at line 1589 of file mesh_refinement.C.

References _mesh, _new_nodes_map, libMesh::Elem::active(), clear(), libMesh::CommWorld, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), end, libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_REFINED, libMesh::MeshBase::libmesh_assert_valid_parallel_ids(), libMesh::Parallel::Communicator::max(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_level(), libMesh::Elem::set_p_refinement_flag(), update_nodes_map(), and libMesh::MeshBase::update_parallel_id_counts().

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

01590 {
01591   // This function must be run on all processors at once
01592   parallel_only();
01593 
01594   // Update the _new_nodes_map so that elements can
01595   // find nodes to connect to.
01596   this->update_nodes_map ();
01597 
01598   START_LOG ("_refine_elements()", "MeshRefinement");
01599 
01600   // Iterate over the elements, counting the elements
01601   // flagged for h refinement.
01602   dof_id_type n_elems_flagged = 0;
01603 
01604   MeshBase::element_iterator       it  = _mesh.elements_begin();
01605   const MeshBase::element_iterator end = _mesh.elements_end();
01606 
01607   for (; it != end; ++it)
01608     {
01609       Elem* elem = *it;
01610       if (elem->refinement_flag() == Elem::REFINE)
01611         n_elems_flagged++;
01612     }
01613 
01614   // Construct a local vector of Elem* which have been
01615   // previously marked for refinement.  We reserve enough
01616   // space to allow for every element to be refined.
01617   std::vector<Elem*> local_copy_of_elements;
01618   local_copy_of_elements.reserve(n_elems_flagged);
01619 
01620   // Iterate over the elements, looking for elements
01621   // flagged for refinement.
01622   for (it = _mesh.elements_begin(); it != end; ++it)
01623     {
01624       Elem* elem = *it;
01625       if (elem->refinement_flag() == Elem::REFINE)
01626         local_copy_of_elements.push_back(elem);
01627       if (elem->p_refinement_flag() == Elem::REFINE &&
01628           elem->active())
01629         {
01630           elem->set_p_level(elem->p_level()+1);
01631           elem->set_p_refinement_flag(Elem::JUST_REFINED);
01632         }
01633     }
01634 
01635   // Now iterate over the local copies and refine each one.
01636   // This may resize the mesh's internal container and invalidate
01637   // any existing iterators.
01638 
01639   for (std::size_t e = 0; e != local_copy_of_elements.size(); ++e)
01640     local_copy_of_elements[e]->refine(*this);
01641 
01642   // The mesh changed if there were elements h refined
01643   bool mesh_changed = !local_copy_of_elements.empty();
01644 
01645   // If the mesh changed on any processor, it changed globally
01646   CommWorld.max(mesh_changed);
01647 
01648   // And we may need to update ParallelMesh values reflecting the changes
01649   if (mesh_changed)
01650     _mesh.update_parallel_id_counts();
01651 
01652   if (mesh_changed && !_mesh.is_serial())
01653     {
01654       MeshCommunication().make_elems_parallel_consistent (_mesh);
01655       MeshCommunication().make_nodes_parallel_consistent
01656         (_mesh, _new_nodes_map);
01657 #ifdef DEBUG
01658       _mesh.libmesh_assert_valid_parallel_ids();
01659 #endif
01660     }
01661 
01662   // Clear the _new_nodes_map and _unused_elements data structures.
01663   this->clear();
01664 
01665   STOP_LOG ("_refine_elements()", "MeshRefinement");
01666 
01667   return mesh_changed;
01668 }

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

References _absolute_global_tolerance, and _use_member_parameters.

00693 {
00694   _use_member_parameters = true;
00695   return _absolute_global_tolerance;
00696 }

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

Adds the element elem to the mesh.

Definition at line 129 of file mesh_refinement.C.

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

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

00130 {
00131   libmesh_assert(elem);
00132 
00133 
00134 //   // If the unused_elements has any iterators from
00135 //   // old elements, take the first one
00136 //   if (!_unused_elements.empty())
00137 //     {
00138 //       std::vector<Elem*>::iterator it = _unused_elements.front();
00139 
00140 //       *it = elem;
00141 
00142 //       _unused_elements.pop_front();
00143 //     }
00144 
00145 //   // Otherwise, use the conventional add method
00146 //   else
00147 //     {
00148 //       _mesh.add_elem (elem);
00149 //     }
00150 
00151   // The _unused_elements optimization has been turned off.
00152   _mesh.add_elem (elem);
00153 
00154   return elem;
00155 }

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

References _mesh, libMesh::MeshBase::elements_begin(), and libMesh::MeshBase::elements_end().

00678 {
00679   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00680   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00681 
00682   for ( ; elem_it != elem_end; ++elem_it)
00683     (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00684 }

Node * libMesh::MeshRefinement::add_point ( const Point p,
const processor_id_type  processor_id,
const Real  tol 
)

Add point p to the mesh. The function returns a pointer to the new node. The processor_id is assigned to the new node (only if no existing node is found. The tolerance tol tells the method how far away from p to search for existing nodes.

Definition at line 99 of file mesh_refinement.C.

References _mesh, _new_nodes_map, libMesh::MeshBase::add_point(), libMesh::LocationMap< T >::find(), libMesh::LocationMap< T >::insert(), and libMesh::DofObject::invalid_id.

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

00102 {
00103   START_LOG("add_point()", "MeshRefinement");
00104 
00105   // Return the node if it already exists
00106   Node *node = _new_nodes_map.find(p, tol);
00107   if (node)
00108     {
00109       STOP_LOG("add_point()", "MeshRefinement");
00110       return node;
00111     }
00112 
00113   // Add the node, with a default id and the requested
00114   // processor_id
00115   node = _mesh.add_point (p, DofObject::invalid_id, processor_id);
00116 
00117   libmesh_assert(node);
00118 
00119   // Add the node to the map.
00120   _new_nodes_map.insert(*node);
00121 
00122   // Return the address of the new node
00123   STOP_LOG("add_point()", "MeshRefinement");
00124   return node;
00125 }

void libMesh::MeshRefinement::clean_refinement_flags (  ) 

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

Definition at line 688 of file mesh_refinement_flagging.C.

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

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

00689 {
00690   // Possibly clean up the refinement flags from
00691   // a previous step
00692 //   elem_iterator       elem_it (_mesh.elements_begin());
00693 //   const elem_iterator elem_end(_mesh.elements_end());
00694 
00695   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00696   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00697 
00698   for ( ; elem_it != elem_end; ++elem_it)
00699     {
00700       if ((*elem_it)->active())
00701         {
00702           (*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
00703           (*elem_it)->set_p_refinement_flag(Elem::DO_NOTHING);
00704         }
00705       else
00706         {
00707           (*elem_it)->set_refinement_flag(Elem::INACTIVE);
00708           (*elem_it)->set_p_refinement_flag(Elem::INACTIVE);
00709         }
00710     }
00711 }

void libMesh::MeshRefinement::clear (  ) 

Deletes all the data that are currently stored.

Definition at line 92 of file mesh_refinement.C.

References _new_nodes_map, and libMesh::LocationMap< T >::clear().

Referenced by _coarsen_elements(), _refine_elements(), and ~MeshRefinement().

00093 {
00094   _new_nodes_map.clear();
00095 }

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

References _coarsen_by_parents, and _use_member_parameters.

00657 {
00658   _use_member_parameters = true;
00659   return _coarsen_by_parents;
00660 }

bool libMesh::MeshRefinement::coarsen_elements ( const bool  maintain_level_one = true  ) 

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. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.

The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.

Definition at line 599 of file mesh_refinement.C.

References _coarsen_elements(), _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, libMesh::Elem::active(), libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), eliminate_unrefined_patches(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_REFINED, limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_coarsening_compatible(), make_flags_parallel_consistent(), libMesh::Parallel::Communicator::max(), libMesh::Parallel::Communicator::min(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), and test_level_one().

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

00600 {
00601   // This function must be run on all processors at once
00602   parallel_only();
00603 
00604   bool _maintain_level_one = maintain_level_one;
00605 
00606   // If the user used non-default parameters, let's warn that they're
00607   // deprecated
00608   if (!maintain_level_one)
00609     {
00610       libmesh_deprecated();
00611     }
00612   else
00613     _maintain_level_one = _face_level_mismatch_limit;
00614 
00615   // We can't yet turn a non-level-one mesh into a level-one mesh
00616   if (_maintain_level_one)
00617     libmesh_assert(test_level_one(true));
00618 
00619   // Possibly clean up the refinement flags from
00620   // a previous step
00621   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00622   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00623 
00624   for ( ; elem_it != elem_end; ++elem_it)
00625     {
00626       // Pointer to the element
00627       Elem* elem = *elem_it;
00628 
00629       // Set refinement flag to INACTIVE if the
00630       // element isn't active
00631       if ( !elem->active())
00632         {
00633           elem->set_refinement_flag(Elem::INACTIVE);
00634           elem->set_p_refinement_flag(Elem::INACTIVE);
00635         }
00636 
00637       // This might be left over from the last step
00638       if (elem->refinement_flag() == Elem::JUST_REFINED)
00639         elem->set_refinement_flag(Elem::DO_NOTHING);
00640     }
00641 
00642   // Parallel consistency has to come first, or coarsening
00643   // along processor boundaries might occasionally be falsely
00644   // prevented
00645   if (!_mesh.is_serial())
00646     this->make_flags_parallel_consistent();
00647 
00648   // Repeat until flag changes match on every processor
00649   do
00650     {
00651       // Repeat until the flags form a conforming mesh.
00652       bool satisfied = false;
00653       do
00654         {
00655           const bool coarsening_satisfied =
00656             this->make_coarsening_compatible(maintain_level_one);
00657 
00658           bool smoothing_satisfied =
00659             !this->eliminate_unrefined_patches();// &&
00660 
00661           if (_edge_level_mismatch_limit)
00662             smoothing_satisfied = smoothing_satisfied &&
00663               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00664 
00665           if (_node_level_mismatch_limit)
00666             smoothing_satisfied = smoothing_satisfied &&
00667               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00668 
00669           satisfied = (coarsening_satisfied &&
00670                        smoothing_satisfied);
00671 #ifdef DEBUG
00672           bool max_satisfied = satisfied,
00673                min_satisfied = satisfied;
00674           CommWorld.max(max_satisfied);
00675           CommWorld.min(min_satisfied);
00676           libmesh_assert_equal_to (satisfied, max_satisfied);
00677           libmesh_assert_equal_to (satisfied, min_satisfied);
00678 #endif
00679         }
00680       while (!satisfied);
00681     }
00682   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00683 
00684   // Coarsen the flagged elements.
00685   const bool mesh_changed =
00686     this->_coarsen_elements ();
00687 
00688   if (_maintain_level_one)
00689     libmesh_assert(test_level_one(true));
00690   libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00691 // FIXME: This won't pass unless we add a redundant find_neighbors()
00692 // call or replace find_neighbors() with on-the-fly neighbor updating
00693 // libmesh_assert(!this->eliminate_unrefined_patches());
00694 
00695   // We can't contract the mesh ourselves anymore - a System might
00696   // need to restrict old coefficient vectors first
00697   // _mesh.contract();
00698 
00699   // Finally, the new mesh may need to be prepared for use
00700   if (mesh_changed)
00701     _mesh.prepare_for_use (/*skip_renumber =*/false);
00702 
00703   return mesh_changed;
00704 }

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

References _coarsen_fraction, and _use_member_parameters.

00669 {
00670   _use_member_parameters = true;
00671   return _coarsen_fraction;
00672 }

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

References _coarsen_threshold, and _use_member_parameters.

00681 {
00682   _use_member_parameters = true;
00683   return _coarsen_threshold;
00684 }

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

References libMesh::CommWorld, libMesh::DofObject::id(), std::max(), std::min(), libMesh::Parallel::Communicator::min(), libMesh::Elem::parent(), libMesh::Parallel::Communicator::sum(), and libMesh::Parallel::Communicator::verify().

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

00164 {
00165   // This function must be run on all processors at once
00166   parallel_only();
00167 
00168   // Make sure the input error vector is valid
00169 #ifdef DEBUG
00170   for (std::size_t i=0; i != error_per_cell.size(); ++i)
00171     {
00172       libmesh_assert_greater_equal (error_per_cell[i], 0);
00173   // isnan() isn't standard C++ yet
00174   #ifdef isnan
00175       libmesh_assert(!isnan(error_per_cell[i]));
00176   #endif
00177     }
00178 
00179   // Use a reference to std::vector to avoid confusing
00180   // CommWorld.verify
00181   std::vector<ErrorVectorReal> &epc = error_per_parent;
00182   libmesh_assert(CommWorld.verify(epc));
00183 #endif // #ifdef DEBUG
00184 
00185   // error values on uncoarsenable elements will be left at -1
00186   error_per_parent.clear();
00187   error_per_parent.resize(error_per_cell.size(), 0.0);
00188 
00189   {
00190   // Find which elements are uncoarsenable
00191   MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00192   const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00193   for (; elem_it != elem_end; ++elem_it)
00194     {
00195       Elem* elem   = *elem_it;
00196       Elem* parent = elem->parent();
00197 
00198       // Active elements are uncoarsenable
00199       error_per_parent[elem->id()] = -1.0;
00200 
00201       // Grandparents and up are uncoarsenable
00202       while (parent)
00203         {
00204           parent = parent->parent();
00205           if (parent)
00206             {
00207               const dof_id_type parentid  = parent->id();
00208               libmesh_assert_less (parentid, error_per_parent.size());
00209               error_per_parent[parentid] = -1.0;
00210             }
00211         }
00212     }
00213 
00214   // Sync between processors.
00215   // Use a reference to std::vector to avoid confusing
00216   // CommWorld.min
00217   std::vector<ErrorVectorReal> &epp = error_per_parent;
00218   CommWorld.min(epp);
00219   }
00220 
00221   // The parent's error is defined as the square root of the
00222   // sum of the children's errors squared, so errors that are
00223   // Hilbert norms remain Hilbert norms.
00224   //
00225   // Because the children may be on different processors, we
00226   // calculate local contributions to the parents' errors squared
00227   // first, then sum across processors and take the square roots
00228   // second.
00229   {
00230   MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00231   const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00232 
00233   for (; elem_it != elem_end; ++elem_it)
00234     {
00235       Elem* elem   = *elem_it;
00236       Elem* parent = elem->parent();
00237 
00238       // Calculate each contribution to parent cells
00239       if (parent)
00240         {
00241           const dof_id_type parentid  = parent->id();
00242           libmesh_assert_less (parentid, error_per_parent.size());
00243 
00244           // If the parent has grandchildren we won't be able to
00245           // coarsen it, so forget it.  Otherwise, add this child's
00246           // contribution to the sum of the squared child errors
00247           if (error_per_parent[parentid] != -1.0)
00248             error_per_parent[parentid] += (error_per_cell[elem->id()] *
00249                                            error_per_cell[elem->id()]);
00250         }
00251     }
00252   }
00253 
00254   // Sum the vector across all processors
00255   CommWorld.sum(static_cast<std::vector<ErrorVectorReal>&>(error_per_parent));
00256 
00257   // Calculate the min and max as we loop
00258   parent_error_min = std::numeric_limits<double>::max();
00259   parent_error_max = 0.;
00260 
00261   for (std::size_t i = 0; i != error_per_parent.size(); ++i)
00262     {
00263       // If this element isn't a coarsenable parent with error, we
00264       // have nothing to do.  Just flag it as -1 and move on
00265       // Note that CommWorld.sum might have left uncoarsenable
00266       // elements with error_per_parent=-n_proc, so reset it to
00267       // error_per_parent=-1
00268       if (error_per_parent[i] < 0.)
00269         {
00270           error_per_parent[i] = -1.;
00271           continue;
00272         }
00273 
00274       // The error estimator might have already given us an
00275       // estimate on the coarsenable parent elements; if so then
00276       // we want to retain that estimate
00277       if (error_per_cell[i])
00278         {
00279           error_per_parent[i] = error_per_cell[i];
00280           continue;
00281         }
00282       // if not, then e_parent = sqrt(sum(e_child^2))
00283       else
00284         error_per_parent[i] = std::sqrt(error_per_parent[i]);
00285 
00286       parent_error_min = std::min (parent_error_min,
00287                                    error_per_parent[i]);
00288       parent_error_max = std::max (parent_error_max,
00289                                    error_per_parent[i]);
00290     }
00291 }

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

References _edge_level_mismatch_limit.

00704 {
00705   return _edge_level_mismatch_limit;
00706 }

bool libMesh::MeshRefinement::eliminate_unrefined_patches (  )  [private]

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

   o---o---o---o---o---o---o
   |   |   |   |   |   |   |
   |   |   |   |   |   |   |
   o---o---o---o---o---o---o
   |   |   |   |   |   |   |
   |   |   |   |   |   |   |
   o---o---o---o---o---o---o
   |   |   |       |   |   |
   |   |   |       |   |   |
   o---o---o       o---o---o
   |   |   |       |   |   |
   |   |   |       |   |   |
   o---o---o---o---o---o---o
   |   |   |   |   |   |   |
   |   |   |   |   |   |   |
   o---o---o---o---o---o---o
   |   |   |   |   |   |   |
   |   |   |   |   |   |   |
   o---o---o---o---o---o---o
   

into this:

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

by refining the indicated element

Definition at line 266 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::Elem::active(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::ancestor(), libMesh::Elem::child(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::Elem::INACTIVE, libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), libMesh::Elem::min_new_p_level_by_neighbor(), libMesh::Elem::n_children(), libMesh::Elem::n_neighbors(), libMesh::Elem::neighbor(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::parent(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Elem::set_p_refinement_flag(), and libMesh::Elem::set_refinement_flag().

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

00267 {
00268   // This function must be run on all processors at once
00269   parallel_only();
00270 
00271   bool flags_changed = false;
00272 
00273   MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00274   const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00275 
00276   for (; elem_it != elem_end; ++elem_it)
00277     {
00278       Elem* elem = *elem_it;
00279       // First assume that we'll have to flag this element for both h
00280       // and p refinement, then change our minds if we see any
00281       // neighbors that are as coarse or coarser than us.
00282       bool h_flag_me = true,
00283            p_flag_me = true;
00284 
00285 
00286       // Skip the element if it is already fully flagged for refinement
00287       if (elem->p_refinement_flag() == Elem::REFINE)
00288         p_flag_me = false;
00289       if (elem->refinement_flag() == Elem::REFINE)
00290         {
00291           h_flag_me = false;
00292           if (!p_flag_me)
00293             continue;
00294         }
00295       // Test the parent if that is already flagged for coarsening
00296       else if (elem->refinement_flag() == Elem::COARSEN)
00297         {
00298           libmesh_assert(elem->parent());
00299           elem = elem->parent();
00300           // FIXME - this doesn't seem right - RHS
00301           if (elem->refinement_flag() != Elem::COARSEN_INACTIVE)
00302             continue;
00303           p_flag_me = false;
00304         }
00305 
00306       const unsigned int my_level = elem->level();
00307       int my_p_adjustment = 0;
00308       if (elem->p_refinement_flag() == Elem::REFINE)
00309         my_p_adjustment = 1;
00310       else if (elem->p_refinement_flag() == Elem::COARSEN)
00311         {
00312           libmesh_assert_greater (elem->p_level(), 0);
00313           my_p_adjustment = -1;
00314         }
00315       const unsigned int my_new_p_level = elem->p_level() +
00316                                           my_p_adjustment;
00317 
00318       // Check all the element neighbors
00319       for (unsigned int n=0; n<elem->n_neighbors(); n++)
00320         {
00321           const Elem *neighbor = elem->neighbor(n);
00322           // Quit if the element is on a local boundary
00323           if (neighbor == NULL || neighbor == remote_elem)
00324             {
00325               h_flag_me = false;
00326               p_flag_me = false;
00327               break;
00328             }
00329           // if the neighbor will be equally or less refined than
00330           // we are, then we will not become an unrefined island.
00331           // So if we are still considering h refinement:
00332           if (h_flag_me &&
00333             // If our neighbor is already at a lower level,
00334             // it can't end up at a higher level even if it
00335             // is flagged for refinement once
00336              ((neighbor->level() < my_level) ||
00337             // If our neighbor is at the same level but isn't
00338             // flagged for refinement, it won't end up at a
00339             // higher level
00340              ((neighbor->active()) &&
00341               (neighbor->refinement_flag() != Elem::REFINE)) ||
00342             // If our neighbor is currently more refined but is
00343             // a parent flagged for coarsening, it will end up
00344             // at the same level.
00345              (neighbor->refinement_flag() == Elem::COARSEN_INACTIVE)))
00346             {
00347               // We've proven we won't become an unrefined island,
00348               // so don't h refine to avoid that.
00349               h_flag_me = false;
00350 
00351               // If we've also proven we don't need to p refine,
00352               // we don't need to check more neighbors
00353               if (!p_flag_me)
00354                 break;
00355             }
00356           if (p_flag_me)
00357             {
00358               // if active neighbors will have a p level
00359               // equal to or lower than ours, then we do not need to p
00360               // refine ourselves.
00361               if (neighbor->active())
00362                 {
00363                   int p_adjustment = 0;
00364                   if (neighbor->p_refinement_flag() == Elem::REFINE)
00365                     p_adjustment = 1;
00366                   else if (neighbor->p_refinement_flag() == Elem::COARSEN)
00367                     {
00368                       libmesh_assert_greater (neighbor->p_level(), 0);
00369                       p_adjustment = -1;
00370                     }
00371                   if (my_new_p_level >= neighbor->p_level() + p_adjustment)
00372                     {
00373                       p_flag_me = false;
00374                       if (!h_flag_me)
00375                         break;
00376                     }
00377                 }
00378               // If we have inactive neighbors, we need to
00379               // test all their active descendants which neighbor us
00380               else if (neighbor->ancestor())
00381                 {
00382                   if (neighbor->min_new_p_level_by_neighbor(elem,
00383                       my_new_p_level + 2) <= my_new_p_level)
00384                     {
00385                       p_flag_me = false;
00386                       if (!h_flag_me)
00387                         break;
00388                     }
00389                 }
00390             }
00391         }
00392 
00393       if (h_flag_me)
00394         {
00395           // Parents that would create islands should no longer
00396           // coarsen
00397           if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
00398             {
00399               for (unsigned int c=0; c<elem->n_children(); c++)
00400                 {
00401                   libmesh_assert_equal_to (elem->child(c)->refinement_flag(),
00402                                           Elem::COARSEN);
00403                   elem->child(c)->set_refinement_flag(Elem::DO_NOTHING);
00404                 }
00405               elem->set_refinement_flag(Elem::INACTIVE);
00406             }
00407           else
00408             elem->set_refinement_flag(Elem::REFINE);
00409           flags_changed = true;
00410         }
00411       if (p_flag_me)
00412         {
00413           if (elem->p_refinement_flag() == Elem::COARSEN)
00414             elem->set_p_refinement_flag(Elem::DO_NOTHING);
00415           else
00416             elem->set_p_refinement_flag(Elem::REFINE);
00417           flags_changed = true;
00418         }
00419     }
00420 
00421   // If flags changed on any processor then they changed globally
00422   CommWorld.max(flags_changed);
00423 
00424   return flags_changed;
00425 }

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

References _face_level_mismatch_limit.

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

00699 {
00700   return _face_level_mismatch_limit;
00701 }

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

References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Parallel::Communicator::allgather(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::CommWorld, create_parent_error_vector(), libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, libMesh::Elem::level(), libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_elem(), libMesh::Elem::parent(), libMesh::Real, libMesh::Elem::REFINE, and libMesh::Elem::set_refinement_flag().

00456 {
00457   parallel_only();
00458 
00459   // The function arguments are currently just there for
00460   // backwards_compatibility
00461   if (!_use_member_parameters)
00462   {
00463     // If the user used non-default parameters, lets warn
00464     // that they're deprecated
00465     if (refine_frac != 0.3 ||
00466         coarsen_frac != 0.0 ||
00467         max_l != libMesh::invalid_uint)
00468       libmesh_deprecated();
00469 
00470     _refine_fraction = refine_frac;
00471     _coarsen_fraction = coarsen_frac;
00472     _max_h_level = max_l;
00473   }
00474 
00475   // Check for valid fractions..
00476   // The fraction values must be in [0,1]
00477   libmesh_assert_greater_equal (_refine_fraction, 0);
00478   libmesh_assert_less_equal (_refine_fraction, 1);
00479   libmesh_assert_greater_equal (_coarsen_fraction, 0);
00480   libmesh_assert_less_equal (_coarsen_fraction, 1);
00481 
00482   // The number of active elements in the mesh
00483   const dof_id_type n_active_elem  = _mesh.n_elem();
00484 
00485   // The number of elements to flag for coarsening
00486   const dof_id_type n_elem_coarsen =
00487     static_cast<dof_id_type>(_coarsen_fraction * n_active_elem);
00488 
00489   // The number of elements to flag for refinement
00490   const dof_id_type n_elem_refine =
00491     static_cast<dof_id_type>(_refine_fraction  * n_active_elem);
00492 
00493 
00494 
00495   // Clean up the refinement flags.  These could be left
00496   // over from previous refinement steps.
00497   this->clean_refinement_flags();
00498 
00499 
00500   // This vector stores the error and element number for all the
00501   // active elements.  It will be sorted and the top & bottom
00502   // elements will then be flagged for coarsening & refinement
00503   std::vector<ErrorVectorReal> sorted_error;
00504 
00505   sorted_error.reserve (n_active_elem);
00506 
00507   // Loop over the active elements and create the entry
00508   // in the sorted_error vector
00509   MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00510   const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00511 
00512   for (; elem_it != elem_end; ++elem_it)
00513     sorted_error.push_back (error_per_cell[(*elem_it)->id()]);
00514 
00515   CommWorld.allgather(sorted_error);
00516 
00517   // Now sort the sorted_error vector
00518   std::sort (sorted_error.begin(), sorted_error.end());
00519 
00520   // If we're coarsening by parents:
00521   // Create a sorted error vector with coarsenable parent elements
00522   // only, sorted by lowest errors first
00523   ErrorVector error_per_parent, sorted_parent_error;
00524   if (_coarsen_by_parents)
00525   {
00526     Real parent_error_min, parent_error_max;
00527 
00528     create_parent_error_vector(error_per_cell,
00529                                error_per_parent,
00530                                parent_error_min,
00531                                parent_error_max);
00532 
00533     sorted_parent_error = error_per_parent;
00534     std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
00535 
00536     // All the other error values will be 0., so get rid of them.
00537     sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
00538                                            sorted_parent_error.end(), 0.),
00539                                sorted_parent_error.end());
00540   }
00541 
00542 
00543   ErrorVectorReal top_error= 0., bottom_error = 0.;
00544 
00545   // Get the maximum error value corresponding to the
00546   // bottom n_elem_coarsen elements
00547   if (_coarsen_by_parents && n_elem_coarsen)
00548     {
00549       const unsigned int dim = _mesh.mesh_dimension();
00550       unsigned int twotodim = 1;
00551       for (unsigned int i=0; i!=dim; ++i)
00552         twotodim *= 2;
00553 
00554       dof_id_type n_parent_coarsen = n_elem_coarsen / (twotodim - 1);
00555 
00556       if (n_parent_coarsen)
00557         bottom_error = sorted_parent_error[n_parent_coarsen - 1];
00558     }
00559   else if (n_elem_coarsen)
00560     {
00561       bottom_error = sorted_error[n_elem_coarsen - 1];
00562     }
00563 
00564   if (n_elem_refine)
00565     top_error = sorted_error[sorted_error.size() - n_elem_refine];
00566 
00567   // Finally, let's do the element flagging
00568   elem_it  = _mesh.active_elements_begin();
00569   for (; elem_it != elem_end; ++elem_it)
00570     {
00571       Elem* elem = *elem_it;
00572       Elem* parent = elem->parent();
00573 
00574       if (_coarsen_by_parents && parent && n_elem_coarsen &&
00575           error_per_parent[parent->id()] <= bottom_error)
00576         elem->set_refinement_flag(Elem::COARSEN);
00577 
00578       if (!_coarsen_by_parents && n_elem_coarsen &&
00579           error_per_cell[elem->id()] <= bottom_error)
00580         elem->set_refinement_flag(Elem::COARSEN);
00581 
00582       if (n_elem_refine &&
00583           elem->level() < _max_h_level &&
00584           error_per_cell[elem->id()] >= top_error)
00585         elem->set_refinement_flag(Elem::REFINE);
00586     }
00587 }

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

References _coarsen_by_parents, _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::CommWorld, create_parent_error_vector(), libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), std::max(), libMesh::Parallel::Communicator::min(), std::min(), libMesh::Elem::parent(), libMesh::Real, libMesh::Elem::REFINE, and libMesh::Elem::set_refinement_flag().

00049 {
00050   parallel_only();
00051 
00052   // The function arguments are currently just there for
00053   // backwards_compatibility
00054   if (!_use_member_parameters)
00055   {
00056     // If the user used non-default parameters, lets warn
00057     // that they're deprecated
00058     if (refine_frac != 0.3 ||
00059         coarsen_frac != 0.0 ||
00060         max_l != libMesh::invalid_uint)
00061       libmesh_deprecated();
00062 
00063     _refine_fraction = refine_frac;
00064     _coarsen_fraction = coarsen_frac;
00065     _max_h_level = max_l;
00066   }
00067 
00068   // Check for valid fractions..
00069   // The fraction values must be in [0,1]
00070   libmesh_assert_greater_equal (_refine_fraction, 0);
00071   libmesh_assert_less_equal (_refine_fraction, 1);
00072   libmesh_assert_greater_equal (_coarsen_fraction, 0);
00073   libmesh_assert_less_equal (_coarsen_fraction, 1);
00074 
00075   // Clean up the refinement flags.  These could be left
00076   // over from previous refinement steps.
00077   this->clean_refinement_flags();
00078 
00079   // We're getting the minimum and maximum error values
00080   // for the ACTIVE elements
00081   Real error_min = 1.e30;
00082   Real error_max = 0.;
00083 
00084   // And, if necessary, for their parents
00085   Real parent_error_min = 1.e30;
00086   Real parent_error_max = 0.;
00087 
00088   // Prepare another error vector if we need to sum parent errors
00089   ErrorVector error_per_parent;
00090   if (_coarsen_by_parents)
00091   {
00092     create_parent_error_vector(error_per_cell,
00093                                error_per_parent,
00094                                parent_error_min,
00095                                parent_error_max);
00096   }
00097 
00098   // We need to loop over all active elements to find the minimum
00099   MeshBase::element_iterator       el_it  =
00100     _mesh.active_local_elements_begin();
00101   const MeshBase::element_iterator el_end =
00102     _mesh.active_local_elements_end();
00103 
00104   for (; el_it != el_end; ++el_it)
00105   {
00106     const dof_id_type id  = (*el_it)->id();
00107     libmesh_assert_less (id, error_per_cell.size());
00108 
00109     error_max = std::max (error_max, error_per_cell[id]);
00110     error_min = std::min (error_min, error_per_cell[id]);
00111   }
00112   CommWorld.max(error_max);
00113   CommWorld.min(error_min);
00114 
00115   // Compute the cutoff values for coarsening and refinement
00116   const Real error_delta = (error_max - error_min);
00117   const Real parent_error_delta = parent_error_max - parent_error_min;
00118 
00119   const Real refine_cutoff  = (1.- _refine_fraction)*error_max;
00120   const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min;
00121   const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min;
00122 
00123 //   // Print information about the error
00124 //   libMesh::out << " Error Information:"                     << std::endl
00125 //          << " ------------------"                     << std::endl
00126 //          << "   min:              " << error_min      << std::endl
00127 //          << "   max:              " << error_max      << std::endl
00128 //          << "   delta:            " << error_delta    << std::endl
00129 //          << "     refine_cutoff:  " << refine_cutoff  << std::endl
00130 //          << "     coarsen_cutoff: " << coarsen_cutoff << std::endl;
00131 
00132 
00133 
00134   // Loop over the elements and flag them for coarsening or
00135   // refinement based on the element error
00136 
00137   MeshBase::element_iterator       e_it  =
00138     _mesh.active_elements_begin();
00139   const MeshBase::element_iterator e_end =
00140     _mesh.active_elements_end();
00141   for (; e_it != e_end; ++e_it)
00142   {
00143     Elem* elem           = *e_it;
00144     const dof_id_type id = elem->id();
00145 
00146     libmesh_assert_less (id, error_per_cell.size());
00147 
00148     const ErrorVectorReal elem_error = error_per_cell[id];
00149 
00150     if (_coarsen_by_parents)
00151     {
00152       Elem* parent           = elem->parent();
00153       if (parent)
00154       {
00155         const dof_id_type parentid  = parent->id();
00156         if (error_per_parent[parentid] >= 0. &&
00157             error_per_parent[parentid] <= parent_cutoff)
00158           elem->set_refinement_flag(Elem::COARSEN);
00159       }
00160     }
00161     // Flag the element for coarsening if its error
00162     // is <= coarsen_fraction*delta + error_min
00163     else if (elem_error <= coarsen_cutoff)
00164     {
00165       elem->set_refinement_flag(Elem::COARSEN);
00166     }
00167 
00168     // Flag the element for refinement if its error
00169     // is >= refinement_cutoff.
00170     if (elem_error >= refine_cutoff)
00171       if (elem->level() < _max_h_level)
00172         elem->set_refinement_flag(Elem::REFINE);
00173   }
00174 }

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

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

00179 {
00180   parallel_only();
00181 
00182   libmesh_assert_greater (_coarsen_threshold, 0);
00183 
00184   // Check for valid fractions..
00185   // The fraction values must be in [0,1]
00186   libmesh_assert_greater_equal (_refine_fraction, 0);
00187   libmesh_assert_less_equal (_refine_fraction, 1);
00188   libmesh_assert_greater_equal (_coarsen_fraction, 0);
00189   libmesh_assert_less_equal (_coarsen_fraction, 1);
00190 
00191   // How much error per cell will we tolerate?
00192   const Real local_refinement_tolerance =
00193     _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
00194   const Real local_coarsening_tolerance =
00195     local_refinement_tolerance * _coarsen_threshold;
00196 
00197   // Prepare another error vector if we need to sum parent errors
00198   ErrorVector error_per_parent;
00199   if (_coarsen_by_parents)
00200   {
00201     Real parent_error_min, parent_error_max;
00202 
00203     create_parent_error_vector(error_per_cell_in,
00204                                error_per_parent,
00205                                parent_error_min,
00206                                parent_error_max);
00207   }
00208 
00209   MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00210   const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00211 
00212   for (; elem_it != elem_end; ++elem_it)
00213   {
00214     Elem* elem = *elem_it;
00215     Elem* parent = elem->parent();
00216     const dof_id_type elem_number    = elem->id();
00217     const ErrorVectorReal elem_error = error_per_cell_in[elem_number];
00218 
00219     if (elem_error > local_refinement_tolerance &&
00220         elem->level() < _max_h_level)
00221       elem->set_refinement_flag(Elem::REFINE);
00222 
00223     if (!_coarsen_by_parents && elem_error <
00224         local_coarsening_tolerance)
00225       elem->set_refinement_flag(Elem::COARSEN);
00226 
00227     if (_coarsen_by_parents && parent)
00228     {
00229       ErrorVectorReal parent_error = error_per_parent[parent->id()];
00230       if (parent_error >= 0.)
00231       {
00232         const Real parent_coarsening_tolerance =
00233           std::sqrt(parent->n_children() *
00234                     local_coarsening_tolerance *
00235                     local_coarsening_tolerance);
00236         if (parent_error < parent_coarsening_tolerance)
00237           elem->set_refinement_flag(Elem::COARSEN);
00238       }
00239     }
00240   }
00241 }

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

References _coarsen_fraction, _max_h_level, _mesh, _refine_fraction, _use_member_parameters, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::COARSEN, libMesh::ErrorVectorReal, libMesh::DofObject::id(), libMesh::invalid_uint, libMesh::Elem::level(), std::max(), libMesh::ErrorVector::mean(), libMesh::Real, libMesh::Elem::REFINE, libMesh::Elem::set_refinement_flag(), and libMesh::ErrorVector::variance().

00595 {
00596   // The function arguments are currently just there for
00597   // backwards_compatibility
00598   if (!_use_member_parameters)
00599     {
00600       // If the user used non-default parameters, lets warn
00601       // that they're deprecated
00602       if (refine_frac != 0.3 ||
00603           coarsen_frac != 0.0 ||
00604           max_l != libMesh::invalid_uint)
00605         libmesh_deprecated();
00606 
00607       _refine_fraction = refine_frac;
00608       _coarsen_fraction = coarsen_frac;
00609       _max_h_level = max_l;
00610     }
00611 
00612   // Get the mean value from the error vector
00613   const Real mean = error_per_cell.mean();
00614 
00615   // Get the standard deviation.  This equals the
00616   // square-root of the variance
00617   const Real stddev = std::sqrt (error_per_cell.variance());
00618 
00619   // Check for valid fractions
00620   libmesh_assert_greater_equal (_refine_fraction, 0);
00621   libmesh_assert_less_equal (_refine_fraction, 1);
00622   libmesh_assert_greater_equal (_coarsen_fraction, 0);
00623   libmesh_assert_less_equal (_coarsen_fraction, 1);
00624 
00625   // The refine and coarsen cutoff
00626   const Real refine_cutoff  =  mean + _refine_fraction  * stddev;
00627   const Real coarsen_cutoff =  std::max(mean - _coarsen_fraction * stddev, 0.);
00628 
00629   // Loop over the elements and flag them for coarsening or
00630   // refinement based on the element error
00631   MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00632   const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00633 
00634   for (; elem_it != elem_end; ++elem_it)
00635     {
00636       Elem* elem             = *elem_it;
00637       const dof_id_type id  = elem->id();
00638 
00639       libmesh_assert_less (id, error_per_cell.size());
00640 
00641       const ErrorVectorReal elem_error = error_per_cell[id];
00642 
00643       // Possibly flag the element for coarsening ...
00644       if (elem_error <= coarsen_cutoff)
00645         elem->set_refinement_flag(Elem::COARSEN);
00646 
00647       // ... or refinement
00648       if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level))
00649         elem->set_refinement_flag(Elem::REFINE);
00650     }
00651 }

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. This method 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 245 of file mesh_refinement_flagging.C.

References _coarsen_by_parents, _coarsen_fraction, _coarsen_threshold, _max_h_level, _mesh, _nelem_target, _refine_fraction, libMesh::Elem::active(), libMesh::MeshBase::active_local_elements_begin(), libMesh::MeshBase::active_local_elements_end(), libMesh::Parallel::Communicator::allgather(), libMesh::Elem::child(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::CommWorld, create_parent_error_vector(), libMesh::Elem::has_children(), libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), libMesh::MeshBase::max_elem_id(), libMesh::MeshBase::mesh_dimension(), std::min(), libMesh::MeshBase::n_active_elem(), libMesh::Elem::n_children(), libMesh::MeshBase::query_elem(), libMesh::Real, libMesh::Elem::REFINE, libMesh::remote_elem, and libMesh::Elem::set_refinement_flag().

00246 {
00247   parallel_only();
00248 
00249   // Check for valid fractions..
00250   // The fraction values must be in [0,1]
00251   libmesh_assert_greater_equal (_refine_fraction, 0);
00252   libmesh_assert_less_equal (_refine_fraction, 1);
00253   libmesh_assert_greater_equal (_coarsen_fraction, 0);
00254   libmesh_assert_less_equal (_coarsen_fraction, 1);
00255 
00256   // This function is currently only coded to work when coarsening by
00257   // parents - it's too hard to guess how many coarsenings will be
00258   // performed otherwise.
00259   libmesh_assert (_coarsen_by_parents);
00260 
00261   // The number of active elements in the mesh - hopefully less than
00262   // 2 billion on 32 bit machines
00263   const dof_id_type n_active_elem  = _mesh.n_active_elem();
00264 
00265   // The maximum number of active elements to flag for coarsening
00266   const dof_id_type max_elem_coarsen =
00267     static_cast<dof_id_type>(_coarsen_fraction * n_active_elem) + 1;
00268 
00269   // The maximum number of elements to flag for refinement
00270   const dof_id_type max_elem_refine  =
00271     static_cast<dof_id_type>(_refine_fraction  * n_active_elem) + 1;
00272 
00273   // Clean up the refinement flags.  These could be left
00274   // over from previous refinement steps.
00275   this->clean_refinement_flags();
00276 
00277   // The target number of elements to add or remove
00278   const std::ptrdiff_t n_elem_new = _nelem_target - n_active_elem;
00279 
00280   // Create an vector with active element errors and ids,
00281   // sorted by highest errors first
00282   const dof_id_type max_elem_id = _mesh.max_elem_id();
00283   std::vector<std::pair<ErrorVectorReal, dof_id_type> > sorted_error;
00284 
00285   sorted_error.reserve (n_active_elem);
00286 
00287   // On a ParallelMesh, we need to communicate to know which remote ids
00288   // correspond to active elements.
00289   {
00290     std::vector<bool> is_active(max_elem_id, false);
00291 
00292     MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00293     const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00294     for (; elem_it != elem_end; ++elem_it)
00295       {
00296         const dof_id_type eid = (*elem_it)->id();
00297         is_active[eid] = true;
00298         libmesh_assert_less (eid, error_per_cell.size());
00299         sorted_error.push_back
00300           (std::make_pair(error_per_cell[eid], eid));
00301       }
00302 
00303     CommWorld.max(is_active);
00304 
00305     CommWorld.allgather(sorted_error);
00306   }
00307 
00308   // Default sort works since pairs are sorted lexicographically
00309   std::sort (sorted_error.begin(), sorted_error.end());
00310   std::reverse (sorted_error.begin(), sorted_error.end());
00311 
00312   // Create a sorted error vector with coarsenable parent elements
00313   // only, sorted by lowest errors first
00314   ErrorVector error_per_parent;
00315   std::vector<std::pair<ErrorVectorReal, dof_id_type> > sorted_parent_error;
00316   Real parent_error_min, parent_error_max;
00317 
00318   create_parent_error_vector(error_per_cell,
00319                              error_per_parent,
00320                              parent_error_min,
00321                              parent_error_max);
00322 
00323   // create_parent_error_vector sets values for non-parents and
00324   // non-coarsenable parents to -1.  Get rid of them.
00325   for (dof_id_type i=0; i != error_per_parent.size(); ++i)
00326     if (error_per_parent[i] != -1)
00327       sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i));
00328 
00329   std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
00330 
00331   // Keep track of how many elements we plan to coarsen & refine
00332   dof_id_type coarsen_count = 0;
00333   dof_id_type refine_count = 0;
00334 
00335   const unsigned int dim = _mesh.mesh_dimension();
00336   unsigned int twotodim = 1;
00337   for (unsigned int i=0; i!=dim; ++i)
00338     twotodim *= 2;
00339 
00340   // First, let's try to get our element count to target_nelem
00341   if (n_elem_new >= 0)
00342   {
00343     // Every element refinement creates at least
00344     // 2^dim-1 new elements
00345     refine_count =
00346       std::min(libmesh_cast_int<dof_id_type>(n_elem_new / (twotodim-1)),
00347                max_elem_refine);
00348   }
00349   else
00350   {
00351     // Every successful element coarsening is likely to destroy
00352     // 2^dim-1 net elements.
00353     coarsen_count =
00354       std::min(libmesh_cast_int<dof_id_type>(-n_elem_new / (twotodim-1)),
00355                max_elem_coarsen);
00356   }
00357 
00358   // Next, let's see if we can trade any refinement for coarsening
00359   while (coarsen_count < max_elem_coarsen &&
00360          refine_count < max_elem_refine &&
00361          coarsen_count < sorted_parent_error.size() &&
00362          refine_count < sorted_error.size() &&
00363          sorted_error[refine_count].first >
00364          sorted_parent_error[coarsen_count].first * _coarsen_threshold)
00365   {
00366     coarsen_count++;
00367     refine_count++;
00368   }
00369 
00370   // On a ParallelMesh, we need to communicate to know which remote ids
00371   // correspond to refinable elements
00372   dof_id_type successful_refine_count = 0;
00373   {
00374     std::vector<bool> is_refinable(max_elem_id, false);
00375 
00376     for (dof_id_type i=0; i != sorted_error.size(); ++i)
00377       {
00378         dof_id_type eid = sorted_error[i].second;
00379         Elem *elem = _mesh.query_elem(eid);
00380         if (elem && elem->level() < _max_h_level)
00381           is_refinable[eid] = true;
00382       }
00383     CommWorld.max(is_refinable);
00384 
00385     if (refine_count > max_elem_refine)
00386       refine_count = max_elem_refine;
00387     for (dof_id_type i=0; i != sorted_error.size(); ++i)
00388       {
00389         if (successful_refine_count >= refine_count)
00390           break;
00391 
00392         dof_id_type eid = sorted_error[i].second;
00393         Elem *elem = _mesh.query_elem(eid);
00394         if (is_refinable[eid])
00395           {
00396             if (elem)
00397               elem->set_refinement_flag(Elem::REFINE);
00398             successful_refine_count++;
00399           }
00400       }
00401   }
00402 
00403   // If we couldn't refine enough elements, don't coarsen too many
00404   // either
00405   if (coarsen_count < (refine_count - successful_refine_count))
00406     coarsen_count = 0;
00407   else
00408     coarsen_count -= (refine_count - successful_refine_count);
00409 
00410   if (coarsen_count > max_elem_coarsen)
00411     coarsen_count = max_elem_coarsen;
00412 
00413   dof_id_type successful_coarsen_count = 0;
00414   if (coarsen_count)
00415     {
00416       for (dof_id_type i=0; i != sorted_parent_error.size(); ++i)
00417         {
00418           if (successful_coarsen_count >= coarsen_count * twotodim)
00419             break;
00420 
00421           dof_id_type parent_id = sorted_parent_error[i].second;
00422           Elem *parent = _mesh.query_elem(parent_id);
00423 
00424           // On a ParallelMesh we skip remote elements
00425           if (!parent)
00426             continue;
00427 
00428           libmesh_assert(parent->has_children());
00429           for (unsigned int c=0; c != parent->n_children(); ++c)
00430             {
00431               Elem *elem = parent->child(c);
00432               if (elem && elem != remote_elem)
00433                 {
00434                   libmesh_assert(elem->active());
00435                   elem->set_refinement_flag(Elem::COARSEN);
00436                   successful_coarsen_count++;
00437                 }
00438             }
00439         }
00440     }
00441 
00442   // Return true if we've done all the AMR/C we can
00443   if (!successful_coarsen_count &&
00444       !successful_refine_count)
00445     return true;
00446   // And false if there may still be more to do.
00447   return false;
00448 }

MeshBase& libMesh::MeshRefinement::get_mesh (  )  [inline]
Returns:
a writeable reference to the MeshBase object associated with this object.

Definition at line 294 of file mesh_refinement.h.

References _mesh.

00294 { return _mesh; }

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

Definition at line 288 of file mesh_refinement.h.

References _mesh.

00288 { return _mesh; }

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

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

Definition at line 1788 of file mesh_refinement.C.

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

Referenced by make_coarsening_compatible(), and make_refinement_compatible().

01791 {
01792 #ifdef LIBMESH_ENABLE_PERIODIC
01793   if (_periodic_boundaries && !_periodic_boundaries->empty())
01794     {
01795       libmesh_assert(point_locator);
01796       return elem->has_topological_neighbor(neighbor, _mesh, *point_locator, _periodic_boundaries);
01797     }
01798 #endif
01799   return elem->has_neighbor(neighbor);
01800 }

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

Definition at line 131 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::build_edge(), libMesh::CommWorld, libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), std::max(), libMesh::Elem::n_edges(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::parent(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), and swap().

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

00132 {
00133   // This function must be run on all processors at once
00134   parallel_only();
00135 
00136   bool flags_changed = false;
00137 
00138 
00139   // Maps holding the maximum element level that touches an edge
00140   std::map<std::pair<unsigned int, unsigned int>, unsigned char>
00141     max_level_at_edge;
00142   std::map<std::pair<unsigned int, unsigned int>, unsigned char>
00143     max_p_level_at_edge;
00144 
00145   // Loop over all the active elements & fill the maps
00146   {
00147     MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00148     const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00149 
00150     for (; elem_it != elem_end; ++elem_it)
00151       {
00152         const Elem* elem = *elem_it;
00153         const unsigned char elem_level =
00154           elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
00155         const unsigned char elem_p_level =
00156           elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);
00157 
00158         // Set the max_level at each edge
00159         for (unsigned int n=0; n<elem->n_edges(); n++)
00160           {
00161             AutoPtr<Elem> edge = elem->build_edge(n);
00162             dof_id_type childnode0 = edge->node(0);
00163             dof_id_type childnode1 = edge->node(1);
00164             if (childnode1 < childnode0)
00165               std::swap(childnode0, childnode1);
00166 
00167             for (const Elem *p = elem; p != NULL; p = p->parent())
00168               {
00169                 AutoPtr<Elem> pedge = p->build_edge(n);
00170                 dof_id_type node0 = pedge->node(0);
00171                 dof_id_type node1 = pedge->node(1);
00172 
00173                 if (node1 < node0)
00174                   std::swap(node0, node1);
00175 
00176                 // If elem does not share this edge with its ancestor
00177                 // p, refinement levels of elements sharing p's edge
00178                 // are not restricted by refinement levels of elem.
00179                 // Furthermore, elem will not share this edge with any
00180                 // of p's ancestors, so we can safely break out of the
00181                 // for loop early.
00182                 if (node0 != childnode0 && node1 != childnode1)
00183                   break;
00184 
00185                 childnode0 = node0;
00186                 childnode1 = node1;
00187 
00188                 std::pair<unsigned int, unsigned int> edge_key =
00189                   std::make_pair(node0, node1);
00190 
00191                 if (max_level_at_edge.find(edge_key) ==
00192                     max_level_at_edge.end())
00193                   {
00194                     max_level_at_edge[edge_key] = elem_level;
00195                     max_p_level_at_edge[edge_key] = elem_p_level;
00196                   }
00197                 else
00198                   {
00199                     max_level_at_edge[edge_key] =
00200                       std::max (max_level_at_edge[edge_key], elem_level);
00201                     max_p_level_at_edge[edge_key] =
00202                       std::max (max_p_level_at_edge[edge_key], elem_p_level);
00203                   }
00204               }
00205           }
00206       }
00207   }
00208 
00209 
00210   // Now loop over the active elements and flag the elements
00211   // who violate the requested level mismatch
00212   {
00213     MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00214     const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00215 
00216     for (; elem_it != elem_end; ++elem_it)
00217       {
00218         Elem* elem = *elem_it;
00219         const unsigned int elem_level = elem->level();
00220         const unsigned int elem_p_level = elem->p_level();
00221 
00222         // Skip the element if it is already fully flagged
00223         if (elem->refinement_flag() == Elem::REFINE &&
00224             elem->p_refinement_flag() == Elem::REFINE)
00225           continue;
00226 
00227         // Loop over the nodes, check for possible mismatch
00228         for (unsigned int n=0; n<elem->n_edges(); n++)
00229           {
00230             AutoPtr<Elem> edge = elem->build_edge(n);
00231             dof_id_type node0 = edge->node(0);
00232             dof_id_type node1 = edge->node(1);
00233             if (node1 < node0)
00234               std::swap(node0, node1);
00235 
00236             std::pair<dof_id_type, dof_id_type> edge_key =
00237               std::make_pair(node0, node1);
00238 
00239             // Flag the element for refinement if it violates
00240             // the requested level mismatch
00241             if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key]
00242                  && elem->refinement_flag() != Elem::REFINE)
00243               {
00244                 elem->set_refinement_flag (Elem::REFINE);
00245                 flags_changed = true;
00246               }
00247             if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
00248                  && elem->p_refinement_flag() != Elem::REFINE)
00249               {
00250                 elem->set_p_refinement_flag (Elem::REFINE);
00251                 flags_changed = true;
00252               }
00253           }
00254       }
00255   }
00256 
00257   // If flags changed on any processor then they changed globally
00258   CommWorld.max(flags_changed);
00259 
00260   return flags_changed;
00261 }

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

This algorithm restricts the maximum level mismatch at any node in the mesh. Calling this with max_mismatch equal to 1 would transform this mesh:

   o---o---o---o---o-------o-------o
   |   |   |   |   |       |       |
   |   |   |   |   |       |       |
   o---o---o---o---o       |       |
   |   |   |   |   |       |       |
   |   |   |   |   |       |       |
   o---o---o---o---o-------o-------o
   |   |   |   |   |       |       |
   |   |   |   |   |       |       |
   o---o---o---o---o       |       |
   |   |   |   |   |       |       |
   |   |   |   |   |       |       |
   o---o---o---o---o-------o-------o
   |       |       |               |
   |       |       |               |
   |       |       |               |
   |       |       |               |
   |       |       |               |
   o-------o-------o               |
   |       |       |               |
   |       |       |               |
   |       |       |               |
   |       |       |               |
   |       |       |               |
   o-------o-------o---------------o
   

into this:

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

by refining the indicated element

Definition at line 39 of file mesh_refinement_smoothing.C.

References _mesh, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::CommWorld, libMesh::Elem::level(), libMesh::Parallel::Communicator::max(), std::max(), libMesh::Elem::n_nodes(), libMesh::MeshBase::n_nodes(), libMesh::Elem::node(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), and libMesh::Elem::set_refinement_flag().

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

00040 {
00041   // This function must be run on all processors at once
00042   parallel_only();
00043 
00044   bool flags_changed = false;
00045 
00046 
00047   // Vector holding the maximum element level that touches a node.
00048   std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0);
00049   std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0);
00050 
00051 
00052   // Loop over all the active elements & fill the vector
00053   {
00054     MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00055     const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00056 
00057     for (; elem_it != elem_end; ++elem_it)
00058       {
00059         const Elem* elem = *elem_it;
00060         const unsigned char elem_level =
00061           elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
00062         const unsigned char elem_p_level =
00063           elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);
00064 
00065         // Set the max_level at each node
00066         for (unsigned int n=0; n<elem->n_nodes(); n++)
00067           {
00068             const dof_id_type node_number = elem->node(n);
00069 
00070             libmesh_assert_less (node_number, max_level_at_node.size());
00071 
00072             max_level_at_node[node_number] =
00073               std::max (max_level_at_node[node_number], elem_level);
00074             max_p_level_at_node[node_number] =
00075               std::max (max_p_level_at_node[node_number], elem_p_level);
00076           }
00077       }
00078   }
00079 
00080 
00081   // Now loop over the active elements and flag the elements
00082   // who violate the requested level mismatch
00083   {
00084     MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
00085     const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
00086 
00087     for (; elem_it != elem_end; ++elem_it)
00088       {
00089         Elem* elem = *elem_it;
00090         const unsigned int elem_level = elem->level();
00091         const unsigned int elem_p_level = elem->p_level();
00092 
00093         // Skip the element if it is already fully flagged
00094         if (elem->refinement_flag() == Elem::REFINE &&
00095             elem->p_refinement_flag() == Elem::REFINE)
00096           continue;
00097 
00098         // Loop over the nodes, check for possible mismatch
00099         for (unsigned int n=0; n<elem->n_nodes(); n++)
00100           {
00101             const dof_id_type node_number = elem->node(n);
00102 
00103             // Flag the element for refinement if it violates
00104             // the requested level mismatch
00105             if ( (elem_level + max_mismatch) < max_level_at_node[node_number]
00106                  && elem->refinement_flag() != Elem::REFINE)
00107               {
00108                 elem->set_refinement_flag (Elem::REFINE);
00109                 flags_changed = true;
00110               }
00111             if ( (elem_p_level + max_mismatch) < max_p_level_at_node[node_number]
00112                  && elem->p_refinement_flag() != Elem::REFINE)
00113               {
00114                 elem->set_p_refinement_flag (Elem::REFINE);
00115                 flags_changed = true;
00116               }
00117           }
00118       }
00119   }
00120 
00121   // If flags changed on any processor then they changed globally
00122   CommWorld.max(flags_changed);
00123 
00124   return flags_changed;
00125 }

bool libMesh::MeshRefinement::make_coarsening_compatible ( const bool  maintain_level_one  )  [private]

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

Definition at line 920 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::ancestor(), libMesh::Elem::child(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::AutoPtr< Tp >::get(), libMesh::Elem::has_children(), has_topological_neighbor(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_serial(), libMesh::Elem::level(), libMesh::MeshBase::level_elements_begin(), libMesh::MeshBase::level_elements_end(), std::max(), libMesh::MeshTools::max_level(), libMesh::Parallel::Communicator::min(), libMesh::Elem::n_children(), libMesh::Elem::n_neighbors(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), libMesh::MeshBase::sub_point_locator(), topological_neighbor(), and libMesh::Parallel::Communicator::verify().

Referenced by coarsen_elements(), and refine_and_coarsen_elements().

00921 {
00922   // This function must be run on all processors at once
00923   parallel_only();
00924 
00925   // We may need a PointLocator for topological_neighbor() tests
00926   // later, which we need to make sure gets constructed on all
00927   // processors at once.
00928   AutoPtr<PointLocatorBase> point_locator;
00929 
00930 #ifdef LIBMESH_ENABLE_PERIODIC
00931   bool has_periodic_boundaries =
00932     _periodic_boundaries && !_periodic_boundaries->empty();
00933   libmesh_assert(CommWorld.verify(has_periodic_boundaries));
00934 
00935   if (has_periodic_boundaries)
00936     point_locator = _mesh.sub_point_locator();
00937 #endif
00938 
00939   START_LOG ("make_coarsening_compatible()", "MeshRefinement");
00940 
00941   bool _maintain_level_one = maintain_level_one;
00942 
00943   // If the user used non-default parameters, let's warn that they're
00944   // deprecated
00945   if (!maintain_level_one)
00946     {
00947       libmesh_deprecated();
00948     }
00949   else
00950     _maintain_level_one = _face_level_mismatch_limit;
00951 
00952 
00953   // Unless we encounter a specific situation level-one
00954   // will be satisfied after executing this loop just once
00955   bool level_one_satisfied = true;
00956 
00957 
00958   // Unless we encounter a specific situation we will be compatible
00959   // with any selected refinement flags
00960   bool compatible_with_refinement = true;
00961 
00962 
00963   // find the maximum h and p levels in the mesh
00964   unsigned int max_level = 0;
00965   unsigned int max_p_level = 0;
00966 
00967   {
00968   // First we look at all the active level-0 elements.  Since it doesn't make
00969   // sense to coarsen them we must un-set their coarsen flags if
00970   // they are set.
00971   MeshBase::element_iterator       el     = _mesh.active_elements_begin();
00972   const MeshBase::element_iterator end_el = _mesh.active_elements_end();
00973 
00974   for (; el != end_el; ++el)
00975     {
00976       Elem *elem = *el;
00977       max_level = std::max(max_level, elem->level());
00978       max_p_level =
00979         std::max(max_p_level,
00980                  static_cast<unsigned int>(elem->p_level()));
00981 
00982       if ((elem->level() == 0) &&
00983           (elem->refinement_flag() == Elem::COARSEN))
00984         elem->set_refinement_flag(Elem::DO_NOTHING);
00985 
00986       if ((elem->p_level() == 0) &&
00987           (elem->p_refinement_flag() == Elem::COARSEN))
00988         elem->set_p_refinement_flag(Elem::DO_NOTHING);
00989     }
00990   }
00991 
00992   // if there are no refined elements on this processor then
00993   // there is no work for us to do
00994   if (max_level == 0 && max_p_level == 0)
00995     {
00996       STOP_LOG ("make_coarsening_compatible()", "MeshRefinement");
00997 
00998       // But we still have to check with other processors
00999       CommWorld.min(compatible_with_refinement);
01000 
01001       return compatible_with_refinement;
01002     }
01003 
01004 
01005 
01006   // Loop over all the active elements.  If an element is marked
01007   // for coarsening we better check its neighbors.  If ANY of these neighbors
01008   // are marked for refinement AND are at the same level then there is a
01009   // conflict.  By convention refinement wins, so we un-mark the element for
01010   // coarsening.  Level-one would be violated in this case so we need to re-run
01011   // the loop.
01012   if (_maintain_level_one)
01013     {
01014 
01015     repeat:
01016       level_one_satisfied = true;
01017 
01018       do
01019         {
01020           level_one_satisfied = true;
01021 
01022           MeshBase::element_iterator       el     = _mesh.active_elements_begin();
01023           const MeshBase::element_iterator end_el = _mesh.active_elements_end();
01024 
01025           for (; el != end_el; ++el)
01026             {
01027               Elem* elem = *el;
01028               bool my_flag_changed = false;
01029 
01030               if (elem->refinement_flag() == Elem::COARSEN) // If the element is active and
01031                 // the coarsen flag is set
01032                 {
01033                   const unsigned int my_level = elem->level();
01034 
01035                   for (unsigned int n=0; n<elem->n_neighbors(); n++)
01036                   {
01037                     const Elem* neighbor =
01038                       topological_neighbor(elem, point_locator.get(), n);
01039 
01040                     if (neighbor != NULL &&      // I have a
01041                         neighbor != remote_elem) // neighbor here
01042                       {
01043                         if (neighbor->active()) // and it is active
01044                           {
01045                             if ((neighbor->level() == my_level) &&
01046                                 (neighbor->refinement_flag() == Elem::REFINE)) // the neighbor is at my level
01047                                                                                // and wants to be refined
01048                               {
01049                                 elem->set_refinement_flag(Elem::DO_NOTHING);
01050                                 my_flag_changed = true;
01051                                 break;
01052                               }
01053                           }
01054                         else // I have a neighbor and it is not active. That means it has children.
01055                           {  // While it _may_ be possible to coarsen us if all the children of
01056                              // that element want to be coarsened, it is impossible to know at this
01057                              // stage.  Forget about it for the moment...  This can be handled in
01058                              // two steps.
01059                             elem->set_refinement_flag(Elem::DO_NOTHING);
01060                             my_flag_changed = true;
01061                             break;
01062                           }
01063                       }
01064                   }
01065                 }
01066               if (elem->p_refinement_flag() == Elem::COARSEN) // If
01067                 // the element is active and the order reduction flag is set
01068                 {
01069                   const unsigned int my_p_level = elem->p_level();
01070 
01071                   for (unsigned int n=0; n<elem->n_neighbors(); n++)
01072                   {
01073                     const Elem* neighbor =
01074                       topological_neighbor(elem, point_locator.get(), n);
01075 
01076                     if (neighbor != NULL &&      // I have a
01077                         neighbor != remote_elem) // neighbor here
01078                       {
01079                         if (neighbor->active()) // and it is active
01080                           {
01081                             if ((neighbor->p_level() > my_p_level &&
01082                                  neighbor->p_refinement_flag() != Elem::COARSEN)
01083                                 || (neighbor->p_level() == my_p_level &&
01084                                  neighbor->p_refinement_flag() == Elem::REFINE))
01085                               {
01086                                 elem->set_p_refinement_flag(Elem::DO_NOTHING);
01087                                 my_flag_changed = true;
01088                                 break;
01089                               }
01090                           }
01091                         else // I have a neighbor and it is not active.
01092                           {  // We need to find which of its children
01093                              // have me as a neighbor, and maintain
01094                              // level one p compatibility with them.
01095                              // Because we currently have level one h
01096                              // compatibility, we don't need to check
01097                              // grandchildren
01098 
01099                              libmesh_assert(neighbor->has_children());
01100                              for (unsigned int c=0; c!=neighbor->n_children(); c++)
01101                                {
01102                                  Elem *subneighbor = neighbor->child(c);
01103                                  if (subneighbor != remote_elem &&
01104                                      subneighbor->active() &&
01105                                      has_topological_neighbor(subneighbor, point_locator.get(), elem))
01106                                    if ((subneighbor->p_level() > my_p_level &&
01107                                        subneighbor->p_refinement_flag() != Elem::COARSEN)
01108                                        || (subneighbor->p_level() == my_p_level &&
01109                                        subneighbor->p_refinement_flag() == Elem::REFINE))
01110                                      {
01111                                        elem->set_p_refinement_flag(Elem::DO_NOTHING);
01112                                        my_flag_changed = true;
01113                                        break;
01114                                      }
01115                                }
01116                              if (my_flag_changed)
01117                                break;
01118                           }
01119                       }
01120                   }
01121                 }
01122 
01123               // If the current element's flag changed, we hadn't
01124               // satisfied the level one rule.
01125               if (my_flag_changed)
01126                 level_one_satisfied = false;
01127 
01128               // Additionally, if it has non-local neighbors, and
01129               // we're not in serial, then we'll eventually have to
01130               // return compatible_with_refinement = false, because
01131               // our change has to propagate to neighboring
01132               // processors.
01133               if (my_flag_changed && !_mesh.is_serial())
01134               for (unsigned int n=0; n != elem->n_neighbors(); ++n)
01135                 {
01136                   Elem* neigh =
01137                     topological_neighbor(elem, point_locator.get(), n);
01138 
01139                   if (!neigh)
01140                     continue;
01141                   if (neigh == remote_elem ||
01142                       neigh->processor_id() !=
01143                       libMesh::processor_id())
01144                     {
01145                       compatible_with_refinement = false;
01146                       break;
01147                     }
01148                   // FIXME - for non-level one meshes we should
01149                   // test all descendants
01150                   if (neigh->has_children())
01151                     for (unsigned int c=0; c != neigh->n_children(); ++c)
01152                       if (neigh->child(c) == remote_elem ||
01153                           neigh->child(c)->processor_id() !=
01154                           libMesh::processor_id())
01155                         {
01156                           compatible_with_refinement = false;
01157                           break;
01158                         }
01159                 }
01160             }
01161         }
01162       while (!level_one_satisfied);
01163 
01164     } // end if (_maintain_level_one)
01165 
01166 
01167   // Next we look at all of the ancestor cells.
01168   // If there is a parent cell with all of its children
01169   // wanting to be unrefined then the element is a candidate
01170   // for unrefinement.  If all the children don't
01171   // all want to be unrefined then ALL of them need to have their
01172   // unrefinement flags cleared.
01173   for (int level=(max_level); level >= 0; level--)
01174     {
01175       MeshBase::element_iterator       el     = _mesh.level_elements_begin(level);
01176       const MeshBase::element_iterator end_el = _mesh.level_elements_end(level);
01177       for (; el != end_el; ++el)
01178         {
01179           Elem *elem = *el;
01180           if (elem->ancestor())
01181             {
01182 
01183               // right now the element hasn't been disqualified
01184               // as a candidate for unrefinement
01185               bool is_a_candidate = true;
01186               bool found_remote_child = false;
01187 
01188               for (unsigned int c=0; c<elem->n_children(); c++)
01189                 {
01190                   Elem *child = elem->child(c);
01191                   if (child == remote_elem)
01192                     found_remote_child = true;
01193                   else if ((child->refinement_flag() != Elem::COARSEN) ||
01194                            !child->active() )
01195                     is_a_candidate = false;
01196                 }
01197 
01198               if (!is_a_candidate && !found_remote_child)
01199                 {
01200                   elem->set_refinement_flag(Elem::INACTIVE);
01201 
01202                   for (unsigned int c=0; c<elem->n_children(); c++)
01203                     {
01204                       Elem *child = elem->child(c);
01205                       if (child == remote_elem)
01206                         continue;
01207                       if (child->refinement_flag() == Elem::COARSEN)
01208                         {
01209                           level_one_satisfied = false;
01210                           child->set_refinement_flag(Elem::DO_NOTHING);
01211                         }
01212                     }
01213                 }
01214             }
01215          }
01216      }
01217 
01218   if (!level_one_satisfied && _maintain_level_one) goto repeat;
01219 
01220 
01221   // If all the children of a parent are set to be coarsened
01222   // then flag the parent so that they can kill thier kids...
01223   MeshBase::element_iterator       all_el     = _mesh.elements_begin();
01224   const MeshBase::element_iterator all_el_end = _mesh.elements_end();
01225   for (; all_el != all_el_end; ++all_el)
01226     {
01227       Elem *elem = *all_el;
01228         if (elem->ancestor())
01229           {
01230 
01231             // Presume all the children are local and flagged for
01232             // coarsening and then look for a contradiction
01233             bool all_children_flagged_for_coarsening = true;
01234             bool found_remote_child = false;
01235 
01236             for (unsigned int c=0; c<elem->n_children(); c++)
01237               {
01238                 Elem *child = elem->child(c);
01239                 if (child == remote_elem)
01240                   found_remote_child = true;
01241                 else if (child->refinement_flag() != Elem::COARSEN)
01242                   all_children_flagged_for_coarsening = false;
01243               }
01244 
01245             if (!found_remote_child &&
01246                 all_children_flagged_for_coarsening)
01247               elem->set_refinement_flag(Elem::COARSEN_INACTIVE);
01248             else if (!found_remote_child)
01249               elem->set_refinement_flag(Elem::INACTIVE);
01250           }
01251     }
01252 
01253   STOP_LOG ("make_coarsening_compatible()", "MeshRefinement");
01254 
01255   // If one processor finds an incompatibility, we're globally
01256   // incompatible
01257   CommWorld.min(compatible_with_refinement);
01258 
01259   return compatible_with_refinement;
01260 }

bool libMesh::MeshRefinement::make_flags_parallel_consistent (  )  [private]

Copy refinement flags on ghost elements from their local processors. Return true if any flags changed.

Definition at line 890 of file mesh_refinement.C.

References _mesh, libMesh::CommWorld, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::Parallel::Communicator::min(), libMesh::Elem::p_refinement_flag(), parallel_consistent, libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), and libMesh::Parallel::sync_dofobject_data_by_id().

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

00891 {
00892   // This function must be run on all processors at once
00893   parallel_only();
00894 
00895   START_LOG ("make_flags_parallel_consistent()", "MeshRefinement");
00896 
00897   SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
00898                             &Elem::set_refinement_flag);
00899   Parallel::sync_dofobject_data_by_id
00900     (_mesh.elements_begin(), _mesh.elements_end(), hsync);
00901 
00902   SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
00903                             &Elem::set_p_refinement_flag);
00904   Parallel::sync_dofobject_data_by_id
00905     (_mesh.elements_begin(), _mesh.elements_end(), psync);
00906 
00907   // If we weren't consistent in both h and p on every processor then
00908   // we weren't globally consistent
00909   bool parallel_consistent = hsync.parallel_consistent &&
00910                              psync.parallel_consistent;
00911   CommWorld.min(parallel_consistent);
00912 
00913   STOP_LOG ("make_flags_parallel_consistent()", "MeshRefinement");
00914 
00915   return parallel_consistent;
00916 }

bool libMesh::MeshRefinement::make_refinement_compatible ( const bool  maintain_level_one  )  [private]

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

Definition at line 1269 of file mesh_refinement.C.

References _face_level_mismatch_limit, _mesh, _periodic_boundaries, libMesh::Elem::active(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::Elem::child(), libMesh::Elem::COARSEN, libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::AutoPtr< Tp >::get(), libMesh::Elem::has_children(), has_topological_neighbor(), libMesh::Elem::INACTIVE, libMesh::Elem::level(), libMesh::Parallel::Communicator::min(), libMesh::Elem::n_children(), libMesh::Elem::n_sides(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::Elem::parent(), libMesh::Elem::REFINE, libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), side, libMesh::MeshBase::sub_point_locator(), topological_neighbor(), and libMesh::Parallel::Communicator::verify().

Referenced by refine_and_coarsen_elements(), and refine_elements().

01270 {
01271   // This function must be run on all processors at once
01272   parallel_only();
01273 
01274   // We may need a PointLocator for topological_neighbor() tests
01275   // later, which we need to make sure gets constructed on all
01276   // processors at once.
01277   AutoPtr<PointLocatorBase> point_locator;
01278 
01279 #ifdef LIBMESH_ENABLE_PERIODIC
01280   bool has_periodic_boundaries =
01281     _periodic_boundaries && !_periodic_boundaries->empty();
01282   libmesh_assert(CommWorld.verify(has_periodic_boundaries));
01283 
01284   if (has_periodic_boundaries)
01285     point_locator = _mesh.sub_point_locator();
01286 #endif
01287 
01288   START_LOG ("make_refinement_compatible()", "MeshRefinement");
01289 
01290   bool _maintain_level_one = maintain_level_one;
01291 
01292   // If the user used non-default parameters, let's warn that they're
01293   // deprecated
01294   if (!maintain_level_one)
01295     {
01296       libmesh_deprecated();
01297     }
01298   else
01299     _maintain_level_one = _face_level_mismatch_limit;
01300 
01301   // Unless we encounter a specific situation level-one
01302   // will be satisfied after executing this loop just once
01303   bool level_one_satisfied = true;
01304 
01305   // Unless we encounter a specific situation we will be compatible
01306   // with any selected coarsening flags
01307   bool compatible_with_coarsening = true;
01308 
01309   // This loop enforces the level-1 rule.  We should only
01310   // execute it if the user indeed wants level-1 satisfied!
01311   if (_maintain_level_one)
01312     {
01313       do
01314         {
01315           level_one_satisfied = true;
01316 
01317           MeshBase::element_iterator       el     = _mesh.active_elements_begin();
01318           const MeshBase::element_iterator end_el = _mesh.active_elements_end();
01319 
01320           for (; el != end_el; ++el)
01321             {
01322             Elem *elem = *el;
01323             if (elem->refinement_flag() == Elem::REFINE)  // If the element is active and the
01324                                                           // h refinement flag is set
01325               {
01326                 const unsigned int my_level = elem->level();
01327 
01328                 for (unsigned int side=0; side != elem->n_sides(); side++)
01329                   {
01330                     Elem* neighbor =
01331                       topological_neighbor(elem, point_locator.get(), side);
01332 
01333                     if (neighbor != NULL        && // I have a
01334                         neighbor != remote_elem && // neighbor here
01335                         neighbor->active()) // and it is active
01336                       {
01337                         // Case 1:  The neighbor is at the same level I am.
01338                         //        1a: The neighbor will be refined       -> NO PROBLEM
01339                         //        1b: The neighbor won't be refined      -> NO PROBLEM
01340                         //        1c: The neighbor wants to be coarsened -> PROBLEM
01341                         if (neighbor->level() == my_level)
01342                           {
01343                             if (neighbor->refinement_flag() == Elem::COARSEN)
01344                               {
01345                                 neighbor->set_refinement_flag(Elem::DO_NOTHING);
01346                                 if (neighbor->parent())
01347                                   neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
01348                                 compatible_with_coarsening = false;
01349                                 level_one_satisfied = false;
01350                               }
01351                           }
01352 
01353 
01354                         // Case 2: The neighbor is one level lower than I am.
01355                         //         The neighbor thus MUST be refined to satisfy
01356                         //         the level-one rule, regardless of whether it
01357                         //         was originally flagged for refinement. If it
01358                         //         wasn't flagged already we need to repeat
01359                         //         this process.
01360                         else if ((neighbor->level()+1) == my_level)
01361                           {
01362                             if (neighbor->refinement_flag() != Elem::REFINE)
01363                               {
01364                                 neighbor->set_refinement_flag(Elem::REFINE);
01365                                 if (neighbor->parent())
01366                                   neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
01367                                 compatible_with_coarsening = false;
01368                                 level_one_satisfied = false;
01369                               }
01370                           }
01371 #ifdef DEBUG
01372 
01373                         // Sanity check. We should never get into a
01374                         // case when our neighbot is more than one
01375                         // level away.
01376                         else if ((neighbor->level()+1) < my_level)
01377                           {
01378                             libmesh_error();
01379                           }
01380 
01381 
01382                         // Note that the only other possibility is that the
01383                         // neighbor is already refined, in which case it isn't
01384                         // active and we should never get here.
01385                         else
01386                           {
01387                             libmesh_error();
01388                           }
01389 #endif
01390                       }
01391                   }
01392               }
01393             if (elem->p_refinement_flag() == Elem::REFINE)  // If the element is active and the
01394                                                             // p refinement flag is set
01395               {
01396                 const unsigned int my_p_level = elem->p_level();
01397 
01398                 for (unsigned int side=0; side != elem->n_sides(); side++)
01399                   {
01400                     Elem* neighbor =
01401                       topological_neighbor(elem, point_locator.get(), side);
01402 
01403                     if (neighbor != NULL &&      // I have a
01404                         neighbor != remote_elem) // neighbor here
01405                       {
01406                         if (neighbor->active()) // and it is active
01407                           {
01408                             if (neighbor->p_level() < my_p_level &&
01409                                 neighbor->p_refinement_flag() != Elem::REFINE)
01410                               {
01411                                 neighbor->set_p_refinement_flag(Elem::REFINE);
01412                                 level_one_satisfied = false;
01413                                 compatible_with_coarsening = false;
01414                               }
01415                             if (neighbor->p_level() == my_p_level &&
01416                                 neighbor->p_refinement_flag() == Elem::COARSEN)
01417                               {
01418                                 neighbor->set_p_refinement_flag(Elem::DO_NOTHING);
01419                                 level_one_satisfied = false;
01420                                 compatible_with_coarsening = false;
01421                               }
01422                           }
01423                         else // I have an inactive neighbor
01424                           {
01425                             libmesh_assert(neighbor->has_children());
01426                             for (unsigned int c=0; c!=neighbor->n_children(); c++)
01427                               {
01428                                 Elem *subneighbor = neighbor->child(c);
01429                                 if (subneighbor == remote_elem)
01430                                   continue;
01431                                 if (subneighbor->active() &&
01432                                     has_topological_neighbor(subneighbor, point_locator.get(), elem))
01433                                   {
01434                                     if (subneighbor->p_level() < my_p_level &&
01435                                         subneighbor->p_refinement_flag() != Elem::REFINE)
01436                                       {
01437                                         // We should already be level one
01438                                         // compatible
01439                                         libmesh_assert_greater (subneighbor->p_level() + 2u,
01440                                                                my_p_level);
01441                                         subneighbor->set_p_refinement_flag(Elem::REFINE);
01442                                         level_one_satisfied = false;
01443                                         compatible_with_coarsening = false;
01444                                       }
01445                                     if (subneighbor->p_level() == my_p_level &&
01446                                         subneighbor->p_refinement_flag() == Elem::COARSEN)
01447                                       {
01448                                         subneighbor->set_p_refinement_flag(Elem::DO_NOTHING);
01449                                         level_one_satisfied = false;
01450                                         compatible_with_coarsening = false;
01451                                       }
01452                                   }
01453                               }
01454                           }
01455                       }
01456                   }
01457               }
01458             }
01459         }
01460 
01461       while (!level_one_satisfied);
01462     } // end if (_maintain_level_one)
01463 
01464   // If we're not compatible on one processor, we're globally not
01465   // compatible
01466   CommWorld.min(compatible_with_coarsening);
01467 
01468   STOP_LOG ("make_refinement_compatible()", "MeshRefinement");
01469 
01470   return compatible_with_coarsening;
01471 }

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

References _max_h_level, and _use_member_parameters.

00675 {
00676   _use_member_parameters = true;
00677   return _max_h_level;
00678 }

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

References _nelem_target, and _use_member_parameters.

00687 {
00688   _use_member_parameters = true;
00689   return _nelem_target;
00690 }

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

References _node_level_mismatch_limit.

00709 {
00710   return _node_level_mismatch_limit;
00711 }

MeshRefinement& libMesh::MeshRefinement::operator= ( const MeshRefinement  )  [private]
bool libMesh::MeshRefinement::refine_and_coarsen_elements ( const bool  maintain_level_one = true  ) 

Refines and coarsens user-requested elements. Will also refine/coarsen additional elements to satisy level-one rule. 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.

The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.

Definition at line 441 of file mesh_refinement.C.

References _coarsen_elements(), _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, _refine_elements(), libMesh::Elem::active(), libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), eliminate_unrefined_patches(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_REFINED, libMesh::MeshBase::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(), libMesh::Parallel::Communicator::max(), libMesh::Parallel::Communicator::min(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), test_level_one(), and test_unflagged().

00442 {
00443   // This function must be run on all processors at once
00444   parallel_only();
00445 
00446   bool _maintain_level_one = maintain_level_one;
00447 
00448   // If the user used non-default parameters, let's warn that they're
00449   // deprecated
00450   if (!maintain_level_one)
00451     {
00452       libmesh_deprecated();
00453     }
00454   else
00455     _maintain_level_one = _face_level_mismatch_limit;
00456 
00457   // We can't yet turn a non-level-one mesh into a level-one mesh
00458   if (_maintain_level_one)
00459     libmesh_assert(test_level_one(true));
00460 
00461   // Possibly clean up the refinement flags from
00462   // a previous step
00463   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00464   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00465 
00466   for ( ; elem_it != elem_end; ++elem_it)
00467     {
00468       // Pointer to the element
00469       Elem *elem = *elem_it;
00470 
00471       // Set refinement flag to INACTIVE if the
00472       // element isn't active
00473       if ( !elem->active())
00474         {
00475           elem->set_refinement_flag(Elem::INACTIVE);
00476           elem->set_p_refinement_flag(Elem::INACTIVE);
00477         }
00478 
00479       // This might be left over from the last step
00480       if (elem->refinement_flag() == Elem::JUST_REFINED)
00481         elem->set_refinement_flag(Elem::DO_NOTHING);
00482     }
00483 
00484   // Parallel consistency has to come first, or coarsening
00485   // along processor boundaries might occasionally be falsely
00486   // prevented
00487   if (!_mesh.is_serial())
00488     this->make_flags_parallel_consistent();
00489 
00490   // Repeat until flag changes match on every processor
00491   do
00492     {
00493       // Repeat until coarsening & refinement flags jive
00494       bool satisfied = false;
00495       do
00496         {
00497           const bool coarsening_satisfied =
00498             this->make_coarsening_compatible(maintain_level_one);
00499 
00500           const bool refinement_satisfied =
00501             this->make_refinement_compatible(maintain_level_one);
00502 
00503           bool smoothing_satisfied =
00504             !this->eliminate_unrefined_patches();
00505 
00506           if (_edge_level_mismatch_limit)
00507             smoothing_satisfied = smoothing_satisfied &&
00508               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00509 
00510           if (_node_level_mismatch_limit)
00511             smoothing_satisfied = smoothing_satisfied &&
00512               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00513 
00514           satisfied = (coarsening_satisfied &&
00515                        refinement_satisfied &&
00516                        smoothing_satisfied);
00517 #ifdef DEBUG
00518           bool max_satisfied = satisfied,
00519                min_satisfied = satisfied;
00520           CommWorld.max(max_satisfied);
00521           CommWorld.min(min_satisfied);
00522           libmesh_assert_equal_to (satisfied, max_satisfied);
00523           libmesh_assert_equal_to (satisfied, min_satisfied);
00524 #endif
00525         }
00526       while (!satisfied);
00527     }
00528   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00529 
00530   // First coarsen the flagged elements.
00531   const bool coarsening_changed_mesh =
00532     this->_coarsen_elements ();
00533 
00534 // FIXME: test_level_one now tests consistency across periodic
00535 // boundaries, which requires a point_locator, which just got
00536 // invalidated by _coarsen_elements() and hasn't yet been cleared by
00537 // prepare_for_use().
00538 
00539 //  if (_maintain_level_one)
00540 //    libmesh_assert(test_level_one(true));
00541 //  libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00542 //  libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00543 
00544 // FIXME: This won't pass unless we add a redundant find_neighbors()
00545 // call or replace find_neighbors() with on-the-fly neighbor updating
00546 // libmesh_assert(!this->eliminate_unrefined_patches());
00547 
00548   // We can't contract the mesh ourselves anymore - a System might
00549   // need to restrict old coefficient vectors first
00550   // _mesh.contract();
00551 
00552   // Now refine the flagged elements.  This will
00553   // take up some space, maybe more than what was freed.
00554   const bool refining_changed_mesh =
00555     this->_refine_elements();
00556 
00557   // Finally, the new mesh needs to be prepared for use
00558   if (coarsening_changed_mesh || refining_changed_mesh)
00559     {
00560 #ifdef DEBUG
00561       _mesh.libmesh_assert_valid_parallel_ids();
00562 #endif
00563 
00564       _mesh.prepare_for_use (/*skip_renumber =*/false);
00565 
00566       if (_maintain_level_one)
00567         libmesh_assert(test_level_one(true));
00568       libmesh_assert(test_unflagged(true));
00569       libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00570       libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00571 // FIXME: This won't pass unless we add a redundant find_neighbors()
00572 // call or replace find_neighbors() with on-the-fly neighbor updating
00573 // libmesh_assert(!this->eliminate_unrefined_patches());
00574 
00575       return true;
00576     }
00577   else
00578     {
00579       if (_maintain_level_one)
00580         libmesh_assert(test_level_one(true));
00581       libmesh_assert(test_unflagged(true));
00582       libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00583       libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00584     }
00585 
00586   // Otherwise there was no change in the mesh,
00587   // let the user know.  Also, there is no need
00588   // to prepare the mesh for use since it did not change.
00589   return false;
00590 
00591 }

bool libMesh::MeshRefinement::refine_elements ( const bool  maintain_level_one = true  ) 

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. Consequently, this function returns true if the mesh actually changed (hence data needs to be projected) and false otherwise.

The argument maintain_level_one is now deprecated; use the option face_level_mismatch_limit() instead.

Definition at line 712 of file mesh_refinement.C.

References _edge_level_mismatch_limit, _face_level_mismatch_limit, _mesh, _node_level_mismatch_limit, _refine_elements(), libMesh::Elem::active(), libMesh::CommWorld, libMesh::Elem::DO_NOTHING, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), eliminate_unrefined_patches(), libMesh::Elem::INACTIVE, libMesh::MeshBase::is_serial(), libMesh::Elem::JUST_REFINED, limit_level_mismatch_at_edge(), limit_level_mismatch_at_node(), make_flags_parallel_consistent(), make_refinement_compatible(), libMesh::Parallel::Communicator::max(), libMesh::Parallel::Communicator::min(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::refinement_flag(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), and test_level_one().

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

00713 {
00714   // This function must be run on all processors at once
00715   parallel_only();
00716 
00717   bool _maintain_level_one = maintain_level_one;
00718 
00719   // If the user used non-default parameters, let's warn that they're
00720   // deprecated
00721   if (!maintain_level_one)
00722     {
00723       libmesh_deprecated();
00724     }
00725   else
00726     _maintain_level_one = _face_level_mismatch_limit;
00727 
00728   if (_maintain_level_one)
00729     libmesh_assert(test_level_one(true));
00730 
00731   // Possibly clean up the refinement flags from
00732   // a previous step
00733   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00734   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00735 
00736   for ( ; elem_it != elem_end; ++elem_it)
00737     {
00738       // Pointer to the element
00739       Elem *elem = *elem_it;
00740 
00741       // Set refinement flag to INACTIVE if the
00742       // element isn't active
00743       if ( !elem->active())
00744         {
00745           elem->set_refinement_flag(Elem::INACTIVE);
00746           elem->set_p_refinement_flag(Elem::INACTIVE);
00747         }
00748 
00749       // This might be left over from the last step
00750       if (elem->refinement_flag() == Elem::JUST_REFINED)
00751         elem->set_refinement_flag(Elem::DO_NOTHING);
00752     }
00753 
00754 
00755 
00756   // Parallel consistency has to come first, or coarsening
00757   // along processor boundaries might occasionally be falsely
00758   // prevented
00759   if (!_mesh.is_serial())
00760     this->make_flags_parallel_consistent();
00761 
00762   // Repeat until flag changes match on every processor
00763   do
00764     {
00765       // Repeat until coarsening & refinement flags jive
00766       bool satisfied = false;
00767       do
00768         {
00769           const bool refinement_satisfied =
00770             this->make_refinement_compatible(maintain_level_one);
00771 
00772           bool smoothing_satisfied =
00773             !this->eliminate_unrefined_patches();// &&
00774 
00775           if (_edge_level_mismatch_limit)
00776             smoothing_satisfied = smoothing_satisfied &&
00777               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00778 
00779           if (_node_level_mismatch_limit)
00780             smoothing_satisfied = smoothing_satisfied &&
00781               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00782 
00783           satisfied = (refinement_satisfied &&
00784                        smoothing_satisfied);
00785 #ifdef DEBUG
00786           bool max_satisfied = satisfied,
00787                min_satisfied = satisfied;
00788           CommWorld.max(max_satisfied);
00789           CommWorld.min(min_satisfied);
00790           libmesh_assert_equal_to (satisfied, max_satisfied);
00791           libmesh_assert_equal_to (satisfied, min_satisfied);
00792 #endif
00793         }
00794       while (!satisfied);
00795     }
00796   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00797 
00798   // Now refine the flagged elements.  This will
00799   // take up some space, maybe more than what was freed.
00800   const bool mesh_changed =
00801     this->_refine_elements();
00802 
00803   if (_maintain_level_one)
00804     libmesh_assert(test_level_one(true));
00805   libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00806 // FIXME: This won't pass unless we add a redundant find_neighbors()
00807 // call or replace find_neighbors() with on-the-fly neighbor updating
00808 // libmesh_assert(!this->eliminate_unrefined_patches());
00809 
00810   // Finally, the new mesh needs to be prepared for use
00811   if (mesh_changed)
00812     _mesh.prepare_for_use (/*skip_renumber =*/false);
00813 
00814   return mesh_changed;
00815 }

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

References _refine_fraction, and _use_member_parameters.

00663 {
00664   _use_member_parameters = true;
00665   return _refine_fraction;
00666 }

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

Definition at line 77 of file mesh_refinement.C.

References _periodic_boundaries.

00078 {
00079   _periodic_boundaries = pb_ptr;
00080 }

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

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

00656 {
00657   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00658   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00659 
00660   for ( ; elem_it != elem_end; ++elem_it)
00661     {
00662       if ((*elem_it)->active())
00663         {
00664           (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00665           (*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
00666         }
00667       else
00668         {
00669           (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00670           (*elem_it)->set_refinement_flag(Elem::INACTIVE);
00671         }
00672     }
00673 }

bool libMesh::MeshRefinement::test_level_one ( bool  libmesh_assert_yes = false  ) 

Returns true if and only if the mesh is level one smooth Returns false otherwise Aborts the program if libmesh_assert_yes is true and the mesh is not level one smooth

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

bool libMesh::MeshRefinement::test_unflagged ( bool  libmesh_assert_yes = false  ) 

Returns true if and only if the mesh has no elements flagged to be coarsened or refined Returns false otherwise Aborts the program if libmesh_assert_yes is true and the mesh has flagged elements

Referenced by refine_and_coarsen_elements().

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

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

Definition at line 1772 of file mesh_refinement.C.

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

Referenced by make_coarsening_compatible(), and make_refinement_compatible().

01775 {
01776 #ifdef LIBMESH_ENABLE_PERIODIC
01777   if (_periodic_boundaries && !_periodic_boundaries->empty())
01778     {
01779       libmesh_assert(point_locator);
01780       return elem->topological_neighbor(side, _mesh, *point_locator, _periodic_boundaries);
01781     }
01782 #endif
01783   return elem->neighbor(side);
01784 }

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

Attempts to uniformly coarsen the mesh n times.

Definition at line 1741 of file mesh_refinement.C.

References _coarsen_elements(), _mesh, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), clean_refinement_flags(), libMesh::Elem::COARSEN, libMesh::Elem::COARSEN_INACTIVE, and libMesh::MeshBase::prepare_for_use().

Referenced by libMesh::AdjointRefinementEstimator::estimate_error().

01742 {
01743   // Coarsen n times
01744   for (unsigned int rstep=0; rstep<n; rstep++)
01745     {
01746       // Clean up the refinement flags
01747       this->clean_refinement_flags();
01748 
01749       // Flag all the active elements for coarsening
01750       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01751       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01752 
01753       for ( ; elem_it != elem_end; ++elem_it)
01754         {
01755           (*elem_it)->set_refinement_flag(Elem::COARSEN);
01756           if ((*elem_it)->parent())
01757             (*elem_it)->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
01758         }
01759 
01760       // Coarsen all the elements we just flagged.
01761       this->_coarsen_elements();
01762     }
01763 
01764 
01765   // Finally, the new mesh probably needs to be prepared for use
01766   if (n > 0)
01767     _mesh.prepare_for_use (/*skip_renumber =*/false);
01768 }

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

Attempts to uniformly p coarsen the mesh n times.

Definition at line 1691 of file mesh_refinement.C.

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

Referenced by libMesh::AdjointRefinementEstimator::estimate_error().

01692 {
01693   // Coarsen p times
01694   for (unsigned int rstep=0; rstep<n; rstep++)
01695     {
01696       // P coarsen all the active elements
01697       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01698       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01699 
01700       for ( ; elem_it != elem_end; ++elem_it)
01701         {
01702           if ((*elem_it)->p_level() > 0)
01703             {
01704               (*elem_it)->set_p_level((*elem_it)->p_level()-1);
01705               (*elem_it)->set_p_refinement_flag(Elem::JUST_COARSENED);
01706             }
01707         }
01708     }
01709 }

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

Uniformly p refines the mesh n times.

Definition at line 1672 of file mesh_refinement.C.

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

Referenced by libMesh::AdjointRefinementEstimator::estimate_error().

01673 {
01674   // Refine n times
01675   for (unsigned int rstep=0; rstep<n; rstep++)
01676     {
01677       // P refine all the active elements
01678       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01679       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01680 
01681       for ( ; elem_it != elem_end; ++elem_it)
01682         {
01683           (*elem_it)->set_p_level((*elem_it)->p_level()+1);
01684           (*elem_it)->set_p_refinement_flag(Elem::JUST_REFINED);
01685         }
01686     }
01687 }

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

Uniformly refines the mesh n times.

Definition at line 1713 of file mesh_refinement.C.

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

Referenced by libMesh::AdjointRefinementEstimator::estimate_error().

01714 {
01715   // Refine n times
01716   // FIXME - this won't work if n>1 and the mesh
01717   // has already been attached to an equation system
01718   for (unsigned int rstep=0; rstep<n; rstep++)
01719     {
01720       // Clean up the refinement flags
01721       this->clean_refinement_flags();
01722 
01723       // Flag all the active elements for refinement.
01724       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01725       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01726 
01727       for ( ; elem_it != elem_end; ++elem_it)
01728         (*elem_it)->set_refinement_flag(Elem::REFINE);
01729 
01730       // Refine all the elements we just flagged.
01731       this->_refine_elements();
01732     }
01733 
01734   // Finally, the new mesh probably needs to be prepared for use
01735   if (n > 0)
01736     _mesh.prepare_for_use (/*skip_renumber =*/false);
01737 }

void libMesh::MeshRefinement::update_nodes_map (  )  [private]

Updates the _new_nodes_map

Definition at line 295 of file mesh_refinement.C.

References _mesh, _new_nodes_map, and libMesh::LocationMap< T >::init().

Referenced by _coarsen_elements(), and _refine_elements().

00296 {
00297   this->_new_nodes_map.init(_mesh);
00298 }


Member Data Documentation

Data structure that holds the new nodes information.

Definition at line 611 of file mesh_refinement.h.

Referenced by _coarsen_elements(), _refine_elements(), add_point(), clear(), and update_nodes_map().

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 623 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:

Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:29 UTC

Hosted By:
SourceForge.net Logo