LCOV - code coverage report
Current view: top level - src/relationshipmanagers - GhostPrimaryFace.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 39a256 Lines: 63 75 84.0 %
Date: 2026-07-14 14:36:17 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "GhostPrimaryFace.h"
      11             : #include "MooseApp.h"
      12             : #include "libmesh/boundary_info.h"
      13             : #include "libmesh/elem.h"
      14             : 
      15             : #include <sstream>
      16             : 
      17             : registerMooseObject("MooseApp", GhostPrimaryFace);
      18             : 
      19             : using namespace libMesh;
      20             : 
      21             : InputParameters
      22        3975 : GhostPrimaryFace::validParams()
      23             : {
      24        3975 :   InputParameters params = RelationshipManager::validParams();
      25       15900 :   params.addRequiredParam<BoundaryName>("primary_boundary",
      26             :                                         "The name of the primary boundary sideset.");
      27       15900 :   params.addRequiredParam<BoundaryName>("secondary_boundary",
      28             :                                         "The name of the secondary boundary sideset.");
      29       15900 :   params.addRequiredParam<bool>("enabled", "Whether this relationship manager should ghost.");
      30        3975 :   params.addClassDescription(
      31             :       "Ghosts full-dimensional elements with sides on the primary boundary to processors that own "
      32             :       "full-dimensional elements with sides on the secondary boundary.");
      33        3975 :   return params;
      34           0 : }
      35             : 
      36         332 : GhostPrimaryFace::GhostPrimaryFace(const InputParameters & params)
      37             :   : RelationshipManager(params),
      38         332 :     _primary_boundary_name(getParam<BoundaryName>("primary_boundary")),
      39         664 :     _secondary_boundary_name(getParam<BoundaryName>("secondary_boundary")),
      40         996 :     _enabled(getParam<bool>("enabled"))
      41             : {
      42         332 : }
      43             : 
      44         250 : GhostPrimaryFace::GhostPrimaryFace(const GhostPrimaryFace & other)
      45             :   : RelationshipManager(other),
      46         250 :     _primary_boundary_name(other._primary_boundary_name),
      47         250 :     _secondary_boundary_name(other._secondary_boundary_name),
      48         250 :     _enabled(other._enabled)
      49             : {
      50         250 : }
      51             : 
      52             : void
      53         278 : GhostPrimaryFace::internalInitWithMesh(const MeshBase &)
      54             : {
      55         278 : }
      56             : 
      57             : std::string
      58           4 : GhostPrimaryFace::getInfo() const
      59             : {
      60           4 :   std::ostringstream oss;
      61           4 :   oss << "GhostPrimaryFace" << (_enabled ? "" : " (disabled)");
      62           8 :   return oss.str();
      63           4 : }
      64             : 
      65             : bool
      66           2 : GhostPrimaryFace::hasSecondaryBoundaryFace(const MeshBase::const_element_iterator & range_begin,
      67             :                                            const MeshBase::const_element_iterator & range_end,
      68             :                                            const BoundaryID secondary_boundary_id,
      69             :                                            const bool generating_mesh) const
      70             : {
      71           2 :   const auto mesh_dim = _mesh->mesh_dimension();
      72           2 :   const BoundaryInfo & binfo = _mesh->get_boundary_info();
      73             : 
      74           2 :   for (const Elem * const elem : as_range(range_begin, range_end))
      75             :   {
      76           2 :     if (elem->dim() != mesh_dim)
      77           0 :       continue;
      78             : 
      79           2 :     if (generating_mesh)
      80             :     {
      81             :       // Boundary ids may not exist yet while generating the mesh, so treat any
      82             :       // full-dimensional boundary element as being on the requested boundary.
      83           0 :       if (elem->on_boundary())
      84           0 :         return true;
      85             :     }
      86             :     else
      87           2 :       for (const auto side : elem->side_index_range())
      88           2 :         if (binfo.has_boundary_id(elem, side, secondary_boundary_id))
      89           2 :           return true;
      90           6 :   }
      91             : 
      92           0 :   return false;
      93             : }
      94             : 
      95             : void
      96         326 : GhostPrimaryFace::operator()(const MeshBase::const_element_iterator & range_begin,
      97             :                              const MeshBase::const_element_iterator & range_end,
      98             :                              const processor_id_type p,
      99             :                              map_type & coupled_elements)
     100             : {
     101         326 :   if (!_enabled)
     102         324 :     return;
     103             : 
     104           2 :   const bool generating_mesh = !_moose_mesh->getMeshPtr();
     105             :   const auto primary_boundary_id = generating_mesh
     106           2 :                                        ? Moose::INVALID_BOUNDARY_ID
     107           2 :                                        : _moose_mesh->getBoundaryID(_primary_boundary_name);
     108             :   const auto secondary_boundary_id = generating_mesh
     109           2 :                                          ? Moose::INVALID_BOUNDARY_ID
     110           2 :                                          : _moose_mesh->getBoundaryID(_secondary_boundary_name);
     111             : 
     112           2 :   if (!hasSecondaryBoundaryFace(range_begin, range_end, secondary_boundary_id, generating_mesh))
     113           0 :     return;
     114             : 
     115           2 :   const auto mesh_dim = _mesh->mesh_dimension();
     116           2 :   const BoundaryInfo & binfo = _mesh->get_boundary_info();
     117             : 
     118          18 :   for (const Elem * const elem : _mesh->active_element_ptr_range())
     119             :   {
     120           8 :     if (elem->processor_id() == p || elem->dim() != mesh_dim)
     121           2 :       continue;
     122             : 
     123           6 :     if (generating_mesh)
     124             :     {
     125             :       // Boundary ids may not exist yet while generating the mesh, so ghost any
     126             :       // full-dimensional boundary element.
     127           0 :       if (elem->on_boundary())
     128           0 :         coupled_elements.emplace(elem, _null_mat);
     129             :     }
     130             :     else
     131          22 :       for (const auto side : elem->side_index_range())
     132          18 :         if (binfo.has_boundary_id(elem, side, primary_boundary_id))
     133             :         {
     134           2 :           coupled_elements.emplace(elem, _null_mat);
     135           2 :           break;
     136             :         }
     137           2 :   }
     138             : }
     139             : 
     140             : bool
     141        1010 : GhostPrimaryFace::operator>=(const RelationshipManager & other) const
     142             : {
     143        1010 :   const auto * const primary_face = dynamic_cast<const GhostPrimaryFace *>(&other);
     144        1010 :   if (!primary_face || !baseGreaterEqual(*primary_face))
     145         772 :     return false;
     146             : 
     147             :   // An enabled instance subsumes an otherwise compatible disabled instance, which adds no
     148             :   // ghosting entries.
     149         238 :   if (_enabled && !primary_face->_enabled)
     150           0 :     return true;
     151             : 
     152             :   // A disabled instance only subsumes another disabled instance.
     153         238 :   if (!_enabled)
     154         238 :     return !primary_face->_enabled;
     155             : 
     156             :   // Once both are enabled, the two instances must ghost the same boundary pair on the same
     157             :   // mesh to cover the same elements.
     158           0 :   return primary_face->_enabled && _use_displaced_mesh == primary_face->_use_displaced_mesh &&
     159           0 :          _primary_boundary_name == primary_face->_primary_boundary_name &&
     160           0 :          _secondary_boundary_name == primary_face->_secondary_boundary_name;
     161             : }
     162             : 
     163             : std::unique_ptr<GhostingFunctor>
     164         250 : GhostPrimaryFace::clone() const
     165             : {
     166         250 :   return _app.getFactory().copyConstruct(*this);
     167             : }

Generated by: LCOV version 1.14