Printer

MRCPP comes with a printer class to handle standard output:

#include "MRCPP/Printer"

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 host program. 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 a host program in MPI parallel, the mrcpp::Printer provides 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 (./program >file.out).

class Printer

Convenience class to handle printed output.

The Printer singleton class holds the current state of the print environment. All mrcpp::print functions, as well as the println and printout macros, take an integer print level as first argument. When the global 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 host program.

Public Static Functions

static void init(int level = 0, int rank = 0, int size = 1, const char *file = nullptr)

Initialize print environment.

Only print statements with lower printlevel than level will be displayed. If a file name is given, each process will print to a separate file called {file}-{rank}.out. If no file name is given, only processes which initialize the printer with rank=0 will print to screen. By default, all ranks initialize with rank=0, i.e. all ranks print to screen by default.

Parameters
  • level[in] Desired print level of output

  • rank[in] MPI rank of current process

  • size[in] Total number of MPI processes

  • file[in] File name for printed output, will get “-{rank}.out” extension

static inline void setScientific()

Use scientific floating point notation, e.g. 1.0e-2.

static inline void setFixed()

Use fixed floating point notation, e.g. 0.01.

static inline int setWidth(int i)

Set new line width for printed output.

Parameters

i[in] New width (number of characters)

Returns

Old width (number of characters)

static inline int setPrecision(int i)

Set new precision for floating point output.

Parameters

i[in] New precision (digits after comma)

Returns

Old precision (digits after comma)

static inline int setPrintLevel(int i)

Set new print level.

Parameters

i[in] New print level

Returns

Old print level

static inline int getWidth()
Returns

Current line width (number of characters)

static inline int getPrecision()
Returns

Current precision for floating point output (digits after comma)

static inline int getPrintLevel()
Returns

Current print level

Functions

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.

void mrcpp::print::environment(int level)

Print information about MRCPP version and build configuration.

Parameters

level[in] Activation level for print statement

void mrcpp::print::separator(int level, const char &c, int newlines = 0)

Print a full line of a single character.

Parameters
  • level[in] Activation level for print statement

  • c[in] Character to fill the line

  • newlines[in] Number of extra newlines

void mrcpp::print::header(int level, const std::string &txt, int newlines = 0, const char &c = '=')

Print a text header.

Parameters
  • level[in] Activation level for print statement

  • txt[in] Header text

  • newlines[in] Number of extra newlines

  • c[in] Character to fill the first line

void mrcpp::print::footer(int level, const Timer &timer, int newlines = 0, const char &c = '=')

Print a footer with elapsed wall time.

Parameters
  • level[in] Activation level for print statement

  • t[in] Timer to be evaluated

  • newlines[in] Number of extra newlines

  • c[in] Character to fill the last line

template<int D>
void mrcpp::print::tree(int level, const std::string &txt, const MWTree<D> &tree, const Timer &timer)

Print tree parameters (nodes, memory) and wall time.

Parameters
  • level[in] Activation level for print statement

  • txt[in] Text string

  • tree[in] Tree to be printed

  • timer[in] Timer to be evaluated

void mrcpp::print::tree(int level, const std::string &txt, int n, int m, double t)

Print tree parameters (nodes, memory) and wall time.

Parameters
  • level[in] Activation level for print statement

  • txt[in] Text string

  • n[in] Number of tree nodes

  • m[in] Memory usage (kB)

  • t[in] Wall time (sec)

void mrcpp::print::time(int level, const std::string &txt, const Timer &timer)

Print elapsed time from Timer.

Parameters
  • level[in] Activation level for print statement

  • txt[in] Text string

  • timer[in] Timer to be evaluated

void mrcpp::print::memory(int level, const std::string &txt)

Print the current memory usage of this process, obtained from system.

Parameters
  • level[in] Activation level for print statement

  • txt[in] Text string

Macros

The following macros should replace the regular calls to std::cout:

println(level, STR)

Print text at the given print level, with newline.

printout(level, STR)

Print text at the given print level, without 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 end with _ABORT will kill the program, all other will continue to run after the message is printed:

MSG_INFO(STR)

Print info message.

MSG_WARN(STR)

Print warning message.

MSG_ERROR(STR)

Print error message, no abort.

MSG_ABORT(STR)

Print error message and abort.

INVALID_ARG_ABORT

You have passed an invalid argument to a function.

NOT_IMPLEMENTED_ABORT

You have reached a point in the code that is not yet implemented.

NOT_REACHED_ABORT

You have reached a point that should not be reached, bug or inconsistency.

NEEDS_TESTING

You have reached an experimental part of the code, results cannot be trusted.

NEEDS_FIX(STR)

You have hit a known bug that is yet to be fixed, results cannot be trusted.

Examples

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 different ranks:

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");