$extrastylesheet
mesh_refinement.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 // C++ includes
00020 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00021 #include <cmath> // for isnan(), when it's defined
00022 #include <limits>
00023 
00024 // Local includes
00025 #include "libmesh/libmesh_config.h"
00026 
00027 // only compile these functions if the user requests AMR support
00028 #ifdef LIBMESH_ENABLE_AMR
00029 
00030 #include "libmesh/boundary_info.h"
00031 #include "libmesh/error_vector.h"
00032 #include "libmesh/libmesh_logging.h"
00033 #include "libmesh/mesh_base.h"
00034 #include "libmesh/mesh_communication.h"
00035 #include "libmesh/mesh_refinement.h"
00036 #include "libmesh/parallel.h"
00037 #include "libmesh/parallel_ghost_sync.h"
00038 #include "libmesh/remote_elem.h"
00039 
00040 #ifdef DEBUG
00041 // Some extra validation for ParallelMesh
00042 #include "libmesh/mesh_tools.h"
00043 #include "libmesh/parallel_mesh.h"
00044 #endif // DEBUG
00045 
00046 #ifdef LIBMESH_ENABLE_PERIODIC
00047 #include "libmesh/periodic_boundaries.h"
00048 #endif
00049 
00050 namespace libMesh
00051 {
00052 
00053 //-----------------------------------------------------------------
00054 // Mesh refinement methods
00055 MeshRefinement::MeshRefinement (MeshBase& m) :
00056   ParallelObject(m),
00057   _mesh(m),
00058   _use_member_parameters(false),
00059   _coarsen_by_parents(false),
00060   _refine_fraction(0.3),
00061   _coarsen_fraction(0.0),
00062   _max_h_level(libMesh::invalid_uint),
00063   _coarsen_threshold(10),
00064   _nelem_target(0),
00065   _absolute_global_tolerance(0.0),
00066   _face_level_mismatch_limit(1),
00067   _edge_level_mismatch_limit(0),
00068   _node_level_mismatch_limit(0),
00069   _enforce_mismatch_limit_prior_to_refinement(false)
00070 #ifdef LIBMESH_ENABLE_PERIODIC
00071   , _periodic_boundaries(NULL)
00072 #endif
00073 {
00074 }
00075 
00076 
00077 
00078 #ifdef LIBMESH_ENABLE_PERIODIC
00079 void MeshRefinement::set_periodic_boundaries_ptr(PeriodicBoundaries * pb_ptr)
00080 {
00081   _periodic_boundaries = pb_ptr;
00082 }
00083 #endif
00084 
00085 
00086 
00087 MeshRefinement::~MeshRefinement ()
00088 {
00089   this->clear();
00090 }
00091 
00092 
00093 
00094 void MeshRefinement::clear ()
00095 {
00096   _new_nodes_map.clear();
00097 }
00098 
00099 
00100 
00101 Node* MeshRefinement::add_point (const Point& p,
00102                                  const processor_id_type proc_id,
00103                                  const Real tol)
00104 {
00105   START_LOG("add_point()", "MeshRefinement");
00106 
00107   // Return the node if it already exists
00108   Node *node = _new_nodes_map.find(p, tol);
00109   if (node)
00110     {
00111       STOP_LOG("add_point()", "MeshRefinement");
00112       return node;
00113     }
00114 
00115   // Add the node, with a default id and the requested
00116   // processor_id
00117   node = _mesh.add_point (p, DofObject::invalid_id, proc_id);
00118 
00119   libmesh_assert(node);
00120 
00121   // Add the node to the map.
00122   _new_nodes_map.insert(*node);
00123 
00124   // Return the address of the new node
00125   STOP_LOG("add_point()", "MeshRefinement");
00126   return node;
00127 }
00128 
00129 
00130 
00131 Elem* MeshRefinement::add_elem (Elem* elem)
00132 {
00133   libmesh_assert(elem);
00134 
00135 
00136   //   // If the unused_elements has any iterators from
00137   //   // old elements, take the first one
00138   //   if (!_unused_elements.empty())
00139   //     {
00140   //       std::vector<Elem*>::iterator it = _unused_elements.front();
00141 
00142   //       *it = elem;
00143 
00144   //       _unused_elements.pop_front();
00145   //     }
00146 
00147   //   // Otherwise, use the conventional add method
00148   //   else
00149   //     {
00150   //       _mesh.add_elem (elem);
00151   //     }
00152 
00153   // The _unused_elements optimization has been turned off.
00154   _mesh.add_elem (elem);
00155 
00156   return elem;
00157 }
00158 
00159 
00160 
00161 void MeshRefinement::create_parent_error_vector
00162 (const ErrorVector& error_per_cell,
00163  ErrorVector& error_per_parent,
00164  Real& parent_error_min,
00165  Real& parent_error_max)
00166 {
00167   // This function must be run on all processors at once
00168   parallel_object_only();
00169 
00170   // Make sure the input error vector is valid
00171 #ifdef DEBUG
00172   for (std::size_t i=0; i != error_per_cell.size(); ++i)
00173     {
00174       libmesh_assert_greater_equal (error_per_cell[i], 0);
00175       // isnan() isn't standard C++ yet
00176 #ifdef isnan
00177       libmesh_assert(!isnan(error_per_cell[i]));
00178 #endif
00179     }
00180 
00181   // Use a reference to std::vector to avoid confusing
00182   // this->comm().verify
00183   std::vector<ErrorVectorReal> &epc = error_per_parent;
00184   libmesh_assert(this->comm().verify(epc));
00185 #endif // #ifdef DEBUG
00186 
00187   // error values on uncoarsenable elements will be left at -1
00188   error_per_parent.clear();
00189   error_per_parent.resize(error_per_cell.size(), 0.0);
00190 
00191   {
00192     // Find which elements are uncoarsenable
00193     MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00194     const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00195     for (; elem_it != elem_end; ++elem_it)
00196       {
00197         Elem* elem   = *elem_it;
00198         Elem* parent = elem->parent();
00199 
00200         // Active elements are uncoarsenable
00201         error_per_parent[elem->id()] = -1.0;
00202 
00203         // Grandparents and up are uncoarsenable
00204         while (parent)
00205           {
00206             parent = parent->parent();
00207             if (parent)
00208               {
00209                 const dof_id_type parentid  = parent->id();
00210                 libmesh_assert_less (parentid, error_per_parent.size());
00211                 error_per_parent[parentid] = -1.0;
00212               }
00213           }
00214       }
00215 
00216     // Sync between processors.
00217     // Use a reference to std::vector to avoid confusing
00218     // this->comm().min
00219     std::vector<ErrorVectorReal> &epp = error_per_parent;
00220     this->comm().min(epp);
00221   }
00222 
00223   // The parent's error is defined as the square root of the
00224   // sum of the children's errors squared, so errors that are
00225   // Hilbert norms remain Hilbert norms.
00226   //
00227   // Because the children may be on different processors, we
00228   // calculate local contributions to the parents' errors squared
00229   // first, then sum across processors and take the square roots
00230   // second.
00231   {
00232     MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00233     const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00234 
00235     for (; elem_it != elem_end; ++elem_it)
00236       {
00237         Elem* elem   = *elem_it;
00238         Elem* parent = elem->parent();
00239 
00240         // Calculate each contribution to parent cells
00241         if (parent)
00242           {
00243             const dof_id_type parentid  = parent->id();
00244             libmesh_assert_less (parentid, error_per_parent.size());
00245 
00246             // If the parent has grandchildren we won't be able to
00247             // coarsen it, so forget it.  Otherwise, add this child's
00248             // contribution to the sum of the squared child errors
00249             if (error_per_parent[parentid] != -1.0)
00250               error_per_parent[parentid] += (error_per_cell[elem->id()] *
00251                                              error_per_cell[elem->id()]);
00252           }
00253       }
00254   }
00255 
00256   // Sum the vector across all processors
00257   this->comm().sum(static_cast<std::vector<ErrorVectorReal>&>(error_per_parent));
00258 
00259   // Calculate the min and max as we loop
00260   parent_error_min = std::numeric_limits<double>::max();
00261   parent_error_max = 0.;
00262 
00263   for (std::size_t i = 0; i != error_per_parent.size(); ++i)
00264     {
00265       // If this element isn't a coarsenable parent with error, we
00266       // have nothing to do.  Just flag it as -1 and move on
00267       // Note that this->comm().sum might have left uncoarsenable
00268       // elements with error_per_parent=-n_proc, so reset it to
00269       // error_per_parent=-1
00270       if (error_per_parent[i] < 0.)
00271         {
00272           error_per_parent[i] = -1.;
00273           continue;
00274         }
00275 
00276       // The error estimator might have already given us an
00277       // estimate on the coarsenable parent elements; if so then
00278       // we want to retain that estimate
00279       if (error_per_cell[i])
00280         {
00281           error_per_parent[i] = error_per_cell[i];
00282           continue;
00283         }
00284       // if not, then e_parent = sqrt(sum(e_child^2))
00285       else
00286         error_per_parent[i] = std::sqrt(error_per_parent[i]);
00287 
00288       parent_error_min = std::min (parent_error_min,
00289                                    error_per_parent[i]);
00290       parent_error_max = std::max (parent_error_max,
00291                                    error_per_parent[i]);
00292     }
00293 }
00294 
00295 
00296 
00297 void MeshRefinement::update_nodes_map ()
00298 {
00299   this->_new_nodes_map.init(_mesh);
00300 }
00301 
00302 
00303 
00304 bool MeshRefinement::test_level_one (bool libmesh_dbg_var(libmesh_assert_pass))
00305 {
00306   // This function must be run on all processors at once
00307   parallel_object_only();
00308 
00309   // We may need a PointLocator for topological_neighbor() tests
00310   // later, which we need to make sure gets constructed on all
00311   // processors at once.
00312   UniquePtr<PointLocatorBase> point_locator;
00313 
00314 #ifdef LIBMESH_ENABLE_PERIODIC
00315   bool has_periodic_boundaries =
00316     _periodic_boundaries && !_periodic_boundaries->empty();
00317   libmesh_assert(this->comm().verify(has_periodic_boundaries));
00318 
00319   if (has_periodic_boundaries)
00320     point_locator = _mesh.sub_point_locator();
00321 #endif
00322 
00323   MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00324   const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00325 
00326   bool failure = false;
00327 
00328 #ifndef NDEBUG
00329   Elem *failed_elem = NULL;
00330   Elem *failed_neighbor = NULL;
00331 #endif // !NDEBUG
00332 
00333   for ( ; elem_it != elem_end && !failure; ++elem_it)
00334     {
00335       // Pointer to the element
00336       Elem *elem = *elem_it;
00337 
00338       for (unsigned int n=0; n<elem->n_neighbors(); n++)
00339         {
00340           Elem *neighbor =
00341             topological_neighbor(elem, point_locator.get(), n);
00342 
00343           if (!neighbor || !neighbor->active() ||
00344               neighbor == remote_elem)
00345             continue;
00346 
00347           if ((neighbor->level() + 1 < elem->level()) ||
00348               (neighbor->p_level() + 1 < elem->p_level()) ||
00349               (neighbor->p_level() > elem->p_level() + 1))
00350             {
00351               failure = true;
00352 #ifndef NDEBUG
00353               failed_elem = elem;
00354               failed_neighbor = neighbor;
00355 #endif // !NDEBUG
00356               break;
00357             }
00358         }
00359     }
00360 
00361   // If any processor failed, we failed globally
00362   this->comm().max(failure);
00363 
00364   if (failure)
00365     {
00366       // We didn't pass the level one test, so libmesh_assert that
00367       // we're allowed not to
00368 #ifndef NDEBUG
00369       if (libmesh_assert_pass)
00370         {
00371           libMesh::out <<
00372             "MeshRefinement Level one failure, element: " <<
00373             *failed_elem << std::endl;
00374           libMesh::out <<
00375             "MeshRefinement Level one failure, neighbor: " <<
00376             *failed_neighbor << std::endl;
00377         }
00378 #endif // !NDEBUG
00379       libmesh_assert(!libmesh_assert_pass);
00380       return false;
00381     }
00382   return true;
00383 }
00384 
00385 
00386 
00387 bool MeshRefinement::test_unflagged (bool libmesh_dbg_var(libmesh_assert_pass))
00388 {
00389   // This function must be run on all processors at once
00390   parallel_object_only();
00391 
00392   bool found_flag = false;
00393 
00394   // Search for local flags
00395   MeshBase::element_iterator       elem_it  = _mesh.active_local_elements_begin();
00396   const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end();
00397 
00398 #ifndef NDEBUG
00399   Elem *failed_elem = NULL;
00400 #endif
00401 
00402   for ( ; elem_it != elem_end; ++elem_it)
00403     {
00404       // Pointer to the element
00405       Elem *elem = *elem_it;
00406 
00407       if (elem->refinement_flag() == Elem::REFINE ||
00408           elem->refinement_flag() == Elem::COARSEN ||
00409           elem->p_refinement_flag() == Elem::REFINE ||
00410           elem->p_refinement_flag() == Elem::COARSEN)
00411         {
00412           found_flag = true;
00413 #ifndef NDEBUG
00414           failed_elem = elem;
00415 #endif
00416           break;
00417         }
00418     }
00419 
00420   // If we found a flag on any processor, it counts
00421   this->comm().max(found_flag);
00422 
00423   if (found_flag)
00424     {
00425 #ifndef NDEBUG
00426       if (libmesh_assert_pass)
00427         {
00428           libMesh::out <<
00429             "MeshRefinement test_unflagged failure, element: " <<
00430             *failed_elem << std::endl;
00431         }
00432 #endif
00433       // We didn't pass the "elements are unflagged" test,
00434       // so libmesh_assert that we're allowed not to
00435       libmesh_assert(!libmesh_assert_pass);
00436       return false;
00437     }
00438   return true;
00439 }
00440 
00441 
00442 
00443 bool MeshRefinement::refine_and_coarsen_elements (const bool maintain_level_one)
00444 {
00445   // This function must be run on all processors at once
00446   parallel_object_only();
00447 
00448   bool _maintain_level_one = maintain_level_one;
00449 
00450   // If the user used non-default parameters, let's warn that they're
00451   // deprecated
00452   if (!maintain_level_one)
00453     {
00454       libmesh_deprecated();
00455     }
00456   else
00457     _maintain_level_one = _face_level_mismatch_limit;
00458 
00459   // We can't yet turn a non-level-one mesh into a level-one mesh
00460   if (_maintain_level_one)
00461     libmesh_assert(test_level_one(true));
00462 
00463   // Possibly clean up the refinement flags from
00464   // a previous step
00465   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00466   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00467 
00468   for ( ; elem_it != elem_end; ++elem_it)
00469     {
00470       // Pointer to the element
00471       Elem *elem = *elem_it;
00472 
00473       // Set refinement flag to INACTIVE if the
00474       // element isn't active
00475       if ( !elem->active())
00476         {
00477           elem->set_refinement_flag(Elem::INACTIVE);
00478           elem->set_p_refinement_flag(Elem::INACTIVE);
00479         }
00480 
00481       // This might be left over from the last step
00482       if (elem->refinement_flag() == Elem::JUST_REFINED)
00483         elem->set_refinement_flag(Elem::DO_NOTHING);
00484     }
00485 
00486   // Parallel consistency has to come first, or coarsening
00487   // along processor boundaries might occasionally be falsely
00488   // prevented
00489   bool flags_were_consistent = this->make_flags_parallel_consistent();
00490 
00491   // In theory, we should be able to remove the above call, which can
00492   // be expensive and should be unnecessary.  In practice, doing
00493   // consistent flagging in parallel is hard, it's impossible to
00494   // verify at the library level if it's being done by user code, and
00495   // we don't want to abort large parallel runs in opt mode... but we
00496   // do want to warn that they should be fixed.
00497   if (!flags_were_consistent)
00498     {
00499       libMesh::out << "Refinement flags were not consistent between processors!\n"
00500                    << "Correcting and continuing.";
00501     }
00502 
00503   // Repeat until flag changes match on every processor
00504   do
00505     {
00506       // Repeat until coarsening & refinement flags jive
00507       bool satisfied = false;
00508       do
00509         {
00510           const bool coarsening_satisfied =
00511             this->make_coarsening_compatible(maintain_level_one);
00512 
00513           const bool refinement_satisfied =
00514             this->make_refinement_compatible(maintain_level_one);
00515 
00516           bool smoothing_satisfied =
00517             !this->eliminate_unrefined_patches();
00518 
00519           if (_edge_level_mismatch_limit)
00520             smoothing_satisfied = smoothing_satisfied &&
00521               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00522 
00523           if (_node_level_mismatch_limit)
00524             smoothing_satisfied = smoothing_satisfied &&
00525               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00526 
00527           satisfied = (coarsening_satisfied &&
00528                        refinement_satisfied &&
00529                        smoothing_satisfied);
00530 #ifdef DEBUG
00531           bool max_satisfied = satisfied,
00532             min_satisfied = satisfied;
00533           this->comm().max(max_satisfied);
00534           this->comm().min(min_satisfied);
00535           libmesh_assert_equal_to (satisfied, max_satisfied);
00536           libmesh_assert_equal_to (satisfied, min_satisfied);
00537 #endif
00538         }
00539       while (!satisfied);
00540     }
00541   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00542 
00543   // First coarsen the flagged elements.
00544   const bool coarsening_changed_mesh =
00545     this->_coarsen_elements ();
00546 
00547   // FIXME: test_level_one now tests consistency across periodic
00548   // boundaries, which requires a point_locator, which just got
00549   // invalidated by _coarsen_elements() and hasn't yet been cleared by
00550   // prepare_for_use().
00551 
00552   //  if (_maintain_level_one)
00553   //    libmesh_assert(test_level_one(true));
00554   //  libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00555   //  libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00556 
00557   // FIXME: This won't pass unless we add a redundant find_neighbors()
00558   // call or replace find_neighbors() with on-the-fly neighbor updating
00559   // libmesh_assert(!this->eliminate_unrefined_patches());
00560 
00561   // We can't contract the mesh ourselves anymore - a System might
00562   // need to restrict old coefficient vectors first
00563   // _mesh.contract();
00564 
00565   // Now refine the flagged elements.  This will
00566   // take up some space, maybe more than what was freed.
00567   const bool refining_changed_mesh =
00568     this->_refine_elements();
00569 
00570   // Finally, the new mesh needs to be prepared for use
00571   if (coarsening_changed_mesh || refining_changed_mesh)
00572     {
00573 #ifdef DEBUG
00574       _mesh.libmesh_assert_valid_parallel_ids();
00575 #endif
00576 
00577       _mesh.prepare_for_use (/*skip_renumber =*/false);
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       // FIXME: This won't pass unless we add a redundant find_neighbors()
00585       // call or replace find_neighbors() with on-the-fly neighbor updating
00586       // libmesh_assert(!this->eliminate_unrefined_patches());
00587 
00588       return true;
00589     }
00590   else
00591     {
00592       if (_maintain_level_one)
00593         libmesh_assert(test_level_one(true));
00594       libmesh_assert(test_unflagged(true));
00595       libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00596       libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00597     }
00598 
00599   // Otherwise there was no change in the mesh,
00600   // let the user know.  Also, there is no need
00601   // to prepare the mesh for use since it did not change.
00602   return false;
00603 
00604 }
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 bool MeshRefinement::coarsen_elements (const bool maintain_level_one)
00613 {
00614   // This function must be run on all processors at once
00615   parallel_object_only();
00616 
00617   bool _maintain_level_one = maintain_level_one;
00618 
00619   // If the user used non-default parameters, let's warn that they're
00620   // deprecated
00621   if (!maintain_level_one)
00622     {
00623       libmesh_deprecated();
00624     }
00625   else
00626     _maintain_level_one = _face_level_mismatch_limit;
00627 
00628   // We can't yet turn a non-level-one mesh into a level-one mesh
00629   if (_maintain_level_one)
00630     libmesh_assert(test_level_one(true));
00631 
00632   // Possibly clean up the refinement flags from
00633   // a previous step
00634   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00635   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00636 
00637   for ( ; elem_it != elem_end; ++elem_it)
00638     {
00639       // Pointer to the element
00640       Elem* elem = *elem_it;
00641 
00642       // Set refinement flag to INACTIVE if the
00643       // element isn't active
00644       if ( !elem->active())
00645         {
00646           elem->set_refinement_flag(Elem::INACTIVE);
00647           elem->set_p_refinement_flag(Elem::INACTIVE);
00648         }
00649 
00650       // This might be left over from the last step
00651       if (elem->refinement_flag() == Elem::JUST_REFINED)
00652         elem->set_refinement_flag(Elem::DO_NOTHING);
00653     }
00654 
00655   // Parallel consistency has to come first, or coarsening
00656   // along processor boundaries might occasionally be falsely
00657   // prevented
00658   bool flags_were_consistent = this->make_flags_parallel_consistent();
00659 
00660   // In theory, we should be able to remove the above call, which can
00661   // be expensive and should be unnecessary.  In practice, doing
00662   // consistent flagging in parallel is hard, it's impossible to
00663   // verify at the library level if it's being done by user code, and
00664   // we don't want to abort large parallel runs in opt mode... but we
00665   // do want to warn that they should be fixed.
00666   libmesh_assert(flags_were_consistent);
00667   if (!flags_were_consistent)
00668     {
00669       libMesh::out << "Refinement flags were not consistent between processors!\n"
00670                    << "Correcting and continuing.";
00671     }
00672 
00673   // Repeat until flag changes match on every processor
00674   do
00675     {
00676       // Repeat until the flags form a conforming mesh.
00677       bool satisfied = false;
00678       do
00679         {
00680           const bool coarsening_satisfied =
00681             this->make_coarsening_compatible(maintain_level_one);
00682 
00683           bool smoothing_satisfied =
00684             !this->eliminate_unrefined_patches();// &&
00685 
00686           if (_edge_level_mismatch_limit)
00687             smoothing_satisfied = smoothing_satisfied &&
00688               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00689 
00690           if (_node_level_mismatch_limit)
00691             smoothing_satisfied = smoothing_satisfied &&
00692               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00693 
00694           satisfied = (coarsening_satisfied &&
00695                        smoothing_satisfied);
00696 #ifdef DEBUG
00697           bool max_satisfied = satisfied,
00698             min_satisfied = satisfied;
00699           this->comm().max(max_satisfied);
00700           this->comm().min(min_satisfied);
00701           libmesh_assert_equal_to (satisfied, max_satisfied);
00702           libmesh_assert_equal_to (satisfied, min_satisfied);
00703 #endif
00704         }
00705       while (!satisfied);
00706     }
00707   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00708 
00709   // Coarsen the flagged elements.
00710   const bool mesh_changed =
00711     this->_coarsen_elements ();
00712 
00713   if (_maintain_level_one)
00714     libmesh_assert(test_level_one(true));
00715   libmesh_assert(this->make_coarsening_compatible(maintain_level_one));
00716   // FIXME: This won't pass unless we add a redundant find_neighbors()
00717   // call or replace find_neighbors() with on-the-fly neighbor updating
00718   // libmesh_assert(!this->eliminate_unrefined_patches());
00719 
00720   // We can't contract the mesh ourselves anymore - a System might
00721   // need to restrict old coefficient vectors first
00722   // _mesh.contract();
00723 
00724   // Finally, the new mesh may need to be prepared for use
00725   if (mesh_changed)
00726     _mesh.prepare_for_use (/*skip_renumber =*/false);
00727 
00728   return mesh_changed;
00729 }
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 bool MeshRefinement::refine_elements (const bool maintain_level_one)
00738 {
00739   // This function must be run on all processors at once
00740   parallel_object_only();
00741 
00742   bool _maintain_level_one = maintain_level_one;
00743 
00744   // If the user used non-default parameters, let's warn that they're
00745   // deprecated
00746   if (!maintain_level_one)
00747     {
00748       libmesh_deprecated();
00749     }
00750   else
00751     _maintain_level_one = _face_level_mismatch_limit;
00752 
00753   if (_maintain_level_one)
00754     libmesh_assert(test_level_one(true));
00755 
00756   // Possibly clean up the refinement flags from
00757   // a previous step
00758   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00759   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00760 
00761   for ( ; elem_it != elem_end; ++elem_it)
00762     {
00763       // Pointer to the element
00764       Elem *elem = *elem_it;
00765 
00766       // Set refinement flag to INACTIVE if the
00767       // element isn't active
00768       if ( !elem->active())
00769         {
00770           elem->set_refinement_flag(Elem::INACTIVE);
00771           elem->set_p_refinement_flag(Elem::INACTIVE);
00772         }
00773 
00774       // This might be left over from the last step
00775       if (elem->refinement_flag() == Elem::JUST_REFINED)
00776         elem->set_refinement_flag(Elem::DO_NOTHING);
00777     }
00778 
00779 
00780 
00781   // Parallel consistency has to come first, or coarsening
00782   // along processor boundaries might occasionally be falsely
00783   // prevented
00784   bool flags_were_consistent = this->make_flags_parallel_consistent();
00785 
00786   // In theory, we should be able to remove the above call, which can
00787   // be expensive and should be unnecessary.  In practice, doing
00788   // consistent flagging in parallel is hard, it's impossible to
00789   // verify at the library level if it's being done by user code, and
00790   // we don't want to abort large parallel runs in opt mode... but we
00791   // do want to warn that they should be fixed.
00792   libmesh_assert(flags_were_consistent);
00793   if (!flags_were_consistent)
00794     {
00795       libMesh::out << "Refinement flags were not consistent between processors!\n"
00796                    << "Correcting and continuing.";
00797     }
00798 
00799   // Repeat until flag changes match on every processor
00800   do
00801     {
00802       // Repeat until coarsening & refinement flags jive
00803       bool satisfied = false;
00804       do
00805         {
00806           const bool refinement_satisfied =
00807             this->make_refinement_compatible(maintain_level_one);
00808 
00809           bool smoothing_satisfied =
00810             !this->eliminate_unrefined_patches();// &&
00811 
00812           if (_edge_level_mismatch_limit)
00813             smoothing_satisfied = smoothing_satisfied &&
00814               !this->limit_level_mismatch_at_edge (_edge_level_mismatch_limit);
00815 
00816           if (_node_level_mismatch_limit)
00817             smoothing_satisfied = smoothing_satisfied &&
00818               !this->limit_level_mismatch_at_node (_node_level_mismatch_limit);
00819 
00820           satisfied = (refinement_satisfied &&
00821                        smoothing_satisfied);
00822 #ifdef DEBUG
00823           bool max_satisfied = satisfied,
00824             min_satisfied = satisfied;
00825           this->comm().max(max_satisfied);
00826           this->comm().min(min_satisfied);
00827           libmesh_assert_equal_to (satisfied, max_satisfied);
00828           libmesh_assert_equal_to (satisfied, min_satisfied);
00829 #endif
00830         }
00831       while (!satisfied);
00832     }
00833   while (!_mesh.is_serial() && !this->make_flags_parallel_consistent());
00834 
00835   // Now refine the flagged elements.  This will
00836   // take up some space, maybe more than what was freed.
00837   const bool mesh_changed =
00838     this->_refine_elements();
00839 
00840   if (_maintain_level_one)
00841     libmesh_assert(test_level_one(true));
00842   libmesh_assert(this->make_refinement_compatible(maintain_level_one));
00843   // FIXME: This won't pass unless we add a redundant find_neighbors()
00844   // call or replace find_neighbors() with on-the-fly neighbor updating
00845   // libmesh_assert(!this->eliminate_unrefined_patches());
00846 
00847   // Finally, the new mesh needs to be prepared for use
00848   if (mesh_changed)
00849     _mesh.prepare_for_use (/*skip_renumber =*/false);
00850 
00851   return mesh_changed;
00852 }
00853 
00854 
00855 // Functor for make_flags_parallel_consistent
00856 namespace {
00857 
00858 struct SyncRefinementFlags
00859 {
00860   typedef unsigned char datum;
00861   typedef Elem::RefinementState (Elem::*get_a_flag)() const;
00862   typedef void (Elem::*set_a_flag)(const Elem::RefinementState);
00863 
00864   SyncRefinementFlags(MeshBase &_mesh,
00865                       get_a_flag _getter,
00866                       set_a_flag _setter) :
00867     mesh(_mesh), parallel_consistent(true),
00868     get_flag(_getter), set_flag(_setter) {}
00869 
00870   MeshBase &mesh;
00871   bool parallel_consistent;
00872   get_a_flag get_flag;
00873   set_a_flag set_flag;
00874   // References to pointers to member functions segfault?
00875   // get_a_flag& get_flag;
00876   // set_a_flag& set_flag;
00877 
00878   // Find the refinement flag on each requested element
00879   void gather_data (const std::vector<dof_id_type>& ids,
00880                     std::vector<datum>& flags)
00881   {
00882     flags.resize(ids.size());
00883 
00884     for (std::size_t i=0; i != ids.size(); ++i)
00885       {
00886         // Look for this element in the mesh
00887         // We'd better find every element we're asked for
00888         Elem *elem = mesh.elem(ids[i]);
00889 
00890         // Return the element's refinement flag
00891         flags[i] = (elem->*get_flag)();
00892       }
00893   }
00894 
00895   void act_on_data (const std::vector<dof_id_type>& ids,
00896                     std::vector<datum>& flags)
00897   {
00898     for (std::size_t i=0; i != ids.size(); ++i)
00899       {
00900         Elem *elem = mesh.elem(ids[i]);
00901 
00902         datum old_flag = (elem->*get_flag)();
00903         datum &new_flag = flags[i];
00904 
00905         if (old_flag != new_flag)
00906           {
00907             // It's possible for foreign flags to be (temporarily) more
00908             // conservative than our own, such as when a refinement in
00909             // one of the foreign processor's elements is mandated by a
00910             // refinement in one of our neighboring elements it can see
00911             // which was mandated by a refinement in one of our
00912             // neighboring elements it can't see
00913             // libmesh_assert (!(new_flag != Elem::REFINE &&
00914             //                   old_flag == Elem::REFINE));
00915             //
00916             (elem->*set_flag)
00917               (static_cast<Elem::RefinementState>(new_flag));
00918             parallel_consistent = false;
00919           }
00920       }
00921   }
00922 };
00923 }
00924 
00925 
00926 
00927 bool MeshRefinement::make_flags_parallel_consistent()
00928 {
00929   // This function must be run on all processors at once
00930   parallel_object_only();
00931 
00932   START_LOG ("make_flags_parallel_consistent()", "MeshRefinement");
00933 
00934   SyncRefinementFlags hsync(_mesh, &Elem::refinement_flag,
00935                             &Elem::set_refinement_flag);
00936   Parallel::sync_dofobject_data_by_id
00937     (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), hsync);
00938 
00939   SyncRefinementFlags psync(_mesh, &Elem::p_refinement_flag,
00940                             &Elem::set_p_refinement_flag);
00941   Parallel::sync_dofobject_data_by_id
00942     (this->comm(), _mesh.elements_begin(), _mesh.elements_end(), psync);
00943 
00944   // If we weren't consistent in both h and p on every processor then
00945   // we weren't globally consistent
00946   bool parallel_consistent = hsync.parallel_consistent &&
00947     psync.parallel_consistent;
00948   this->comm().min(parallel_consistent);
00949 
00950   STOP_LOG ("make_flags_parallel_consistent()", "MeshRefinement");
00951 
00952   return parallel_consistent;
00953 }
00954 
00955 
00956 
00957 bool MeshRefinement::make_coarsening_compatible(const bool maintain_level_one)
00958 {
00959   // This function must be run on all processors at once
00960   parallel_object_only();
00961 
00962   // We may need a PointLocator for topological_neighbor() tests
00963   // later, which we need to make sure gets constructed on all
00964   // processors at once.
00965   UniquePtr<PointLocatorBase> point_locator;
00966 
00967 #ifdef LIBMESH_ENABLE_PERIODIC
00968   bool has_periodic_boundaries =
00969     _periodic_boundaries && !_periodic_boundaries->empty();
00970   libmesh_assert(this->comm().verify(has_periodic_boundaries));
00971 
00972   if (has_periodic_boundaries)
00973     point_locator = _mesh.sub_point_locator();
00974 #endif
00975 
00976   START_LOG ("make_coarsening_compatible()", "MeshRefinement");
00977 
00978   bool _maintain_level_one = maintain_level_one;
00979 
00980   // If the user used non-default parameters, let's warn that they're
00981   // deprecated
00982   if (!maintain_level_one)
00983     {
00984       libmesh_deprecated();
00985     }
00986   else
00987     _maintain_level_one = _face_level_mismatch_limit;
00988 
00989 
00990   // Unless we encounter a specific situation level-one
00991   // will be satisfied after executing this loop just once
00992   bool level_one_satisfied = true;
00993 
00994 
00995   // Unless we encounter a specific situation we will be compatible
00996   // with any selected refinement flags
00997   bool compatible_with_refinement = true;
00998 
00999 
01000   // find the maximum h and p levels in the mesh
01001   unsigned int max_level = 0;
01002   unsigned int max_p_level = 0;
01003 
01004   {
01005     // First we look at all the active level-0 elements.  Since it doesn't make
01006     // sense to coarsen them we must un-set their coarsen flags if
01007     // they are set.
01008     MeshBase::element_iterator       el     = _mesh.active_elements_begin();
01009     const MeshBase::element_iterator end_el = _mesh.active_elements_end();
01010 
01011     for (; el != end_el; ++el)
01012       {
01013         Elem *elem = *el;
01014         max_level = std::max(max_level, elem->level());
01015         max_p_level =
01016           std::max(max_p_level,
01017                    static_cast<unsigned int>(elem->p_level()));
01018 
01019         if ((elem->level() == 0) &&
01020             (elem->refinement_flag() == Elem::COARSEN))
01021           elem->set_refinement_flag(Elem::DO_NOTHING);
01022 
01023         if ((elem->p_level() == 0) &&
01024             (elem->p_refinement_flag() == Elem::COARSEN))
01025           elem->set_p_refinement_flag(Elem::DO_NOTHING);
01026       }
01027   }
01028 
01029   // if there are no refined elements on this processor then
01030   // there is no work for us to do
01031   if (max_level == 0 && max_p_level == 0)
01032     {
01033       STOP_LOG ("make_coarsening_compatible()", "MeshRefinement");
01034 
01035       // But we still have to check with other processors
01036       this->comm().min(compatible_with_refinement);
01037 
01038       return compatible_with_refinement;
01039     }
01040 
01041 
01042 
01043   // Loop over all the active elements.  If an element is marked
01044   // for coarsening we better check its neighbors.  If ANY of these neighbors
01045   // are marked for refinement AND are at the same level then there is a
01046   // conflict.  By convention refinement wins, so we un-mark the element for
01047   // coarsening.  Level-one would be violated in this case so we need to re-run
01048   // the loop.
01049   if (_maintain_level_one)
01050     {
01051 
01052     repeat:
01053       level_one_satisfied = true;
01054 
01055       do
01056         {
01057           level_one_satisfied = true;
01058 
01059           MeshBase::element_iterator       el     = _mesh.active_elements_begin();
01060           const MeshBase::element_iterator end_el = _mesh.active_elements_end();
01061 
01062           for (; el != end_el; ++el)
01063             {
01064               Elem* elem = *el;
01065               bool my_flag_changed = false;
01066 
01067               if (elem->refinement_flag() == Elem::COARSEN) // If the element is active and
01068                 // the coarsen flag is set
01069                 {
01070                   const unsigned int my_level = elem->level();
01071 
01072                   for (unsigned int n=0; n<elem->n_neighbors(); n++)
01073                     {
01074                       const Elem* neighbor =
01075                         topological_neighbor(elem, point_locator.get(), n);
01076 
01077                       if (neighbor != NULL &&      // I have a
01078                           neighbor != remote_elem) // neighbor here
01079                         {
01080                           if (neighbor->active()) // and it is active
01081                             {
01082                               if ((neighbor->level() == my_level) &&
01083                                   (neighbor->refinement_flag() == Elem::REFINE)) // the neighbor is at my level
01084                                 // and wants to be refined
01085                                 {
01086                                   elem->set_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. That means it has children.
01092                             {  // While it _may_ be possible to coarsen us if all the children of
01093                               // that element want to be coarsened, it is impossible to know at this
01094                               // stage.  Forget about it for the moment...  This can be handled in
01095                               // two steps.
01096                               elem->set_refinement_flag(Elem::DO_NOTHING);
01097                               my_flag_changed = true;
01098                               break;
01099                             }
01100                         }
01101                     }
01102                 }
01103               if (elem->p_refinement_flag() == Elem::COARSEN) // If
01104                 // the element is active and the order reduction flag is set
01105                 {
01106                   const unsigned int my_p_level = elem->p_level();
01107 
01108                   for (unsigned int n=0; n<elem->n_neighbors(); n++)
01109                     {
01110                       const Elem* neighbor =
01111                         topological_neighbor(elem, point_locator.get(), n);
01112 
01113                       if (neighbor != NULL &&      // I have a
01114                           neighbor != remote_elem) // neighbor here
01115                         {
01116                           if (neighbor->active()) // and it is active
01117                             {
01118                               if ((neighbor->p_level() > my_p_level &&
01119                                    neighbor->p_refinement_flag() != Elem::COARSEN)
01120                                   || (neighbor->p_level() == my_p_level &&
01121                                       neighbor->p_refinement_flag() == Elem::REFINE))
01122                                 {
01123                                   elem->set_p_refinement_flag(Elem::DO_NOTHING);
01124                                   my_flag_changed = true;
01125                                   break;
01126                                 }
01127                             }
01128                           else // I have a neighbor and it is not active.
01129                             {  // We need to find which of its children
01130                               // have me as a neighbor, and maintain
01131                               // level one p compatibility with them.
01132                               // Because we currently have level one h
01133                               // compatibility, we don't need to check
01134                               // grandchildren
01135 
01136                               libmesh_assert(neighbor->has_children());
01137                               for (unsigned int c=0; c!=neighbor->n_children(); c++)
01138                                 {
01139                                   Elem *subneighbor = neighbor->child(c);
01140                                   if (subneighbor != remote_elem &&
01141                                       subneighbor->active() &&
01142                                       has_topological_neighbor(subneighbor, point_locator.get(), elem))
01143                                     if ((subneighbor->p_level() > my_p_level &&
01144                                          subneighbor->p_refinement_flag() != Elem::COARSEN)
01145                                         || (subneighbor->p_level() == my_p_level &&
01146                                             subneighbor->p_refinement_flag() == Elem::REFINE))
01147                                       {
01148                                         elem->set_p_refinement_flag(Elem::DO_NOTHING);
01149                                         my_flag_changed = true;
01150                                         break;
01151                                       }
01152                                 }
01153                               if (my_flag_changed)
01154                                 break;
01155                             }
01156                         }
01157                     }
01158                 }
01159 
01160               // If the current element's flag changed, we hadn't
01161               // satisfied the level one rule.
01162               if (my_flag_changed)
01163                 level_one_satisfied = false;
01164 
01165               // Additionally, if it has non-local neighbors, and
01166               // we're not in serial, then we'll eventually have to
01167               // return compatible_with_refinement = false, because
01168               // our change has to propagate to neighboring
01169               // processors.
01170               if (my_flag_changed && !_mesh.is_serial())
01171                 for (unsigned int n=0; n != elem->n_neighbors(); ++n)
01172                   {
01173                     Elem* neigh =
01174                       topological_neighbor(elem, point_locator.get(), n);
01175 
01176                     if (!neigh)
01177                       continue;
01178                     if (neigh == remote_elem ||
01179                         neigh->processor_id() !=
01180                         this->processor_id())
01181                       {
01182                         compatible_with_refinement = false;
01183                         break;
01184                       }
01185                     // FIXME - for non-level one meshes we should
01186                     // test all descendants
01187                     if (neigh->has_children())
01188                       for (unsigned int c=0; c != neigh->n_children(); ++c)
01189                         if (neigh->child(c) == remote_elem ||
01190                             neigh->child(c)->processor_id() !=
01191                             this->processor_id())
01192                           {
01193                             compatible_with_refinement = false;
01194                             break;
01195                           }
01196                   }
01197             }
01198         }
01199       while (!level_one_satisfied);
01200 
01201     } // end if (_maintain_level_one)
01202 
01203 
01204   // Next we look at all of the ancestor cells.
01205   // If there is a parent cell with all of its children
01206   // wanting to be unrefined then the element is a candidate
01207   // for unrefinement.  If all the children don't
01208   // all want to be unrefined then ALL of them need to have their
01209   // unrefinement flags cleared.
01210   for (int level=(max_level); level >= 0; level--)
01211     {
01212       MeshBase::element_iterator       el     = _mesh.level_elements_begin(level);
01213       const MeshBase::element_iterator end_el = _mesh.level_elements_end(level);
01214       for (; el != end_el; ++el)
01215         {
01216           Elem *elem = *el;
01217           if (elem->ancestor())
01218             {
01219 
01220               // right now the element hasn't been disqualified
01221               // as a candidate for unrefinement
01222               bool is_a_candidate = true;
01223               bool found_remote_child = false;
01224 
01225               for (unsigned int c=0; c<elem->n_children(); c++)
01226                 {
01227                   Elem *child = elem->child(c);
01228                   if (child == remote_elem)
01229                     found_remote_child = true;
01230                   else if ((child->refinement_flag() != Elem::COARSEN) ||
01231                            !child->active() )
01232                     is_a_candidate = false;
01233                 }
01234 
01235               if (!is_a_candidate && !found_remote_child)
01236                 {
01237                   elem->set_refinement_flag(Elem::INACTIVE);
01238 
01239                   for (unsigned int c=0; c<elem->n_children(); c++)
01240                     {
01241                       Elem *child = elem->child(c);
01242                       if (child == remote_elem)
01243                         continue;
01244                       if (child->refinement_flag() == Elem::COARSEN)
01245                         {
01246                           level_one_satisfied = false;
01247                           child->set_refinement_flag(Elem::DO_NOTHING);
01248                         }
01249                     }
01250                 }
01251             }
01252         }
01253     }
01254 
01255   if (!level_one_satisfied && _maintain_level_one) goto repeat;
01256 
01257 
01258   // If all the children of a parent are set to be coarsened
01259   // then flag the parent so that they can kill thier kids...
01260   MeshBase::element_iterator       all_el     = _mesh.elements_begin();
01261   const MeshBase::element_iterator all_el_end = _mesh.elements_end();
01262   for (; all_el != all_el_end; ++all_el)
01263     {
01264       Elem *elem = *all_el;
01265       if (elem->ancestor())
01266         {
01267 
01268           // Presume all the children are local and flagged for
01269           // coarsening and then look for a contradiction
01270           bool all_children_flagged_for_coarsening = true;
01271           bool found_remote_child = false;
01272 
01273           for (unsigned int c=0; c<elem->n_children(); c++)
01274             {
01275               Elem *child = elem->child(c);
01276               if (child == remote_elem)
01277                 found_remote_child = true;
01278               else if (child->refinement_flag() != Elem::COARSEN)
01279                 all_children_flagged_for_coarsening = false;
01280             }
01281 
01282           if (!found_remote_child &&
01283               all_children_flagged_for_coarsening)
01284             elem->set_refinement_flag(Elem::COARSEN_INACTIVE);
01285           else if (!found_remote_child)
01286             elem->set_refinement_flag(Elem::INACTIVE);
01287         }
01288     }
01289 
01290   STOP_LOG ("make_coarsening_compatible()", "MeshRefinement");
01291 
01292   // If one processor finds an incompatibility, we're globally
01293   // incompatible
01294   this->comm().min(compatible_with_refinement);
01295 
01296   return compatible_with_refinement;
01297 }
01298 
01299 
01300 
01301 
01302 
01303 
01304 
01305 
01306 bool MeshRefinement::make_refinement_compatible(const bool maintain_level_one)
01307 {
01308   // This function must be run on all processors at once
01309   parallel_object_only();
01310 
01311   // We may need a PointLocator for topological_neighbor() tests
01312   // later, which we need to make sure gets constructed on all
01313   // processors at once.
01314   UniquePtr<PointLocatorBase> point_locator;
01315 
01316 #ifdef LIBMESH_ENABLE_PERIODIC
01317   bool has_periodic_boundaries =
01318     _periodic_boundaries && !_periodic_boundaries->empty();
01319   libmesh_assert(this->comm().verify(has_periodic_boundaries));
01320 
01321   if (has_periodic_boundaries)
01322     point_locator = _mesh.sub_point_locator();
01323 #endif
01324 
01325   START_LOG ("make_refinement_compatible()", "MeshRefinement");
01326 
01327   bool _maintain_level_one = maintain_level_one;
01328 
01329   // If the user used non-default parameters, let's warn that they're
01330   // deprecated
01331   if (!maintain_level_one)
01332     {
01333       libmesh_deprecated();
01334     }
01335   else
01336     _maintain_level_one = _face_level_mismatch_limit;
01337 
01338   // Unless we encounter a specific situation we will be compatible
01339   // with any selected coarsening flags
01340   bool compatible_with_coarsening = true;
01341 
01342   // This loop enforces the level-1 rule.  We should only
01343   // execute it if the user indeed wants level-1 satisfied!
01344   if (_maintain_level_one)
01345     {
01346       // Unless we encounter a specific situation level-one
01347       // will be satisfied after executing this loop just once
01348       bool level_one_satisfied = true;
01349 
01350       do
01351         {
01352           level_one_satisfied = true;
01353 
01354           MeshBase::element_iterator       el     = _mesh.active_elements_begin();
01355           const MeshBase::element_iterator end_el = _mesh.active_elements_end();
01356 
01357           for (; el != end_el; ++el)
01358             {
01359               Elem *elem = *el;
01360               if (elem->refinement_flag() == Elem::REFINE)  // If the element is active and the
01361                 // h refinement flag is set
01362                 {
01363                   const unsigned int my_level = elem->level();
01364 
01365                   for (unsigned int side=0; side != elem->n_sides(); side++)
01366                     {
01367                       Elem* neighbor =
01368                         topological_neighbor(elem, point_locator.get(), side);
01369 
01370                       if (neighbor != NULL        && // I have a
01371                           neighbor != remote_elem && // neighbor here
01372                           neighbor->active()) // and it is active
01373                         {
01374                           // Case 1:  The neighbor is at the same level I am.
01375                           //        1a: The neighbor will be refined       -> NO PROBLEM
01376                           //        1b: The neighbor won't be refined      -> NO PROBLEM
01377                           //        1c: The neighbor wants to be coarsened -> PROBLEM
01378                           if (neighbor->level() == my_level)
01379                             {
01380                               if (neighbor->refinement_flag() == Elem::COARSEN)
01381                                 {
01382                                   neighbor->set_refinement_flag(Elem::DO_NOTHING);
01383                                   if (neighbor->parent())
01384                                     neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
01385                                   compatible_with_coarsening = false;
01386                                   level_one_satisfied = false;
01387                                 }
01388                             }
01389 
01390 
01391                           // Case 2: The neighbor is one level lower than I am.
01392                           //         The neighbor thus MUST be refined to satisfy
01393                           //         the level-one rule, regardless of whether it
01394                           //         was originally flagged for refinement. If it
01395                           //         wasn't flagged already we need to repeat
01396                           //         this process.
01397                           else if ((neighbor->level()+1) == my_level)
01398                             {
01399                               if (neighbor->refinement_flag() != Elem::REFINE)
01400                                 {
01401                                   neighbor->set_refinement_flag(Elem::REFINE);
01402                                   if (neighbor->parent())
01403                                     neighbor->parent()->set_refinement_flag(Elem::INACTIVE);
01404                                   compatible_with_coarsening = false;
01405                                   level_one_satisfied = false;
01406                                 }
01407                             }
01408 #ifdef DEBUG
01409                           // Note that the only other possibility is that the
01410                           // neighbor is already refined, in which case it isn't
01411                           // active and we should never get here.
01412                           else
01413                             libmesh_error_msg("ERROR: Neighbor level must be equal or 1 higher than mine.");
01414 #endif
01415                         }
01416                     }
01417                 }
01418               if (elem->p_refinement_flag() == Elem::REFINE)  // If the element is active and the
01419                 // p refinement flag is set
01420                 {
01421                   const unsigned int my_p_level = elem->p_level();
01422 
01423                   for (unsigned int side=0; side != elem->n_sides(); side++)
01424                     {
01425                       Elem* neighbor =
01426                         topological_neighbor(elem, point_locator.get(), side);
01427 
01428                       if (neighbor != NULL &&      // I have a
01429                           neighbor != remote_elem) // neighbor here
01430                         {
01431                           if (neighbor->active()) // and it is active
01432                             {
01433                               if (neighbor->p_level() < my_p_level &&
01434                                   neighbor->p_refinement_flag() != Elem::REFINE)
01435                                 {
01436                                   neighbor->set_p_refinement_flag(Elem::REFINE);
01437                                   level_one_satisfied = false;
01438                                   compatible_with_coarsening = false;
01439                                 }
01440                               if (neighbor->p_level() == my_p_level &&
01441                                   neighbor->p_refinement_flag() == Elem::COARSEN)
01442                                 {
01443                                   neighbor->set_p_refinement_flag(Elem::DO_NOTHING);
01444                                   level_one_satisfied = false;
01445                                   compatible_with_coarsening = false;
01446                                 }
01447                             }
01448                           else // I have an inactive neighbor
01449                             {
01450                               libmesh_assert(neighbor->has_children());
01451                               for (unsigned int c=0; c!=neighbor->n_children(); c++)
01452                                 {
01453                                   Elem *subneighbor = neighbor->child(c);
01454                                   if (subneighbor == remote_elem)
01455                                     continue;
01456                                   if (subneighbor->active() &&
01457                                       has_topological_neighbor(subneighbor, point_locator.get(), elem))
01458                                     {
01459                                       if (subneighbor->p_level() < my_p_level &&
01460                                           subneighbor->p_refinement_flag() != Elem::REFINE)
01461                                         {
01462                                           // We should already be level one
01463                                           // compatible
01464                                           libmesh_assert_greater (subneighbor->p_level() + 2u,
01465                                                                   my_p_level);
01466                                           subneighbor->set_p_refinement_flag(Elem::REFINE);
01467                                           level_one_satisfied = false;
01468                                           compatible_with_coarsening = false;
01469                                         }
01470                                       if (subneighbor->p_level() == my_p_level &&
01471                                           subneighbor->p_refinement_flag() == Elem::COARSEN)
01472                                         {
01473                                           subneighbor->set_p_refinement_flag(Elem::DO_NOTHING);
01474                                           level_one_satisfied = false;
01475                                           compatible_with_coarsening = false;
01476                                         }
01477                                     }
01478                                 }
01479                             }
01480                         }
01481                     }
01482                 }
01483             }
01484         }
01485 
01486       while (!level_one_satisfied);
01487     } // end if (_maintain_level_one)
01488 
01489   // If we're not compatible on one processor, we're globally not
01490   // compatible
01491   this->comm().min(compatible_with_coarsening);
01492 
01493   STOP_LOG ("make_refinement_compatible()", "MeshRefinement");
01494 
01495   return compatible_with_coarsening;
01496 }
01497 
01498 
01499 
01500 
01501 bool MeshRefinement::_coarsen_elements ()
01502 {
01503   // This function must be run on all processors at once
01504   parallel_object_only();
01505 
01506   START_LOG ("_coarsen_elements()", "MeshRefinement");
01507 
01508   // Flag indicating if this call actually changes the mesh
01509   bool mesh_changed = false;
01510 
01511   // Clear the unused_elements data structure.
01512   // The elements have been packed since it was built,
01513   // so there are _no_ unused elements.  We cannot trust
01514   // any iterators currently in this data structure.
01515   // _unused_elements.clear();
01516 
01517   MeshBase::element_iterator       it  = _mesh.elements_begin();
01518   const MeshBase::element_iterator end = _mesh.elements_end();
01519 
01520   // Loop over the elements.
01521   for ( ; it != end; ++it)
01522     {
01523       Elem* elem = *it;
01524 
01525       // Not necessary when using elem_iterator
01526       // libmesh_assert(elem);
01527 
01528       // active elements flagged for coarsening will
01529       // no longer be deleted until MeshRefinement::contract()
01530       if (elem->refinement_flag() == Elem::COARSEN)
01531         {
01532           // Huh?  no level-0 element should be active
01533           // and flagged for coarsening.
01534           libmesh_assert_not_equal_to (elem->level(), 0);
01535 
01536           // Remove this element from any neighbor
01537           // lists that point to it.
01538           elem->nullify_neighbors();
01539 
01540           // Remove any boundary information associated
01541           // with this element
01542           _mesh.get_boundary_info().remove (elem);
01543 
01544           // Add this iterator to the _unused_elements
01545           // data structure so we might fill it.
01546           // The _unused_elements optimization is currently off.
01547           // _unused_elements.push_back (it);
01548 
01549           // Don't delete the element until
01550           // MeshRefinement::contract()
01551           // _mesh.delete_elem(elem);
01552 
01553           // the mesh has certainly changed
01554           mesh_changed = true;
01555         }
01556 
01557       // inactive elements flagged for coarsening
01558       // will become active
01559       else if (elem->refinement_flag() == Elem::COARSEN_INACTIVE)
01560         {
01561           elem->coarsen();
01562           libmesh_assert (elem->active());
01563 
01564           // the mesh has certainly changed
01565           mesh_changed = true;
01566         }
01567       if (elem->p_refinement_flag() == Elem::COARSEN)
01568         {
01569           if (elem->p_level() > 0)
01570             {
01571               elem->set_p_refinement_flag(Elem::JUST_COARSENED);
01572               elem->set_p_level(elem->p_level() - 1);
01573               mesh_changed = true;
01574             }
01575           else
01576             {
01577               elem->set_p_refinement_flag(Elem::DO_NOTHING);
01578             }
01579         }
01580     }
01581 
01582   // If the mesh changed on any processor, it changed globally
01583   this->comm().max(mesh_changed);
01584   // And we may need to update ParallelMesh values reflecting the changes
01585   if (mesh_changed)
01586     _mesh.update_parallel_id_counts();
01587 
01588   // Node processor ids may need to change if an element of that id
01589   // was coarsened away
01590   if (mesh_changed && !_mesh.is_serial())
01591     {
01592       // Update the _new_nodes_map so that processors can
01593       // find requested nodes
01594       this->update_nodes_map ();
01595 
01596       MeshCommunication().make_nodes_parallel_consistent (_mesh);
01597 
01598       // Clear the _new_nodes_map
01599       this->clear();
01600 
01601 #ifdef DEBUG
01602       MeshTools::libmesh_assert_valid_procids<Node>(_mesh);
01603 #endif
01604     }
01605 
01606   STOP_LOG ("_coarsen_elements()", "MeshRefinement");
01607 
01608   return mesh_changed;
01609 }
01610 
01611 
01612 
01613 bool MeshRefinement::_refine_elements ()
01614 {
01615   // This function must be run on all processors at once
01616   parallel_object_only();
01617 
01618   // Update the _new_nodes_map so that elements can
01619   // find nodes to connect to.
01620   this->update_nodes_map ();
01621 
01622   START_LOG ("_refine_elements()", "MeshRefinement");
01623 
01624   // Iterate over the elements, counting the elements
01625   // flagged for h refinement.
01626   dof_id_type n_elems_flagged = 0;
01627 
01628   MeshBase::element_iterator       it  = _mesh.elements_begin();
01629   const MeshBase::element_iterator end = _mesh.elements_end();
01630 
01631   for (; it != end; ++it)
01632     {
01633       Elem* elem = *it;
01634       if (elem->refinement_flag() == Elem::REFINE)
01635         n_elems_flagged++;
01636     }
01637 
01638   // Construct a local vector of Elem* which have been
01639   // previously marked for refinement.  We reserve enough
01640   // space to allow for every element to be refined.
01641   std::vector<Elem*> local_copy_of_elements;
01642   local_copy_of_elements.reserve(n_elems_flagged);
01643 
01644   // Iterate over the elements, looking for elements
01645   // flagged for refinement.
01646   for (it = _mesh.elements_begin(); it != end; ++it)
01647     {
01648       Elem* elem = *it;
01649       if (elem->refinement_flag() == Elem::REFINE)
01650         local_copy_of_elements.push_back(elem);
01651       if (elem->p_refinement_flag() == Elem::REFINE &&
01652           elem->active())
01653         {
01654           elem->set_p_level(elem->p_level()+1);
01655           elem->set_p_refinement_flag(Elem::JUST_REFINED);
01656         }
01657     }
01658 
01659   // Now iterate over the local copies and refine each one.
01660   // This may resize the mesh's internal container and invalidate
01661   // any existing iterators.
01662 
01663   for (std::size_t e = 0; e != local_copy_of_elements.size(); ++e)
01664     local_copy_of_elements[e]->refine(*this);
01665 
01666   // The mesh changed if there were elements h refined
01667   bool mesh_changed = !local_copy_of_elements.empty();
01668 
01669   // If the mesh changed on any processor, it changed globally
01670   this->comm().max(mesh_changed);
01671 
01672   // And we may need to update ParallelMesh values reflecting the changes
01673   if (mesh_changed)
01674     _mesh.update_parallel_id_counts();
01675 
01676   if (mesh_changed && !_mesh.is_serial())
01677     {
01678       MeshCommunication().make_elems_parallel_consistent (_mesh);
01679       MeshCommunication().make_nodes_parallel_consistent (_mesh);
01680 #ifdef DEBUG
01681       _mesh.libmesh_assert_valid_parallel_ids();
01682 #endif
01683     }
01684 
01685   // Clear the _new_nodes_map and _unused_elements data structures.
01686   this->clear();
01687 
01688   STOP_LOG ("_refine_elements()", "MeshRefinement");
01689 
01690   return mesh_changed;
01691 }
01692 
01693 
01694 
01695 void MeshRefinement::uniformly_p_refine (unsigned int n)
01696 {
01697   // Refine n times
01698   for (unsigned int rstep=0; rstep<n; rstep++)
01699     {
01700       // P refine all the active elements
01701       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01702       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01703 
01704       for ( ; elem_it != elem_end; ++elem_it)
01705         {
01706           (*elem_it)->set_p_level((*elem_it)->p_level()+1);
01707           (*elem_it)->set_p_refinement_flag(Elem::JUST_REFINED);
01708         }
01709     }
01710 }
01711 
01712 
01713 
01714 void MeshRefinement::uniformly_p_coarsen (unsigned int n)
01715 {
01716   // Coarsen p times
01717   for (unsigned int rstep=0; rstep<n; rstep++)
01718     {
01719       // P coarsen all the active elements
01720       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01721       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01722 
01723       for ( ; elem_it != elem_end; ++elem_it)
01724         {
01725           if ((*elem_it)->p_level() > 0)
01726             {
01727               (*elem_it)->set_p_level((*elem_it)->p_level()-1);
01728               (*elem_it)->set_p_refinement_flag(Elem::JUST_COARSENED);
01729             }
01730         }
01731     }
01732 }
01733 
01734 
01735 
01736 void MeshRefinement::uniformly_refine (unsigned int n)
01737 {
01738   // Refine n times
01739   // FIXME - this won't work if n>1 and the mesh
01740   // has already been attached to an equation system
01741   for (unsigned int rstep=0; rstep<n; rstep++)
01742     {
01743       // Clean up the refinement flags
01744       this->clean_refinement_flags();
01745 
01746       // Flag all the active elements for refinement.
01747       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01748       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01749 
01750       for ( ; elem_it != elem_end; ++elem_it)
01751         (*elem_it)->set_refinement_flag(Elem::REFINE);
01752 
01753       // Refine all the elements we just flagged.
01754       this->_refine_elements();
01755     }
01756 
01757   // Finally, the new mesh probably needs to be prepared for use
01758   if (n > 0)
01759     _mesh.prepare_for_use (/*skip_renumber =*/false);
01760 }
01761 
01762 
01763 
01764 void MeshRefinement::uniformly_coarsen (unsigned int n)
01765 {
01766   // Coarsen n times
01767   for (unsigned int rstep=0; rstep<n; rstep++)
01768     {
01769       // Clean up the refinement flags
01770       this->clean_refinement_flags();
01771 
01772       // Flag all the active elements for coarsening
01773       MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
01774       const MeshBase::element_iterator elem_end = _mesh.active_elements_end();
01775 
01776       for ( ; elem_it != elem_end; ++elem_it)
01777         {
01778           (*elem_it)->set_refinement_flag(Elem::COARSEN);
01779           if ((*elem_it)->parent())
01780             (*elem_it)->parent()->set_refinement_flag(Elem::COARSEN_INACTIVE);
01781         }
01782 
01783       // Coarsen all the elements we just flagged.
01784       this->_coarsen_elements();
01785     }
01786 
01787 
01788   // Finally, the new mesh probably needs to be prepared for use
01789   if (n > 0)
01790     _mesh.prepare_for_use (/*skip_renumber =*/false);
01791 }
01792 
01793 
01794 
01795 Elem* MeshRefinement::topological_neighbor(Elem* elem,
01796                                            const PointLocatorBase* point_locator,
01797                                            const unsigned int side)
01798 {
01799 #ifdef LIBMESH_ENABLE_PERIODIC
01800   if (_periodic_boundaries && !_periodic_boundaries->empty())
01801     {
01802       libmesh_assert(point_locator);
01803       return elem->topological_neighbor(side, _mesh, *point_locator, _periodic_boundaries);
01804     }
01805 #endif
01806   return elem->neighbor(side);
01807 }
01808 
01809 
01810 
01811 bool MeshRefinement::has_topological_neighbor(Elem* elem,
01812                                               const PointLocatorBase* point_locator,
01813                                               Elem* neighbor)
01814 {
01815 #ifdef LIBMESH_ENABLE_PERIODIC
01816   if (_periodic_boundaries && !_periodic_boundaries->empty())
01817     {
01818       libmesh_assert(point_locator);
01819       return elem->has_topological_neighbor(neighbor, _mesh, *point_locator, _periodic_boundaries);
01820     }
01821 #endif
01822   return elem->has_neighbor(neighbor);
01823 }
01824 
01825 
01826 
01827 } // namespace libMesh
01828 
01829 
01830 #endif