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 "Console.h"
12 : #include "ConsoleUtils.h"
13 : #include "FEProblem.h"
14 : #include "EigenProblem.h"
15 : #include "Postprocessor.h"
16 : #include "PetscSupport.h"
17 : #include "Executioner.h"
18 : #include "MooseApp.h"
19 : #include "Moose.h"
20 : #include "FormattedTable.h"
21 : #include "NonlinearSystem.h"
22 : #include "CommonOutputAction.h"
23 :
24 : // libMesh includes
25 : #include "libmesh/enum_norm_type.h"
26 :
27 : using namespace libMesh;
28 :
29 : registerMooseObject("MooseApp", Console);
30 :
31 : InputParameters
32 156572 : Console::validParams()
33 : {
34 : // Enum for selecting the fit mode for the table when printed to the screen
35 156572 : MooseEnum pps_fit_mode(FormattedTable::getWidthModes());
36 :
37 : // Get the parameters from the base class
38 156572 : InputParameters params = TableOutput::validParams();
39 156572 : params.addClassDescription("Object for screen output.");
40 :
41 156572 : params += TableOutput::enableOutputTypes("system_information scalar postprocessor input");
42 :
43 156572 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_on");
44 156572 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_postprocessors_on");
45 156572 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_scalars_on");
46 :
47 : // Screen and file output toggles
48 156572 : params.addParam<bool>("output_screen", true, "Output to the screen");
49 469716 : params.addParam<bool>("output_file",
50 313144 : false,
51 : "Output to the file. The default behavior is to write to file only from "
52 : "the head processor. If \"--keep-cout\" is passed to the executable, then "
53 : "each processor will write to its own file. The same parallel behaviour "
54 : "can also be achieved by passing \"--keep-cout --redirect-stdout\" to the "
55 : "executable without setting this parameter to true.");
56 469716 : params.addParam<bool>(
57 313144 : "show_multiapp_name", false, "Indent multiapp output using the multiapp name");
58 :
59 : // Table fitting options
60 469716 : params.addParam<unsigned int>("max_rows",
61 313144 : 15,
62 : "The maximum number of postprocessor/scalar values "
63 : "displayed on screen during a timestep (set to 0 "
64 : "for unlimited)");
65 156572 : params.addParam<MooseEnum>("fit_mode",
66 : pps_fit_mode,
67 : "Specifies the wrapping mode for post-processor tables that are "
68 : "printed to the screen (ENVIRONMENT: Read \"MOOSE_PPS_WIDTH\" for "
69 : "desired width (if not set, defaults to AUTO), AUTO: Attempt to "
70 : "determine width automatically (serial only), <n>: Desired width");
71 :
72 : // Verbosity
73 156572 : params.addParam<bool>("verbose", false, "Print detailed diagnostics on timestep calculation");
74 :
75 : // Basic table output controls
76 469716 : params.addParam<bool>(
77 313144 : "scientific_time", false, "Control the printing of time and dt in scientific notation");
78 156572 : params.addParam<unsigned int>(
79 : "time_precision",
80 : "The number of significant digits that are printed on time related outputs");
81 156572 : MooseEnum time_format("plain=0 second=1 minute=2 hour=3 day=4 dtime=5", "plain");
82 156572 : params.addParam<MooseEnum>(
83 : "time_format",
84 : time_format,
85 : "The format for the printed times ('dtime' means a format like 1d 01:01:0.1)");
86 :
87 : // Performance Logging
88 469716 : params.addDeprecatedParam<bool>("perf_log",
89 313144 : false,
90 : "If true, all performance logs will be printed. The "
91 : "individual log settings will override this option.",
92 : "Use PerfGraphOutput");
93 469716 : params.addDeprecatedParam<unsigned int>(
94 : "perf_log_interval",
95 313144 : 0,
96 : "If set, the performance log will be printed every n time steps",
97 : "Use PerfGraphOutput instead");
98 156572 : params.addParam<bool>("solve_log", "Toggles the printing of the 'Moose Test Performance' log");
99 156572 : params.addDeprecatedParam<bool>(
100 : "perf_header",
101 : "Print the libMesh performance log header (requires that 'perf_log = true')",
102 : "Use PerfGraphOutput instead");
103 :
104 469716 : params.addParam<bool>(
105 : "libmesh_log",
106 313144 : true,
107 : "Print the libMesh performance log, requires libMesh to be configured with --enable-perflog");
108 :
109 : // Toggle printing of mesh information on adaptivity steps
110 469716 : params.addParam<bool>("print_mesh_changed_info",
111 313144 : false,
112 : "When true, each time the mesh is changed the mesh information is printed");
113 :
114 : // Toggle for printing variable norms
115 469716 : params.addParam<bool>("outlier_variable_norms",
116 313144 : true,
117 : "If true, outlier variable norms will be printed after each solve");
118 469716 : params.addParam<bool>(
119 313144 : "all_variable_norms", false, "If true, all variable norms will be printed after each solve");
120 :
121 : // Multipliers for coloring of variable residual norms
122 156572 : std::vector<Real> multiplier;
123 156572 : multiplier.push_back(0.8);
124 156572 : multiplier.push_back(2);
125 156572 : params.addParam<std::vector<Real>>("outlier_multiplier",
126 : multiplier,
127 : "Multiplier utilized to determine if a residual norm is an "
128 : "outlier. If the variable residual is less than "
129 : "multiplier[0] times the total residual it is colored red. "
130 : "If the variable residual is less than multiplier[1] times "
131 : "the average residual it is colored yellow.");
132 :
133 : // System information controls
134 : MultiMooseEnum info("framework mesh aux nonlinear linear relationship execution output",
135 156572 : "framework mesh aux nonlinear linear execution");
136 156572 : params.addParam<MultiMooseEnum>("system_info",
137 : info,
138 : "List of information types to display "
139 : "('framework', 'mesh', 'aux', 'nonlinear', 'relationship', "
140 : "'execution', 'output')");
141 :
142 : // Advanced group
143 156572 : params.addParamNamesToGroup("verbose show_multiapp_name system_info", "Advanced");
144 :
145 : // Performance log group
146 156572 : params.addParamNamesToGroup("perf_log solve_log perf_header libmesh_log", "Perf Log");
147 :
148 : // Variable norms group
149 156572 : params.addParamNamesToGroup("outlier_variable_norms all_variable_norms outlier_multiplier",
150 : "Variable and Residual Norms");
151 :
152 : // Number formatting
153 156572 : params.addParamNamesToGroup("scientific_time time_precision time_format",
154 : "Time output formatting");
155 :
156 : // Table of postprocessor output formatting
157 156572 : params.addParamNamesToGroup("max_rows fit_mode", "Table formatting");
158 :
159 : /*
160 : * The following modifies the default behavior from base class parameters. Notice the extra flag
161 : * on
162 : * the set method. This enables "quiet mode". This is done to allow for the proper detection
163 : * of user-modified parameters
164 : */
165 : // By default set System Information to output on initial
166 156572 : params.set<ExecFlagEnum>("execute_system_information_on", /*quite_mode=*/true) = EXEC_INITIAL;
167 :
168 : // Change the default behavior of 'execute_on' to included nonlinear iterations and failed
169 : // timesteps
170 313144 : params.set<ExecFlagEnum>("execute_on", /*quiet_mode=*/true) = {
171 1096004 : EXEC_INITIAL, EXEC_TIMESTEP_BEGIN, EXEC_LINEAR, EXEC_NONLINEAR, EXEC_FAILED};
172 :
173 : // By default postprocessors and scalar are only output at the end of a timestep
174 313144 : params.set<ExecFlagEnum>("execute_postprocessors_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
175 626288 : EXEC_TIMESTEP_END};
176 313144 : params.set<ExecFlagEnum>("execute_vector_postprocessors_on",
177 626288 : /*quiet_mode=*/true) = {EXEC_INITIAL, EXEC_TIMESTEP_END};
178 313144 : params.set<ExecFlagEnum>("execute_scalars_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
179 626288 : EXEC_TIMESTEP_END};
180 313144 : params.set<ExecFlagEnum>("execute_reporters_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
181 626288 : EXEC_TIMESTEP_END};
182 313144 : return params;
183 939432 : }
184 :
185 61262 : Console::Console(const InputParameters & parameters)
186 : : TableOutput(parameters),
187 61262 : _max_rows(getParam<unsigned int>("max_rows")),
188 61262 : _fit_mode(getParam<MooseEnum>("fit_mode")),
189 61262 : _scientific_time(getParam<bool>("scientific_time")),
190 61262 : _write_file(getParam<bool>("output_file")),
191 61262 : _write_screen(getParam<bool>("output_screen")),
192 61262 : _verbose(getParam<bool>("verbose")),
193 61262 : _perf_log(getParam<bool>("perf_log")),
194 61262 : _perf_log_interval(getParam<unsigned int>("perf_log_interval")),
195 61262 : _solve_log(isParamValid("solve_log") ? getParam<bool>("solve_log") : _perf_log),
196 61262 : _libmesh_log(getParam<bool>("libmesh_log")),
197 61262 : _perf_header(isParamValid("perf_header") ? getParam<bool>("perf_header") : _perf_log),
198 61262 : _all_variable_norms(getParam<bool>("all_variable_norms")),
199 61262 : _outlier_variable_norms(getParam<bool>("outlier_variable_norms")),
200 61262 : _outlier_multiplier(getParam<std::vector<Real>>("outlier_multiplier")),
201 61262 : _precision(isParamValid("time_precision") ? getParam<unsigned int>("time_precision") : 0),
202 61262 : _time_format(getParam<MooseEnum>("time_format").getEnum<TimeFormatEnum>()),
203 61262 : _write_all_procs_to_files(_app.getParam<bool>("keep_cout")),
204 61262 : _console_buffer(_app.getOutputWarehouse().consoleBuffer()),
205 61262 : _old_linear_norm(std::numeric_limits<Real>::max()),
206 61262 : _old_nonlinear_norm(std::numeric_limits<Real>::max()),
207 61262 : _print_mesh_changed_info(getParam<bool>("print_mesh_changed_info")),
208 61262 : _system_info_flags(getParam<MultiMooseEnum>("system_info")),
209 61262 : _allow_changing_sysinfo_flag(true),
210 122524 : _last_message_ended_in_newline(true)
211 : {
212 : // Apply the special common console flags (print_...)
213 61262 : ActionWarehouse & awh = _app.actionWarehouse();
214 61262 : const auto actions = awh.getActions<CommonOutputAction>();
215 : mooseAssert(actions.size() <= 1, "Should not be more than one CommonOutputAction");
216 61262 : const Action * common = actions.empty() ? nullptr : *actions.begin();
217 :
218 61262 : if (!parameters.isParamSetByUser("execute_on"))
219 : {
220 : // Honor the 'print_linear_residuals' option, only if 'linear' has not been set in 'execute_on'
221 : // by the user
222 61086 : if (common && common->getParam<bool>("print_linear_residuals"))
223 60287 : _execute_on.setAdditionalValue("linear");
224 : else
225 799 : _execute_on.eraseSetValue("linear");
226 61086 : if (common && common->getParam<bool>("print_nonlinear_residuals"))
227 60968 : _execute_on.setAdditionalValue("nonlinear");
228 : else
229 118 : _execute_on.eraseSetValue("nonlinear");
230 : }
231 :
232 61262 : if (!_pars.isParamSetByUser("perf_log") && common && common->getParam<bool>("print_perf_log"))
233 : {
234 0 : _perf_log = true;
235 0 : _solve_log = true;
236 : }
237 :
238 : // Append the common 'execute_on' to the setting for this object
239 : // This is unique to the Console object, all other objects inherit from the common options
240 61262 : if (common)
241 : {
242 61262 : const ExecFlagEnum & common_execute_on = common->getParam<ExecFlagEnum>("execute_on");
243 175315 : for (auto & mme : common_execute_on)
244 114053 : _execute_on.setAdditionalValue(mme);
245 : }
246 :
247 : // If --show-outputs is used, enable it
248 61262 : if (_app.getParam<bool>("show_outputs"))
249 10 : _system_info_flags.setAdditionalValue("output");
250 61262 : }
251 :
252 116090 : Console::~Console()
253 : {
254 : // Write the libMesh log
255 58045 : if (_libmesh_log)
256 58045 : write(libMesh::perflog.get_perf_info(), false);
257 :
258 : // Write the file output stream
259 58045 : writeStreamToFile();
260 :
261 : // Disable logging so that the destructor in libMesh doesn't print
262 58045 : libMesh::perflog.disable_logging();
263 116090 : }
264 :
265 : void
266 59997 : Console::initialSetup()
267 : {
268 : // Only allow the main app to change the perf_log settings.
269 59997 : if (_app.name() == "main")
270 : {
271 : // Disable libMesh log
272 48041 : if (!_libmesh_log)
273 0 : libMesh::perflog.disable_logging();
274 : }
275 :
276 : // system info flag can be changed only before console initial setup
277 59997 : _allow_changing_sysinfo_flag = false;
278 :
279 : // If execute_on = 'initial' perform the output
280 59997 : if (wantOutput("system_information", EXEC_INITIAL))
281 59997 : outputSystemInformation();
282 :
283 : // Call the base class method
284 59997 : TableOutput::initialSetup();
285 :
286 : // If file output is desired, wipe out the existing file if not recovering
287 59981 : if (!_app.isRecovering())
288 56144 : writeStreamToFile(false);
289 :
290 : // Enable verbose output if Executioner has it enabled
291 179943 : if (_app.getExecutioner()->isParamValid("verbose") &&
292 119962 : _app.getExecutioner()->getParam<bool>("verbose"))
293 1077 : _verbose = true;
294 :
295 : // If the user adds "final" to the execute on, append this to the postprocessors, scalars, etc.,
296 : // but only
297 : // if the parameter (e.g., postprocessor_execute_on) has not been modified by the user.
298 59981 : if (_execute_on.isValueSet("final"))
299 : {
300 752 : if (!_pars.isParamSetByUser("postprocessor_execute_on"))
301 752 : _advanced_execute_on["postprocessors"].setAdditionalValue("final");
302 752 : if (!_pars.isParamSetByUser("scalars_execute_on"))
303 752 : _advanced_execute_on["scalars"].setAdditionalValue("final");
304 752 : if (!_pars.isParamSetByUser("vector_postprocessor_execute_on"))
305 752 : _advanced_execute_on["vector_postprocessors"].setAdditionalValue("final");
306 : }
307 59981 : }
308 :
309 : std::string
310 82538 : Console::filename()
311 : {
312 82538 : std::string file_name;
313 82538 : if (_write_all_procs_to_files)
314 : {
315 406 : std::string pid = std::to_string(processor_id());
316 406 : file_name = _file_base + "_" + pid + ".txt";
317 406 : }
318 : else
319 82132 : file_name = _file_base + ".txt";
320 82538 : return file_name;
321 0 : }
322 :
323 : void
324 283108 : Console::timestepSetup()
325 : {
326 283108 : writeTimestepInformation(/*output_dt = */ true);
327 283108 : }
328 :
329 : void
330 4029261 : Console::output()
331 : {
332 4029261 : const auto & type = _current_execute_flag;
333 :
334 : // Return if the current output is not on the desired interval
335 4029261 : if (type != EXEC_FINAL && !onInterval())
336 0 : return;
337 :
338 : // Output the system information first; this forces this to be the first item to write by default
339 : // However, 'output_system_information_on' still operates correctly, so it may be changed by the
340 : // user
341 4029261 : if (wantOutput("system_information", type) && !(type == EXEC_INITIAL))
342 0 : outputSystemInformation();
343 :
344 : // Write the input
345 4029261 : if (wantOutput("input", type))
346 30 : outputInput();
347 :
348 : // Write the timestep information ("Time Step 0 ..."), this is controlled with "execute_on"
349 : // We only write the initial and final here. All of the intermediate outputs will be written
350 : // through timestepSetup.
351 4029261 : if (type == EXEC_INITIAL && _execute_on.isValueSet(EXEC_INITIAL))
352 56760 : writeTimestepInformation(/*output_dt = */ false);
353 3972501 : else if (type == EXEC_FINAL && _execute_on.isValueSet(EXEC_FINAL))
354 : {
355 759 : if (wantOutput("postprocessors", type) || wantOutput("scalars", type))
356 263 : _console << "\nFINAL:\n";
357 : }
358 :
359 : // Print Non-linear Residual (control with "execute_on")
360 4029261 : if (type == EXEC_NONLINEAR && _execute_on.isValueSet(EXEC_NONLINEAR))
361 : {
362 811506 : if (_nonlinear_iter == 0)
363 307462 : _old_nonlinear_norm = std::numeric_limits<Real>::max();
364 :
365 811506 : _console << std::right << std::setw(2) << _nonlinear_iter
366 811506 : << " Nonlinear |R| = " << outputNorm(_old_nonlinear_norm, _norm) << '\n';
367 :
368 811506 : _old_nonlinear_norm = _norm;
369 : }
370 :
371 : // Print Linear Residual (control with "execute_on")
372 3217755 : else if (type == EXEC_LINEAR && _execute_on.isValueSet(EXEC_LINEAR))
373 : {
374 2595618 : if (_linear_iter == 0)
375 511080 : _old_linear_norm = std::numeric_limits<Real>::max();
376 :
377 2595618 : _console << std::right << std::setw(7) << _linear_iter
378 2595618 : << " Linear |R| = " << outputNorm(_old_linear_norm, _norm) << '\n';
379 :
380 2595618 : _old_linear_norm = _norm;
381 : }
382 :
383 : // Write variable norms
384 622137 : else if (type == EXEC_TIMESTEP_END)
385 230403 : writeVariableNorms();
386 :
387 4029261 : if (wantOutput("postprocessors", type))
388 115712 : outputPostprocessors();
389 :
390 4029257 : if (wantOutput("scalars", type))
391 18167 : outputScalarVariables();
392 :
393 4029257 : if (wantOutput("reporters", type))
394 5958 : outputReporters();
395 :
396 : // Write the file
397 4029257 : writeStreamToFile();
398 :
399 4029257 : _console << std::flush;
400 : }
401 :
402 : void
403 4143446 : Console::writeStreamToFile(bool append)
404 : {
405 4143446 : if (!_write_file || (!_write_all_procs_to_files && processor_id() > 0))
406 4120909 : return;
407 :
408 : // Create the stream
409 22537 : std::ofstream output;
410 :
411 : // Open the file
412 22537 : if (append)
413 22346 : output.open(filename().c_str(), std::ios::app | std::ios::out);
414 : else
415 191 : output.open(filename().c_str(), std::ios::trunc);
416 :
417 22537 : if (output.fail())
418 0 : mooseError("Unable to open file ", filename());
419 :
420 22537 : std::string s = _file_output_stream.str();
421 : // Write contents of file output stream and close the file
422 22537 : output << MooseUtils::removeColor(s);
423 22537 : output.close();
424 :
425 : // Clear the file output stream
426 22537 : _file_output_stream.str("");
427 22537 : }
428 :
429 : void
430 339868 : Console::writeTimestepInformation(bool output_dt)
431 : {
432 : // Stream to build the time step information
433 339868 : std::stringstream oss;
434 :
435 : // Write timestep data for transient executioners
436 339868 : if (_transient)
437 : {
438 : // Write time step and time information
439 281561 : oss << "\nTime Step " << timeStep();
440 281561 : unsigned int time_step_digits = oss.str().length() - 11;
441 :
442 : // Print the time
443 281561 : oss << ", time = " << formatTime(getOutputTime());
444 :
445 281561 : if (output_dt)
446 : {
447 253526 : if (!_verbose)
448 : // Show the time delta information
449 245419 : oss << ", dt = " << std::left << formatTime(dt());
450 :
451 : // Show old time information, if desired on separate lines
452 : else
453 : {
454 8107 : unsigned int fillsize = 19 + time_step_digits;
455 8107 : oss << '\n'
456 8107 : << std::right << std::setw(fillsize) << std::setfill(' ') << "old time = " << std::left
457 8107 : << formatTime(timeOld()) << '\n';
458 :
459 : // Show the time delta information
460 8107 : oss << std::right << std::setw(fillsize) << std::setfill(' ') << "dt = " << std::left
461 8107 : << formatTime(dt()) << '\n';
462 :
463 : // Show the old time delta information, if desired
464 8107 : if (_verbose)
465 8107 : oss << std::right << std::setw(fillsize) << std::setfill(' ')
466 8107 : << "old dt = " << formatTime(_dt_old) << '\n';
467 : }
468 : }
469 :
470 281561 : oss << '\n';
471 :
472 : // Output to the screen
473 281561 : _console << oss.str() << std::flush;
474 : }
475 339868 : }
476 :
477 : std::string
478 551301 : Console::formatTime(const Real t) const
479 : {
480 551301 : std::ostringstream oss;
481 551301 : if (_time_format != TimeFormatEnum::DTIME)
482 : {
483 548931 : if (_precision > 0)
484 7910 : oss << std::setw(_precision) << std::setprecision(_precision) << std::setfill('0')
485 7910 : << std::showpoint;
486 548931 : if (_scientific_time)
487 0 : oss << std::scientific;
488 :
489 548931 : if (_time_format == TimeFormatEnum::PLAIN)
490 541821 : oss << t;
491 7110 : else if (_time_format == TimeFormatEnum::SECOND)
492 0 : oss << t << "s";
493 7110 : else if (_time_format == TimeFormatEnum::MINUTE)
494 2370 : oss << t / 60 << "m";
495 4740 : else if (_time_format == TimeFormatEnum::HOUR)
496 2370 : oss << t / 3600 << "h";
497 2370 : else if (_time_format == TimeFormatEnum::DAY)
498 2370 : oss << t / 86400 << "d";
499 : }
500 : else
501 : {
502 2370 : Real abst = t;
503 2370 : if (t < 0)
504 : {
505 80 : oss << "-";
506 80 : abst = -t;
507 : }
508 2370 : int days = std::floor(abst / 24 / 3600);
509 2370 : int hours = std::floor(abst / 3600 - days * 24);
510 2370 : int mins = std::floor(abst / 60 - days * 24 * 60 - hours * 60);
511 2370 : Real second = abst - days * 24 * 3600 - hours * 3600 - mins * 60;
512 :
513 2370 : if (days != 0)
514 30 : oss << days << "d";
515 2370 : if (hours != 0 || mins != 0 || second != 0)
516 : {
517 2370 : if (days != 0)
518 30 : oss << " ";
519 2370 : oss << std::setfill('0') << std::setw(2) << hours << ":" << std::setfill('0') << std::setw(2)
520 2370 : << mins << ":";
521 :
522 2370 : if (second < 10)
523 890 : oss << "0";
524 2370 : if (_precision > 0)
525 2370 : oss << std::setw(_precision) << std::setprecision(_precision) << std::setfill('0')
526 2370 : << std::showpoint;
527 2370 : if (_scientific_time)
528 0 : oss << std::scientific;
529 2370 : oss << second;
530 : }
531 0 : else if (days == 0)
532 0 : oss << "0s";
533 : }
534 1102602 : return oss.str();
535 551301 : }
536 :
537 : void
538 230403 : Console::writeVariableNorms()
539 : {
540 : // If all_variable_norms is true, then so should outlier printing
541 230403 : if (_all_variable_norms)
542 19 : _outlier_variable_norms = true;
543 :
544 : // if we are not priting anything, let's not waste time computing the norms below and just exit
545 : // this call
546 230403 : if ((_all_variable_norms == false) && (_outlier_variable_norms == false))
547 652 : return;
548 :
549 : // if it is an eigenvalue prolblem, we do not know to define RHS,
550 : // and then we do not know how to compute variable norms
551 230367 : if (dynamic_cast<EigenProblem *>(_problem_ptr) != nullptr)
552 616 : return;
553 :
554 : // Flag set when header prints
555 229751 : bool header = false;
556 :
557 : // String stream for variable norm information
558 229751 : std::ostringstream oss;
559 :
560 461763 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
561 : {
562 : // Get a references to the NonlinearSystem and libMesh system
563 232012 : NonlinearSystemBase & nl = _problem_ptr->getNonlinearSystemBase(i);
564 232012 : System & sys = nl.system();
565 :
566 : // Storage for norm outputs
567 232012 : std::map<std::string, Real> other;
568 232012 : std::map<std::string, Real> outlier;
569 :
570 : // Average norm
571 232012 : unsigned int n_vars = sys.n_vars();
572 232012 : Real avg_norm = (nl.nonlinearNorm() * nl.nonlinearNorm()) / n_vars;
573 :
574 : // Compute the norms for each of the variables
575 517506 : for (unsigned int i = 0; i < n_vars; i++)
576 : {
577 : // Compute the norm and extract the variable name
578 285494 : Real var_norm = sys.calculate_norm(nl.RHS(), i, DISCRETE_L2);
579 285494 : var_norm *= var_norm; // use the norm squared
580 285494 : std::string var_name = sys.variable_name(i);
581 :
582 : // Outlier if the variable norm is greater than twice (default) of the average norm
583 285494 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[1] * avg_norm))
584 : {
585 : // Print the header
586 14544 : if (!header)
587 : {
588 14034 : oss << "\nOutlier Variable Residual Norms:\n";
589 14034 : header = true;
590 : }
591 :
592 : // Set the color, RED if the variable norm is 0.8 (default) of the total norm
593 14544 : std::string color = COLOR_YELLOW;
594 14544 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[0] * avg_norm * n_vars))
595 13615 : color = COLOR_RED;
596 :
597 : // Display the residual
598 14544 : oss << " " << var_name << ": " << std::scientific << color << std::sqrt(var_norm)
599 14544 : << COLOR_DEFAULT << '\n';
600 14544 : }
601 :
602 : // GREEN
603 270950 : else if (_all_variable_norms)
604 : {
605 : // Print the header if it doesn't already exist
606 38 : if (!header)
607 : {
608 19 : oss << "\nVariable Residual Norms:\n";
609 19 : header = true;
610 : }
611 38 : oss << " " << var_name << ": " << std::scientific << COLOR_GREEN << std::sqrt(var_norm)
612 38 : << COLOR_DEFAULT << '\n';
613 : }
614 285494 : }
615 232012 : }
616 :
617 : // Update the output streams
618 229751 : _console << oss.str() << std::flush;
619 229751 : }
620 :
621 : // Quick helper to output the norm in color
622 : std::string
623 3771380 : Console::outputNorm(const Real & old_norm, const Real & norm, const unsigned int precision)
624 : {
625 3771380 : std::string color = COLOR_GREEN;
626 :
627 : // Red if the residual went up... or if the norm is nan
628 3771380 : if (norm != norm || norm > old_norm)
629 62110 : color = COLOR_RED;
630 : // Yellow if change is less than 5%
631 3709270 : else if ((old_norm - norm) / old_norm <= 0.05)
632 99833 : color = COLOR_YELLOW;
633 :
634 3771380 : std::stringstream oss;
635 3771380 : oss << std::scientific << std::setprecision(precision) << color << norm << COLOR_DEFAULT;
636 :
637 7542760 : return oss.str();
638 3771380 : }
639 :
640 : void
641 30 : Console::outputInput()
642 : {
643 30 : if (!_write_screen && !_write_file)
644 0 : return;
645 :
646 30 : std::ostringstream oss;
647 60 : for (const auto & filename : _app.getInputFileNames())
648 30 : oss << "--- " << filename << "\n";
649 30 : _app.actionWarehouse().printInputFile(oss);
650 30 : _console << oss.str() << std::endl;
651 30 : }
652 :
653 : void
654 115712 : Console::outputPostprocessors()
655 : {
656 115712 : TableOutput::outputPostprocessors();
657 :
658 115712 : if (!_postprocessor_table.empty())
659 : {
660 115712 : std::stringstream oss;
661 115712 : oss << "\nPostprocessor Values:\n";
662 115712 : _postprocessor_table.sortColumns();
663 115712 : _postprocessor_table.printTable(oss, _max_rows, _fit_mode);
664 115708 : _console << oss.str() << std::endl;
665 115708 : }
666 115708 : }
667 :
668 : void
669 5958 : Console::outputReporters()
670 : {
671 5958 : TableOutput::outputReporters();
672 :
673 5958 : if (!_reporter_table.empty())
674 : {
675 2682 : std::stringstream oss;
676 2682 : oss << "\nReporter Values:\n";
677 2682 : _reporter_table.sortColumns();
678 2682 : _reporter_table.printTable(oss, _max_rows, _fit_mode);
679 2682 : _console << oss.str() << '\n';
680 2682 : }
681 5958 : }
682 :
683 : void
684 18167 : Console::outputScalarVariables()
685 : {
686 18167 : TableOutput::outputScalarVariables();
687 :
688 18167 : if (!_scalar_table.empty())
689 : {
690 18167 : std::stringstream oss;
691 18167 : oss << "\nScalar Variable Values:\n";
692 18167 : if (processor_id() == 0)
693 : {
694 16104 : _scalar_table.sortColumns();
695 16104 : _scalar_table.printTable(oss, _max_rows, _fit_mode);
696 : }
697 18167 : _console << oss.str() << std::endl;
698 18167 : }
699 18167 : }
700 :
701 : void
702 59997 : Console::outputSystemInformation()
703 : {
704 : // skip system information output for sub-apps other than the zero-th of a MultiApp
705 : // because they are using the same inputs and are most likely having the same information.
706 59997 : if (_app.multiAppNumber() > 0)
707 5264 : return;
708 :
709 54733 : if (_system_info_flags.isValueSet("framework"))
710 54720 : _console << ConsoleUtils::outputFrameworkInformation(_app);
711 :
712 54733 : if (_system_info_flags.isValueSet("mesh"))
713 54720 : _console << ConsoleUtils::outputMeshInformation(*_problem_ptr);
714 :
715 54733 : if (_system_info_flags.isValueSet("nonlinear"))
716 : {
717 108375 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
718 : {
719 53655 : std::string output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr, i);
720 53655 : if (!output.empty())
721 : {
722 44449 : _console << "Nonlinear System";
723 44449 : if (_problem_ptr->numNonlinearSystems() > 1)
724 424 : _console << " [" + _problem_ptr->getNonlinearSystemNames()[i] + "]";
725 44449 : _console << ":\n" << output;
726 : }
727 53655 : }
728 : }
729 :
730 54733 : if (_system_info_flags.isValueSet("linear"))
731 55945 : for (const auto i : make_range(_problem_ptr->numLinearSystems()))
732 : {
733 : std::string output = ConsoleUtils::outputSolverSystemInformation(
734 1314 : *_problem_ptr, _problem_ptr->numNonlinearSystems() + i);
735 1314 : if (!output.empty())
736 2628 : _console << "Linear System" +
737 5256 : (_problem_ptr->numLinearSystems() > 1 ? (" " + std::to_string(i)) : "") +
738 2628 : ":\n"
739 1314 : << output;
740 1314 : }
741 :
742 54733 : if (_system_info_flags.isValueSet("aux"))
743 : {
744 54720 : std::string output = ConsoleUtils::outputAuxiliarySystemInformation(*_problem_ptr);
745 54720 : if (!output.empty())
746 22444 : _console << "Auxiliary System:\n" << output;
747 54720 : }
748 :
749 54733 : if (_system_info_flags.isValueSet("relationship"))
750 : {
751 102 : std::string output = ConsoleUtils::outputRelationshipManagerInformation(_app);
752 102 : if (!output.empty())
753 102 : _console << "Relationship Managers:\n" << output;
754 102 : }
755 :
756 54733 : if (_system_info_flags.isValueSet("execution"))
757 54720 : _console << ConsoleUtils::outputExecutionInformation(_app, *_problem_ptr);
758 :
759 54733 : if (_app.getParam<bool>("show_data_paths"))
760 10 : _console << ConsoleUtils::outputDataFilePaths();
761 :
762 54733 : if (_app.getParam<bool>("show_data_params"))
763 10 : _console << ConsoleUtils::outputDataFileParams(_app);
764 :
765 54733 : if (_system_info_flags.isValueSet("output"))
766 10 : _console << ConsoleUtils::outputOutputInformation(_app);
767 :
768 54733 : if (!_app.getParam<bool>("use_legacy_initial_residual_evaluation_behavior"))
769 108375 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
770 53668 : if (_problem_ptr->getNonlinearSystemBase(i).usePreSMOResidual())
771 : {
772 26 : _console << ConsoleUtils::outputPreSMOResidualInformation();
773 26 : break;
774 : }
775 :
776 : // Output the legacy flags, these cannot be turned off so they become annoying to people.
777 54733 : _console << ConsoleUtils::outputLegacyInformation(_app);
778 :
779 54733 : _console << std::flush;
780 : }
781 :
782 : void
783 6898 : Console::meshChanged()
784 : {
785 6898 : if (_print_mesh_changed_info)
786 : {
787 363 : _console << ConsoleUtils::outputMeshInformation(*_problem_ptr, /*verbose = */ false);
788 :
789 363 : std::string output;
790 726 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
791 : {
792 363 : output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr, i);
793 363 : if (!output.empty())
794 : {
795 363 : _console << "Nonlinear System";
796 363 : if (_problem_ptr->numNonlinearSystems() > 1)
797 0 : _console << " [" + _problem_ptr->getNonlinearSystemNames()[i] + "]";
798 363 : _console << ":\n" << output;
799 : }
800 : }
801 :
802 363 : for (const auto i : make_range(_problem_ptr->numLinearSystems()))
803 : {
804 0 : output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr,
805 0 : _problem_ptr->numNonlinearSystems() + i);
806 0 : if (!output.empty())
807 0 : _console << "Linear System" +
808 0 : (_problem_ptr->numLinearSystems() > 1 ? (" " + std::to_string(i)) : "") +
809 0 : ":\n"
810 0 : << output;
811 : }
812 :
813 363 : output = ConsoleUtils::outputAuxiliarySystemInformation(*_problem_ptr);
814 363 : if (!output.empty())
815 240 : _console << "Auxiliary System:\n" << output;
816 :
817 363 : _console << std::flush;
818 363 : }
819 6898 : }
820 :
821 : void
822 6084266 : Console::write(std::string message, bool indent /*=true*/)
823 : {
824 : // Do nothing if the message is empty, writing empty strings messes with multiapp indenting
825 6084266 : if (message.empty())
826 1131117 : return;
827 :
828 : // Write the message to file
829 4953149 : if (_write_file)
830 23959 : _file_output_stream << message;
831 :
832 : // The empty case gets the right behavior, even though the boolean is technically wrong
833 4953149 : bool this_message_ends_in_newline = message.empty() ? true : (message.back() == '\n');
834 4953149 : bool this_message_starts_with_newline = message.empty() ? true : (message.front() == '\n');
835 :
836 : // Apply MultiApp indenting
837 9905525 : if ((this_message_starts_with_newline || _last_message_ended_in_newline) && indent &&
838 4952376 : _app.multiAppLevel() > 0)
839 1100159 : MooseUtils::indentMessage(_app.name(), message);
840 :
841 : // Write message to the screen
842 4953149 : if (_write_screen)
843 4953149 : Moose::out << message;
844 :
845 4953149 : _last_message_ended_in_newline = this_message_ends_in_newline;
846 : }
847 :
848 : void
849 6026221 : Console::mooseConsole(const std::string & message)
850 : {
851 : // Write the messages
852 6026221 : write(message);
853 :
854 : // Flush the stream to the screen
855 6026221 : Moose::out << std::flush;
856 6026221 : }
857 :
858 : void
859 0 : Console::petscSetupOutput()
860 : {
861 0 : char c[] = {
862 : 32, 47, 94, 92, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
863 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
864 : 32, 32, 32, 32, 32, 32, 32, 47, 94, 92, 13, 10, 124, 32, 32, 32, 92, 95, 47,
865 : 94, 92, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
866 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 94, 92, 95, 47,
867 : 32, 32, 32, 124, 13, 10, 124, 32, 32, 32, 32, 32, 32, 32, 32, 92, 95, 47, 94,
868 : 92, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
869 : 32, 32, 32, 47, 94, 92, 95, 47, 32, 32, 32, 32, 32, 32, 32, 32, 124, 13, 10,
870 : 32, 92, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 92, 95, 47, 94, 92,
871 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 94, 92, 95, 47, 32, 32, 32,
872 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 13, 10, 32, 32, 92, 95, 95, 32, 32,
873 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 92, 95, 95, 95, 45, 45, 45,
874 : 95, 95, 95, 47, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95,
875 : 95, 47, 13, 10, 32, 32, 32, 32, 32, 45, 45, 45, 95, 95, 95, 32, 32, 32, 32,
876 : 32, 32, 32, 32, 32, 47, 32, 32, 32, 32, 32, 32, 32, 92, 32, 32, 32, 32, 32,
877 : 32, 32, 32, 32, 95, 95, 95, 45, 45, 45, 13, 10, 32, 32, 32, 32, 32, 32, 32,
878 : 32, 32, 32, 32, 45, 45, 45, 95, 95, 95, 32, 32, 124, 32, 32, 32, 32, 32, 32,
879 : 32, 32, 32, 124, 32, 32, 95, 95, 95, 45, 45, 45, 13, 10, 32, 32, 32, 32, 32,
880 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 124, 32, 32, 95, 32,
881 : 32, 32, 95, 32, 32, 124, 45, 45, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
882 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 124, 111, 124, 32, 124, 111, 124,
883 : 32, 32, 124, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
884 : 32, 32, 32, 47, 32, 32, 32, 32, 45, 32, 32, 32, 45, 32, 32, 32, 32, 92, 13,
885 : 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32,
886 : 32, 32, 32, 32, 32, 95, 95, 95, 32, 32, 32, 32, 32, 32, 124, 13, 10, 32, 32,
887 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 32, 32, 32,
888 : 45, 45, 32, 32, 32, 45, 45, 32, 32, 32, 32, 32, 92, 13, 10, 32, 32, 32, 32,
889 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 32, 32, 32, 32, 32, 32, 32,
890 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 92, 13, 10, 32, 32, 32, 32,
891 : 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 32, 32, 32, 32, 47, 92, 32,
892 : 32, 32, 32, 32, 47, 92, 32, 32, 32, 32, 32, 32, 32, 124, 13, 10, 32, 32, 32,
893 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 92, 32, 32, 92, 32, 32, 32, 32, 32,
894 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 47, 13, 10, 32, 32, 32,
895 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 92, 32, 32, 92, 95, 95, 95, 95,
896 : 95, 95, 95, 95, 95, 95, 95, 95, 32, 47, 32, 32, 47, 92, 13, 10, 32, 32, 32,
897 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 92, 32, 32, 32, 32, 32, 32,
898 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 92, 13, 10, 32, 32,
899 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 32, 32, 92, 32, 32, 32, 32,
900 : 32, 39, 95, 95, 95, 39, 32, 32, 32, 32, 32, 47, 32, 32, 32, 32, 92, 13, 10,
901 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 92, 32, 32, 32, 32, 32, 92, 32,
902 : 45, 45, 95, 95, 45, 45, 45, 95, 95, 45, 45, 32, 47, 32, 32, 32, 32, 32, 47,
903 : 92, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 92, 47, 32, 32,
904 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
905 : 92, 47, 32, 32, 92, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 32,
906 : 47, 32, 32, 32, 32, 32, 32, 32, 77, 46, 79, 46, 79, 46, 83, 46, 69, 32, 32,
907 : 32, 32, 32, 32, 32, 92, 32, 32, 32, 92, 13, 10, 32, 32, 32, 32, 32, 32, 32,
908 : 47, 32, 32, 32, 124, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
909 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 92, 13, 10, 32,
910 : 32, 32, 32, 32, 32, 124, 32, 32, 32, 32, 124, 45, 45, 45, 45, 45, 45, 45, 45,
911 : 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 124, 32,
912 : 32, 32, 32, 124, 13, 10, 32, 32, 32, 32, 32, 32, 32, 92, 32, 32, 32, 32, 92,
913 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
914 : 32, 32, 32, 32, 47, 32, 32, 32, 32, 47, 13, 10, 32, 32, 32, 32, 32, 32, 32,
915 : 32, 32, 92, 92, 32, 92, 95, 92, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
916 : 32, 32, 32, 32, 32, 32, 32, 32, 47, 95, 47, 32, 47, 47, 13, 10, 32, 32, 32,
917 : 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 32, 32, 92, 32, 32, 32, 32, 32, 32,
918 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 47, 32, 32, 45, 45, 13, 10, 32,
919 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 45,
920 : 45, 45, 95, 95, 95, 95, 95, 45, 45, 45, 32, 32, 124, 13, 10, 32, 32, 32, 32,
921 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 32, 32, 124,
922 : 32, 32, 32, 124, 32, 32, 32, 32, 32, 124, 13, 10, 32, 32, 32, 32, 32, 32, 32,
923 : 32, 32, 32, 32, 32, 32, 32, 32, 32, 124, 32, 32, 32, 32, 32, 124, 32, 32, 32,
924 : 124, 32, 32, 32, 32, 32, 124, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
925 : 32, 32, 32, 32, 32, 47, 32, 86, 32, 32, 32, 32, 32, 92, 32, 47, 32, 32, 32,
926 : 32, 86, 32, 32, 92, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
927 : 32, 32, 32, 124, 95, 124, 95, 95, 95, 95, 95, 124, 32, 124, 95, 95, 95, 95, 124,
928 : 95, 95, 124};
929 0 : Moose::out << std::string(c) << std::endl << std::endl;
930 0 : }
|