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 158084 : Console::validParams()
33 : {
34 : // Enum for selecting the fit mode for the table when printed to the screen
35 158084 : MooseEnum pps_fit_mode(FormattedTable::getWidthModes());
36 :
37 : // Get the parameters from the base class
38 158084 : InputParameters params = TableOutput::validParams();
39 316168 : params.addClassDescription("Object for screen output.");
40 :
41 316168 : params += TableOutput::enableOutputTypes("system_information scalar postprocessor input");
42 :
43 316168 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_on");
44 316168 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_postprocessors_on");
45 316168 : addMultiAppFixedPointIterationEndExecFlag(params, "execute_scalars_on");
46 :
47 : // Screen and file output toggles
48 632336 : params.addParam<bool>("output_screen", true, "Output to the screen");
49 474252 : params.addParam<bool>("output_file",
50 316168 : 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 474252 : params.addParam<bool>(
57 316168 : "show_multiapp_name", false, "Indent multiapp output using the multiapp name");
58 :
59 : // Table fitting options
60 474252 : params.addParam<unsigned int>("max_rows",
61 316168 : 15,
62 : "The maximum number of postprocessor/scalar values "
63 : "displayed on screen during a timestep (set to 0 "
64 : "for unlimited)");
65 632336 : 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 632336 : params.addParam<bool>("verbose", false, "Print detailed diagnostics on timestep calculation");
74 :
75 : // Basic table output controls
76 474252 : params.addParam<bool>(
77 316168 : "scientific_time", false, "Control the printing of time and dt in scientific notation");
78 632336 : params.addParam<unsigned int>(
79 : "time_precision",
80 : "The number of significant digits that are printed on time related outputs");
81 632336 : MooseEnum time_format("plain=0 second=1 minute=2 hour=3 day=4 dtime=5", "plain");
82 632336 : 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 948504 : params.addDeprecatedParam<bool>("perf_log",
89 316168 : false,
90 : "If true, all performance logs will be printed. The "
91 : "individual log settings will override this option.",
92 : "Use PerfGraphOutput");
93 790420 : params.addDeprecatedParam<unsigned int>(
94 : "perf_log_interval",
95 316168 : 0,
96 : "If set, the performance log will be printed every n time steps",
97 : "Use PerfGraphOutput instead");
98 632336 : params.addParam<bool>("solve_log", "Toggles the printing of the 'Moose Test Performance' log");
99 948504 : params.addDeprecatedParam<bool>(
100 : "perf_header",
101 : "Print the libMesh performance log header (requires that 'perf_log = true')",
102 : "Use PerfGraphOutput instead");
103 :
104 474252 : params.addParam<bool>(
105 : "libmesh_log",
106 316168 : 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 474252 : params.addParam<bool>("print_mesh_changed_info",
111 316168 : false,
112 : "When true, each time the mesh is changed the mesh information is printed");
113 :
114 : // Toggle for printing variable norms
115 474252 : params.addParam<bool>("outlier_variable_norms",
116 316168 : true,
117 : "If true, outlier variable norms will be printed after each solve");
118 316168 : params.addParam<bool>(
119 316168 : "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 158084 : std::vector<Real> multiplier;
123 158084 : multiplier.push_back(0.8);
124 158084 : multiplier.push_back(2);
125 632336 : 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 316168 : "framework mesh aux nonlinear linear execution");
136 632336 : 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 632336 : params.addParamNamesToGroup("verbose show_multiapp_name system_info", "Advanced");
144 :
145 : // Performance log group
146 632336 : params.addParamNamesToGroup("perf_log solve_log perf_header libmesh_log", "Perf Log");
147 :
148 : // Variable norms group
149 632336 : params.addParamNamesToGroup("outlier_variable_norms all_variable_norms outlier_multiplier",
150 : "Variable and Residual Norms");
151 :
152 : // Number formatting
153 632336 : params.addParamNamesToGroup("scientific_time time_precision time_format",
154 : "Time output formatting");
155 :
156 : // Table of postprocessor output formatting
157 632336 : 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 158084 : 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 316168 : params.set<ExecFlagEnum>("execute_on", /*quiet_mode=*/true) = {
171 1106588 : 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 316168 : params.set<ExecFlagEnum>("execute_postprocessors_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
175 632336 : EXEC_TIMESTEP_END};
176 316168 : params.set<ExecFlagEnum>("execute_vector_postprocessors_on",
177 632336 : /*quiet_mode=*/true) = {EXEC_INITIAL, EXEC_TIMESTEP_END};
178 316168 : params.set<ExecFlagEnum>("execute_scalars_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
179 632336 : EXEC_TIMESTEP_END};
180 316168 : params.set<ExecFlagEnum>("execute_reporters_on", /*quiet_mode=*/true) = {EXEC_INITIAL,
181 632336 : EXEC_TIMESTEP_END};
182 316168 : return params;
183 948504 : }
184 :
185 61955 : Console::Console(const InputParameters & parameters)
186 : : TableOutput(parameters),
187 61955 : _max_rows(getParam<unsigned int>("max_rows")),
188 123910 : _fit_mode(getParam<MooseEnum>("fit_mode")),
189 123910 : _scientific_time(getParam<bool>("scientific_time")),
190 123910 : _write_file(getParam<bool>("output_file")),
191 123910 : _write_screen(getParam<bool>("output_screen")),
192 123910 : _verbose(getParam<bool>("verbose")),
193 123910 : _perf_log(getParam<bool>("perf_log")),
194 123910 : _perf_log_interval(getParam<unsigned int>("perf_log_interval")),
195 123932 : _solve_log(isParamValid("solve_log") ? getParam<bool>("solve_log") : _perf_log),
196 123910 : _libmesh_log(getParam<bool>("libmesh_log")),
197 123910 : _perf_header(isParamValid("perf_header") ? getParam<bool>("perf_header") : _perf_log),
198 123910 : _all_variable_norms(getParam<bool>("all_variable_norms")),
199 123910 : _outlier_variable_norms(getParam<bool>("outlier_variable_norms")),
200 123910 : _outlier_multiplier(getParam<std::vector<Real>>("outlier_multiplier")),
201 124030 : _precision(isParamValid("time_precision") ? getParam<unsigned int>("time_precision") : 0),
202 123910 : _time_format(getParam<MooseEnum>("time_format").getEnum<TimeFormatEnum>()),
203 123910 : _write_all_procs_to_files(_app.getParam<bool>("keep_cout")),
204 61955 : _console_buffer(_app.getOutputWarehouse().consoleBuffer()),
205 61955 : _old_linear_norm(std::numeric_limits<Real>::max()),
206 61955 : _old_nonlinear_norm(std::numeric_limits<Real>::max()),
207 123910 : _print_mesh_changed_info(getParam<bool>("print_mesh_changed_info")),
208 123910 : _system_info_flags(getParam<MultiMooseEnum>("system_info")),
209 61955 : _allow_changing_sysinfo_flag(true),
210 123910 : _last_message_ended_in_newline(true)
211 : {
212 : // Apply the special common console flags (print_...)
213 61955 : ActionWarehouse & awh = _app.actionWarehouse();
214 61955 : const auto actions = awh.getActions<CommonOutputAction>();
215 : mooseAssert(actions.size() <= 1, "Should not be more than one CommonOutputAction");
216 61955 : const Action * common = actions.empty() ? nullptr : *actions.begin();
217 :
218 123910 : 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 185337 : if (common && common->getParam<bool>("print_linear_residuals"))
223 182940 : _execute_on.setAdditionalValue("linear");
224 : else
225 2397 : _execute_on.eraseSetValue("linear");
226 185337 : if (common && common->getParam<bool>("print_nonlinear_residuals"))
227 184983 : _execute_on.setAdditionalValue("nonlinear");
228 : else
229 354 : _execute_on.eraseSetValue("nonlinear");
230 : }
231 :
232 309775 : 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 61955 : if (common)
241 : {
242 123910 : const ExecFlagEnum & common_execute_on = common->getParam<ExecFlagEnum>("execute_on");
243 177351 : for (auto & mme : common_execute_on)
244 115396 : _execute_on.setAdditionalValue(mme);
245 : }
246 :
247 : // If --show-outputs is used, enable it
248 185865 : if (_app.getParam<bool>("show_outputs"))
249 30 : _system_info_flags.setAdditionalValue("output");
250 61955 : }
251 :
252 117420 : Console::~Console()
253 : {
254 : // Write the libMesh log
255 58710 : if (_libmesh_log)
256 58710 : write(libMesh::perflog.get_perf_info(), false);
257 :
258 : // Write the file output stream
259 58710 : writeStreamToFile();
260 :
261 : // Disable logging so that the destructor in libMesh doesn't print
262 58710 : libMesh::perflog.disable_logging();
263 117420 : }
264 :
265 : void
266 60686 : Console::initialSetup()
267 : {
268 : // Only allow the main app to change the perf_log settings.
269 60686 : if (_app.name() == "main")
270 : {
271 : // Disable libMesh log
272 48678 : if (!_libmesh_log)
273 0 : libMesh::perflog.disable_logging();
274 : }
275 :
276 : // system info flag can be changed only before console initial setup
277 60686 : _allow_changing_sysinfo_flag = false;
278 :
279 : // If execute_on = 'initial' perform the output
280 182058 : if (wantOutput("system_information", EXEC_INITIAL))
281 60686 : outputSystemInformation();
282 :
283 : // Call the base class method
284 60686 : TableOutput::initialSetup();
285 :
286 : // If file output is desired, wipe out the existing file if not recovering
287 60670 : if (!_app.isRecovering())
288 56796 : writeStreamToFile(false);
289 :
290 : // Enable verbose output if Executioner has it enabled
291 303350 : if (_app.getExecutioner()->isParamValid("verbose") &&
292 242680 : _app.getExecutioner()->getParam<bool>("verbose"))
293 1090 : _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 182010 : if (_execute_on.isValueSet("final"))
299 : {
300 2256 : if (!_pars.isParamSetByUser("postprocessor_execute_on"))
301 3760 : _advanced_execute_on["postprocessors"].setAdditionalValue("final");
302 2256 : if (!_pars.isParamSetByUser("scalars_execute_on"))
303 3760 : _advanced_execute_on["scalars"].setAdditionalValue("final");
304 2256 : if (!_pars.isParamSetByUser("vector_postprocessor_execute_on"))
305 3760 : _advanced_execute_on["vector_postprocessors"].setAdditionalValue("final");
306 : }
307 60670 : }
308 :
309 : std::string
310 83227 : Console::filename()
311 : {
312 83227 : std::string file_name;
313 83227 : 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 82821 : file_name = _file_base + ".txt";
320 83227 : return file_name;
321 0 : }
322 :
323 : void
324 285047 : Console::timestepSetup()
325 : {
326 285047 : writeTimestepInformation(/*output_dt = */ true);
327 285047 : }
328 :
329 : void
330 4051715 : Console::output()
331 : {
332 4051715 : const auto & type = _current_execute_flag;
333 :
334 : // Return if the current output is not on the desired interval
335 4051715 : 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 12155145 : if (wantOutput("system_information", type) && !(type == EXEC_INITIAL))
342 0 : outputSystemInformation();
343 :
344 : // Write the input
345 12155145 : 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 4051715 : if (type == EXEC_INITIAL && _execute_on.isValueSet(EXEC_INITIAL))
352 57468 : writeTimestepInformation(/*output_dt = */ false);
353 3994247 : else if (type == EXEC_FINAL && _execute_on.isValueSet(EXEC_FINAL))
354 : {
355 3269 : if (wantOutput("postprocessors", type) || wantOutput("scalars", type))
356 263 : _console << "\nFINAL:\n";
357 : }
358 :
359 : // Print Non-linear Residual (control with "execute_on")
360 4051715 : if (type == EXEC_NONLINEAR && _execute_on.isValueSet(EXEC_NONLINEAR))
361 : {
362 814942 : if (_nonlinear_iter == 0)
363 308646 : _old_nonlinear_norm = std::numeric_limits<Real>::max();
364 :
365 814942 : _console << std::right << std::setw(2) << _nonlinear_iter
366 814942 : << " Nonlinear |R| = " << outputNorm(_old_nonlinear_norm, _norm) << '\n';
367 :
368 814942 : _old_nonlinear_norm = _norm;
369 : }
370 :
371 : // Print Linear Residual (control with "execute_on")
372 3236773 : else if (type == EXEC_LINEAR && _execute_on.isValueSet(EXEC_LINEAR))
373 : {
374 2609891 : if (_linear_iter == 0)
375 513332 : _old_linear_norm = std::numeric_limits<Real>::max();
376 :
377 2609891 : _console << std::right << std::setw(7) << _linear_iter
378 2609891 : << " Linear |R| = " << outputNorm(_old_linear_norm, _norm) << '\n';
379 :
380 2609891 : _old_linear_norm = _norm;
381 : }
382 :
383 : // Write variable norms
384 626882 : else if (type == EXEC_TIMESTEP_END)
385 232156 : writeVariableNorms();
386 :
387 12155145 : if (wantOutput("postprocessors", type))
388 116536 : outputPostprocessors();
389 :
390 12155133 : if (wantOutput("scalars", type))
391 18167 : outputScalarVariables();
392 :
393 12155133 : if (wantOutput("reporters", type))
394 6301 : outputReporters();
395 :
396 : // Write the file
397 4051711 : writeStreamToFile();
398 :
399 4051711 : _console << std::flush;
400 : }
401 :
402 : void
403 4167217 : Console::writeStreamToFile(bool append)
404 : {
405 4167217 : if (!_write_file || (!_write_all_procs_to_files && processor_id() > 0))
406 4144680 : 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 45074 : _file_output_stream.str("");
427 22537 : }
428 :
429 : void
430 342515 : Console::writeTimestepInformation(bool output_dt)
431 : {
432 : // Stream to build the time step information
433 342515 : std::stringstream oss;
434 :
435 : // Write timestep data for transient executioners
436 342515 : if (_transient)
437 : {
438 : // Write time step and time information
439 283692 : oss << "\nTime Step " << timeStep();
440 283692 : unsigned int time_step_digits = oss.str().length() - 11;
441 :
442 : // Print the time
443 283692 : oss << ", time = " << formatTime(getOutputTime());
444 :
445 283692 : if (output_dt)
446 : {
447 255207 : if (!_verbose)
448 : // Show the time delta information
449 246980 : oss << ", dt = " << std::left << formatTime(dt());
450 :
451 : // Show old time information, if desired on separate lines
452 : else
453 : {
454 8227 : unsigned int fillsize = 19 + time_step_digits;
455 8227 : oss << '\n'
456 8227 : << std::right << std::setw(fillsize) << std::setfill(' ') << "old time = " << std::left
457 8227 : << formatTime(timeOld()) << '\n';
458 :
459 : // Show the time delta information
460 8227 : oss << std::right << std::setw(fillsize) << std::setfill(' ') << "dt = " << std::left
461 8227 : << formatTime(dt()) << '\n';
462 :
463 : // Show the old time delta information, if desired
464 8227 : if (_verbose)
465 8227 : oss << std::right << std::setw(fillsize) << std::setfill(' ')
466 8227 : << "old dt = " << formatTime(_dt_old) << '\n';
467 : }
468 : }
469 :
470 283692 : oss << '\n';
471 :
472 : // Output to the screen
473 283692 : _console << oss.str() << std::flush;
474 : }
475 342515 : }
476 :
477 : std::string
478 555353 : Console::formatTime(const Real t) const
479 : {
480 555353 : std::ostringstream oss;
481 555353 : if (_time_format != TimeFormatEnum::DTIME)
482 : {
483 552983 : if (_precision > 0)
484 7910 : oss << std::setw(_precision) << std::setprecision(_precision) << std::setfill('0')
485 7910 : << std::showpoint;
486 552983 : if (_scientific_time)
487 0 : oss << std::scientific;
488 :
489 552983 : if (_time_format == TimeFormatEnum::PLAIN)
490 545873 : 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 1110706 : return oss.str();
535 555353 : }
536 :
537 : void
538 232156 : Console::writeVariableNorms()
539 : {
540 : // If all_variable_norms is true, then so should outlier printing
541 232156 : 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 232156 : 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 232120 : if (dynamic_cast<EigenProblem *>(_problem_ptr) != nullptr)
552 616 : return;
553 :
554 : // Flag set when header prints
555 231504 : bool header = false;
556 :
557 : // String stream for variable norm information
558 231504 : std::ostringstream oss;
559 :
560 465269 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
561 : {
562 : // Get a references to the NonlinearSystem and libMesh system
563 233765 : NonlinearSystemBase & nl = _problem_ptr->getNonlinearSystemBase(i);
564 233765 : System & sys = nl.system();
565 :
566 : // Storage for norm outputs
567 233765 : std::map<std::string, Real> other;
568 233765 : std::map<std::string, Real> outlier;
569 :
570 : // Average norm
571 233765 : unsigned int n_vars = sys.n_vars();
572 233765 : Real avg_norm = (nl.nonlinearNorm() * nl.nonlinearNorm()) / n_vars;
573 :
574 : // Compute the norms for each of the variables
575 520696 : for (unsigned int i = 0; i < n_vars; i++)
576 : {
577 : // Compute the norm and extract the variable name
578 286931 : Real var_norm = sys.calculate_norm(nl.RHS(), i, DISCRETE_L2);
579 286931 : var_norm *= var_norm; // use the norm squared
580 286931 : 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 286931 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[1] * avg_norm))
584 : {
585 : // Print the header
586 14556 : if (!header)
587 : {
588 14046 : oss << "\nOutlier Variable Residual Norms:\n";
589 14046 : header = true;
590 : }
591 :
592 : // Set the color, RED if the variable norm is 0.8 (default) of the total norm
593 14556 : std::string color = COLOR_YELLOW;
594 14556 : if (_outlier_variable_norms && (var_norm > _outlier_multiplier[0] * avg_norm * n_vars))
595 13627 : color = COLOR_RED;
596 :
597 : // Display the residual
598 14556 : oss << " " << var_name << ": " << std::scientific << color << std::sqrt(var_norm)
599 14556 : << COLOR_DEFAULT << '\n';
600 14556 : }
601 :
602 : // GREEN
603 272375 : 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 286931 : }
615 233765 : }
616 :
617 : // Update the output streams
618 231504 : _console << oss.str() << std::flush;
619 231504 : }
620 :
621 : // Quick helper to output the norm in color
622 : std::string
623 3789173 : Console::outputNorm(const Real & old_norm, const Real & norm, const unsigned int precision)
624 : {
625 3789173 : std::string color = COLOR_GREEN;
626 :
627 : // Red if the residual went up... or if the norm is nan
628 3789173 : if (norm != norm || norm > old_norm)
629 62122 : color = COLOR_RED;
630 : // Yellow if change is less than 5%
631 3727051 : else if ((old_norm - norm) / old_norm <= 0.05)
632 99863 : color = COLOR_YELLOW;
633 :
634 3789173 : std::stringstream oss;
635 3789173 : oss << std::scientific << std::setprecision(precision) << color << norm << COLOR_DEFAULT;
636 :
637 7578346 : return oss.str();
638 3789173 : }
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 116536 : Console::outputPostprocessors()
655 : {
656 116536 : TableOutput::outputPostprocessors();
657 :
658 116536 : if (!_postprocessor_table.empty())
659 : {
660 116536 : std::stringstream oss;
661 116536 : oss << "\nPostprocessor Values:\n";
662 116536 : _postprocessor_table.sortColumns();
663 116536 : _postprocessor_table.printTable(oss, _max_rows, _fit_mode);
664 116532 : _console << oss.str() << std::endl;
665 116532 : }
666 116532 : }
667 :
668 : void
669 6301 : Console::outputReporters()
670 : {
671 6301 : TableOutput::outputReporters();
672 :
673 6301 : if (!_reporter_table.empty())
674 : {
675 2704 : std::stringstream oss;
676 2704 : oss << "\nReporter Values:\n";
677 2704 : _reporter_table.sortColumns();
678 2704 : _reporter_table.printTable(oss, _max_rows, _fit_mode);
679 2704 : _console << oss.str() << '\n';
680 2704 : }
681 6301 : }
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 60686 : 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 60686 : if (_app.multiAppNumber() > 0)
707 5264 : return;
708 :
709 166266 : if (_system_info_flags.isValueSet("framework"))
710 55409 : _console << ConsoleUtils::outputFrameworkInformation(_app);
711 :
712 166266 : if (_system_info_flags.isValueSet("mesh"))
713 55409 : _console << ConsoleUtils::outputMeshInformation(*_problem_ptr);
714 :
715 166266 : if (_system_info_flags.isValueSet("nonlinear"))
716 : {
717 109753 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
718 : {
719 54344 : std::string output = ConsoleUtils::outputSolverSystemInformation(*_problem_ptr, i);
720 54344 : if (!output.empty())
721 : {
722 44873 : _console << "Nonlinear System";
723 44873 : if (_problem_ptr->numNonlinearSystems() > 1)
724 424 : _console << " [" + _problem_ptr->getNonlinearSystemNames()[i] + "]";
725 44873 : _console << ":\n" << output;
726 : }
727 54344 : }
728 : }
729 :
730 166266 : if (_system_info_flags.isValueSet("linear"))
731 56660 : for (const auto i : make_range(_problem_ptr->numLinearSystems()))
732 : {
733 : std::string output = ConsoleUtils::outputSolverSystemInformation(
734 1340 : *_problem_ptr, _problem_ptr->numNonlinearSystems() + i);
735 1340 : if (!output.empty())
736 2680 : _console << "Linear System" +
737 7988 : (_problem_ptr->numLinearSystems() > 1 ? (" " + std::to_string(i)) : "") +
738 2680 : ":\n"
739 1340 : << output;
740 1340 : }
741 :
742 166266 : if (_system_info_flags.isValueSet("aux"))
743 : {
744 55409 : std::string output = ConsoleUtils::outputAuxiliarySystemInformation(*_problem_ptr);
745 55409 : if (!output.empty())
746 22759 : _console << "Auxiliary System:\n" << output;
747 55409 : }
748 :
749 166266 : 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 166266 : if (_system_info_flags.isValueSet("execution"))
757 55409 : _console << ConsoleUtils::outputExecutionInformation(_app, *_problem_ptr);
758 :
759 166266 : if (_app.getParam<bool>("show_data_paths"))
760 10 : _console << ConsoleUtils::outputDataFilePaths();
761 :
762 166266 : if (_app.getParam<bool>("show_data_params"))
763 10 : _console << ConsoleUtils::outputDataFileParams(_app);
764 :
765 166266 : if (_system_info_flags.isValueSet("output"))
766 10 : _console << ConsoleUtils::outputOutputInformation(_app);
767 :
768 166266 : if (!_app.getParam<bool>("use_legacy_initial_residual_evaluation_behavior"))
769 109753 : for (const auto i : make_range(_problem_ptr->numNonlinearSystems()))
770 54357 : 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 55422 : _console << ConsoleUtils::outputLegacyInformation(_app);
778 :
779 55422 : _console << std::flush;
780 : }
781 :
782 : void
783 7662 : Console::meshChanged()
784 : {
785 7662 : 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 7662 : }
820 :
821 : void
822 6108818 : 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 6108818 : if (message.empty())
826 1141107 : return;
827 :
828 : // Write the message to file
829 4967711 : if (_write_file)
830 23941 : _file_output_stream << message;
831 :
832 : // The empty case gets the right behavior, even though the boolean is technically wrong
833 4967711 : bool this_message_ends_in_newline = message.empty() ? true : (message.back() == '\n');
834 4967711 : bool this_message_starts_with_newline = message.empty() ? true : (message.front() == '\n');
835 :
836 : // Apply MultiApp indenting
837 9934979 : if ((this_message_starts_with_newline || _last_message_ended_in_newline) && indent &&
838 4967268 : _app.multiAppLevel() > 0)
839 2193576 : MooseUtils::indentMessage(_app.name(), message);
840 :
841 : // Write message to the screen
842 4967711 : if (_write_screen)
843 4967711 : Moose::out << message;
844 :
845 4967711 : _last_message_ended_in_newline = this_message_ends_in_newline;
846 : }
847 :
848 : void
849 6050108 : Console::mooseConsole(const std::string & message)
850 : {
851 : // Write the messages
852 6050108 : write(message);
853 :
854 : // Flush the stream to the screen
855 6050108 : Moose::out << std::flush;
856 6050108 : }
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 : }
|