17#include "libmesh/elem.h"
18#include "libmesh/mesh_base.h"
19#include "libmesh/boundary_info.h"
24AugmentSparsityOnInterface::validParams()
28 "The name of the primary boundary sideset.");
30 "The name of the secondary boundary sideset.");
32 "The name of the primary lower dimensional subdomain.");
34 "The name of the secondary lower dimensional subdomain.");
36 "ghost_point_neighbors",
38 "Whether we should ghost point neighbors of secondary lower-dimensional elements and "
39 "also their mortar interface couples for applications such as mortar nodal auxiliary "
42 "ghost_higher_d_neighbors",
44 "Whether we should ghost higher-dimensional neighbors. This is necessary when we are doing "
45 "second order mortar with finite volume primal variables, because in order for the method to "
46 "be second order we must use cell gradients, which couples in the neighbor cells.");
54 params.
set<
bool>(
"attach_geometric_early") =
false;
60 _primary_boundary_name(getParam<BoundaryName>(
"primary_boundary")),
61 _secondary_boundary_name(getParam<BoundaryName>(
"secondary_boundary")),
62 _primary_subdomain_name(getParam<SubdomainName>(
"primary_subdomain")),
63 _secondary_subdomain_name(getParam<SubdomainName>(
"secondary_subdomain")),
65 _ghost_point_neighbors(getParam<bool>(
"ghost_point_neighbors")),
66 _ghost_higher_d_neighbors(getParam<bool>(
"ghost_higher_d_neighbors"))
72 _primary_boundary_name(other._primary_boundary_name),
73 _secondary_boundary_name(other._secondary_boundary_name),
74 _primary_subdomain_name(other._primary_subdomain_name),
75 _secondary_subdomain_name(other._secondary_subdomain_name),
76 _is_coupling_functor(other._is_coupling_functor),
77 _ghost_point_neighbors(other._ghost_point_neighbors),
78 _ghost_higher_d_neighbors(other._ghost_higher_d_neighbors)
83AugmentSparsityOnInterface::internalInitWithMesh(
const MeshBase &)
88AugmentSparsityOnInterface::getInfo()
const
90 std::ostringstream oss;
91 oss <<
"AugmentSparsityOnInterface";
96AugmentSparsityOnInterface::ghostMortarInterfaceCouplings(
97 const processor_id_type p,
98 const Elem *
const elem,
99 map_type & coupled_elements,
104 auto find_it = mic.find(elem->id());
105 if (find_it == mic.end())
108 const auto & coupled_set = find_it->second;
110 for (
const auto coupled_elem_id : coupled_set)
112 const Elem * coupled_elem =
_mesh->elem_ptr(coupled_elem_id);
113 mooseAssert(coupled_elem,
114 "The coupled element with id " << coupled_elem_id <<
" doesn't exist!");
116 if (coupled_elem->processor_id() != p)
117 coupled_elements.emplace(coupled_elem, _null_mat);
122AugmentSparsityOnInterface::ghostLowerDSecondaryElemPointNeighbors(
123 const processor_id_type p,
124 const Elem *
const query_elem,
125 map_type & coupled_elements,
145 std::set<dof_id_type> secondary_lower_elems_handled;
146 const BoundaryInfo & binfo =
_mesh->get_boundary_info();
147 for (
auto side : query_elem->side_index_range())
149 if (!binfo.has_boundary_id(query_elem, side, secondary_boundary_id))
155 auto find_it = mic.find(query_elem->id());
156 if (find_it == mic.end())
159 const auto & coupled_set = find_it->second;
160 for (
const auto coupled_elem_id : coupled_set)
162 auto *
const coupled_elem =
_mesh->elem_ptr(coupled_elem_id);
164 if (coupled_elem->subdomain_id() != secondary_subdomain_id)
169 mooseAssert(coupled_elem->dim() == query_elem->dim(),
"These should be matching dim");
173 auto insert_pr = secondary_lower_elems_handled.insert(coupled_elem_id);
176 if (!insert_pr.second)
183 std::set<const Elem *> secondary_lower_elem_point_neighbors;
184 coupled_elem->find_point_neighbors(secondary_lower_elem_point_neighbors);
186 for (
const Elem *
const neigh : secondary_lower_elem_point_neighbors)
188 if (neigh->processor_id() != p)
189 coupled_elements.emplace(neigh, _null_mat);
191 ghostMortarInterfaceCouplings(p, neigh, coupled_elements, amg);
203AugmentSparsityOnInterface::ghostHigherDNeighbors(
const processor_id_type p,
204 const Elem *
const query_elem,
205 map_type & coupled_elements,
215 if (query_elem->subdomain_id() != secondary_subdomain_id)
218 const BoundaryInfo & binfo =
_mesh->get_boundary_info();
219 const auto which_side = query_elem->interior_parent()->which_side_am_i(query_elem);
220 if (!binfo.has_boundary_id(query_elem->interior_parent(), which_side, secondary_boundary_id))
224 auto find_it = mic.find(query_elem->id());
225 if (find_it == mic.end())
229 const auto & lower_d_coupled_set = find_it->second;
230 for (
const auto coupled_elem_id : lower_d_coupled_set)
232 auto *
const coupled_elem =
_mesh->elem_ptr(coupled_elem_id);
233 if (coupled_elem->dim() == query_elem->dim())
237 std::vector<const Elem *> active_neighbors;
239 for (
auto s : coupled_elem->side_index_range())
241 const Elem *
const neigh = coupled_elem->neighbor_ptr(s);
243 if (!neigh || neigh == remote_elem)
248 neigh->active_family_tree_by_neighbor(active_neighbors, coupled_elem);
250 for (
const auto & neighbor : active_neighbors)
254 neighbor->subdomain_id() != secondary_subdomain_id,
255 "Ensure that we aren't missing potential erasures from the secondary-to-msms map");
256 coupled_elements.emplace(neighbor, _null_mat);
264 const MeshBase::const_element_iterator & range_end,
265 const processor_id_type p,
266 map_type & coupled_elements)
272 const auto primary_boundary_id = generating_mesh
275 const auto secondary_boundary_id = generating_mesh
278 const auto primary_subdomain_id = generating_mesh
281 const auto secondary_subdomain_id = generating_mesh
287 std::make_pair(primary_boundary_id, secondary_boundary_id),
288 std::make_pair(primary_subdomain_id, secondary_subdomain_id),
301 for (
const Elem *
const elem :
_mesh->active_element_ptr_range())
308 if (elem->on_boundary())
309 coupled_elements.insert(std::make_pair(elem, _null_mat));
310 else if (
const Elem *
const ip = elem->interior_parent())
312 if (ip->on_boundary())
313 coupled_elements.insert(std::make_pair(elem, _null_mat));
322 "Primary boundary id should exist by now.");
324 "Secondary boundary id should exist by now.");
326 "Primary subdomain id should exist by now.");
328 "Secondary subdomain id should exist by now.");
331 const BoundaryInfo & binfo =
_mesh->get_boundary_info();
333 for (
auto side : elem->side_index_range())
335 (binfo.has_boundary_id(elem, side, primary_boundary_id) ||
336 binfo.has_boundary_id(elem, side, secondary_boundary_id)))
337 coupled_elements.insert(
std::make_pair(elem, _null_mat));
340 if ((elem->processor_id() != p) && (elem->subdomain_id() == primary_subdomain_id ||
341 elem->subdomain_id() == secondary_subdomain_id))
343 coupled_elements.insert(std::make_pair(elem, _null_mat));
347 const Elem *
const ip = elem->interior_parent();
349 "We should have set interior parents for all of our lower-dimensional mortar "
351 auto side = ip->which_side_am_i(elem);
352 auto bnd_id = elem->subdomain_id() == primary_subdomain_id ? primary_boundary_id
353 : secondary_boundary_id;
354 mooseAssert(
_mesh->get_boundary_info().has_boundary_id(ip, side, bnd_id),
355 "The interior parent for the lower-dimensional element does not lie on the "
366 for (
const Elem *
const elem :
as_range(range_begin, range_end))
368 ghostMortarInterfaceCouplings(p, elem, coupled_elements, *amg);
370 if (_ghost_point_neighbors)
371 ghostLowerDSecondaryElemPointNeighbors(
372 p, elem, coupled_elements, secondary_boundary_id, secondary_subdomain_id, *amg);
373 if (_ghost_higher_d_neighbors)
374 ghostHigherDNeighbors(
375 p, elem, coupled_elements, secondary_boundary_id, secondary_subdomain_id, *amg);
385 if (_primary_boundary_name == asoi->_primary_boundary_name &&
386 _secondary_boundary_name == asoi->_secondary_boundary_name &&
387 _primary_subdomain_name == asoi->_primary_subdomain_name &&
388 _secondary_subdomain_name == asoi->_secondary_subdomain_name &&
389 _ghost_point_neighbors >= asoi->_ghost_point_neighbors &&
390 _ghost_higher_d_neighbors >= asoi->_ghost_higher_d_neighbors &&
baseGreaterEqual(*asoi))
396std::unique_ptr<GhostingFunctor>
registerMooseObject("MooseApp", AugmentSparsityOnInterface)
boundary_id_type BoundaryID
subdomain_id_type SubdomainID
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
AugmentSparsityOnInterface(MeshBase &mesh, boundary_id_type crack_boundary_lower, boundary_id_type crack_boundary_upper)
virtual std::unique_ptr< GhostingFunctor > clone() const override
virtual void operator()(const MeshBase::const_element_iterator &range_begin, const MeshBase::const_element_iterator &range_end, processor_id_type p, map_type &coupled_elements) override
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
const std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > & mortarInterfaceCoupling() const
FEProblemBase & feProblem()
Return a reference to this Executioner's FEProblemBase instance.
const AutomaticMortarGeneration & getMortarInterface(const std::pair< BoundaryID, BoundaryID > &primary_secondary_boundary_pair, const std::pair< SubdomainID, SubdomainID > &primary_secondary_subdomain_pair, bool on_displaced) const
Return the undisplaced or displaced mortar generation object associated with the provided boundaries ...
std::unique_ptr< T > copyConstruct(const T &object)
Copy constructs the object object.
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
const MeshBase * getMeshPtr() const
SubdomainID getSubdomainID(const SubdomainName &subdomain_name) const
Get the associated subdomain ID for the subdomain name.
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
MooseApp & _app
The MOOSE application this is associated with.
RelationshipManagers are used for describing what kinds of non-local resources are needed for an obje...
const bool _use_displaced_mesh
Which system this should go to (undisplaced or displaced)
virtual bool baseGreaterEqual(const RelationshipManager &rhs) const
Whether the base class provides more or the same amount and type of ghosting as the rhs.
static InputParameters validParams()
MooseMesh * _moose_mesh
Pointer to the MooseMesh object.
processor_id_type processor_id() const
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
RelationshipManagerType
Main types of Relationship Managers.
const BoundaryID INVALID_BOUNDARY_ID
const SubdomainID INVALID_BLOCK_ID
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)