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