From 8de441a6387f163a31e803b2453cec67e4efc76d Mon Sep 17 00:00:00 2001
From: Erik Schnetter
Date: Sun, 27 Jun 2021 14:45:00 -0400
Subject: [PATCH 01/94] Partial Julia bindings
---
CMakeLists.txt | 53 ++
src/binding/julia/Access.cpp | 12 +
src/binding/julia/Attributable.cpp | 22 +
src/binding/julia/Attribute.cpp | 14 +
src/binding/julia/BaseRecordComponent.cpp | 22 +
src/binding/julia/Container.cpp | 3 +
src/binding/julia/Container.hpp | 83 +++
src/binding/julia/Dataset.cpp | 23 +
src/binding/julia/Datatype.cpp | 35 +
src/binding/julia/Format.cpp | 18 +
src/binding/julia/Iteration.cpp | 30 +
src/binding/julia/Mesh.cpp | 72 ++
src/binding/julia/MeshRecordComponent.cpp | 22 +
src/binding/julia/RecordComponent.cpp | 89 +++
src/binding/julia/Series.cpp | 78 ++
src/binding/julia/UnitDimension.cpp | 16 +
src/binding/julia/WriteIterations.cpp | 17 +
src/binding/julia/defs.hpp | 150 ++++
src/binding/julia/openPMD.cpp | 49 ++
.../julia/openPMD.jl/.JuliaFormatter.toml | 10 +
.../julia/openPMD.jl/.github/workflows/CI.yml | 77 ++
src/binding/julia/openPMD.jl/.gitignore | 1 +
src/binding/julia/openPMD.jl/COPYING | 675 ++++++++++++++++++
src/binding/julia/openPMD.jl/COPYING.LESSER | 166 +++++
src/binding/julia/openPMD.jl/Project.toml | 14 +
src/binding/julia/openPMD.jl/docs/.gitignore | 2 +
.../julia/openPMD.jl/docs/Project.toml | 2 +
src/binding/julia/openPMD.jl/docs/make.jl | 11 +
.../julia/openPMD.jl/docs/src/index.md | 5 +
src/binding/julia/openPMD.jl/src/Access.jl | 12 +
.../julia/openPMD.jl/src/Attributable.jl | 86 +++
src/binding/julia/openPMD.jl/src/Attribute.jl | 25 +
.../openPMD.jl/src/BaseRecordComponent.jl | 28 +
src/binding/julia/openPMD.jl/src/Container.jl | 65 ++
src/binding/julia/openPMD.jl/src/Dataset.jl | 78 ++
src/binding/julia/openPMD.jl/src/Datatype.jl | 245 +++++++
src/binding/julia/openPMD.jl/src/Format.jl | 28 +
src/binding/julia/openPMD.jl/src/Iteration.jl | 58 ++
src/binding/julia/openPMD.jl/src/Mesh.jl | 140 ++++
.../openPMD.jl/src/MeshRecordComponent.jl | 33 +
.../julia/openPMD.jl/src/RecordComponent.jl | 82 +++
src/binding/julia/openPMD.jl/src/Series.jl | 159 +++++
.../julia/openPMD.jl/src/UnitDimension.jl | 18 +
.../julia/openPMD.jl/src/WriteIterations.jl | 13 +
src/binding/julia/openPMD.jl/src/openPMD.jl | 61 ++
src/binding/julia/openPMD.jl/src/version.jl | 34 +
src/binding/julia/openPMD.jl/test/Access.jl | 11 +
.../julia/openPMD.jl/test/Attributable.jl | 22 +
.../julia/openPMD.jl/test/Attribute.jl | 8 +
.../openPMD.jl/test/BaseRecordComponent.jl | 10 +
.../julia/openPMD.jl/test/Container.jl | 33 +
src/binding/julia/openPMD.jl/test/Dataset.jl | 7 +
src/binding/julia/openPMD.jl/test/Datatype.jl | 83 +++
src/binding/julia/openPMD.jl/test/Format.jl | 24 +
.../julia/openPMD.jl/test/Iteration.jl | 22 +
src/binding/julia/openPMD.jl/test/Mesh.jl | 14 +
.../openPMD.jl/test/MeshRecordComponent.jl | 14 +
.../julia/openPMD.jl/test/RecordComponent.jl | 7 +
src/binding/julia/openPMD.jl/test/Series.jl | 77 ++
.../julia/openPMD.jl/test/UnitDimension.jl | 15 +
.../julia/openPMD.jl/test/WriteIterations.jl | 11 +
src/binding/julia/openPMD.jl/test/runtests.jl | 48 ++
src/binding/julia/openPMD.jl/test/version.jl | 12 +
src/binding/julia/version.cpp | 12 +
64 files changed, 3366 insertions(+)
create mode 100644 src/binding/julia/Access.cpp
create mode 100644 src/binding/julia/Attributable.cpp
create mode 100644 src/binding/julia/Attribute.cpp
create mode 100644 src/binding/julia/BaseRecordComponent.cpp
create mode 100644 src/binding/julia/Container.cpp
create mode 100644 src/binding/julia/Container.hpp
create mode 100644 src/binding/julia/Dataset.cpp
create mode 100644 src/binding/julia/Datatype.cpp
create mode 100644 src/binding/julia/Format.cpp
create mode 100644 src/binding/julia/Iteration.cpp
create mode 100644 src/binding/julia/Mesh.cpp
create mode 100644 src/binding/julia/MeshRecordComponent.cpp
create mode 100644 src/binding/julia/RecordComponent.cpp
create mode 100644 src/binding/julia/Series.cpp
create mode 100644 src/binding/julia/UnitDimension.cpp
create mode 100644 src/binding/julia/WriteIterations.cpp
create mode 100644 src/binding/julia/defs.hpp
create mode 100644 src/binding/julia/openPMD.cpp
create mode 100644 src/binding/julia/openPMD.jl/.JuliaFormatter.toml
create mode 100644 src/binding/julia/openPMD.jl/.github/workflows/CI.yml
create mode 100644 src/binding/julia/openPMD.jl/.gitignore
create mode 100644 src/binding/julia/openPMD.jl/COPYING
create mode 100644 src/binding/julia/openPMD.jl/COPYING.LESSER
create mode 100644 src/binding/julia/openPMD.jl/Project.toml
create mode 100644 src/binding/julia/openPMD.jl/docs/.gitignore
create mode 100644 src/binding/julia/openPMD.jl/docs/Project.toml
create mode 100644 src/binding/julia/openPMD.jl/docs/make.jl
create mode 100644 src/binding/julia/openPMD.jl/docs/src/index.md
create mode 100644 src/binding/julia/openPMD.jl/src/Access.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Attributable.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Attribute.jl
create mode 100644 src/binding/julia/openPMD.jl/src/BaseRecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Container.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Dataset.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Datatype.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Format.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Iteration.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Mesh.jl
create mode 100644 src/binding/julia/openPMD.jl/src/MeshRecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/src/RecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/src/Series.jl
create mode 100644 src/binding/julia/openPMD.jl/src/UnitDimension.jl
create mode 100644 src/binding/julia/openPMD.jl/src/WriteIterations.jl
create mode 100644 src/binding/julia/openPMD.jl/src/openPMD.jl
create mode 100644 src/binding/julia/openPMD.jl/src/version.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Access.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Attributable.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Attribute.jl
create mode 100644 src/binding/julia/openPMD.jl/test/BaseRecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Container.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Dataset.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Datatype.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Format.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Iteration.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Mesh.jl
create mode 100644 src/binding/julia/openPMD.jl/test/MeshRecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/test/RecordComponent.jl
create mode 100644 src/binding/julia/openPMD.jl/test/Series.jl
create mode 100644 src/binding/julia/openPMD.jl/test/UnitDimension.jl
create mode 100644 src/binding/julia/openPMD.jl/test/WriteIterations.jl
create mode 100644 src/binding/julia/openPMD.jl/test/runtests.jl
create mode 100644 src/binding/julia/openPMD.jl/test/version.jl
create mode 100644 src/binding/julia/version.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae1dc79983..def77ef0ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,7 @@ openpmd_option(MPI "Parallel, Multi-Node I/O for clusters" AUTO)
openpmd_option(HDF5 "HDF5 backend (.h5 files)" AUTO)
openpmd_option(ADIOS1 "ADIOS1 backend (.bp files)" AUTO)
openpmd_option(ADIOS2 "ADIOS2 backend (.bp files)" AUTO)
+openpmd_option(JULIA "Enable Julia bindings" AUTO)
openpmd_option(PYTHON "Enable Python bindings" AUTO)
option(openPMD_INSTALL "Add installation targets" ON)
@@ -283,6 +284,34 @@ endif()
# TODO: Check if ADIOS2 is parallel when openPMD_HAVE_MPI is ON
+# External library: libcxxwrap-julia
+if(openPMD_USE_JULIA STREQUAL AUTO)
+ find_package(JlCxx 0.8.3)
+ if(JlCxx_FOUND)
+ set(openPMD_HAVE_JlCxx TRUE)
+ else()
+ set(openPMD_HAVE_JlCxx FALSE)
+ endif()
+ if(JULIA_FOUND)
+ set(openPMD_HAVE_JULIA TRUE)
+ else()
+ set(openPMD_HAVE_JULIA FALSE)
+ endif()
+elseif(openPMD_USE_JULIA)
+ find_package(JlCxx 0.8.3 REQUIRED)
+ set(openPMD_HAVE_JULIA TRUE)
+ set(openPMD_HAVE_JlCxx TRUE)
+else()
+ set(openPMD_HAVE_JULIA FALSE)
+ set(openPMD_HAVE_JlCxx FALSE)
+endif()
+if(openPMD_HAVE_JlCxx)
+ get_target_property(JlCxx_location JlCxx::cxxwrap_julia LOCATION)
+ get_filename_component(JlCxx_location ${JlCxx_location} DIRECTORY)
+ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${JlCxx_location}")
+ message(STATUS "Found JlCxx version ${JlCxx_VERSION} at ${JlCxx_location}")
+endif()
+
# external library: pybind11 (optional)
set(_PY_DEV_MODULE Development.Module)
if(CMAKE_VERSION VERSION_LESS 3.18.0)
@@ -574,6 +603,30 @@ else()
target_compile_definitions(openPMD PRIVATE openPMD_USE_VERIFY=0)
endif()
+# Julia bindings
+if(openPMD_HAVE_JlCxx)
+ add_library(openPMD_jl SHARED
+ src/binding/julia/Access.cpp
+ src/binding/julia/Attributable.cpp
+ src/binding/julia/Attribute.cpp
+ src/binding/julia/BaseRecordComponent.cpp
+ src/binding/julia/Container.cpp
+ src/binding/julia/Dataset.cpp
+ src/binding/julia/Datatype.cpp
+ src/binding/julia/Format.cpp
+ src/binding/julia/Iteration.cpp
+ src/binding/julia/Mesh.cpp
+ src/binding/julia/MeshRecordComponent.cpp
+ src/binding/julia/RecordComponent.cpp
+ src/binding/julia/Series.cpp
+ src/binding/julia/UnitDimension.cpp
+ src/binding/julia/WriteIterations.cpp
+ src/binding/julia/openPMD.cpp
+ src/binding/julia/version.cpp
+ )
+ target_link_libraries(openPMD_jl PRIVATE openPMD JlCxx::cxxwrap_julia JlCxx::cxxwrap_julia_stl)
+endif()
+
# python bindings
if(openPMD_HAVE_PYTHON)
add_library(openPMD.py MODULE
diff --git a/src/binding/julia/Access.cpp b/src/binding/julia/Access.cpp
new file mode 100644
index 0000000000..2940c99001
--- /dev/null
+++ b/src/binding/julia/Access.cpp
@@ -0,0 +1,12 @@
+// IO/Access
+
+#include "defs.hpp"
+
+void define_julia_Access(jlcxx::Module &mod) {
+ mod.add_bits("Access", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("READ_ONLY", Access::READ_ONLY);
+ mod.set_const("READ_WRITE", Access::READ_WRITE);
+ mod.set_const("CREATE", Access::CREATE);
+}
diff --git a/src/binding/julia/Attributable.cpp b/src/binding/julia/Attributable.cpp
new file mode 100644
index 0000000000..ec5d398c71
--- /dev/null
+++ b/src/binding/julia/Attributable.cpp
@@ -0,0 +1,22 @@
+// Attributable
+
+#include "defs.hpp"
+
+void define_julia_Attributable(jlcxx::Module &mod) {
+ auto type = mod.add_type("Attributable");
+
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("set_attribute1_" NAME "!", &Attributable::setAttribute);
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+
+ type.method("get_attribute1", &Attributable::getAttribute);
+ type.method("delete_attribute!", &Attributable::deleteAttribute);
+ type.method("attributes", &Attributable::attributes);
+ type.method("num_attributes1", &Attributable::numAttributes);
+ type.method("contains_attribute", &Attributable::containsAttribute);
+ type.method("comment", &Attributable::comment);
+ type.method("set_comment!", &Attributable::setComment);
+ type.method("series_flush", static_cast(
+ &Attributable::seriesFlush));
+}
diff --git a/src/binding/julia/Attribute.cpp b/src/binding/julia/Attribute.cpp
new file mode 100644
index 0000000000..b9f0e82e94
--- /dev/null
+++ b/src/binding/julia/Attribute.cpp
@@ -0,0 +1,14 @@
+// Attribute
+
+#include "defs.hpp"
+
+void define_julia_Attribute(jlcxx::Module &mod) {
+ auto type = mod.add_type("Attribute");
+
+ type.method("dtype1", [](const Attribute &attr) { return attr.dtype; });
+
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("get1_" NAME, &Attribute::get);
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+}
diff --git a/src/binding/julia/BaseRecordComponent.cpp b/src/binding/julia/BaseRecordComponent.cpp
new file mode 100644
index 0000000000..ade27dbc8c
--- /dev/null
+++ b/src/binding/julia/BaseRecordComponent.cpp
@@ -0,0 +1,22 @@
+// BaseRecordComponent
+
+#include "defs.hpp"
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType {
+ typedef Attributable type;
+};
+} // namespace jlcxx
+
+void define_julia_BaseRecordComponent(jlcxx::Module &mod) {
+
+ auto type = mod.add_type(
+ "BaseRecordComponent", jlcxx::julia_base_type());
+
+ type.method("unit_SI", &BaseRecordComponent::unitSI);
+ type.method("reset_datatype1!", &BaseRecordComponent::resetDatatype);
+ type.method("get_datatype1", &BaseRecordComponent::getDatatype);
+ type.method("is_constant", &BaseRecordComponent::constant);
+ // TODO: availableChunks
+}
diff --git a/src/binding/julia/Container.cpp b/src/binding/julia/Container.cpp
new file mode 100644
index 0000000000..ab2fc2cb18
--- /dev/null
+++ b/src/binding/julia/Container.cpp
@@ -0,0 +1,3 @@
+#include "Container.hpp"
+
+std::unique_ptr julia_Container_type;
diff --git a/src/binding/julia/Container.hpp b/src/binding/julia/Container.hpp
new file mode 100644
index 0000000000..f5af677dcc
--- /dev/null
+++ b/src/binding/julia/Container.hpp
@@ -0,0 +1,83 @@
+#ifndef CONTAINER_HPP
+#define CONTAINER_HPP
+
+// Container
+
+#include "defs.hpp"
+
+#include
+#include
+
+// Define supertype relationships
+namespace jlcxx {
+template struct SuperType> {
+ typedef Attributable type;
+};
+} // namespace jlcxx
+
+// TODO: use std::optional instead of std::unique_ptr
+typedef jlcxx::TypeWrapper<
+ jlcxx::Parametric, jlcxx::TypeVar<2>>>
+ julia_Container_type_t;
+extern std::unique_ptr julia_Container_type;
+
+template
+void define_julia_Container(jlcxx::Module &mod) {
+ if (!julia_Container_type)
+ julia_Container_type = std::make_unique(
+ mod.add_type, jlcxx::TypeVar<2>>>(
+ "Container", jlcxx::julia_base_type()));
+
+ julia_Container_type->apply>([](auto type) {
+ using ContainerT = typename decltype(type)::type;
+ using key_type = typename ContainerT::key_type;
+ using mapped_type = typename ContainerT::mapped_type;
+ using size_type = typename ContainerT::size_type;
+ static_assert(std::is_same_v);
+ static_assert(std::is_same_v);
+
+ type.template constructor();
+
+ type.method("empty1", &ContainerT::empty);
+ type.method("length1", &ContainerT::size);
+ type.method("empty1!", &ContainerT::clear);
+ type.method("getindex1",
+ static_cast(
+ &ContainerT::at));
+ type.method("get1!",
+ [](ContainerT &cont, const key_type &key) -> mapped_type & {
+ return cont[key];
+ });
+ type.method("setindex1!",
+ [](ContainerT &cont, const mapped_type &value,
+ const key_type &key) { return cont[key] = value; });
+ type.method("count1", &ContainerT::count);
+ type.method("contains1", &ContainerT::contains);
+ type.method("delete1!",
+ static_cast(
+ &ContainerT::erase));
+ type.method("keys1", [](const ContainerT &cont) {
+ std::vector res;
+ res.reserve(cont.size());
+ for (auto iter = cont.begin(); iter != cont.end(); ++iter)
+ res.push_back(iter->first);
+ return res;
+ });
+ // type.method("values1", [](const ContainerT &cont) {
+ // std::vector res;
+ // res.reserve(cont.size());
+ // for (auto iter = cont.begin(); iter != cont.end(); ++iter)
+ // res.push_back(&iter->second);
+ // return res;
+ // });
+ // type.method("collect1", [](const ContainerT &cont) {
+ // std::vector> res;
+ // res.reserve(cont.size());
+ // for (auto iter = cont.begin(); iter != cont.end(); ++iter)
+ // res.emplace_back(iter->first, &iter->second);
+ // return res;
+ // });
+ });
+}
+
+#endif // #ifndef CONTAINER_HPP
diff --git a/src/binding/julia/Dataset.cpp b/src/binding/julia/Dataset.cpp
new file mode 100644
index 0000000000..1e0638d243
--- /dev/null
+++ b/src/binding/julia/Dataset.cpp
@@ -0,0 +1,23 @@
+// Dataset
+
+#include "defs.hpp"
+
+void define_julia_Dataset(jlcxx::Module &mod) {
+ auto type = mod.add_type("Dataset");
+
+ type.constructor();
+ type.constructor();
+ type.constructor();
+
+ type.method("extend!", &Dataset::extend);
+ type.method("set_chunk_size!", &Dataset::setChunkSize);
+ type.method("set_compression!", &Dataset::setCompression);
+ type.method("set_custom_transform!", &Dataset::setCustomTransform);
+ type.method("extent1", [](const Dataset &d) { return d.extent; });
+ type.method("dtype1", [](const Dataset &d) { return d.dtype; });
+ type.method("rank1", [](const Dataset &d) { return d.rank; });
+ type.method("chunk_size1", [](const Dataset &d) { return d.chunkSize; });
+ type.method("compression", [](const Dataset &d) { return d.compression; });
+ type.method("transform", [](const Dataset &d) { return d.transform; });
+ type.method("options", [](const Dataset &d) { return d.options; });
+}
diff --git a/src/binding/julia/Datatype.cpp b/src/binding/julia/Datatype.cpp
new file mode 100644
index 0000000000..8f46f80c2c
--- /dev/null
+++ b/src/binding/julia/Datatype.cpp
@@ -0,0 +1,35 @@
+// Datatype
+
+#include "defs.hpp"
+
+void define_julia_Datatype(jlcxx::Module &mod) {
+ mod.add_bits("Datatype", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+#define USE_TYPE(NAME, ENUM, TYPE) mod.set_const(NAME, ENUM);
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+ mod.set_const("DATATYPE", Datatype::DATATYPE);
+ mod.set_const("UNDEFINED", Datatype::UNDEFINED);
+
+ mod.set_const("openPMD_datatypes", openPMD_Datatypes);
+ // mod.method("determine_datatype", determineDatatype);
+ mod.method("to_bytes1", toBytes);
+ mod.method("to_bits1", toBits);
+ mod.method("is_vector1", isVector);
+ mod.method("is_floating_point1", (bool (*)(Datatype))isFloatingPoint);
+ mod.method("is_complex_floating_point1",
+ static_cast(isComplexFloatingPoint));
+ mod.method("is_integer1", (std::tuple(*)(Datatype))isInteger);
+ // isSameFloatingPoint
+ // isSameComplexFloatingPoint
+ // isSameInteger
+ mod.method("is_same1", isSame);
+ mod.method("basic_datatype1", basicDatatype);
+ mod.method("to_vector_type1", toVectorType);
+ mod.method("datatype_to_string1", datatypeToString);
+ mod.method("string_to_datatype1", stringToDatatype);
+ mod.method("warn_wrong_datatype1", warnWrongDtype);
+ // mod.method("==", operator==);
+ // mod.method("!=", operator!=);
+}
diff --git a/src/binding/julia/Format.cpp b/src/binding/julia/Format.cpp
new file mode 100644
index 0000000000..dec3d96eec
--- /dev/null
+++ b/src/binding/julia/Format.cpp
@@ -0,0 +1,18 @@
+// IO/Format
+
+#include "defs.hpp"
+
+void define_julia_Format(jlcxx::Module &mod) {
+ mod.add_bits("Format", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("HDF5", Format::HDF5);
+ mod.set_const("ADIOS1", Format::ADIOS1);
+ mod.set_const("ADIOS2", Format::ADIOS2);
+ mod.set_const("ADIOS2_SST", Format::ADIOS2_SST);
+ mod.set_const("ADIOS2_SSC", Format::ADIOS2_SSC);
+ mod.set_const("JSON", Format::JSON);
+ mod.set_const("DUMMY", Format::DUMMY);
+ mod.method("determine_format", determineFormat);
+ mod.method("suffix", suffix);
+}
diff --git a/src/binding/julia/Iteration.cpp b/src/binding/julia/Iteration.cpp
new file mode 100644
index 0000000000..6ff8c1de3f
--- /dev/null
+++ b/src/binding/julia/Iteration.cpp
@@ -0,0 +1,30 @@
+// Iteration
+
+#include "defs.hpp"
+
+#include
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType { typedef Attributable type; };
+} // namespace jlcxx
+
+void define_julia_Iteration(jlcxx::Module &mod) {
+ auto type = mod.add_type("Iteration",
+ jlcxx::julia_base_type());
+
+ type.method("time1", &Iteration::time);
+ type.method("set_time!", &Iteration::setTime);
+ type.method("dt", &Iteration::dt);
+ type.method("set_dt!", &Iteration::setDt);
+ type.method("time_unit_SI", &Iteration::timeUnitSI);
+ type.method("set_time_unit_SI!", &Iteration::setTimeUnitSI);
+ type.method("close1",
+ static_cast(&Iteration::close));
+ type.method("open", &Iteration::open);
+ type.method("closed", &Iteration::closed);
+ type.method("closed_by_writer", &Iteration::closedByWriter);
+ type.method("meshes",
+ [](Iteration &iter) -> Container & { return iter.meshes; });
+ // TODO: particles
+}
diff --git a/src/binding/julia/Mesh.cpp b/src/binding/julia/Mesh.cpp
new file mode 100644
index 0000000000..7a562cf602
--- /dev/null
+++ b/src/binding/julia/Mesh.cpp
@@ -0,0 +1,72 @@
+// Mesh
+
+#include "defs.hpp"
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType {
+ typedef Container type;
+};
+} // namespace jlcxx
+
+void define_julia_Mesh(jlcxx::Module &mod) {
+
+ // Mesh::Geometry
+ mod.add_bits("Geometry", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("cartesian", Mesh::Geometry::cartesian);
+ mod.set_const("theta_mode", Mesh::Geometry::thetaMode);
+ mod.set_const("cylindrical", Mesh::Geometry::cylindrical);
+ mod.set_const("spherical", Mesh::Geometry::spherical);
+ mod.set_const("other", Mesh::Geometry::other);
+
+ // Mesh::DataOrder
+ mod.add_bits("DataOrder", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("C", Mesh::DataOrder::C);
+ mod.set_const("F", Mesh::DataOrder::F);
+
+ // Mesh
+ auto type = mod.add_type(
+ "Mesh",
+ // We don't wrap BaseRecord for simplicity. We thus need to declare
+ // Container as our supertype.
+ jlcxx::julia_base_type>());
+
+ // These two functions come from our superclass
+ // BaseRecord. We declare them as if they were our own.
+ type.method("unit_dimension", &Mesh::unitDimension);
+ type.method("isscalar", &Mesh::scalar);
+
+ type.method("geometry", &Mesh::geometry);
+ type.method("set_geometry!", static_cast(
+ &Mesh::setGeometry));
+ type.method("geometry_parameters", &Mesh::geometryParameters);
+ type.method("set_geometry_parameters!", &Mesh::setGeometryParameters);
+ type.method("data_order", &Mesh::dataOrder);
+ type.method("set_data_order!", &Mesh::setDataOrder);
+ type.method("axis_labels", &Mesh::axisLabels);
+ type.method("set_axis_labels1!", &Mesh::setAxisLabels);
+ type.method("grid_spacing", &Mesh::gridSpacing);
+ type.method("set_grid_spacing1!", &Mesh::setGridSpacing);
+ type.method("grid_global_offset", &Mesh::gridGlobalOffset);
+ type.method("set_grid_global_offset1!", &Mesh::setGridGlobalOffset);
+ type.method("grid_unit_SI", &Mesh::gridUnitSI);
+ type.method("set_grid_unit_SI!", &Mesh::setGridUnitSI);
+ type.method("set_unit_dimension1!", [](Mesh &mesh,
+ const array7 &unitDimension) {
+ return mesh.setUnitDimension(std::map{
+ {UnitDimension::L, unitDimension[uint8_t(UnitDimension::L)]},
+ {UnitDimension::M, unitDimension[uint8_t(UnitDimension::M)]},
+ {UnitDimension::T, unitDimension[uint8_t(UnitDimension::T)]},
+ {UnitDimension::I, unitDimension[uint8_t(UnitDimension::I)]},
+ {UnitDimension::theta, unitDimension[uint8_t(UnitDimension::theta)]},
+ {UnitDimension::N, unitDimension[uint8_t(UnitDimension::N)]},
+ {UnitDimension::J, unitDimension[uint8_t(UnitDimension::J)]},
+ });
+ });
+ type.method("time_offset", &Mesh::timeOffset);
+ type.method("set_time_offset!", &Mesh::setTimeOffset);
+}
diff --git a/src/binding/julia/MeshRecordComponent.cpp b/src/binding/julia/MeshRecordComponent.cpp
new file mode 100644
index 0000000000..7a80e48225
--- /dev/null
+++ b/src/binding/julia/MeshRecordComponent.cpp
@@ -0,0 +1,22 @@
+// MeshRecordComponent
+
+#include "defs.hpp"
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType {
+ typedef RecordComponent type;
+};
+} // namespace jlcxx
+
+void define_julia_MeshRecordComponent(jlcxx::Module &mod) {
+ auto type = mod.add_type(
+ "MeshRecordComponent", jlcxx::julia_base_type());
+
+ type.method("position1", &MeshRecordComponent::position);
+ type.method("set_position1!", &MeshRecordComponent::setPosition);
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("make_constant1_" NAME, &MeshRecordComponent::makeConstant);
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+}
diff --git a/src/binding/julia/RecordComponent.cpp b/src/binding/julia/RecordComponent.cpp
new file mode 100644
index 0000000000..c3974e3ddc
--- /dev/null
+++ b/src/binding/julia/RecordComponent.cpp
@@ -0,0 +1,89 @@
+// RecordComponent
+
+#include "defs.hpp"
+
+#include
+#include
+#include
+#include
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType {
+ typedef BaseRecordComponent type;
+};
+} // namespace jlcxx
+
+namespace {
+template std::shared_ptr capture_vector(std::vector vec) {
+ if constexpr (std::is_same_v) {
+ // Copy the vector, because std::vector is special
+ T *dataptr = new T[vec.size()];
+ std::shared_ptr ptr(dataptr, std::default_delete());
+ std::copy(vec.begin(), vec.end(), dataptr);
+ return ptr;
+ } else {
+ // Capture the vector
+ T *dataptr = vec.data();
+ std::shared_ptr ptr(dataptr, [vec = std::move(vec)](T *p) {
+ /* We moved the vector into the anonymous function, and thus it will be
+ * destructed when the anonymous function is destructed. There is no need
+ * to call a destructor manually. */
+ });
+ return ptr;
+ }
+}
+} // namespace
+
+void define_julia_RecordComponent(jlcxx::Module &mod) {
+
+ // RecordComponent::Allocation
+ mod.add_bits("Allocation",
+ jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("USER", RecordComponent::Allocation::USER);
+ mod.set_const("API", RecordComponent::Allocation::API);
+ mod.set_const("AUTO", RecordComponent::Allocation::AUTO);
+
+ auto type = mod.add_type(
+ "RecordComponent", jlcxx::julia_base_type());
+
+ type.method("set_unit_SI!", &RecordComponent::setUnitSI);
+ type.method("reset_dataset!", &RecordComponent::resetDataset);
+ type.method("get_dimensionality1", &RecordComponent::getDimensionality);
+ type.method("get_extent1", &RecordComponent::getExtent);
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("make_constant1_" NAME, &RecordComponent::makeConstant);
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+ type.method(
+ "make_empty1",
+ static_cast(
+ &RecordComponent::makeEmpty));
+ type.method("empty1", &RecordComponent::empty);
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method( \
+ "load_chunk1_" NAME, \
+ static_cast (RecordComponent::*)(Offset, Extent)>( \
+ &RecordComponent::loadChunk));
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("store_chunk1_" NAME, \
+ static_cast, \
+ Offset, Extent)>( \
+ &RecordComponent::storeChunk));
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+#define USE_TYPE(NAME, ENUM, TYPE) \
+ type.method("store_chunk_copy1_" NAME, [](RecordComponent &comp, \
+ std::vector data, \
+ Offset offset, Extent extent) { \
+ std::shared_ptr ptr(capture_vector(std::move(data))); \
+ comp.storeChunk(std::move(ptr), std::move(offset), std::move(extent)); \
+ }); \
+ { FORALL_OPENPMD_TYPES }
+#undef USE_TYPE
+ type.method("SCALAR1", []() { return RecordComponent::SCALAR; });
+}
diff --git a/src/binding/julia/Series.cpp b/src/binding/julia/Series.cpp
new file mode 100644
index 0000000000..57a803c980
--- /dev/null
+++ b/src/binding/julia/Series.cpp
@@ -0,0 +1,78 @@
+// Series
+
+#include "defs.hpp"
+
+// Define supertype relationships
+namespace jlcxx {
+template <> struct SuperType { typedef Attributable type; };
+template <> struct SuperType { typedef SeriesImpl type; };
+} // namespace jlcxx
+
+void define_julia_Series(jlcxx::Module &mod) {
+
+ // SeriesImpl
+ {
+ auto type = mod.add_type(
+ "SeriesImpl", jlcxx::julia_base_type());
+
+ type.method("openPMD_version", &SeriesImpl::openPMD);
+ type.method("set_openPMD_version!", &SeriesImpl::setOpenPMD);
+ type.method("openPMD_extension", &SeriesImpl::openPMDextension);
+ type.method("set_openPMD_extension!", &SeriesImpl::setOpenPMDextension);
+ type.method("base_path", &SeriesImpl::basePath);
+ type.method("set_base_path!", &SeriesImpl::setBasePath);
+ type.method("meshes_path", &SeriesImpl::meshesPath);
+ type.method("set_meshes_path!", &SeriesImpl::setMeshesPath);
+ type.method("particles_path", &SeriesImpl::particlesPath);
+ type.method("set_particles_path!", &SeriesImpl::setParticlesPath);
+ type.method("author", &SeriesImpl::author);
+ type.method("set_author!", &SeriesImpl::setAuthor);
+ type.method("software", &SeriesImpl::software);
+ type.method("set_software!",
+ static_cast(
+ &SeriesImpl::setSoftware));
+ type.method("set_software!",
+ (SeriesImpl & (SeriesImpl::*)(std::string const &))(
+ &SeriesImpl::setSoftware));
+ type.method("software_version", &SeriesImpl::softwareVersion);
+ // type.method("set_software_version!", &SeriesImpl::setSoftwareVersion);
+ type.method("date", &SeriesImpl::date);
+ type.method("set_date!", &SeriesImpl::setDate);
+ type.method("software_dependencies", &SeriesImpl::softwareDependencies);
+ type.method("set_software_dependencies!",
+ &SeriesImpl::setSoftwareDependencies);
+ type.method("machine", &SeriesImpl::machine);
+ type.method("set_machine!", &SeriesImpl::setMachine);
+ // TODO: type.method("iteration_encoding", &SeriesImpl::iterationEncoding);
+ // TODO: type.method("set_iteration_encoding!",
+ // &SeriesImpl::setIterationEncoding);
+ type.method("iteration_format", &SeriesImpl::iterationFormat);
+ type.method("set_iteration_format!", &SeriesImpl::setIterationFormat);
+ type.method("name", &SeriesImpl::name);
+ type.method("set_name!", &SeriesImpl::setName);
+ type.method("backend", &SeriesImpl::backend);
+ type.method("flush1", &SeriesImpl::flush);
+ }
+
+ // Series
+
+ {
+ auto type =
+ mod.add_type("Series", jlcxx::julia_base_type());
+
+ type.constructor<>();
+#if openPMD_HAVE_MPI
+ type.constructor();
+ type.constructor();
+#endif
+ type.constructor();
+ type.constructor();
+
+ type.method("isvalid1", [](const Series &s) { return bool(s); });
+ // TODO: iterations
+ // TODO: readIterations
+ type.method("write_iterations", &Series::writeIterations);
+ }
+}
diff --git a/src/binding/julia/UnitDimension.cpp b/src/binding/julia/UnitDimension.cpp
new file mode 100644
index 0000000000..2225bcdddb
--- /dev/null
+++ b/src/binding/julia/UnitDimension.cpp
@@ -0,0 +1,16 @@
+// IO/UnitDimension
+
+#include "defs.hpp"
+
+void define_julia_UnitDimension(jlcxx::Module &mod) {
+ mod.add_bits("UnitDimension", jlcxx::julia_type("CppEnum"));
+ jlcxx::stl::apply_stl(mod);
+
+ mod.set_const("L", UnitDimension::L);
+ mod.set_const("M", UnitDimension::M);
+ mod.set_const("T", UnitDimension::T);
+ mod.set_const("I", UnitDimension::I);
+ mod.set_const("θ", UnitDimension::theta);
+ mod.set_const("N", UnitDimension::N);
+ mod.set_const("J", UnitDimension::J);
+}
diff --git a/src/binding/julia/WriteIterations.cpp b/src/binding/julia/WriteIterations.cpp
new file mode 100644
index 0000000000..8961c8fbee
--- /dev/null
+++ b/src/binding/julia/WriteIterations.cpp
@@ -0,0 +1,17 @@
+// WriteIterations
+
+#include "defs.hpp"
+
+#include
+
+void define_julia_WriteIterations(jlcxx::Module &mod) {
+ using iterations_t = Container;
+ using key_type = typename iterations_t::key_type;
+ using mapped_type = typename iterations_t::mapped_type;
+
+ auto type = mod.add_type("WriteIterations");
+ type.method("get1!",
+ [](WriteIterations &w, const key_type &k) -> Iteration & {
+ return w[k];
+ });
+}
diff --git a/src/binding/julia/defs.hpp b/src/binding/julia/defs.hpp
new file mode 100644
index 0000000000..75cebc0536
--- /dev/null
+++ b/src/binding/julia/defs.hpp
@@ -0,0 +1,150 @@
+#ifndef DEFS_HPP
+#define DEFS_HPP
+
+#include "openPMD/openPMD.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include