@@ -270,6 +270,10 @@ SeriesImpl::setIterationEncoding(IterationEncoding ie)
270270 setIterationFormat (BASEPATH);
271271 setAttribute (" iterationEncoding" , std::string (" groupBased" ));
272272 break ;
273+ case IterationEncoding::stepBased:
274+ setIterationFormat (BASEPATH);
275+ setAttribute (" iterationEncoding" , std::string (" stepBased" ));
276+ break ;
273277 }
274278 return *this ;
275279}
@@ -283,13 +287,13 @@ SeriesImpl::iterationFormat() const
283287SeriesImpl&
284288SeriesImpl::setIterationFormat (std::string const & i)
285289{
286- auto & series = get ();
287290 if ( written () )
288291 throw std::runtime_error (" A files iterationFormat can not (yet) be changed after it has been written." );
289292
290- if ( *series.m_iterationEncoding == IterationEncoding::groupBased )
293+ if ( iterationEncoding () == IterationEncoding::groupBased ||
294+ iterationEncoding () == IterationEncoding::stepBased )
291295 if ( basePath () != i && (openPMD () == " 1.0.1" || openPMD () == " 1.0.0" ) )
292- throw std::invalid_argument (" iterationFormat must not differ from basePath " + basePath () + " for groupBased data" );
296+ throw std::invalid_argument (" iterationFormat must not differ from basePath " + basePath () + " for group- or stepBased data" );
293297
294298 setAttribute (" iterationFormat" , i);
295299 return *this ;
@@ -467,6 +471,7 @@ SeriesImpl::flush_impl( iterations_iterator begin, iterations_iterator end )
467471 flushFileBased ( begin, end );
468472 break ;
469473 case IE::groupBased:
474+ case IE::stepBased:
470475 flushGroupBased ( begin, end );
471476 break ;
472477 }
@@ -607,6 +612,7 @@ SeriesImpl::flushFileBased( iterations_iterator begin, iterations_iterator end )
607612 }
608613}
609614
615+ // @todo rename as flushGroupStepBased
610616void
611617SeriesImpl::flushGroupBased ( iterations_iterator begin, iterations_iterator end )
612618{
@@ -675,7 +681,19 @@ SeriesImpl::flushGroupBased( iterations_iterator begin, iterations_iterator end
675681 {
676682 it->second .parent () = getWritable ( &series.iterations );
677683 }
678- it->second .flushGroupBased (it->first );
684+ switch ( iterationEncoding () )
685+ {
686+ using IE = IterationEncoding;
687+ case IE::groupBased:
688+ it->second .flushGroupBased ( it->first );
689+ break ;
690+ case IE::stepBased:
691+ it->second .flushStepBased ( it->first );
692+ break ;
693+ default :
694+ throw std::runtime_error (
695+ " [Series] Internal control flow error" );
696+ }
679697 if ( *it->second .m_closed == Iteration::CloseStatus::ClosedInFrontend )
680698 {
681699 // the iteration has no dedicated file in group-based mode
@@ -760,6 +778,15 @@ SeriesImpl::readFileBased( )
760778 << " time series with fileBased iteration "
761779 " encoding. Loaded file is groupBased.\n " ;
762780 }
781+ else if ( encoding == " stepBased" )
782+ {
783+ // @todo should we throw? test this path
784+ *series.m_iterationEncoding = IterationEncoding::stepBased;
785+ std::cerr << " Series constructor called with iteration "
786+ " regex '%T' suggests loading a "
787+ << " time series with fileBased iteration "
788+ " encoding. Loaded file is stepBased.\n " ;
789+ }
763790 else
764791 throw std::runtime_error (
765792 " Unknown iterationEncoding: " + encoding );
@@ -814,6 +841,7 @@ SeriesImpl::readFileBased( )
814841 " Please specify '%0<N>T' or open as read-only." );
815842}
816843
844+ // @todo rename as readGroupStepBased
817845void
818846SeriesImpl::readGroupBased ( bool do_init )
819847{
@@ -837,6 +865,8 @@ SeriesImpl::readGroupBased( bool do_init )
837865 std::string encoding = Attribute (*aRead.resource ).get < std::string >();
838866 if ( encoding == " groupBased" )
839867 *series.m_iterationEncoding = IterationEncoding::groupBased;
868+ else if ( encoding == " stepBased" )
869+ *series.m_iterationEncoding = IterationEncoding::stepBased;
840870 else if ( encoding == " fileBased" )
841871 {
842872 *series.m_iterationEncoding = IterationEncoding::fileBased;
@@ -954,23 +984,50 @@ SeriesImpl::read()
954984 IOHandler ()->enqueue (IOTask (&series.iterations , pOpen));
955985
956986 readAttributes ();
957- series.iterations .readAttributes ();
987+ /*
988+ * __step__ changes over steps, so reread that.
989+ */
990+ series.iterations .readAttributes ( /* reread = */ true );
958991
959992 /* obtain all paths inside the basepath (i.e. all iterations) */
960- Parameter< Operation::LIST_PATHS > pList;
961- IOHandler ()->enqueue (IOTask (&series.iterations , pList));
962- IOHandler ()->flush ();
963-
964- for ( auto const & it : *pList.paths )
993+ switch (*series.m_iterationEncoding )
965994 {
966- Iteration& i = series.iterations [std::stoull (it)];
967- if ( i.closedByWriter ( ) )
995+ using IE = IterationEncoding;
996+ case IE::groupBased:
997+ case IE::fileBased:
968998 {
969- continue ;
999+ Parameter< Operation::LIST_PATHS > pList;
1000+ IOHandler ()->enqueue (IOTask (&series.iterations , pList));
1001+ IOHandler ()->flush ();
1002+
1003+ for ( auto const & it : *pList.paths )
1004+ {
1005+ Iteration& i = series.iterations [std::stoull (it)];
1006+ if ( i.closedByWriter ( ) )
1007+ {
1008+ continue ;
1009+ }
1010+ pOpen.path = it;
1011+ IOHandler ()->enqueue (IOTask (&i, pOpen));
1012+ i.read ();
1013+ }
9701014 }
971- pOpen.path = it;
972- IOHandler ()->enqueue (IOTask (&i, pOpen));
973- i.read ();
1015+ break ;
1016+ case IE::stepBased:
1017+ {
1018+ Parameter< Operation::READ_ATT > aRead;
1019+ uint64_t index = 0 ;
1020+ if ( series.iterations .containsAttribute ( " __step__" ) )
1021+ {
1022+ index = series.iterations .getAttribute ( " __step__" )
1023+ .get < uint64_t >();
1024+ }
1025+ Iteration & i = series.iterations [ index ];
1026+ pOpen.path = " " ;
1027+ IOHandler ()->enqueue ( IOTask ( &i, pOpen ) );
1028+ i.read ();
1029+ }
1030+ break ;
9741031 }
9751032}
9761033
@@ -1027,6 +1084,7 @@ SeriesImpl::advance(
10271084 {
10281085 using IE = IterationEncoding;
10291086 case IE::groupBased:
1087+ case IE::stepBased:
10301088 flushGroupBased ( begin, end );
10311089 break ;
10321090 case IE::fileBased:
@@ -1095,8 +1153,10 @@ SeriesImpl::advance(
10951153 // not closed on a per-iteration basis
10961154 // We will treat it as such nonetheless
10971155 *iteration.m_closed = Iteration::CloseStatus::ClosedInBackend;
1156+ break ;
10981157 }
1099- break ;
1158+ case IE::stepBased: // no action necessary
1159+ break ;
11001160 }
11011161 }
11021162
@@ -1122,7 +1182,9 @@ SeriesImpl::openIteration( uint64_t index, Iteration iteration )
11221182 pOpen.path = auxiliary::replace_first ( basePath (), " %T/" , " " );
11231183 IOHandler ()->enqueue ( IOTask ( &series.iterations , pOpen ) );
11241184 /* open iteration path */
1125- pOpen.path = std::to_string ( index );
1185+ pOpen.path = iterationEncoding () == IterationEncoding::stepBased
1186+ ? " "
1187+ : std::to_string ( index );
11261188 IOHandler ()->enqueue ( IOTask ( &iteration, pOpen ) );
11271189 switch ( *iteration.m_closed )
11281190 {
@@ -1367,6 +1429,7 @@ SeriesIterator::operator++()
13671429 {
13681430 using IE = IterationEncoding;
13691431 case IE::groupBased:
1432+ case IE::stepBased:
13701433 {
13711434 // since we are in group-based iteration layout, it does not
13721435 // matter which iteration we begin a step upon
0 commit comments