MRCPP comes with a printer class to handle standard output which is available by including:
The main purpose of this class is to provide (or suppress) any internal printing
in MRCPP routines that might be useful for debugging. Also, it provides a sane
printing environment for parallel computations that can also be used by the
application program. E.g. by using the printing routines of this class, as
opposed to the standard
std::cout, only the master thread in a OpenMP region
will provide any output while all other threads remain silent. Similarly, when
running an application program in MPI parallel the
three different options for handling printed output (see examples below):
- Only master rank prints to screen (stdout)
- All ranks prints to screen (stdout)
- All ranks prints to individual files
If you want only the master rank to print to an output file, this can be
achieved by redirecting the output from the first option to a file
The main functionality of the MRCPP printer is given by the two macros
println (see below for details) which should replace the
regular calls to
std::cout. In addition there are a few helper functions
and macros for convenience output.
mrcpp::print functions takes an integer print level as first argument.
mrcpp::Printer is initialized with a given print level, only print
statements with a lower print level will be displayed. All internal printing
in MRCPP is at print level 10 or higher, so there is some flexibility left
(levels 0 through 9) for adjusting the print volume within the application
- Initialize the
mrcpp::Printerwith print level and options for parallel printing. No output is provided by the mrcpp::print routines unless the
- Use scientific notation (e.g. 1.0e02) for floating point numbers.
- Use fixed notation (e.g. 100.0) for floating point numbers.
- Set new precision for floating point values, e.i. number of digits after the comma. Returns the old precision.
- Get the current precision for floating point values.
- Change the print level from this point onwards. Returns the old print level.
- Get the current print level.
- Set the line width (in number of characters) of the helper function output. Default is 60 characters.
- Get the current line width (in number of characters).
Some convenience functions for printing output is provided within the
mrcpp::print namespace. These functions use the data of the
mrcpp::Printer class to provide pretty output of a few standard data types.
- Print information on how MRCPP was built. Version number and git revision, which linear algebra library is used, and parallel options.
- Print a full line of a single character.
- Print a headline.
- Print a footline, including a timer.
- Print a floating point value, including unit.
- Print a tree size (nodes and memory) and time.
- Print the current memory usage of the this process.
The following macros should replace the regular calls to
- Print a string with a given print level, no newline.
- Print a string with a given print level, with newline.
The following macros will print a message along with information on where you
are in the code (file name, line number and function name). Only macros that
_ABORT will kill the program, all other will continue to run after
the message is printed.
- Prints a “Info: ” message, no abort.
- Prints a “Warning: ” message, no abort.
- Prints a “Error: ” message, no abort.
- Prints a “Error: ” message and aborts the program.
- You have passed an invalid argument to a function. Aborts program.
- You have reached a function that is yet to be implemeted. Aborts program.
- You have reached a point in the code that should not be reached, probably due to a bug or inconsistency. Aborts program.
- You have reached an experimental part of the code, results cannot be trusted.
- You have hit a known bug that is yet to be fixed, results cannot be trusted.
Using the print level to adjust the amount of output:
int level = 10; mrcpp::Printer::init(level); // Initialize printer with printlevel 10 println( 0, "This is printlevel 0"); // This will be displayed at printlevel 10 println(10, "This is printlevel 10"); // This will be displayed at printlevel 10 println(11, "This is printlevel 11"); // This will NOT be displayed at printlevel 10
Using headers and footers to get pretty output:
using namespace mrcpp; Timer timer; // Start timer project(prec, tree, func); // Project function double integral = tree.integrate(); // Integrate function timer.stop(); // Stop timer print::header(0, "Projecting analytic function"); print::tree(0, "Projected function", tree, timer); print::value(0, "Integrated function", integral, "(au)"); print::footer(0, timer);
This will produce the following output:
============================================================ Projecting analytic function ------------------------------------------------------------ Projected function 520 nds 16 MB 0.09 sec Integrated function (au) 9.999999999992e-01 ------------------------------------------------------------ Wall time: 9.32703e-02 sec ============================================================
As mentioned above, when running in MPI parallel there are three different ways
of handling printed output (master to stdout, all to stdout or all to files).
These can be chosen by adding appropriate arguments to
init. The default
setting will in a parallel environment have all MPI ranks printing to screen,
but by adding MPI info to the printer, we can separate the output of the
int level = 10; int wrank, wsize; MPI_Comm_rank(MPI_COMM_WORLD, &wrank); // Get my rank MPI_Comm_size(MPI_COMM_WORLD, &wsize); // Get total number of ranks // All ranks will print to screen mrcpp::Printer::init(level); // Only master rank will print to screen mrcpp::Printer::init(level, wrank, wsize); // All ranks will print to separate files called filename-<rank>.out mrcpp::Printer::init(level, wrank, wsize, "filename");