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 68926 : CommonOutputAction::validParams()
36 : {
37 68926 : InputParameters params = Action::validParams();
38 137852 : params.addClassDescription("Adds short-cut syntax and common parameters to the Outputs block.");
39 :
40 : // Short-cut methods for typical output objects
41 206778 : params.addParam<bool>(
42 137852 : "exodus", false, "Output the results using the default settings for Exodus output.");
43 206778 : params.addParam<bool>(
44 137852 : "nemesis", false, "Output the results using the default settings for Nemesis output");
45 206778 : params.addParam<bool>(
46 137852 : "console", true, "Output the results using the default settings for Console output");
47 206778 : params.addParam<bool>("csv",
48 137852 : false,
49 : "Output the scalar variable and postprocessors to a *.csv "
50 : "file using the default CSV output.");
51 206778 : params.addParam<bool>("xml",
52 137852 : false,
53 : "Output the vector postprocessors to a *.xml "
54 : "file using the default XML output.");
55 206778 : params.addParam<bool>("json",
56 137852 : false,
57 : "Output Reporter values to a *.json "
58 : "file using the default JSON output.");
59 206778 : params.addParam<bool>(
60 137852 : "vtk", false, "Output the results using the default settings for VTKOutput output");
61 206778 : params.addParam<bool>(
62 137852 : "xda", false, "Output the results using the default settings for XDA/XDR output (ascii)");
63 206778 : params.addParam<bool>(
64 137852 : "xdr", false, "Output the results using the default settings for XDA/XDR output (binary)");
65 206778 : params.addParam<bool>(
66 137852 : "gmv", false, "Output the results using the default settings for GMV output");
67 206778 : params.addParam<bool>(
68 137852 : "tecplot", false, "Output the results using the default settings for Tecplot output");
69 206778 : params.addParam<bool>(
70 : "gnuplot",
71 137852 : false,
72 : "Output the scalar and postprocessor results using the default settings for GNUPlot output");
73 206778 : params.addParam<bool>(
74 137852 : "solution_history", false, "Print a solution history file (.slh) using the default settings");
75 275704 : params.addParam<bool>("progress", false, "Print a progress bar");
76 275704 : params.addParam<bool>("dofmap", false, "Create the dof map .json output file");
77 275704 : 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 275704 : params.addParam<bool>("color", true, "Set to false to turn off all coloring in all outputs");
83 275704 : params.addParam<std::string>("file_base",
84 : "Common file base name to be utilized with all output objects");
85 275704 : 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 206778 : params.addParam<unsigned int>(
91 137852 : "time_step_interval", 1, "The interval (number of time steps) at which output occurs");
92 275704 : params.addParam<unsigned int>("interval",
93 : "The interval (number of time steps) at which output occurs");
94 413556 : params.deprecateParam("interval", "time_step_interval", "02/01/2025");
95 206778 : params.addParam<std::vector<Real>>("sync_times",
96 137852 : std::vector<Real>(),
97 : "Times at which the output and solution is forced to occur");
98 206778 : params.addParam<Real>(
99 137852 : "minimum_time_interval", 0.0, "The minimum simulation time between output steps");
100 206778 : params.addParam<bool>(
101 137852 : "append_date", false, "When true the date and time are appended to the output filename.");
102 275704 : 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 275704 : 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 206778 : 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 68926 : ExecFlagEnum exec_enum = Output::getDefaultExecFlagEnum();
120 206778 : exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
121 206778 : params.addParam<ExecFlagEnum>("execute_on", exec_enum, exec_enum.getDocString());
122 :
123 : // Add special Console flags
124 344630 : params.addDeprecatedParam<bool>(
125 137852 : "print_perf_log", false, "Use perf_graph instead!", "Use perf_graph instead!");
126 :
127 206778 : params.addParam<bool>(
128 137852 : "perf_graph", false, "Enable printing of the performance graph to the screen (Console)");
129 :
130 275704 : params.addParam<bool>("perf_graph_live", true, "Enables printing of live progress messages");
131 206778 : params.addParam<Real>(
132 137852 : "perf_graph_live_time_limit", 5.0, "Time (in seconds) to wait before printing a message.");
133 206778 : params.addParam<unsigned int>(
134 137852 : "perf_graph_live_mem_limit", 100, "Memory (in MB) to cause a message to be printed.");
135 275704 : params.addParam<bool>("perf_graph_json", false, "Output the perf graph in JSON");
136 275704 : params.addParam<FileName>("perf_graph_json_file", "Path to a .json file to store the perf graph");
137 :
138 206778 : params.addParam<bool>("print_mesh_changed_info",
139 137852 : false,
140 : "When true, each time the mesh is changed the mesh information is printed");
141 206778 : params.addParam<bool>("print_linear_residuals",
142 137852 : true,
143 : "Enable printing of linear residuals to the screen (Console)");
144 206778 : params.addParam<bool>("print_nonlinear_residuals",
145 137852 : true,
146 : "Enable printing of nonlinear residuals to the screen (Console)");
147 206778 : params.addParam<bool>("print_nonlinear_converged_reason",
148 137852 : 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 206778 : params.addParam<bool>("print_linear_converged_reason",
153 137852 : 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 137852 : params.addParam<bool>(
159 : "solution_invalidity_history",
160 137852 : true,
161 : "Enable printing of the time history of the solution invalidity occurrences "
162 : "to the screen (console)");
163 :
164 : // Return object
165 137852 : return params;
166 137852 : }
167 :
168 68722 : CommonOutputAction::CommonOutputAction(const InputParameters & params)
169 206166 : : Action(params), _action_params(_action_factory.getValidParams("AddOutputAction"))
170 : {
171 68722 : }
172 :
173 : void
174 194290 : CommonOutputAction::act()
175 : {
176 194290 : if (_current_task == "common_output")
177 : {
178 : // Store the common output parameters in the OutputWarehouse
179 68548 : _app.getOutputWarehouse().setCommonParameters(&_pars);
180 :
181 : // Create the actions for the short-cut methods
182 : #ifdef LIBMESH_HAVE_EXODUS_API
183 205644 : if (getParam<bool>("exodus"))
184 107277 : 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 205644 : if (getParam<bool>("nemesis"))
192 771 : 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 205644 : if (getParam<bool>("console") && !hasConsole())
200 201942 : create("Console", "console");
201 :
202 205644 : if (getParam<bool>("csv"))
203 35799 : create("CSV", "csv");
204 :
205 205644 : if (getParam<bool>("xml"))
206 180 : create("XMLOutput", "xml");
207 :
208 205644 : if (getParam<bool>("json"))
209 411 : create("JSON", "json");
210 :
211 : #ifdef LIBMESH_HAVE_VTK
212 205644 : if (getParam<bool>("vtk"))
213 273 : create("VTK", "vtk");
214 : #else
215 : if (getParam<bool>("vtk"))
216 : mooseWarning("VTK output requested but not enabled through libMesh");
217 : #endif
218 :
219 205644 : if (getParam<bool>("xda"))
220 390 : create("XDA", "xda");
221 :
222 205644 : if (getParam<bool>("xdr"))
223 156 : create("XDR", "xdr");
224 :
225 205644 : if (getParam<bool>("gmv"))
226 114 : create("GMV", "gmv");
227 :
228 205644 : if (getParam<bool>("tecplot"))
229 117 : create("Tecplot", "tecplot");
230 :
231 205644 : if (getParam<bool>("gnuplot"))
232 39 : create("Gnuplot", "gnuplot");
233 :
234 205644 : if (getParam<bool>("solution_history"))
235 39 : create("SolutionHistory", "solution_history");
236 :
237 205644 : if (getParam<bool>("progress"))
238 30 : create("Progress", "progress");
239 :
240 205644 : if (getParam<bool>("dofmap"))
241 78 : 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 137086 : [](const std::vector<std::pair<const InputParameters *, std::string>> & options)
247 : {
248 137086 : std::optional<std::string> from_param_name;
249 137086 : const InputParameters * from_params = nullptr;
250 308012 : for (const auto & [params, param_name] : options)
251 236348 : if (params->template get<bool>(param_name))
252 : {
253 65422 : from_param_name = param_name;
254 65422 : from_params = params;
255 65422 : break;
256 : }
257 274172 : return std::make_pair(from_param_name, from_params);
258 137086 : };
259 :
260 : {
261 68548 : const auto [from_param_name, from_params] =
262 274192 : find_param({{¶meters(), "controls"}, {&_app.parameters(), "show_controls"}});
263 68548 : if (from_param_name)
264 60 : create("ControlOutput", *from_param_name, from_params);
265 68548 : }
266 :
267 205644 : if (!_app.getParam<bool>("no_timing"))
268 : {
269 274152 : auto [from_param_name, from_params] = find_param({{¶meters(), "perf_graph"},
270 0 : {¶meters(), "print_perf_log"},
271 342690 : {&_app.parameters(), "timing"}});
272 68538 : if (from_param_name)
273 196206 : create("PerfGraphOutput", *from_param_name, from_params);
274 :
275 26 : const auto add_perf_graph_json = [this](const std::string & from_param_name,
276 : const std::string & set_param_name,
277 : const std::string & set_param_value)
278 : {
279 : // To avoid this reporter value appearing in all other JSON output
280 26 : _common_reporter_names.push_back(perf_graph_json_reporter);
281 :
282 52 : auto params = _factory.getValidParams("JSON");
283 78 : params.set<std::vector<ReporterName>>("reporters") = {perf_graph_json_reporter};
284 78 : params.set<ExecFlagEnum>("execute_on") = {EXEC_FINAL};
285 78 : params.set<ExecFlagEnum>("execute_system_information_on") = {EXEC_NONE};
286 26 : params.set<std::string>(set_param_name) = set_param_value;
287 26 : params.set<bool>("distributed") = false;
288 26 : if (set_param_name == "file_base")
289 26 : params.set<bool>("append_date") = false;
290 78 : create("JSON", from_param_name, ¶meters(), ¶ms, from_param_name);
291 104 : };
292 :
293 205614 : if (getParam<bool>("perf_graph_json"))
294 78 : add_perf_graph_json("perf_graph_json", "file_base_suffix", "perf_graph");
295 205614 : if (isParamValid("perf_graph_json_file"))
296 : {
297 34 : const auto & file = getParam<FileName>("perf_graph_json_file");
298 17 : if (MooseUtils::getExtension(file, true) != "json")
299 8 : paramError("perf_graph_json_file", "File must end with .json");
300 13 : const auto file_stripped = MooseUtils::stripExtension(file, true);
301 39 : add_perf_graph_json("perf_graph_json_file", "file_base", file_stripped);
302 13 : }
303 :
304 205602 : if (!getParam<bool>("perf_graph_live"))
305 : {
306 0 : if (!from_param_name)
307 0 : perfGraph().setActive(false);
308 0 : perfGraph().disableLivePrint();
309 : }
310 68534 : }
311 : else
312 : {
313 10 : perfGraph().setActive(false);
314 10 : perfGraph().disableLivePrint();
315 : }
316 :
317 137088 : perfGraph().setLiveTimeLimit(getParam<Real>("perf_graph_live_time_limit"));
318 137088 : perfGraph().setLiveMemoryLimit(getParam<unsigned int>("perf_graph_live_mem_limit"));
319 :
320 205632 : if (getParam<bool>("solution_invalidity_history"))
321 : {
322 205602 : create("SolutionInvalidityOutput", "solution_invalidity_history");
323 : }
324 :
325 205632 : if (!getParam<bool>("color"))
326 185 : Moose::setColorConsole(false);
327 : }
328 125742 : 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 440570 : if (!getParam<bool>("console") || (isParamValid("print_nonlinear_converged_reason") &&
334 251717 : !getParam<bool>("print_nonlinear_converged_reason")))
335 72 : Moose::PetscSupport::dontAddNonlinearConvergedReason(*_problem);
336 :
337 440570 : if (!getParam<bool>("console") || (isParamValid("print_linear_converged_reason") &&
338 251717 : !getParam<bool>("print_linear_converged_reason")))
339 82 : Moose::PetscSupport::dontAddLinearConvergedReason(*_problem);
340 : }
341 62791 : else if (_current_task == "add_reporter")
342 : {
343 313945 : if (!_app.getParam<bool>("no_timing") &&
344 376670 : (getParam<bool>("perf_graph_json") || isParamValid("perf_graph_json_file")))
345 : {
346 78 : auto params = _factory.getValidParams("PerfGraphReporter");
347 26 : params.set<ExecFlagEnum>("execute_on") = EXEC_FINAL;
348 52 : _problem->addReporter("PerfGraphReporter", perf_graph_json_reporter.getObjectName(), params);
349 26 : }
350 : }
351 : else
352 0 : mooseError("unrecognized task ", _current_task, " in CommonOutputAction.");
353 331372 : }
354 :
355 : void
356 249854 : 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 249854 : auto params = _action_params;
364 :
365 : // Set the 'type =' parameters for the desired object
366 249854 : params.set<std::string>("type") = object_type;
367 :
368 : // Create the complete object name (uses lower case of type)
369 249854 : std::string name;
370 249854 : if (object_name)
371 26 : name = *object_name;
372 : else
373 : {
374 249828 : name = object_type;
375 249828 : 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 499708 : _action_factory.create("AddOutputAction", name, params));
381 249854 : auto & object_params = action->getObjectParams();
382 :
383 : // Set flag indicating that the object to be created was created with short-cut syntax
384 249854 : object_params.set<bool>("_built_by_moose") = true;
385 :
386 : // Apply any additional parameters
387 249854 : if (apply_params)
388 26 : 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 249854 : if (param_name)
393 : {
394 249854 : const InputParameters & associated_params = from_params ? *from_params : parameters();
395 249854 : associateWithParameter(associated_params, *param_name, object_params);
396 : }
397 :
398 : // Add the action to the warehouse
399 249854 : _awh.addActionBlock(action);
400 249854 : }
401 :
402 : bool
403 68519 : CommonOutputAction::hasConsole()
404 : {
405 :
406 : // Loop through all of the actions for adding output objects
407 205557 : for (ActionIterator it = _awh.actionBlocksWithActionBegin("add_output");
408 560034 : it != _awh.actionBlocksWithActionEnd("add_output");
409 118159 : it++)
410 : {
411 119364 : MooseObjectAction * moa = dynamic_cast<MooseObjectAction *>(*it);
412 119364 : if (!moa)
413 70330 : continue;
414 :
415 49034 : const std::string & type = moa->getMooseObjectType();
416 49034 : InputParameters & params = moa->getObjectParams();
417 49034 : if (type.compare("Console") == 0 && params.get<bool>("output_screen"))
418 1205 : return true;
419 : }
420 :
421 67314 : return false;
422 : }
|