$extrastylesheet
mesh_refinement_flagging.C
Go to the documentation of this file.
00001 
00002 // The libMesh Finite Element Library.
00003 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00004 
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 
00020 
00021 // Local includes
00022 #include "libmesh/libmesh_config.h"
00023 
00024 // only compile these functions if the user requests AMR support
00025 #ifdef LIBMESH_ENABLE_AMR
00026 
00027 // C++ includes
00028 #include <algorithm> // for std::sort
00029 
00030 // Local includes
00031 #include "libmesh/elem.h"
00032 #include "libmesh/error_vector.h"
00033 #include "libmesh/mesh_refinement.h"
00034 #include "libmesh/mesh_base.h"
00035 #include "libmesh/parallel.h"
00036 #include "libmesh/remote_elem.h"
00037 
00038 namespace libMesh
00039 {
00040 
00041 
00042 
00043 //-----------------------------------------------------------------
00044 // Mesh refinement methods
00045 void MeshRefinement::flag_elements_by_error_fraction (const ErrorVector& error_per_cell,
00046                                                       const Real refine_frac,
00047                                                       const Real coarsen_frac,
00048                                                       const unsigned int max_l)
00049 {
00050   parallel_object_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   this->comm().max(error_max);
00113   this->comm().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 }
00175 
00176 
00177 
00178 void MeshRefinement::flag_elements_by_error_tolerance (const ErrorVector& error_per_cell_in)
00179 {
00180   parallel_object_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 }
00242 
00243 
00244 
00245 bool MeshRefinement::flag_elements_by_nelem_target (const ErrorVector& error_per_cell)
00246 {
00247   parallel_object_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     this->comm().max(is_active);
00304 
00305     this->comm().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(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(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     this->comm().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 }
00449 
00450 
00451 
00452 void MeshRefinement::flag_elements_by_elem_fraction (const ErrorVector& error_per_cell,
00453                                                      const Real refine_frac,
00454                                                      const Real coarsen_frac,
00455                                                      const unsigned int max_l)
00456 {
00457   parallel_object_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   this->comm().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 }
00588 
00589 
00590 
00591 void MeshRefinement::flag_elements_by_mean_stddev (const ErrorVector& error_per_cell,
00592                                                    const Real refine_frac,
00593                                                    const Real coarsen_frac,
00594                                                    const unsigned int max_l)
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 }
00652 
00653 
00654 
00655 void MeshRefinement::flag_elements_by (ElementFlagging &element_flagging)
00656 {
00657   element_flagging.flag_elements();
00658 }
00659 
00660 
00661 
00662 void MeshRefinement::switch_h_to_p_refinement ()
00663 {
00664   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00665   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00666 
00667   for ( ; elem_it != elem_end; ++elem_it)
00668     {
00669       if ((*elem_it)->active())
00670         {
00671           (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00672           (*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
00673         }
00674       else
00675         {
00676           (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00677           (*elem_it)->set_refinement_flag(Elem::INACTIVE);
00678         }
00679     }
00680 }
00681 
00682 
00683 
00684 void MeshRefinement::add_p_to_h_refinement ()
00685 {
00686   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00687   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00688 
00689   for ( ; elem_it != elem_end; ++elem_it)
00690     (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag());
00691 }
00692 
00693 
00694 
00695 void MeshRefinement::clean_refinement_flags ()
00696 {
00697   // Possibly clean up the refinement flags from
00698   // a previous step
00699   //   elem_iterator       elem_it (_mesh.elements_begin());
00700   //   const elem_iterator elem_end(_mesh.elements_end());
00701 
00702   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00703   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00704 
00705   for ( ; elem_it != elem_end; ++elem_it)
00706     {
00707       if ((*elem_it)->active())
00708         {
00709           (*elem_it)->set_refinement_flag(Elem::DO_NOTHING);
00710           (*elem_it)->set_p_refinement_flag(Elem::DO_NOTHING);
00711         }
00712       else
00713         {
00714           (*elem_it)->set_refinement_flag(Elem::INACTIVE);
00715           (*elem_it)->set_p_refinement_flag(Elem::INACTIVE);
00716         }
00717     }
00718 }
00719 
00720 } // namespace libMesh
00721 
00722 #endif