LCOV - code coverage report
Current view: top level - src/interfaces - BlockRestrictable.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 130 172 75.6 %
Date: 2025-08-08 20:01:16 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    11227174 : BlockRestrictable::validParams()
      22             : {
      23             :   // Create InputParameters object that will be appended to the parameters for the inheriting object
      24    11227174 :   InputParameters params = emptyInputParameters();
      25             : 
      26             :   // Add the user-facing 'block' input parameter
      27    11227174 :   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    11227174 :   if (!params.have_parameter<bool>("_dual_restrictable"))
      33    11227174 :     params.addPrivateParam<bool>("_dual_restrictable", false);
      34             : 
      35             :   // Return the parameters
      36    11227174 :   return params;
      37           0 : }
      38             : 
      39             : // Standard constructor
      40      483819 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object, bool initialize /*=true*/)
      41      483819 :   : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      42      967638 :     _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
      43      483819 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      44             :                        : NULL),
      45      483819 :     _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      46             :                                                   : NULL),
      47      483819 :     _boundary_ids(_empty_boundary_ids),
      48      483819 :     _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      49      483819 :     _blk_name(moose_object->getParam<std::string>("_object_name")),
      50      967638 :     _blk_dim(libMesh::invalid_uint)
      51             : {
      52      483819 :   if (initialize)
      53      483819 :     initializeBlockRestrictable(moose_object);
      54      483815 : }
      55             : 
      56             : // Dual restricted constructor
      57           0 : BlockRestrictable::BlockRestrictable(const MooseObject * moose_object,
      58           0 :                                      const std::set<BoundaryID> & boundary_ids)
      59           0 :   : _blk_dual_restrictable(moose_object->getParam<bool>("_dual_restrictable")),
      60           0 :     _blk_feproblem(moose_object->isParamValid("_fe_problem_base")
      61           0 :                        ? moose_object->getParam<FEProblemBase *>("_fe_problem_base")
      62             :                        : NULL),
      63           0 :     _blk_mesh(moose_object->isParamValid("_mesh") ? moose_object->getParam<MooseMesh *>("_mesh")
      64             :                                                   : NULL),
      65           0 :     _boundary_ids(boundary_ids),
      66           0 :     _blk_tid(moose_object->isParamValid("_tid") ? moose_object->getParam<THREAD_ID>("_tid") : 0),
      67           0 :     _blk_name(moose_object->getParam<std::string>("_object_name")),
      68           0 :     _blk_dim(libMesh::invalid_uint)
      69             : {
      70           0 :   initializeBlockRestrictable(moose_object);
      71           0 : }
      72             : 
      73             : void
      74      483819 : BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
      75             : {
      76             :   // If the mesh pointer is not defined, but FEProblemBase is, get it from there
      77      483819 :   if (_blk_feproblem != NULL && _blk_mesh == NULL)
      78      483819 :     _blk_mesh = &_blk_feproblem->mesh();
      79             : 
      80             :   // Check that the mesh pointer was defined, it is required for this class to operate
      81      483819 :   if (_blk_mesh == NULL)
      82           0 :     mooseError("The input parameters must contain a pointer to FEProblem via '_fe_problem' or a "
      83             :                "pointer to the MooseMesh via '_mesh'");
      84             : 
      85             :   // Populate the MaterialData pointer
      86      483819 :   if (_blk_feproblem != NULL)
      87      483819 :     _blk_material_data = &_blk_feproblem->getMaterialData(Moose::BLOCK_MATERIAL_DATA, _blk_tid);
      88             : 
      89             :   // The 'block' input is defined
      90      483819 :   if (moose_object->isParamValid("block"))
      91             :   {
      92             :     // Extract the blocks from the input
      93       72188 :     _blocks = moose_object->getParam<std::vector<SubdomainName>>("block");
      94             : 
      95             :     // Store the IDs in a set, handling ANY_BLOCK_ID if supplied
      96       72188 :     if (std::find(_blocks.begin(), _blocks.end(), "ANY_BLOCK_ID") != _blocks.end())
      97        4368 :       _blk_ids.insert(Moose::ANY_BLOCK_ID);
      98             :     else
      99             :     {
     100             :       // Get the IDs from the supplied names
     101       67820 :       _vec_ids = _blk_mesh->getSubdomainIDs(_blocks);
     102       67820 :       _blk_ids.insert(_vec_ids.begin(), _vec_ids.end());
     103             :     }
     104             :   }
     105             : 
     106             :   // When 'blocks' is not set and there is a "variable", use the blocks from the variable
     107      411631 :   else if (moose_object->isParamValid("variable"))
     108             :   {
     109      201243 :     std::string variable_name = moose_object->parameters().getMooseType("variable");
     110      201243 :     if (!variable_name.empty())
     111      173928 :       _blk_ids = _blk_feproblem
     112      347856 :                      ->getVariable(_blk_tid,
     113             :                                    variable_name,
     114             :                                    Moose::VarKindType::VAR_ANY,
     115             :                                    Moose::VarFieldType::VAR_FIELD_ANY)
     116      173928 :                      .activeSubdomains();
     117      201243 :   }
     118             : 
     119             :   // Produce error if the object is not allowed to be both block and boundary restricted
     120      483819 :   if (!_blk_dual_restrictable && !_boundary_ids.empty() && !_boundary_ids.empty())
     121           0 :     if (!_boundary_ids.empty() && _boundary_ids.find(Moose::ANY_BOUNDARY_ID) == _boundary_ids.end())
     122           0 :       moose_object->paramError("block",
     123             :                                "Attempted to restrict the object '",
     124           0 :                                _blk_name,
     125             :                                "' to a block, but the object is already restricted by boundary");
     126             : 
     127             :   // If no blocks were defined above, specify that it is valid on all blocks
     128      483819 :   if (_blk_ids.empty() && !moose_object->isParamValid("boundary"))
     129             :   {
     130      390475 :     _blk_ids.insert(Moose::ANY_BLOCK_ID);
     131      780950 :     _blocks = {"ANY_BLOCK_ID"};
     132             :   }
     133             : 
     134             :   // If this object is block restricted, check that defined blocks exist on the mesh
     135      483819 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end())
     136             :   {
     137       88976 :     const std::set<SubdomainID> & valid_ids = _blk_mesh->meshSubdomains();
     138       88976 :     std::vector<SubdomainID> diff;
     139             : 
     140       88976 :     std::set_difference(_blk_ids.begin(),
     141             :                         _blk_ids.end(),
     142             :                         valid_ids.begin(),
     143             :                         valid_ids.end(),
     144             :                         std::back_inserter(diff));
     145             : 
     146       88976 :     if (!diff.empty())
     147             :     {
     148           4 :       std::ostringstream msg;
     149           4 :       auto sep = " ";
     150           4 :       msg << "the following blocks (ids) do not exist on the mesh:";
     151           8 :       for (const auto & id : diff)
     152             :       {
     153           4 :         if (_blk_name.size() > 0)
     154             :         {
     155             :           auto & name =
     156           4 :               _blocks.at(std::find(_vec_ids.begin(), _vec_ids.end(), id) - _vec_ids.begin());
     157           4 :           if (std::to_string(id) != name)
     158           0 :             msg << sep << name << " (" << id << ")";
     159             :           else
     160           4 :             msg << sep << id;
     161             :         }
     162             :         else
     163           0 :           msg << sep << id;
     164           4 :         sep = ", ";
     165             :       }
     166           4 :       std::vector<SubdomainID> valid_ids_vec(valid_ids.begin(), valid_ids.end());
     167           4 :       auto valid_names = _blk_mesh->getSubdomainNames(valid_ids_vec);
     168           8 :       msg << "\nBlocks names (resp. ids) that do exist: " << Moose::stringify(valid_names) << " ("
     169           8 :           << Moose::stringify(valid_ids) << ")";
     170           4 :       moose_object->paramError("block", msg.str());
     171           0 :     }
     172       88972 :   }
     173             : 
     174             :   // Get the mesh dimension for the blocks
     175      483815 :   if (blockRestricted())
     176       88972 :     _blk_dim = _blk_mesh->getBlocksMaxDimension(_blocks);
     177             :   else
     178      394843 :     _blk_dim = _blk_mesh->dimension();
     179      874290 : }
     180             : 
     181             : bool
     182     2034025 : BlockRestrictable::blockRestricted() const
     183             : {
     184     2034025 :   return _blk_ids.find(Moose::ANY_BLOCK_ID) == _blk_ids.end();
     185             : }
     186             : 
     187             : const std::vector<SubdomainName> &
     188       28835 : BlockRestrictable::blocks() const
     189             : {
     190       28835 :   return _blocks;
     191             : }
     192             : 
     193             : const std::set<SubdomainID> &
     194     7589112 : BlockRestrictable::blockIDs() const
     195             : {
     196     7589112 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     197     5598413 :     return _blk_mesh->meshSubdomains();
     198             :   else
     199     1990699 :     return _blk_ids;
     200             : }
     201             : 
     202             : unsigned int
     203          26 : BlockRestrictable::numBlocks() const
     204             : {
     205          26 :   return (unsigned int)_blk_ids.size();
     206             : }
     207             : 
     208             : bool
     209           8 : BlockRestrictable::hasBlocks(const SubdomainName & name) const
     210             : {
     211             :   // Create a vector and utilize the getSubdomainIDs function, which
     212             :   // handles the ANY_BLOCK_ID (getSubdomainID does not)
     213           8 :   std::vector<SubdomainName> names(1);
     214           8 :   names[0] = name;
     215          16 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     216           8 : }
     217             : 
     218             : bool
     219           8 : BlockRestrictable::hasBlocks(const std::vector<SubdomainName> & names) const
     220             : {
     221           8 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     222             : }
     223             : 
     224             : bool
     225           0 : BlockRestrictable::hasBlocks(const std::set<SubdomainName> & names) const
     226             : {
     227           0 :   return hasBlocks(_blk_mesh->getSubdomainIDs(names));
     228             : }
     229             : 
     230             : bool
     231   640424842 : BlockRestrictable::hasBlocks(const SubdomainID id) const
     232             : {
     233   640424842 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     234   540056453 :     return true;
     235             :   else
     236   100368389 :     return _blk_ids.find(id) != _blk_ids.end();
     237             : }
     238             : 
     239             : bool
     240          24 : BlockRestrictable::hasBlocks(const std::vector<SubdomainID> & ids) const
     241             : {
     242          24 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     243          48 :   return hasBlocks(ids_set);
     244          24 : }
     245             : 
     246             : bool
     247        2365 : BlockRestrictable::hasBlocks(const std::set<SubdomainID> & ids) const
     248             : {
     249        2365 :   if (_blk_ids.empty() || _blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     250        1048 :     return true;
     251             :   else
     252        1317 :     return std::includes(_blk_ids.begin(), _blk_ids.end(), ids.begin(), ids.end());
     253             : }
     254             : 
     255             : bool
     256     1126761 : BlockRestrictable::isBlockSubset(const std::set<SubdomainID> & ids) const
     257             : {
     258             :   // An empty input is assumed to be ANY_BLOCK_ID
     259     1126761 :   if (ids.empty() || ids.find(Moose::ANY_BLOCK_ID) != ids.end())
     260     1068876 :     return true;
     261             : 
     262       57885 :   if (_blk_ids.find(Moose::ANY_BLOCK_ID) != _blk_ids.end())
     263        1488 :     return std::includes(ids.begin(),
     264             :                          ids.end(),
     265        1488 :                          _blk_mesh->meshSubdomains().begin(),
     266        2976 :                          _blk_mesh->meshSubdomains().end());
     267             :   else
     268       56397 :     return std::includes(ids.begin(), ids.end(), _blk_ids.begin(), _blk_ids.end());
     269             : }
     270             : 
     271             : bool
     272           0 : BlockRestrictable::isBlockSubset(const std::vector<SubdomainID> & ids) const
     273             : {
     274           0 :   std::set<SubdomainID> ids_set(ids.begin(), ids.end());
     275           0 :   return isBlockSubset(ids_set);
     276           0 : }
     277             : 
     278             : const std::set<SubdomainID> &
     279      559967 : BlockRestrictable::meshBlockIDs() const
     280             : {
     281      559967 :   return _blk_mesh->meshSubdomains();
     282             : }
     283             : 
     284             : bool
     285       14625 : BlockRestrictable::hasBlockMaterialPropertyHelper(const std::string & prop_name)
     286             : {
     287             : 
     288             :   // Reference to MaterialWarehouse for testing and retrieving block ids
     289       14625 :   const MaterialWarehouse & warehouse = _blk_feproblem->getMaterialWarehouse();
     290             : 
     291             :   // Complete set of ids that this object is active
     292       14625 :   const std::set<SubdomainID> & ids = blockRestricted() ? blockIDs() : meshBlockIDs();
     293             : 
     294             :   // Loop over each id for this object
     295       15433 :   for (const auto & id : ids)
     296             :   {
     297             :     // Storage of material properties that have been DECLARED on this id
     298       14703 :     std::set<std::string> declared_props;
     299             : 
     300             :     // If block materials exist, populated the set of properties that were declared
     301       14703 :     if (warehouse.hasActiveBlockObjects(id))
     302             :     {
     303       13993 :       const std::vector<std::shared_ptr<MaterialBase>> & mats = warehouse.getActiveBlockObjects(id);
     304      120342 :       for (const auto & mat : mats)
     305             :       {
     306      106349 :         const std::set<std::string> & mat_props = mat->getSuppliedItems();
     307      106349 :         declared_props.insert(mat_props.begin(), mat_props.end());
     308             :       }
     309             :     }
     310             : 
     311             :     // If the supplied property is not in the list of properties on the current id, return false
     312       14703 :     if (declared_props.find(prop_name) == declared_props.end())
     313       13895 :       return false;
     314       14703 :   }
     315             : 
     316             :   // If you get here the supplied property is defined on all blocks
     317         730 :   return true;
     318             : }
     319             : 
     320             : Moose::CoordinateSystemType
     321           0 : BlockRestrictable::getBlockCoordSystem()
     322             : {
     323           0 :   if (!_blk_mesh)
     324           0 :     mooseError("No mesh available in BlockRestrictable::checkCoordSystem()");
     325           0 :   if (!_blk_feproblem)
     326           0 :     mooseError("No problem available in BlockRestrictable::checkCoordSystem()");
     327             : 
     328           0 :   const auto & subdomains = blockRestricted() ? blockIDs() : meshBlockIDs();
     329             : 
     330           0 :   if (subdomains.empty())
     331           0 :     mooseError("No subdomains found in the problem.");
     332             : 
     333             :   // make sure all subdomains are using the same coordinate system
     334           0 :   auto coord_system = _blk_feproblem->getCoordSystem(*subdomains.begin());
     335           0 :   for (auto subdomain : subdomains)
     336           0 :     if (_blk_feproblem->getCoordSystem(subdomain) != coord_system)
     337           0 :       mooseError("This object requires all subdomains to have the same coordinate system.");
     338             : 
     339           0 :   return coord_system;
     340             : }
     341             : 
     342             : void
     343     1128541 : BlockRestrictable::checkVariable(const MooseVariableFieldBase & variable) const
     344             : {
     345             :   // a variable defined on all internal sides does not need this check because
     346             :   // it can be coupled with other variables in DG kernels
     347     1138399 :   if (!_blk_mesh->interiorLowerDBlocks().empty() &&
     348        9858 :       variable.activeOnSubdomains(_blk_mesh->interiorLowerDBlocks()))
     349        3114 :     return;
     350             : 
     351     1125427 :   if (!isBlockSubset(variable.activeSubdomains()))
     352             :   {
     353          32 :     std::string var_ids = Moose::stringify(variable.activeSubdomains(), ", ");
     354          32 :     std::string obj_ids = Moose::stringify(blockRestricted() ? _blk_ids : meshBlockIDs(), ", ");
     355          96 :     mooseError("The 'block' parameter of the object '",
     356          32 :                _blk_name,
     357             :                "' must be a subset of the 'block' parameter of the variable '",
     358          32 :                variable.name(),
     359             :                "':\n    Object '",
     360          32 :                _blk_name,
     361             :                "': ",
     362             :                obj_ids,
     363             :                "\n    Variable '",
     364          32 :                variable.name(),
     365             :                "': ",
     366             :                var_ids);
     367           0 :   }
     368             : }
     369             : 
     370             : unsigned int
     371           0 : BlockRestrictable::blocksMaxDimension() const
     372             : {
     373             :   mooseAssert(_blk_dim != libMesh::invalid_uint, "Block restriction not initialized");
     374           0 :   return _blk_dim;
     375             : }

Generated by: LCOV version 1.14