LCOV - code coverage report
Current view: top level - src/interfaces - BoundaryRestrictable.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 123 143 86.0 %
Date: 2025-07-17 01:28:37 Functions: 17 20 85.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     5452440 : BoundaryRestrictable::validParams()
      18             : {
      19             : 
      20             :   // Create instance of InputParameters
      21     5452440 :   InputParameters params = emptyInputParameters();
      22             : 
      23             :   // Create user-facing 'boundary' input for restricting inheriting object to boundaries
      24     5452440 :   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     5452440 :   if (!params.isParamValid("_dual_restrictable"))
      30     5452440 :     params.addPrivateParam<bool>("_dual_restrictable", false);
      31             : 
      32     5452440 :   return params;
      33           0 : }
      34             : 
      35             : // Standard constructor
      36      192939 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object, bool nodal)
      37      385878 :   : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
      38      192939 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      39             :                        : NULL),
      40      192939 :     _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      41             :                                                   : NULL),
      42      192939 :     _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      43      192939 :     _block_ids(_empty_block_ids),
      44      192939 :     _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      45      192939 :     _bnd_material_data(_bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
      46      192939 :     _bnd_nodal(nodal),
      47      578817 :     _moose_object(*moose_object)
      48             : {
      49      192939 :   initializeBoundaryRestrictable();
      50      192934 : }
      51             : 
      52             : // Dual restricted constructor
      53       36106 : BoundaryRestrictable::BoundaryRestrictable(const MooseObject * moose_object,
      54             :                                            const std::set<SubdomainID> & block_ids,
      55       36106 :                                            bool nodal)
      56       72212 :   : _bnd_feproblem(moose_object->isParamValid("_fe_problem_base")
      57       36106 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      58             :                        : NULL),
      59       36106 :     _bnd_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      60             :                                                   : NULL),
      61       36106 :     _bnd_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      62       36106 :     _block_ids(block_ids),
      63       36106 :     _bnd_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      64       36106 :     _bnd_material_data(_bnd_feproblem->getMaterialData(Moose::BOUNDARY_MATERIAL_DATA, _bnd_tid)),
      65       36106 :     _bnd_nodal(nodal),
      66      108318 :     _moose_object(*moose_object)
      67             : {
      68       36106 :   initializeBoundaryRestrictable();
      69       36102 : }
      70             : 
      71             : void
      72      229045 : BoundaryRestrictable::initializeBoundaryRestrictable()
      73             : {
      74             :   // The name and id of the object
      75      229045 :   const std::string & name = _moose_object.getParam<std::string>("_object_name");
      76             : 
      77             :   // If the mesh pointer is not defined, but FEProblemBase is, get it from there
      78      229045 :   if (_bnd_feproblem != NULL && _bnd_mesh == NULL)
      79      229045 :     _bnd_mesh = &_bnd_feproblem->mesh();
      80             : 
      81             :   // Check that the mesh pointer was defined, it is required for this class to operate
      82      229045 :   if (_bnd_mesh == NULL)
      83           0 :     mooseError("The input parameters must contain a pointer to FEProblemBase via '_fe_problem' or "
      84             :                "a pointer to the MooseMesh via '_mesh'");
      85             : 
      86             :   // If the user supplies boundary IDs
      87      229045 :   if (_moose_object.isParamValid("boundary"))
      88             :   {
      89             :     // Extract the blocks from the input
      90      108613 :     _boundary_names = _moose_object.getParam<std::vector<BoundaryName>>("boundary");
      91             : 
      92             :     // Get the IDs from the supplied names
      93      108613 :     _vec_ids = _bnd_mesh->getBoundaryIDs(_boundary_names, true);
      94             : 
      95             :     // Store the IDs, handling ANY_BOUNDARY_ID if supplied
      96      108613 :     if (std::find(_boundary_names.begin(), _boundary_names.end(), "ANY_BOUNDARY_ID") !=
      97      217226 :         _boundary_names.end())
      98          67 :       _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
      99             :     else
     100      108546 :       _bnd_ids.insert(_vec_ids.begin(), _vec_ids.end());
     101             :   }
     102             : 
     103             :   // Produce error if the object is not allowed to be both block and boundary restricted
     104      229045 :   if (!_bnd_dual_restrictable && !_bnd_ids.empty() && !_block_ids.empty())
     105           4 :     if (!_block_ids.empty() && _block_ids.find(Moose::ANY_BLOCK_ID) == _block_ids.end())
     106           4 :       _moose_object.paramError("boundary",
     107             :                                "Attempted to restrict the object '",
     108             :                                name,
     109             :                                "' to a boundary, but the object is already restricted by block(s)");
     110             : 
     111             :   // Store ANY_BOUNDARY_ID if empty
     112      229041 :   if (_bnd_ids.empty())
     113             :   {
     114      120432 :     _bnd_ids.insert(Moose::ANY_BOUNDARY_ID);
     115      240864 :     _boundary_names = {"ANY_BOUNDARY_ID"};
     116             :   }
     117             : 
     118             :   // If this object is block restricted, check that defined blocks exist on the mesh
     119      229041 :   if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) == _bnd_ids.end())
     120             :   {
     121             :     const std::set<BoundaryID> * valid_ids;
     122      108542 :     const char * message_ptr = nullptr;
     123             : 
     124      108542 :     if (_bnd_nodal)
     125             :     {
     126       80552 :       valid_ids = &_bnd_mesh->meshNodesetIds();
     127       80552 :       message_ptr = "node sets";
     128             :     }
     129             :     else
     130             :     {
     131       27990 :       valid_ids = &_bnd_mesh->meshSidesetIds();
     132       27990 :       message_ptr = "side sets";
     133             :     }
     134             : 
     135      108542 :     std::vector<BoundaryID> diff;
     136             : 
     137      108542 :     std::set_difference(_bnd_ids.begin(),
     138             :                         _bnd_ids.end(),
     139             :                         valid_ids->begin(),
     140             :                         valid_ids->end(),
     141             :                         std::back_inserter(diff));
     142             : 
     143      108542 :     if (!diff.empty())
     144             :     {
     145           9 :       std::ostringstream msg;
     146           9 :       auto sep = " ";
     147           9 :       msg << "the following " << message_ptr << " (ids) do not exist on the mesh:";
     148          19 :       for (const auto & id : diff)
     149             :       {
     150          10 :         if (_boundary_names.size() > 0)
     151             :         {
     152          10 :           auto & name = _boundary_names.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) -
     153          10 :                                            _vec_ids.begin());
     154          10 :           if (std::to_string(id) != name)
     155           6 :             msg << sep << name << " (" << id << ")";
     156             :           else
     157           4 :             msg << sep << id;
     158             :         }
     159             :         else
     160           0 :           msg << sep << id;
     161          10 :         sep = ", ";
     162             :       }
     163           9 :       if (!_bnd_nodal)
     164             :         // Diagnostic message
     165             :         msg << "\n\nMOOSE distinguishes between \"node sets\" and \"side sets\" depending on "
     166             :                "whether \nyou are using \"Nodal\" or \"Integrated\" BCs respectively. Node sets "
     167             :                "corresponding \nto your side sets are constructed for you by default.\n\n"
     168             :                "Try setting \"Mesh/construct_side_list_from_node_list=true\" if you see this "
     169             :                "error.\n"
     170           5 :                "Note: If you are running with adaptivity you should prefer using side sets.";
     171             : 
     172          12 :       _moose_object.paramError("boundary", msg.str());
     173           1 :     }
     174      108534 :   }
     175      349464 : }
     176             : 
     177      216297 : BoundaryRestrictable::~BoundaryRestrictable() {}
     178             : 
     179             : const std::set<BoundaryID> &
     180      772509 : BoundaryRestrictable::boundaryIDs() const
     181             : {
     182      772509 :   return _bnd_ids;
     183             : }
     184             : 
     185             : const std::vector<BoundaryName> &
     186       12992 : BoundaryRestrictable::boundaryNames() const
     187             : {
     188       12992 :   return _boundary_names;
     189             : }
     190             : 
     191             : unsigned int
     192         192 : BoundaryRestrictable::numBoundaryIDs() const
     193             : {
     194         192 :   return (unsigned int)_bnd_ids.size();
     195             : }
     196             : 
     197             : bool
     198     1058803 : BoundaryRestrictable::boundaryRestricted() const
     199             : {
     200     1058803 :   return BoundaryRestrictable::restricted(_bnd_ids);
     201             : }
     202             : 
     203             : bool
     204     1271318 : BoundaryRestrictable::restricted(const std::set<BoundaryID> & ids)
     205             : {
     206     1271318 :   return ids.find(Moose::ANY_BOUNDARY_ID) == ids.end();
     207             : }
     208             : 
     209             : bool
     210           8 : BoundaryRestrictable::hasBoundary(const BoundaryName & name) const
     211             : {
     212             :   // Create a vector and utilize the getBoundaryIDs function, which
     213             :   // handles the ANY_BOUNDARY_ID (getBoundaryID does not)
     214          16 :   return hasBoundary(_bnd_mesh->getBoundaryIDs({name}));
     215           8 : }
     216             : 
     217             : bool
     218           8 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryName> & names) const
     219             : {
     220           8 :   return hasBoundary(_bnd_mesh->getBoundaryIDs(names));
     221             : }
     222             : 
     223             : bool
     224      180522 : BoundaryRestrictable::hasBoundary(const BoundaryID & id) const
     225             : {
     226      180522 :   if (_bnd_ids.empty() || _bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     227           0 :     return true;
     228             :   else
     229      180522 :     return _bnd_ids.find(id) != _bnd_ids.end();
     230             : }
     231             : 
     232             : bool
     233          24 : BoundaryRestrictable::hasBoundary(const std::vector<BoundaryID> & ids, TEST_TYPE type) const
     234             : {
     235          24 :   std::set<BoundaryID> ids_set(ids.begin(), ids.end());
     236          48 :   return hasBoundary(ids_set, type);
     237          24 : }
     238             : 
     239             : bool
     240         282 : BoundaryRestrictable::hasBoundary(const std::set<BoundaryID> & ids, TEST_TYPE type) const
     241             : {
     242             :   // An empty input is assumed to be ANY_BOUNDARY_ID
     243         282 :   if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
     244         242 :     return true;
     245             : 
     246             :   // All supplied IDs must match those of the object
     247          40 :   else if (type == ALL)
     248             :   {
     249          40 :     if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     250           0 :       return true;
     251             :     else
     252          40 :       return std::includes(_bnd_ids.begin(), _bnd_ids.end(), ids.begin(), ids.end());
     253             :   }
     254             :   // Any of the supplied IDs must match those of the object
     255             :   else
     256             :   {
     257             :     // Loop through the supplied ids
     258           0 :     for (const auto & id : ids)
     259             :     {
     260             :       // Test the current supplied id
     261           0 :       bool test = hasBoundary(id);
     262             : 
     263             :       // If the id exists in the stored ids, then return true, otherwise
     264           0 :       if (test)
     265           0 :         return true;
     266             :     }
     267           0 :     return false;
     268             :   }
     269             : }
     270             : 
     271             : bool
     272           4 : BoundaryRestrictable::isBoundarySubset(const std::set<BoundaryID> & ids) const
     273             : {
     274             :   // An empty input is assumed to be ANY_BOUNDARY_ID
     275           4 :   if (ids.empty() || ids.find(Moose::ANY_BOUNDARY_ID) != ids.end())
     276           0 :     return true;
     277             : 
     278           4 :   if (_bnd_ids.find(Moose::ANY_BOUNDARY_ID) != _bnd_ids.end())
     279           0 :     return std::includes(ids.begin(),
     280             :                          ids.end(),
     281           0 :                          _bnd_mesh->meshBoundaryIds().begin(),
     282           0 :                          _bnd_mesh->meshBoundaryIds().end());
     283             :   else
     284           4 :     return std::includes(ids.begin(), ids.end(), _bnd_ids.begin(), _bnd_ids.end());
     285             : }
     286             : 
     287             : bool
     288           0 : BoundaryRestrictable::isBoundarySubset(const std::vector<BoundaryID> & ids) const
     289             : {
     290           0 :   std::set<BoundaryID> ids_set(ids.begin(), ids.end());
     291           0 :   return isBoundarySubset(ids_set);
     292           0 : }
     293             : 
     294             : const std::set<BoundaryID> &
     295           0 : BoundaryRestrictable::meshBoundaryIDs() const
     296             : {
     297           0 :   return _bnd_mesh->getBoundaryIDs();
     298             : }
     299             : 
     300             : bool
     301          25 : BoundaryRestrictable::hasBoundaryMaterialPropertyHelper(const std::string & prop_name) const
     302             : {
     303             :   // Reference to MaterialWarehouse for testing and retrieving boundary ids
     304          25 :   const MaterialWarehouse & warehouse = _bnd_feproblem->getMaterialWarehouse();
     305             : 
     306             :   // Complete set of BoundaryIDs that this object is defined
     307             :   const std::set<BoundaryID> & ids =
     308          25 :       hasBoundary(Moose::ANY_BOUNDARY_ID) ? meshBoundaryIDs() : boundaryIDs();
     309             : 
     310             :   // Loop over each BoundaryID for this object
     311          42 :   for (const auto & id : ids)
     312             :   {
     313             :     // Storage of material properties that have been DECLARED on this BoundaryID
     314          25 :     std::set<std::string> declared_props;
     315             : 
     316             :     // If boundary materials exist, populated the set of properties that were declared
     317          25 :     if (warehouse.hasActiveBoundaryObjects(id))
     318             :     {
     319             :       const std::vector<std::shared_ptr<MaterialBase>> & mats =
     320          25 :           warehouse.getActiveBoundaryObjects(id);
     321          50 :       for (const auto & mat : mats)
     322             :       {
     323          25 :         const std::set<std::string> & mat_props = mat->getSuppliedItems();
     324          25 :         declared_props.insert(mat_props.begin(), mat_props.end());
     325             :       }
     326             :     }
     327             : 
     328             :     // If the supplied property is not in the list of properties on the current id, return false
     329          25 :     if (declared_props.find(prop_name) == declared_props.end())
     330           8 :       return false;
     331          25 :   }
     332             : 
     333             :   // If you get here the supplied property is defined on all boundaries
     334          17 :   return true;
     335             : }

Generated by: LCOV version 1.14