libMesh
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 
34 namespace libMesh
35 {
36 
37 void 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
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
virtual void mesh_reinit()
GhostingFunctor subclasses which cache data will need to initialize that cache.
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
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
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
The definition of the const_element_iterator struct.
Definition: mesh_base.h:2521
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
const PeriodicBoundaries * _periodic_bcs
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.
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?
The libMesh namespace provides an interface to certain functionality in the library.
uint8_t processor_id_type
Definition: id_types.h:104
dof_id_type id() const
Definition: dof_object.h:819
PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs()
Definition: mesh_base.C:2256
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
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
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
libmesh_assert(ctx)
processor_id_type processor_id() const
Definition: dof_object.h:881
This class defines a coupling matrix.
const RemoteElem * remote_elem
Definition: remote_elem.C:57