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 : }