libMesh
Loading...
Searching...
No Matches
default_coupling.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
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
32namespace 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
73void 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
This class defines a coupling matrix.
virtual void mesh_reinit() override
If we have periodic boundaries, then we'll need the mesh to have an updated point locator whenever we...
const PeriodicBoundaries * _periodic_bcs
void set_dof_coupling(const CouplingMatrix *dof_coupling)
const CouplingMatrix * _dof_coupling
This is the base class from which all geometric element types are derived.
Definition elem.h:96
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
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:2288
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition elem.C:1287
const Elem * neighbor_ptr(unsigned int i) const
Definition elem.h:2615
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?
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition mesh_base.C:1833
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
libmesh_assert(ctx)
const RemoteElem * remote_elem
Definition remote_elem.C:57
uint8_t processor_id_type
Definition id_types.h:104
The definition of the const_element_iterator struct.
Definition mesh_base.h:2556