Skip to content

Commit bd1ef94

Browse files
committed
Step/variable-based layout: Frontend implementation
1 parent b34cb35 commit bd1ef94

File tree

8 files changed

+133
-31
lines changed

8 files changed

+133
-31
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 LegacyAttributable
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
@@ -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/Iteration.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,21 @@ Iteration::flushGroupBased(uint64_t i)
252252
flush();
253253
}
254254

255+
void
256+
Iteration::flushStepBased( uint64_t i )
257+
{
258+
if( !written() )
259+
{
260+
/* create iteration path */
261+
Parameter< Operation::OPEN_PATH > pOpen;
262+
pOpen.path = "";
263+
IOHandler()->enqueue( IOTask( this, pOpen ) );
264+
this->setAttribute( "__step__", i );
265+
}
266+
267+
flush();
268+
}
269+
255270
void
256271
Iteration::flush()
257272
{
@@ -270,8 +285,10 @@ Iteration::flush()
270285
if( !meshes.empty() || s->containsAttribute("meshesPath") )
271286
{
272287
if( !s->containsAttribute("meshesPath") )
288+
{
273289
s->setMeshesPath("meshes/");
274-
s->flushMeshesPath();
290+
s->flushMeshesPath();
291+
}
275292
meshes.flush(s->meshesPath());
276293
for( auto& m : meshes )
277294
m.second.flush(m.first);
@@ -280,8 +297,10 @@ Iteration::flush()
280297
if( !particles.empty() || s->containsAttribute("particlesPath") )
281298
{
282299
if( !s->containsAttribute("particlesPath") )
300+
{
283301
s->setParticlesPath("particles/");
284-
s->flushParticlesPath();
302+
s->flushParticlesPath();
303+
}
285304
particles.flush(s->particlesPath());
286305
for( auto& species : particles )
287306
species.second.flush(species.first);
@@ -454,6 +473,7 @@ Iteration::beginStep()
454473
file = m_attributableData.get();
455474
break;
456475
case IE::groupBased:
476+
case IE::stepBased:
457477
file = &series;
458478
break;
459479
}
@@ -465,7 +485,8 @@ Iteration::beginStep()
465485
}
466486

467487
// re-read -> new datasets might be available
468-
if( series.iterationEncoding() == IE::groupBased &&
488+
if( ( series.iterationEncoding() == IE::groupBased ||
489+
series.iterationEncoding() == IE::stepBased ) &&
469490
( this->IOHandler()->m_frontendAccess == Access::READ_ONLY ||
470491
this->IOHandler()->m_frontendAccess == Access::READ_WRITE ) )
471492
{
@@ -497,6 +518,7 @@ Iteration::endStep()
497518
file = m_attributableData.get();
498519
break;
499520
case IE::groupBased:
521+
case IE::stepBased:
500522
file = &series;
501523
break;
502524
}
@@ -515,6 +537,7 @@ Iteration::getStepStatus()
515537
case IE::fileBased:
516538
return *this->m_stepStatus;
517539
case IE::groupBased:
540+
case IE::stepBased:
518541
return *s->m_stepStatus;
519542
default:
520543
throw std::runtime_error( "[Iteration] unreachable" );
@@ -532,6 +555,7 @@ Iteration::setStepStatus( StepStatus status )
532555
*this->m_stepStatus = status;
533556
break;
534557
case IE::groupBased:
558+
case IE::stepBased:
535559
*s->m_stepStatus = status;
536560
break;
537561
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 & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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
283287
SeriesImpl&
284288
SeriesImpl::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
610616
void
611617
SeriesImpl::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
817845
void
818846
SeriesImpl::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

src/backend/Attributable.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,21 +153,31 @@ AttributableImpl::flushAttributes()
153153
}
154154

155155
void
156-
AttributableImpl::readAttributes()
156+
AttributableImpl::readAttributes( bool reread )
157157
{
158158
Parameter< Operation::LIST_ATTS > aList;
159159
IOHandler()->enqueue(IOTask(this, aList));
160160
IOHandler()->flush();
161161
std::vector< std::string > written_attributes = attributes();
162162

163-
/* std::set_difference requires sorted ranges */
164-
std::sort(aList.attributes->begin(), aList.attributes->end());
165-
std::sort(written_attributes.begin(), written_attributes.end());
166-
167163
std::set< std::string > tmpAttributes;
168-
std::set_difference(aList.attributes->begin(), aList.attributes->end(),
169-
written_attributes.begin(), written_attributes.end(),
170-
std::inserter(tmpAttributes, tmpAttributes.begin()));
164+
if( reread )
165+
{
166+
tmpAttributes = std::set< std::string >(
167+
aList.attributes->begin(),
168+
aList.attributes->end() );
169+
}
170+
else
171+
{
172+
/* std::set_difference requires sorted ranges */
173+
std::sort(aList.attributes->begin(), aList.attributes->end());
174+
std::sort(written_attributes.begin(), written_attributes.end());
175+
176+
std::set_difference(
177+
aList.attributes->begin(), aList.attributes->end(),
178+
written_attributes.begin(), written_attributes.end(),
179+
std::inserter(tmpAttributes, tmpAttributes.begin()));
180+
}
171181

172182
using DT = Datatype;
173183
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)