Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
default_coupling.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 
20 // Local Includes
21 #include "libmesh/default_coupling.h"
22 #include "libmesh/coupling_matrix.h"
23 #include "libmesh/elem.h"
24 #include "libmesh/periodic_boundaries.h"
25 #include "libmesh/remote_elem.h"
26 #include "libmesh/int_range.h"
27 #include "libmesh/libmesh_logging.h"
28 
29 // C++ Includes
30 #include <unordered_set>
31 
32 namespace libMesh
33 {
34 
36 {
37  // We used to treat an empty 0x0 _dof_coupling matrix as if it
38  // were an NxN all-ones matrix. We'd like to stop supporting this
39  // behavior, but for now we'll just warn about it, while supporting
40  // it via the preferred mechanism: a nullptr _dof_coupling
41  // matrix pointer is interpreted as a full coupling matrix.
42  if (dof_coupling && dof_coupling->empty())
43  {
44  libmesh_deprecated();
45  _dof_coupling = nullptr;
46  }
47  else
48  _dof_coupling = dof_coupling;
49 }
50 
51 
52 
54 {
55  // Unless we have periodic boundary conditions, we don't need
56  // anything precomputed.
57 #ifdef LIBMESH_ENABLE_PERIODIC
58  if (!_periodic_bcs || _periodic_bcs->empty())
59  return;
60 #endif
61 
62  // If we do have periodic boundary conditions, we'll need a master
63  // point locator, so we'd better have a mesh to build it on.
65 
66  // Make sure an up-to-date master point locator has been
67  // constructed; we'll need to grab sub-locators soon.
69 }
70 
71 
72 
73 void DefaultCoupling::operator()
74  (const MeshBase::const_element_iterator & range_begin,
75  const MeshBase::const_element_iterator & range_end,
77  map_type & coupled_elements)
78 {
79  LOG_SCOPE("operator()", "DefaultCoupling");
80 
81  // Let us not do assertion at this moment for API upgrade.
82  // There is a functor inside of ElementSideNeighborLayers.
83  // We can not set mesh for that functor because there is no handle
84  // in libmesh. We need to override set_mesh in moose for setting a mesh for the functor.
85  // The set_mesh overridden will not happen until the current change gets in.
86  //libmesh_assert(_mesh);
87 
88 #ifdef LIBMESH_ENABLE_PERIODIC
89  bool check_periodic_bcs =
90  (_periodic_bcs && !_periodic_bcs->empty());
91 
92  std::unique_ptr<PointLocatorBase> point_locator;
93  if (check_periodic_bcs)
94  {
95  libmesh_assert(_mesh);
96  point_locator = _mesh->sub_point_locator();
97  }
98 #endif
99 
100  if (!this->_n_levels)
101  {
102  for (const auto & elem : as_range(range_begin, range_end))
103  {
104  //libmesh_assert(_mesh->query_elem_ptr(elem->id()) ==elem);
105  if (elem->processor_id() != p)
106  coupled_elements.emplace(elem, _dof_coupling);
107  }
108  return;
109  }
110 
111  typedef std::unordered_set<const Elem*> set_type;
112  set_type next_elements_to_check(range_begin, range_end);
113  set_type elements_to_check;
114  set_type elements_checked;
115 
116  for (unsigned int i=0; i != this->_n_levels; ++i)
117  {
118  elements_to_check.swap(next_elements_to_check);
119  next_elements_to_check.clear();
120  elements_checked.insert(elements_to_check.begin(), elements_to_check.end());
121 
122  for (const auto & elem : elements_to_check)
123  {
124  std::vector<const Elem *> active_neighbors;
125 
126  //libmesh_assert(_mesh->query_elem_ptr(elem->id()) ==elem);
127 
128  if (elem->processor_id() != p)
129  coupled_elements.emplace(elem, _dof_coupling);
130 
131  for (auto s : elem->side_index_range())
132  {
133  const Elem * neigh = elem->neighbor_ptr(s);
134 
135 #ifdef LIBMESH_ENABLE_PERIODIC
136  // We might still have a periodic neighbor here
137  if (!neigh && check_periodic_bcs)
138  {
139  libmesh_assert(_mesh);
140 
141  neigh = elem->topological_neighbor
142  (s, *_mesh, *point_locator, _periodic_bcs);
143  }
144 #endif
145 
146  // With no regular *or* periodic neighbors we have nothing
147  // to do. *Or* Mesh ghosting might ask us about what we want to
148  // distribute along with non-local elements, and those
149  // non-local elements might have remote neighbors, and
150  // if they do then we can't say anything about them.
151  if (!neigh || neigh == remote_elem)
152  continue;
153 
154  // With any kind of neighbor, we need to couple to all the
155  // active descendants on our side.
156 #ifdef LIBMESH_ENABLE_AMR
157  if (neigh == elem->neighbor_ptr(s))
158  neigh->active_family_tree_by_neighbor(active_neighbors,elem);
159 # ifdef LIBMESH_ENABLE_PERIODIC
160  else
162  (active_neighbors,elem,*_mesh,*point_locator,_periodic_bcs);
163 # endif
164 #else
165  active_neighbors.clear();
166  active_neighbors.push_back(neigh);
167 #endif
168 
169  for (const auto & neighbor : active_neighbors)
170  {
171  if (!elements_checked.count(neighbor))
172  next_elements_to_check.insert(neighbor);
173 
174  if (neighbor->processor_id() != p)
175  coupled_elements.emplace(neighbor, _dof_coupling);
176  }
177  }
178  }
179  }
180 }
181 
182 
183 } // 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:2150
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1620
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1184
The definition of the const_element_iterator struct.
Definition: mesh_base.h:2180
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
virtual void mesh_reinit() override
If we have periodic boundaries, then we&#39;ll need the mesh to have an updated point locator whenever we...
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
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
libmesh_assert(ctx)
void set_dof_coupling(const CouplingMatrix *dof_coupling)
void active_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to neighbor...
Definition: elem.C:2132
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2520
const CouplingMatrix * _dof_coupling
const PeriodicBoundaries * _periodic_bcs
This class defines a coupling matrix.
const RemoteElem * remote_elem
Definition: remote_elem.C:57