LCOV - code coverage report
Current view: top level - src/interfaces - BlockRestrictable.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 136 179 76.0 %
Date: 2026-05-29 20:35:17 Functions: 16 21 76.2 %
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 "BlockRestrictable.h"
      12             : 
      13             : #include "FEProblem.h"
      14             : #include "Material.h"
      15             : #include "MooseMesh.h"
      16             : #include "MooseVariableFE.h"
      17             : #include "SystemBase.h"
      18             : #include "Conversion.h"
      19             : 
      20             : InputParameters
      21     3331972 : BlockRestrictable::validParams()
      22             : {
      23             :   // Create InputParameters object that will be appended to the parameters for the inheriting object
      24     3331972 :   InputParameters params = emptyInputParameters();
      25             : 
      26             :   // Add the user-facing 'block' input parameter
      27     9995916 :   params.addParam<std::vector<SubdomainName>>(
      28             :       "block", "The list of blocks (ids or names) that this object will be applied");
      29             : 
      30             :   // A parameter for disabling error message for objects restrictable by boundary and block,
      31             :   // if the parameter is valid it was already set so don't do anything
      32     3331972 :   if (!params.have_parameter<bool>("_dual_restrictable"))
      33     9995916 :     params.addPrivateParam<bool>("_dual_restrictable", false);
      34             : 
      35             :   // Return the parameters
      36     3331972 :   return params;
      37           0 : }
      38             : 
      39             : // Standard constructor
      40      471696 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object, bool initialize /*=true*/)
      41      943392 :   : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      42      943392 :     _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
      43     1415088 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      44             :                        : NULL),
      45      943392 :     _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      46             :                                                   : NULL),
      47      471696 :     _boundary_ids(_empty_boundary_ids),
      48     1886784 :     _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      49      471696 :     _blk_name(moose_object->name()),
      50      471696 :     _blk_dim(libMesh::invalid_uint),
      51     1305576 :     _moose_object(moose_object)
      52             : {
      53      471696 :   if (initialize)
      54      471696 :     initializeBlockRestrictable(_moose_object);
      55      471693 : }
      56             : 
      57             : // Dual restricted constructor
      58           0 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object,
      59           0 :                                      const std::set<BoundaryID> & boundary_ids)
      60           0 :   : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      61           0 :     _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
      62           0 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      63             :                        : NULL),
      64           0 :     _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      65             :                                                   : NULL),
      66           0 :     _boundary_ids(boundary_ids),
      67           0 :     _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      68           0 :     _blk_name(moose_object->name()),
      69           0 :     _blk_dim(libMesh::invalid_uint),
      70           0 :     _moose_object(moose_object)
      71             : {
      72           0 :   initializeBlockRestrictable(_moose_object);
      73           0 : }
      74             : 
      75             : void
      76      471696 : BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
      77             : {
      78             :   // If the mesh pointer is not defined, but FEProblemBase is, get it from there
      79      471696 :   if (_blk_feproblem != NULL && _blk_mesh == NULL)
      80      471696 :     _blk_mesh = &_blk_feproblem->mesh();
      81             : 
      82             :   // Check that the mesh pointer was defined, it is required for this class to operate
      83      471696 :   if (_blk_mesh == NULL)
      84           0 :     mooseError("The input parameters must contain a pointer to FEProblem via '_fe_problem' or a "
      85             :                "pointer to the MooseMesh via '_mesh'");
      86             : 
      87             :   // Populate the MaterialData pointer
      88      471696 :   if (_blk_feproblem != NULL)
      89             :   {
      90             : #ifdef MOOSE_KOKKOS_ENABLED
      91      362184 :     if (_moose_object->isKokkosObject())
      92        7872 :       _blk_material_data = &_blk_feproblem->getKokkosMaterialData(Moose::BLOCK_MATERIAL_DATA);
      93             :     else
      94             : #endif
      95      463824 :       _blk_material_data = &_blk_feproblem->getMaterialData(Moose::BLOCK_MATERIAL_DATA, _blk_tid);
      96             :   }
      97             : 
      98             :   // The 'block' input is defined
      99     1415088 :   if (moose_object->isParamValid("block"))
     100             :   {
     101             :     // Extract the blocks from the input
     102      144726 :     _blocks = moose_object->getParam<std::vector<SubdomainName>>("block");
     103             : 
     104             :     // Store the IDs in a set, handling ANY_BLOCK_ID if supplied
     105       72363 :     if (std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end())
     106        4275 :       _blk_ids.insert(Moose::ANY_BLOCK_ID);
     107             :     else
     108             :     {
     109             :       // Get the IDs from the supplied names
     110       68088 :       _vec_ids = _blk_mesh->getSubdomainIDs(_blocks);
     111       68088 :       _blk_ids.insert(_vec_ids.begin(), _vec_ids.end());
     112             :     }
     113             :   }
     114             : 
     115             :   // When 'blocks' is not set and there is a "variable", use the blocks from the variable
     116     1197999 :   else if (moose_object->isParamValid("variable"))
     117             :   {
     118      389692 :     std::string variable_name = moose_object->parameters().getMooseType("variable");
     119      194846 :     if (!variable_name.empty())
     120      167811 :       _blk_ids = _blk_feproblem
     121      335622 :                      ->getVariable(_blk_tid,
     122             :                                    variable_name,
     123             :                                    Moose::VarKindType::VAR_ANY,
     124             :                                    Moose::VarFieldType::VAR_FIELD_ANY)
     125      167811 :                      .activeSubdomains();
     126      194846 :   }
     127             : 
     128             :   // Produce error if the object is not allowed to be both block and boundary restricted
     129      471696 :   if (!_blk_dual_restrictable && !_boundary_ids.empty() && !_boundary_ids.empty())
     130           0 :     if (!_boundary_ids.empty() && _boundary_ids.find(Moose::ANY_BOUNDARY_ID) == _boundary_ids.end())
     131           0 :       moose_object->paramError("block",
     132             :                                "Attempted to restrict the object '",
     133           0 :                                _blk_name,
     134             :                                "' to a block, but the object is already restricted by boundary");
     135             : 
     136             :   // If no blocks were defined above, specify that it is valid on all blocks
     137     1260846 :   if (_blk_ids.empty() && !moose_object->isParamValid("boundary"))
     138             :   {
     139      379285 :     _blk_ids.insert(Moose::ANY_BLOCK_ID);
     140      758570 :     _blocks = {"ANY_BLOCK_ID"};
     141             :   }
     142             : 
     143             :   // If this object is block restricted, check that defined blocks exist on the mesh
     144      471696 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end())
     145             :   {
     146       88136 :     const std::set<SubdomainID> & valid_ids = _blk_mesh->meshSubdomains();
     147       88136 :     std::vector<SubdomainID> diff;
     148             : 
     149       88136 :     std::set_difference(_blk_ids.begin(),
     150             :                         _blk_ids.end(),
     151             :                         valid_ids.begin(),
     152             :                         valid_ids.end(),
     153             :                         std::back_inserter(diff));
     154             : 
     155       88136 :     if (!diff.empty())
     156             :     {
     157           3 :       std::ostringstream msg;
     158           3 :       auto sep = " ";
     159           3 :       msg << "the following blocks (ids) do not exist on the mesh:";
     160           6 :       for (const auto & id : diff)
     161             :       {
     162           3 :         if (_blk_name.size() > 0)
     163             :         {
     164             :           auto & name =
     165           3 :               _blocks.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) - _vec_ids.begin());
     166           3 :           if (std::to_string(id) != name)
     167           0 :             msg << sep << name << " (" << id << ")";
     168             :           else
     169           3 :             msg << sep << id;
     170             :         }
     171             :         else
     172           0 :           msg << sep << id;
     173           3 :         sep = ", ";
     174             :       }
     175           3 :       std::vector<SubdomainID> valid_ids_vec(valid_ids.begin(), valid_ids.end());
     176           3 :       auto valid_names = _blk_mesh->getSubdomainNames(valid_ids_vec);
     177          12 :       msg << "\nBlocks names (resp. ids) that do exist: " << Moose::stringify(valid_names) << " ("
     178          18 :           << Moose::stringify(valid_ids) << ")";
     179           6 :       moose_object->paramError("block", msg.str());
     180           0 :     }
     181       88133 :   }
     182             : 
     183             :   // Get the mesh dimension for the blocks
     184      471693 :   if (blockRestricted())
     185       88133 :     _blk_dim = _blk_mesh->getBlocksMaxDimension(_blocks);
     186             :   else
     187      383560 :     _blk_dim = _blk_mesh->dimension();
     188             : 
     189             : #ifdef MOOSE_KOKKOS_ENABLED
     190      362182 :   if (moose_object->isKokkosObject())
     191        7872 :     _blk_feproblem->addKokkosMeshInitializationHook(
     192       15744 :         std::bind(&BlockRestrictable::initializeKokkosBlockRestrictable, this));
     193             : #endif
     194      850978 : }
     195             : 
     196             : bool
     197     1654892 : BlockRestrictable::blockRestricted() const
     198             : {
     199     1654892 :   return _blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end();
     200             : }
     201             : 
     202             : const std::vector<SubdomainName> &
     203       27814 : BlockRestrictable::blocks() const
     204             : {
     205       27814 :   return _blocks;
     206             : }
     207             : 
     208             : const std::set<SubdomainID> &
     209     6841494 : BlockRestrictable::blockIDs() const
     210             : {
     211     6841494 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     212     5492192 :     return _blk_mesh->meshSubdomains();
     213             :   else
     214     1349302 :     return _blk_ids;
     215             : }
     216             : 
     217             : unsigned int
     218          24 : BlockRestrictable::numBlocks() const
     219             : {
     220          24 :   return (unsigned int)_blk_ids.size();
     221             : }
     222             : 
     223             : bool
     224           6 : BlockRestrictable::hasBlocks(const SubdomainName & name) const
     225             : {
     226             :   // Create a vector and utilize the getSubdomainIDs function, which
     227             :   // handles the ANY_BLOCK_ID (getSubdomainID does not)
     228           6 :   std::vector<SubdomainName> names(1);
     229           6 :   names[0] = name;
     230          12 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     231           6 : }
     232             : 
     233             : bool
     234           6 : BlockRestrictable::hasBlocks(const std::vector<SubdomainName> & names) const
     235             : {
     236           6 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     237             : }
     238             : 
     239             : bool
     240           0 : BlockRestrictable::hasBlocks(const std::set<SubdomainName> & names) const
     241             : {
     242           0 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     243             : }
     244             : 
     245             : bool
     246   853836636 : BlockRestrictable::hasBlocks(const SubdomainID id) const
     247             : {
     248   853836636 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     249   785502701 :     return true;
     250             :   else
     251    68333935 :     return _blk_ids.find(id) != _blk_ids.end();
     252             : }
     253             : 
     254             : bool
     255          18 : BlockRestrictable::hasBlocks(const std::vector<SubdomainID> & ids) const
     256             : {
     257          18 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     258          36 :   return hasBlocks(ids_set);
     259          18 : }
     260             : 
     261             : bool
     262        2076 : BlockRestrictable::hasBlocks(const std::set<SubdomainID> & ids) const
     263             : {
     264        2076 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     265         933 :     return true;
     266             :   else
     267        1143 :     return std::includes(_blk_ids.begin(), _blk_ids.end(), ids.begin(), ids.end());
     268             : }
     269             : 
     270             : bool
     271      844394 : BlockRestrictable::isBlockSubset(const std::set<SubdomainID> & ids) const
     272             : {
     273             :   // An empty input is assumed to be ANY_BLOCK_ID
     274      844394 :   if (ids.empty() || ids.find(Moose::ANY_BLOCK_ID) != ids.end())
     275      806053 :     return true;
     276             : 
     277       38341 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     278        1287 :     return std::includes(ids.begin(),
     279             :                          ids.end(),
     280        1287 :                          _blk_mesh->meshSubdomains().begin(),
     281        2574 :                          _blk_mesh->meshSubdomains().end());
     282             :   else
     283       37054 :     return std::includes(ids.begin(), ids.end(), _blk_ids.begin(), _blk_ids.end());
     284             : }
     285             : 
     286             : bool
     287           0 : BlockRestrictable::isBlockSubset(const std::vector<SubdomainID> & ids) const
     288             : {
     289           0 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     290           0 :   return isBlockSubset(ids_set);
     291           0 : }
     292             : 
     293             : const std::set<SubdomainID> &
     294      442428 : BlockRestrictable::meshBlockIDs() const
     295             : {
     296      442428 :   return _blk_mesh->meshSubdomains();
     297             : }
     298             : 
     299             : bool
     300       14651 : BlockRestrictable::hasBlockMaterialPropertyHelper(const std::string & prop_name)
     301             : {
     302             : 
     303             :   // Reference to MaterialWarehouse for testing and retrieving block ids
     304       14651 :   const MaterialWarehouse & warehouse = _blk_feproblem->getMaterialWarehouse();
     305             : 
     306             :   // Complete set of ids that this object is active
     307       14651 :   const std::set<SubdomainID> & ids = blockRestricted() ? blockIDs() : meshBlockIDs();
     308             : 
     309             :   // Loop over each id for this object
     310       15467 :   for (const auto & id : ids)
     311             :   {
     312             :     // Storage of material properties that have been DECLARED on this id
     313       14721 :     std::set<std::string> declared_props;
     314             : 
     315             :     // If block materials exist, populated the set of properties that were declared
     316       14721 :     if (warehouse.hasActiveBlockObjects(id))
     317             :     {
     318       14060 :       const std::vector<std::shared_ptr<MaterialBase>> & mats = warehouse.getActiveBlockObjects(id);
     319      113411 :       for (const auto & mat : mats)
     320             :       {
     321       99351 :         const std::set<std::string> & mat_props = mat->getSuppliedItems();
     322       99351 :         declared_props.insert(mat_props.begin(), mat_props.end());
     323             :       }
     324             :     }
     325             : 
     326             :     // If the supplied property is not in the list of properties on the current id, return false
     327       14721 :     if (declared_props.find(prop_name) == declared_props.end())
     328       13905 :       return false;
     329       14721 :   }
     330             : 
     331             :   // If you get here the supplied property is defined on all blocks
     332         746 :   return true;
     333             : }
     334             : 
     335             : Moose::CoordinateSystemType
     336           0 : BlockRestrictable::getBlockCoordSystem()
     337             : {
     338           0 :   if (!_blk_mesh)
     339           0 :     mooseError("No mesh available in BlockRestrictable::checkCoordSystem()");
     340           0 :   if (!_blk_feproblem)
     341           0 :     mooseError("No problem available in BlockRestrictable::checkCoordSystem()");
     342             : 
     343           0 :   const auto & subdomains = blockRestricted() ? blockIDs() : meshBlockIDs();
     344             : 
     345           0 :   if (subdomains.empty())
     346           0 :     mooseError("No subdomains found in the problem.");
     347             : 
     348             :   // make sure all subdomains are using the same coordinate system
     349           0 :   auto coord_system = _blk_feproblem->getCoordSystem(*subdomains.begin());
     350           0 :   for (auto subdomain : subdomains)
     351           0 :     if (_blk_feproblem->getCoordSystem(subdomain) != coord_system)
     352           0 :       mooseError("This object requires all subdomains to have the same coordinate system.");
     353             : 
     354           0 :   return coord_system;
     355             : }
     356             : 
     357             : void
     358      844308 : BlockRestrictable::checkVariable(const MooseVariableFieldBase & variable) const
     359             : {
     360             :   // a variable defined on all internal sides does not need this check because
     361             :   // it can be coupled with other variables in DG kernels
     362      849892 :   if (!_blk_mesh->interiorLowerDBlocks().empty() &&
     363        5584 :       variable.activeOnSubdomains(_blk_mesh->interiorLowerDBlocks()))
     364        1152 :     return;
     365             : 
     366      843156 :   if (!isBlockSubset(variable.activeSubdomains()))
     367             :   {
     368          96 :     std::string var_ids = Moose::stringify(variable.activeSubdomains(), ", ");
     369          72 :     std::string obj_ids = Moose::stringify(blockRestricted() ? _blk_ids : meshBlockIDs(), ", ");
     370          24 :     mooseError("The 'block' parameter of the object '",
     371          24 :                _blk_name,
     372             :                "' must be a subset of the 'block' parameter of the variable '",
     373          24 :                variable.name(),
     374             :                "':\n    Object '",
     375          24 :                _blk_name,
     376             :                "': ",
     377             :                obj_ids,
     378             :                "\n    Variable '",
     379          24 :                variable.name(),
     380             :                "': ",
     381             :                var_ids);
     382           0 :   }
     383             : }
     384             : 
     385             : unsigned int
     386           0 : BlockRestrictable::blocksMaxDimension() const
     387             : {
     388             :   mooseAssert(_blk_dim != libMesh::invalid_uint, "Block restriction not initialized");
     389           0 :   return _blk_dim;
     390             : }

Generated by: LCOV version 1.14