LCOV - code coverage report
Current view: top level - src/actions - ActionWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 909fe5 Lines: 203 231 87.9 %
Date: 2025-08-29 20:01:24 Functions: 21 23 91.3 %
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             : #include "ActionWarehouse.h"
      11             : #include "ActionFactory.h"
      12             : #include "Parser.h"
      13             : #include "MooseObjectAction.h"
      14             : #include "InputFileFormatter.h"
      15             : #include "InputParameters.h"
      16             : #include "MooseMesh.h"
      17             : #include "AddVariableAction.h"
      18             : #include "AddAuxVariableAction.h"
      19             : #include "XTermConstants.h"
      20             : #include "InfixIterator.h"
      21             : #include "FEProblem.h"
      22             : #include "MemoryUtils.h"
      23             : #include "InputParameterWarehouse.h"
      24             : 
      25             : #include "libmesh/simple_range.h"
      26             : 
      27       68420 : ActionWarehouse::ActionWarehouse(MooseApp & app, Syntax & syntax, ActionFactory & factory)
      28             :   : ConsoleStreamInterface(app),
      29       68420 :     _app(app),
      30       68420 :     _syntax(syntax),
      31       68420 :     _action_factory(factory),
      32       68420 :     _generator_valid(false),
      33       68420 :     _show_action_dependencies(false),
      34       68420 :     _show_actions(false),
      35       68420 :     _show_parser(false),
      36       68420 :     _current_action(nullptr),
      37       68420 :     _mesh(nullptr),
      38      136840 :     _displaced_mesh(nullptr)
      39             : {
      40       68420 : }
      41             : 
      42       62828 : ActionWarehouse::~ActionWarehouse() {}
      43             : 
      44             : void
      45        4102 : ActionWarehouse::setFinalTask(const std::string & task)
      46             : {
      47        4102 :   if (!_syntax.hasTask(task))
      48           0 :     mooseError("cannot use unregistered task '", task, "' as final task");
      49        4102 :   _final_task = task;
      50        4102 : }
      51             : 
      52             : void
      53       67606 : ActionWarehouse::build()
      54             : {
      55       67606 :   _ordered_names = _syntax.getSortedTask();
      56     9734733 :   for (const auto & name : _ordered_names)
      57     9667127 :     buildBuildableActions(name);
      58       67606 : }
      59             : 
      60             : void
      61       62827 : ActionWarehouse::clear()
      62             : {
      63     3130153 :   for (auto & ptr : _all_ptrs)
      64     3067326 :     ptr.reset();
      65             : 
      66       62827 :   _action_blocks.clear();
      67       62827 :   _generator_valid = false;
      68             : 
      69             :   // Due to the way ActionWarehouse is cleaned up (see MooseApp's
      70             :   // destructor) we must guarantee that ActionWarehouse::clear()
      71             :   // releases all the resources which have to be released _before_ the
      72             :   // _comm object owned by the MooseApp is destroyed.
      73       62827 :   _problem.reset();
      74       62827 :   _displaced_mesh.reset();
      75       62827 :   _mesh.reset();
      76       62827 : }
      77             : 
      78             : void
      79     3314010 : ActionWarehouse::addActionBlock(std::shared_ptr<Action> action)
      80             : {
      81             :   /**
      82             :    * Note: This routine uses the XTerm colors directly which is not advised for general purpose
      83             :    * output coloring. Most users should prefer using Problem::colorText() which respects the
      84             :    * "color_output" option for terminals that do not support coloring.  Since this routine is
      85             :    * intended for debugging only and runs before several objects exist in the system, we are just
      86             :    * using the constants directly.
      87             :    */
      88             :   std::string registered_identifier =
      89     3314010 :       action->parameters().get<std::string>("registered_identifier");
      90     3314010 :   std::set<std::string> tasks;
      91             : 
      92     3314010 :   if (_show_parser)
      93           0 :     Moose::err << COLOR_DEFAULT << "Parsing Syntax:        " << COLOR_GREEN << action->name()
      94           0 :                << '\n'
      95           0 :                << COLOR_DEFAULT << "Building Action:       " << COLOR_DEFAULT << action->type()
      96           0 :                << '\n'
      97           0 :                << COLOR_DEFAULT << "Registered Identifier: " << COLOR_GREEN << registered_identifier
      98           0 :                << '\n'
      99           0 :                << COLOR_DEFAULT << "Specific Task:         " << COLOR_CYAN
     100           0 :                << action->specificTaskName() << std::endl;
     101             : 
     102             :   /**
     103             :    * We need to see if the current Action satisfies multiple tasks. There are a few cases to
     104             :    * consider:
     105             :    *
     106             :    * 1. The current Action is registered with multiple syntax blocks. In this case we can only use
     107             :    *    the current instance to satisfy the specific task listed for this syntax block.  We can
     108             :    *    detect this case by inspecting whether it has a "specific task name" set in the Action
     109             :    *    instance.
     110             :    *
     111             :    * 2. This action does not have a valid "registered identifier" set in the Action instance. This
     112             :    *    means that this Action was not built by the Parser.  It was most likely created through a
     113             :    *    Meta-Action (See Case 3 for exception). In this case, the ActionFactory itself would have
     114             :    *    already set the task it found from the build info used to construct the Action so we'd
     115             :    *    arbitrarily satisfy a single task in this case.
     116             :    *
     117             :    * 3. The current Action is registered with only a single syntax block. In this case we can simply
     118             :    *    re-use the current instance to act and satisfy _all_ registered tasks. This is the normal
     119             :    *    case where we have a Parser-built Action that does not have a specific task name to satisfy.
     120             :    *    We will use the Action "type" to retrieve the list of tasks that this Action may satisfy.
     121             :    */
     122     3314010 :   if (action->specificTaskName() != "") // Case 1
     123      463906 :     tasks.insert(action->specificTaskName());
     124     3123424 :   else if (registered_identifier == "" &&
     125     3670064 :            _syntax.getNonDeprecatedSyntaxByAction(action->type()).size() > 1) // Case 2
     126             :   {
     127          79 :     std::set<std::string> local_tasks = action->getAllTasks();
     128             :     mooseAssert(local_tasks.size() == 1, "More than one task inside of the " << action->name());
     129          79 :     tasks.insert(*local_tasks.begin());
     130          79 :   }
     131             :   else // Case 3
     132     2850025 :     tasks = _action_factory.getTasksByAction(action->type());
     133             : 
     134             :   // TODO: Now we need to weed out the double registrations!
     135     8499679 :   for (const auto & task : tasks)
     136             :   {
     137             :     // Some error checking
     138     5185673 :     if (!_syntax.hasTask(task))
     139           0 :       mooseError("A(n) ", task, " is not a registered task");
     140             : 
     141             :     // Make sure that the ObjectAction task and Action task are consistent
     142             :     // otherwise that means that is action was built by the wrong type
     143     5185673 :     std::shared_ptr<MooseObjectAction> moa = std::dynamic_pointer_cast<MooseObjectAction>(action);
     144     5185673 :     if (moa.get())
     145             :     {
     146     1170512 :       const InputParameters & mparams = moa->getObjectParams();
     147             : 
     148     1170512 :       if (mparams.hasBase())
     149             :       {
     150     1170512 :         const std::string & base = mparams.getBase();
     151     1170512 :         if (!_syntax.verifyMooseObjectTask(base, task))
     152           4 :           mooseError("Task ", task, " is not registered to build ", base, " derived objects");
     153             :       }
     154             :       else
     155           0 :         mooseError("Unable to locate registered base parameter for ", moa->getMooseObjectType());
     156             :     }
     157             : 
     158             :     // Add the current task to current action
     159     5185669 :     action->appendTask(task);
     160             : 
     161     5185669 :     if (_show_parser)
     162           0 :       Moose::err << COLOR_YELLOW << "Adding Action:         " << COLOR_DEFAULT << action->type()
     163           0 :                  << " (" << COLOR_YELLOW << task << COLOR_DEFAULT << ")" << std::endl;
     164             : 
     165             :     // Add it to the warehouse
     166     5185669 :     _action_blocks[task].push_back(action.get());
     167     5185669 :   }
     168     3314006 :   _all_ptrs.push_back(action);
     169             : 
     170     3314006 :   if (_show_parser)
     171           0 :     Moose::err << std::endl;
     172     3314006 : }
     173             : 
     174             : ActionIterator
     175    11526534 : ActionWarehouse::actionBlocksWithActionBegin(const std::string & task)
     176             : {
     177    11526534 :   return _action_blocks[task].begin();
     178             : }
     179             : 
     180             : ActionIterator
     181    16543123 : ActionWarehouse::actionBlocksWithActionEnd(const std::string & task)
     182             : {
     183    16543123 :   return _action_blocks[task].end();
     184             : }
     185             : 
     186             : const std::vector<std::shared_ptr<Action>> &
     187      190140 : ActionWarehouse::allActionBlocks() const
     188             : {
     189      190140 :   return _all_ptrs;
     190             : }
     191             : 
     192             : const std::list<Action *> &
     193      318856 : ActionWarehouse::getActionListByName(const std::string & task) const
     194             : {
     195      318856 :   const auto it = _action_blocks.find(task);
     196      318856 :   if (it == _action_blocks.end())
     197       40579 :     return _empty_action_list;
     198             :   else
     199      278277 :     return it->second;
     200             : }
     201             : 
     202             : bool
     203      306691 : ActionWarehouse::hasActions(const std::string & task) const
     204             : {
     205      306691 :   auto it = _action_blocks.find(task);
     206      306691 :   return it != _action_blocks.end() && !it->second.empty();
     207             : }
     208             : 
     209             : void
     210     9667127 : ActionWarehouse::buildBuildableActions(const std::string & task)
     211             : {
     212     9667127 :   if (_syntax.shouldAutoBuild(task) && _action_blocks[task].empty())
     213             :   {
     214     1610185 :     bool ret_value = false;
     215     1610185 :     auto it_pair = _action_factory.getActionsByTask(task);
     216     3243650 :     for (const auto & action_pair : as_range(it_pair))
     217             :     {
     218     1633465 :       const auto & type = action_pair.second;
     219     1633465 :       InputParameters params = _action_factory.getValidParams(type);
     220     3266930 :       params.set<ActionWarehouse *>("awh") = this;
     221             : 
     222     1633465 :       std::string name = "auto_" + type;
     223     1633465 :       std::transform(
     224    45082573 :           name.begin(), name.end(), name.begin(), [](const auto v) { return std::tolower(v); });
     225             : 
     226     1633465 :       if (params.areAllRequiredParamsValid())
     227             :       {
     228     1521846 :         params.set<std::string>("registered_identifier") = "(AutoBuilt)";
     229     1521846 :         addActionBlock(_action_factory.create(type, name, params));
     230     1521846 :         ret_value = true;
     231             :       }
     232     1633465 :     }
     233             : 
     234     1610185 :     if (!ret_value)
     235       88339 :       _unsatisfied_dependencies.insert(task);
     236             :   }
     237     9667127 : }
     238             : 
     239             : void
     240       61244 : ActionWarehouse::checkUnsatisfiedActions() const
     241             : {
     242       61244 :   std::stringstream oss;
     243       61244 :   bool empty = true;
     244             : 
     245      142493 :   for (const auto & udep : _unsatisfied_dependencies)
     246             :   {
     247       81249 :     if (_action_blocks.find(udep) == _action_blocks.end())
     248             :     {
     249           0 :       if (empty)
     250           0 :         empty = false;
     251             :       else
     252           0 :         oss << " ";
     253           0 :       oss << udep;
     254             :     }
     255             :   }
     256             : 
     257       61244 :   if (!empty)
     258           0 :     mooseError(
     259           0 :         std::string(
     260           0 :             "The following unsatisfied actions where found while setting up the MOOSE problem:\n") +
     261           0 :         oss.str() + "\n");
     262       61244 : }
     263             : 
     264             : void
     265          20 : ActionWarehouse::printActionDependencySets() const
     266             : {
     267             :   /**
     268             :    * Note: This routine uses the XTerm colors directly which is not advised for general purpose
     269             :    * output coloring.
     270             :    * Most users should prefer using Problem::colorText() which respects the "color_output" option
     271             :    * for terminals
     272             :    * that do not support coloring.  Since this routine is intended for debugging only and runs
     273             :    * before several
     274             :    * objects exist in the system, we are just using the constants directly.
     275             :    */
     276          20 :   std::ostringstream oss;
     277             : 
     278          20 :   const auto & ordered_names = _syntax.getSortedTaskSet();
     279        2024 :   for (const auto & task_vector : ordered_names)
     280             :   {
     281        2004 :     oss << "[DBG][ACT] (" << COLOR_YELLOW;
     282        2004 :     std::copy(
     283             :         task_vector.begin(), task_vector.end(), infix_ostream_iterator<std::string>(oss, ", "));
     284        2004 :     oss << COLOR_DEFAULT << ")\n";
     285             : 
     286        2004 :     std::set<std::string> task_set(task_vector.begin(), task_vector.end());
     287        4856 :     for (const auto & task : task_set)
     288             :     {
     289        2852 :       if (_action_blocks.find(task) == _action_blocks.end())
     290        1636 :         continue;
     291             : 
     292        2568 :       for (const auto & act : _action_blocks.at(task))
     293             :       {
     294             :         // The Syntax of the Action if it exists
     295        1352 :         if (act->name() != "")
     296        1352 :           oss << "[DBG][ACT]\t" << COLOR_GREEN << act->name() << COLOR_DEFAULT << '\n';
     297             : 
     298             :         // The task sets
     299        1352 :         oss << "[DBG][ACT]\t" << act->type();
     300        1352 :         const std::set<std::string> tasks = act->getAllTasks();
     301        1352 :         if (tasks.size() > 1)
     302             :         {
     303         820 :           oss << " (";
     304             :           // Break the current Action's tasks into 2 sets, those intersecting with current set and
     305             :           // then the difference.
     306         820 :           std::set<std::string> intersection, difference;
     307         820 :           std::set_intersection(tasks.begin(),
     308             :                                 tasks.end(),
     309             :                                 task_set.begin(),
     310             :                                 task_set.end(),
     311             :                                 std::inserter(intersection, intersection.end()));
     312         820 :           std::set_difference(tasks.begin(),
     313             :                               tasks.end(),
     314             :                               intersection.begin(),
     315             :                               intersection.end(),
     316             :                               std::inserter(difference, difference.end()));
     317             : 
     318         820 :           oss << COLOR_CYAN;
     319         820 :           std::copy(intersection.begin(),
     320             :                     intersection.end(),
     321             :                     infix_ostream_iterator<std::string>(oss, ", "));
     322         820 :           oss << COLOR_MAGENTA << (difference.empty() ? "" : ", ");
     323         820 :           std::copy(
     324             :               difference.begin(), difference.end(), infix_ostream_iterator<std::string>(oss, ", "));
     325         820 :           oss << COLOR_DEFAULT << ")";
     326         820 :         }
     327        1352 :         oss << '\n';
     328        1352 :       }
     329             :     }
     330        2004 :   }
     331             : 
     332          20 :   if (_show_action_dependencies)
     333          20 :     _console << oss.str() << std::endl;
     334          20 : }
     335             : 
     336             : void
     337       67598 : ActionWarehouse::executeAllActions()
     338             : {
     339       67598 :   _completed_tasks.clear();
     340             : 
     341       67598 :   if (_show_action_dependencies)
     342             :   {
     343          20 :     _console << "[DBG][ACT] Action Dependency Sets:\n";
     344          20 :     printActionDependencySets();
     345             : 
     346          20 :     _console << "\n[DBG][ACT] Executing actions:" << std::endl;
     347             :   }
     348             : 
     349     9091495 :   for (const auto & task : _ordered_names)
     350             :   {
     351     9030371 :     executeActionsWithAction(task);
     352     9027443 :     std::scoped_lock lock(_completed_tasks_mutex);
     353     9027443 :     _completed_tasks.insert(task);
     354     9027443 :     if (_final_task != "" && task == _final_task)
     355        3546 :       break;
     356     9027443 :   }
     357             : 
     358       64670 :   if (_show_actions)
     359             :   {
     360             :     MemoryUtils::Stats stats;
     361          73 :     MemoryUtils::getMemoryStats(stats);
     362             :     auto usage =
     363          73 :         MemoryUtils::convertBytes(stats._physical_memory, MemoryUtils::MemUnits::Megabytes);
     364          73 :     _console << "[DBG][ACT] Finished executing all actions with memory usage " << usage << "MB\n"
     365          73 :              << std::endl;
     366             :   }
     367       64670 : }
     368             : 
     369             : void
     370     9030371 : ActionWarehouse::executeActionsWithAction(const std::string & task)
     371             : {
     372             :   // Set the current task name
     373     9030371 :   _current_task = task;
     374             : 
     375    13930799 :   for (auto it = actionBlocksWithActionBegin(task); it != actionBlocksWithActionEnd(task); ++it)
     376             :   {
     377     4903356 :     _current_action = *it;
     378             : 
     379     4903356 :     if (_show_actions)
     380             :     {
     381             :       MemoryUtils::Stats stats;
     382        5690 :       MemoryUtils::getMemoryStats(stats);
     383             :       auto usage =
     384        5690 :           MemoryUtils::convertBytes(stats._physical_memory, MemoryUtils::MemUnits::Megabytes);
     385        5690 :       _console << "[DBG][ACT] "
     386        5690 :                << "TASK (" << COLOR_YELLOW << std::setw(24) << task << COLOR_DEFAULT << ") "
     387        5690 :                << "TYPE (" << COLOR_YELLOW << std::setw(32) << _current_action->type()
     388        5690 :                << COLOR_DEFAULT << ") "
     389        5690 :                << "NAME (" << COLOR_YELLOW << std::setw(16) << _current_action->name()
     390        5690 :                << COLOR_DEFAULT << ") Memory usage " << usage << "MB" << std::endl;
     391             :     }
     392             : 
     393     4903356 :     _current_action->timedAct();
     394             :   }
     395             : 
     396     9027443 :   _current_action = nullptr;
     397     9027443 : }
     398             : 
     399             : void
     400       34832 : ActionWarehouse::printInputFile(std::ostream & out)
     401             : {
     402       34832 :   InputFileFormatter tree(false);
     403             : 
     404       34832 :   std::map<std::string, std::vector<Action *>>::iterator iter;
     405             : 
     406       34832 :   std::vector<Action *> ordered_actions;
     407     5012932 :   for (const auto & block : _action_blocks)
     408     7720515 :     for (const auto & act : block.second)
     409     2742415 :       ordered_actions.push_back(act);
     410             : 
     411     2777247 :   for (const auto & act : ordered_actions)
     412             :   {
     413     2742415 :     std::string name;
     414     2742415 :     if (act->parameters().blockFullpath() != "")
     415     1468351 :       name = act->parameters().blockFullpath();
     416             :     else
     417     1274064 :       name = act->name();
     418     2742415 :     const std::set<std::string> & tasks = act->getAllTasks();
     419             :     mooseAssert(!tasks.empty(), "Task list is empty");
     420             : 
     421             :     bool is_parent;
     422     2742415 :     if (_syntax.isAssociated(name, &is_parent) != "")
     423             :     {
     424     1451134 :       const auto & all_params = _app.getInputParameterWarehouse().getInputParameters();
     425     1451134 :       InputParameters & params = *(all_params.find(act->uniqueActionName())->second.get());
     426             : 
     427             :       // temporarily allow input parameter copies required by the input file formatter
     428     1451134 :       params.allowCopy(true);
     429             : 
     430             :       // TODO: Do we need to insert more nodes for each task?
     431     1451134 :       tree.insertNode(name, *tasks.begin(), true, &params);
     432     1451134 :       params.allowCopy(false);
     433             : 
     434     1451134 :       MooseObjectAction * moose_object_action = dynamic_cast<MooseObjectAction *>(act);
     435     1451134 :       if (moose_object_action)
     436             :       {
     437      634025 :         InputParameters obj_params = moose_object_action->getObjectParams();
     438      634025 :         tree.insertNode(name, *tasks.begin(), false, &obj_params);
     439      634025 :       }
     440             :     }
     441     2742415 :   }
     442             : 
     443       34832 :   out << tree.print("");
     444       34832 : }
     445             : 
     446             : std::shared_ptr<FEProblem>
     447           0 : ActionWarehouse::problem()
     448             : {
     449           0 :   mooseDeprecated(
     450             :       "ActionWarehouse::problem() is deprecated, please use ActionWarehouse::problemBase() \n");
     451           0 :   return std::dynamic_pointer_cast<FEProblem>(_problem);
     452             : }
     453             : 
     454             : std::string
     455         100 : ActionWarehouse::getCurrentActionName() const
     456             : {
     457         100 :   return getCurrentAction()->parameters().getHitNode()->fullpath();
     458             : }
     459             : 
     460             : const std::string &
     461           0 : ActionWarehouse::getMooseAppName()
     462             : {
     463           0 :   return _app.name();
     464             : }
     465             : 
     466             : bool
     467      217556 : ActionWarehouse::hasTask(const std::string & task) const
     468             : {
     469      217556 :   return _action_factory.isRegisteredTask(task);
     470             : }
     471             : 
     472             : bool
     473      183921 : ActionWarehouse::isTaskComplete(const std::string & task) const
     474             : {
     475      183921 :   if (!hasTask(task))
     476           0 :     mooseError("\"", task, "\" is not a registered task.");
     477      183921 :   std::scoped_lock lock(_completed_tasks_mutex);
     478      367842 :   return _completed_tasks.count(task);
     479      183921 : }

Generated by: LCOV version 1.14