Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
b58d44a
Flush structural info of resetDataset() to backend immediately
franzpoeschel Mar 11, 2026
874e8e1
Erase flushMeshes/ParticlesPath
franzpoeschel Mar 11, 2026
a350eb0
Move flushing from storeChunk to resetDataset
franzpoeschel Mar 11, 2026
7fa990d
Hmm, move CREATE_DATASET task back to storeChunk
franzpoeschel Mar 12, 2026
3f1db50
Fix attribute flushing logic
franzpoeschel Mar 12, 2026
3f8aa71
flush mode helpers
franzpoeschel Jan 14, 2026
724c098
Fix dirty handling
franzpoeschel Jan 14, 2026
e6ca360
Add TODO comment
franzpoeschel Mar 12, 2026
50d0214
WIP Runtime verification of flush level
franzpoeschel Mar 12, 2026
fd97745
dont flush to IO handler yet in resetDataset
franzpoeschel Mar 13, 2026
c30b278
Revert "dont flush to IO handler yet in resetDataset"
franzpoeschel Mar 13, 2026
426a8de
Continue fixing and breaking things..
franzpoeschel Mar 13, 2026
9bf742f
Fix API call after rebase
franzpoeschel Mar 16, 2026
78ed217
Fix dirty handling filebased
franzpoeschel Mar 16, 2026
3406ad9
TMP REVERT ME: deactivate span table tests
franzpoeschel Mar 16, 2026
931e9e9
TMP REVERT ME take out hanging parallel test
franzpoeschel Mar 16, 2026
769965d
Fix ranktable logic
franzpoeschel Mar 27, 2026
f94d882
Take out the next hanging parallel test
franzpoeschel Mar 27, 2026
a572f33
Separate MPI tests by MPI barriers
franzpoeschel Mar 27, 2026
3dd8d66
Fix wrong MPI_COMM_WORLD
franzpoeschel Mar 27, 2026
665a3b1
wip: debugging state
franzpoeschel Mar 27, 2026
5eb80e5
deactivate malicious tests
franzpoeschel Mar 30, 2026
300506f
Revert "deactivate malicious tests"
franzpoeschel Mar 30, 2026
99be82c
Revert "wip: debugging state"
franzpoeschel Mar 30, 2026
f24fcdb
Revert "TMP REVERT ME take out hanging parallel test"
franzpoeschel Mar 30, 2026
e6d81c7
Revert some WIPs
franzpoeschel Mar 30, 2026
8d72468
Use an Attributable per Iteration for rankTable in filebased encoding
franzpoeschel May 19, 2026
a67f869
fix nompi builds
franzpoeschel May 20, 2026
257949e
CI fixes
franzpoeschel May 20, 2026
503e53a
Activate test again
franzpoeschel May 20, 2026
e248ab8
Guard against any internal unsetDirty operation
franzpoeschel Jul 8, 2026
e1c2670
Span API: more precise written and error checks
franzpoeschel Jul 8, 2026
000bee6
Revert the defer stuff
franzpoeschel Jul 13, 2026
c06caf5
dont enforce flush upon reset dataset
franzpoeschel Jul 13, 2026
cea11c9
keep only the false branch
franzpoeschel Jul 13, 2026
bc00986
docs
franzpoeschel Jul 20, 2026
94b3589
Keep a list of children per Attributable
franzpoeschel Apr 30, 2026
fcfd6bd
Steal CustomHierarchy.hpp from old branch
franzpoeschel May 5, 2026
44d6c8d
Add DeferredInitPolicy
franzpoeschel May 6, 2026
88d3739
Derive CustomHierarchy from Container<CustomHierarchy>
franzpoeschel May 6, 2026
7a984c9
Untested: reopening as custom hierarchy might work now
franzpoeschel May 6, 2026
0112c73
little test
franzpoeschel May 6, 2026
ce88a22
Emplace custom classes into backend hierarchy
franzpoeschel May 6, 2026
dbe4a44
wip: reading
franzpoeschel May 7, 2026
cd29227
Seem like CustomHierarchy::read() is now somewhat working lmao
franzpoeschel May 7, 2026
94fe295
Sync state more carefully
franzpoeschel May 8, 2026
9aff012
Recursive reading
franzpoeschel May 8, 2026
0a5f5fb
TODO comments
franzpoeschel May 8, 2026
db78b91
object storage for custom hierarchies
franzpoeschel May 11, 2026
0727752
Fix object storage
franzpoeschel May 11, 2026
9b6faf3
Add preferCurrentBackpointer
franzpoeschel May 11, 2026
c791158
TMP: example changes
franzpoeschel May 11, 2026
ff672c9
WIP customHierarchyFlush
franzpoeschel May 11, 2026
25fe3f8
Guard against unset meshes/particles path
franzpoeschel May 12, 2026
429c7a5
Fix custom hierarchy flushing
franzpoeschel May 18, 2026
b1360ed
Cleanup
franzpoeschel May 18, 2026
2249cc1
Rename
franzpoeschel May 18, 2026
fb269cb
Add custom hierarchy flush at series level
franzpoeschel May 18, 2026
41ef215
Rudimentary test, to be extended
franzpoeschel May 18, 2026
ec05768
Fix ADIOS2 path creation relative to /
franzpoeschel May 18, 2026
a5f8df6
Reading test
franzpoeschel May 18, 2026
e70b45a
Add more CustomHierarchyFlush operations
franzpoeschel May 18, 2026
81c365d
Add series.iterations to test
franzpoeschel May 18, 2026
8a0304a
explain that nonsense lmao
franzpoeschel May 20, 2026
7538b6d
Untested rudimentary support for Datasets
franzpoeschel Jul 17, 2026
b9d4f4c
Also support resizing across instances
franzpoeschel Jul 17, 2026
236c38c
Add todo note
franzpoeschel Jul 17, 2026
5ca7372
Support writing custom datasets
franzpoeschel Jul 20, 2026
855ff65
Support reading custom datasets
franzpoeschel Jul 20, 2026
7fa4905
Fix tests / examples
franzpoeschel Jul 20, 2026
2a8dd64
cleanup
franzpoeschel Jul 20, 2026
2ef763b
WIP: Merge new backend structures
franzpoeschel Jul 20, 2026
64c6248
we are getting close
franzpoeschel Jul 21, 2026
ce80816
Some fixes
franzpoeschel Jul 21, 2026
c96cf5e
put group meta info into writable
franzpoeschel Jul 21, 2026
3658077
Fixes
franzpoeschel Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ include(${openPMD_SOURCE_DIR}/cmake/dependencies/pybind11.cmake)
set(CORE_SOURCE
src/config.cpp
src/ChunkInfo.cpp
src/CustomHierarchy.cpp
src/Dataset.cpp
src/Datatype.cpp
src/Error.cpp
Expand Down Expand Up @@ -866,6 +867,7 @@ if(openPMD_BUILD_TESTING)
list(APPEND ${out_list}
test/Files_Core/automatic_variable_encoding.cpp
test/Files_Core/read_nonexistent_attribute.cpp
test/Files_Core/custom_hierarchy.cpp
)
endif()
endmacro()
Expand Down
190 changes: 190 additions & 0 deletions include/openPMD/CustomHierarchy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/* Copyright 2023 Franz Poeschel
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include "openPMD/Error.hpp"
#include "openPMD/IO/AbstractIOHandler.hpp"
#include "openPMD/Mesh.hpp"
#include "openPMD/ParticleSpecies.hpp"
#include "openPMD/RecordComponent.hpp"
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/Writable.hpp"

#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>

namespace openPMD
{
class CustomHierarchy;
namespace internal
{
using CustomHierarchyData = ContainerData<Attributable>;
} // namespace internal

class CustomHierarchy;

/*
* This is its own class, so the return value of asContainerOf() is also
* convsertible again.
*/
template <typename MappedType>
class ConvertibleContainer : public Container<MappedType>
{
template <typename>
friend class ConversibleContainer;
friend class CustomHierarchy;

protected:
using Container_t = Container<MappedType>;
using Data_t = internal::ContainerData<MappedType>;
static_assert(
std::is_base_of_v<typename Container_t::ContainerData, Data_t>);

using Container_t::Container_t;

private:
explicit ConvertibleContainer() = default;

public:
auto asDataset() -> RecordComponent;
// TODO also: asContainerOf()
};

namespace traits
{
template <>
struct DeferredInitPolicy<Container<CustomHierarchy>>
{
template <typename Container_const_or_not>
static void call(Container_const_or_not &);
};

template <>
struct GenerationPolicy<CustomHierarchy>
{
constexpr static bool is_noop = false;
template <typename Container, typename Iterator>
void operator()(Container &cont, Iterator &it)
{
auto &writable = it->second.writable();

// These should be different
auto child_shared_data = &it->second.Attributable::get();
auto parent_shared_data = &cont.Attributable::get();
if (child_shared_data == parent_shared_data)
{
throw std::runtime_error(
"Trying to emplace object as its own child");
}

// These might be different, but might also be the same
//
// For an explanation, ref. the documentation of
// Writable::attributable: This is a pointer back to the first
// created Attributable instance linking this Writable. There might
// be multiple Attributable objects linking the same backend
// Writable object when opening multiple "views" on the same backend
// object, e.g. when a scalar Record is at the same time a
// RecordComponent, or when reopening an object as a
// CustomHierarchy.
//
// Since CustomHierarchy performs no memory management by default,
// we must ensure that the backpointer in Writable::attributable
// remains valid when the frontend instance pointed by
// Writable::attributable *is* the CustomHierarchy instance (happens
// when it is the first frontend object created for that backend
// object).
auto backpointer = writable.attributable;
auto emplaced_pointer = it->second.m_attri.get();
auto *group_metadata =
(**cont.m_attri).m_writable.objectType.requireGroup();
if (backpointer == emplaced_pointer)
{
group_metadata
->m_children_managed_as_custom_hierarchy[it->first] =
// NO move!! The iterator must stay alive
std::make_shared<CustomHierarchy>(it->second);
}
}
};
} // namespace traits

// If we want to break the DeferredInitPolicy logic, we may alternatively derive
// this privately from ConvertibleContainer<Attributable>, and then overload
// access operators to return CustomHierarchy instances
class CustomHierarchy : public ConvertibleContainer<CustomHierarchy>
{
friend class Iteration;
friend class Container<CustomHierarchy>;
friend class Attributable;
friend struct traits::DeferredInitPolicy<Container<CustomHierarchy>>;

private:
using Parent_t = ConvertibleContainer<CustomHierarchy>;
using Container_t = typename Parent_t::Container_t;
using Data_t = typename Parent_t::Data_t;

protected:
CustomHierarchy(NoInit);
CustomHierarchy(std::shared_ptr<internal::SharedAttributableData> other);
CustomHierarchy(Attributable const &other);

void read(std::vector<std::string> &currentPath);

void flush_internal(
internal::FlushParams const &, std::vector<std::string> currentPath);
void flush(std::string const &path, internal::FlushParams const &) override;

/**
* @brief Link with parent.
*
* @param w The Writable representing the parent.
*/
void linkHierarchy(Writable &w) override;

public:
CustomHierarchy();

CustomHierarchy(CustomHierarchy const &other) = default;
CustomHierarchy(CustomHierarchy &&other) = default;

CustomHierarchy &operator=(CustomHierarchy const &) = default;
CustomHierarchy &operator=(CustomHierarchy &&) = default;

// TODO should we automatically read upon returning / instantiating a
// CustomHierarchy object? i.e. upon Attributable::customHierarchy() and
// CustomHierarchy::operator[]().
//
// set max_recursion_depth = 0 for infinite cycling
// recursion depth includes the current object
// recursion will not continue expanding into regions that are already known
// (hence not transitively expand into unknown subregions of known regions)
auto read(size_t max_recursion_depth = 1) -> CustomHierarchy;

void printRecursively();

private:
void printRecursively(std::string indent);
};
} // namespace openPMD
62 changes: 62 additions & 0 deletions include/openPMD/IO/AbstractIOHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "openPMD/IterationEncoding.hpp"
#include "openPMD/config.hpp"
#include "openPMD/version.hpp"
#include <ostream>

#if openPMD_HAVE_MPI
#include <mpi.h>
Expand Down Expand Up @@ -81,6 +82,66 @@ enum class FlushLevel
CreateOrOpenFiles
};

std::ostream &operator<<(std::ostream &, FlushLevel);

namespace flush_level
{
inline constexpr auto global_flushpoint(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
return true;
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
// same as global_flushpoint for now, but we will soon introduce
// immediate_flush
inline constexpr auto write_datasets(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
return true;
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
inline constexpr auto write_attributes(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
case FlushLevel::InternalFlush:
return true;
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
inline constexpr auto flush_hierarchy(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
return true;
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
} // namespace flush_level

enum class OpenpmdStandard
{
v_1_0_0,
Expand Down Expand Up @@ -121,6 +182,7 @@ namespace internal
* To be used for reading
*/
FlushParams const defaultFlushParams{};
FlushParams const publicFlush{FlushLevel::UserFlush};

struct ParsedFlushParams;

Expand Down
2 changes: 1 addition & 1 deletion include/openPMD/IO/AbstractIOHandlerImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class AbstractIOHandlerImpl

virtual ~AbstractIOHandlerImpl() = default;

std::future<void> flush();
std::future<void> flush(FlushLevel);

/**
* Close the file corresponding with the writable and release file handles.
Expand Down
3 changes: 3 additions & 0 deletions include/openPMD/IO/IOTask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <cstddef>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>
#include <variant>
Expand Down Expand Up @@ -89,6 +90,8 @@ OPENPMDAPI_EXPORT_ENUM_CLASS(Operation){
}; // note: if you change the enum members here, please update
// docs/source/dev/design.rst

std::ostream &operator<<(std::ostream &os, Operation op);

namespace internal
{
/*
Expand Down
2 changes: 1 addition & 1 deletion include/openPMD/IO/JSON/JSONIOHandlerImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class JSONIOHandlerImpl : public AbstractIOHandlerImpl

void touch(Writable *, Parameter<Operation::TOUCH> const &) override;

std::future<void> flush();
std::future<void> flush(internal::ParsedFlushParams &params);

private:
#if openPMD_HAVE_MPI
Expand Down
21 changes: 12 additions & 9 deletions include/openPMD/Iteration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/HierarchyVisitor.hpp"
#include "openPMD/backend/PerIterationData.hpp"
#include "openPMD/backend/scientific_defaults/ScientificDefaults.hpp"

#include <cstdint>
Expand Down Expand Up @@ -122,14 +123,16 @@ namespace internal
*/
bool allow_reopening_implicitly = false;

/**
* Whether a step is currently active for this iteration.
* Used for file-based iteration layout, see Series.hpp for
* group-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
/*
* This stores data items that are:
*
* 1. global in group and variable encodings
* 2. per-iteration in file encoding
*
* The struct is stored as part of the Series and as part of each
* Iteration. Access must be distinguished by iteration encoding.
*/
StepStatus m_stepStatus = StepStatus::NoStep;
PerIterationData m_perIterationData;

/**
* Cached copy of the key under which this Iteration lives in
Expand Down Expand Up @@ -483,8 +486,8 @@ namespace traits
struct GenerationPolicy<Iteration>
{
constexpr static bool is_noop = false;
template <typename Iterator>
void operator()(Iterator &it)
template <typename Container, typename Iterator>
void operator()(Container &, Iterator &it)
{
it->second.get().m_iterationIndex = it->first;
}
Expand Down
4 changes: 2 additions & 2 deletions include/openPMD/ParticleSpecies.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ namespace traits
struct GenerationPolicy<ParticleSpecies>
{
constexpr static bool is_noop = false;
template <typename T>
void operator()(T &it)
template <typename Container, typename T>
void operator()(Container &, T &it)
{
it->second.particlePatches.linkHierarchy(it->second.writable());
}
Expand Down
Loading
Loading