{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Heisenberg Model\n", "\n", "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/block-hczhai/block2-preview/blob/master/docs/source/tutorial/heisenberg.ipynb)" ], "metadata": { "id": "1L3j_iDngtG_" } }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "DJLjdeRfgeSH" }, "outputs": [], "source": [ "!pip install block2==0.5.2rc13 -qq --progress-bar off --extra-index-url=https://block-hczhai.github.io/block2-preview/pypi/" ] }, { "cell_type": "markdown", "source": [ "## Introduction\n", "\n", "In this tutorial we explain how to solve the Heisenberg model using the python interface of ``block2``.\n", "\n", "First, we have to define the \"site-spin\" of the model. The parameter ``heis_twos`` represents two times the spin in each site. Namely, for $S = 1/2$ Heisenberg model, ``heis_twos = 1``, for $S = 1$ Heisenberg model, ``heis_twos = 2``, etc. Note that arbitrary non-negative half-integer and integer $S$ can be supported in ``block2``.\n", "\n", "Second, we can solve the model using the SU2 symmetry (``SU2`` mode) or U1 symmetry (``SGB`` mode). The SU2 symmetry can be more efficient (for large ``S``) and can generate states with well-defined total spin symmetry, but requires some additional rearrangement of the Hamiltonian terms." ], "metadata": { "id": "kCcbGRlYg0eS" } }, { "cell_type": "markdown", "source": [ "## The ``SGB`` Mode\n", "\n", "The Hamiltonian is\n", "\n", "$$\n", "\\hat{H} = \\sum_{i=1}^{L-1} \\Big( \\frac{1}{2} S^+_{i} S^-_{i+1} + \\frac{1}{2} S^-_{i} S^+_{i+1} + S^z_{i} S^z_{i+1} \\Big)\n", "$$\n", "\n", "We can solve this model using the following code:" ], "metadata": { "id": "eeJ-l24EiRPE" } }, { "cell_type": "code", "source": [ "import numpy as np\n", "from pyblock2.driver.core import DMRGDriver, SymmetryTypes\n", "\n", "L = 100\n", "heis_twos = 1\n", "\n", "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGB, n_threads=4)\n", "driver.initialize_system(n_sites=L, heis_twos=heis_twos, heis_twosz=0)\n", "\n", "b = driver.expr_builder()\n", "for i in range(L - 1):\n", " b.add_term(\"PM\", [i, i + 1], 0.5)\n", " b.add_term(\"MP\", [i, i + 1], 0.5)\n", " b.add_term(\"ZZ\", [i, i + 1], 1.0)\n", "heis_mpo = driver.get_mpo(b.finalize(), iprint=0)\n", "\n", "def run_dmrg(driver, mpo):\n", " ket = driver.get_random_mps(tag=\"KET\", bond_dim=250, nroots=1)\n", " bond_dims = [250] * 4 + [500] * 4\n", " noises = [1e-5] * 4 + [1e-6] * 2 + [0]\n", " thrds = [1e-6] * 4 + [1e-8] * 4\n", " return driver.dmrg(\n", " mpo,\n", " ket,\n", " n_sweeps=8,\n", " bond_dims=bond_dims,\n", " noises=noises,\n", " thrds=thrds,\n", " cutoff=1E-24,\n", " iprint=1,\n", " )\n", "\n", "energies = run_dmrg(driver, heis_mpo)\n", "print('DMRG energy = %20.15f' % energies)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Pu9I8YCwgwvz", "outputId": "54bdc8df-48bb-4758-cf4b-be18087b0fc8" }, "execution_count": 2, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 32.844 | E = -44.1201487994 | DW = 1.12e-09\n", "\n", "Sweep = 1 | Direction = backward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 38.582 | E = -44.1277383773 | DE = -7.59e-03 | DW = 1.21e-13\n", "\n", "Sweep = 2 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 41.882 | E = -44.1277383773 | DE = -4.01e-12 | DW = 7.28e-14\n", "\n", "Sweep = 3 | Direction = backward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 44.918 | E = -44.1277383773 | DE = -1.34e-12 | DW = 2.79e-14\n", "\n", "Sweep = 4 | Direction = forward | Bond dimension = 500 | Noise = 1.00e-06 | Dav threshold = 1.00e-08\n", "Time elapsed = 60.141 | E = -44.1277398826 | DE = -1.51e-06 | DW = 4.18e-17\n", "\n", "Sweep = 5 | Direction = backward | Bond dimension = 500 | Noise = 1.00e-06 | Dav threshold = 1.00e-08\n", "Time elapsed = 79.821 | E = -44.1277398826 | DE = -1.92e-13 | DW = 3.84e-17\n", "\n", "Sweep = 6 | Direction = forward | Bond dimension = 500 | Noise = 0.00e+00 | Dav threshold = 1.00e-08\n", "Time elapsed = 94.075 | E = -44.1277398826 | DE = -1.35e-13 | DW = 1.61e-20\n", "\n", "DMRG energy = -44.127739882610513\n" ] } ] }, { "cell_type": "markdown", "source": [ "## The ``SU2`` Mode\n", "\n", "To solve the model in the ``SU2`` mode, we define the following (triplet) spin tensor operator:\n", "\n", "$$ \\big(T_p\\big)^{[1]} := \\begin{pmatrix} -S^+_p \\\\ \\sqrt{2}S^z_p \\\\ S^-_p \\end{pmatrix}^{[1]} $$\n", "\n", "Then we have\n", "\n", "$$\n", "\\big(T_p\\big)^{[1]} \\otimes_{[0]} \\big(T_q\\big)^{[1]} =\n", "\\begin{pmatrix} -S^+_p \\\\ \\sqrt{2}S^z_p \\\\ S^-_p \\end{pmatrix}^{[1]}\n", "\\otimes_{[0]}\n", "\\begin{pmatrix} -S^+_q \\\\ \\sqrt{2}S^z_q \\\\ S^-_q \\end{pmatrix}^{[1]} \\\\\n", "=\\frac{1}{\\sqrt{3}}\n", "\\begin{pmatrix} -S^+_p S^-_q -S^-_p S^+_q -2 S^z_p S^z_q \\end{pmatrix}^{[0]}\n", "=-\\frac{2}{\\sqrt{3}}\n", "\\begin{pmatrix} \\frac{1}{2} S^+_p S^-_q + \\frac{1}{2} S^-_p S^+_q + S^z_p S^z_q \\end{pmatrix}^{[0]}\n", "$$" ], "metadata": { "id": "OqDTHLmNlbsG" } }, { "cell_type": "markdown", "source": [ "Note that in the above calculation, we have used the following CG factors:" ], "metadata": { "id": "nlNrFNUvon5h" } }, { "cell_type": "code", "source": [ "from block2 import SU2CG\n", "print(' = ', SU2CG().cg(2, 2, 0, 2, -2, 0))\n", "print(' = ', SU2CG().cg(2, 2, 0, -2, 2, 0))\n", "print(' = ', SU2CG().cg(2, 2, 0, 0, 0, 0))\n", "print(1 / 3 ** 0.5)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "wSNAL3Tyj-xX", "outputId": "848b6ac6-eb70-4b00-c3c1-33696b048ec3" }, "execution_count": 3, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ " = 0.5773502691896257\n", " = 0.5773502691896257\n", " = -0.5773502691896257\n", "0.5773502691896258\n" ] } ] }, { "cell_type": "markdown", "source": [ "So the Hamiltonian in ``SU2`` notation is\n", "\n", "$$\n", "\\hat{H} = -\\frac{\\sqrt{3}}{2}\\sum_{i=1}^{L-1} \\big( T_i \\big)^{[1]} \\otimes_{[0]} \\big( T_{i+1} \\big)^{[1]}\n", "$$\n", "\n", "We can solve this model using the following code:" ], "metadata": { "id": "GsBGJzT7oyTA" } }, { "cell_type": "code", "source": [ "import numpy as np\n", "from pyblock2.driver.core import DMRGDriver, SymmetryTypes\n", "\n", "L = 100\n", "heis_twos = 1\n", "\n", "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=L, heis_twos=heis_twos, spin=0)\n", "\n", "b = driver.expr_builder()\n", "for i in range(L - 1):\n", " b.add_term(\"(T+T)0\", [i, i + 1], -np.sqrt(3) / 2)\n", "heis_mpo = driver.get_mpo(b.finalize(adjust_order=False), iprint=0)\n", "\n", "energies = run_dmrg(driver, heis_mpo)\n", "print('DMRG energy = %20.15f' % energies)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "_RjfaHzIoDmA", "outputId": "371be8d4-392b-47f9-90a3-3592dbe40849" }, "execution_count": 5, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 48.587 | E = -44.1275743858 | DW = 7.23e-12\n", "\n", "Sweep = 1 | Direction = backward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 53.973 | E = -44.1277393752 | DE = -1.65e-04 | DW = 6.90e-14\n", "\n", "Sweep = 2 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 59.107 | E = -44.1277393752 | DE = -3.84e-13 | DW = 3.59e-16\n", "\n", "Sweep = 3 | Direction = backward | Bond dimension = 250 | Noise = 1.00e-05 | Dav threshold = 1.00e-06\n", "Time elapsed = 63.144 | E = -44.1277393752 | DE = -1.28e-13 | DW = 8.81e-17\n", "\n", "Sweep = 4 | Direction = forward | Bond dimension = 500 | Noise = 1.00e-06 | Dav threshold = 1.00e-08\n", "Time elapsed = 75.269 | E = -44.1277398850 | DE = -5.10e-07 | DW = 3.06e-22\n", "\n", "Sweep = 5 | Direction = backward | Bond dimension = 500 | Noise = 1.00e-06 | Dav threshold = 1.00e-08\n", "Time elapsed = 94.287 | E = -44.1277398850 | DE = -1.99e-13 | DW = 6.38e-23\n", "\n", "Sweep = 6 | Direction = forward | Bond dimension = 500 | Noise = 0.00e+00 | Dav threshold = 1.00e-08\n", "Time elapsed = 103.865 | E = -44.1277398850 | DE = 0.00e+00 | DW = 1.42e-23\n", "\n", "DMRG energy = -44.127739885005937\n" ] } ] } ] }