Hello World

Like in any language, the first program you write is the “Hello World” program.

In this tutorial, we will see how to write “Hello World from ADIOS2” and read it back with ADIOS2. So let’s dig in!

Start editing the skeleton file ADIOS2/examples/hello/helloWorld/hello-world_tutorialSkeleton.cpp.

  1. We create an ADIOS instance, and define the greeting message in our main function as follows:

int main()
{
  adios2::ADIOS adios();
  const std::string greeting("Hello World from ADIOS2");
  ...
  return 0;
}
  1. Then we create a writer function in which we pass the adios instance, and the greeting message as follows:

void writer(adios2::ADIOS& adios, const std::string& greeting)
{
  ...
}
  1. In this writer function, we define an IO object, a string variable for the message as follows:

adios2::IO io = adios.DeclareIO("hello-world-writer");
adios2::Variable<std::string> varGreeting = io.DefineVariable<std::string>("Greeting");

Note

Using the IO object, we can define the engine type that we want to utilize using the io.SetEngine() function. If SetEngine() is not used, the default engine type is BPFile which is an alias for the latest version of the BP engine of the ADIOS2 library. See Available Engines and Supported Engines for more information. It’s important to note that the file extension of an output file, although it’s not a good practice, it can differ from the engine type, e.g. write a foo.h5 file with the BPFile engine. When reading foo.h5 you should explicitly specify the engine type as BPFile to read it properly.

  1. Then we open a file with the name “hello-world-cpp.bp” and write the greeting message to it as follows:

adios2::Engine writer = io.Open("hello-world-cpp.bp", adios2::Mode::Write);
writer.BeginStep();
writer.Put(varGreeting, greeting);
writer.EndStep();
writer.Close();

Note

The BeginStep and EndStep calls are optional when writing one step, but they are required for multiple steps, so it is a good practice to always use them.

  1. Now we create a reader function in which we pass the adios instance, and get the greeting message back as follows:

std::string reader(adios2::ADIOS& adios)
{
  ...
}
  1. In this reader function, we define an IO object and inquire a string variable for the message as follows:

adios2::IO io = adios.DeclareIO("hello-world-reader");
reader.BeginStep();
adios2::Variable<std::string> varGreeting = io.InquireVariable<std::string>("Greeting");
  1. Then we open the file with the name “hello-world-cpp.bp”, read the greeting message from it and return it as follows:

adios2::Engine reader = io.Open("hello-world-cpp.bp", adios2::Mode::Read);
std::string greeting;
reader.BeginStep();
reader.Get(varGreeting, greeting);
reader.EndStep();
reader.Close();
return greeting;

Note

In Mode::Read, the BeginStep and EndStep calls are required when reading one step and multiple steps. We will see in another tutorial how to read multiple steps. It’s important to note that the BeginStep should be called before all Inquire* / Available* function calls.

  1. Finally, we call the writer and reader functions in our main function as follows:

int main()
{
  adios2::ADIOS adios();
  const std::string greeting("Hello World from ADIOS2");
  writer(adios, greeting);
  std::string message = reader(adios);
  std::cout << message << std::endl;
  return 0;
}
  1. The final code should look as follows (excluding try/catch and the optional usage of MPI), and it was derived from the example ADIOS2/examples/hello/helloWorld/hello-world.cpp.

/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * hello-world.cpp : adios2 low-level API example to write and read a
 *                   std::string Variable with a greeting
 *
 *  Created on: Nov 14, 2019
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include <iostream>
#include <stdexcept>

#include <adios2.h>
#if ADIOS2_USE_MPI
#include <mpi.h>
#endif

void writer(adios2::ADIOS &adios, const std::string &greeting)
{
    adios2::IO io = adios.DeclareIO("hello-world-writer");
    adios2::Variable<std::string> varGreeting = io.DefineVariable<std::string>("Greeting");

    adios2::Engine writer = io.Open("hello-world-cpp.bp", adios2::Mode::Write);
    writer.BeginStep();
    writer.Put(varGreeting, greeting);
    writer.EndStep();
    writer.Close();
}

std::string reader(adios2::ADIOS &adios)
{
    adios2::IO io = adios.DeclareIO("hello-world-reader");
    adios2::Engine reader = io.Open("hello-world-cpp.bp", adios2::Mode::Read);
    reader.BeginStep();
    adios2::Variable<std::string> varGreeting = io.InquireVariable<std::string>("Greeting");
    std::string greeting;
    reader.Get(varGreeting, greeting);
    reader.EndStep();
    reader.Close();
    return greeting;
}

int main(int argc, char *argv[])
{
#if ADIOS2_USE_MPI
    MPI_Init(&argc, &argv);
#endif

    try
    {
#if ADIOS2_USE_MPI
        adios2::ADIOS adios(MPI_COMM_WORLD);
#else
        adios2::ADIOS adios;
#endif

        const std::string greeting = "Hello World from ADIOS2";
        writer(adios, greeting);

        const std::string message = reader(adios);
        std::cout << message << "\n";
    }
    catch (std::exception &e)
    {
        std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n";
#if ADIOS2_USE_MPI
        MPI_Abort(MPI_COMM_WORLD, -1);
#endif
    }

#if ADIOS2_USE_MPI
    MPI_Finalize();
#endif

    return 0;
}
  1. You can compile and run it as follows:

cd Path-To-ADIOS2/examples/hello/helloWorld
mkdir build
cd build
cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ ..
cmake --build .
./adios2_hello_helloWorld
  1. You can check the content of the output file “hello-world-cpp.bp” using bpls as follows:

Path-To-ADIOS2/build/bin/bpls ./hello-world-cpp.bp

   string   Greeting  scalar
  1. The Python version of this tutorial can be found at ADIOS2/examples/hello/helloWorld/hello-world.py. and it looks as follows:

#
# Distributed under the OSI-approved Apache License, Version 2.0.  See
# accompanying file Copyright.txt for details.
#
# hello-world.py : adios2 Python API example to write and read a
#                   string Variable with a greeting
#
#  Created on: 2/2/2021
#      Author: Dmitry Ganyushin ganyushindi@ornl.gov
#
import sys
from mpi4py import MPI
from adios2 import Stream, FileReader

DATA_FILENAME = "hello-world-py.bp"
# MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()


def writer(greeting):
    """write a string to a bp file"""
    with Stream(DATA_FILENAME, "w", comm) as fh:
        fh.write("Greeting", greeting)
    return 0


def reader():
    """read a string from a bp file as Stream"""
    message = f"variable Greeting not found in {DATA_FILENAME}"
    with Stream(DATA_FILENAME, "r", comm) as fh:
        for _ in fh.steps():
            message = fh.read("Greeting")
    return message


def filereader():
    """read a string from a bp file using random access read mode"""
    with FileReader(DATA_FILENAME, comm) as fh:
        message = fh.read("Greeting")
    return message


def main():
    """driver function"""
    greeting = "Hello World from ADIOS2"
    writer(greeting)
    message = reader()
    print("As read from adios2.Stream: {}".format(message))
    message2 = filereader()
    print("As read from adios2.FileReader: {}".format(message2))
    return 0


if __name__ == "__main__":
    sys.exit(main())