libMesh
Loading...
Searching...
No Matches
patch.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
30namespace libMesh
31{
32
33
34
35//-----------------------------------------------------------------
36// Patch implementations
37void 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
102void 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
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 ||
210 libmesh_assert_equal_to (elem->processor_id(), _my_procid);
211 }
212#endif
213
214}
215
216} // namespace libMesh
processor_id_type processor_id() const
Definition dof_object.h:881
This is the base class from which all geometric element types are derived.
Definition elem.h:96
bool active() const
Definition elem.h:2958
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:118
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:143
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:102
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:75
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:129
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:64
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:156
const processor_id_type _my_procid
Definition patch.h:131
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:89
The libMesh namespace provides an interface to certain functionality in the library.
OStreamProxy err
libmesh_assert(ctx)