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