MPS Import/Export

The block2 MPS can be translated into StackBlock format for restarting the calculation in StackBlock. Alternatively, the StackBlock rotation matrices and wavefunction can be translated into block2 MPS. Since different initial guess for MPS is generated in StackBlock and block2, this feature can be useful for sharing MPS initial guess among different codes, debugging, or performing some DMRG methods not implemented in one of the code.

The translation itself should be exact, with the support for both spin-adapted and non-spin-adapted case. If the canonical form is not LLL...KR, some small error may occur during the canonical form translation.

The script ${BLOCK2HOME}/pyblock2/driver/readwfn.py can be used to translate from StackBlock to block2. The script ${BLOCK2HOME}/pyblock2/driver/writewfn.py can be used to translate from block2 to StackBlock. These two scripts depend on block2, pyblock and StackBlock. To install pyblock and StackBlock, the boost package is required. We will first explain the installation of these extra dependencies.

Boost Installation

One can download the most recent version of boost in https://www.boost.org/users/download/ Assuming the downloaded file is named boost_1_76_0.tar.gz, stored in ~/program/boost-1.76 (you can choose any other directory). One can then install boost in the following way. Please make sure the correct version of C++ compiler is set in the environment. The same C++ compiler should be used for compiling boost and block2, pyblock and StackBlock.

$ mkdir ~/program/boost-1.76
$ cd ~/program/boost-1.76
$ PREFIX=$PWD
$ wget https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz
$ tar zxf boost_1_76_0.tar.gz
$ cd boost_1_76_0
$ gcc --version
gcc (GCC) 9.2.0
$ bash bootstrap.sh
$ echo 'using mpi ;' >> project-config.jam
$ ./b2 install --prefix=$PREFIX
$ echo $PREFIX
/home/.../program/boost-1.76

Now an environment variable BOOSTROOT should be added. This will ensure that this boost installation can be found by cmake for compiling StackBlock and pyblock. For example, one can add the following line into ~/.bashrc.

export BOOSTROOT=~/program/boost-1.76

Note

The --prefix parameter cannot be set to a path beginning with ~. If you need such a path, please use an absolute path instead, namely, setting --prefix=/home/<user>/....

StackBlock Installation

The default vresion of StackBlock has some bugs for some non-popular features. It is recommended to use this fork, which can be compiled using cmake. First, make sure a working MPI library such as openmpi 4.0 can be found in the system, a C++ compiler with the correct version can be found, and BOOSTROOT is set. Then StackBlock can be compiled in the following way (starting from the cloned StackBlock repo directory):

export STACKBLOCK=$PWD
mkdir build
cd build
cmake ..
make -j 10
rm CMakeCache.txt
cmake .. -DBUILD_OH=ON
make -j 10
rm CMakeCache.txt
cmake .. -DBUILD_READROT=ON
make -j 10
rm CMakeCache.txt
cmake .. -DBUILD_GAOPT=ON
make -j 10

This will generate four executables in the build direcotry.

block.spin_adapted is the main StackBlock program. One can optionally add the following to ~/.bashrc:

export PATH=${STACKBLOCK}/build:$PATH

OH is the program to compute the expectation value on an MPS (or between two MPSs), of Hamiltonian and/or the identity operator.

read_rot is the program to translate the intermediate rotation matrix format (from the spin-projected zmpo_dmrg code) to the StackBlock rotation matrix and wavefunction format.

gaopt is the program for orbital reordering using genetic algorithm. Note that for this purpose, the block2 driver ${BLOCK2HOME}/pyblock2/driver/gaopt.py should provide much better performance.

pyblock Installation

pyblock is a python3 wrapper for the StackBlock code. pyblock contains a slightly revised version of StackBlock, which must be compiled. The code can be obtained here. First, make sure that a C++ compiler with the correct version can be found, and BOOSTROOT is set. Then pyblock can be compiled in the following way (starting from the cloned pyblock repo directory):

export PYBLOCKHOME=$PWD
mkdir build
cd build
cmake .. -DBUILD_LIB=ON -DUSE_MKL=ON
make -j 10

Import MPS to block2

Now we are ready to show how to translate a StackBlock MPS to block2 MPS.

First, make sure a testing integral file C2.CAS.PVDZ.FCIDUMP is in the working directory. The integral file can be found in ${BLOCK2HOME}/data/C2.CAS.PVDZ.FCIDUMP.

Note

Normally, orbital reordering can create some unnecessary complexities. It is recommended to use a already reordered FCIDUMP file across different codes. If the MPS has to be adjusted for orbital reordering, see MPS Orbital Rotation.

We will first perform a DMRG ground-state calculation using the following input file dmrg.conf:

sym d2h
orbitals C2.CAS.PVDZ.FCIDUMP

nelec 8
spin 0
irrep 1

hf_occ integral
schedule default
maxM 500
maxiter 30
prefix ./tmp
noreorder

The following command can be used to run StackBlock with this input file:

mkdir ./tmp
${STACKBLOCK}/build/block.spin_adapted dmrg.conf > dmrg.out

The DMRG ground-state energy can be obtained from the output file:

$ grep 'Sweep Energy' dmrg.out | tail -1
M = 500     state = 0     Largest Discarded Weight = 0.000000000000  Sweep Energy = -75.728442606745

The energy for the MPS that will be translated is the energy at the last site of the last sweep:

$ grep 'sweep energy' dmrg.out | tail -1
Finished Sweep with 500 states and sweep energy for State [ 0 ] with Spin [ 0 ] :: -75.728442606745

Since in the default schedule the one-site algorithm is used for the last sweep. This two energies are identical.

Now the MPS in StackBlock format is stored in the scratch folder ./tmp/node0. We will only need files in this folder with file names Rotation-*, StateInfo-*, wave-*. The other files Block-b-* and Block-f-* (with renormalized operators stored) are not part of the MPS, which can be deleted.

The folowing commands can be used to translate the MPS. Please make sure that the environment variables ${STACKBLOCK}, ${PYBLOCKHOME}, and ${BLOCK2HOME} are correctly set.

$ PYTHONPATH=${BLOCK2HOME}/build:$PYTHONPATH
$ PYTHONPATH=${PYBLOCKHOME}:$PYTHONPATH
$ PYTHONPATH=${PYBLOCKHOME}/build:$PYTHONPATH
$ READWFN=${BLOCK2HOME}/pyblock2/driver/readwfn.py
$ python3 $READWFN dmrg.conf -expect
-75.72844260674495

Note

Here we use a special build of block2 python extension, which was built using the cmake option -DTBB=OFF (the default is OFF). On some systems -DUSE_MKL=OFF -OMP_LIB=SEQ may be required. This is to solve the conflicts for importing pyblock and block2 in the same script.

Note that -expect option is optional. With this option, the energy of the translated MPS will be evaluted in block2 and printed. We can see that the printed block2 energy is almost exactly the same as the one obtained from StackBlock. By default, the translated block2 MPS will be put in the output directory named ./out with the tag KET.

Export MPS from block2

Now we show how to translate a block2 MPS to StackBlock MPS.

We will first perform a DMRG ground-state calculation using the following input file dmrg2.conf:

sym d2h
orbitals C2.CAS.PVDZ.FCIDUMP

nelec 8
spin 0
irrep 1

hf_occ integral
schedule default
maxM 500
maxiter 30
prefix ./tmp2
noreorder

Note that the only difference between dmrg.conf and dmrg2.conf is the prefix. The following command can be used to run block2 with this input file:

${BLOCK2HOME}/pyblock2/driver/block2main dmrg2.conf > dmrg2.out

The energy for the MPS that will be translated is the energy at the last site of the last sweep:

$ grep 'DW' dmrg2.out | tail -1
Time elapsed =      3.883 | E =     -75.7284436933 | DE = -3.85e-07 | DW = 3.76e-16

The folowing commands can be used to translate the MPS. Please make sure that the environment variables ${STACKBLOCK}, ${PYBLOCKHOME}, and ${BLOCK2HOME} are correctly set.

$ PYTHONPATH=${BLOCK2HOME}/build:$PYTHONPATH
$ PYTHONPATH=${PYBLOCKHOME}:$PYTHONPATH
$ PYTHONPATH=${PYBLOCKHOME}/build:$PYTHONPATH
$ WRITEWFN=${BLOCK2HOME}/pyblock2/driver/writewfn.py
$ python3 $WRITEWFN dmrg2.conf -out out2
load MPSInfo from ././tmp2/KET-mps_info.bin
SRRRRRRRRRRRRRRRRRRRRRRRRR -> LLLLLLLLLLLLLLLLLLLLLLLLKR 24

From the print we can see that the canonical form of MPS has been changed, which may cause some small error in the translated MPS. The translated MPS in StackBlock format is now stored in the out2 directory. We can now evaluate the energy of the translated MPS using the OH program in StackBlock:

$ sed -i "s|^prefix.*|prefix ./out2|" dmrg2.conf
$ ${STACKBLOCK}/build/OH dmrg2.conf | grep -A 1 'printing hamiltonian' | tail -1
-75.7284436933

We can see that the printed StackBlock energy is exactly the same as the one obtained from block2.

Note

The OH program in StackBlock can only evalute the onedot MPS (namely, MPS used in 1-site DMRG algorithm). The MPS can be spin-adapted or non-spin-adapted. If you use the OH in the default standard version of StackBlock, the non-spin-adapted MPS is not supported and you need an extra argument for a file including the MPS ids. For example, you should use /path/to/default/StackBlock/OH dmrg2.conf wavenum where a file named wavenum should be set with contents 0 (or any space-separated list of integers, if you have multiple MPSs).

Alternatively, we can also translate back to block2 and evaluate the energy:

$ sed -i "s|^prefix.*|prefix ./out2|" dmrg2.conf
$ READWFN=${BLOCK2HOME}/pyblock2/driver/readwfn.py
$ python3 $READWFN dmrg2.conf -dot 1 -expect -out out3
-75.72844369332921

Which also prints the same energy.