libMesh
Loading...
Searching...
No Matches
ghost_point_neighbors.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// Local Includes
20#include "libmesh/ghost_point_neighbors.h"
21
22#include "libmesh/elem.h"
23#include "libmesh/remote_elem.h"
24#ifdef LIBMESH_ENABLE_PERIODIC
25#include "libmesh/periodic_boundaries.h"
26#include "libmesh/boundary_info.h"
27#endif
28
29// C++ Includes
30#include <unordered_set>
31#include <set>
32#include <vector>
33
34namespace libMesh
35{
36
37void GhostPointNeighbors::operator()
38 (const MeshBase::const_element_iterator & range_begin,
39 const MeshBase::const_element_iterator & range_end,
41 GhostPointNeighbors::map_type & coupled_elements)
42{
43 libmesh_assert(_mesh);
44
45#ifdef LIBMESH_ENABLE_PERIODIC
46 const bool check_periodic_bcs =
47 (_periodic_bcs && !_periodic_bcs->empty());
48
49 auto * db = _mesh->get_disjoint_neighbor_boundary_pairs();
50 const bool check_disjoint_bcs = (db && !db->empty());
51
52 std::unique_ptr<PointLocatorBase> point_locator;
53 if (check_periodic_bcs || check_disjoint_bcs)
54 point_locator = _mesh->sub_point_locator();
55
56 std::set<const Elem *> periodic_elems_examined;
57 const BoundaryInfo & binfo = _mesh->get_boundary_info();
58 std::vector<boundary_id_type> appn_bcids;
59 std::vector<const Elem *> active_periodic_neighbors;
60#endif
61
62 // Using a connected_nodes set rather than point_neighbors() would
63 // give us correct results even in corner cases, such as where two
64 // elements meet only at a corner. ;-)
65 //
66 // std::unordered_set<const Node *> connected_nodes;
67 //
68 // Unfortunately, it's not a *fast* enough test to use on a
69 // ReplicatedMesh (where it's O(Nprocs) times slower), or as a
70 // coupling functor (where it's O(Nelem/Nprocs) times slower), or as
71 // a coupling functor on a ReplicatedMesh (where you might as well
72 // just give up now)
73
74 // Links between boundary and interior elements on mixed
75 // dimensional meshes also give us correct ghosting in this way.
76 std::unordered_set<const Elem *> interior_parents;
77
78 // We also preserve neighbors and their neighboring children for
79 // active local elements - in most cases this is redundant with the
80 // node check, but for non-conforming Tet4 meshes and
81 // non-level-one-conforming 2D+3D meshes it is possible for an
82 // element and its coarse neighbor to not share any vertices.
83 //
84 // We also preserve interior parents for active pid elements
85
86
87 // This code is just for geometric coupling, so we use a null
88 // CouplingMatrix pointer. We'll declare that here so as to avoid
89 // confusing the insert() calls later.
90 CouplingMatrix * nullcm = nullptr;
91
92 for (const auto & elem : as_range(range_begin, range_end))
93 {
94 libmesh_assert(_mesh->query_elem_ptr(elem->id()) == elem);
95
96 if (elem->processor_id() != p)
97 coupled_elements.emplace(elem, nullcm);
98
99 std::set<const Elem *> elem_point_neighbors;
100 elem->find_point_neighbors(elem_point_neighbors);
101
102 for (const auto & neigh : elem_point_neighbors)
103 if (neigh->processor_id() != p)
104 coupled_elements.emplace(neigh, nullcm);
105
106 // An interior_parent isn't on the same manifold so won't be
107 // found as a point neighbor, and it may not share nodes so we
108 // can't use a connected_nodes test.
109 //
110 // Trying to preserve interior_parent() only works if it's on
111 // the same Mesh, which is *not* guaranteed! So we'll
112 // double-check.
113 const Elem * ip = elem->interior_parent();
114 if (ip && ip->processor_id() != p &&
115 _mesh->query_elem_ptr(ip->id()) == ip)
116 coupled_elements.emplace(ip, nullcm);
117
118#ifdef LIBMESH_ENABLE_PERIODIC
119 if (check_periodic_bcs)
120 {
121 for (const auto s : elem->side_index_range())
122 {
123 if (elem->neighbor_ptr(s))
124 continue;
125
126 const Elem * const equal_level_periodic_neigh = elem->topological_neighbor
127 (s, *_mesh, *point_locator, _periodic_bcs);
128
129 if (!equal_level_periodic_neigh || equal_level_periodic_neigh == remote_elem)
130 continue;
131
132#ifdef LIBMESH_ENABLE_AMR
133 equal_level_periodic_neigh->active_family_tree_by_topological_neighbor(
134 active_periodic_neighbors,
135 elem,
136 *_mesh,
137 *point_locator,
138 _periodic_bcs,
139 /*reset=*/true);
140#else
141 active_periodic_neighbors = { equal_level_periodic_neigh };
142#endif
143
144 for (const Elem * const active_periodic_neigh : active_periodic_neighbors)
145 {
146 std::set <const Elem *> active_periodic_point_neighbors;
147
148 // This fills point neighbors *including*
149 // active_periodic_neigh. The documentation for this method
150 // states that this will return *active* point neighbors
151 active_periodic_neigh->find_point_neighbors(active_periodic_point_neighbors);
152
153 for (const Elem * const appn : active_periodic_point_neighbors)
154 {
155 // Don't need to ghost RemoteElem or an element we already own or an
156 // element we've already examined
157 if (appn == remote_elem || appn->processor_id() == p ||
158 periodic_elems_examined.count(appn))
159 continue;
160
161 // We only need to keep point neighbors that are along the periodic boundaries
162 bool on_periodic_boundary = false;
163 for (const auto appn_s : appn->side_index_range())
164 {
165 binfo.boundary_ids(appn, appn_s, appn_bcids);
166 for (const auto appn_bcid : appn_bcids)
167 if (_periodic_bcs->find(appn_bcid) != _periodic_bcs->end())
168 {
169 on_periodic_boundary = true;
170 goto jump;
171 }
172 }
173 jump:
174 if (on_periodic_boundary)
175 coupled_elements.emplace(appn, nullcm);
176
177 periodic_elems_examined.insert(appn);
178 }
179 }
180 }
181 }
182
183 if (check_disjoint_bcs)
184 {
185 // Also ghost their disjoint neighbors
186 for (auto s : elem->side_index_range())
187 {
188 for (const auto & [id, boundary_ptr] : *db)
189 {
190 if (!_mesh->get_boundary_info().has_boundary_id(elem, s, id))
191 continue;
192
193 unsigned int neigh_side = invalid_uint;
194 const Elem * neigh =
195 db->neighbor(id, *point_locator, elem, s, &neigh_side);
196
197 if (!neigh || neigh == remote_elem)
198 continue;
199
200 if (neigh->processor_id() != p)
201 coupled_elements.emplace(neigh, nullcm);
202 }
203 }
204 }
205
206#endif // LIBMESH_ENABLE_PERIODIC
207 }
208}
209
211{
212 // Unless we have periodic boundary conditions, we don't need
213 // anything precomputed.
214#ifdef LIBMESH_ENABLE_PERIODIC
215 const bool check_periodic_bcs =
216 (_periodic_bcs && !_periodic_bcs->empty());
217
219 const bool check_disjoint_bcs = (db && !db->empty());
220
221 if (!check_periodic_bcs && !check_disjoint_bcs)
222 return;
223#endif
224
225 // If we do have periodic boundary conditions, we'll need a master
226 // point locator, so we'd better have a mesh to build it on.
228
229 // Make sure an up-to-date master point locator has been
230 // constructed; we'll need to grab sub-locators soon.
232}
233
234} // namespace libMesh
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
This class defines a coupling matrix.
processor_id_type processor_id() const
Definition dof_object.h:881
dof_id_type id() const
Definition dof_object.h:819
This is the base class from which all geometric element types are derived.
Definition elem.h:96
void active_family_tree_by_topological_neighbor(std::vector< const Elem * > &family, const Elem *neighbor, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true) const
Same as the active_family_tree_by_neighbor() member, but the neighbor here may be a topological (e....
Definition elem.C:2306
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:967
const Elem * interior_parent() const
Definition elem.C:1160
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition elem.C:1287
const PeriodicBoundaries * _periodic_bcs
std::map< const Elem *, const CouplingMatrix *, CompareDofObjectsByPIDAndThenID > map_type
What elements do we care about and what variables do we care about on each element?
virtual void mesh_reinit()
GhostingFunctor subclasses which cache data will need to initialize that cache.
PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs()
Definition mesh_base.C:2296
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition mesh_base.C:1833
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
libmesh_assert(ctx)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303
const RemoteElem * remote_elem
Definition remote_elem.C:57
uint8_t processor_id_type
Definition id_types.h:104
The definition of the const_element_iterator struct.
Definition mesh_base.h:2556