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, ¶ms);
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 : }
|