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 : #pragma once 11 : 12 : #include <string> 13 : #include <set> 14 : #include <map> 15 : #include <vector> 16 : #include <list> 17 : #include <ostream> 18 : 19 : // MOOSE includes 20 : #include "Action.h" 21 : #include "ConsoleStreamInterface.h" 22 : 23 : /// alias to hide implementation details 24 : using ActionIterator = std::list<Action *>::iterator; 25 : 26 : class MooseMesh; 27 : class Syntax; 28 : class ActionFactory; 29 : class FEProblem; 30 : class PhysicsBase; 31 : 32 : /** 33 : * Storage for action instances. 34 : */ 35 : class ActionWarehouse : public ConsoleStreamInterface 36 : { 37 : public: 38 : ActionWarehouse(MooseApp & app, Syntax & syntax, ActionFactory & factory); 39 : ~ActionWarehouse(); 40 : 41 : /** 42 : * Builds all auto-buildable tasks. This method is typically called after the Parser has 43 : * created Actions based on an input file. 44 : */ 45 : void build(); 46 : 47 : /** 48 : * This method deletes all of the Actions in the warehouse. 49 : */ 50 : void clear(); 51 : 52 : /** 53 : * \p returns a Boolean indicating whether the warehouse is empty or not. 54 : */ 55 : bool empty() const { return _action_blocks.empty(); } 56 : 57 : /** 58 : * This method add an \p Action instance to the warehouse. 59 : */ 60 : void addActionBlock(std::shared_ptr<Action> blk); 61 : 62 : /** 63 : * This method checks the actions stored in the warehouse against the list of required registered 64 : * actions to see if all of them have been satisfied. It should be called before running 65 : * a MOOSE problem 66 : */ 67 : void checkUnsatisfiedActions() const; 68 : 69 : /** 70 : * This method is used only during debugging when \p show_actions is set to \p true. 71 : * It prints all of the actions sets in the correct dependency resolved order with 72 : * all of the Action objects inside. 73 : */ 74 : void printActionDependencySets() const; 75 : 76 : /** 77 : * This method uses the Actions in the warehouse to reproduce the input file. This method 78 : * is useful for debugging as it can assist in finding difficult to track parsing or input 79 : * file problems. 80 : * @param out A writable \p ostream object where the output will be sent. 81 : */ 82 : void printInputFile(std::ostream & out); 83 : 84 : ///@{ 85 : /** 86 : * Iterators to the Actions in the warehouse. Iterators should always be used when executing 87 : * Actions to capture dynamically added Actions (meta-Actions). Meta-Actions are allowed to 88 : * create and add additional Actions to the warehouse on the fly. Those Actions will fire 89 : * as long as their associated task hasn't already passed (i.e. matches or is later). 90 : */ 91 : ActionIterator actionBlocksWithActionBegin(const std::string & task); 92 : ActionIterator actionBlocksWithActionEnd(const std::string & task); 93 : ///@} 94 : 95 : /** 96 : * Returns a reference to all of the actions. 97 : */ 98 : const std::vector<std::shared_ptr<Action>> & allActionBlocks() const; 99 : 100 : /** 101 : * Retrieve a constant list of \p Action pointers associated with the passed in task. 102 : * Empty list will be returned if no actions are associated with the task. 103 : */ 104 : const std::list<Action *> & getActionListByName(const std::string & task) const; 105 : 106 : /** 107 : * Retrieve an action with its name and the desired type. 108 : * @param name The action name. 109 : */ 110 : template <class T> 111 356 : const T & getAction(const std::string & name) const 112 : { 113 356 : typename std::shared_ptr<T> p; 114 11340 : for (auto act_ptr : _all_ptrs) 115 : { 116 10984 : if (act_ptr->name() == name) 117 : { 118 550 : p = std::dynamic_pointer_cast<T>(act_ptr); 119 550 : if (p) 120 356 : break; 121 : } 122 : } 123 356 : if (!p) 124 : { 125 0 : std::vector<std::string> all_names; 126 0 : for (auto act_ptr : _all_ptrs) 127 0 : if (!act_ptr->name().empty()) 128 0 : all_names.push_back(act_ptr->name()); 129 : else 130 0 : all_names.push_back("unnamed"); 131 0 : mooseError("Action with name '", 132 : name, 133 : "' does not exist.\n These are the Actions that do exist:", 134 : Moose::stringify(all_names)); 135 0 : } 136 712 : return *p; 137 356 : } 138 : template <class T> 139 132 : T * getPhysics(const std::string & name) const 140 : { 141 132 : auto physics = const_cast<T *>(&getAction<T>(name)); 142 132 : if (!dynamic_cast<const PhysicsBase *>(physics)) 143 0 : mooseError("The Physics requested of type '", 144 : MooseUtils::prettyCppType<T>(), 145 : "' and name '", 146 : name, 147 : "' is not derived from the PhysicsBase class"); 148 132 : return physics; 149 : } 150 : 151 : /** 152 : * Retrieve all actions in a specific type ordered by their names. 153 : */ 154 : template <class T> 155 455671 : std::vector<const T *> getActions() 156 : { 157 : // we need to create the map first to ensure that all actions in the map are unique 158 : // and the actions are sorted by their names 159 455671 : typename std::map<std::string, const std::shared_ptr<T>> actions; 160 23304168 : for (auto act_ptr : _all_ptrs) 161 : { 162 22848497 : auto p = std::dynamic_pointer_cast<T>(act_ptr); 163 22848497 : if (p) 164 455769 : actions.insert(std::make_pair(act_ptr->name(), p)); 165 : } 166 : // construct the vector from the map entries 167 455671 : std::vector<const T *> action_vector; 168 911440 : for (auto & pair : actions) 169 455769 : action_vector.push_back(pair.second.get()); 170 911342 : return action_vector; 171 455671 : } 172 : 173 : /** 174 : * Retrieve all Physics with a specific type ordered by their names 175 : */ 176 : template <class T> 177 : std::vector<T *> getPhysics() 178 : { 179 : const auto physics_vector = getActions<T>(); 180 : for (const auto phys_ptr : physics_vector) 181 : if (!dynamic_cast<const PhysicsBase *>(phys_ptr)) 182 : mooseError("The Physics requested of type '", 183 : MooseUtils::prettyCppType<T>(), 184 : "' and name '", 185 : phys_ptr->name(), 186 : "' is not derived from the PhysicsBase class"); 187 : return physics_vector; 188 : } 189 : 190 : /** 191 : * Retrieve the action on a specific task with its type. 192 : * Error will be thrown if more than one actions are found. 193 : * @param task The task name. 194 : * @return The action pointer. Null means that such an action does not exist. 195 : */ 196 : template <class T> 197 112643 : const T * getActionByTask(const std::string & task) 198 : { 199 112643 : const auto it = _action_blocks.find(task); 200 112643 : if (it == _action_blocks.end()) 201 36 : return nullptr; 202 : 203 112607 : T * p = nullptr; 204 188567 : for (const auto & action : it->second) 205 : { 206 75960 : T * tp = dynamic_cast<T *>(action); 207 75960 : if (tp) 208 : { 209 75960 : if (p) 210 0 : mooseError("More than one actions have been detected in getActionByTask for the task '", 211 : task, 212 : "' in the app '", 213 0 : getMooseAppName(), 214 : "'"); 215 : else 216 75960 : p = tp; 217 : } 218 : } 219 112607 : return p; 220 : } 221 : 222 : void setFinalTask(const std::string & task); 223 : 224 : /** 225 : * Check if Actions associated with passed in task exist. 226 : */ 227 : bool hasActions(const std::string & task) const; 228 : 229 : /** 230 : * This method loops over all actions in the warehouse and executes them. Meta-actions 231 : * may add new actions to the warehouse on the fly and they will still be executed in order 232 : */ 233 : void executeAllActions(); 234 : 235 : /** 236 : * This method executes only the actions in the warehouse that satisfy the task 237 : * passed in. 238 : */ 239 : void executeActionsWithAction(const std::string & name); 240 : 241 : /** 242 : * This method sets a Boolean which is used to print information about action dependencies 243 : * before various warehouse operations during the problem setup phase. 244 : * @param state Flag indicating whether to print action dependencies. 245 : */ 246 1623 : void showActionDependencies(bool state = true) { _show_action_dependencies = state; } 247 : 248 : /** 249 : * This method sets a Boolean which is used to show information about action execution 250 : * of various warehouse operations during the problem setup phase. 251 : * @param state Flag indicating whether to show action information. 252 : */ 253 1623 : void showActions(bool state = true) { _show_actions = state; } 254 : 255 : /** 256 : * This method sets a Boolean which is used to show debugging information when 257 : * actions are inserted in the warehouse by the parser. 258 : * @param state Flag indicating whether to show action insertion. 259 : */ 260 1623 : void showParser(bool state = true) { _show_parser = state; } 261 : 262 : //// Getters 263 62764 : Syntax & syntax() { return _syntax; } 264 : 265 : // We are not really using the reference counting capabilities of 266 : // shared pointers here, just their memory management capability. 267 : // Therefore, _mesh is actually being used more like a unique_ptr in 268 : // this context. Since full support for unique_ptr is not quite 269 : // available yet, we've implemented it as a std::shared_ptr. 270 3402707 : std::shared_ptr<MooseMesh> & mesh() { return _mesh; } 271 23649 : const std::shared_ptr<MooseMesh> & getMesh() const { return _mesh; } 272 : 273 3131324 : std::shared_ptr<MooseMesh> & displacedMesh() { return _displaced_mesh; } 274 95 : const std::shared_ptr<MooseMesh> & getDisplacedMesh() const { return _displaced_mesh; } 275 : 276 6530607 : std::shared_ptr<FEProblemBase> & problemBase() { return _problem; } 277 : std::shared_ptr<FEProblem> problem(); 278 33251 : MooseApp & mooseApp() { return _app; } 279 : const std::string & getMooseAppName(); 280 3345938 : const std::string & getCurrentTaskName() const { return _current_task; } 281 : 282 : /** 283 : * @return The current action that is running, if any 284 : */ 285 2469723 : const Action * getCurrentAction() const { return _current_action; } 286 : /** 287 : * @return The name of the current action that is running 288 : */ 289 : std::string getCurrentActionName() const; 290 : 291 : /** 292 : * @returns True if a task with the name \p task is registered. 293 : */ 294 : bool hasTask(const std::string & task) const; 295 : /** 296 : * @returns True if the registered task with the name \p task is complete. 297 : */ 298 : bool isTaskComplete(const std::string & task) const; 299 : 300 : protected: 301 : /** 302 : * This method auto-builds all Actions that needs to be built and adds them to ActionWarehouse. 303 : * An Action needs to be built if it is associated with a task that is marked as required and 304 : * all of it's parameters are valid (are not required or have default values supplied). 305 : * 306 : * @param task The name of the task to find and build Actions for. 307 : */ 308 : void buildBuildableActions(const std::string & task); 309 : 310 : std::vector<std::shared_ptr<Action>> _all_ptrs; 311 : 312 : /// The MooseApp this Warehouse is associated with 313 : MooseApp & _app; 314 : /// Reference to a "syntax" of actions 315 : Syntax & _syntax; 316 : /// The Factory that builds Actions 317 : ActionFactory & _action_factory; 318 : /// Pointers to the actual parsed input file blocks 319 : std::map<std::string, std::list<Action *>> _action_blocks; 320 : /// The container that holds the sorted action names from the DependencyResolver 321 : std::vector<std::string> _ordered_names; 322 : /// The completed tasks 323 : std::set<std::string> _completed_tasks; 324 : /// Use to store the current list of unsatisfied dependencies 325 : std::set<std::string> _unsatisfied_dependencies; 326 : 327 : /** 328 : * Flag to indicate whether or not there is an active iterator on this class. 329 : * There can only be a single active iterator because of the potential for 330 : * meta Actions to add new Actions into the warehouse on the fly 331 : */ 332 : bool _generator_valid; 333 : 334 : /// Whether or not the action warehouse prints the action dependency information 335 : bool _show_action_dependencies; 336 : /// Whether or not the action warehouse prints the action execution information 337 : bool _show_actions; 338 : /// Whether or not to print messages when actions are inserted in the warehouse by the parser 339 : bool _show_parser; 340 : 341 : // When executing the actions in the warehouse, this string will always contain 342 : // the current task name 343 : std::string _current_task; 344 : // The current action that is running 345 : Action * _current_action; 346 : 347 : // 348 : // data created by actions 349 : // 350 : 351 : /// Mesh class 352 : std::shared_ptr<MooseMesh> _mesh; 353 : 354 : /// Possible mesh for displaced problem 355 : std::shared_ptr<MooseMesh> _displaced_mesh; 356 : 357 : /// Problem class 358 : std::shared_ptr<FEProblemBase> _problem; 359 : 360 : private: 361 : /// Last task to run before (optional) early termination - blank means no early termination. 362 : std::string _final_task; 363 : 364 : const std::list<Action *> _empty_action_list; 365 : 366 : /// Mutex for preventing read/write races for _completed_tasks 367 : mutable std::mutex _completed_tasks_mutex; 368 : };