$extrastylesheet
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