Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
ghost_point_neighbors.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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  bool check_periodic_bcs =
47  (_periodic_bcs && !_periodic_bcs->empty());
48 
49  std::unique_ptr<PointLocatorBase> point_locator;
50  if (check_periodic_bcs)
51  point_locator = _mesh->sub_point_locator();
52 
53  std::set<const Elem *> periodic_elems_examined;
54  const BoundaryInfo & binfo = _mesh->get_boundary_info();
55  std::vector<boundary_id_type> appn_bcids;
56  std::vector<const Elem *> active_periodic_neighbors;
57 #endif
58 
59  // Using a connected_nodes set rather than point_neighbors() would
60  // give us correct results even in corner cases, such as where two
61  // elements meet only at a corner. ;-)
62  //
63  // std::unordered_set<const Node *> connected_nodes;
64  //
65  // Unfortunately, it's not a *fast* enough test to use on a
66  // ReplicatedMesh (where it's O(Nprocs) times slower), or as a
67  // coupling functor (where it's O(Nelem/Nprocs) times slower), or as
68  // a coupling functor on a ReplicatedMesh (where you might as well
69  // just give up now)
70 
71  // Links between boundary and interior elements on mixed
72  // dimensional meshes also give us correct ghosting in this way.
73  std::unordered_set<const Elem *> interior_parents;
74 
75  // We also preserve neighbors and their neighboring children for
76  // active local elements - in most cases this is redundant with the
77  // node check, but for non-conforming Tet4 meshes and
78  // non-level-one-conforming 2D+3D meshes it is possible for an
79  // element and its coarse neighbor to not share any vertices.
80  //
81  // We also preserve interior parents for active pid elements
82 
83 
84  // This code is just for geometric coupling, so we use a null
85  // CouplingMatrix pointer. We'll declare that here so as to avoid
86  // confusing the insert() calls later.
87  CouplingMatrix * nullcm = nullptr;
88 
89  for (const auto & elem : as_range(range_begin, range_end))
90  {
91  libmesh_assert(_mesh->query_elem_ptr(elem->id()) == elem);
92 
93  if (elem->processor_id() != p)
94  coupled_elements.emplace(elem, nullcm);
95 
96  std::set<const Elem *> elem_point_neighbors;
97  elem->find_point_neighbors(elem_point_neighbors);
98 
99  for (const auto & neigh : elem_point_neighbors)
100  if (neigh->processor_id() != p)
101  coupled_elements.emplace(neigh, nullcm);
102 
103  // An interior_parent isn't on the same manifold so won't be
104  // found as a point neighbor, and it may not share nodes so we
105  // can't use a connected_nodes test.
106  //
107  // Trying to preserve interior_parent() only works if it's on
108  // the same Mesh, which is *not* guaranteed! So we'll
109  // double-check.
110  const Elem * ip = elem->interior_parent();
111  if (ip && ip->processor_id() != p &&
112  _mesh->query_elem_ptr(ip->id()) == ip)
113  coupled_elements.emplace(ip, nullcm);
114 
115 #ifdef LIBMESH_ENABLE_PERIODIC
116  if (check_periodic_bcs)
117  {
118  for (const auto s : elem->side_index_range())
119  {
120  if (elem->neighbor_ptr(s))
121  continue;
122 
123  const Elem * const equal_level_periodic_neigh = elem->topological_neighbor
124  (s, *_mesh, *point_locator, _periodic_bcs);
125 
126  if (!equal_level_periodic_neigh || equal_level_periodic_neigh == remote_elem)
127  continue;
128 
129 #ifdef LIBMESH_ENABLE_AMR
130  equal_level_periodic_neigh->active_family_tree_by_topological_neighbor(
131  active_periodic_neighbors,
132  elem,
133  *_mesh,
134  *point_locator,
135  _periodic_bcs,
136  /*reset=*/true);
137 #else
138  active_periodic_neighbors = { equal_level_periodic_neigh };
139 #endif
140 
141  for (const Elem * const active_periodic_neigh : active_periodic_neighbors)
142  {
143  std::set <const Elem *> active_periodic_point_neighbors;
144 
145  // This fills point neighbors *including*
146  // active_periodic_neigh. The documentation for this method
147  // states that this will return *active* point neighbors
148  active_periodic_neigh->find_point_neighbors(active_periodic_point_neighbors);
149 
150  for (const Elem * const appn : active_periodic_point_neighbors)
151  {
152  // Don't need to ghost RemoteElem or an element we already own or an
153  // element we've already examined
154  if (appn == remote_elem || appn->processor_id() == p ||
155  periodic_elems_examined.count(appn))
156  continue;
157 
158  // We only need to keep point neighbors that are along the periodic boundaries
159  bool on_periodic_boundary = false;
160  for (const auto appn_s : appn->side_index_range())
161  {
162  binfo.boundary_ids(appn, appn_s, appn_bcids);
163  for (const auto appn_bcid : appn_bcids)
164  if (_periodic_bcs->find(appn_bcid) != _periodic_bcs->end())
165  {
166  on_periodic_boundary = true;
167  goto jump;
168  }
169  }
170  jump:
171  if (on_periodic_boundary)
172  coupled_elements.emplace(appn, nullcm);
173 
174  periodic_elems_examined.insert(appn);
175  }
176  }
177  }
178  }
179 #endif // LIBMESH_ENABLE_PERIODIC
180  }
181 }
182 
184 {
185  // Unless we have periodic boundary conditions, we don't need
186  // anything precomputed.
187 #ifdef LIBMESH_ENABLE_PERIODIC
188  if (!_periodic_bcs || _periodic_bcs->empty())
189  return;
190 #endif
191 
192  // If we do have periodic boundary conditions, we'll need a master
193  // point locator, so we'd better have a mesh to build it on.
195 
196  // Make sure an up-to-date master point locator has been
197  // constructed; we'll need to grab sub-locators soon.
199 }
200 
201 } // 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:2279
virtual void mesh_reinit()
GhostingFunctor subclasses which cache data will need to initialize that cache.
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1638
const Elem * interior_parent() const
Definition: elem.C:1186
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1313
The definition of the const_element_iterator struct.
Definition: mesh_base.h:2216
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:828
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:993
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:905
This class defines a coupling matrix.
const RemoteElem * remote_elem
Definition: remote_elem.C:57