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 809 : const T & getAction(const std::string & name) const 112 : { 113 809 : typename std::shared_ptr<T> p; 114 59198 : for (auto act_ptr : _all_ptrs) 115 : { 116 29599 : if (act_ptr->name() == name) 117 : { 118 1468 : p = std::dynamic_pointer_cast<T>(act_ptr); 119 1468 : if (p) 120 809 : break; 121 : } 122 : } 123 809 : 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 1618 : return *p; 137 809 : } 138 : template <class T> 139 686 : T & getAction(const std::string & name) 140 : { 141 686 : return const_cast<T &>(static_cast<const ActionWarehouse *>(this)->getAction<T>(name)); 142 : } 143 : 144 : /** 145 : * Retrieve a Physics with its name and the desired type. 146 : * @param name The action name. 147 : */ 148 : template <class T> 149 123 : T * getPhysics(const std::string & name) const 150 : { 151 123 : auto physics = const_cast<T *>(&getAction<T>(name)); 152 123 : if (!dynamic_cast<const PhysicsBase *>(physics)) 153 0 : mooseError("The Physics requested of type '", 154 : MooseUtils::prettyCppType<T>(), 155 : "' and name '", 156 : name, 157 : "' is not derived from the PhysicsBase class"); 158 123 : return physics; 159 : } 160 : 161 : /** 162 : * Retrieve all actions in a specific type ordered by their names. 163 : */ 164 : template <class T> 165 467881 : std::vector<const T *> getActions() 166 : { 167 : // we need to create the map first to ensure that all actions in the map are unique 168 : // and the actions are sorted by their names 169 467881 : typename std::map<std::string, const std::shared_ptr<T>> actions; 170 24611563 : for (auto act_ptr : _all_ptrs) 171 : { 172 24143682 : auto p = std::dynamic_pointer_cast<T>(act_ptr); 173 24143682 : if (p) 174 467974 : actions.insert(std::make_pair(act_ptr->name(), p)); 175 : } 176 : // construct the vector from the map entries 177 467881 : std::vector<const T *> action_vector; 178 935855 : for (auto & pair : actions) 179 467974 : action_vector.push_back(pair.second.get()); 180 935762 : return action_vector; 181 467881 : } 182 : 183 : /** 184 : * Retrieve all Physics with a specific type ordered by their names 185 : */ 186 : template <class T> 187 : std::vector<T *> getPhysics() 188 : { 189 : const auto physics_vector = getActions<T>(); 190 : for (const auto phys_ptr : physics_vector) 191 : if (!dynamic_cast<const PhysicsBase *>(phys_ptr)) 192 : mooseError("The Physics requested of type '", 193 : MooseUtils::prettyCppType<T>(), 194 : "' and name '", 195 : phys_ptr->name(), 196 : "' is not derived from the PhysicsBase class"); 197 : return physics_vector; 198 : } 199 : 200 : /** 201 : * Retrieve the action on a specific task with its type. 202 : * Error will be thrown if more than one actions are found. 203 : * @param task The task name. 204 : * @return The action pointer. Null means that such an action does not exist. 205 : */ 206 : template <class T> 207 117650 : const T * getActionByTask(const std::string & task) 208 : { 209 117650 : const auto it = _action_blocks.find(task); 210 117650 : if (it == _action_blocks.end()) 211 30 : return nullptr; 212 : 213 117620 : T * p = nullptr; 214 198307 : for (const auto & action : it->second) 215 : { 216 80687 : T * tp = dynamic_cast<T *>(action); 217 80687 : if (tp) 218 : { 219 80687 : if (p) 220 0 : mooseError("More than one actions have been detected in getActionByTask for the task '", 221 : task, 222 : "' in the app '", 223 0 : getMooseAppName(), 224 : "'"); 225 : else 226 80687 : p = tp; 227 : } 228 : } 229 117620 : return p; 230 : } 231 : 232 : void setFinalTask(const std::string & task); 233 : 234 : /** 235 : * Check if Actions associated with passed in task exist. 236 : */ 237 : bool hasActions(const std::string & task) const; 238 : 239 : /** 240 : * This method loops over all actions in the warehouse and executes them. Meta-actions 241 : * may add new actions to the warehouse on the fly and they will still be executed in order 242 : */ 243 : void executeAllActions(); 244 : 245 : /** 246 : * This method executes only the actions in the warehouse that satisfy the task 247 : * passed in. 248 : */ 249 : void executeActionsWithAction(const std::string & task_name); 250 : 251 : /** 252 : * This method sets a Boolean which is used to print information about action dependencies 253 : * before various warehouse operations during the problem setup phase. 254 : * @param state Flag indicating whether to print action dependencies. 255 : */ 256 1675 : void showActionDependencies(bool state = true) { _show_action_dependencies = state; } 257 : 258 : /** 259 : * This method sets a Boolean which is used to show information about action execution 260 : * of various warehouse operations during the problem setup phase. 261 : * @param state Flag indicating whether to show action information. 262 : */ 263 1675 : void showActions(bool state = true) { _show_actions = state; } 264 : 265 : /** 266 : * This method sets a Boolean which is used to show debugging information when 267 : * actions are inserted in the warehouse by the parser. 268 : * @param state Flag indicating whether to show action insertion. 269 : */ 270 1675 : void showParser(bool state = true) { _show_parser = state; } 271 : 272 : //// Getters 273 67004 : Syntax & syntax() { return _syntax; } 274 : 275 : // We are not really using the reference counting capabilities of 276 : // shared pointers here, just their memory management capability. 277 : // Therefore, _mesh is actually being used more like a unique_ptr in 278 : // this context. Since full support for unique_ptr is not quite 279 : // available yet, we've implemented it as a std::shared_ptr. 280 3672581 : std::shared_ptr<MooseMesh> & mesh() { return _mesh; } 281 25574 : const std::shared_ptr<MooseMesh> & getMesh() const { return _mesh; } 282 : 283 3338973 : std::shared_ptr<MooseMesh> & displacedMesh() { return _displaced_mesh; } 284 91 : const std::shared_ptr<MooseMesh> & getDisplacedMesh() const { return _displaced_mesh; } 285 : 286 10408044 : std::shared_ptr<FEProblemBase> & problemBase() { return _problem; } 287 : std::shared_ptr<FEProblem> problem(); 288 35283 : MooseApp & mooseApp() { return _app; } 289 : const std::string & getMooseAppName(); 290 3670858 : const std::string & getCurrentTaskName() const { return _current_task; } 291 : 292 : /** 293 : * @return The current action that is running, if any 294 : */ 295 2731956 : const Action * getCurrentAction() const { return _current_action; } 296 : /** 297 : * @return The name of the current action that is running 298 : */ 299 : std::string getCurrentActionName() const; 300 : 301 : /** 302 : * @returns True if a task with the name \p task is registered. 303 : */ 304 : bool hasTask(const std::string & task) const; 305 : /** 306 : * @returns True if the registered task with the name \p task is complete. 307 : */ 308 : bool isTaskComplete(const std::string & task) const; 309 : 310 : protected: 311 : /** 312 : * This method auto-builds all Actions that needs to be built and adds them to ActionWarehouse. 313 : * An Action needs to be built if it is associated with a task that is marked as required and 314 : * all of it's parameters are valid (are not required or have default values supplied). 315 : * 316 : * @param task The name of the task to find and build Actions for. 317 : */ 318 : void buildBuildableActions(const std::string & task); 319 : 320 : std::vector<std::shared_ptr<Action>> _all_ptrs; 321 : 322 : /// The MooseApp this Warehouse is associated with 323 : MooseApp & _app; 324 : /// Reference to a "syntax" of actions 325 : Syntax & _syntax; 326 : /// The Factory that builds Actions 327 : ActionFactory & _action_factory; 328 : /// Pointers to the actual parsed input file blocks 329 : std::map<std::string, std::list<Action *>> _action_blocks; 330 : /// The container that holds the sorted action names from the DependencyResolver 331 : std::vector<std::string> _ordered_names; 332 : /// The completed tasks 333 : std::set<std::string> _completed_tasks; 334 : /// Use to store the current list of unsatisfied dependencies 335 : std::set<std::string> _unsatisfied_dependencies; 336 : 337 : /** 338 : * Flag to indicate whether or not there is an active iterator on this class. 339 : * There can only be a single active iterator because of the potential for 340 : * meta Actions to add new Actions into the warehouse on the fly 341 : */ 342 : bool _generator_valid; 343 : 344 : /// Whether or not the action warehouse prints the action dependency information 345 : bool _show_action_dependencies; 346 : /// Whether or not the action warehouse prints the action execution information 347 : bool _show_actions; 348 : /// Whether or not to print messages when actions are inserted in the warehouse by the parser 349 : bool _show_parser; 350 : 351 : // When executing the actions in the warehouse, this string will always contain 352 : // the current task name 353 : std::string _current_task; 354 : // The current action that is running 355 : Action * _current_action; 356 : 357 : // 358 : // data created by actions 359 : // 360 : 361 : /// Mesh class 362 : std::shared_ptr<MooseMesh> _mesh; 363 : 364 : /// Possible mesh for displaced problem 365 : std::shared_ptr<MooseMesh> _displaced_mesh; 366 : 367 : /// Problem class 368 : std::shared_ptr<FEProblemBase> _problem; 369 : 370 : private: 371 : /// Last task to run before (optional) early termination - blank means no early termination. 372 : std::string _final_task; 373 : 374 : const std::list<Action *> _empty_action_list; 375 : 376 : /// Mutex for preventing read/write races for _completed_tasks 377 : mutable std::mutex _completed_tasks_mutex; 378 : };