An Efficient python block-sparse tensor and MPS/DMRG Library
Copyright (C) 2020-2021 The pyblock3 developers. All Rights Reserved.
Authors:
Please cite this work as:
Huanchen Zhai, Yang Gao, and Garnet K.-L. Chan. pyblock3: an efficient python block-sparse tensor and MPS/DMRG library. 2021; https://github.com/block-hczhai/pyblock3-preview.
Documentation: https://pyblock3.readthedocs.io/en/latest
Tutorial: https://colab.research.google.com/drive/1grQyYP9oTivjqQRZiwU40tF9SdWyrPfV?usp=sharing
Using pip
:
pip install pyblock3
To install the most recent development version, use:
pip install pyblock3==<version> --extra-index-url=https://block-hczhai.github.io/pyblock3-preview/pypi/
where <version>
can be some development version number like 0.2.7rc5
.
Or you can compile it manually:
Dependence: python3
, psutil
, numba
, and numpy
(version >= 1.17.0). pyblock3 can run in pure python mode,
in which no C++ source code is required to be compiled.
For optimal performance, the C++ source code is used and there are some additional dependences:
pybind11
(https://github.com/pybind/pybind11)cmake
(version >= 3.0)MKL
(or blas + lapack
)
MKL
is available, add cmake
option: -DUSE_MKL=ON
.cmake
cannot find MKL
, one can add environment variable hint MKLROOT
.g++
or clang
icpc
currently not tested/supportedhptt
(https://github.com/springer13/hptt) (optional)
HPTT
is available, add cmake
option: -DUSE_HPTT=ON
.cmake
cannot find HPTT
, one can add environment variable hint HPTTHOME
.gomp
or iomp5
(optional)
cmake
option: -DOMP_LIB=SEQ
.gomp
): add cmake
option: -DOMP_LIB=GNU
.iomp5
): add cmake
option: -DOMP_LIB=INTEL
(default).cmake
cannot find openMP library, one can add the path to libgomp.so
or libiomp5.so
to environment variable PATH
.To compile the C++ part of the code (for better performance):
mkdir build
cd build
cmake .. -DUSE_MKL=ON -DUSE_HPTT=ON
make
Add package root directory to PYTHONPATH
before running the following examples.
If you used directory names other than build
for the build directory (which contains the compiled python extension),
you also need to add the build directory to PYTHONPATH
.
Ground-state DMRG (H8 STO6G) in pure python (52 seconds):
import numpy as np
from pyblock3.algebra.mpe import MPE
from pyblock3.hamiltonian import Hamiltonian
from pyblock3.fcidump import FCIDUMP
fd = 'data/H8.STO6G.R1.8.FCIDUMP'
bond_dim = 250
hamil = Hamiltonian(FCIDUMP(pg='d2h').read(fd), flat=False)
mpo = hamil.build_qc_mpo()
mpo, _ = mpo.compress(cutoff=1E-9, norm_cutoff=1E-9)
mps = hamil.build_mps(bond_dim)
dmrg = MPE(mps, mpo, mps).dmrg(bdims=[bond_dim], noises=[1E-6, 0],
dav_thrds=[1E-3], iprint=2, n_sweeps=10)
ener = dmrg.energies[-1]
print("Energy = %20.12f" % ener)
Ground-state DMRG (H8 STO6G) with C++ optimized core functions (0.87 seconds):
import numpy as np
from pyblock3.algebra.mpe import MPE
from pyblock3.hamiltonian import Hamiltonian
from pyblock3.fcidump import FCIDUMP
fd = 'data/H8.STO6G.R1.8.FCIDUMP'
bond_dim = 250
hamil = Hamiltonian(FCIDUMP(pg='d2h').read(fd), flat=True)
mpo = hamil.build_qc_mpo()
mpo, _ = mpo.compress(cutoff=1E-9, norm_cutoff=1E-9)
mps = hamil.build_mps(bond_dim)
dmrg = MPE(mps, mpo, mps).dmrg(bdims=[bond_dim], noises=[1E-6, 0],
dav_thrds=[1E-3], iprint=2, n_sweeps=10)
ener = dmrg.energies[-1]
print("Energy = %20.12f" % ener)
The printed ground-state energy for this system should be -4.345079402665
.
Write the C++ definition of the class (named QPN
, for example) in src/qpn.hpp
, which should be similar to src/sz.hpp
.
Add the following in src/symmetry_tmpl.hpp
after add other symmetries here
line:
#include "qpn.hpp"
#define TMPL_Q QPN
#include NAME_IMPL(TMPL_NAME,_tmpl.hpp)
#undef TMPL_Q
Note that if multiple symmetry class are defined in the same file src/qpn.hpp
, you may only write #include "qpn.hpp"
once. The other three lines have to be repeated for each symmetry class.
If you do not need the default symmetry class SZ
and you want to save compiling time, the four lines for SZ
can be removed/commented.
Add the following in src/main.hpp
after bind extra symmetry here
line:
py::module m_qpn = m.def_submodule("qpn", "General other symmetry.");
bind_sparse_tensor<QPN>(m_qpn, m, "QPN");
If you do not need the default symmetry class SZ
and you want to save compiling time, the two lines bind_ ...
for SZ
can be removed/commented.
In python script, use the following to indicate which symmetry class is being used:
if DEFAULT_SYMMETRY == SZ:
import block3.sz as block3
elif DEFAULT_SYMMETRY == QPN:
import block3.qpn as block3