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

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:06 UTC

Hosted By:
SourceForge.net Logo