ghost_point_neighbors.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 // Local Includes
21 
22 #include "libmesh/elem.h"
23 #include "libmesh/remote_elem.h"
24 
25 // C++ Includes
26 #include <unordered_set>
27 #include <utility> // std::make_pair
28 
29 namespace libMesh
30 {
31 
32 void GhostPointNeighbors::operator()
33  (const MeshBase::const_element_iterator & range_begin,
34  const MeshBase::const_element_iterator & range_end,
36  GhostPointNeighbors::map_type & coupled_elements)
37 {
38  // Using the connected_nodes set rather than point_neighbors() gives
39  // us correct results even in corner cases, such as where two
40  // elements meet only at a corner. ;-)
41 
42  std::unordered_set<const Node *> connected_nodes;
43 
44  // Links between boundary and interior elements on mixed
45  // dimensional meshes also give us correct ghosting in this way.
46  std::unordered_set<const Elem *> interior_parents;
47 
48  // We also preserve neighbors and their neighboring children for
49  // active local elements - in most cases this is redundant with the
50  // node check, but for non-conforming Tet4 meshes and
51  // non-level-one-conforming 2D+3D meshes it is possible for an
52  // element and its coarse neighbor to not share any vertices.
53  //
54  // We also preserve interior parents for active pid elements
55 
56 
57  // This code is just for geometric coupling, so we use a null
58  // CouplingMatrix pointer. We'll declare that here so as to avoid
59  // confusing the insert() calls later.
60  CouplingMatrix * nullcm = nullptr;
61 
62  for (const auto & elem : as_range(range_begin, range_end))
63  {
64  if (elem->processor_id() != p)
65  coupled_elements.insert (std::make_pair(elem,nullcm));
66 
67  for (auto neigh : elem->neighbor_ptr_range())
68  {
69  if (neigh && neigh != remote_elem)
70  {
71 #ifdef LIBMESH_ENABLE_AMR
72  if (!neigh->active())
73  {
74  std::vector<const Elem*> family;
75  neigh->active_family_tree_by_neighbor(family, elem);
76 
77  for (const Elem * f : family)
78  if (f->processor_id() != p)
79  coupled_elements.insert
80  (std::make_pair(f, nullcm));
81  }
82  else
83 #endif
84  if (neigh->processor_id() != p)
85  coupled_elements.insert
86  (std::make_pair(neigh, nullcm));
87  }
88  }
89 
90  // It is possible that a refined boundary element will not
91  // touch any nodes of its interior_parent, in TRI3/TET4 and in
92  // non-level-one rule cases. So we can't just rely on node
93  // connections to preserve interior_parent(). However, trying
94  // to preserve interior_parent() manually only works if it's on
95  // the same Mesh, which is *not* guaranteed! So we'll
96  // double-check later to make sure our interior parents are in
97  // the mesh before we connect them.
98  if (elem->dim() < LIBMESH_DIM &&
99  elem->interior_parent() &&
100  elem->interior_parent()->processor_id() != p)
101  interior_parents.insert (elem->interior_parent());
102 
103  // Add nodes connected to active local elements
104  for (auto n : elem->node_index_range())
105  connected_nodes.insert (elem->node_ptr(n));
106  }
107 
108  // Connect any interior_parents who are really in our mesh
109  for (const auto & elem : _mesh.element_ptr_range())
110  {
111  std::unordered_set<const Elem *>::iterator ip_it =
112  interior_parents.find(elem);
113 
114  if (ip_it != interior_parents.end())
115  {
116  coupled_elements.insert
117  (std::make_pair(elem, nullcm));
118 
119  // Shrink the set ASAP to speed up subsequent searches
120  interior_parents.erase(ip_it);
121  }
122  }
123 
124  // Connect any active elements which are connected to our range's
125  // elements' nodes by addin elements connected to nodes on active
126  // local elements.
127  for (const auto & elem : _mesh.active_element_ptr_range())
128  if (elem->processor_id() != p)
129  for (auto & n : elem->node_ref_range())
130  if (connected_nodes.count(&n))
131  coupled_elements.insert(std::make_pair(elem, nullcm));
132 }
133 
134 } // namespace libMesh
The base class for all geometric element types.
Definition: elem.h:100
uint8_t processor_id_type
Definition: id_types.h:99
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
Defines the coupling between variables of a System.
const RemoteElem * remote_elem
Definition: remote_elem.C:57