patch.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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  for (const auto & elem : *this)
41  for (auto neighbor : elem->neighbor_ptr_range())
42  if (neighbor != nullptr) // we have a neighbor on this side
43  {
44 #ifdef LIBMESH_ENABLE_AMR
45  if (!neighbor->active()) // the neighbor is *not* active,
46  { // so add *all* neighboring
47  // active children to the patch
48  std::vector<const Elem *> active_neighbor_children;
49 
50  neighbor->active_family_tree_by_neighbor
51  (active_neighbor_children, elem);
52 
53  for (const auto & child : active_neighbor_children)
54  new_neighbors.insert(child);
55  }
56  else
57 #endif // #ifdef LIBMESH_ENABLE_AMR
58  new_neighbors.insert (neighbor); // add active neighbors
59  }
60 }
61 
62 
63 
65 {
66  std::set<const Elem *> new_neighbors;
67 
68  this->find_face_neighbors(new_neighbors);
69 
70  this->insert(new_neighbors.begin(), new_neighbors.end());
71 }
72 
73 
74 
76 {
77  std::set<const Elem *> new_neighbors;
78 
79  this->find_face_neighbors(new_neighbors);
80 
81  // if neighbor belongs to this processor then add it to the patch
82  for (const auto & neighbor : new_neighbors)
83  if (neighbor->processor_id() == _my_procid)
84  this->insert (neighbor);
85 }
86 
87 
88 
90 {
91  std::set<const Elem *> new_neighbors;
92 
93  this->find_face_neighbors(new_neighbors);
94 
95  for (const auto & neighbor : new_neighbors)
96  if (neighbor->is_semilocal(_my_procid))
97  this->insert (neighbor);
98 }
99 
100 
101 
102 void Patch::find_point_neighbors(std::set<const Elem *> & new_neighbors)
103 {
104  // Loop over all the elements in the patch
105  for (const auto & elem : *this)
106  {
107  std::set<const Elem *> elem_point_neighbors;
108 
109  elem->find_point_neighbors(elem_point_neighbors);
110 
111  new_neighbors.insert(elem_point_neighbors.begin(),
112  elem_point_neighbors.end());
113  }
114 }
115 
116 
117 
119 {
120  std::set<const Elem *> new_neighbors;
121 
122  this->find_point_neighbors(new_neighbors);
123 
124  this->insert(new_neighbors.begin(), new_neighbors.end());
125 }
126 
127 
128 
130 {
131  std::set<const Elem *> new_neighbors;
132 
133  this->find_point_neighbors(new_neighbors);
134 
135  // if neighbor belongs to this processor then add it to the patch
136  for (const auto & neighbor : new_neighbors)
137  if (neighbor->processor_id() == _my_procid)
138  this->insert (neighbor);
139 }
140 
141 
142 
144 {
145  std::set<const Elem *> new_neighbors;
146 
147  this->find_point_neighbors(new_neighbors);
148 
149  for (const auto & neighbor : new_neighbors)
150  if (neighbor->is_semilocal(_my_procid))
151  this->insert (neighbor);
152 }
153 
154 
155 
157  const unsigned int target_patch_size,
158  PMF patchtype)
159 {
160 
161  // Make sure we are building a patch for an active element.
162  libmesh_assert(e0);
163  libmesh_assert (e0->active());
164  // Make sure we are either starting with a local element or
165  // requesting a nonlocal patch
166  libmesh_assert ((patchtype != &Patch::add_local_face_neighbors &&
167  patchtype != &Patch::add_local_point_neighbors) ||
168  e0->processor_id() == _my_procid);
169 
170  // First clear the current set, then add the element of interest.
171  this->clear();
172  this->insert (e0);
173 
174  // Repeatedly add the neighbors of the elements in the patch until
175  // the target patch size is met
176  while (this->size() < target_patch_size)
177  {
178  // It is possible that the target patch size is larger than the number
179  // of elements that can be added to the patch. Since we don't
180  // have access to the Mesh object here, the only way we can
181  // detect this case is by detecting a "stagnant patch," i.e. a
182  // patch whose size does not increase after adding face neighbors
183  const std::size_t old_patch_size = this->size();
184 
185  // We profile the patch-extending functions separately
186  (this->*patchtype)();
187 
188  // Check for a "stagnant" patch
189  if (this->size() == old_patch_size)
190  {
191  libmesh_do_once(libMesh::err <<
192  "WARNING: stagnant patch of " << this->size() << " elements."
193  << std::endl <<
194  "Does the target patch size exceed the number of local elements?"
195  << std::endl;
196  libmesh_here(););
197  break;
198  }
199  } // end while loop
200 
201 
202  // make sure all the elements in the patch are active and local
203  // if we are in debug mode
204 #ifdef DEBUG
205  for (const auto & elem : *this)
206  {
207  libmesh_assert (elem->active());
208  if ((patchtype == &Patch::add_local_face_neighbors ||
209  patchtype == &Patch::add_local_point_neighbors))
210  libmesh_assert_equal_to (elem->processor_id(), _my_procid);
211  }
212 #endif
213 
214 }
215 
216 } // namespace libMesh
void add_local_point_neighbors()
Definition: patch.C:129
The base class for all geometric element types.
Definition: elem.h:100
void build_around_element(const Elem *elem, const unsigned int target_patch_size=10, PMF patchtype=&Patch::add_local_face_neighbors)
Definition: patch.C:156
void find_face_neighbors(std::set< const Elem *> &neighbor_set)
Definition: patch.C:37
void add_point_neighbors()
Definition: patch.C:118
void add_semilocal_point_neighbors()
Definition: patch.C:143
OStreamProxy err(std::cerr)
void add_local_face_neighbors()
Definition: patch.C:75
void find_point_neighbors(std::set< const Elem *> &neighbor_set)
Definition: patch.C:102
void add_face_neighbors()
Definition: patch.C:64
void add_semilocal_face_neighbors()
Definition: patch.C:89
const processor_id_type _my_procid
Definition: patch.h:131
bool active() const
Definition: elem.h:2390
processor_id_type processor_id() const
Definition: dof_object.h:717