default_coupling.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 
20 // Local Includes
23 #include "libmesh/elem.h"
25 #include "libmesh/remote_elem.h"
26 #include "libmesh/int_range.h"
27 
28 // C++ Includes
29 #include <unordered_set>
30 
31 namespace libMesh
32 {
33 
35 {
36  // We used to treat an empty 0x0 _dof_coupling matrix as if it
37  // were an NxN all-ones matrix. We'd like to stop supporting this
38  // behavior, but for now we'll just warn about it, while supporting
39  // it via the preferred mechanism: a nullptr _dof_coupling
40  // matrix pointer is interpreted as a full coupling matrix.
41  if (dof_coupling && dof_coupling->empty())
42  {
43  libmesh_deprecated();
44  _dof_coupling = nullptr;
45  }
46  else
47  _dof_coupling = dof_coupling;
48 }
49 
50 
51 
53 {
54  // Unless we have periodic boundary conditions, we don't need
55  // anything precomputed.
56 #ifdef LIBMESH_ENABLE_PERIODIC
57  if (!_periodic_bcs || _periodic_bcs->empty())
58  return;
59 #endif
60 
61  // If we do have periodic boundary conditions, we'll need a master
62  // point locator, so we'd better have a mesh to build it on.
63  libmesh_assert(_mesh);
64 
65  // Make sure an up-to-date master point locator has been
66  // constructed; we'll need to grab sub-locators soon.
68 }
69 
70 
71 
72 void DefaultCoupling::operator()
73  (const MeshBase::const_element_iterator & range_begin,
74  const MeshBase::const_element_iterator & range_end,
76  map_type & coupled_elements)
77 {
78  LOG_SCOPE("operator()", "DefaultCoupling");
79 
80 #ifdef LIBMESH_ENABLE_PERIODIC
81  bool check_periodic_bcs =
82  (_periodic_bcs && !_periodic_bcs->empty());
83 
84  std::unique_ptr<PointLocatorBase> point_locator;
85  if (check_periodic_bcs)
86  {
87  libmesh_assert(_mesh);
88  point_locator = _mesh->sub_point_locator();
89  }
90 #endif
91 
92  if (!this->_n_levels)
93  {
94  for (const auto & elem : as_range(range_begin, range_end))
95  if (elem->processor_id() != p)
96  coupled_elements.insert (std::make_pair(elem,_dof_coupling));
97  return;
98  }
99 
100  typedef std::unordered_set<const Elem*> set_type;
101  set_type next_elements_to_check(range_begin, range_end);
102  set_type elements_to_check;
103  set_type elements_checked;
104 
105  for (unsigned int i=0; i != this->_n_levels; ++i)
106  {
107  elements_to_check.swap(next_elements_to_check);
108  next_elements_to_check.clear();
109  elements_checked.insert(elements_to_check.begin(), elements_to_check.end());
110 
111  for (const auto & elem : elements_to_check)
112  {
113  std::vector<const Elem *> active_neighbors;
114 
115  if (elem->processor_id() != p)
116  coupled_elements.insert (std::make_pair(elem,_dof_coupling));
117 
118  for (auto s : elem->side_index_range())
119  {
120  const Elem * neigh = elem->neighbor_ptr(s);
121 
122  // If we have a neighbor here
123  if (neigh)
124  {
125  // Mesh ghosting might ask us about what we want to
126  // distribute along with non-local elements, and those
127  // non-local elements might have remote neighbors, and
128  // if they do then we can't say anything about them.
129  if (neigh == remote_elem)
130  continue;
131  }
132 #ifdef LIBMESH_ENABLE_PERIODIC
133  // We might still have a periodic neighbor here
134  else if (check_periodic_bcs)
135  {
136  libmesh_assert(_mesh);
137 
138  neigh = elem->topological_neighbor
139  (s, *_mesh, *point_locator, _periodic_bcs);
140  }
141 #endif
142 
143  // With no regular *or* periodic neighbors we have nothing
144  // to do.
145  if (!neigh)
146  continue;
147 
148  // With any kind of neighbor, we need to couple to all the
149  // active descendants on our side.
150 #ifdef LIBMESH_ENABLE_AMR
151  if (neigh == elem->neighbor_ptr(s))
152  neigh->active_family_tree_by_neighbor(active_neighbors,elem);
153 # ifdef LIBMESH_ENABLE_PERIODIC
154  else
156  (active_neighbors,elem,*_mesh,*point_locator,_periodic_bcs);
157 # endif
158 #else
159  active_neighbors.clear();
160  active_neighbors.push_back(neigh);
161 #endif
162 
163  for (const auto & neighbor : active_neighbors)
164  {
165  if (!elements_checked.count(neighbor))
166  next_elements_to_check.insert(neighbor);
167 
168  if (neighbor->processor_id() != p)
169  coupled_elements.insert
170  (std::make_pair(neighbor, _dof_coupling));
171  }
172  }
173  }
174  }
175 }
176 
177 
178 } // namespace libMesh
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:496
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:920
The base class for all geometric element types.
Definition: elem.h:100
uint8_t processor_id_type
Definition: id_types.h:99
virtual void mesh_reinit() override
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, const bool reset=true) const
Definition: elem.C:1795
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
void set_dof_coupling(const CouplingMatrix *dof_coupling)
void active_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const bool reset=true) const
Definition: elem.C:1837
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2050
const CouplingMatrix * _dof_coupling
const PeriodicBoundaries * _periodic_bcs
Defines the coupling between variables of a System.
const RemoteElem * remote_elem
Definition: remote_elem.C:57