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 : // MOOSE includes
11 : #include "CommonOutputAction.h"
12 : #include "MooseApp.h"
13 : #include "FEProblem.h"
14 : #include "MooseObjectAction.h"
15 : #include "ActionFactory.h"
16 : #include "Output.h"
17 : #include "OutputWarehouse.h"
18 : #include "MooseUtils.h"
19 : #include "PerfGraphReporter.h"
20 :
21 : // Extrnal includes
22 : #include "tinydir.h"
23 : #include "pcrecpp.h"
24 : #include <libgen.h>
25 : #include <sys/types.h>
26 : #include <sys/stat.h>
27 : #include <unistd.h>
28 :
29 : registerMooseAction("MooseApp", CommonOutputAction, "common_output");
30 : registerMooseAction("MooseApp", CommonOutputAction, "add_output");
31 : registerMooseAction("MooseApp", CommonOutputAction, "add_reporter");
32 :
33 : InputParameters
34 66081 : CommonOutputAction::validParams()
35 : {
36 66081 : InputParameters params = Action::validParams();
37 132162 : params.addClassDescription("Adds short-cut syntax and common parameters to the Outputs block.");
38 :
39 : // Short-cut methods for typical output objects
40 198243 : params.addParam<bool>(
41 132162 : "exodus", false, "Output the results using the default settings for Exodus output.");
42 198243 : params.addParam<bool>(
43 132162 : "nemesis", false, "Output the results using the default settings for Nemesis output");
44 198243 : params.addParam<bool>(
45 132162 : "console", true, "Output the results using the default settings for Console output");
46 198243 : params.addParam<bool>("csv",
47 132162 : false,
48 : "Output the scalar variable and postprocessors to a *.csv "
49 : "file using the default CSV output.");
50 198243 : params.addParam<bool>("xml",
51 132162 : false,
52 : "Output the vector postprocessors to a *.xml "
53 : "file using the default XML output.");
54 198243 : params.addParam<bool>("json",
55 132162 : false,
56 : "Output Reporter values to a *.json "
57 : "file using the default JSON output.");
58 198243 : params.addParam<bool>(
59 132162 : "vtk", false, "Output the results using the default settings for VTKOutput output");
60 198243 : params.addParam<bool>(
61 132162 : "xda", false, "Output the results using the default settings for XDA/XDR output (ascii)");
62 198243 : params.addParam<bool>(
63 132162 : "xdr", false, "Output the results using the default settings for XDA/XDR output (binary)");
64 198243 : params.addParam<bool>(
65 132162 : "gmv", false, "Output the results using the default settings for GMV output");
66 198243 : params.addParam<bool>(
67 132162 : "tecplot", false, "Output the results using the default settings for Tecplot output");
68 198243 : params.addParam<bool>(
69 : "gnuplot",
70 132162 : false,
71 : "Output the scalar and postprocessor results using the default settings for GNUPlot output");
72 198243 : params.addParam<bool>(
73 132162 : "solution_history", false, "Print a solution history file (.slh) using the default settings");
74 264324 : params.addParam<bool>("progress", false, "Print a progress bar");
75 264324 : params.addParam<bool>("dofmap", false, "Create the dof map .json output file");
76 264324 : params.addParam<bool>("controls", false, "Enable the screen output of Control systems.");
77 :
78 : // Common parameters
79 :
80 : // Note: Be sure that objects that share these parameters utilize the same defaults
81 264324 : params.addParam<bool>("color", true, "Set to false to turn off all coloring in all outputs");
82 264324 : params.addParam<std::string>("file_base",
83 : "Common file base name to be utilized with all output objects");
84 264324 : params.addParam<std::vector<std::string>>("output_if_base_contains",
85 : "If this is supplied then output will only be done in "
86 : "the case that the output base contains one of these "
87 : "strings. This is helpful in outputting only a subset "
88 : "of outputs when using MultiApps.");
89 198243 : params.addParam<unsigned int>(
90 132162 : "time_step_interval", 1, "The interval (number of time steps) at which output occurs");
91 198243 : params.addParam<std::vector<Real>>("sync_times",
92 132162 : std::vector<Real>(),
93 : "Times at which the output and solution is forced to occur");
94 198243 : params.addParam<Real>(
95 132162 : "min_simulation_time_interval", 0.0, "The minimum simulation time between output steps");
96 198243 : params.addParam<bool>(
97 132162 : "append_date", false, "When true the date and time are appended to the output filename.");
98 264324 : params.addParam<std::string>("append_date_format",
99 : "The format of the date/time to append (see "
100 : "http://www.cplusplus.com/reference/ctime/"
101 : "strftime).");
102 :
103 264324 : params.addParam<std::vector<VariableName>>(
104 : "hide",
105 : {},
106 : "A list of the variables and postprocessors that should NOT be output to the Exodus "
107 : "file (may include Variables, ScalarVariables, and Postprocessor names).");
108 198243 : params.addParam<std::vector<VariableName>>(
109 : "show",
110 : {},
111 : "A list of the variables and postprocessors that should be output to the Exodus file "
112 : "(may include Variables, ScalarVariables, and Postprocessor names).");
113 :
114 : // Add the 'execute_on' input parameter
115 66081 : ExecFlagEnum exec_enum = Output::getDefaultExecFlagEnum();
116 198243 : exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
117 198243 : params.addParam<ExecFlagEnum>("execute_on", exec_enum, exec_enum.getDocString());
118 :
119 : // Add special Console flags
120 330405 : params.addDeprecatedParam<bool>(
121 132162 : "print_perf_log", false, "Use perf_graph instead!", "Use perf_graph instead!");
122 :
123 198243 : params.addParam<bool>(
124 132162 : "perf_graph", false, "Enable printing of the performance graph to the screen (Console)");
125 :
126 264324 : params.addParam<bool>("perf_graph_live", true, "Enables printing of live progress messages");
127 198243 : params.addParam<Real>(
128 132162 : "perf_graph_live_time_limit", 5.0, "Time (in seconds) to wait before printing a message.");
129 198243 : params.addParam<unsigned int>(
130 132162 : "perf_graph_live_mem_limit", 100, "Memory (in MB) to cause a message to be printed.");
131 264324 : params.addParam<bool>("perf_graph_json", false, "Output the perf graph in JSON");
132 264324 : params.addParam<FileName>("perf_graph_json_file", "Path to a .json file to store the perf graph");
133 :
134 198243 : params.addParam<bool>("print_mesh_changed_info",
135 132162 : false,
136 : "When true, each time the mesh is changed the mesh information is printed");
137 198243 : params.addParam<bool>("print_linear_residuals",
138 132162 : true,
139 : "Enable printing of linear residuals to the screen (Console)");
140 198243 : params.addParam<bool>("print_nonlinear_residuals",
141 132162 : true,
142 : "Enable printing of nonlinear residuals to the screen (Console)");
143 198243 : params.addParam<bool>("print_nonlinear_converged_reason",
144 132162 : true,
145 : "Enable/disable printing of the nonlinear solver convergence reason to the "
146 : "screen. This parameter only affects the output of the third-party solver "
147 : "(e.g. PETSc), not MOOSE itself.");
148 198243 : params.addParam<bool>("print_linear_converged_reason",
149 132162 : true,
150 : "Enable/disable printing of the linear solver convergence reason to the "
151 : "screen. This parameter only affects the output of the third-party solver "
152 : "(e.g. PETSc), not MOOSE itself.");
153 :
154 132162 : params.addParam<bool>(
155 : "solution_invalidity_history",
156 132162 : true,
157 : "Enable printing of the time history of the solution invalidity occurrences "
158 : "to the screen (console)");
159 :
160 : // Return object
161 132162 : return params;
162 132162 : }
163 :
164 66031 : CommonOutputAction::CommonOutputAction(const InputParameters & params)
165 198093 : : Action(params), _action_params(_action_factory.getValidParams("AddOutputAction"))
166 : {
167 66031 : }
168 :
169 : void
170 186585 : CommonOutputAction::act()
171 : {
172 : // Name of the PerfGraphReporter that could be created for the perf graph output
173 294195 : static const std::string perf_graph_reporter_name = "perf_graph_json";
174 : // Name of the JSON output that could be created for the perf graph output
175 186585 : static const OutputName perf_graph_json_output_name = "auto_perf_graph_json";
176 :
177 186585 : if (_current_task == "common_output")
178 : {
179 : // Store the common output parameters in the OutputWarehouse
180 65927 : _app.getOutputWarehouse().setCommonParameters(&_pars);
181 :
182 : // Create the actions for the short-cut methods
183 : #ifdef LIBMESH_HAVE_EXODUS_API
184 197781 : if (getParam<bool>("exodus"))
185 101175 : create("Exodus", "exodus");
186 : #else
187 : if (getParam<bool>("exodus"))
188 : mooseWarning("Exodus output requested but not enabled through libMesh");
189 : #endif
190 :
191 : #ifdef LIBMESH_HAVE_NEMESIS_API
192 197781 : if (getParam<bool>("nemesis"))
193 672 : create("Nemesis", "nemesis");
194 : #else
195 : if (getParam<bool>("nemesis"))
196 : mooseWarning("Nemesis output requested but not enabled through libMesh");
197 : #endif
198 :
199 : // Only create a Console if screen output was not created
200 197781 : if (getParam<bool>("console") && !hasConsole())
201 194412 : create("Console", "console");
202 :
203 197781 : if (getParam<bool>("csv"))
204 36288 : create("CSV", "csv");
205 :
206 197781 : if (getParam<bool>("xml"))
207 162 : create("XMLOutput", "xml");
208 :
209 197781 : if (getParam<bool>("json"))
210 390 : create("JSON", "json");
211 :
212 : #ifdef LIBMESH_HAVE_VTK
213 197781 : if (getParam<bool>("vtk"))
214 213 : create("VTK", "vtk");
215 : #else
216 : if (getParam<bool>("vtk"))
217 : mooseWarning("VTK output requested but not enabled through libMesh");
218 : #endif
219 :
220 197781 : if (getParam<bool>("xda"))
221 390 : create("XDA", "xda");
222 :
223 197781 : if (getParam<bool>("xdr"))
224 144 : create("XDR", "xdr");
225 :
226 197781 : if (getParam<bool>("gmv"))
227 102 : create("GMV", "gmv");
228 :
229 197781 : if (getParam<bool>("tecplot"))
230 108 : create("Tecplot", "tecplot");
231 :
232 197781 : if (getParam<bool>("gnuplot"))
233 36 : create("Gnuplot", "gnuplot");
234 :
235 197781 : if (getParam<bool>("solution_history"))
236 36 : create("SolutionHistory", "solution_history");
237 :
238 197781 : if (getParam<bool>("progress"))
239 27 : create("Progress", "progress");
240 :
241 197781 : if (getParam<bool>("dofmap"))
242 72 : create("DOFMap", "dofmap");
243 :
244 : // Helper for looking through a pair of [parameters, param name]
245 : // to find a true boolean parameter, returning the pair that was found
246 : const auto find_param =
247 131845 : [](const std::vector<std::pair<const InputParameters *, std::string>> & options)
248 : {
249 131845 : std::optional<std::string> from_param_name;
250 131845 : const InputParameters * from_params = nullptr;
251 292234 : for (const auto & [params, param_name] : options)
252 224719 : if (params->template get<bool>(param_name))
253 : {
254 64330 : from_param_name = param_name;
255 64330 : from_params = params;
256 64330 : break;
257 : }
258 263690 : return std::make_pair(from_param_name, from_params);
259 131845 : };
260 :
261 : {
262 65927 : const auto [from_param_name, from_params] =
263 263708 : find_param({{¶meters(), "controls"}, {&_app.parameters(), "show_controls"}});
264 65927 : if (from_param_name)
265 54 : create("ControlOutput", *from_param_name, from_params);
266 65927 : }
267 :
268 197781 : if (!_app.getParam<bool>("no_timing"))
269 : {
270 263672 : auto [from_param_name, from_params] = find_param({{¶meters(), "perf_graph"},
271 0 : {¶meters(), "print_perf_log"},
272 329590 : {&_app.parameters(), "timing"}});
273 65918 : if (from_param_name)
274 192936 : create("PerfGraphOutput", *from_param_name, from_params);
275 :
276 24 : const auto add_perf_graph_json = [this](const std::string & from_param_name,
277 : const std::string & set_param_name,
278 : const std::string & set_param_value)
279 : {
280 24 : const auto & value_names = PerfGraphReporter::value_names;
281 24 : std::vector<ReporterName> reporters;
282 24 : reporters.reserve(value_names.size());
283 120 : for (const auto & value_name : value_names)
284 : {
285 96 : const ReporterName name(perf_graph_reporter_name, value_name);
286 :
287 : // To avoid this reporter value appearing in all other JSON output
288 96 : _common_reporter_names.push_back(name);
289 :
290 96 : reporters.push_back(name);
291 96 : }
292 :
293 72 : auto params = _factory.getValidParams("JSON");
294 24 : params.set<std::vector<ReporterName>>("reporters") = reporters;
295 72 : params.set<ExecFlagEnum>("execute_on") = {EXEC_FINAL};
296 72 : params.set<ExecFlagEnum>("execute_system_information_on") = {EXEC_NONE};
297 24 : params.set<std::string>(set_param_name) = set_param_value;
298 24 : params.set<bool>("distributed") = false;
299 24 : if (set_param_name == "file_base")
300 24 : params.set<bool>("append_date") = false;
301 72 : create("JSON", from_param_name, ¶meters(), ¶ms, perf_graph_json_output_name);
302 72 : };
303 :
304 197754 : if (getParam<bool>("perf_graph_json"))
305 72 : add_perf_graph_json("perf_graph_json", "file_base_suffix", "perf_graph");
306 197754 : if (isParamValid("perf_graph_json_file"))
307 : {
308 30 : const auto & file = getParam<FileName>("perf_graph_json_file");
309 15 : if (MooseUtils::getExtension(file, true) != "json")
310 6 : paramError("perf_graph_json_file", "File must end with .json");
311 12 : const auto file_stripped = MooseUtils::stripExtension(file, true);
312 36 : add_perf_graph_json("perf_graph_json_file", "file_base", file_stripped);
313 12 : }
314 :
315 197745 : if (!getParam<bool>("perf_graph_live"))
316 : {
317 0 : if (!from_param_name)
318 0 : perfGraph().setActive(false);
319 0 : perfGraph().disableLivePrint();
320 : }
321 65915 : }
322 : else
323 : {
324 9 : perfGraph().setActive(false);
325 9 : perfGraph().disableLivePrint();
326 : }
327 :
328 131848 : perfGraph().setLiveTimeLimit(getParam<Real>("perf_graph_live_time_limit"));
329 131848 : perfGraph().setLiveMemoryLimit(getParam<unsigned int>("perf_graph_live_mem_limit"));
330 :
331 197772 : if (getParam<bool>("solution_invalidity_history"))
332 : {
333 197739 : create("SolutionInvalidityOutput", "solution_invalidity_history");
334 : }
335 :
336 197772 : if (!getParam<bool>("color"))
337 166 : Moose::setColorConsole(false);
338 : }
339 120658 : else if (_current_task == "add_output")
340 : {
341 : // More like remove output. This can't be done during the "common_output" task because the
342 : // finite element problem is not yet constructed
343 :
344 422679 : if (!getParam<bool>("console") || (isParamValid("print_nonlinear_converged_reason") &&
345 241500 : !getParam<bool>("print_nonlinear_converged_reason")))
346 63 : Moose::PetscSupport::dontAddNonlinearConvergedReason(*_problem);
347 :
348 422679 : if (!getParam<bool>("console") || (isParamValid("print_linear_converged_reason") &&
349 241500 : !getParam<bool>("print_linear_converged_reason")))
350 72 : Moose::PetscSupport::dontAddLinearConvergedReason(*_problem);
351 : }
352 60265 : else if (_current_task == "add_reporter")
353 : {
354 301316 : if (!_app.getParam<bool>("no_timing") &&
355 361521 : (getParam<bool>("perf_graph_json") || isParamValid("perf_graph_json_file")))
356 : {
357 72 : auto params = _factory.getValidParams("PerfGraphReporter");
358 24 : params.set<ExecFlagEnum>("execute_on") = EXEC_FINAL;
359 48 : params.set<std::vector<OutputName>>("outputs") =
360 120 : std::vector<OutputName>{perf_graph_json_output_name};
361 48 : _problem->addReporter("PerfGraphReporter", perf_graph_reporter_name, params);
362 24 : }
363 : }
364 : else
365 0 : mooseError("unrecognized task ", _current_task, " in CommonOutputAction.");
366 318451 : }
367 :
368 : void
369 241676 : CommonOutputAction::create(const std::string & object_type,
370 : const std::optional<std::string> & param_name,
371 : const InputParameters * const from_params /* = nullptr */,
372 : const InputParameters * const apply_params /* = nullptr */,
373 : const std::optional<std::string> & object_name /* = {} */)
374 : {
375 : // Create our copy of the parameters
376 241676 : auto params = _action_params;
377 :
378 : // Set the 'type =' parameters for the desired object
379 241676 : params.set<std::string>("type") = object_type;
380 :
381 : // Create the complete object name (uses lower case of type)
382 241676 : std::string name;
383 241676 : if (object_name)
384 24 : name = *object_name;
385 : else
386 : {
387 241652 : name = object_type;
388 241652 : std::transform(name.begin(), name.end(), name.begin(), ::tolower);
389 : }
390 :
391 : // Create the action
392 : std::shared_ptr<MooseObjectAction> action = std::static_pointer_cast<MooseObjectAction>(
393 483352 : _action_factory.create("AddOutputAction", name, params));
394 241676 : auto & object_params = action->getObjectParams();
395 :
396 : // Set flag indicating that the object to be created was created with short-cut syntax
397 241676 : object_params.set<bool>("_built_by_moose") = true;
398 :
399 : // Apply any additional parameters
400 241676 : if (apply_params)
401 24 : object_params.applyParameters(*apply_params);
402 :
403 : // Associate all action output object errors with param_name
404 : // If from_params is specified, it means to associate it with parameters other than parameters()
405 241676 : if (param_name)
406 : {
407 241676 : const InputParameters & associated_params = from_params ? *from_params : parameters();
408 241676 : associateWithParameter(associated_params, *param_name, object_params);
409 : }
410 :
411 : // Add the action to the warehouse
412 241676 : _awh.addActionBlock(action);
413 241676 : }
414 :
415 : bool
416 65903 : CommonOutputAction::hasConsole()
417 : {
418 :
419 : // Loop through all of the actions for adding output objects
420 197709 : for (ActionIterator it = _awh.actionBlocksWithActionBegin("add_output");
421 535860 : it != _awh.actionBlocksWithActionEnd("add_output");
422 112717 : it++)
423 : {
424 113816 : MooseObjectAction * moa = dynamic_cast<MooseObjectAction *>(*it);
425 113816 : if (!moa)
426 67578 : continue;
427 :
428 46238 : const std::string & type = moa->getMooseObjectType();
429 46238 : InputParameters & params = moa->getObjectParams();
430 46238 : if (type.compare("Console") == 0 && params.get<bool>("output_screen"))
431 1099 : return true;
432 : }
433 :
434 64804 : return false;
435 : }
|