Skip to content

Commit 4ec8a29

Browse files
committed
Step/variable-based layout: Frontend implementation
1 parent 569303d commit 4ec8a29

File tree

9 files changed

+133
-35
lines changed

9 files changed

+133
-35
lines changed

include/openPMD/Iteration.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class Iteration : public Attributable
155155

156156
void flushFileBased(std::string const&, uint64_t);
157157
void flushGroupBased(uint64_t);
158+
void flushStepBased(uint64_t);
158159
void flush();
159160
void read();
160161

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, stepBased
3535
};
3636

3737
std::ostream&

include/openPMD/backend/Attributable.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class Attributable
153153

154154
OPENPMD_protected:
155155
void flushAttributes();
156-
void readAttributes();
156+
void readAttributes( bool reread = false );
157157

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

src/IO/ADIOS/ADIOS2IOHandler.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,11 +1838,6 @@ namespace detail
18381838
const adios2::Dims & count,
18391839
const bool constantDims )
18401840
{
1841-
/*
1842-
* Step/Variable-based iteration layout:
1843-
* The variable may already be defined from a previous step,
1844-
* so check if it's already here.
1845-
*/
18461841
adios2::Variable< T > var = IO.InquireVariable< T >( name );
18471842
if( !var )
18481843
{

src/Iteration.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,21 @@ Iteration::flushGroupBased(uint64_t i)
287287
flush();
288288
}
289289

290+
void
291+
Iteration::flushStepBased( uint64_t i )
292+
{
293+
if( !written() )
294+
{
295+
/* create iteration path */
296+
Parameter< Operation::OPEN_PATH > pOpen;
297+
pOpen.path = "";
298+
IOHandler->enqueue( IOTask( this, pOpen ) );
299+
this->setAttribute( "__step__", i );
300+
}
301+
302+
flush();
303+
}
304+
290305
void
291306
Iteration::flush()
292307
{
@@ -306,8 +321,10 @@ Iteration::flush()
306321
if( !meshes.empty() || s->containsAttribute("meshesPath") )
307322
{
308323
if( !s->containsAttribute("meshesPath") )
324+
{
309325
s->setMeshesPath("meshes/");
310-
s->flushMeshesPath();
326+
s->flushMeshesPath();
327+
}
311328
meshes.flush(s->meshesPath());
312329
for( auto& m : meshes )
313330
m.second.flush(m.first);
@@ -316,8 +333,10 @@ Iteration::flush()
316333
if( !particles.empty() || s->containsAttribute("particlesPath") )
317334
{
318335
if( !s->containsAttribute("particlesPath") )
336+
{
319337
s->setParticlesPath("particles/");
320-
s->flushParticlesPath();
338+
s->flushParticlesPath();
339+
}
321340
particles.flush(s->particlesPath());
322341
for( auto& species : particles )
323342
species.second.flush(species.first);
@@ -492,6 +511,7 @@ Iteration::beginStep()
492511
file = this;
493512
break;
494513
case IE::groupBased:
514+
case IE::stepBased:
495515
file = &series;
496516
break;
497517
}
@@ -503,7 +523,8 @@ Iteration::beginStep()
503523
}
504524

505525
// re-read -> new datasets might be available
506-
if( *series.m_iterationEncoding == IE::groupBased &&
526+
if( ( *series.m_iterationEncoding == IE::groupBased ||
527+
*series.m_iterationEncoding == IE::stepBased ) &&
507528
( this->IOHandler->m_frontendAccess == Access::READ_ONLY ||
508529
this->IOHandler->m_frontendAccess == Access::READ_WRITE ) )
509530
{
@@ -536,6 +557,7 @@ Iteration::endStep()
536557
file = this;
537558
break;
538559
case IE::groupBased:
560+
case IE::stepBased:
539561
file = &series;
540562
break;
541563
}
@@ -555,6 +577,7 @@ Iteration::getStepStatus()
555577
case IE::fileBased:
556578
return *this->m_stepStatus;
557579
case IE::groupBased:
580+
case IE::stepBased:
558581
return *s->m_stepStatus;
559582
default:
560583
throw std::runtime_error( "[Iteration] unreachable" );
@@ -573,6 +596,7 @@ Iteration::setStepStatus( StepStatus status )
573596
*this->m_stepStatus = status;
574597
break;
575598
case IE::groupBased:
599+
case IE::stepBased:
576600
*s->m_stepStatus = status;
577601
break;
578602
default:

src/IterationEncoding.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ openPMD::operator<<(std::ostream& os, openPMD::IterationEncoding const& ie)
3434
case openPMD::IterationEncoding::groupBased:
3535
os << "groupBased";
3636
break;
37+
case openPMD::IterationEncoding::stepBased:
38+
os << "stepBased";
39+
break;
3740
}
3841
return os;
3942
}

src/Series.cpp

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ Series::setIterationEncoding(IterationEncoding ie)
305305
setIterationFormat(BASEPATH);
306306
setAttribute("iterationEncoding", std::string("groupBased"));
307307
break;
308+
case IterationEncoding::stepBased:
309+
setIterationFormat(BASEPATH);
310+
setAttribute("iterationEncoding", std::string("stepBased"));
311+
break;
308312
}
309313
return *this;
310314
}
@@ -321,9 +325,10 @@ Series::setIterationFormat(std::string const& i)
321325
if( written() )
322326
throw std::runtime_error("A files iterationFormat can not (yet) be changed after it has been written.");
323327

324-
if( *m_iterationEncoding == IterationEncoding::groupBased )
328+
if( *m_iterationEncoding == IterationEncoding::groupBased ||
329+
*m_iterationEncoding == IterationEncoding::stepBased )
325330
if( basePath() != i && (openPMD() == "1.0.1" || openPMD() == "1.0.0") )
326-
throw std::invalid_argument("iterationFormat must not differ from basePath " + basePath() + " for groupBased data");
331+
throw std::invalid_argument("iterationFormat must not differ from basePath " + basePath() + " for group- or stepBased data");
327332

328333
setAttribute("iterationFormat", i);
329334
return *this;
@@ -515,6 +520,7 @@ Series::flush_impl( iterations_iterator begin, iterations_iterator end )
515520
flushFileBased( begin, end );
516521
break;
517522
case IE::groupBased:
523+
case IE::stepBased:
518524
flushGroupBased( begin, end );
519525
break;
520526
}
@@ -654,6 +660,7 @@ Series::flushFileBased( iterations_iterator begin, iterations_iterator end )
654660
}
655661
}
656662

663+
// @todo rename as flushGroupStepBased
657664
void
658665
Series::flushGroupBased( iterations_iterator begin, iterations_iterator end )
659666
{
@@ -722,7 +729,19 @@ Series::flushGroupBased( iterations_iterator begin, iterations_iterator end )
722729
it->second.m_writable->parent = getWritable( &iterations );
723730
it->second.parent = getWritable( &iterations );
724731
}
725-
it->second.flushGroupBased(it->first);
732+
switch( *m_iterationEncoding )
733+
{
734+
using IE = IterationEncoding;
735+
case IE::groupBased:
736+
it->second.flushGroupBased( it->first );
737+
break;
738+
case IE::stepBased:
739+
it->second.flushStepBased( it->first );
740+
break;
741+
default:
742+
throw std::runtime_error(
743+
"[Series] Internal control flow error" );
744+
}
726745
if( *it->second.m_closed == Iteration::CloseStatus::ClosedInFrontend )
727746
{
728747
// the iteration has no dedicated file in group-based mode
@@ -805,6 +824,15 @@ Series::readFileBased( )
805824
<< "time series with fileBased iteration "
806825
"encoding. Loaded file is groupBased.\n";
807826
}
827+
else if( encoding == "stepBased" )
828+
{
829+
// @todo should we throw? test this path
830+
*m_iterationEncoding = IterationEncoding::stepBased;
831+
std::cerr << "Series constructor called with iteration "
832+
"regex '%T' suggests loading a "
833+
<< "time series with fileBased iteration "
834+
"encoding. Loaded file is stepBased.\n";
835+
}
808836
else
809837
throw std::runtime_error(
810838
"Unknown iterationEncoding: " + encoding );
@@ -859,6 +887,7 @@ Series::readFileBased( )
859887
"Please specify '%0<N>T' or open as read-only.");
860888
}
861889

890+
// @todo rename as readGroupStepBased
862891
void
863892
Series::readGroupBased( bool do_init )
864893
{
@@ -881,6 +910,8 @@ Series::readGroupBased( bool do_init )
881910
std::string encoding = Attribute(*aRead.resource).get< std::string >();
882911
if( encoding == "groupBased" )
883912
*m_iterationEncoding = IterationEncoding::groupBased;
913+
else if( encoding == "stepBased" )
914+
*m_iterationEncoding = IterationEncoding::stepBased;
884915
else if( encoding == "fileBased" )
885916
{
886917
*m_iterationEncoding = IterationEncoding::fileBased;
@@ -996,23 +1027,50 @@ Series::read()
9961027
IOHandler->enqueue(IOTask(&iterations, pOpen));
9971028

9981029
readAttributes();
999-
iterations.readAttributes();
1030+
/*
1031+
* __step__ changes over steps, so reread that.
1032+
*/
1033+
iterations.readAttributes( /* reread = */ true );
10001034

10011035
/* obtain all paths inside the basepath (i.e. all iterations) */
1002-
Parameter< Operation::LIST_PATHS > pList;
1003-
IOHandler->enqueue(IOTask(&iterations, pList));
1004-
IOHandler->flush();
1005-
1006-
for( auto const& it : *pList.paths )
1036+
switch(*m_iterationEncoding)
10071037
{
1008-
Iteration& i = iterations[std::stoull(it)];
1009-
if ( i.closedByWriter( ) )
1038+
using IE = IterationEncoding;
1039+
case IE::groupBased:
1040+
case IE::fileBased:
10101041
{
1011-
continue;
1042+
Parameter< Operation::LIST_PATHS > pList;
1043+
IOHandler->enqueue(IOTask(&iterations, pList));
1044+
IOHandler->flush();
1045+
1046+
for( auto const& it : *pList.paths )
1047+
{
1048+
Iteration& i = iterations[std::stoull(it)];
1049+
if ( i.closedByWriter( ) )
1050+
{
1051+
continue;
1052+
}
1053+
pOpen.path = it;
1054+
IOHandler->enqueue(IOTask(&i, pOpen));
1055+
i.read();
1056+
}
10121057
}
1013-
pOpen.path = it;
1014-
IOHandler->enqueue(IOTask(&i, pOpen));
1015-
i.read();
1058+
break;
1059+
case IE::stepBased:
1060+
{
1061+
Parameter< Operation::READ_ATT > aRead;
1062+
uint64_t index = 0;
1063+
if( iterations.containsAttribute( "__step__" ) )
1064+
{
1065+
index = iterations.getAttribute( "__step__" )
1066+
.get< uint64_t >();
1067+
}
1068+
Iteration & i = iterations[ index ];
1069+
pOpen.path = "";
1070+
IOHandler->enqueue( IOTask( &i, pOpen ) );
1071+
i.read();
1072+
}
1073+
break;
10161074
}
10171075
}
10181076

@@ -1063,6 +1121,7 @@ Series::advance(
10631121
{
10641122
using IE = IterationEncoding;
10651123
case IE::groupBased:
1124+
case IE::stepBased:
10661125
flushGroupBased( begin, end );
10671126
break;
10681127
case IE::fileBased:
@@ -1131,8 +1190,10 @@ Series::advance(
11311190
// not closed on a per-iteration basis
11321191
// We will treat it as such nonetheless
11331192
*iteration.m_closed = Iteration::CloseStatus::ClosedInBackend;
1193+
break;
11341194
}
1135-
break;
1195+
case IE::stepBased: // no action necessary
1196+
break;
11361197
}
11371198
}
11381199

@@ -1157,7 +1218,9 @@ Series::openIteration( uint64_t index, Iteration iteration )
11571218
pOpen.path = auxiliary::replace_first( basePath(), "%T/", "" );
11581219
IOHandler->enqueue( IOTask( &iterations, pOpen ) );
11591220
/* open iteration path */
1160-
pOpen.path = std::to_string( index );
1221+
pOpen.path = *m_iterationEncoding == IterationEncoding::stepBased
1222+
? ""
1223+
: std::to_string( index );
11611224
IOHandler->enqueue( IOTask( &iteration, pOpen ) );
11621225
switch( *iteration.m_closed )
11631226
{
@@ -1297,6 +1360,7 @@ SeriesIterator::operator++()
12971360
{
12981361
using IE = IterationEncoding;
12991362
case IE::groupBased:
1363+
case IE::stepBased:
13001364
{
13011365
// since we are in group-based iteration layout, it does not
13021366
// matter which iteration we begin a step upon

src/backend/Attributable.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,31 @@ Attributable::flushAttributes()
142142
}
143143

144144
void
145-
Attributable::readAttributes()
145+
Attributable::readAttributes( bool reread )
146146
{
147147
Parameter< Operation::LIST_ATTS > aList;
148148
IOHandler->enqueue(IOTask(this, aList));
149149
IOHandler->flush();
150150
std::vector< std::string > written_attributes = attributes();
151151

152-
/* std::set_difference requires sorted ranges */
153-
std::sort(aList.attributes->begin(), aList.attributes->end());
154-
std::sort(written_attributes.begin(), written_attributes.end());
155-
156152
std::set< std::string > tmpAttributes;
157-
std::set_difference(aList.attributes->begin(), aList.attributes->end(),
158-
written_attributes.begin(), written_attributes.end(),
159-
std::inserter(tmpAttributes, tmpAttributes.begin()));
153+
if( reread )
154+
{
155+
tmpAttributes = std::set< std::string >(
156+
aList.attributes->begin(),
157+
aList.attributes->end() );
158+
}
159+
else
160+
{
161+
/* std::set_difference requires sorted ranges */
162+
std::sort(aList.attributes->begin(), aList.attributes->end());
163+
std::sort(written_attributes.begin(), written_attributes.end());
164+
165+
std::set_difference(
166+
aList.attributes->begin(), aList.attributes->end(),
167+
written_attributes.begin(), written_attributes.end(),
168+
std::inserter(tmpAttributes, tmpAttributes.begin()));
169+
}
160170

161171
using DT = Datatype;
162172
Parameter< Operation::READ_ATT > aRead;

src/binding/python/IterationEncoding.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ void init_IterationEncoding(py::module &m) {
3131
py::enum_<IterationEncoding>(m, "Iteration_Encoding")
3232
.value("file_based", IterationEncoding::fileBased)
3333
.value("group_based", IterationEncoding::groupBased)
34+
.value("step_based", IterationEncoding::stepBased)
3435
;
3536
}

0 commit comments

Comments
 (0)