libMesh
patch.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // C++ includes
20 #include <algorithm> // for std::fill
21 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
22 #include <cmath> // for std::sqrt std::pow std::abs
23 
24 
25 // Local Includes
26 #include "libmesh/libmesh_common.h"
27 #include "libmesh/patch.h"
28 #include "libmesh/elem.h"
29 
30 namespace libMesh
31 {
32 
33 
34 
35 //-----------------------------------------------------------------
36 // Patch implementations
37 void Patch::find_face_neighbors(std::set<const Elem *> & new_neighbors)
38 {
39  // Loop over all the elements in the patch
40  std::set<const Elem *>::const_iterator it = this->begin();
41  const std::set<const Elem *>::const_iterator end_it = this->end();
42 
43  for (; it != end_it; ++it)
44  {
45  const Elem * elem = *it;
46  for (auto neighbor : elem->neighbor_ptr_range())
47  if (neighbor != libmesh_nullptr) // we have a neighbor on this side
48  {
49 #ifdef LIBMESH_ENABLE_AMR
50  if (!neighbor->active()) // the neighbor is *not* active,
51  { // so add *all* neighboring
52  // active children to the patch
53  std::vector<const Elem *> active_neighbor_children;
54 
56  (active_neighbor_children, elem);
57 
58  std::vector<const Elem *>::const_iterator
59  child_it = active_neighbor_children.begin();
60  const std::vector<const Elem *>::const_iterator
61  child_end = active_neighbor_children.end();
62  for (; child_it != child_end; ++child_it)
63  new_neighbors.insert(*child_it);
64  }
65  else
66 #endif // #ifdef LIBMESH_ENABLE_AMR
67  new_neighbors.insert (neighbor); // add active neighbors
68  }
69  }
70 }
71 
72 
73 
75 {
76  std::set<const Elem *> new_neighbors;
77 
78  this->find_face_neighbors(new_neighbors);
79 
80  this->insert(new_neighbors.begin(), new_neighbors.end());
81 }
82 
83 
84 
86 {
87  std::set<const Elem *> new_neighbors;
88 
89  this->find_face_neighbors(new_neighbors);
90 
91  std::set<const Elem *>::const_iterator it = new_neighbors.begin();
92  const std::set<const Elem *>::const_iterator end_it = new_neighbors.end();
93 
94  for (; it != end_it; ++it)
95  {
96  const Elem * neighbor = *it;
97  if (neighbor->processor_id() ==
98  _my_procid) // ... if the neighbor belongs to this processor
99  this->insert (neighbor); // ... then add it to the patch
100  }
101 }
102 
103 
104 
106 {
107  std::set<const Elem *> new_neighbors;
108 
109  this->find_face_neighbors(new_neighbors);
110 
111  std::set<const Elem *>::const_iterator it = new_neighbors.begin();
112  const std::set<const Elem *>::const_iterator end_it = new_neighbors.end();
113 
114  for (; it != end_it; ++it)
115  {
116  const Elem * neighbor = *it;
117  if (neighbor->is_semilocal(_my_procid))
118  this->insert (neighbor);
119  }
120 }
121 
122 
123 
124 void Patch::find_point_neighbors(std::set<const Elem *> & new_neighbors)
125 {
126  // Loop over all the elements in the patch
127  std::set<const Elem *>::const_iterator it = this->begin();
128  const std::set<const Elem *>::const_iterator end_it = this->end();
129 
130  for (; it != end_it; ++it)
131  {
132  std::set<const Elem *> elem_point_neighbors;
133 
134  const Elem * elem = *it;
135  elem->find_point_neighbors(elem_point_neighbors);
136 
137  new_neighbors.insert(elem_point_neighbors.begin(),
138  elem_point_neighbors.end());
139  }
140 }
141 
142 
143 
145 {
146  std::set<const Elem *> new_neighbors;
147 
148  this->find_point_neighbors(new_neighbors);
149 
150  this->insert(new_neighbors.begin(), new_neighbors.end());
151 }
152 
153 
154 
156 {
157  std::set<const Elem *> new_neighbors;
158 
159  this->find_point_neighbors(new_neighbors);
160 
161  std::set<const Elem *>::const_iterator it = new_neighbors.begin();
162  const std::set<const Elem *>::const_iterator end_it = new_neighbors.end();
163 
164  for (; it != end_it; ++it)
165  {
166  const Elem * neighbor = *it;
167  if (neighbor->processor_id() ==
168  _my_procid) // ... if the neighbor belongs to this processor
169  this->insert (neighbor); // ... then add it to the patch
170  }
171 }
172 
173 
174 
176 {
177  std::set<const Elem *> new_neighbors;
178 
179  this->find_point_neighbors(new_neighbors);
180 
181  std::set<const Elem *>::const_iterator it = new_neighbors.begin();
182  const std::set<const Elem *>::const_iterator end_it = new_neighbors.end();
183 
184  for (; it != end_it; ++it)
185  {
186  const Elem * neighbor = *it;
187  if (neighbor->is_semilocal(_my_procid))
188  this->insert (neighbor);
189  }
190 }
191 
192 
193 
195  const unsigned int target_patch_size,
196  PMF patchtype)
197 {
198 
199  // Make sure we are building a patch for an active element.
200  libmesh_assert(e0);
201  libmesh_assert (e0->active());
202  // Make sure we are either starting with a local element or
203  // requesting a nonlocal patch
205  patchtype != &Patch::add_local_point_neighbors) ||
206  e0->processor_id() == _my_procid);
207 
208  // First clear the current set, then add the element of interest.
209  this->clear();
210  this->insert (e0);
211 
212  // Repeatedly add the neighbors of the elements in the patch until
213  // the target patch size is met
214  while (this->size() < target_patch_size)
215  {
216  // It is possible that the target patch size is larger than the number
217  // of elements that can be added to the patch. Since we don't
218  // have access to the Mesh object here, the only way we can
219  // detect this case is by detecting a "stagnant patch," i.e. a
220  // patch whose size does not increase after adding face neighbors
221  const std::size_t old_patch_size = this->size();
222 
223  // We profile the patch-extending functions separately
224  (this->*patchtype)();
225 
226  // Check for a "stagnant" patch
227  if (this->size() == old_patch_size)
228  {
229  libmesh_do_once(libMesh::err <<
230  "WARNING: stagnant patch of " << this->size() << " elements."
231  << std::endl <<
232  "Does the target patch size exceed the number of local elements?"
233  << std::endl;
234  libmesh_here(););
235  break;
236  }
237  } // end while loop
238 
239 
240  // make sure all the elements in the patch are active and local
241  // if we are in debug mode
242 #ifdef DEBUG
243  {
244  std::set<const Elem *>::const_iterator it = this->begin();
245  const std::set<const Elem *>::const_iterator end_it = this->end();
246 
247  for (; it != end_it; ++it)
248  {
249  // Convenience. Keep the syntax simple.
250  const Elem * elem = *it;
251 
252  libmesh_assert (elem->active());
253  if ((patchtype == &Patch::add_local_face_neighbors ||
254  patchtype == &Patch::add_local_point_neighbors))
255  libmesh_assert_equal_to (elem->processor_id(), _my_procid);
256  }
257  }
258 #endif
259 
260 }
261 
262 } // namespace libMesh
OStreamProxy err
bool active() const
Definition: elem.h:2257
void add_local_point_neighbors()
This function finds all elements on the current processor which touch the current patch at any point...
Definition: patch.C:155
This is the base class from which all geometric element types are derived.
Definition: elem.h:89
const class libmesh_nullptr_t libmesh_nullptr
bool is_semilocal(const processor_id_type my_pid) const
Definition: elem.C:552
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end...
The libMesh namespace provides an interface to certain functionality in the library.
void find_point_neighbors(const Point &p, std::set< const Elem * > &neighbor_set) const
This function finds all active elements (including this one) which are in the same manifold as this e...
Definition: elem.C:605
void build_around_element(const Elem *elem, const unsigned int target_patch_size=10, PMF patchtype=&Patch::add_local_face_neighbors)
Erases any elements in the current patch, then builds a new patch containing element elem by repeated...
Definition: patch.C:194
libmesh_assert(j)
void add_point_neighbors()
This function finds all elements which touch the current patch at any point, and adds them to the pat...
Definition: patch.C:144
void add_semilocal_point_neighbors()
This function finds all elements which touch the current patch at any point and which touch one of ou...
Definition: patch.C:175
void find_face_neighbors(std::set< const Elem * > &neighbor_set)
This function finds all elements which touch the current patch at a face.
Definition: patch.C:37
void add_local_face_neighbors()
This function finds all elements on the current processor which touch the current patch at a face...
Definition: patch.C:85
void(Patch::* PMF)()
Pointer to Member Function typedef.
Definition: patch.h:104
void add_face_neighbors()
This function finds all elements which touch the current patch at a face, and adds them to the patch...
Definition: patch.C:74
void add_semilocal_face_neighbors()
This function finds all elements which touch the current patch at a face and which touch one of our p...
Definition: patch.C:105
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:2855
void active_family_tree_by_neighbor(std::vector< const Elem * > &family, const Elem *neighbor, const bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to neighbor...
Definition: elem.C:1984
const processor_id_type _my_procid
Definition: patch.h:131
void find_point_neighbors(std::set< const Elem * > &neighbor_set)
This function finds all elements which touch the current patch at any point.
Definition: patch.C:124
processor_id_type processor_id() const
Definition: dof_object.h:694