LCOV - code coverage report
Current view: top level - src/actions - ActionWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 199 227 87.7 %
Date: 2025-07-17 01:28:37 Functions: 20 22 90.9 %
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       62755 : ActionWarehouse::ActionWarehouse(MooseApp & app, Syntax & syntax, ActionFactory & factory)
      28             :   : ConsoleStreamInterface(app),
      29       62755 :     _app(app),
      30       62755 :     _syntax(syntax),
      31       62755 :     _action_factory(factory),
      32       62755 :     _generator_valid(false),
      33       62755 :     _show_action_dependencies(false),
      34       62755 :     _show_actions(false),
      35       62755 :     _show_parser(false),
      36       62755 :     _current_action(nullptr),
      37       62755 :     _mesh(nullptr),
      38      125510 :     _displaced_mesh(nullptr)
      39             : {
      40       62755 : }
      41             : 
      42       57254 : ActionWarehouse::~ActionWarehouse() {}
      43             : 
      44             : void
      45        3639 : ActionWarehouse::setFinalTask(const std::string & task)
      46             : {
      47        3639 :   if (!_syntax.hasTask(task))
      48           0 :     mooseError("cannot use unregistered task '", task, "' as final task");
      49        3639 :   _final_task = task;
      50        3639 : }
      51             : 
      52             : void
      53       61934 : ActionWarehouse::build()
      54             : {
      55       61934 :   _ordered_names = _syntax.getSortedTask();
      56     8784768 :   for (const auto & name : _ordered_names)
      57     8722834 :     buildBuildableActions(name);
      58       61934 : }
      59             : 
      60             : void
      61       57253 : ActionWarehouse::clear()
      62             : {
      63     2826823 :   for (auto & ptr : _all_ptrs)
      64     2769570 :     ptr.reset();
      65             : 
      66       57253 :   _action_blocks.clear();
      67       57253 :   _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       57253 :   _problem.reset();
      74       57253 :   _displaced_mesh.reset();
      75       57253 :   _mesh.reset();
      76       57253 : }
      77             : 
      78             : void
      79     3008763 : 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     3008763 :       action->parameters().get<std::string>("registered_identifier");
      90     3008763 :   std::set<std::string> tasks;
      91             : 
      92     3008763 :   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     3008763 :   if (action->specificTaskName() != "") // Case 1
     123      424632 :     tasks.insert(action->specificTaskName());
     124     2834568 :   else if (registered_identifier == "" &&
     125     2834568 :            _syntax.getNonDeprecatedSyntaxByAction(action->type()).size() > 1) // Case 2
     126             :   {
     127          75 :     std::set<std::string> local_tasks = action->getAllTasks();
     128             :     mooseAssert(local_tasks.size() == 1, "More than one task inside of the " << action->name());
     129          75 :     tasks.insert(*local_tasks.begin());
     130          75 :   }
     131             :   else // Case 3
     132     2584056 :     tasks = _action_factory.getTasksByAction(action->type());
     133             : 
     134             :   // TODO: Now we need to weed out the double registrations!
     135     7670889 :   for (const auto & task : tasks)
     136             :   {
     137             :     // Some error checking
     138     4662130 :     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     4662130 :     std::shared_ptr<MooseObjectAction> moa = std::dynamic_pointer_cast<MooseObjectAction>(action);
     144     4662130 :     if (moa.get())
     145             :     {
     146     1069805 :       const InputParameters & mparams = moa->getObjectParams();
     147             : 
     148     1069805 :       if (mparams.have_parameter<std::string>("_moose_base"))
     149             :       {
     150     1069805 :         const std::string & base = mparams.get<std::string>("_moose_base");
     151     1069805 :         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     4662126 :     action->appendTask(task);
     160             : 
     161     4662126 :     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     4662126 :     _action_blocks[task].push_back(action.get());
     167     4662126 :   }
     168     3008759 :   _all_ptrs.push_back(action);
     169             : 
     170     3008759 :   if (_show_parser)
     171           0 :     Moose::err << std::endl;
     172     3008759 : }
     173             : 
     174             : ActionIterator
     175    10374788 : ActionWarehouse::actionBlocksWithActionBegin(const std::string & task)
     176             : {
     177    10374788 :   return _action_blocks[task].begin();
     178             : }
     179             : 
     180             : ActionIterator
     181    14887052 : ActionWarehouse::actionBlocksWithActionEnd(const std::string & task)
     182             : {
     183    14887052 :   return _action_blocks[task].end();
     184             : }
     185             : 
     186             : const std::vector<std::shared_ptr<Action>> &
     187      174058 : ActionWarehouse::allActionBlocks() const
     188             : {
     189      174058 :   return _all_ptrs;
     190             : }
     191             : 
     192             : const std::list<Action *> &
     193      292288 : ActionWarehouse::getActionListByName(const std::string & task) const
     194             : {
     195      292288 :   const auto it = _action_blocks.find(task);
     196      292288 :   if (it == _action_blocks.end())
     197       37564 :     return _empty_action_list;
     198             :   else
     199      254724 :     return it->second;
     200             : }
     201             : 
     202             : bool
     203      281228 : ActionWarehouse::hasActions(const std::string & task) const
     204             : {
     205      281228 :   auto it = _action_blocks.find(task);
     206      281228 :   return it != _action_blocks.end() && !it->second.empty();
     207             : }
     208             : 
     209             : void
     210     8722834 : ActionWarehouse::buildBuildableActions(const std::string & task)
     211             : {
     212     8722834 :   if (_syntax.shouldAutoBuild(task) && _action_blocks[task].empty())
     213             :   {
     214     1408884 :     bool ret_value = false;
     215     1408884 :     auto it_pair = _action_factory.getActionsByTask(task);
     216     2879677 :     for (const auto & action_pair : as_range(it_pair))
     217             :     {
     218     1470793 :       InputParameters params = _action_factory.getValidParams(action_pair.second);
     219     1470793 :       params.set<ActionWarehouse *>("awh") = this;
     220             : 
     221     1470793 :       if (params.areAllRequiredParamsValid())
     222             :       {
     223     1369944 :         params.set<std::string>("registered_identifier") = "(AutoBuilt)";
     224     1369944 :         addActionBlock(_action_factory.create(action_pair.second, "", params));
     225     1369944 :         ret_value = true;
     226             :       }
     227     1470793 :     }
     228             : 
     229     1408884 :     if (!ret_value)
     230       38940 :       _unsatisfied_dependencies.insert(task);
     231             :   }
     232     8722834 : }
     233             : 
     234             : void
     235       56039 : ActionWarehouse::checkUnsatisfiedActions() const
     236             : {
     237       56039 :   std::stringstream oss;
     238       56039 :   bool empty = true;
     239             : 
     240       91833 :   for (const auto & udep : _unsatisfied_dependencies)
     241             :   {
     242       35794 :     if (_action_blocks.find(udep) == _action_blocks.end())
     243             :     {
     244           0 :       if (empty)
     245           0 :         empty = false;
     246             :       else
     247           0 :         oss << " ";
     248           0 :       oss << udep;
     249             :     }
     250             :   }
     251             : 
     252       56039 :   if (!empty)
     253           0 :     mooseError(
     254           0 :         std::string(
     255           0 :             "The following unsatisfied actions where found while setting up the MOOSE problem:\n") +
     256           0 :         oss.str() + "\n");
     257       56039 : }
     258             : 
     259             : void
     260          20 : ActionWarehouse::printActionDependencySets() const
     261             : {
     262             :   /**
     263             :    * Note: This routine uses the XTerm colors directly which is not advised for general purpose
     264             :    * output coloring.
     265             :    * Most users should prefer using Problem::colorText() which respects the "color_output" option
     266             :    * for terminals
     267             :    * that do not support coloring.  Since this routine is intended for debugging only and runs
     268             :    * before several
     269             :    * objects exist in the system, we are just using the constants directly.
     270             :    */
     271          20 :   std::ostringstream oss;
     272             : 
     273          20 :   const auto & ordered_names = _syntax.getSortedTaskSet();
     274        1984 :   for (const auto & task_vector : ordered_names)
     275             :   {
     276        1964 :     oss << "[DBG][ACT] (" << COLOR_YELLOW;
     277        1964 :     std::copy(
     278             :         task_vector.begin(), task_vector.end(), infix_ostream_iterator<std::string>(oss, ", "));
     279        1964 :     oss << COLOR_DEFAULT << ")\n";
     280             : 
     281        1964 :     std::set<std::string> task_set(task_vector.begin(), task_vector.end());
     282        4776 :     for (const auto & task : task_set)
     283             :     {
     284        2812 :       if (_action_blocks.find(task) == _action_blocks.end())
     285        1636 :         continue;
     286             : 
     287        2500 :       for (const auto & act : _action_blocks.at(task))
     288             :       {
     289             :         // The Syntax of the Action if it exists
     290        1324 :         if (act->name() != "")
     291         600 :           oss << "[DBG][ACT]\t" << COLOR_GREEN << act->name() << COLOR_DEFAULT << '\n';
     292             : 
     293             :         // The task sets
     294        1324 :         oss << "[DBG][ACT]\t" << act->type();
     295        1324 :         const std::set<std::string> tasks = act->getAllTasks();
     296        1324 :         if (tasks.size() > 1)
     297             :         {
     298         800 :           oss << " (";
     299             :           // Break the current Action's tasks into 2 sets, those intersecting with current set and
     300             :           // then the difference.
     301         800 :           std::set<std::string> intersection, difference;
     302         800 :           std::set_intersection(tasks.begin(),
     303             :                                 tasks.end(),
     304             :                                 task_set.begin(),
     305             :                                 task_set.end(),
     306             :                                 std::inserter(intersection, intersection.end()));
     307         800 :           std::set_difference(tasks.begin(),
     308             :                               tasks.end(),
     309             :                               intersection.begin(),
     310             :                               intersection.end(),
     311             :                               std::inserter(difference, difference.end()));
     312             : 
     313         800 :           oss << COLOR_CYAN;
     314         800 :           std::copy(intersection.begin(),
     315             :                     intersection.end(),
     316             :                     infix_ostream_iterator<std::string>(oss, ", "));
     317         800 :           oss << COLOR_MAGENTA << (difference.empty() ? "" : ", ");
     318         800 :           std::copy(
     319             :               difference.begin(), difference.end(), infix_ostream_iterator<std::string>(oss, ", "));
     320         800 :           oss << COLOR_DEFAULT << ")";
     321         800 :         }
     322        1324 :         oss << '\n';
     323        1324 :       }
     324             :     }
     325        1964 :   }
     326             : 
     327          20 :   if (_show_action_dependencies)
     328          20 :     _console << oss.str() << std::endl;
     329          20 : }
     330             : 
     331             : void
     332       61926 : ActionWarehouse::executeAllActions()
     333             : {
     334       61926 :   _completed_tasks.clear();
     335             : 
     336       61926 :   if (_show_action_dependencies)
     337             :   {
     338          20 :     _console << "[DBG][ACT] Action Dependency Sets:\n";
     339          20 :     printActionDependencySets();
     340             : 
     341          20 :     _console << "\n[DBG][ACT] Executing actions:" << std::endl;
     342             :   }
     343             : 
     344     8204552 :   for (const auto & task : _ordered_names)
     345             :   {
     346     8148633 :     executeActionsWithAction(task);
     347     8145753 :     std::scoped_lock lock(_completed_tasks_mutex);
     348     8145753 :     _completed_tasks.insert(task);
     349     8145753 :     if (_final_task != "" && task == _final_task)
     350        3127 :       break;
     351     8145753 :   }
     352             : 
     353       59046 :   if (_show_actions)
     354             :   {
     355             :     MemoryUtils::Stats stats;
     356          70 :     MemoryUtils::getMemoryStats(stats);
     357             :     auto usage =
     358          70 :         MemoryUtils::convertBytes(stats._physical_memory, MemoryUtils::MemUnits::Megabytes);
     359          70 :     _console << "[DBG][ACT] Finished executing all actions with memory usage " << usage << "MB\n"
     360          70 :              << std::endl;
     361             :   }
     362       59046 : }
     363             : 
     364             : void
     365     8148633 : ActionWarehouse::executeActionsWithAction(const std::string & task)
     366             : {
     367             :   // Set the current task name
     368     8148633 :   _current_task = task;
     369             : 
     370    12554642 :   for (auto it = actionBlocksWithActionBegin(task); it != actionBlocksWithActionEnd(task); ++it)
     371             :   {
     372     4408889 :     _current_action = *it;
     373             : 
     374     4408889 :     if (_show_actions)
     375             :     {
     376             :       MemoryUtils::Stats stats;
     377        5358 :       MemoryUtils::getMemoryStats(stats);
     378             :       auto usage =
     379        5358 :           MemoryUtils::convertBytes(stats._physical_memory, MemoryUtils::MemUnits::Megabytes);
     380        5358 :       _console << "[DBG][ACT] "
     381        5358 :                << "TASK (" << COLOR_YELLOW << std::setw(24) << task << COLOR_DEFAULT << ") "
     382        5358 :                << "TYPE (" << COLOR_YELLOW << std::setw(32) << _current_action->type()
     383        5358 :                << COLOR_DEFAULT << ") "
     384        5358 :                << "NAME (" << COLOR_YELLOW << std::setw(16) << _current_action->name()
     385        5358 :                << COLOR_DEFAULT << ") Memory usage " << usage << "MB" << std::endl;
     386             :     }
     387             : 
     388     4408889 :     _current_action->timedAct();
     389             :   }
     390             : 
     391     8145753 :   _current_action = nullptr;
     392     8145753 : }
     393             : 
     394             : void
     395       31658 : ActionWarehouse::printInputFile(std::ostream & out)
     396             : {
     397       31658 :   InputFileFormatter tree(false);
     398             : 
     399       31658 :   std::map<std::string, std::vector<Action *>>::iterator iter;
     400             : 
     401       31658 :   std::vector<Action *> ordered_actions;
     402     4486824 :   for (const auto & block : _action_blocks)
     403     6901612 :     for (const auto & act : block.second)
     404     2446446 :       ordered_actions.push_back(act);
     405             : 
     406     2478104 :   for (const auto & act : ordered_actions)
     407             :   {
     408     2446446 :     std::string name;
     409     2446446 :     if (act->parameters().blockFullpath() != "")
     410     1332646 :       name = act->parameters().blockFullpath();
     411             :     else
     412     1113800 :       name = act->name();
     413     2446446 :     const std::set<std::string> & tasks = act->getAllTasks();
     414             :     mooseAssert(!tasks.empty(), "Task list is empty");
     415             : 
     416             :     bool is_parent;
     417     2446446 :     if (_syntax.isAssociated(name, &is_parent) != "")
     418             :     {
     419     2430795 :       const auto & all_params = _app.getInputParameterWarehouse().getInputParameters();
     420     2430795 :       InputParameters & params = *(all_params.find(act->uniqueActionName())->second.get());
     421             : 
     422             :       // temporarily allow input parameter copies required by the input file formatter
     423     2430795 :       params.allowCopy(true);
     424             : 
     425             :       // TODO: Do we need to insert more nodes for each task?
     426     2430795 :       tree.insertNode(name, *tasks.begin(), true, &params);
     427     2430795 :       params.allowCopy(false);
     428             : 
     429     2430795 :       MooseObjectAction * moose_object_action = dynamic_cast<MooseObjectAction *>(act);
     430     2430795 :       if (moose_object_action)
     431             :       {
     432      575144 :         InputParameters obj_params = moose_object_action->getObjectParams();
     433      575144 :         tree.insertNode(name, *tasks.begin(), false, &obj_params);
     434      575144 :       }
     435             :     }
     436     2446446 :   }
     437             : 
     438       31658 :   out << tree.print("");
     439       31658 : }
     440             : 
     441             : std::shared_ptr<FEProblem>
     442           0 : ActionWarehouse::problem()
     443             : {
     444           0 :   mooseDeprecated(
     445             :       "ActionWarehouse::problem() is deprecated, please use ActionWarehouse::problemBase() \n");
     446           0 :   return std::dynamic_pointer_cast<FEProblem>(_problem);
     447             : }
     448             : 
     449             : std::string
     450         100 : ActionWarehouse::getCurrentActionName() const
     451             : {
     452         100 :   return getCurrentAction()->parameters().getHitNode()->fullpath();
     453             : }
     454             : 
     455             : const std::string &
     456           0 : ActionWarehouse::getMooseAppName()
     457             : {
     458           0 :   return _app.name();
     459             : }
     460             : 
     461             : bool
     462      163599 : ActionWarehouse::hasTask(const std::string & task) const
     463             : {
     464      163599 :   return _action_factory.isRegisteredTask(task);
     465             : }
     466             : 
     467             : bool
     468      163231 : ActionWarehouse::isTaskComplete(const std::string & task) const
     469             : {
     470      163231 :   if (!hasTask(task))
     471           0 :     mooseError("\"", task, "\" is not a registered task.");
     472      163231 :   std::scoped_lock lock(_completed_tasks_mutex);
     473      326462 :   return _completed_tasks.count(task);
     474      163231 : }

Generated by: LCOV version 1.14