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 66092 : CommonOutputAction::validParams()
35 : {
36 66092 : InputParameters params = Action::validParams();
37 132184 : params.addClassDescription("Adds short-cut syntax and common parameters to the Outputs block.");
38 :
39 : // Short-cut methods for typical output objects
40 198276 : params.addParam<bool>(
41 132184 : "exodus", false, "Output the results using the default settings for Exodus output.");
42 198276 : params.addParam<bool>(
43 132184 : "nemesis", false, "Output the results using the default settings for Nemesis output");
44 198276 : params.addParam<bool>(
45 132184 : "console", true, "Output the results using the default settings for Console output");
46 198276 : params.addParam<bool>("csv",
47 132184 : false,
48 : "Output the scalar variable and postprocessors to a *.csv "
49 : "file using the default CSV output.");
50 198276 : params.addParam<bool>("xml",
51 132184 : false,
52 : "Output the vector postprocessors to a *.xml "
53 : "file using the default XML output.");
54 198276 : params.addParam<bool>("json",
55 132184 : false,
56 : "Output Reporter values to a *.json "
57 : "file using the default JSON output.");
58 198276 : params.addParam<bool>(
59 132184 : "vtk", false, "Output the results using the default settings for VTKOutput output");
60 198276 : params.addParam<bool>(
61 132184 : "xda", false, "Output the results using the default settings for XDA/XDR output (ascii)");
62 198276 : params.addParam<bool>(
63 132184 : "xdr", false, "Output the results using the default settings for XDA/XDR output (binary)");
64 198276 : params.addParam<bool>(
65 132184 : "gmv", false, "Output the results using the default settings for GMV output");
66 198276 : params.addParam<bool>(
67 132184 : "tecplot", false, "Output the results using the default settings for Tecplot output");
68 198276 : params.addParam<bool>(
69 : "gnuplot",
70 132184 : false,
71 : "Output the scalar and postprocessor results using the default settings for GNUPlot output");
72 198276 : params.addParam<bool>(
73 132184 : "solution_history", false, "Print a solution history file (.slh) using the default settings");
74 264368 : params.addParam<bool>("progress", false, "Print a progress bar");
75 264368 : params.addParam<bool>("dofmap", false, "Create the dof map .json output file");
76 264368 : 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 264368 : params.addParam<bool>("color", true, "Set to false to turn off all coloring in all outputs");
82 264368 : params.addParam<std::string>("file_base",
83 : "Common file base name to be utilized with all output objects");
84 264368 : 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 198276 : params.addParam<unsigned int>(
90 132184 : "time_step_interval", 1, "The interval (number of time steps) at which output occurs");
91 198276 : params.addParam<std::vector<Real>>("sync_times",
92 132184 : std::vector<Real>(),
93 : "Times at which the output and solution is forced to occur");
94 198276 : params.addParam<Real>(
95 132184 : "min_simulation_time_interval", 0.0, "The minimum simulation time between output steps");
96 198276 : params.addParam<bool>(
97 132184 : "append_date", false, "When true the date and time are appended to the output filename.");
98 264368 : 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 264368 : 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 198276 : 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 66092 : ExecFlagEnum exec_enum = Output::getDefaultExecFlagEnum();
116 198276 : exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
117 198276 : params.addParam<ExecFlagEnum>("execute_on", exec_enum, exec_enum.getDocString());
118 :
119 : // Add special Console flags
120 330460 : params.addDeprecatedParam<bool>(
121 132184 : "print_perf_log", false, "Use perf_graph instead!", "Use perf_graph instead!");
122 :
123 198276 : params.addParam<bool>(
124 132184 : "perf_graph", false, "Enable printing of the performance graph to the screen (Console)");
125 :
126 264368 : params.addParam<bool>("perf_graph_live", true, "Enables printing of live progress messages");
127 198276 : params.addParam<Real>(
128 132184 : "perf_graph_live_time_limit", 5.0, "Time (in seconds) to wait before printing a message.");
129 198276 : params.addParam<unsigned int>(
130 132184 : "perf_graph_live_mem_limit", 100, "Memory (in MB) to cause a message to be printed.");
131 264368 : params.addParam<bool>("perf_graph_json", false, "Output the perf graph in JSON");
132 264368 : params.addParam<FileName>("perf_graph_json_file", "Path to a .json file to store the perf graph");
133 :
134 198276 : params.addParam<bool>("print_mesh_changed_info",
135 132184 : false,
136 : "When true, each time the mesh is changed the mesh information is printed");
137 198276 : params.addParam<bool>("print_linear_residuals",
138 132184 : true,
139 : "Enable printing of linear residuals to the screen (Console)");
140 198276 : params.addParam<bool>("print_nonlinear_residuals",
141 132184 : true,
142 : "Enable printing of nonlinear residuals to the screen (Console)");
143 198276 : params.addParam<bool>("print_nonlinear_converged_reason",
144 132184 : 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 198276 : params.addParam<bool>("print_linear_converged_reason",
149 132184 : 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 132184 : params.addParam<bool>(
155 : "solution_invalidity_history",
156 132184 : true,
157 : "Enable printing of the time history of the solution invalidity occurrences "
158 : "to the screen (console)");
159 :
160 : // Return object
161 132184 : return params;
162 132184 : }
163 :
164 66042 : CommonOutputAction::CommonOutputAction(const InputParameters & params)
165 198126 : : Action(params), _action_params(_action_factory.getValidParams("AddOutputAction"))
166 : {
167 66042 : }
168 :
169 : void
170 186618 : CommonOutputAction::act()
171 : {
172 : // Name of the PerfGraphReporter that could be created for the perf graph output
173 294250 : 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 186618 : static const OutputName perf_graph_json_output_name = "auto_perf_graph_json";
176 :
177 186618 : if (_current_task == "common_output")
178 : {
179 : // Store the common output parameters in the OutputWarehouse
180 65938 : _app.getOutputWarehouse().setCommonParameters(&_pars);
181 :
182 : // Create the actions for the short-cut methods
183 : #ifdef LIBMESH_HAVE_EXODUS_API
184 197814 : 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 197814 : 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 197814 : if (getParam<bool>("console") && !hasConsole())
201 194445 : create("Console", "console");
202 :
203 197814 : if (getParam<bool>("csv"))
204 36288 : create("CSV", "csv");
205 :
206 197814 : if (getParam<bool>("xml"))
207 162 : create("XMLOutput", "xml");
208 :
209 197814 : if (getParam<bool>("json"))
210 390 : create("JSON", "json");
211 :
212 : #ifdef LIBMESH_HAVE_VTK
213 197814 : 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 197814 : if (getParam<bool>("xda"))
221 390 : create("XDA", "xda");
222 :
223 197814 : if (getParam<bool>("xdr"))
224 144 : create("XDR", "xdr");
225 :
226 197814 : if (getParam<bool>("gmv"))
227 102 : create("GMV", "gmv");
228 :
229 197814 : if (getParam<bool>("tecplot"))
230 108 : create("Tecplot", "tecplot");
231 :
232 197814 : if (getParam<bool>("gnuplot"))
233 36 : create("Gnuplot", "gnuplot");
234 :
235 197814 : if (getParam<bool>("solution_history"))
236 36 : create("SolutionHistory", "solution_history");
237 :
238 197814 : if (getParam<bool>("progress"))
239 27 : create("Progress", "progress");
240 :
241 197814 : 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 131867 : [](const std::vector<std::pair<const InputParameters *, std::string>> & options)
248 : {
249 131867 : std::optional<std::string> from_param_name;
250 131867 : const InputParameters * from_params = nullptr;
251 292278 : for (const auto & [params, param_name] : options)
252 224752 : if (params->template get<bool>(param_name))
253 : {
254 64341 : from_param_name = param_name;
255 64341 : from_params = params;
256 64341 : break;
257 : }
258 263734 : return std::make_pair(from_param_name, from_params);
259 131867 : };
260 :
261 : {
262 65938 : const auto [from_param_name, from_params] =
263 263752 : find_param({{¶meters(), "controls"}, {&_app.parameters(), "show_controls"}});
264 65938 : if (from_param_name)
265 54 : create("ControlOutput", *from_param_name, from_params);
266 65938 : }
267 :
268 197814 : if (!_app.getParam<bool>("no_timing"))
269 : {
270 263716 : auto [from_param_name, from_params] = find_param({{¶meters(), "perf_graph"},
271 0 : {¶meters(), "print_perf_log"},
272 329645 : {&_app.parameters(), "timing"}});
273 65929 : if (from_param_name)
274 192969 : 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 197787 : if (getParam<bool>("perf_graph_json"))
305 72 : add_perf_graph_json("perf_graph_json", "file_base_suffix", "perf_graph");
306 197787 : 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 197778 : if (!getParam<bool>("perf_graph_live"))
316 : {
317 0 : if (!from_param_name)
318 0 : perfGraph().setActive(false);
319 0 : perfGraph().disableLivePrint();
320 : }
321 65926 : }
322 : else
323 : {
324 9 : perfGraph().setActive(false);
325 9 : perfGraph().disableLivePrint();
326 : }
327 :
328 131870 : perfGraph().setLiveTimeLimit(getParam<Real>("perf_graph_live_time_limit"));
329 131870 : perfGraph().setLiveMemoryLimit(getParam<unsigned int>("perf_graph_live_mem_limit"));
330 :
331 197805 : if (getParam<bool>("solution_invalidity_history"))
332 : {
333 197772 : create("SolutionInvalidityOutput", "solution_invalidity_history");
334 : }
335 :
336 197805 : if (!getParam<bool>("color"))
337 166 : Moose::setColorConsole(false);
338 : }
339 120680 : 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 422756 : if (!getParam<bool>("console") || (isParamValid("print_nonlinear_converged_reason") &&
345 241544 : !getParam<bool>("print_nonlinear_converged_reason")))
346 63 : Moose::PetscSupport::dontAddNonlinearConvergedReason(*_problem);
347 :
348 422756 : if (!getParam<bool>("console") || (isParamValid("print_linear_converged_reason") &&
349 241544 : !getParam<bool>("print_linear_converged_reason")))
350 72 : Moose::PetscSupport::dontAddLinearConvergedReason(*_problem);
351 : }
352 60276 : else if (_current_task == "add_reporter")
353 : {
354 301371 : if (!_app.getParam<bool>("no_timing") &&
355 361587 : (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 318506 : }
367 :
368 : void
369 241709 : 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 241709 : auto params = _action_params;
377 :
378 : // Set the 'type =' parameters for the desired object
379 241709 : params.set<std::string>("type") = object_type;
380 :
381 : // Create the complete object name (uses lower case of type)
382 241709 : std::string name;
383 241709 : if (object_name)
384 24 : name = *object_name;
385 : else
386 : {
387 241685 : name = object_type;
388 241685 : 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 483418 : _action_factory.create("AddOutputAction", name, params));
394 241709 : auto & object_params = action->getObjectParams();
395 :
396 : // Set flag indicating that the object to be created was created with short-cut syntax
397 241709 : object_params.set<bool>("_built_by_moose") = true;
398 :
399 : // Apply any additional parameters
400 241709 : 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 241709 : if (param_name)
406 : {
407 241709 : const InputParameters & associated_params = from_params ? *from_params : parameters();
408 241709 : associateWithParameter(associated_params, *param_name, object_params);
409 : }
410 :
411 : // Add the action to the warehouse
412 241709 : _awh.addActionBlock(action);
413 241709 : }
414 :
415 : bool
416 65914 : CommonOutputAction::hasConsole()
417 : {
418 :
419 : // Loop through all of the actions for adding output objects
420 197742 : for (ActionIterator it = _awh.actionBlocksWithActionBegin("add_output");
421 535959 : it != _awh.actionBlocksWithActionEnd("add_output");
422 112739 : it++)
423 : {
424 113838 : MooseObjectAction * moa = dynamic_cast<MooseObjectAction *>(*it);
425 113838 : if (!moa)
426 67589 : continue;
427 :
428 46249 : const std::string & type = moa->getMooseObjectType();
429 46249 : InputParameters & params = moa->getObjectParams();
430 46249 : if (type.compare("Console") == 0 && params.get<bool>("output_screen"))
431 1099 : return true;
432 : }
433 :
434 64815 : return false;
435 : }
|