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 132423 : Console::validParams()
33 : {
34 : // Enum for selecting the fit mode for the table when printed to the screen
35 132423 : MooseEnum pps_fit_mode(FormattedTable::getWidthModes());
36 :
37 : // Get the parameters from the base class
38 132423 : InputParameters params = TableOutput::validParams();
39 264846 : params.addClassDescription("Object for screen output.");
40 :
41 264846 : params += TableOutput::enableOutputTypes("system_information scalar postprocessor input");
42 :
43 264846 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_on");
44 264846 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_postprocessors_on");
45 264846 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_scalars_on");
46 :
47 : // Screen and file output toggles
48 529692 : params.addParam<bool>("output_screen", true, "Output to the screen");
49 397269 : params.addParam<bool>("output_file",
50 264846 : 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 397269 : params.addParam<bool>(
57 264846 : "show_multiapp_name", false, "Indent multiapp output using the multiapp name");
58 :
59 : // Table fitting options
60 397269 : params.addParam<unsigned int>("max_rows",
61 264846 : 15,
62 : "The maximum number of postprocessor/scalar values "
63 : "displayed on screen during a timestep (set to 0 "
64 : "for unlimited)");
65 529692 : 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 529692 : params.addParam<bool>("verbose", false, "Print detailed diagnostics on timestep calculation");
74 :
75 : // Basic table output controls
76 397269 : params.addParam<bool>(
77 264846 : "scientific_time", false, "Control the printing of time and dt in scientific notation");
78 529692 : params.addParam<unsigned int>(
79 : "time_precision",
80 : "The number of significant digits that are printed on time related outputs");
81 529692 : MooseEnum time_format("plain=0 second=1 minute=2 hour=3 day=4 dtime=5", "plain");
82 529692 : 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 794538 : params.addDeprecatedParam<bool>("perf_log",
89 264846 : false,
90 : "If true, all performance logs will be printed. The "
91 : "individual log settings will override this option.",
92 : "Use PerfGraphOutput");
93 662115 : params.addDeprecatedParam<unsigned int>(
94 : "perf_log_interval",
95 264846 : 0,
96 : "If set, the performance log will be printed every n time steps",
97 : "Use PerfGraphOutput instead");
98 529692 : params.addParam<bool>("solve_log", "Toggles the printing of the 'Moose Test Performance' log");
99 794538 : params.addDeprecatedParam<bool>(
100 : "perf_header",
101 : "Print the libMesh performance log header (requires that 'perf_log = true')",
102 : "Use PerfGraphOutput instead");
103 :
104 397269 : params.addParam<bool>(
105 : "libmesh_log",
106 264846 : 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 397269 : params.addParam<bool>("print_mesh_changed_info",
111 264846 : false,
112 : "When true, each time the mesh is changed the mesh information is printed");
113 :
114 : // Toggle for printing variable norms
115 397269 : params.addParam<bool>("outlier_variable_norms",
116 264846 : true,
117 : "If true, outlier variable norms will be printed after each solve");
118 264846 : params.addParam<bool>(
119 264846 : "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 132423 : std::vector<Real> multiplier;
123 132423 : multiplier.push_back(0.8);
124 132423 : multiplier.push_back(2);
125 529692 : 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 264846 : "framework mesh aux nonlinear linear execution");
136 529692 : 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 529692 : params.addParamNamesToGroup("verbose show_multiapp_name system_info", "Advanced");
144 :
145 : // Performance log group
146 529692 : params.addParamNamesToGroup("perf_log solve_log perf_header libmesh_log", "Perf Log");
147 :
148 : // Variable norms group
149 529692 : params.addParamNamesToGroup("outlier_variable_norms all_variable_norms outlier_multiplier",
150 : "Variable and Residual Norms");
151 :
152 : // Number formatting
153 529692 : params.addParamNamesToGroup("scientific_time time_precision time_format",
154 : "Time output formatting");
155 :
156 : // Table of postprocessor output formatting
157 529692 : 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 132423 : 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 264846 : params.set<ExecFlagEnum>("execute_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
171 : EXEC_TIMESTEP_BEGIN,
172 : EXEC_LINEAR,
173 : EXEC_NONLINEAR,
174 : EXEC_FAILED,
175 1059384 : EXEC_TIMESTEP_END};
176 :
177 : // By default postprocessors and scalar are only output at the end of a timestep
178 264846 : params.set<ExecFlagEnum>("execute_postprocessors_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
179 529692 : EXEC_TIMESTEP_END};
180 264846 : params.set<ExecFlagEnum>("execute_vector_postprocessors_on",
181 529692 : /*quiet_mode=*/true) = {EXEC_INITIAL, EXEC_TIMESTEP_END};
182 264846 : params.set<ExecFlagEnum>("execute_scalars_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
183 529692 : EXEC_TIMESTEP_END};
184 264846 : params.set<ExecFlagEnum>("execute_reporters_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
185 529692 : EXEC_TIMESTEP_END};
186 264846 : return params;
187 794538 : }
188 :
189 60372 : Console::Console(const InputParameters & parameters)
190 : : TableOutput(parameters),
191 60372 : _max_rows(getParam<unsigned int>("max_rows")),
192 120744 : _fit_mode(getParam<MooseEnum>("fit_mode")),
193 120744 : _scientific_time(getParam<bool>("scientific_time")),
194 120744 : _write_file(getParam<bool>("output_file")),
195 120744 : _write_screen(getParam<bool>("output_screen")),
196 120744 : _verbose(getParam<bool>("verbose")),
197 120744 : _perf_log(getParam<bool>("perf_log")),
198 120744 : _perf_log_interval(getParam<unsigned int>("perf_log_interval")),
199 120764 : _solve_log(isParamValid("solve_log") ? getParam<bool>("solve_log") : _perf_log),
200 120744 : _libmesh_log(getParam<bool>("libmesh_log")),
201 120744 : _perf_header(isParamValid("perf_header") ? getParam<bool>("perf_header") : _perf_log),
202 120744 : _all_variable_norms(getParam<bool>("all_variable_norms")),
203 120744 : _outlier_variable_norms(getParam<bool>("outlier_variable_norms")),
204 120744 : _outlier_multiplier(getParam<std::vector<Real>>("outlier_multiplier")),
205 120852 : _precision(isParamValid("time_precision") ? getParam<unsigned int>("time_precision") : 0),
206 120744 : _time_format(getParam<MooseEnum>("time_format").getEnum<TimeFormatEnum>()),
207 120744 : _write_all_procs_to_files(_app.getParam<bool>("keep_cout")),
208 60372 : _console_buffer(_app.getOutputWarehouse().consoleBuffer()),
209 60372 : _old_linear_norm(std::numeric_limits<Real>::max()),
210 60372 : _old_nonlinear_norm(std::numeric_limits<Real>::max()),
211 120744 : _print_mesh_changed_info(getParam<bool>("print_mesh_changed_info")),
212 120744 : _system_info_flags(getParam<MultiMooseEnum>("system_info")),
213 60372 : _allow_changing_sysinfo_flag(true),
214 120744 : _last_message_ended_in_newline(true)
215 : {
216 : // Apply the special common console flags (print_...)
217 60372 : ActionWarehouse & awh = _app.actionWarehouse();
218 60372 : const auto actions = awh.getActions<CommonOutputAction>();
219 : mooseAssert(actions.size() <= 1, "Should not be more than one CommonOutputAction");
220 60372 : const Action * common = actions.empty() ? nullptr : *actions.begin();
221 :
222 120744 : if (!parameters.isParamSetByUser("execute_on"))
223 : {
224 : // Honor the 'print_linear_residuals' option, only if 'linear' has not been set in 'execute_on'
225 : // by the user
226 152913 : if (common && common->getParam<bool>("print_linear_residuals"))
227 151074 : _execute_on.setAdditionalValue("linear");
228 : else
229 1839 : _execute_on.eraseSetValue("linear");
230 152913 : if (common && common->getParam<bool>("print_nonlinear_residuals"))
231 152589 : _execute_on.setAdditionalValue("nonlinear");
232 : else
233 324 : _execute_on.eraseSetValue("nonlinear");
234 : }
235 :
236 301860 : if (!_pars.isParamSetByUser("perf_log") && common && common->getParam<bool>("print_perf_log"))
237 : {
238 0 : _perf_log = true;
239 0 : _solve_log = true;
240 : }
241 :
242 : // If --show-outputs is used, enable it
243 181116 : if (_app.getParam<bool>("show_outputs"))
244 27 : _system_info_flags.setAdditionalValue("output");
245 60372 : }
246 :
247 58133 : Console::~Console()
248 : {
249 : // Write the libMesh log
250 58133 : if (_libmesh_log)
251 58133 : write(libMesh::perflog.get_perf_info(), false);
252 :
253 : // Write the file output stream
254 58133 : writeStreamToFile();
255 :
256 : // Disable logging so that the destructor in libMesh doesn't print
257 58133 : libMesh::perflog.disable_logging();
258 58133 : }
259 :
260 : void
261 59375 : Console::initialSetup()
262 : {
263 : // Only allow the main app to change the perf_log settings.
264 59375 : if (_app.name() == "main")
265 : {
266 : // Disable libMesh log
267 47587 : if (!_libmesh_log)
268 0 : libMesh::perflog.disable_logging();
269 : }
270 :
271 : // system info flag can be changed only before console initial setup
272 59375 : _allow_changing_sysinfo_flag = false;
273 :
274 : // If execute_on = 'initial' perform the output
275 178125 : if (wantOutput("system_information", EXEC_INITIAL))
276 59375 : outputSystemInformation();
277 :
278 : // Call the base class method
279 59375 : TableOutput::initialSetup();
280 :
281 : // If file output is desired, wipe out the existing file if not recovering
282 59363 : if (!_app.isRecovering())
283 55110 : writeStreamToFile(false);
284 :
285 : // Enable verbose output if Executioner has it enabled
286 296815 : if (_app.getExecutioner()->isParamValid("verbose") &&
287 237452 : _app.getExecutioner()->getParam<bool>("verbose"))
288 998 : _verbose = true;
289 :
290 : // If the user explicitly set execute_on but did not set a type-specific flag,
291 : // replace that type's schedule with the user's execute_on so the two are consistent.
292 178089 : if (_pars.isParamSetByUser("execute_on"))
293 : {
294 27804 : if (!_pars.isParamSetByUser("execute_postprocessors_on"))
295 27750 : _advanced_execute_on["postprocessors"] = _execute_on;
296 27804 : if (!_pars.isParamSetByUser("execute_scalars_on"))
297 27768 : _advanced_execute_on["scalars"] = _execute_on;
298 27804 : if (!_pars.isParamSetByUser("execute_vector_postprocessors_on"))
299 27804 : _advanced_execute_on["vector_postprocessors"] = _execute_on;
300 27804 : if (!_pars.isParamSetByUser("execute_reporters_on"))
301 27804 : _advanced_execute_on["reporters"] = _execute_on;
302 : }
303 59363 : }
304 :
305 : std::string
306 78804 : Console::filename()
307 : {
308 78804 : std::string file_name;
309 78804 : if (_write_all_procs_to_files)
310 : {
311 172 : std::string pid = std::to_string(processor_id());
312 172 : file_name = _file_base + "_" + pid + ".txt";
313 172 : }
314 : else
315 78632 : file_name = _file_base + ".txt";
316 78804 : return file_name;
317 0 : }
318 :
319 : void
320 265154 : Console::timestepSetup()
321 : {
322 265154 : writeTimestepInformation(/*output_dt = */ true);
323 265154 : }
324 :
325 : void
326 3159252 : Console::output()
327 : {
328 3159252 : const auto & type = _current_execute_flag;
329 :
330 : // Return if the current output is not on the desired interval
331 3159252 : 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 9477756 : if (wantOutput("system_information", type) && !(type == EXEC_INITIAL))
338 0 : outputSystemInformation();
339 :
340 : // Write the input
341 9477756 : if (wantOutput("input", type))
342 27 : 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 3159252 : if (type == EXEC_INITIAL && _execute_on.isValueSet(EXEC_INITIAL))
348 47772 : writeTimestepInformation(/*output_dt = */ false);
349 3111480 : else if (type == EXEC_FINAL && _execute_on.isValueSet(EXEC_FINAL))
350 : {
351 3041 : if (wantOutput("postprocessors", type) || wantOutput("scalars", type))
352 262 : _console << "\nFINAL:\n";
353 : }
354 :
355 : // Print Non-linear Residual (control with "execute_on")
356 3159252 : if (type == EXEC_NONLINEAR && _execute_on.isValueSet(EXEC_NONLINEAR))
357 : {
358 650425 : if (_nonlinear_iter == 0)
359 249873 : _old_nonlinear_norm = std::numeric_limits<Real>::max();
360 :
361 650425 : _console << std::right << std::setw(2) << _nonlinear_iter
362 650425 : << " Nonlinear |R| = " << outputNorm(_old_nonlinear_norm, _norm) << '\n';
363 :
364 650425 : _old_nonlinear_norm = _norm;
365 : }
366 :
367 : // Print Linear Residual (control with "execute_on")
368 2508827 : else if (type == EXEC_LINEAR && _execute_on.isValueSet(EXEC_LINEAR))
369 : {
370 1954505 : if (_linear_iter == 0)
371 401796 : _old_linear_norm = std::numeric_limits<Real>::max();
372 :
373 1954505 : _console << std::right << std::setw(7) << _linear_iter
374 1954505 : << " Linear |R| = " << outputNorm(_old_linear_norm, _norm) << '\n';
375 :
376 1954505 : _old_linear_norm = _norm;
377 : }
378 :
379 : // Write variable norms
380 554322 : else if (type == EXEC_TIMESTEP_END)
381 216323 : writeVariableNorms();
382 :
383 9477756 : if (wantOutput("postprocessors", type))
384 105001 : outputPostprocessors();
385 :
386 9477747 : if (wantOutput("scalars", type))
387 13874 : outputScalarVariables();
388 :
389 9477747 : if (wantOutput("reporters", type))
390 5845 : outputReporters();
391 :
392 : // Write the file
393 3159249 : writeStreamToFile();
394 :
395 3159249 : _console << std::flush;
396 : }
397 :
398 : void
399 3272492 : Console::writeStreamToFile(bool append)
400 : {
401 3272492 : if (!_write_file || (!_write_all_procs_to_files && processor_id() > 0))
402 3253066 : return;
403 :
404 : // Create the stream
405 19426 : std::ofstream output;
406 :
407 : // Open the file
408 19426 : if (append)
409 19257 : 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 19426 : if (output.fail())
414 0 : mooseError("Unable to open file ", filename());
415 :
416 19426 : std::string s = _file_output_stream.str();
417 : // Write contents of file output stream and close the file
418 19426 : output << MooseUtils::removeColor(s);
419 19426 : output.close();
420 :
421 : // Clear the file output stream
422 38852 : _file_output_stream.str("");
423 19426 : }
424 :
425 : void
426 312926 : Console::writeTimestepInformation(bool output_dt)
427 : {
428 : // Stream to build the time step information
429 312926 : std::stringstream oss;
430 :
431 : // Write timestep data for transient executioners
432 312926 : if (_transient)
433 : {
434 : // Write time step and time information
435 258937 : oss << "\nTime Step " << timeStep();
436 258937 : unsigned int time_step_digits = oss.str().length() - 11;
437 :
438 : // Print the time
439 258937 : oss << ", time = " << formatTime(getOutputTime());
440 :
441 258937 : if (output_dt)
442 : {
443 235887 : if (!_verbose)
444 : // Show the time delta information
445 228560 : oss << ", dt = " << std::left << formatTime(dt());
446 :
447 : // Show old time information, if desired on separate lines
448 : else
449 : {
450 7327 : unsigned int fillsize = 19 + time_step_digits;
451 7327 : oss << '\n'
452 7327 : << std::right << std::setw(fillsize) << std::setfill(' ') << "old time = " << std::left
453 7327 : << formatTime(timeOld()) << '\n';
454 :
455 : // Show the time delta information
456 7327 : oss << std::right << std::setw(fillsize) << std::setfill(' ') << "dt = " << std::left
457 7327 : << formatTime(dt()) << '\n';
458 :
459 : // Show the old time delta information, if desired
460 7327 : if (_verbose)
461 7327 : oss << std::right << std::setw(fillsize) << std::setfill(' ')
462 7327 : << "old dt = " << formatTime(_dt_old) << '\n';
463 : }
464 : }
465 :
466 258937 : oss << '\n';
467 :
468 : // Output to the screen
469 258937 : _console << oss.str() << std::flush;
470 : }
471 312926 : }
472 :
473 : std::string
474 509478 : Console::formatTime(const Real t) const
475 : {
476 509478 : std::ostringstream oss;
477 509478 : if (_time_format != TimeFormatEnum::DTIME)
478 : {
479 507354 : if (_precision > 0)
480 7092 : oss << std::setw(_precision) << std::setprecision(_precision) << std::setfill('0')
481 7092 : << std::showpoint;
482 507354 : if (_scientific_time)
483 0 : oss << std::scientific;
484 :
485 507354 : if (_time_format == TimeFormatEnum::PLAIN)
486 500982 : oss << t;
487 6372 : else if (_time_format == TimeFormatEnum::SECOND)
488 0 : oss << t << "s";
489 6372 : else if (_time_format == TimeFormatEnum::MINUTE)
490 2124 : oss << t / 60 << "m";
491 4248 : else if (_time_format == TimeFormatEnum::HOUR)
492 2124 : oss << t / 3600 << "h";
493 2124 : else if (_time_format == TimeFormatEnum::DAY)
494 2124 : oss << t / 86400 << "d";
495 : }
496 : else
497 : {
498 2124 : Real abst = t;
499 2124 : if (t < 0)
500 : {
501 63 : oss << "-";
502 63 : abst = -t;
503 : }
504 2124 : int days = std::floor(abst / 24 / 3600);
505 2124 : int hours = std::floor(abst / 3600 - days * 24);
506 2124 : int mins = std::floor(abst / 60 - days * 24 * 60 - hours * 60);
507 2124 : Real second = abst - days * 24 * 3600 - hours * 3600 - mins * 60;
508 :
509 2124 : if (days != 0)
510 27 : oss << days << "d";
511 2124 : if (hours != 0 || mins != 0 || second != 0)
512 : {
513 2124 : if (days != 0)
514 27 : oss << " ";
515 2124 : oss << std::setfill('0') << std::setw(2) << hours << ":" << std::setfill('0') << std::setw(2)
516 2124 : << mins << ":";
517 :
518 2124 : if (second < 10)
519 792 : oss << "0";
520 2124 : if (_precision > 0)
521 2124 : oss << std::setw(_precision) << std::setprecision(_precision) << std::setfill('0')
522 2124 : << std::showpoint;
523 2124 : if (_scientific_time)
524 0 : oss << std::scientific;
525 2124 : oss << second;
526 : }
527 0 : else if (days == 0)
528 0 : oss << "0s";
529 : }
530 1018956 : return oss.str();
531 509478 : }
532 :
533 : void
534 216323 : Console::writeVariableNorms()
535 : {
536 : // If all_variable_norms is true, then so should outlier printing
537 216323 : if (_all_variable_norms)
538 14 : _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 216323 : if ((_all_variable_norms == false) && (_outlier_variable_norms == false))
543 609 : 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 216290 : if (dynamic_cast<EigenProblem *>(_problem_ptr) != nullptr)
548 576 : return;
549 :
550 : // Flag set when header prints
551 215714 : bool header = false;
552 :
553 : // String stream for variable norm information
554 215714 : std::ostringstream oss;
555 :
556 433669 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
557 : {
558 : // Get a references to the NonlinearSystem and libMesh system
559 217955 : NonlinearSystemBase & nl = _problem_ptr->getNonlinearSystemBase(i);
560 217955 : System & sys = nl.system();
561 :
562 : // Storage for norm outputs
563 217955 : std::map<std::string, Real> other;
564 217955 : std::map<std::string, Real> outlier;
565 :
566 : // Average norm
567 217955 : unsigned int n_vars = sys.n_vars();
568 217955 : Real avg_norm = (nl.nonlinearNorm() * nl.nonlinearNorm()) / n_vars;
569 :
570 : // Compute the norms for each of the variables
571 482973 : for (unsigned int i = 0; i < n_vars; i++)
572 : {
573 : // Compute the norm and extract the variable name
574 265018 : Real var_norm = sys.calculate_norm(nl.RHS(), i, DISCRETE_L2);
575 265018 : var_norm *= var_norm; // use the norm squared
576 265018 : 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 265018 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[1] * avg_norm))
580 : {
581 : // Print the header
582 13683 : if (!header)
583 : {
584 13217 : oss << "\nOutlier Variable Residual Norms:\n";
585 13217 : header = true;
586 : }
587 :
588 : // Set the color, RED if the variable norm is 0.8 (default) of the total norm
589 13683 : std::string color = COLOR_YELLOW;
590 13683 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[0] * avg_norm * n_vars))
591 12914 : color = COLOR_RED;
592 :
593 : // Display the residual
594 13683 : oss << " " << var_name << ": " << std::scientific << color << std::sqrt(var_norm)
595 13683 : << COLOR_DEFAULT << '\n';
596 13683 : }
597 :
598 : // GREEN
599 251335 : else if (_all_variable_norms)
600 : {
601 : // Print the header if it doesn't already exist
602 28 : if (!header)
603 : {
604 14 : oss << "\nVariable Residual Norms:\n";
605 14 : header = true;
606 : }
607 28 : oss << " " << var_name << ": " << std::scientific << COLOR_GREEN << std::sqrt(var_norm)
608 28 : << COLOR_DEFAULT << '\n';
609 : }
610 265018 : }
611 217955 : }
612 :
613 : // Update the output streams
614 215714 : _console << oss.str() << std::flush;
615 215714 : }
616 :
617 : // Quick helper to output the norm in color
618 : std::string
619 2950740 : Console::outputNorm(const Real & old_norm, const Real & norm, const unsigned int precision)
620 : {
621 2950740 : std::string color = COLOR_GREEN;
622 :
623 : // Red if the residual went up... or if the norm is nan
624 2950740 : if (norm != norm || norm > old_norm)
625 57770 : color = COLOR_RED;
626 : // Yellow if change is less than 5%
627 2892970 : else if ((old_norm - norm) / old_norm <= 0.05)
628 76975 : color = COLOR_YELLOW;
629 :
630 2950740 : std::stringstream oss;
631 2950740 : oss << std::scientific << std::setprecision(precision) << color << norm << COLOR_DEFAULT;
632 :
633 5901480 : return oss.str();
634 2950740 : }
635 :
636 : void
637 27 : Console::outputInput()
638 : {
639 27 : if (!_write_screen && !_write_file)
640 0 : return;
641 :
642 27 : std::ostringstream oss;
643 54 : for (const auto & filename : _app.getInputFileNames())
644 27 : oss << "--- " << filename << "\n";
645 27 : _app.actionWarehouse().printInputFile(oss);
646 27 : _console << oss.str() << std::endl;
647 27 : }
648 :
649 : void
650 105001 : Console::outputPostprocessors()
651 : {
652 105001 : TableOutput::outputPostprocessors();
653 :
654 105001 : if (!_postprocessor_table.empty())
655 : {
656 105001 : std::stringstream oss;
657 105001 : oss << "\nPostprocessor Values:\n";
658 105001 : _postprocessor_table.sortColumns();
659 105001 : _postprocessor_table.printTable(oss, _max_rows, _fit_mode);
660 104998 : _console << oss.str() << std::endl;
661 104998 : }
662 104998 : }
663 :
664 : void
665 5845 : Console::outputReporters()
666 : {
667 5845 : TableOutput::outputReporters();
668 :
669 5845 : if (!_reporter_table.empty())
670 : {
671 2252 : std::stringstream oss;
672 2252 : oss << "\nReporter Values:\n";
673 2252 : _reporter_table.sortColumns();
674 2252 : _reporter_table.printTable(oss, _max_rows, _fit_mode);
675 2252 : _console << oss.str() << '\n';
676 2252 : }
677 5845 : }
678 :
679 : void
680 13874 : Console::outputScalarVariables()
681 : {
682 13874 : TableOutput::outputScalarVariables();
683 :
684 13874 : if (!_scalar_table.empty())
685 : {
686 13874 : std::stringstream oss;
687 13874 : oss << "\nScalar Variable Values:\n";
688 13874 : if (processor_id() == 0)
689 : {
690 11895 : _scalar_table.sortColumns();
691 11895 : _scalar_table.printTable(oss, _max_rows, _fit_mode);
692 : }
693 13874 : _console << oss.str() << std::endl;
694 13874 : }
695 13874 : }
696 :
697 : void
698 59375 : 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 59375 : if (_app.multiAppNumber() > 0)
703 4643 : return;
704 :
705 164196 : if (_system_info_flags.isValueSet("framework"))
706 54720 : _console << ConsoleUtils::outputFrameworkInformation(_app);
707 :
708 164196 : if (_system_info_flags.isValueSet("mesh"))
709 54720 : _console << ConsoleUtils::outputMeshInformation(*_problem_ptr);
710 :
711 164196 : if (_system_info_flags.isValueSet("nonlinear"))
712 : {
713 108655 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
714 : {
715 53935 : std::string output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr, i);
716 53935 : if (!output.empty())
717 : {
718 42832 : _console << "Nonlinear System";
719 42832 : if (_problem_ptr->numNonlinearSystems() > 1)
720 390 : _console << " [" + _problem_ptr->getNonlinearSystemNames()[i] + "]";
721 42832 : _console << ":\n" << output;
722 : }
723 53935 : }
724 : }
725 :
726 164196 : if (_system_info_flags.isValueSet("linear"))
727 55673 : for (const auto i : make_range(_problem_ptr->numLinearSystems()))
728 : {
729 : std::string output = ConsoleUtils::outputSolverSystemInformation(
730 1032 : *_problem_ptr, _problem_ptr->numNonlinearSystems() + i);
731 1032 : if (!output.empty())
732 2064 : _console << "Linear System" +
733 6148 : (_problem_ptr->numLinearSystems() > 1 ? (" " + std::to_string(i)) : "") +
734 2064 : ":\n"
735 1032 : << output;
736 1032 : }
737 :
738 164196 : if (_system_info_flags.isValueSet("aux"))
739 : {
740 54720 : std::string output = ConsoleUtils::outputAuxiliarySystemInformation(*_problem_ptr);
741 54720 : if (!output.empty())
742 22761 : _console << "Auxiliary System:\n" << output;
743 54720 : }
744 :
745 164196 : if (_system_info_flags.isValueSet("relationship"))
746 : {
747 91 : std::string output = ConsoleUtils::outputRelationshipManagerInformation(_app);
748 91 : if (!output.empty())
749 91 : _console << "Relationship Managers:\n" << output;
750 91 : }
751 :
752 164196 : if (_system_info_flags.isValueSet("execution"))
753 54720 : _console << ConsoleUtils::outputExecutionInformation(_app, *_problem_ptr);
754 :
755 164196 : if (_app.getParam<bool>("show_data_paths"))
756 9 : _console << ConsoleUtils::outputDataFilePaths();
757 :
758 164196 : if (_app.getParam<bool>("show_data_params"))
759 9 : _console << ConsoleUtils::outputDataFileParams(_app);
760 :
761 164196 : if (_system_info_flags.isValueSet("output"))
762 9 : _console << ConsoleUtils::outputOutputInformation(_app);
763 :
764 164196 : if (!_app.getParam<bool>("use_legacy_initial_residual_evaluation_behavior"))
765 108647 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
766 53943 : 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 54732 : _console << ConsoleUtils::outputLegacyInformation(_app);
774 :
775 54732 : _console << std::flush;
776 : }
777 :
778 : void
779 7068 : Console::meshChanged()
780 : {
781 7068 : if (_print_mesh_changed_info)
782 : {
783 325 : _console << ConsoleUtils::outputMeshInformation(*_problem_ptr, /*verbose = */ false);
784 :
785 325 : std::string output;
786 650 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
787 : {
788 325 : output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr, i);
789 325 : if (!output.empty())
790 : {
791 325 : _console << "Nonlinear System";
792 325 : if (_problem_ptr->numNonlinearSystems() > 1)
793 0 : _console << " [" + _problem_ptr->getNonlinearSystemNames()[i] + "]";
794 325 : _console << ":\n" << output;
795 : }
796 : }
797 :
798 325 : 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 325 : output = ConsoleUtils::outputAuxiliarySystemInformation(*_problem_ptr);
810 325 : if (!output.empty())
811 219 : _console << "Auxiliary System:\n" << output;
812 :
813 325 : _console << std::flush;
814 325 : }
815 7068 : }
816 :
817 : void
818 5125588 : 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 5125588 : if (message.empty())
822 1049088 : return;
823 :
824 : // Write the message to file
825 4076500 : if (_write_file)
826 20556 : _file_output_stream << message;
827 :
828 : // The empty case gets the right behavior, even though the boolean is technically wrong
829 4076500 : bool this_message_ends_in_newline = message.empty() ? true : (message.back() == '\n');
830 4076500 : bool this_message_starts_with_newline = message.empty() ? true : (message.front() == '\n');
831 :
832 : // Apply MultiApp indenting
833 8151267 : if ((this_message_starts_with_newline || _last_message_ended_in_newline) && indent &&
834 4074767 : _app.multiAppLevel() > 0)
835 1965792 : MooseUtils::indentMessage(_app.name(), message);
836 :
837 : // Write message to the screen
838 4076500 : if (_write_screen)
839 4076500 : Moose::out << message;
840 :
841 4076500 : _last_message_ended_in_newline = this_message_ends_in_newline;
842 : }
843 :
844 : void
845 5067455 : Console::mooseConsole(const std::string & message)
846 : {
847 : // Write the messages
848 5067455 : write(message);
849 :
850 : // Flush the stream to the screen
851 5067455 : Moose::out << std::flush;
852 5067455 : }
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 : }
|