Skip to content

Commit cb6583b

Browse files
committed
Step-based iteration layout
1 parent 9f5cbc1 commit cb6583b

19 files changed

Lines changed: 381 additions & 75 deletions

include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "openPMD/auxiliary/Option.hpp"
3333
#include "openPMD/backend/Writable.hpp"
3434
#include "openPMD/config.hpp"
35+
#include "openPMD/IterationEncoding.hpp"
3536

3637
#if openPMD_HAVE_ADIOS2
3738
# include <adios2.h>
@@ -219,6 +220,7 @@ class ADIOS2IOHandlerImpl
219220

220221
private:
221222
adios2::ADIOS m_ADIOS;
223+
IterationEncoding m_iterationEncoding = IterationEncoding::groupBased;
222224
/**
223225
* The ADIOS2 engine type, to be passed to adios2::IO::SetEngine
224226
*/
@@ -1303,7 +1305,7 @@ class ADIOS2IOHandler : public AbstractIOHandler
13031305
{
13041306
#if openPMD_HAVE_ADIOS2
13051307

1306-
friend class ADIOS2IOHandlerImpl;
1308+
friend class ADIOS2IOHandlerImpl;
13071309

13081310
private:
13091311
ADIOS2IOHandlerImpl m_impl;
@@ -1322,7 +1324,7 @@ friend class ADIOS2IOHandlerImpl;
13221324
}
13231325
catch( ... )
13241326
{
1325-
std::cerr << "[~ADIOS2IOHandler] An error occurred." << std::endl;
1327+
std::cerr << "[~ADIOS2IOHandler] An error occurred." << std::endl;
13261328
}
13271329
}
13281330

include/openPMD/IO/AbstractIOHandlerImpl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class AbstractIOHandlerImpl
238238
*
239239
* The operation should overwrite existing file positions, even when the Writable was already marked written.
240240
* The path parameters.path may contain multiple levels (e.g. first/second/third/). This path should be relative (i.e. it should not start with a slash "/").
241+
* The number of levels may be zero, i.e. parameters.path may be an empty string.
241242
* The Writables file position should correspond to the complete opened path (i.e. first/second/third/ should be assigned to the Writables file position).
242243
* The Writable should be marked written when the operation completes successfully.
243244
*/

include/openPMD/IO/IOTask.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "openPMD/backend/Attribute.hpp"
2626
#include "openPMD/ChunkInfo.hpp"
2727
#include "openPMD/Dataset.hpp"
28+
#include "openPMD/IterationEncoding.hpp"
2829

2930
#include <memory>
3031
#include <map>
@@ -107,7 +108,8 @@ template<>
107108
struct OPENPMDAPI_EXPORT Parameter< Operation::CREATE_FILE > : public AbstractParameter
108109
{
109110
Parameter() = default;
110-
Parameter(Parameter const & p) : AbstractParameter(), name(p.name) {}
111+
Parameter(Parameter const & p) :
112+
AbstractParameter(), name(p.name), encoding(p.encoding) {}
111113

112114
std::unique_ptr< AbstractParameter >
113115
clone() const override
@@ -117,13 +119,15 @@ struct OPENPMDAPI_EXPORT Parameter< Operation::CREATE_FILE > : public AbstractPa
117119
}
118120

119121
std::string name = "";
122+
IterationEncoding encoding = IterationEncoding::groupBased;
120123
};
121124

122125
template<>
123126
struct OPENPMDAPI_EXPORT Parameter< Operation::OPEN_FILE > : public AbstractParameter
124127
{
125128
Parameter() = default;
126-
Parameter(Parameter const & p) : AbstractParameter(), name(p.name) {}
129+
Parameter(Parameter const & p) :
130+
AbstractParameter(), name(p.name), encoding(p.encoding) {}
127131

128132
std::unique_ptr< AbstractParameter >
129133
clone() const override
@@ -133,6 +137,7 @@ struct OPENPMDAPI_EXPORT Parameter< Operation::OPEN_FILE > : public AbstractPara
133137
}
134138

135139
std::string name = "";
140+
IterationEncoding encoding = IterationEncoding::groupBased;
136141
};
137142

138143
template<>

include/openPMD/Iteration.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,15 @@ class Iteration : public LegacyAttributable
156156

157157
struct DeferredRead
158158
{
159-
std::string index;
159+
std::string path;
160+
uint64_t iteration = 0;
160161
bool fileBased = false;
161162
std::string filename;
162163
};
163164

164165
void flushFileBased(std::string const&, uint64_t);
165166
void flushGroupBased(uint64_t);
167+
void flushVariableBased(uint64_t);
166168
void flush();
167169
void deferRead( DeferredRead );
168170
/*

include/openPMD/IterationEncoding.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace openPMD
3131
*/
3232
enum class IterationEncoding
3333
{
34-
fileBased, groupBased
34+
fileBased, groupBased, variableBased
3535
};
3636

3737
std::ostream&

include/openPMD/Series.hpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,18 @@ class SeriesImpl : public AttributableImpl
331331

332332
std::unique_ptr< ParsedInput > parseInput(std::string);
333333
void init(std::shared_ptr< AbstractIOHandler >, std::unique_ptr< ParsedInput >);
334-
void initDefaults();
334+
void initDefaults( IterationEncoding );
335335
std::future< void > flush_impl(
336336
iterations_iterator begin, iterations_iterator end );
337337
void flushFileBased( iterations_iterator begin, iterations_iterator end );
338-
void flushGroupBased( iterations_iterator begin, iterations_iterator end );
338+
/*
339+
* Group-based and variable-based iteration layouts share a lot of logic
340+
* (realistically, the variable-based iteration layout only throws out
341+
* one layer in the hierarchy).
342+
* As a convention, methods that deal with both layouts are called
343+
* .*GorVBased, short for .*GroupOrVariableBased
344+
*/
345+
void flushGorVBased( iterations_iterator begin, iterations_iterator end );
339346
void flushMeshesPath();
340347
void flushParticlesPath();
341348
void readFileBased( );
@@ -348,7 +355,7 @@ class SeriesImpl : public AttributableImpl
348355
* as of yet. Such a facility will be required upon implementing things such
349356
* as resizable datasets.
350357
*/
351-
void readGroupBased( bool init = true );
358+
void readGorVBased( bool init = true );
352359
void readBase();
353360
std::string iterationFilename( uint64_t i );
354361
void openIteration( uint64_t index, Iteration iteration );

include/openPMD/backend/Attributable.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class AttributableImpl
204204
internal::SeriesInternal & retrieveSeries();
205205

206206
void flushAttributes();
207-
void readAttributes();
207+
void readAttributes( bool reread = false );
208208

209209
/** Retrieve the value of a floating point Attribute of user-defined precision with ensured type-safety.
210210
*

src/IO/ADIOS/ADIOS1IOHandler.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ ADIOS1IOHandlerImpl::flush()
9595
case O::CREATE_PATH:
9696
createPath(i.writable, deref_dynamic_cast< Parameter< O::CREATE_PATH > >(i.parameter.get()));
9797
break;
98+
case O::OPEN_PATH:
99+
openPath(i.writable, deref_dynamic_cast< Parameter< O::OPEN_PATH > >(i.parameter.get()));
100+
break;
98101
case O::CREATE_DATASET:
99102
createDataset(i.writable, deref_dynamic_cast< Parameter< O::CREATE_DATASET > >(i.parameter.get()));
100103
break;
@@ -129,9 +132,6 @@ ADIOS1IOHandlerImpl::flush()
129132
case O::EXTEND_DATASET:
130133
extendDataset(i.writable, deref_dynamic_cast< Parameter< O::EXTEND_DATASET > >(i.parameter.get()));
131134
break;
132-
case O::OPEN_PATH:
133-
openPath(i.writable, deref_dynamic_cast< Parameter< O::OPEN_PATH > >(i.parameter.get()));
134-
break;
135135
case O::CLOSE_PATH:
136136
closePath(i.writable, deref_dynamic_cast< Parameter< O::CLOSE_PATH > >(i.parameter.get()));
137137
break;
@@ -240,6 +240,7 @@ ADIOS1IOHandler::enqueue(IOTask const& i)
240240
{
241241
case Operation::CREATE_FILE:
242242
case Operation::CREATE_PATH:
243+
case Operation::OPEN_PATH:
243244
case Operation::CREATE_DATASET:
244245
case Operation::OPEN_FILE:
245246
case Operation::WRITE_ATT:

src/IO/ADIOS/ADIOS2IOHandler.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ void ADIOS2IOHandlerImpl::createFile(
289289
VERIFY( success, "[ADIOS2] Could not create directory." );
290290
}
291291

292+
m_iterationEncoding = parameters.encoding;
292293
associateWithFile( writable, shared_name );
293294
this->m_dirty.emplace( shared_name );
294295
getFileData( shared_name ).m_mode = adios2::Mode::Write; // WORKAROUND
@@ -470,6 +471,7 @@ ADIOS2IOHandlerImpl::openFile(
470471
writable->written = true;
471472
writable->abstractFilePosition = std::make_shared< ADIOS2FilePosition >( );
472473

474+
m_iterationEncoding = parameters.encoding;
473475
// enforce opening the file
474476
// lazy opening is deathly in parallel situations
475477
getFileData( file );
@@ -511,7 +513,9 @@ void ADIOS2IOHandlerImpl::openPath(
511513
std::string prefix =
512514
filePositionToString( setAndGetFilePosition( writable->parent ) );
513515
std::string suffix = auxiliary::removeSlashes( parameters.path );
514-
std::string infix = auxiliary::ends_with( prefix, '/' ) ? "" : "/";
516+
std::string infix = suffix.empty() || auxiliary::ends_with( prefix, '/' )
517+
? ""
518+
: "/";
515519

516520
/* ADIOS has no concept for explicitly creating paths.
517521
* They are implicitly created with the paths of variables/attributes. */
@@ -1428,9 +1432,27 @@ namespace detail
14281432
adios2::Dims const & count,
14291433
bool const constantDims )
14301434
{
1431-
adios2::Variable< T > var =
1432-
IO.DefineVariable< T >( name, shape, start, count, constantDims );
1433-
if ( !var )
1435+
/*
1436+
* Step/Variable-based iteration layout:
1437+
* The variable may already be defined from a previous step,
1438+
* so check if it's already here.
1439+
*/
1440+
adios2::Variable< T > var = IO.InquireVariable< T >( name );
1441+
if( !var )
1442+
{
1443+
var = IO.DefineVariable< T >(
1444+
name, shape, start, count, constantDims );
1445+
}
1446+
else
1447+
{
1448+
var.SetShape( shape );
1449+
if( count.size() > 0 )
1450+
{
1451+
var.SetSelection( { start, count } );
1452+
}
1453+
}
1454+
1455+
if( !var )
14341456
{
14351457
throw std::runtime_error(
14361458
"[ADIOS2] Internal error: Could not create Variable '" + name + "'." );
@@ -2109,6 +2131,12 @@ namespace detail
21092131
"bp4", "bp3", "hdf5", "file"
21102132
};
21112133

2134+
// step/variable-based iteration encoding requires the new schema
2135+
if( m_impl->m_iterationEncoding == IterationEncoding::variableBased )
2136+
{
2137+
m_impl->m_schema = ADIOS2Schema::schema_2021_02_09;
2138+
}
2139+
21122140
// set engine type
21132141
bool isStreaming = false;
21142142
{

src/IO/ADIOS/CommonADIOS1IOHandler.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -677,10 +677,13 @@ CommonADIOS1IOHandlerImpl::openPath(
677677
{
678678
/* Sanitize path */
679679
std::string path = parameters.path;
680-
if( auxiliary::starts_with(path, '/') )
681-
path = auxiliary::replace_first(path, "/", "");
682-
if( !auxiliary::ends_with(path, '/') )
683-
path += '/';
680+
if( !path.empty() )
681+
{
682+
if( auxiliary::starts_with(path, '/') )
683+
path = auxiliary::replace_first(path, "/", "");
684+
if( !auxiliary::ends_with(path, '/') )
685+
path += '/';
686+
}
684687

685688
writable->written = true;
686689
writable->abstractFilePosition = std::make_shared< ADIOS1FilePosition >(path);

0 commit comments

Comments
 (0)