Skip to content
Draft

Hdf5 #783

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4a4879a
_Save(std::fstream) and _Load(std::fstream) become new more generic m…
manuschneider Apr 11, 2026
5d05e27
fixed bug: UniTensor::Load did not set the name of the UniTensor corr…
manuschneider Apr 11, 2026
f45c7c8
added pickle support, fixed MPS.Save() binding
manuschneider Apr 11, 2026
c00d238
added Load_, argument restore_device, and cleaned up the code and doc…
manuschneider Apr 28, 2026
1899e89
added hdf5 dependency, Type translations between Cytnx and HDF5 data …
manuschneider Apr 28, 2026
627acac
fixed typos and bugs
manuschneider Apr 28, 2026
020b729
Merge remote-tracking branch 'origin/master' into save_load
manuschneider Apr 28, 2026
f5350ef
added hdf5 support for Storage and Tensor
manuschneider Apr 28, 2026
5ff3887
established hdf5 framework; some implementations still missing
manuschneider Apr 29, 2026
3d36e25
HDF5 support for Bond implemented
manuschneider Apr 29, 2026
101f158
Merge remote-tracking branch 'origin/save_load' into hdf5
manuschneider Apr 29, 2026
a589b5b
fixed merge issues, removed pybindings for to_hdf5 and from_hdf5 beca…
manuschneider Apr 29, 2026
cf39fca
implemented file paths for Bond and Symmetry; Save and Load accept pa…
manuschneider Apr 30, 2026
b392265
fixed bugs, implemented Save/Load path for Tensor
manuschneider Apr 30, 2026
2406482
bug fixes when opening groups
manuschneider Apr 30, 2026
7b96872
groups are created without switching off HDF5 error messages
manuschneider May 1, 2026
f975f9c
replaced Symmetry.name() by Symmetry.getname() to be consistent with …
manuschneider May 1, 2026
261464f
enable reuse of space from deleted objects in HDF5 files; requires HD…
manuschneider May 2, 2026
5f110cc
using native HDF5 complex types; requires HDF5 2.0.0 or newer
manuschneider May 2, 2026
fc322a2
added save/load support for DenseUniTensor
manuschneider May 2, 2026
81d4c53
added HDF5 support for BlockUniTensor and BlockFermionicUniTensor
manuschneider May 2, 2026
4242b99
removed unused option to save Bonds without Symmetries; cleaned up code
manuschneider May 2, 2026
0d90499
bug fixes, github action uses hdf5, warnings if data requests GPU wit…
manuschneider May 2, 2026
fe622f0
added support for older versions of hdf5 without native complex types
manuschneider May 2, 2026
6a0683a
removed variable length array
manuschneider May 3, 2026
b76d918
fixed unit tests
manuschneider May 4, 2026
93a0835
Merge remote-tracking branch 'origin/master' into hdf5
manuschneider May 5, 2026
64b25e4
Merge remote-tracking branch 'origin/master' into save_load
manuschneider May 5, 2026
12609d7
added hdf5 to dependencies in github workflow
manuschneider May 5, 2026
19ac5b0
fixed issue
manuschneider May 5, 2026
13ad2a0
fixed pybind issues
manuschneider May 6, 2026
1f96612
added io namespace, implemented Save and Load there
manuschneider May 10, 2026
5be63fe
added save_attribute
manuschneider May 22, 2026
6952b18
moved more hdf5 saving functions into io namespace to avoid boilerplate
manuschneider May 22, 2026
fce5e49
fixed Load for UniTensor, Storage, MPS
manuschneider May 22, 2026
88353a0
implemented load functions for different datatypes in namespace io
manuschneider May 22, 2026
a606ef5
fixed error messages
manuschneider May 22, 2026
f65c3d5
Merge remote-tracking branch 'origin/master' into hdf5
manuschneider May 23, 2026
b001663
added unit tests
manuschneider May 25, 2026
122e16f
Merge remote-tracking branch 'origin/master' into save_load
manuschneider May 30, 2026
cbc7201
bug fixed in Storage.Fromfile: Nelem was used before being initialized
manuschneider May 30, 2026
b9a3620
Load_: fixes issues where previous data was not erased by Load_
manuschneider May 30, 2026
080e2d3
expose restore_device in pybind for MPS
manuschneider May 30, 2026
f54dfe8
Merge branch 'save_load' into hdf5
manuschneider May 31, 2026
dcaa86a
Merge remote-tracking branch 'origin/master' into hdf5
manuschneider May 31, 2026
edd46ad
fixed merging and ci issues
manuschneider May 31, 2026
822f311
added mising files
manuschneider May 31, 2026
7be8d9c
added hdf5 to the build wheels
manuschneider May 31, 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
3 changes: 2 additions & 1 deletion .github/workflows/ci-cmake_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ jobs:
# pyproject.toml as the single source of truth for everything
# Python.
run: |
mamba install _openmp_mutex=*=*_llvm cmake make boost git compilers blas=*=openblas liblapacke arpack gtest
mamba install _openmp_mutex=*=*_llvm cmake make boost git compilers blas=*=openblas liblapacke arpack gtest hdf5


- name: CPU info
run: lscpu
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/coverity-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ jobs:
- name: Install dependencies
shell: bash -l {0}
run: |
mamba install cmake make boost compilers blas=*=mkl pybind11 arpack
mamba config append channels conda-forge

cmake -S ${{github.workspace}} -B ${{github.workspace}}/build -DCMAKE_INSTALL_PREFIX=/home/runner/works/Cytnx_lib --preset=mkl-cpu
mamba install cmake make boost compilers hdf5 mkl mkl-include arpack

cmake -S ${{github.workspace}} -B ${{github.workspace}}/build \
-DCMAKE_INSTALL_PREFIX=/home/runner/works/Cytnx_lib \
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
-DHDF5_ROOT=$CONDA_PREFIX \
--preset=mkl-cpu -DBUILD_PYTHON=OFF
- name: Download Coverity Build Tool
shell: bash -l {0}
working-directory: ${{github.workspace}}/build
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ find_library(ARPACK_LIB arpack REQUIRED)
message(STATUS "Found ARPACK_LIB at: ${ARPACK_LIB}")
target_link_libraries(cytnx PRIVATE ${ARPACK_LIB})

#HDF5
find_package(HDF5 1.10.0 REQUIRED COMPONENTS CXX)
target_include_directories(cytnx PRIVATE ${HDF5_INCLUDE_DIRS})
target_link_libraries(cytnx PRIVATE ${HDF5_LIBRARIES})


# #####################################################################
# ## Get Gtest & benchmark
Expand Down Expand Up @@ -375,6 +380,7 @@ IF(BUILD_PYTHON)
endif()

pybind11_add_module(pycytnx MODULE pybind/cytnx.cpp
pybind/io_py.cpp
pybind/generator_py.cpp
pybind/storage_py.cpp
pybind/tensor_py.cpp
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/linalg/Svd_bm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace BMTest_Svd {
BENCHMARK(BM_Tensor_Svd_C128)->Args({1, 1})->Args({10, 10})->Args({100, 100})->Args({1000, 1000});

// DenseUniTensor
UniTensor ConstructDenseUT(const int D, const int dtype, const unsigned int device = Device.cpu) {
UniTensor ConstructDenseUT(const int D, const int dtype, const int device = Device.cpu) {
auto bd_vi = Bond(D, BD_IN);
auto bd_pi = Bond(2, BD_IN);
auto bd_po = Bond(2, BD_OUT);
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/linalg/Svd_truncate_bm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using namespace cytnx;
namespace BMTest_Svd_truncate {

// DenseUniTensor
UniTensor ConstructDenseUT(const int D, const int dtype, const unsigned int device = Device.cpu) {
UniTensor ConstructDenseUT(const int D, const int dtype, const int device = Device.cpu) {
auto bd_vi = Bond(D, BD_IN);
auto bd_pi = Bond(2, BD_IN);
auto bd_po = Bond(2, BD_OUT);
Expand Down
5 changes: 5 additions & 0 deletions conda_build/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ source:

build:
number: 0
channels:
- conda-forge
- defaults
script_env:
# Refer to : https://github.com/ccache/ccache/discussions/821#discussioncomment-521209
- CCACHE_NOHASHDIR=1
Expand Down Expand Up @@ -39,6 +42,7 @@ requirements:
- boost >=1.82.0
- blas=*=mkl # [x86]
- blas=*=openblas # [not x86]
- hdf5 >=1.10.0
- gtest
- arpack
run:
Expand All @@ -49,6 +53,7 @@ requirements:
- graphviz
- blas=*=mkl # [x86]
- blas=*=openblas # [not x86]
- hdf5 >=1.10.0
- beartype
- arpack

Expand Down
9 changes: 9 additions & 0 deletions cytnx/io_conti.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing import Any
from cytnx import *

def Load(obj: Any, container, name: str, path: str = ""):
io.c_Load(obj, container, name, path)

# inject into the submodule
obj = io
setattr(obj,"Load",Load)
4 changes: 2 additions & 2 deletions docs/source/adv_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ There are two methods how you can set-up all the dependencies before starting th

.. code-block:: shell

$conda install cmake make boost boost-cpp git compilers numpy openblas arpack pybind11 beartype arpack
$conda install cmake make boost boost-cpp git compilers hdf5 numpy openblas arpack pybind11 beartype arpack


.. Note::
Expand All @@ -103,7 +103,7 @@ There are two methods how you can set-up all the dependencies before starting th

.. code-block:: shell

$conda install cmake make boost boost-cpp git compilers numpy mkl mkl-include mkl-service arpack pybind11 libblas=*=*mkl beartype arpack
$conda install cmake make boost boost-cpp git compilers hdf5 numpy mkl mkl-include mkl-service arpack pybind11 libblas=*=*mkl beartype arpack

3. After the installation, an automated test based on gtest and benchmark can be run. This option needs to be activated in the install script. In this case, gtest needs to be installed as well:

Expand Down
148 changes: 110 additions & 38 deletions include/Bond.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#ifndef CYTNX_BOND_H_
#define CYTNX_BOND_H_

#include "Type.hpp"
#include "cytnx_error.hpp"
#include "Symmetry.hpp"
#include <initializer_list>
#include <vector>
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <initializer_list>
#include <map>
#include <algorithm>
#include <vector>

#include "H5Cpp.h"

#include "Symmetry.hpp"
#include "Type.hpp"
#include "cytnx_error.hpp"
#include "intrusive_ptr_base.hpp"
#include "utils/vec_clone.hpp"

Expand Down Expand Up @@ -36,6 +40,10 @@ namespace cytnx {
BD_IN = -1, /*!< -1, same as BD_KET */
BD_OUT = 1 /*!< 1, same as BD_BRA */
};
static const std::map<bondType, std::string> bondtype_to_string = {
{BD_REG, "REG"}, {BD_IN, "IN"}, {BD_OUT, "OUT"}};
static const std::map<std::string, bondType> string_to_bondtype = {
{"REG", BD_REG}, {"IN", BD_IN}, {"OUT", BD_OUT}};

/// @cond
class Bond_impl : public intrusive_ptr_base<Bond_impl> {
Expand Down Expand Up @@ -848,52 +856,116 @@ namespace cytnx {
}

/**
@brief Save the Bond object to the file.
@details Save the Bond object to the file. The file extension will be automatically
added as ".cybd".
@param[in] fname the file name of the Bond object (exclude the file extension).
@see Load(const std::string &fname)
*/
void Save(const std::string &fname) const;

* @brief Save Bond to file
* @details Save the Bond to a file. The file ending should be one of ".h5", ".hdf5", ".H5",
* ".HDF5", ".hdf" to save in HDF5 file format. Otherwise, a binary file format is used.
* @param[in] fname file name
* @param[in] path path inside the file. Only used for HDF5 files. A path '/foo/bar/' will write
* the Bond to the group '/foo/bar' in the file.
* @param[in] mode the write mode:\n
* `w` Creates a new file. If the given file exists, its contents are destroyed.\n
* `x` Creates a new file. Fails if the given file exists already.\n
* `a` Opens for writing without overwriting any existing content. Creates the file if it
* doesn't exist. Only available for HDF5 files.\n
* `u` Opens for writing. Existing content will be updated(overwritten).
* Creates the file if it doesn't exist. Only available for HDF5 files.
* @note The common file ending for saving a Bond in binary format is ".cybd".
* @warning HDF5 file format is strongly recommended for compatibility with other libraries,
* readability, and future-proofing.
* @see Load()
*/
void Save(const std::filesystem::path &fname, const std::string &path = "/Bond/",
const char mode = 'w') const;
/**
@see Save(const std::string &fname) const;
*/
void Save(const char *fname) const;
* @see Save(const std::filesystem::path &fname, const std::string &path, const char mode)
* const;
*/
void Save(const char *fname, const std::string &path = "/Bond/", const char mode = 'w') const;

/**
* @brief Load Bond from file and create new instance
* @details This function creates a new Bond and keeps the original Bond unchanged. See Load_()
* for loading the Bond to the current Bond.
* @param fname[in] file name
* @param[in] path path inside the file. Only used for HDF5 files. A path '/foo/bar/' will read
* the Bond from the group '/foo/bar' in the file.
* @param[in] restore_device whether to try restoring the device on which the data is stored; if
* false, the data will be kept on the CPU. Use .to_() to move it to the target device after
* loading.
* @pre The file must be a Bond object which is saved by Save().
* @note For HDF5 file format, one of the file endings ".h5", ".hdf5", ".H5", ".HDF5", ".hdf" is
* expected. For binary format, the common file ending for a Bond is ".cybd".
*/
static cytnx::Bond Load(const std::filesystem::path &fname, const std::string &path = "/Bond/");
/**
* @see Load(const std::filesystem::path &fname, const std::string &path)
*/
static cytnx::Bond Load(const char *fname, const std::string &path = "/Bond/");

/**
@brief Load the Bond object from the file.
@param[in] fname the file name of the Bond object.
@pre The file need to be the file of Bond object, which is saved by the
function Bond::Save(const std::string &fname) const.
*/
static cytnx::Bond Load(const std::string &fname);
* @brief Load Bond from file and overwrite current instance
* @details This function overwrites the existing Bond. See Load() for creating a new Bond.
* @see Load()
*/
void Load_(const std::filesystem::path &fname, const std::string &path = "/Bond/");
/**
* @see Load_(const std::filesystem::path &fname, const std::string &path)
*/
void Load_(const char *fname, const std::string &path = "/Bond/");

/**
@see Load(const std::string &fname)
*/
static cytnx::Bond Load(const char *fname);
* @brief Save Bond to HDF5 file
* @param[in] container the HDF5 parent group.
* @param[in] name the subgroup in which the Bond will be saved.
* @param[in] overwrite overwrite previous Bond information in the container.
* @warning This function is only available in C++. Use Save() for saving to file in C++ or
* Python.
* @see from_hdf5()
*/
void to_hdf5(H5::Group &container, const std::string &name = "Bond",
const bool overwrite = false) const;
/**
* @brief Load Bond from HDF5 file (inline)
* @param[in] container the HDF5 parent group.
* @param[in] name the subgroup from which the Bond will be loaded.
* @warning This function is only available in C++. Use Load() for loading from file in C++ or
* Python.
* @see to_hdf5() const
*/
void from_hdf5(H5::Group &container, const std::string &name = "Bond");

/// @cond
void _Save(std::fstream &f) const;
void _Load(std::fstream &f);
/// @endcond
/**
* @brief Save Bond to binary file
* @param[in] f the output stream where the Bond will be saved.
* @warning This function is only available in C++. In Python, use pickle for the same binary
* file format. Use Save() for saving to file in C++ or Python.
* @see from_binary()
*/
void to_binary(std::ostream &f) const;
/**
* @brief Load Bond from binary file
* @param[in] f the input stream from which the Bond will be loaded.
* @warning This function is only available in C++. In Python, use pickle for the same binary
* file format. Use Load() for loading from file in C++ or Python.
* @see to_binary() const
*/
void from_binary(std::istream &f);

/**
@brief The comparison operator 'equal to'.
@details The comparison operators to compare two Bonds. If two Bond object are
same, return true. Otherwise, return false. This equal to operator will
compare all the "value" of the Bond object. Even the Bond object are different
object (different address), but they are same "value", it will return true.
@see operator!=(const Bond &rhs) const
@details The comparison operators to compare two Bonds. If two Bond object are same, return
true. Otherwise, return false. This equal to operator will compare all the "value" of the Bond
object. Even the Bond object are different object (different address), but they are same
"value", it will return true.
@see operator!=(const Bond &rhs) const
*/
bool operator==(const Bond &rhs) const;

/**
@brief The comparison operator 'not equal to'.
@details The comparison operators to compare two Bonds. More precisely, it is
the opposite result of the operator==(const Bond &rhs) const.
@see operator==(const Bond &rhs) const
@details The comparison operators to compare two Bonds. More precisely, it is the opposite
result of the operator==(const Bond &rhs) const.
@see operator==(const Bond &rhs) const
*/
bool operator!=(const Bond &rhs) const;

Expand Down
Loading
Loading