diff --git a/include/openPMD/RecordComponent.tpp b/include/openPMD/RecordComponent.tpp index 923e3e2e09..2796ed1ae3 100644 --- a/include/openPMD/RecordComponent.tpp +++ b/include/openPMD/RecordComponent.tpp @@ -114,6 +114,15 @@ RecordComponent::storeChunk(Offset o, Extent e, F &&createBuffer) dCreate.name = rc.m_name; IOHandler()->enqueue(IOTask(this, dCreate)); } + + if (size == 0) + { + // Don't forward this operation to the backend as it might create ugly + // zero-blocks in ADIOS2 + setDirtyRecursive(true); + return DynamicMemoryView(); + } + Parameter getBufferView; getBufferView.offset = o; getBufferView.extent = e; diff --git a/include/openPMD/Span.hpp b/include/openPMD/Span.hpp index 93bc0d24f7..85570fd148 100644 --- a/include/openPMD/Span.hpp +++ b/include/openPMD/Span.hpp @@ -113,7 +113,10 @@ class DynamicMemoryView } public: - explicit DynamicMemoryView() = default; + explicit DynamicMemoryView() + { + m_param.out->backendManagedBuffer = false; + } /** * @brief Acquire the underlying buffer at its current position in memory. diff --git a/src/Iteration.cpp b/src/Iteration.cpp index 39ae03fdca..35fbf15247 100644 --- a/src/Iteration.cpp +++ b/src/Iteration.cpp @@ -362,9 +362,14 @@ void Iteration::flush(internal::FlushParams const &flushParams) s.setMeshesPath("meshes/"); s.flushMeshesPath(); } - meshes.flush(s.meshesPath(), flushParams); - for (auto &m : meshes) - m.second.flush(m.first, flushParams); + if (meshes.dirtyRecursive()) + { + meshes.flush(s.meshesPath(), flushParams); + for (auto &m : meshes) + { + m.second.flush(m.first, flushParams); + } + } } else { @@ -378,9 +383,14 @@ void Iteration::flush(internal::FlushParams const &flushParams) s.setParticlesPath("particles/"); s.flushParticlesPath(); } - particles.flush(s.particlesPath(), flushParams); - for (auto &species : particles) - species.second.flush(species.first, flushParams); + if (particles.dirtyRecursive()) + { + particles.flush(s.particlesPath(), flushParams); + for (auto &species : particles) + { + species.second.flush(species.first, flushParams); + } + } } else { @@ -470,6 +480,11 @@ void Iteration::readGorVBased( void Iteration::read_impl(std::string const &groupPath) { + if (!get().m_deferredParseAccess.has_value()) + { + throw error::Internal( + "Attempted reparsing an Iteration that is already parsed."); + } Parameter pOpen; pOpen.path = groupPath; IOHandler()->enqueue(IOTask(this, pOpen)); diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 227a8764a3..cfd1735898 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -366,6 +366,10 @@ template Mesh &Mesh::setTimeOffset(float); void Mesh::flush_impl( std::string const &name, internal::FlushParams const &flushParams) { + if (!dirtyRecursive()) + { + return; + } if (access::readOnly(IOHandler()->m_frontendAccess)) { auto &m = get(); diff --git a/src/ParticleSpecies.cpp b/src/ParticleSpecies.cpp index 4debca137c..99ec6dfe6d 100644 --- a/src/ParticleSpecies.cpp +++ b/src/ParticleSpecies.cpp @@ -155,6 +155,10 @@ namespace void ParticleSpecies::flush( std::string const &path, internal::FlushParams const &flushParams) { + if (!dirtyRecursive()) + { + return; + } if (access::readOnly(IOHandler()->m_frontendAccess)) { for (auto &record : *this) @@ -168,12 +172,15 @@ void ParticleSpecies::flush( } else { - auto it = find("position"); - if (it != end()) - it->second.setUnitDimension({{UnitDimension::L, 1}}); - it = find("positionOffset"); - if (it != end()) - it->second.setUnitDimension({{UnitDimension::L, 1}}); + if (flushParams.flushLevel != FlushLevel::SkeletonOnly) + { + auto it = find("position"); + if (it != end()) + it->second.setUnitDimension({{UnitDimension::L, 1}}); + it = find("positionOffset"); + if (it != end()) + it->second.setUnitDimension({{UnitDimension::L, 1}}); + } Container::flush(path, flushParams); diff --git a/src/Record.cpp b/src/Record.cpp index 7d41fce5c2..c6baedec7c 100644 --- a/src/Record.cpp +++ b/src/Record.cpp @@ -45,13 +45,17 @@ Record &Record::setUnitDimension(unit_representations::AsMap const &udim) } Record &Record::setUnitDimension(unit_representations::AsArray const &udim) { - return setUnitDimension( - unit_representations::asMap(udim, /* skip_zeros = */ false)); + setAttribute("unitDimension", udim); + return *this; } void Record::flush_impl( std::string const &name, internal::FlushParams const &flushParams) { + if (!dirtyRecursive()) + { + return; + } if (access::readOnly(IOHandler()->m_frontendAccess)) { if (scalar()) diff --git a/src/RecordComponent.cpp b/src/RecordComponent.cpp index 49febc68e8..f2a67a2f60 100644 --- a/src/RecordComponent.cpp +++ b/src/RecordComponent.cpp @@ -255,6 +255,10 @@ bool RecordComponent::empty() const void RecordComponent::flush( std::string const &name, internal::FlushParams const &flushParams) { + if (!dirtyRecursive()) + { + return; + } auto &rc = get(); if (flushParams.flushLevel == FlushLevel::SkeletonOnly) { diff --git a/src/backend/BaseRecord.cpp b/src/backend/BaseRecord.cpp index 111cdab61b..9467701a2a 100644 --- a/src/backend/BaseRecord.cpp +++ b/src/backend/BaseRecord.cpp @@ -819,6 +819,11 @@ template inline void BaseRecord::flush( std::string const &name, internal::FlushParams const &flushParams) { + if (!this->dirtyRecursive()) + { + return; + } + if (!this->written() && this->empty() && !this->datasetDefined()) throw std::runtime_error( "A Record can not be written without any contained " diff --git a/src/backend/MeshRecordComponent.cpp b/src/backend/MeshRecordComponent.cpp index 827102ad32..947db30f7c 100644 --- a/src/backend/MeshRecordComponent.cpp +++ b/src/backend/MeshRecordComponent.cpp @@ -72,6 +72,10 @@ void MeshRecordComponent::read() void MeshRecordComponent::flush( std::string const &name, internal::FlushParams const ¶ms) { + if (!dirtyRecursive()) + { + return; + } if (access::write(IOHandler()->m_frontendAccess) && !containsAttribute("position")) { diff --git a/src/backend/PatchRecord.cpp b/src/backend/PatchRecord.cpp index 2a6581e56d..e674828181 100644 --- a/src/backend/PatchRecord.cpp +++ b/src/backend/PatchRecord.cpp @@ -41,6 +41,10 @@ PatchRecord::setUnitDimension(std::map const &udim) void PatchRecord::flush_impl( std::string const &path, internal::FlushParams const &flushParams) { + if (!dirtyRecursive()) + { + return; + } if (!this->datasetDefined()) { if (IOHandler()->m_frontendAccess != Access::READ_ONLY)