LCOV - code coverage report
Current view: top level - src/interfaces - BoundaryRestrictable.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33187 (5aa0b2) with base d7c4bd Lines: 148 169 87.6 %
Date: 2026-06-30 12:18:20 Functions: 18 20 90.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             : // MOOSE includes
      11             : #include "BoundaryRestrictable.h"
      12             : #include "Material.h"
      13             : #include "MooseMesh.h"
      14             : #include "MooseObject.h"
      15             : 
      16             : InputParameters
      17     1520725 : BoundaryRestrictable::validParams()
      18             : {
      19             : 
      20             :   // Create instance of InputParameters
      21     1520725 :   InputParameters params = emptyInputParameters();
      22             : 
      23             :   // Create user-facing 'boundary' input for restricting inheriting object to boundaries
      24     6082900 :   params.addParam<std::vector<BoundaryName>>(
      25             :       "boundary", "The list of boundaries (ids or names) from the mesh where this object applies");
      26             : 
      27             :   // A parameter for disabling error message for objects restrictable by boundary and block,
      28             :   // if the parameter is valid it was already set so don't do anything
      29     3041450 :   if (!params.isParamValid("_dual_restrictable"))
      30     4562175 :     params.addPrivateParam<bool>("_dual_restrictable", false);
      31             : 
      32     1520725 :   return params;
      33           0 : }
      34             : 
      35             : // Standard constructor
      36      202824 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
      37      202824 :   : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
      38      608472 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      39             :                        : NULL),
      40      405648 :     _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      41             :                                                   : NULL),
      42      405648 :     _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      43      202824 :     _block_ids(_empty_block_ids),
      44      811296 :     _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      45      357155 :     _bnd_material_data(
      46             : #ifdef MOOSE_KOKKOS_ENABLED
      47      154331 :         moose_object->isKokkosObject()
      48        5227 :             ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
      49             :             :
      50             : #endif
      51      197597 :             _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
      52      202824 :     _bnd_nodal(nodal),
      53      762803 :     _moose_object(*moose_object)
      54             : {
      55      202824 :   initializeBoundaryRestrictable();
      56      202828 : }
      57             : 
      58             : // Dual restricted constructor
      59       40750 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
      60             :                                            const std::set<SubdomainID> & block_ids,
      61       40750 :                                            bool nodal)
      62       40750 :   : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
      63      122250 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      64             :                        : NULL),
      65       81500 :     _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      66             :                                                   : NULL),
      67       81500 :     _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      68       40750 :     _block_ids(block_ids),
      69      163000 :     _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      70       72124 :     _bnd_material_data(
      71             : #ifdef MOOSE_KOKKOS_ENABLED
      72       31374 :         moose_object->isKokkosObject()
      73        3023 :             ? _bnd_feproblem->getKokkosMaterialData(Moose::BOUNDARY_MATERIAL_DATA)
      74             :             :
      75             : #endif
      76       37727 :             _bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
      77       40750 :     _bnd_nodal(nodal),
      78      153624 :     _moose_object(*moose_object)
      79             : {
      80       40750 :   initializeBoundaryRestrictable();
      81       40747 : }
      82             : 
      83             : void
      84      243574 : BoundaryRestrictable::initializeBoundaryRestrictable()
      85             : {
      86             :   // The name and id of the object
      87      243574 :   const std::string & name = _moose_object.name();
      88             : 
      89             :   // If the mesh pointer is not defined, but FEProblemBase is, get it from there
      90      243574 :   if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
      91      243574 :     _bnd_mesh = &_bnd_feproblem->mesh();
      92             : 
      93             :   // Check that the mesh pointer was defined, it is required for this class to operate
      94      243574 :   if (_bnd_mesh == NULL)
      95           0 :     mooseError("The input parameters must contain a pointer to FEProblemBase via '_fe_problem' or "
      96             :                "a pointer to the MooseMesh via '_mesh'");
      97             : 
      98             :   // If the user supplies boundary IDs
      99      730722 :   if (_moose_object.isParamValid("boundary"))
     100             :   {
     101             :     // Extract the blocks from the input
     102      222604 :     _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
     103             : 
     104             :     // Get the IDs from the supplied names
     105      111302 :     _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
     106             : 
     107             :     // Store the IDs, handling ANY_BOUNDARY_ID if supplied
     108      111302 :     if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
     109      222604 :         _boundary_names.end())
     110          64 :       _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
     111             :     else
     112      111238 :       _bnd_ids.insert(_vec_ids.begin(), _vec_ids.end());
     113             :   }
     114             : 
     115             :   // Produce error if the object is not allowed to be both block and boundary restricted
     116      243574 :   if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
     117           3 :     if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
     118           6 :       _moose_object.paramError("boundary",
     119             :                                "Attempted to restrict the object '",
     120             :                                name,
     121             :                                "' to a boundary, but the object is already restricted by block(s)");
     122             : 
     123             :   // Store ANY_BOUNDARY_ID if empty
     124      243571 :   if (_bnd_ids.empty())
     125             :   {
     126      132272 :     _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
     127      264544 :     _boundary_names = {"ANY_BOUNDARY_ID"};
     128             :   }
     129             : 
     130             :   // If this object is block restricted, check that defined blocks exist on the mesh
     131      243571 :   if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
     132             :   {
     133             :     const std::set<BoundaryID> * valid_ids;
     134      111235 :     const char * message_ptr = nullptr;
     135             : 
     136      111235 :     if (_bnd_nodal)
     137             :     {
     138       83482 :       valid_ids = &_bnd_mesh->meshNodesetIds();
     139       83482 :       message_ptr = "node sets";
     140             :     }
     141             :     else
     142             :     {
     143       27753 :       valid_ids = &_bnd_mesh->meshSidesetIds();
     144       27753 :       message_ptr = "side sets";
     145             :     }
     146             : 
     147      111235 :     std::vector<BoundaryID> diff;
     148             : 
     149      111235 :     std::set_difference(_bnd_ids.begin(),
     150             :                         _bnd_ids.end(),
     151             :                         valid_ids->begin(),
     152             :                         valid_ids->end(),
     153             :                         std::back_inserter(diff));
     154             : 
     155      111235 :     if (!diff.empty())
     156             :     {
     157           8 :       std::ostringstream msg;
     158           8 :       auto sep = " ";
     159           8 :       msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
     160          18 :       for (const auto & id : diff)
     161             :       {
     162          10 :         if (_boundary_names.size() > 0)
     163             :         {
     164          10 :           auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
     165          10 :                                            _vec_ids.begin());
     166          10 :           if (std::to_string(id) != name)
     167           7 :             msg << sep << name << " (" << id << ")";
     168             :           else
     169           3 :             msg << sep << id;
     170             :         }
     171             :         else
     172           0 :           msg << sep << id;
     173          10 :         sep = ", ";
     174             :       }
     175             : 
     176             :       const auto & other_ids =
     177           8 :           _bnd_nodal ? _bnd_mesh->meshSidesetIds() : _bnd_mesh->meshNodesetIds();
     178           8 :       std::vector<BoundaryID> other_boundary_ids;
     179           8 :       std::set_intersection(diff.begin(),
     180             :                             diff.end(),
     181             :                             other_ids.begin(),
     182             :                             other_ids.end(),
     183             :                             std::back_inserter(other_boundary_ids));
     184           8 :       if (!other_boundary_ids.empty())
     185             :       {
     186           3 :         msg << "\n\nThe following boundary ";
     187           3 :         if (other_boundary_ids.size() == 1)
     188           3 :           msg << "id exists";
     189             :         else
     190           0 :           msg << "ids exist";
     191           3 :         if (other_boundary_ids.size() == 1)
     192           3 :           msg << " as " << (_bnd_nodal ? "a side set" : "a node set")
     193           3 :               << " but is being requested as " << (_bnd_nodal ? "a node set" : "a side set") << ":";
     194             :         else
     195           0 :           msg << " as " << (_bnd_nodal ? "side sets" : "node sets")
     196           0 :               << " but are being requested as " << (_bnd_nodal ? "node sets" : "side sets") << ":";
     197             : 
     198           3 :         sep = " ";
     199           6 :         for (const auto id : other_boundary_ids)
     200             :         {
     201           3 :           msg << sep << id;
     202           3 :           sep = ", ";
     203             :         }
     204             : 
     205           3 :         if (!_bnd_nodal)
     206             :           msg << "\n\nTry setting Mesh/construct_side_list_from_node_list=true if you want side "
     207           3 :                  "sets constructed from node sets.";
     208             :       }
     209             : 
     210          20 :       _moose_object.paramError("boundary", msg.str());
     211           4 :     }
     212      111229 :   }
     213             : 
     214             : #ifdef MOOSE_KOKKOS_ENABLED
     215      185697 :   if (_moose_object.isKokkosObject())
     216        8250 :     _bnd_feproblem->addKokkosMeshInitializationHook(
     217       16500 :         std::bind(&BoundaryRestrictable::initializeKokkosBoundaryRestrictable, this));
     218             : #endif
     219      375835 : }
     220             : 
     221      583707 : BoundaryRestrictable::~BoundaryRestrictable() {}
     222             : 
     223             : const std::set<BoundaryID> &
     224      795778 : BoundaryRestrictable::boundaryIDs() const
     225             : {
     226      795778 :   return _bnd_ids;
     227             : }
     228             : 
     229             : const std::vector<BoundaryName> &
     230       13051 : BoundaryRestrictable::boundaryNames() const
     231             : {
     232       13051 :   return _boundary_names;
     233             : }
     234             : 
     235             : unsigned int
     236         192 : BoundaryRestrictable::numBoundaryIDs() const
     237             : {
     238         192 :   return (unsigned int)_bnd_ids.size();
     239             : }
     240             : 
     241             : bool
     242     1173356 : BoundaryRestrictable::boundaryRestricted() const
     243             : {
     244     1173356 :   return BoundaryRestrictable::restricted(_bnd_ids);
     245             : }
     246             : 
     247             : bool
     248     1397231 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
     249             : {
     250     1397231 :   return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
     251             : }
     252             : 
     253             : bool
     254           6 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
     255             : {
     256             :   // Create a vector and utilize the getBoundaryIDs function, which
     257             :   // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
     258          18 :   return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
     259           6 : }
     260             : 
     261             : bool
     262           6 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
     263             : {
     264           6 :   return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
     265             : }
     266             : 
     267             : bool
     268      174867 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
     269             : {
     270      174867 :   if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     271           0 :     return true;
     272             :   else
     273      174867 :     return _bnd_ids.find(id) != _bnd_ids.end();
     274             : }
     275             : 
     276             : bool
     277          18 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
     278             : {
     279          18 :   std::set<BoundaryID> ids_set(ids.begin(), ids.end());
     280          36 :   return hasBoundary(ids_set, type);
     281          18 : }
     282             : 
     283             : bool
     284         270 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
     285             : {
     286             :   // An empty input is assumed to be ANY_BOUNDARY_ID
     287         270 :   if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
     288         240 :     return true;
     289             : 
     290             :   // All supplied IDs must match those of the object
     291          30 :   else if (type == ALL)
     292             :   {
     293          30 :     if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     294           0 :       return true;
     295             :     else
     296          30 :       return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
     297             :   }
     298             :   // Any of the supplied IDs must match those of the object
     299             :   else
     300             :   {
     301             :     // Loop through the supplied ids
     302           0 :     for (const auto & id : ids)
     303             :     {
     304             :       // Test the current supplied id
     305           0 :       bool test = hasBoundary(id);
     306             : 
     307             :       // If the id exists in the stored ids, then return true, otherwise
     308           0 :       if (test)
     309           0 :         return true;
     310             :     }
     311           0 :     return false;
     312             :   }
     313             : }
     314             : 
     315             : bool
     316           3 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
     317             : {
     318             :   // An empty input is assumed to be ANY_BOUNDARY_ID
     319           3 :   if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
     320           0 :     return true;
     321             : 
     322           3 :   if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     323           0 :     return std::includes(ids.begin(),
     324             :                          ids.end(),
     325           0 :                          _bnd_mesh->meshBoundaryIds().begin(),
     326           0 :                          _bnd_mesh->meshBoundaryIds().end());
     327             :   else
     328           3 :     return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
     329             : }
     330             : 
     331             : bool
     332           0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
     333             : {
     334           0 :   std::set<BoundaryID> ids_set(ids.begin(), ids.end());
     335           0 :   return isBoundarySubset(ids_set);
     336           0 : }
     337             : 
     338             : const std::set<BoundaryID> &
     339        2992 : BoundaryRestrictable::meshBoundaryIDs() const
     340             : {
     341        2992 :   return _bnd_mesh->getBoundaryIDs();
     342             : }
     343             : 
     344             : bool
     345          22 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
     346             : {
     347             :   // Reference to MaterialWarehouse for testing and retrieving boundary ids
     348          22 :   const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
     349             : 
     350             :   // Complete set of BoundaryIDs that this object is defined
     351             :   const std::set<BoundaryID> & ids =
     352          22 :       hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
     353             : 
     354             :   // Loop over each BoundaryID for this object
     355          38 :   for (const auto & id : ids)
     356             :   {
     357             :     // Storage of material properties that have been DECLARED on this BoundaryID
     358          22 :     std::set<std::string> declared_props;
     359             : 
     360             :     // If boundary materials exist, populated the set of properties that were declared
     361          22 :     if (warehouse.hasActiveBoundaryObjects(id))
     362             :     {
     363             :       const std::vector<std::shared_ptr<MaterialBase>> & mats =
     364          22 :           warehouse.getActiveBoundaryObjects(id);
     365          44 :       for (const auto & mat : mats)
     366             :       {
     367          22 :         const std::set<std::string> & mat_props = mat->getSuppliedItems();
     368          22 :         declared_props.insert(mat_props.begin(), mat_props.end());
     369             :       }
     370             :     }
     371             : 
     372             :     // If the supplied property is not in the list of properties on the current id, return false
     373          22 :     if (declared_props.find(prop_name) == declared_props.end())
     374           6 :       return false;
     375          22 :   }
     376             : 
     377             :   // If you get here the supplied property is defined on all boundaries
     378          16 :   return true;
     379             : }

Generated by: LCOV version 1.14