LCOV - code coverage report
Current view: top level - src/outputs - BlockRestrictionDebugOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 39a256 Lines: 296 333 88.9 %
Date: 2026-07-14 14:36:17 Functions: 31 31 100.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 "BlockRestrictionDebugOutput.h"
      12             : #include "FEProblem.h"
      13             : #include "Material.h"
      14             : #include "ConsoleUtils.h"
      15             : #include "MooseMesh.h"
      16             : #include "MooseObjectName.h"
      17             : #include "NonlinearSystemBase.h"
      18             : #include "MooseVariableBase.h"
      19             : #include "BlockRestrictable.h"
      20             : #include "BoundaryRestrictable.h"
      21             : #include "KernelBase.h"
      22             : #include "AuxiliarySystem.h"
      23             : #include "AuxKernel.h"
      24             : #include "UserObject.h"
      25             : #include "MooseObject.h"
      26             : #include "InitialConditionBase.h"
      27             : #include "FVInitialConditionBase.h"
      28             : #include "Constraint.h"
      29             : 
      30             : #include "libmesh/transient_system.h"
      31             : 
      32             : #include <functional>
      33             : #include <map>
      34             : 
      35             : using namespace libMesh;
      36             : 
      37             : registerMooseObject("MooseApp", BlockRestrictionDebugOutput);
      38             : 
      39             : namespace
      40             : {
      41             : template <typename ID>
      42             : using RestrictionGroups = std::map<std::set<ID>, std::set<std::string>>;
      43             : 
      44             : template <typename ID>
      45             : std::string
      46          54 : formatRestrictionIDs(const std::set<ID> & ids,
      47             :                      const std::set<ID> & all_ids,
      48             :                      const std::string & all_text,
      49             :                      const std::function<std::string(ID)> & id_to_string)
      50             : {
      51          54 :   if (ids.empty())
      52          18 :     return "(none)";
      53             : 
      54          45 :   if (ids == all_ids)
      55           9 :     return all_text;
      56             : 
      57          36 :   std::stringstream out;
      58          36 :   unsigned int i = 0;
      59          72 :   for (const auto id : ids)
      60          36 :     out << id_to_string(id) << (++i < ids.size() ? ", " : "");
      61             : 
      62          36 :   return out.str();
      63          36 : }
      64             : 
      65             : void
      66          54 : printGroupNames(std::stringstream & out, const std::set<std::string> & names)
      67             : {
      68          54 :   std::streampos begin_string_pos = out.tellp();
      69          54 :   std::streampos curr_string_pos = begin_string_pos;
      70          54 :   unsigned int i = 0;
      71         171 :   for (const auto & name : names)
      72             :   {
      73         117 :     out << Moose::stringify(name) << (++i < names.size() ? ", " : "");
      74         117 :     curr_string_pos = out.tellp();
      75         117 :     ConsoleUtils::insertNewline(out, begin_string_pos, curr_string_pos);
      76             :   }
      77          54 :   out << '\n';
      78          54 : }
      79             : 
      80             : std::string
      81          90 : objectRestrictionName(const MooseObject & object)
      82             : {
      83          90 :   return object.type() + "/" + object.name();
      84             : }
      85             : 
      86             : void
      87          45 : addBlockRestrictionObject(RestrictionGroups<SubdomainID> & groups, const MooseObject & object)
      88             : {
      89          45 :   if (!object.enabled())
      90           0 :     return;
      91             : 
      92          45 :   const auto * const block_restrictable = dynamic_cast<const BlockRestrictable *>(&object);
      93          45 :   if (block_restrictable)
      94          45 :     groups[block_restrictable->blockIDs()].insert(objectRestrictionName(object));
      95             : }
      96             : 
      97             : void
      98          45 : addBoundaryRestrictionObject(RestrictionGroups<BoundaryID> & groups,
      99             :                              const MooseObject & object,
     100             :                              const bool include_unrestricted)
     101             : {
     102          45 :   if (!object.enabled())
     103           0 :     return;
     104             : 
     105          45 :   const auto * const boundary_restrictable = dynamic_cast<const BoundaryRestrictable *>(&object);
     106          45 :   if (!boundary_restrictable)
     107           0 :     return;
     108             : 
     109          45 :   if (!include_unrestricted && !boundary_restrictable->boundaryRestricted())
     110          27 :     return;
     111             : 
     112          18 :   const auto & ids = boundary_restrictable->boundaryRestricted()
     113          18 :                          ? boundary_restrictable->boundaryIDs()
     114           0 :                          : boundary_restrictable->meshBoundaryIDs();
     115          18 :   groups[ids].insert(objectRestrictionName(object));
     116             : }
     117             : 
     118             : template <typename T>
     119             : void
     120         111 : addWarehouseBlockRestrictionObjects(RestrictionGroups<SubdomainID> & groups,
     121             :                                     const MooseObjectWarehouseBase<T> & warehouse)
     122             : {
     123         156 :   for (const auto & object : warehouse.getObjects(/*tid = */ 0))
     124          45 :     addBlockRestrictionObject(groups, *object);
     125         111 : }
     126             : 
     127             : template <typename T>
     128             : void
     129         102 : addWarehouseBoundaryRestrictionObjects(RestrictionGroups<BoundaryID> & groups,
     130             :                                        const MooseObjectWarehouseBase<T> & warehouse,
     131             :                                        const bool include_unrestricted)
     132             : {
     133         147 :   for (const auto & object : warehouse.getObjects(/*tid = */ 0))
     134          45 :     addBoundaryRestrictionObject(groups, *object, include_unrestricted);
     135         102 : }
     136             : }
     137             : 
     138             : InputParameters
     139        3115 : BlockRestrictionDebugOutput::validParams()
     140             : {
     141        3115 :   InputParameters params = Output::validParams();
     142             : 
     143        9345 :   params.addParam<MultiMooseEnum>("scope",
     144        9345 :                                   getScopes("all"),
     145             :                                   "The types of object to output block coverage for, if nothing is "
     146             :                                   "provided everything will be output.");
     147             : 
     148       12460 :   params.addParam<NonlinearSystemName>(
     149             :       "nl_sys", "nl0", "The nonlinear system that we should output information for.");
     150        9345 :   params.addParam<bool>(
     151             :       "show_block_restriction_map",
     152        6230 :       true,
     153             :       "Print active objects for each block. This is the default block-restriction debug output.");
     154        9345 :   params.addParam<bool>("show_block_restriction_groups",
     155        6230 :                         false,
     156             :                         "Print groups of objects with identical block restrictions.");
     157        9345 :   params.addParam<bool>("show_boundary_restriction_groups",
     158        6230 :                         false,
     159             :                         "Print groups of objects with identical boundary restrictions.");
     160             : 
     161        6230 :   params.addClassDescription(
     162             :       "Debug output object for displaying information regarding block and boundary restrictions of "
     163             :       "objects.");
     164        3115 :   params.set<ExecFlagEnum>("execute_on") = EXEC_INITIAL;
     165        3115 :   return params;
     166           0 : }
     167             : 
     168             : MultiMooseEnum
     169        4928 : BlockRestrictionDebugOutput::getScopes(std::string default_scopes)
     170             : {
     171             :   return MultiMooseEnum("none all variables kernels auxvariables auxkernels materials userobjects",
     172       14784 :                         default_scopes);
     173             : }
     174             : 
     175          27 : BlockRestrictionDebugOutput::BlockRestrictionDebugOutput(const InputParameters & parameters)
     176             :   : Output(parameters),
     177          27 :     _scope(getParam<MultiMooseEnum>("scope")),
     178          27 :     _nl(_problem_ptr->getNonlinearSystemBase(
     179          27 :         _problem_ptr->nlSysNum(getParam<NonlinearSystemName>("nl_sys")))),
     180          27 :     _sys(_nl.system()),
     181          54 :     _show_block_restriction_map(getParam<bool>("show_block_restriction_map")),
     182          54 :     _show_block_restriction_groups(getParam<bool>("show_block_restriction_groups")),
     183          81 :     _show_boundary_restriction_groups(getParam<bool>("show_boundary_restriction_groups"))
     184             : {
     185          27 : }
     186             : 
     187             : void
     188          27 : BlockRestrictionDebugOutput::output()
     189             : {
     190          27 :   if (_show_block_restriction_map)
     191          18 :     printBlockRestrictionMap();
     192             : 
     193          27 :   if (_show_block_restriction_groups)
     194           9 :     printBlockRestrictionGroups();
     195             : 
     196          27 :   if (_show_boundary_restriction_groups)
     197           9 :     printBoundaryRestrictionGroups();
     198          27 : }
     199             : 
     200             : void
     201          18 : BlockRestrictionDebugOutput::printBlockRestrictionMap() const
     202             : {
     203             :   // is there anything to do?
     204          54 :   if (_scope.isValid() && _scope.contains("none"))
     205           0 :     return;
     206             : 
     207             :   // Build output stream
     208          18 :   std::stringstream out;
     209             : 
     210         396 :   auto printCategoryAndNames = [&out](std::string category, std::set<std::string> & names)
     211             :   {
     212         396 :     const auto n = names.size();
     213         396 :     if (n > 0)
     214             :     {
     215             :       // print the category and number of items
     216         108 :       out << "    " << category << " (" << n << " " << ((n == 1) ? "item" : "items") << "): ";
     217             : 
     218             :       // If we would just use Moose::stringify(names), the indention is not right.
     219             :       // So we are printing the names one by one and using ConsoleUtils::insertNewline.
     220         108 :       std::streampos begin_string_pos = out.tellp();
     221         108 :       std::streampos curr_string_pos = begin_string_pos;
     222         108 :       unsigned int i = 0;
     223         234 :       for (const auto & name : names)
     224             :       {
     225         126 :         out << Moose::stringify(name) << ((i++ < (n - 1)) ? ", " : "");
     226         126 :         curr_string_pos = out.tellp();
     227         126 :         ConsoleUtils::insertNewline(out, begin_string_pos, curr_string_pos);
     228             :       }
     229         108 :       out << '\n';
     230         108 :       return true;
     231             :     }
     232             :     else
     233             :     {
     234         288 :       return false;
     235             :     }
     236          18 :   };
     237             : 
     238             :   // Reference to mesh for getting block names
     239          18 :   MooseMesh & mesh = _problem_ptr->mesh();
     240             : 
     241             :   // set of all subdomains in the mesh
     242          18 :   const std::set<SubdomainID> & mesh_subdomains = mesh.meshSubdomains();
     243             : 
     244             :   // get kernels via reference to the Kernel warehouse
     245          18 :   const auto & kernel_warehouse = _nl.getKernelWarehouse();
     246          18 :   const auto & kernels = kernel_warehouse.getObjects(/*tid = */ 0);
     247             : 
     248             :   // AuxSystem
     249          18 :   const auto & auxSystem = _problem_ptr->getAuxiliarySystem();
     250             : 
     251             :   // Reference to the Material warehouse
     252          18 :   const auto & material_warehouse = _problem_ptr->getMaterialWarehouse();
     253             : 
     254             :   // get all user objects
     255          18 :   std::vector<UserObject *> userObjects;
     256          18 :   _problem_ptr->theWarehouse()
     257          18 :       .query()
     258          18 :       .condition<AttribSystem>("UserObject")
     259          36 :       .condition<AttribThread>(0)
     260          18 :       .queryIntoUnsorted(userObjects);
     261             : 
     262             :   // do we have to check all object types?
     263          36 :   const bool include_all = !_scope.isValid() || _scope.contains("all");
     264             : 
     265             :   // iterate all subdomains
     266          54 :   for (const auto & subdomain_id : mesh_subdomains)
     267             :   {
     268             :     // get the corresponding subdomain name
     269          36 :     const auto & subdomain_name = mesh.getSubdomainName(subdomain_id);
     270             : 
     271          36 :     out << "\n";
     272          36 :     out << "  Subdomain '" << subdomain_name << "' (id " << subdomain_id << "):\n";
     273             : 
     274          36 :     bool objectsFound = false;
     275             : 
     276             :     // Variables
     277          36 :     if (include_all || _scope.contains("variables"))
     278             :     {
     279          36 :       std::set<std::string> names;
     280          72 :       for (unsigned int var_num = 0; var_num < _sys.n_vars(); var_num++)
     281             :       {
     282          36 :         const auto & var_name = _sys.variable_name(var_num);
     283          36 :         if (_problem_ptr->hasVariable(var_name))
     284             :         {
     285             :           const MooseVariableBase & var =
     286          36 :               _problem_ptr->getVariable(/*tid = */ 0,
     287             :                                         var_name,
     288             :                                         Moose::VarKindType::VAR_ANY,
     289          36 :                                         Moose::VarFieldType::VAR_FIELD_ANY);
     290          36 :           if (var.hasBlocks(subdomain_id))
     291          36 :             names.insert(var_name);
     292             :         }
     293             :       }
     294          72 :       objectsFound = printCategoryAndNames("Variables", names) || objectsFound;
     295          36 :     }
     296             : 
     297             :     // Kernels
     298          36 :     if (include_all || _scope.contains("kernels"))
     299             :     {
     300          36 :       std::set<std::string> names;
     301          72 :       for (const auto & kernel : kernels)
     302             :       {
     303          36 :         if (kernel->hasBlocks(subdomain_id))
     304          36 :           names.insert(kernel->name());
     305             :       }
     306          72 :       objectsFound = printCategoryAndNames("Kernels", names) || objectsFound;
     307          36 :     }
     308             : 
     309             :     // AuxVariables
     310          36 :     if (include_all || _scope.contains("auxvariables"))
     311             :     {
     312          36 :       std::set<std::string> names;
     313          36 :       const auto & sys = auxSystem.system();
     314          36 :       for (unsigned int vg = 0; vg < sys.n_variable_groups(); vg++)
     315             :       {
     316           0 :         const VariableGroup & vg_description(sys.variable_group(vg));
     317           0 :         for (unsigned int vn = 0; vn < vg_description.n_variables(); vn++)
     318             :         {
     319           0 :           if (vg_description.active_on_subdomain(subdomain_id))
     320           0 :             names.insert(vg_description.name(vn));
     321             :         }
     322             :       }
     323          72 :       objectsFound = printCategoryAndNames("AuxVariables", names) || objectsFound;
     324          36 :     }
     325             : 
     326             :     // AuxKernels
     327          36 :     if (include_all || _scope.contains("auxkernels"))
     328             :     {
     329             : 
     330             :       {
     331          36 :         const auto & wh = auxSystem.nodalAuxWarehouse();
     332          36 :         std::set<std::string> names;
     333          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     334             :         {
     335           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     336           0 :           for (auto & auxkernel : auxkernels)
     337           0 :             names.insert(auxkernel->name());
     338             :         }
     339          72 :         objectsFound = printCategoryAndNames("AuxKernels[nodal]", names) || objectsFound;
     340          36 :       }
     341             : 
     342             :       {
     343          36 :         const auto & wh = auxSystem.nodalVectorAuxWarehouse();
     344          36 :         std::set<std::string> names;
     345          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     346             :         {
     347           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     348           0 :           for (auto & auxkernel : auxkernels)
     349           0 :             names.insert(auxkernel->name());
     350             :         }
     351          72 :         objectsFound = printCategoryAndNames("AuxKernels[nodalVector]", names) || objectsFound;
     352          36 :       }
     353             : 
     354             :       {
     355          36 :         const auto & wh = auxSystem.nodalArrayAuxWarehouse();
     356          36 :         std::set<std::string> names;
     357          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     358             :         {
     359           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     360           0 :           for (auto & auxkernel : auxkernels)
     361           0 :             names.insert(auxkernel->name());
     362             :         }
     363          72 :         objectsFound = printCategoryAndNames("AuxKernels[nodalArray]", names) || objectsFound;
     364          36 :       }
     365             : 
     366             :       {
     367          36 :         const auto & wh = auxSystem.elemAuxWarehouse();
     368          36 :         std::set<std::string> names;
     369          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     370             :         {
     371           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     372           0 :           for (auto & auxkernel : auxkernels)
     373           0 :             names.insert(auxkernel->name());
     374             :         }
     375          72 :         objectsFound = printCategoryAndNames("AuxKernels[elemAux]", names) || objectsFound;
     376          36 :       }
     377             : 
     378             :       {
     379          36 :         const auto & wh = auxSystem.elemVectorAuxWarehouse();
     380          36 :         std::set<std::string> names;
     381          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     382             :         {
     383           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     384           0 :           for (auto & auxkernel : auxkernels)
     385           0 :             names.insert(auxkernel->name());
     386             :         }
     387          72 :         objectsFound = printCategoryAndNames("AuxKernels[elemVector]", names) || objectsFound;
     388          36 :       }
     389             : 
     390             :       {
     391          36 :         const auto & wh = auxSystem.elemArrayAuxWarehouse();
     392          36 :         std::set<std::string> names;
     393          36 :         if (wh.hasActiveBlockObjects(subdomain_id))
     394             :         {
     395           0 :           const auto & auxkernels = wh.getActiveBlockObjects(subdomain_id);
     396           0 :           for (auto & auxkernel : auxkernels)
     397           0 :             names.insert(auxkernel->name());
     398             :         }
     399          72 :         objectsFound = printCategoryAndNames("AuxKernels[elemArray]", names) || objectsFound;
     400          36 :       }
     401             :     }
     402             : 
     403             :     // Materials
     404          36 :     if (include_all || _scope.contains("materials"))
     405             :     {
     406          36 :       std::set<std::string> names;
     407          36 :       if (material_warehouse.hasActiveBlockObjects(subdomain_id))
     408             :       {
     409          36 :         auto const objs = material_warehouse.getBlockObjects(subdomain_id);
     410          90 :         for (const auto & mat : objs)
     411          54 :           names.insert(mat->name());
     412          36 :       }
     413          72 :       objectsFound = printCategoryAndNames("Materials", names) || objectsFound;
     414          36 :     }
     415             : 
     416             :     // UserObjects
     417          36 :     if (include_all || _scope.contains("userobjects"))
     418             :     {
     419          36 :       std::set<std::string> names;
     420          36 :       for (const auto & obj : userObjects)
     421           0 :         if (BlockRestrictable * blockrestrictable_obj = dynamic_cast<BlockRestrictable *>(obj))
     422           0 :           if (blockrestrictable_obj->hasBlocks(subdomain_id))
     423           0 :             names.insert(obj->name());
     424          72 :       objectsFound = printCategoryAndNames("UserObjects", names) || objectsFound;
     425          36 :     }
     426             : 
     427          36 :     if (!objectsFound)
     428           0 :       out << "    (no objects found)\n";
     429             :   }
     430             : 
     431          18 :   out << std::flush;
     432             : 
     433             :   // Write the stored string to the ConsoleUtils output objects
     434          18 :   _console << "\n[DBG] Block-Restrictions (" << mesh_subdomains.size()
     435          18 :            << " subdomains): showing active objects\n";
     436          18 :   _console << std::setw(ConsoleUtils::console_field_width) << out.str() << std::endl;
     437          18 : }
     438             : 
     439             : void
     440           9 : BlockRestrictionDebugOutput::printBlockRestrictionGroups() const
     441             : {
     442           9 :   MooseMesh & mesh = _problem_ptr->mesh();
     443           9 :   const auto & mesh_subdomains = mesh.meshSubdomains();
     444             : 
     445           9 :   RestrictionGroups<SubdomainID> groups;
     446           9 :   std::vector<MooseObject *> objects;
     447           9 :   _problem_ptr->theWarehouse()
     448           9 :       .query()
     449           9 :       .condition<AttribInterfaces>(Interfaces::BlockRestrictable)
     450          18 :       .condition<AttribThread>(0)
     451           9 :       .queryIntoUnsorted(objects);
     452             : 
     453          18 :   for (const auto object : objects)
     454           9 :     if (object->enabled())
     455             :     {
     456           9 :       const auto * const block_restrictable = dynamic_cast<const BlockRestrictable *>(object);
     457             :       mooseAssert(block_restrictable, "Query returned an object without BlockRestrictable");
     458           9 :       groups[block_restrictable->blockIDs()].insert(objectRestrictionName(*object));
     459             :     }
     460             : 
     461             :   // Variables and aux variables are stored in libMesh systems / VariableWarehouse, not in
     462             :   // theWarehouse(), so add their block restrictions explicitly.
     463          18 :   for (const auto var_num : make_range(_sys.n_vars()))
     464             :   {
     465           9 :     const auto & var_name = _sys.variable_name(var_num);
     466           9 :     if (_problem_ptr->hasVariable(var_name))
     467             :     {
     468           9 :       const auto & var = _problem_ptr->getVariable(
     469             :           /*tid = */ 0, var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
     470           9 :       groups[var.blockIDs()].insert("Variable/" + var_name);
     471             :     }
     472             :   }
     473             : 
     474           9 :   const auto & aux_system = _problem_ptr->getAuxiliarySystem().system();
     475          18 :   for (const auto vg : make_range(aux_system.n_variable_groups()))
     476             :   {
     477           9 :     const VariableGroup & vg_description(aux_system.variable_group(vg));
     478           9 :     std::set<SubdomainID> blocks;
     479          27 :     for (const auto subdomain_id : mesh_subdomains)
     480          18 :       if (vg_description.active_on_subdomain(subdomain_id))
     481          18 :         blocks.insert(subdomain_id);
     482             : 
     483          27 :     for (const auto vn : make_range(vg_description.n_variables()))
     484          18 :       groups[blocks].insert("AuxVariable/" + vg_description.name(vn));
     485           9 :   }
     486             : 
     487             :   // Custom warehouses below are not covered by theWarehouse() queries.
     488           9 :   const auto & aux_system_base = _problem_ptr->getAuxiliarySystem();
     489           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.nodalAuxWarehouse());
     490           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.mortarNodalAuxWarehouse());
     491           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.nodalVectorAuxWarehouse());
     492           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.nodalArrayAuxWarehouse());
     493           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.elemAuxWarehouse());
     494           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.elemVectorAuxWarehouse());
     495           9 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.elemArrayAuxWarehouse());
     496             : #ifdef MOOSE_KOKKOS_ENABLED
     497           6 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.kokkosNodalAuxWarehouse());
     498           6 :   addWarehouseBlockRestrictionObjects(groups, aux_system_base.kokkosElemAuxWarehouse());
     499             : #endif
     500             : 
     501           9 :   addWarehouseBlockRestrictionObjects(groups, _problem_ptr->getInitialConditionWarehouse());
     502           9 :   addWarehouseBlockRestrictionObjects(groups, _problem_ptr->getFVInitialConditionWarehouse());
     503           9 :   addWarehouseBlockRestrictionObjects(groups, _nl.getConstraintWarehouse());
     504             : 
     505             :   // Materials use MaterialWarehouse, which also owns automatically-created face and neighbor
     506             :   // materials; report the primary material objects from the aggregate material warehouse.
     507           9 :   addWarehouseBlockRestrictionObjects(groups, _problem_ptr->getMaterialWarehouse());
     508             : 
     509           9 :   std::stringstream out;
     510          36 :   for (const auto & group : groups)
     511             :   {
     512          27 :     out << "\n";
     513             :     out << "  Blocks "
     514          81 :         << formatRestrictionIDs<SubdomainID>(group.first,
     515             :                                              mesh_subdomains,
     516             :                                              "all blocks",
     517           0 :                                              [&mesh](const SubdomainID id)
     518             :                                              {
     519           9 :                                                const auto & name = mesh.getSubdomainName(id);
     520           9 :                                                return name.empty() ? std::to_string(id)
     521          18 :                                                                    : "'" + name + "' (id " +
     522          27 :                                                                          std::to_string(id) + ")";
     523             :                                              })
     524          54 :         << " (" << group.second.size() << " " << (group.second.size() == 1 ? "item" : "items")
     525          27 :         << "): ";
     526          27 :     printGroupNames(out, group.second);
     527             :   }
     528             : 
     529           9 :   if (groups.empty())
     530           0 :     out << "\n  (no objects found)\n";
     531             : 
     532           9 :   out << std::flush;
     533             : 
     534           9 :   _console << "\n[DBG] Block-Restriction Groups (" << groups.size()
     535           9 :            << " groups): showing objects with matching block restrictions\n";
     536           9 :   _console << std::setw(ConsoleUtils::console_field_width) << out.str() << std::endl;
     537           9 : }
     538             : 
     539             : void
     540           9 : BlockRestrictionDebugOutput::printBoundaryRestrictionGroups() const
     541             : {
     542           9 :   MooseMesh & mesh = _problem_ptr->mesh();
     543           9 :   const auto & mesh_boundaries = mesh.getBoundaryIDs();
     544             : 
     545           9 :   RestrictionGroups<BoundaryID> groups;
     546           9 :   std::vector<MooseObject *> objects;
     547           9 :   _problem_ptr->theWarehouse()
     548           9 :       .query()
     549           9 :       .condition<AttribInterfaces>(Interfaces::BoundaryRestrictable)
     550          18 :       .condition<AttribThread>(0)
     551           9 :       .queryIntoUnsorted(objects);
     552             : 
     553          27 :   for (const auto object : objects)
     554          18 :     if (object->enabled())
     555             :     {
     556          18 :       const auto * const boundary_restrictable = dynamic_cast<const BoundaryRestrictable *>(object);
     557             :       mooseAssert(boundary_restrictable, "Query returned an object without BoundaryRestrictable");
     558          18 :       const auto & ids = boundary_restrictable->boundaryRestricted()
     559          18 :                              ? boundary_restrictable->boundaryIDs()
     560           0 :                              : boundary_restrictable->meshBoundaryIDs();
     561          18 :       groups[ids].insert(objectRestrictionName(*object));
     562             :     }
     563             : 
     564             :   // Custom warehouses below are not covered by theWarehouse() queries. For these explicit passes,
     565             :   // only boundary-restricted objects belong in boundary-restriction groups; block-only objects are
     566             :   // already represented in the block groups.
     567           9 :   const auto & aux_system = _problem_ptr->getAuxiliarySystem();
     568           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.nodalAuxWarehouse(), false);
     569           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.mortarNodalAuxWarehouse(), false);
     570           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.nodalVectorAuxWarehouse(), false);
     571           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.nodalArrayAuxWarehouse(), false);
     572           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.elemAuxWarehouse(), false);
     573           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.elemVectorAuxWarehouse(), false);
     574           9 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.elemArrayAuxWarehouse(), false);
     575             : #ifdef MOOSE_KOKKOS_ENABLED
     576           6 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.kokkosNodalAuxWarehouse(), false);
     577           6 :   addWarehouseBoundaryRestrictionObjects(groups, aux_system.kokkosElemAuxWarehouse(), false);
     578             : #endif
     579             : 
     580           9 :   addWarehouseBoundaryRestrictionObjects(
     581           9 :       groups, _problem_ptr->getInitialConditionWarehouse(), false);
     582           9 :   addWarehouseBoundaryRestrictionObjects(groups, _nl.getConstraintWarehouse(), false);
     583           9 :   addWarehouseBoundaryRestrictionObjects(groups, _problem_ptr->getMaterialWarehouse(), false);
     584             : 
     585           9 :   std::stringstream out;
     586          36 :   for (const auto & group : groups)
     587             :   {
     588          27 :     out << "\n";
     589             :     out << "  Boundaries "
     590          81 :         << formatRestrictionIDs<BoundaryID>(group.first,
     591             :                                             mesh_boundaries,
     592             :                                             "all boundaries",
     593           0 :                                             [&mesh](const BoundaryID id)
     594             :                                             {
     595          27 :                                               const auto name = mesh.getBoundaryString(id);
     596          54 :                                               return "'" + name + "' (id " + std::to_string(id) +
     597          54 :                                                      ")";
     598          27 :                                             })
     599          54 :         << " (" << group.second.size() << " " << (group.second.size() == 1 ? "item" : "items")
     600          27 :         << "): ";
     601          27 :     printGroupNames(out, group.second);
     602             :   }
     603             : 
     604           9 :   if (groups.empty())
     605           0 :     out << "\n  (no objects found)\n";
     606             : 
     607           9 :   out << std::flush;
     608             : 
     609           9 :   _console << "\n[DBG] Boundary-Restriction Groups (" << groups.size()
     610           9 :            << " groups): showing objects with matching boundary restrictions\n";
     611           9 :   _console << std::setw(ConsoleUtils::console_field_width) << out.str() << std::endl;
     612           9 : }

Generated by: LCOV version 1.14