LCOV - code coverage report
Current view: top level - src/interfaces - BlockRestrictable.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 99787a Lines: 135 178 75.8 %
Date: 2025-10-14 20:01:24 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    12058446 : BlockRestrictable::validParams()
      22             : {
      23             :   // Create InputParameters object that will be appended to the parameters for the inheriting object
      24    12058446 :   InputParameters params = emptyInputParameters();
      25             : 
      26             :   // Add the user-facing 'block' input parameter
      27    36175338 :   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    12058446 :   if (!params.have_parameter<bool>("_dual_restrictable"))
      33    36175338 :     params.addPrivateParam<bool>("_dual_restrictable", false);
      34             : 
      35             :   // Return the parameters
      36    12058446 :   return params;
      37           0 : }
      38             : 
      39             : // Standard constructor
      40      497417 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object, bool initialize /*=true*/)
      41      994834 :   : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      42      994834 :     _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
      43     1492251 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      44             :                        : NULL),
      45      994834 :     _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      46             :                                                   : NULL),
      47      497417 :     _boundary_ids(_empty_boundary_ids),
      48     1989668 :     _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      49      497417 :     _blk_name(moose_object->name()),
      50      497417 :     _blk_dim(libMesh::invalid_uint),
      51     1339769 :     _moose_object(moose_object)
      52             : {
      53      497417 :   if (initialize)
      54      497417 :     initializeBlockRestrictable(_moose_object);
      55      497413 : }
      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      497417 : BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
      77             : {
      78             :   // If the mesh pointer is not defined, but FEProblemBase is, get it from there
      79      497417 :   if (_blk_feproblem != NULL && _blk_mesh == NULL)
      80      497417 :     _blk_mesh = &_blk_feproblem->mesh();
      81             : 
      82             :   // Check that the mesh pointer was defined, it is required for this class to operate
      83      497417 :   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      497417 :   if (_blk_feproblem != NULL)
      89             :   {
      90             : #ifdef MOOSE_KOKKOS_ENABLED
      91      344935 :     if (_moose_object->isKokkosObject({}))
      92        2523 :       _blk_material_data = &_blk_feproblem->getKokkosMaterialData(Moose::BLOCK_MATERIAL_DATA);
      93             :     else
      94             : #endif
      95      494894 :       _blk_material_data = &_blk_feproblem->getMaterialData(Moose::BLOCK_MATERIAL_DATA, _blk_tid);
      96             :   }
      97             : 
      98             :   // The 'block' input is defined
      99     1492251 :   if (moose_object->isParamValid("block"))
     100             :   {
     101             :     // Extract the blocks from the input
     102      153680 :     _blocks = moose_object->getParam<std::vector<SubdomainName>>("block");
     103             : 
     104             :     // Store the IDs in a set, handling ANY_BLOCK_ID if supplied
     105       76840 :     if (std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end())
     106        4525 :       _blk_ids.insert(Moose::ANY_BLOCK_ID);
     107             :     else
     108             :     {
     109             :       // Get the IDs from the supplied names
     110       72315 :       _vec_ids = _blk_mesh->getSubdomainIDs(_blocks);
     111       72315 :       _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     1261731 :   else if (moose_object->isParamValid("variable"))
     117             :   {
     118      411126 :     std::string variable_name = moose_object->parameters().getMooseType("variable");
     119      205563 :     if (!variable_name.empty())
     120      178076 :       _blk_ids = _blk_feproblem
     121      356152 :                      ->getVariable(_blk_tid,
     122             :                                    variable_name,
     123             :                                    Moose::VarKindType::VAR_ANY,
     124             :                                    Moose::VarFieldType::VAR_FIELD_ANY)
     125      178076 :                      .activeSubdomains();
     126      205563 :   }
     127             : 
     128             :   // Produce error if the object is not allowed to be both block and boundary restricted
     129      497417 :   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     1328573 :   if (_blk_ids.empty() && !moose_object->isParamValid("boundary"))
     138             :   {
     139      399098 :     _blk_ids.insert(Moose::ANY_BLOCK_ID);
     140      798196 :     _blocks = {"ANY_BLOCK_ID"};
     141             :   }
     142             : 
     143             :   // If this object is block restricted, check that defined blocks exist on the mesh
     144      497417 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end())
     145             :   {
     146       93794 :     const std::set<SubdomainID> & valid_ids = _blk_mesh->meshSubdomains();
     147       93794 :     std::vector<SubdomainID> diff;
     148             : 
     149       93794 :     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       93794 :     if (!diff.empty())
     156             :     {
     157           4 :       std::ostringstream msg;
     158           4 :       auto sep = " ";
     159           4 :       msg << "the following blocks (ids) do not exist on the mesh:";
     160           8 :       for (const auto & id : diff)
     161             :       {
     162           4 :         if (_blk_name.size() > 0)
     163             :         {
     164             :           auto & name =
     165           4 :               _blocks.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) - _vec_ids.begin());
     166           4 :           if (std::to_string(id) != name)
     167           0 :             msg << sep << name << " (" << id << ")";
     168             :           else
     169           4 :             msg << sep << id;
     170             :         }
     171             :         else
     172           0 :           msg << sep << id;
     173           4 :         sep = ", ";
     174             :       }
     175           4 :       std::vector<SubdomainID> valid_ids_vec(valid_ids.begin(), valid_ids.end());
     176           4 :       auto valid_names = _blk_mesh->getSubdomainNames(valid_ids_vec);
     177          16 :       msg << "\nBlocks names (resp. ids) that do exist: " << Moose::stringify(valid_names) << " ("
     178          24 :           << Moose::stringify(valid_ids) << ")";
     179           8 :       moose_object->paramError("block", msg.str());
     180           0 :     }
     181       93790 :   }
     182             : 
     183             :   // Get the mesh dimension for the blocks
     184      497413 :   if (blockRestricted())
     185       93790 :     _blk_dim = _blk_mesh->getBlocksMaxDimension(_blocks);
     186             :   else
     187      403623 :     _blk_dim = _blk_mesh->dimension();
     188             : 
     189             : #ifdef MOOSE_KOKKOS_ENABLED
     190      344933 :   if (moose_object->isKokkosObject({}))
     191        2523 :     initializeKokkosBlockRestrictable(_blk_mesh->getKokkosMesh());
     192             : #endif
     193      896511 : }
     194             : 
     195             : bool
     196     2089368 : BlockRestrictable::blockRestricted() const
     197             : {
     198     2089368 :   return _blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end();
     199             : }
     200             : 
     201             : const std::vector<SubdomainName> &
     202       28969 : BlockRestrictable::blocks() const
     203             : {
     204       28969 :   return _blocks;
     205             : }
     206             : 
     207             : const std::set<SubdomainID> &
     208     7630344 : BlockRestrictable::blockIDs() const
     209             : {
     210     7630344 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     211     5616195 :     return _blk_mesh->meshSubdomains();
     212             :   else
     213     2014149 :     return _blk_ids;
     214             : }
     215             : 
     216             : unsigned int
     217          26 : BlockRestrictable::numBlocks() const
     218             : {
     219          26 :   return (unsigned int)_blk_ids.size();
     220             : }
     221             : 
     222             : bool
     223           8 : BlockRestrictable::hasBlocks(const SubdomainName & name) const
     224             : {
     225             :   // Create a vector and utilize the getSubdomainIDs function, which
     226             :   // handles the ANY_BLOCK_ID (getSubdomainID does not)
     227           8 :   std::vector<SubdomainName> names(1);
     228           8 :   names[0] = name;
     229          16 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     230           8 : }
     231             : 
     232             : bool
     233           8 : BlockRestrictable::hasBlocks(const std::vector<SubdomainName> & names) const
     234             : {
     235           8 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     236             : }
     237             : 
     238             : bool
     239           0 : BlockRestrictable::hasBlocks(const std::set<SubdomainName> & names) const
     240             : {
     241           0 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     242             : }
     243             : 
     244             : bool
     245   641741829 : BlockRestrictable::hasBlocks(const SubdomainID id) const
     246             : {
     247   641741829 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     248   541283547 :     return true;
     249             :   else
     250   100458282 :     return _blk_ids.find(id) != _blk_ids.end();
     251             : }
     252             : 
     253             : bool
     254          24 : BlockRestrictable::hasBlocks(const std::vector<SubdomainID> & ids) const
     255             : {
     256          24 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     257          48 :   return hasBlocks(ids_set);
     258          24 : }
     259             : 
     260             : bool
     261        2379 : BlockRestrictable::hasBlocks(const std::set<SubdomainID> & ids) const
     262             : {
     263        2379 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     264        1062 :     return true;
     265             :   else
     266        1317 :     return std::includes(_blk_ids.begin(), _blk_ids.end(), ids.begin(), ids.end());
     267             : }
     268             : 
     269             : bool
     270     1156412 : BlockRestrictable::isBlockSubset(const std::set<SubdomainID> & ids) const
     271             : {
     272             :   // An empty input is assumed to be ANY_BLOCK_ID
     273     1156412 :   if (ids.empty() || ids.find(Moose::ANY_BLOCK_ID) != ids.end())
     274     1089225 :     return true;
     275             : 
     276       67187 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     277        1488 :     return std::includes(ids.begin(),
     278             :                          ids.end(),
     279        1488 :                          _blk_mesh->meshSubdomains().begin(),
     280        2976 :                          _blk_mesh->meshSubdomains().end());
     281             :   else
     282       65699 :     return std::includes(ids.begin(), ids.end(), _blk_ids.begin(), _blk_ids.end());
     283             : }
     284             : 
     285             : bool
     286           0 : BlockRestrictable::isBlockSubset(const std::vector<SubdomainID> & ids) const
     287             : {
     288           0 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     289           0 :   return isBlockSubset(ids_set);
     290           0 : }
     291             : 
     292             : const std::set<SubdomainID> &
     293      579315 : BlockRestrictable::meshBlockIDs() const
     294             : {
     295      579315 :   return _blk_mesh->meshSubdomains();
     296             : }
     297             : 
     298             : bool
     299       15687 : BlockRestrictable::hasBlockMaterialPropertyHelper(const std::string & prop_name)
     300             : {
     301             : 
     302             :   // Reference to MaterialWarehouse for testing and retrieving block ids
     303       15687 :   const MaterialWarehouse & warehouse = _blk_feproblem->getMaterialWarehouse();
     304             : 
     305             :   // Complete set of ids that this object is active
     306       15687 :   const std::set<SubdomainID> & ids = blockRestricted() ? blockIDs() : meshBlockIDs();
     307             : 
     308             :   // Loop over each id for this object
     309       16513 :   for (const auto & id : ids)
     310             :   {
     311             :     // Storage of material properties that have been DECLARED on this id
     312       15765 :     std::set<std::string> declared_props;
     313             : 
     314             :     // If block materials exist, populated the set of properties that were declared
     315       15765 :     if (warehouse.hasActiveBlockObjects(id))
     316             :     {
     317       15047 :       const std::vector<std::shared_ptr<MaterialBase>> & mats = warehouse.getActiveBlockObjects(id);
     318      122464 :       for (const auto & mat : mats)
     319             :       {
     320      107417 :         const std::set<std::string> & mat_props = mat->getSuppliedItems();
     321      107417 :         declared_props.insert(mat_props.begin(), mat_props.end());
     322             :       }
     323             :     }
     324             : 
     325             :     // If the supplied property is not in the list of properties on the current id, return false
     326       15765 :     if (declared_props.find(prop_name) == declared_props.end())
     327       14939 :       return false;
     328       15765 :   }
     329             : 
     330             :   // If you get here the supplied property is defined on all blocks
     331         748 :   return true;
     332             : }
     333             : 
     334             : Moose::CoordinateSystemType
     335           0 : BlockRestrictable::getBlockCoordSystem()
     336             : {
     337           0 :   if (!_blk_mesh)
     338           0 :     mooseError("No mesh available in BlockRestrictable::checkCoordSystem()");
     339           0 :   if (!_blk_feproblem)
     340           0 :     mooseError("No problem available in BlockRestrictable::checkCoordSystem()");
     341             : 
     342           0 :   const auto & subdomains = blockRestricted() ? blockIDs() : meshBlockIDs();
     343             : 
     344           0 :   if (subdomains.empty())
     345           0 :     mooseError("No subdomains found in the problem.");
     346             : 
     347             :   // make sure all subdomains are using the same coordinate system
     348           0 :   auto coord_system = _blk_feproblem->getCoordSystem(*subdomains.begin());
     349           0 :   for (auto subdomain : subdomains)
     350           0 :     if (_blk_feproblem->getCoordSystem(subdomain) != coord_system)
     351           0 :       mooseError("This object requires all subdomains to have the same coordinate system.");
     352             : 
     353           0 :   return coord_system;
     354             : }
     355             : 
     356             : void
     357     1158198 : BlockRestrictable::checkVariable(const MooseVariableFieldBase & variable) const
     358             : {
     359             :   // a variable defined on all internal sides does not need this check because
     360             :   // it can be coupled with other variables in DG kernels
     361     1168106 :   if (!_blk_mesh->interiorLowerDBlocks().empty() &&
     362        9908 :       variable.activeOnSubdomains(_blk_mesh->interiorLowerDBlocks()))
     363        3120 :     return;
     364             : 
     365     1155078 :   if (!isBlockSubset(variable.activeSubdomains()))
     366             :   {
     367         128 :     std::string var_ids = Moose::stringify(variable.activeSubdomains(), ", ");
     368          96 :     std::string obj_ids = Moose::stringify(blockRestricted() ? _blk_ids : meshBlockIDs(), ", ");
     369          32 :     mooseError("The 'block' parameter of the object '",
     370          32 :                _blk_name,
     371             :                "' must be a subset of the 'block' parameter of the variable '",
     372          32 :                variable.name(),
     373             :                "':\n    Object '",
     374          32 :                _blk_name,
     375             :                "': ",
     376             :                obj_ids,
     377             :                "\n    Variable '",
     378          32 :                variable.name(),
     379             :                "': ",
     380             :                var_ids);
     381           0 :   }
     382             : }
     383             : 
     384             : unsigned int
     385           0 : BlockRestrictable::blocksMaxDimension() const
     386             : {
     387             :   mooseAssert(_blk_dim != libMesh::invalid_uint, "Block restriction not initialized");
     388           0 :   return _blk_dim;
     389             : }

Generated by: LCOV version 1.14