Line data Source code
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 : #ifndef LIBMESH_NON_MANIFOLD_COUPLING_H 19 : #define LIBMESH_NON_MANIFOLD_COUPLING_H 20 : 21 : // libMesh Includes 22 : #include "libmesh/ghosting_functor.h" // base class 23 : #include "libmesh/sides_to_elem_map.h" // MeshTools::SidesToElemMap 24 : 25 : // C++ includes 26 : #include <memory> 27 : 28 : namespace libMesh 29 : { 30 : 31 : // Forward declarations 32 : class MeshBase; 33 : 34 : /** 35 : * A GhostingFunctor subclass that uses a SidesToElemMap object to 36 : * determine when Elem DOFs should be ghosted in non-manifold meshes. 37 : * A basic use case for this functor is "truss" meshes where multiple 38 : * 1D elements meet at a single node, but there are also 2D 39 : * generalizations of practical importance, such as "shell stiffener" 40 : * models where three or more quadrilateral elements meet at the same 41 : * side. This functor can be used to avoid DOF ghosting issues related 42 : * to non-manifold meshes which are due to the assumption in libMesh 43 : * that there is at most one neighbor per Elem side. 44 : * Notes on the GhostingFunctor-derived classes: 45 : * 46 : * * For the GhostingFunctor::operator() overrides, the input range 47 : * is saying, "we already need these Elems' DOFs, so what other 48 : * Elems' DOFs do we need?" This is why we always see the following 49 : * logic in the GhostingFunctor::operator() overrides: 50 : * 51 : * if (elem->processor_id() != p) 52 : * coupled_elements.emplace(elem, _dof_coupling); 53 : * 54 : * * The idea is that the "output" range that we are creating should always 55 : * include the entire "non-local" part of the input range. We don't need to 56 : * include members of the input range that are already owned by processor p, 57 : * see e.g. the API docs which say: 58 : * "Don't bother to return any results which already have processor_id p." 59 : * 60 : * \author John W. Peterson 61 : * \date 2024 62 : */ 63 : class NonManifoldGhostingFunctor : public GhostingFunctor 64 : { 65 : public: 66 : /** 67 : * Constructor. Calls base class constructor. 68 : */ 69 : NonManifoldGhostingFunctor(const MeshBase & mesh); 70 : 71 : /** 72 : * Special functions. 73 : * These are all defaulted for now until there is some reason to 74 : * delete/customize one of them. 75 : */ 76 0 : NonManifoldGhostingFunctor (const NonManifoldGhostingFunctor &) = default; 77 : NonManifoldGhostingFunctor (NonManifoldGhostingFunctor &&) = default; 78 : NonManifoldGhostingFunctor & operator= (const NonManifoldGhostingFunctor &) = default; 79 : NonManifoldGhostingFunctor & operator= (NonManifoldGhostingFunctor &&) = default; 80 8 : virtual ~NonManifoldGhostingFunctor() = default; 81 : 82 : /** 83 : * clone() just calls the copy ctor. 84 : */ 85 : virtual std::unique_ptr<GhostingFunctor> clone () const override; 86 : 87 : /** 88 : * If the Mesh changes, we'll need to clear the SidesToElemMap and 89 : * recreate it, since all the neighbor information (standard and 90 : * non-manifold) might have changed. 91 : */ 92 : virtual void mesh_reinit () override; 93 : 94 : /** 95 : * When the Mesh is redistributed, we may need to update the 96 : * information in the SidesToElemMap by removing pointers to 97 : * non-local Elems. Currently calls mesh_reinit(). 98 : */ 99 : virtual void redistribute () override; 100 : 101 : /** 102 : * When remote elements are deleted, we should remove them from the 103 : * information in the SidesToElemMap. Currently calls mesh_reinit(). 104 : */ 105 : virtual void delete_remote_elements() override; 106 : 107 : /** 108 : * For the specified range of active elements, query the SidesToElemMap 109 : * and add _all_ side neighbors to the list of coupled_elements, ignoring 110 : * those on processor p. 111 : */ 112 : virtual void operator() (const MeshBase::const_element_iterator & range_begin, 113 : const MeshBase::const_element_iterator & range_end, 114 : processor_id_type p, 115 : map_type & coupled_elements) override; 116 : private: 117 : 118 : /** 119 : * Quickly-searchable map from (elem, side) pair to list of connected Elems. 120 : */ 121 : MeshTools::SidesToElemMap _stem; 122 : }; 123 : 124 : } // namespace libMesh 125 : 126 : #endif // LIBMESH_NON_MANIFOLD_COUPLING_H