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 69145 : CommonOutputAction::validParams()
36 : {
37 69145 : InputParameters params = Action::validParams();
38 138290 : params.addClassDescription("Adds short-cut syntax and common parameters to the Outputs block.");
39 :
40 : // Short-cut methods for typical output objects
41 207435 : params.addParam<bool>(
42 138290 : "exodus", false, "Output the results using the default settings for Exodus output.");
43 207435 : params.addParam<bool>(
44 138290 : "nemesis", false, "Output the results using the default settings for Nemesis output");
45 207435 : params.addParam<bool>(
46 138290 : "console", true, "Output the results using the default settings for Console output");
47 207435 : params.addParam<bool>("csv",
48 138290 : false,
49 : "Output the scalar variable and postprocessors to a *.csv "
50 : "file using the default CSV output.");
51 207435 : params.addParam<bool>("xml",
52 138290 : false,
53 : "Output the vector postprocessors to a *.xml "
54 : "file using the default XML output.");
55 207435 : params.addParam<bool>("json",
56 138290 : false,
57 : "Output Reporter values to a *.json "
58 : "file using the default JSON output.");
59 207435 : params.addParam<bool>(
60 138290 : "vtk", false, "Output the results using the default settings for VTKOutput output");
61 207435 : params.addParam<bool>(
62 138290 : "xda", false, "Output the results using the default settings for XDA/XDR output (ascii)");
63 207435 : params.addParam<bool>(
64 138290 : "xdr", false, "Output the results using the default settings for XDA/XDR output (binary)");
65 207435 : params.addParam<bool>(
66 138290 : "gmv", false, "Output the results using the default settings for GMV output");
67 207435 : params.addParam<bool>(
68 138290 : "tecplot", false, "Output the results using the default settings for Tecplot output");
69 207435 : params.addParam<bool>(
70 : "gnuplot",
71 138290 : false,
72 : "Output the scalar and postprocessor results using the default settings for GNUPlot output");
73 207435 : params.addParam<bool>(
74 138290 : "solution_history", false, "Print a solution history file (.slh) using the default settings");
75 276580 : params.addParam<bool>("progress", false, "Print a progress bar");
76 276580 : params.addParam<bool>("dofmap", false, "Create the dof map .json output file");
77 276580 : 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 276580 : params.addParam<bool>("color", true, "Set to false to turn off all coloring in all outputs");
83 276580 : params.addParam<std::string>("file_base",
84 : "Common file base name to be utilized with all output objects");
85 276580 : 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 207435 : params.addParam<unsigned int>(
91 138290 : "time_step_interval", 1, "The interval (number of time steps) at which output occurs");
92 276580 : params.addParam<unsigned int>("interval",
93 : "The interval (number of time steps) at which output occurs");
94 414870 : params.deprecateParam("interval", "time_step_interval", "02/01/2025");
95 207435 : params.addParam<std::vector<Real>>("sync_times",
96 138290 : std::vector<Real>(),
97 : "Times at which the output and solution is forced to occur");
98 207435 : params.addParam<Real>(
99 138290 : "minimum_time_interval", 0.0, "The minimum simulation time between output steps");
100 207435 : params.addParam<bool>(
101 138290 : "append_date", false, "When true the date and time are appended to the output filename.");
102 276580 : 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 276580 : 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 207435 : 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 69145 : ExecFlagEnum exec_enum = Output::getDefaultExecFlagEnum();
120 207435 : exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
121 207435 : params.addParam<ExecFlagEnum>("execute_on", exec_enum, exec_enum.getDocString());
122 :
123 : // Add special Console flags
124 345725 : params.addDeprecatedParam<bool>(
125 138290 : "print_perf_log", false, "Use perf_graph instead!", "Use perf_graph instead!");
126 :
127 207435 : params.addParam<bool>(
128 138290 : "perf_graph", false, "Enable printing of the performance graph to the screen (Console)");
129 :
130 276580 : params.addParam<bool>("perf_graph_live", true, "Enables printing of live progress messages");
131 207435 : params.addParam<Real>(
132 138290 : "perf_graph_live_time_limit", 5.0, "Time (in seconds) to wait before printing a message.");
133 207435 : params.addParam<unsigned int>(
134 138290 : "perf_graph_live_mem_limit", 100, "Memory (in MB) to cause a message to be printed.");
135 276580 : params.addParam<bool>("perf_graph_json", false, "Output the perf graph in JSON");
136 276580 : params.addParam<FileName>("perf_graph_json_file", "Path to a .json file to store the perf graph");
137 :
138 207435 : params.addParam<bool>("print_mesh_changed_info",
139 138290 : false,
140 : "When true, each time the mesh is changed the mesh information is printed");
141 207435 : params.addParam<bool>("print_linear_residuals",
142 138290 : true,
143 : "Enable printing of linear residuals to the screen (Console)");
144 207435 : params.addParam<bool>("print_nonlinear_residuals",
145 138290 : true,
146 : "Enable printing of nonlinear residuals to the screen (Console)");
147 207435 : params.addParam<bool>("print_nonlinear_converged_reason",
148 138290 : 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 207435 : params.addParam<bool>("print_linear_converged_reason",
153 138290 : 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 138290 : params.addParam<bool>(
159 : "solution_invalidity_history",
160 138290 : true,
161 : "Enable printing of the time history of the solution invalidity occurrences "
162 : "to the screen (console)");
163 :
164 : // Return object
165 138290 : return params;
166 138290 : }
167 :
168 68940 : CommonOutputAction::CommonOutputAction(const InputParameters & params)
169 206820 : : Action(params), _action_params(_action_factory.getValidParams("AddOutputAction"))
170 : {
171 68940 : }
172 :
173 : void
174 194932 : CommonOutputAction::act()
175 : {
176 194932 : if (_current_task == "common_output")
177 : {
178 : // Store the common output parameters in the OutputWarehouse
179 68766 : _app.getOutputWarehouse().setCommonParameters(&_pars);
180 :
181 : // Create the actions for the short-cut methods
182 : #ifdef LIBMESH_HAVE_EXODUS_API
183 206298 : if (getParam<bool>("exodus"))
184 107580 : 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 206298 : 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 206298 : if (getParam<bool>("console") && !hasConsole())
200 202593 : create("Console", "console");
201 :
202 206298 : if (getParam<bool>("csv"))
203 36072 : create("CSV", "csv");
204 :
205 206298 : if (getParam<bool>("xml"))
206 180 : create("XMLOutput", "xml");
207 :
208 206298 : if (getParam<bool>("json"))
209 411 : create("JSON", "json");
210 :
211 : #ifdef LIBMESH_HAVE_VTK
212 206298 : 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 206298 : if (getParam<bool>("xda"))
220 390 : create("XDA", "xda");
221 :
222 206298 : if (getParam<bool>("xdr"))
223 156 : create("XDR", "xdr");
224 :
225 206298 : if (getParam<bool>("gmv"))
226 114 : create("GMV", "gmv");
227 :
228 206298 : if (getParam<bool>("tecplot"))
229 117 : create("Tecplot", "tecplot");
230 :
231 206298 : if (getParam<bool>("gnuplot"))
232 39 : create("Gnuplot", "gnuplot");
233 :
234 206298 : if (getParam<bool>("solution_history"))
235 39 : create("SolutionHistory", "solution_history");
236 :
237 206298 : if (getParam<bool>("progress"))
238 30 : create("Progress", "progress");
239 :
240 206298 : 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 137522 : [](const std::vector<std::pair<const InputParameters *, std::string>> & options)
247 : {
248 137522 : std::optional<std::string> from_param_name;
249 137522 : const InputParameters * from_params = nullptr;
250 308923 : for (const auto & [params, param_name] : options)
251 237028 : if (params->template get<bool>(param_name))
252 : {
253 65627 : from_param_name = param_name;
254 65627 : from_params = params;
255 65627 : break;
256 : }
257 275044 : return std::make_pair(from_param_name, from_params);
258 137522 : };
259 :
260 : {
261 68766 : const auto [from_param_name, from_params] =
262 275064 : find_param({{¶meters(), "controls"}, {&_app.parameters(), "show_controls"}});
263 68766 : if (from_param_name)
264 60 : create("ControlOutput", *from_param_name, from_params);
265 68766 : }
266 :
267 206298 : if (!_app.getParam<bool>("no_timing"))
268 : {
269 275024 : auto [from_param_name, from_params] = find_param({{¶meters(), "perf_graph"},
270 0 : {¶meters(), "print_perf_log"},
271 343780 : {&_app.parameters(), "timing"}});
272 68756 : if (from_param_name)
273 196821 : 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 206268 : if (getParam<bool>("perf_graph_json"))
294 78 : add_perf_graph_json("perf_graph_json", "file_base_suffix", "perf_graph");
295 206268 : 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 206256 : if (!getParam<bool>("perf_graph_live"))
305 : {
306 0 : if (!from_param_name)
307 0 : perfGraph().setActive(false);
308 0 : perfGraph().disableLivePrint();
309 : }
310 68752 : }
311 : else
312 : {
313 10 : perfGraph().setActive(false);
314 10 : perfGraph().disableLivePrint();
315 : }
316 :
317 137524 : perfGraph().setLiveTimeLimit(getParam<Real>("perf_graph_live_time_limit"));
318 137524 : perfGraph().setLiveMemoryLimit(getParam<unsigned int>("perf_graph_live_mem_limit"));
319 :
320 206286 : if (getParam<bool>("solution_invalidity_history"))
321 : {
322 206256 : create("SolutionInvalidityOutput", "solution_invalidity_history");
323 : }
324 :
325 206286 : if (!getParam<bool>("color"))
326 185 : Moose::setColorConsole(false);
327 : }
328 126166 : 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 442079 : if (!getParam<bool>("console") || (isParamValid("print_nonlinear_converged_reason") &&
334 252578 : !getParam<bool>("print_nonlinear_converged_reason")))
335 73 : Moose::PetscSupport::dontAddNonlinearConvergedReason(*_problem);
336 :
337 442079 : if (!getParam<bool>("console") || (isParamValid("print_linear_converged_reason") &&
338 252578 : !getParam<bool>("print_linear_converged_reason")))
339 83 : Moose::PetscSupport::dontAddLinearConvergedReason(*_problem);
340 : }
341 62999 : else if (_current_task == "add_reporter")
342 : {
343 314985 : if (!_app.getParam<bool>("no_timing") &&
344 377918 : (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 332450 : }
354 :
355 : void
356 250686 : 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 250686 : auto params = _action_params;
364 :
365 : // Set the 'type =' parameters for the desired object
366 250686 : params.set<std::string>("type") = object_type;
367 :
368 : // Create the complete object name (uses lower case of type)
369 250686 : std::string name;
370 250686 : if (object_name)
371 26 : name = *object_name;
372 : else
373 : {
374 250660 : name = object_type;
375 250660 : 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 501372 : _action_factory.create("AddOutputAction", name, params));
381 250686 : auto & object_params = action->getObjectParams();
382 :
383 : // Set flag indicating that the object to be created was created with short-cut syntax
384 250686 : object_params.set<bool>("_built_by_moose") = true;
385 :
386 : // Apply any additional parameters
387 250686 : 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 250686 : if (param_name)
393 : {
394 250686 : const InputParameters & associated_params = from_params ? *from_params : parameters();
395 250686 : associateWithParameter(associated_params, *param_name, object_params);
396 : }
397 :
398 : // Add the action to the warehouse
399 250686 : _awh.addActionBlock(action);
400 250686 : }
401 :
402 : bool
403 68736 : CommonOutputAction::hasConsole()
404 : {
405 :
406 : // Loop through all of the actions for adding output objects
407 206208 : for (ActionIterator it = _awh.actionBlocksWithActionBegin("add_output");
408 561756 : it != _awh.actionBlocksWithActionEnd("add_output");
409 118516 : it++)
410 : {
411 119721 : MooseObjectAction * moa = dynamic_cast<MooseObjectAction *>(*it);
412 119721 : if (!moa)
413 70547 : continue;
414 :
415 49174 : const std::string & type = moa->getMooseObjectType();
416 49174 : InputParameters & params = moa->getObjectParams();
417 49174 : if (type.compare("Console") == 0 && params.get<bool>("output_screen"))
418 1205 : return true;
419 : }
420 :
421 67531 : return false;
422 : }
|