Skip to content

ReadRandomAccess: Cannot read variables with changing dimensionality #4474

@franzpoeschel

Description

@franzpoeschel

Describe the bug
ADIOS2 seems to fundamentally support variables that change their shape across steps. This includes changes in dimensionality:

> bpls sample.bp5/ -dt
Step 0:
  int32_t  /data/meshes/theta  {5}
    (0)    0 1 2 3 4 

Step 1:
  int32_t  /data/meshes/theta  {10}
    (0)    0 1 2 3 4 5
    (6)    6 7 8 9 

Step 2:
  int32_t  /data/meshes/theta  {2, 5}
    (0,0)    0 1 2 3 4 5
    (1,1)    6 7 8 9 

This dataset can be read with adios2::Mode::Read, but not adios2::Mode::ReadRandomAccess:

To Reproduce

#include <adios2.h>
#include <numeric>

static void create_file()
{
    adios2::ADIOS adios;
    auto IO = adios.DeclareIO("IO");
    IO.SetEngine("bp5");
    auto engine = IO.Open("sample.bp5", adios2::Mode::Write);

    auto variable = IO.DefineVariable<int>("/data/meshes/theta", {5}, {0}, {5});
    std::vector<int> data(10);
    std::iota(data.begin(), data.end(), 0);

    engine.BeginStep();
    engine.Put(variable, data.data());
    engine.EndStep();

    engine.BeginStep();
    variable.SetShape({10});
    variable.SetSelection({{0}, {10}});
    engine.Put(variable, data.data());
    engine.EndStep();

    engine.BeginStep();
    variable.SetShape({2, 5});
    variable.SetSelection({{0, 0}, {2, 5}});
    engine.Put(variable, data.data());
    engine.EndStep();

    engine.Close();
}

static void read_file()
{
    adios2::ADIOS adios;
    auto IO = adios.DeclareIO("IO");
    auto engine = IO.Open("sample.bp5", adios2::Mode::ReadRandomAccess);

    auto variable = IO.InquireVariable<int>("/data/meshes/theta");

    auto print_shape = [&](std::string const &comment) {
        auto shape = variable.Shape();
        std::cout << comment << ":\t";
        if (shape.size() == 0)
        {
            std::cout << "[]\n";
        }
        else
        {
            auto it = shape.begin();
            std::cout << "[" << *it++;
            for (; it != shape.end(); ++it)
            {
                std::cout << ", " << *it;
            }
            std::cout << "]\n";
        }
    };

    std::vector<int> data(10);

    print_shape("After opening file");

    variable.SetStepSelection({0, 1});
    print_shape("Step 0");
    variable.SetSelection({{0}, {5}});

    variable.SetStepSelection({1, 1});
    print_shape("Step 1");
    variable.SetSelection({{0}, {10}});

    variable.SetStepSelection({2, 1});
    print_shape("Step 2");

    variable.SetSelection({{0, 0}, {2, 5}});

    engine.Close();
}

int main(int argsc, char **argsv)
{
    create_file();
    read_file();
}

Produces the file printed at the top. When executed:

> ./main
After opening file:     [5]                                                                                                                                                                                                                                                                                                
Step 0: [5]                                                                                                                                                                                                                                                                                                                
Step 1: [10]                                                                                                                                                                                                                                                                                                               
Step 2: [2, 5]                                                                                                                                                                                                                                                                                                             
terminate called after throwing an instance of 'std::invalid_argument'                                                                                                                                                                                                                                                     
  what():  [Tue Mar 11 14:54:44 2025] [ADIOS2 EXCEPTION] <Core> <VariableBase> <SetSelection> : count and start must be the same size as shape for variable /data/meshes/theta, in call to SetSelection                                                                                                                    
                                                                                                                                                                                                                                                                                                                           
Aborted (core dumped)

The error is thrown from this line:

helper::Throw<std::invalid_argument>("Core", "VariableBase", "SetSelection",

While variable.Shape() in the reproducer correctly produces the current extent [2, 5], gdb shows the internal value of m_Shape as [5], i.e. the shape from step 0.

Expected behavior
Either of the following:

  1. Varying dimensionality is not supported: In this case, the error should be clearer
  2. Varying dimensionality is supported: No error

Desktop (please complete the following information):

  • OS/Platform: Ubuntu 24.04
  • Build: gcc 13.3.0
  • ADIOS2 v2.10.2 as well as current master a290f4e

Additional context
Add any other context about the problem here.

Following up
Was the issue fixed? Please report back.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions