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