$extrastylesheet
patch.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 // C++ includes
00021 #include <algorithm> // for std::fill
00022 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00023 #include <cmath>     // for std::sqrt std::pow std::abs
00024 
00025 
00026 // Local Includes
00027 #include "libmesh/libmesh_common.h"
00028 #include "libmesh/patch.h"
00029 #include "libmesh/elem.h"
00030 
00031 namespace libMesh
00032 {
00033 
00034 
00035 
00036 //-----------------------------------------------------------------
00037 // Patch implementations
00038 void Patch::find_face_neighbors(std::set<const Elem *> &new_neighbors)
00039 {
00040   // Loop over all the elements in the patch
00041   std::set<const Elem*>::const_iterator       it  = this->begin();
00042   const std::set<const Elem*>::const_iterator end_it = this->end();
00043 
00044   for (; it != end_it; ++it)
00045     {
00046       const Elem* elem = *it;
00047       for (unsigned int s=0; s<elem->n_sides(); s++)
00048         if (elem->neighbor(s) != NULL)        // we have a neighbor on this side
00049           {
00050             const Elem* neighbor = elem->neighbor(s);
00051 
00052 #ifdef LIBMESH_ENABLE_AMR
00053             if (!neighbor->active())          // the neighbor is *not* active,
00054               {                               // so add *all* neighboring
00055                                               // active children to the patch
00056                 std::vector<const Elem*> active_neighbor_children;
00057 
00058                 neighbor->active_family_tree_by_neighbor
00059                   (active_neighbor_children, elem);
00060 
00061                 std::vector<const Elem*>::const_iterator
00062                   child_it  = active_neighbor_children.begin();
00063                 const std::vector<const Elem*>::const_iterator
00064                   child_end = active_neighbor_children.end();
00065                 for (; child_it != child_end; ++child_it)
00066                   new_neighbors.insert(*child_it);
00067               }
00068             else
00069 #endif // #ifdef LIBMESH_ENABLE_AMR
00070               new_neighbors.insert (neighbor); // add active neighbors
00071           }
00072     }
00073 }
00074 
00075 
00076 
00077 void Patch::add_face_neighbors()
00078 {
00079   std::set<const Elem *> new_neighbors;
00080 
00081   this->find_face_neighbors(new_neighbors);
00082 
00083   this->insert(new_neighbors.begin(), new_neighbors.end());
00084 }
00085 
00086 
00087 
00088 void Patch::add_local_face_neighbors()
00089 {
00090   std::set<const Elem *> new_neighbors;
00091 
00092   this->find_face_neighbors(new_neighbors);
00093 
00094   std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
00095   const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();
00096 
00097   for (; it != end_it; ++it)
00098     {
00099       const Elem* neighbor = *it;
00100       if (neighbor->processor_id() ==
00101           _my_procid) // ... if the neighbor belongs to this processor
00102         this->insert (neighbor);   // ... then add it to the patch
00103     }
00104 }
00105 
00106 
00107 
00108 void Patch::add_semilocal_face_neighbors()
00109 {
00110   std::set<const Elem *> new_neighbors;
00111 
00112   this->find_face_neighbors(new_neighbors);
00113 
00114   std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
00115   const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();
00116 
00117   for (; it != end_it; ++it)
00118     {
00119       const Elem* neighbor = *it;
00120       if (neighbor->is_semilocal(_my_procid))
00121         this->insert (neighbor);
00122     }
00123 }
00124 
00125 
00126 
00127 void Patch::find_point_neighbors(std::set<const Elem *> &new_neighbors)
00128 {
00129   // Loop over all the elements in the patch
00130   std::set<const Elem*>::const_iterator       it  = this->begin();
00131   const std::set<const Elem*>::const_iterator end_it = this->end();
00132 
00133   for (; it != end_it; ++it)
00134     {
00135       std::set<const Elem*> elem_point_neighbors;
00136 
00137       const Elem* elem = *it;
00138       elem->find_point_neighbors(elem_point_neighbors);
00139 
00140       new_neighbors.insert(elem_point_neighbors.begin(),
00141                            elem_point_neighbors.end());
00142     }
00143 }
00144 
00145 
00146 
00147 void Patch::add_point_neighbors()
00148 {
00149   std::set<const Elem *> new_neighbors;
00150 
00151   this->find_point_neighbors(new_neighbors);
00152 
00153   this->insert(new_neighbors.begin(), new_neighbors.end());
00154 }
00155 
00156 
00157 
00158 void Patch::add_local_point_neighbors()
00159 {
00160   std::set<const Elem *> new_neighbors;
00161 
00162   this->find_point_neighbors(new_neighbors);
00163 
00164   std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
00165   const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();
00166 
00167   for (; it != end_it; ++it)
00168     {
00169       const Elem* neighbor = *it;
00170       if (neighbor->processor_id() ==
00171           _my_procid) // ... if the neighbor belongs to this processor
00172         this->insert (neighbor);   // ... then add it to the patch
00173     }
00174 }
00175 
00176 
00177 
00178 void Patch::add_semilocal_point_neighbors()
00179 {
00180   std::set<const Elem *> new_neighbors;
00181 
00182   this->find_point_neighbors(new_neighbors);
00183 
00184   std::set<const Elem*>::const_iterator       it  = new_neighbors.begin();
00185   const std::set<const Elem*>::const_iterator end_it = new_neighbors.end();
00186 
00187   for (; it != end_it; ++it)
00188     {
00189       const Elem* neighbor = *it;
00190       if (neighbor->is_semilocal(_my_procid))
00191         this->insert (neighbor);
00192     }
00193 }
00194 
00195 
00196 
00197 void Patch::build_around_element (const Elem* e0,
00198                                   const unsigned int target_patch_size,
00199                                   PMF patchtype)
00200 {
00201 
00202   // Make sure we are building a patch for an active element.
00203   libmesh_assert(e0);
00204   libmesh_assert (e0->active());
00205   // Make sure we are either starting with a local element or
00206   // requesting a nonlocal patch
00207   libmesh_assert ((patchtype != &Patch::add_local_face_neighbors &&
00208                    patchtype != &Patch::add_local_point_neighbors) ||
00209                   e0->processor_id() == _my_procid);
00210 
00211   // First clear the current set, then add the element of interest.
00212   this->clear();
00213   this->insert (e0);
00214 
00215   // Repeatedly add the neighbors of the elements in the patch until
00216   // the target patch size is met
00217   while (this->size() < target_patch_size)
00218     {
00219       // It is possible that the target patch size is larger than the number
00220       // of elements that can be added to the patch.  Since we don't
00221       // have access to the Mesh object here, the only way we can
00222       // detect this case is by detecting a "stagnant patch," i.e. a
00223       // patch whose size does not increase after adding face neighbors
00224       const std::size_t old_patch_size = this->size();
00225 
00226       // We profile the patch-extending functions separately
00227       (this->*patchtype)();
00228 
00229       // Check for a "stagnant" patch
00230       if (this->size() == old_patch_size)
00231         {
00232           libmesh_do_once(libMesh::err <<
00233                           "WARNING: stagnant patch of " << this->size() << " elements."
00234                           << std::endl <<
00235                           "Does the target patch size exceed the number of local elements?"
00236                           << std::endl;
00237                           libmesh_here(););
00238           break;
00239         }
00240     } // end while loop
00241 
00242 
00243   // make sure all the elements in the patch are active and local
00244   // if we are in debug mode
00245 #ifdef DEBUG
00246   {
00247     std::set<const Elem*>::const_iterator       it  = this->begin();
00248     const std::set<const Elem*>::const_iterator end_it = this->end();
00249 
00250     for (; it != end_it; ++it)
00251       {
00252         // Convenience.  Keep the syntax simple.
00253         const Elem* elem = *it;
00254 
00255         libmesh_assert (elem->active());
00256         if ((patchtype == &Patch::add_local_face_neighbors ||
00257              patchtype == &Patch::add_local_point_neighbors))
00258           libmesh_assert_equal_to (elem->processor_id(), _my_procid);
00259       }
00260   }
00261 #endif
00262 
00263 }
00264 
00265 } // namespace libMesh