From 1dcea754943ce60ef1576ea2451445be592e7172 Mon Sep 17 00:00:00 2001 From: Huanchen Zhai Date: Sat, 9 Dec 2023 23:16:05 -0800 Subject: [PATCH] fix docs --- docs/source/tutorial/qc-hamiltonians.ipynb | 1472 ++++++++++---------- 1 file changed, 736 insertions(+), 736 deletions(-) diff --git a/docs/source/tutorial/qc-hamiltonians.ipynb b/docs/source/tutorial/qc-hamiltonians.ipynb index 6734245f..0a34679f 100644 --- a/docs/source/tutorial/qc-hamiltonians.ipynb +++ b/docs/source/tutorial/qc-hamiltonians.ipynb @@ -1,30 +1,15 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [], - "toc_visible": true - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "f1v7ZIHNvg7D" + }, "source": [ "# Quantum Chemistry Hamiltonians\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/qc-hamiltonians.ipynb)" - ], - "metadata": { - "id": "f1v7ZIHNvg7D" - } + ] }, { "cell_type": "code", @@ -40,12 +25,15 @@ }, { "cell_type": "markdown", + "metadata": { + "id": "QbsjgwANwd-C" + }, "source": [ "## Introduction\n", "\n", "In this tutorial we explain how to perform quantum chemistry DMRG using the python interface of ``block2``.\n", "\n", - "The quantum chemistry Hamiltonian in its second quantized form has to be defined in a set of orbitals, such as the Hartree-Fock (or Density Functional Theory) orbitals. The symmetry that can be used in the DMRG calculation is thus has a dependence on the symmetry of the Hartree-Fock orbitals.\n", + "The quantum chemistry Hamiltonian in its second quantized form has to be defined in a set of orbitals, such as the Hartree-Fock (or Density Functional Theory) orbitals. The symmetries that can be used in the DMRG calculation thus have a dependence on the symmetry of the Hartree-Fock orbitals.\n", "\n", "1. For spin-restricted Hartree-Fock (RHF) orbitals, we can perform spin-adapted DMRG (``SU2`` mode in ``block2``) or non-spin-adapted DMRG with any lower symmetries (``SZ`` or ``SGF``).\n", "\n", @@ -58,26 +46,26 @@ "5. For atom and diatomic molecules, we can perform spin-adapted/non-spin-adapted/spin-orbital DMRG (``SAnySU2LZ/SAnySZLZ/SAnySGFLZ`` modes in ``block2``) with the $L_z$ symmetry.\n", "\n", "Next, we will explain how to set up the integrals and perform DMRG in each of the modes (1) (2) (3) (4) and (5). The quantum chemistry integrals will be generated using ``pyscf`` and transformed using funtions defined in ``pyblock2._pyscf.ao2mo``.\n" - ], - "metadata": { - "id": "QbsjgwANwd-C" - } + ] }, { "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "aEtzPUucyvCg" + }, + "outputs": [], "source": [ "import numpy as np\n", "from pyblock2._pyscf.ao2mo import integrals as itg\n", "from pyblock2.driver.core import DMRGDriver, SymmetryTypes" - ], - "metadata": { - "id": "aEtzPUucyvCg" - }, - "execution_count": 2, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "kzFc7fBTyuQ_" + }, "source": [ "## Spin-Restricted Integrals\n", "\n", @@ -86,43 +74,11 @@ "For medium to large scale DMRG calculations, it is highly recommended to use a scratch space with high IO speed rather than the ``./tmp`` used in the following example. One also needs to set a suitable ``stack_mem`` in the ``DMRGDriver`` constructor to set the memory used for storing renormalized operators (in bytes). The default is ``stack_mem=int(1024**3)`` (1 GB). For medium scale calculations 10 to 30 GB might be required.\n", "\n", "For the meaning of DMRG parameters, please have a look at the [Hubbard - Run DMRG](https://block2.readthedocs.io/en/latest/tutorial/hubbard.html#Run-DMRG) page." - ], - "metadata": { - "id": "kzFc7fBTyuQ_" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "bond_dims = [250] * 4 + [500] * 4\n", - "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", - "thrds = [1e-10] * 8\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)\n", - "\n", - "pdm1 = driver.get_1pdm(ket)\n", - "pdm2 = driver.get_2pdm(ket).transpose(0, 3, 1, 2)\n", - "print('Energy from pdms = %20.15f' % (np.einsum('ij,ij->', pdm1, h1e)\n", - " + 0.5 * np.einsum('ijkl,ijkl->', pdm2, driver.unpack_g2e(g2e)) + ecore))\n", - "\n", - "impo = driver.get_identity_mpo()\n", - "expt = driver.expectation(ket, mpo, ket) / driver.expectation(ket, impo, ket)\n", - "print('Energy from expectation = %20.15f' % expt)" - ], + "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -130,11 +86,10 @@ "id": "6t5RHG5hvv8V", "outputId": "42b89155-6079-4149-8a2b-6e7515463070" }, - "execution_count": 3, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 5.977257773040786e-14\n", "integral cutoff error = 0.0\n", @@ -188,29 +143,50 @@ "Energy from expectation = -107.654122447524344\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "bond_dims = [250] * 4 + [500] * 4\n", + "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", + "thrds = [1e-10] * 8\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)\n", + "\n", + "pdm1 = driver.get_1pdm(ket)\n", + "pdm2 = driver.get_2pdm(ket).transpose(0, 3, 1, 2)\n", + "print('Energy from pdms = %20.15f' % (np.einsum('ij,ij->', pdm1, h1e)\n", + " + 0.5 * np.einsum('ijkl,ijkl->', pdm2, driver.unpack_g2e(g2e)) + ecore))\n", + "\n", + "impo = driver.get_identity_mpo()\n", + "expt = driver.expectation(ket, mpo, ket) / driver.expectation(ket, impo, ket)\n", + "print('Energy from expectation = %20.15f' % expt)" ] }, { "cell_type": "markdown", - "source": [ - "We can also run non-spin-adapted DMRG (``SZ`` mode) using the restricted integrals." - ], "metadata": { "id": "ErrotOt42zbM" - } + }, + "source": [ + "We can also run non-spin-adapted DMRG (``SZ`` mode) using the restricted integrals." + ] }, { "cell_type": "code", - "source": [ - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -218,11 +194,10 @@ "id": "rUIaHYBZ2gBZ", "outputId": "51c4247a-aa65-43e7-b52a-303a7d20648a" }, - "execution_count": 4, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 7.512924107430347e-14\n", "integral cutoff error = 0.0\n", @@ -274,35 +249,30 @@ "DMRG energy = -107.654122447524500\n" ] } + ], + "source": [ + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", - "source": [ - "We can also run DMRG in spin orbitals (``SGF`` mode) using the restricted integrals, which will be much slower (for more realistic systems)." - ], "metadata": { "id": "jeeDGMB83AaU" - } + }, + "source": [ + "We can also run DMRG in spin orbitals (``SGF`` mode) using the restricted integrals, which will be much slower (for more realistic systems)." + ] }, { "cell_type": "code", - "source": [ - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", - "\n", - "driver.n_sites = ncas\n", - "g2e = driver.unpack_g2e(g2e)\n", - "orb_sym = [orb_sym[i // 2] for i in range(len(orb_sym) * 2)]\n", - "n_sites = ncas * 2\n", - "\n", - "driver.initialize_system(n_sites=n_sites, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -310,11 +280,10 @@ "id": "yM1JgseK26_K", "outputId": "31bbbd40-2cce-42d7-d331-900a132adc33" }, - "execution_count": 5, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 7.512924107430346e-14\n", "integral cutoff error = 0.0\n", @@ -376,52 +345,40 @@ "DMRG energy = -107.654122437940984\n" ] } + ], + "source": [ + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", + "\n", + "driver.n_sites = ncas\n", + "g2e = driver.unpack_g2e(g2e)\n", + "orb_sym = [orb_sym[i // 2] for i in range(len(orb_sym) * 2)]\n", + "n_sites = ncas * 2\n", + "\n", + "driver.initialize_system(n_sites=n_sites, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", + "metadata": { + "id": "Tv12wxAZ-__F" + }, "source": [ "## Read and Write FCIDUMP Files\n", "\n", "Instead of generating integrals (``h1e`` and ``g2e``) using ``pyscf``, we can also read these integrals from a FCIDUMP file (which can be generated using any of many other quantum chemistry packages) then perform DMRG. Additionally, we also provide methods to write the FCIDUMP file using the data in the ``h1e`` and ``g2e`` arrays.\n", "\n", "After invoking ``driver.read_fcidump``, the integrals and target state infomation can be obtained from ``driver.h1e``, ``driver.g2e``, ``driver.n_sites``, etc." - ], - "metadata": { - "id": "Tv12wxAZ-__F" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", - "\n", - "# write integrals to file\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "driver.write_fcidump(h1e, g2e, ecore, filename='N2.STO3G.FCIDUMP', h1e_symm=True, pg='d2h')\n", - "\n", - "# read integrals from file\n", - "driver.read_fcidump(filename='N2.STO3G.FCIDUMP', pg='d2h')\n", - "driver.initialize_system(n_sites=driver.n_sites, n_elec=driver.n_elec,\n", - " spin=driver.spin, orb_sym=driver.orb_sym)\n", - "\n", - "bond_dims = [250] * 4 + [500] * 4\n", - "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", - "thrds = [1e-10] * 8\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=driver.h1e, g2e=driver.g2e, ecore=driver.ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -429,11 +386,10 @@ "id": "iPFRxRzO9MQe", "outputId": "f1675633-7e1f-4ba5-a90f-05ebd44865db" }, - "execution_count": 6, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "symmetrize error = 2.3300000000000018e-14\n", "integral symmetrize error = 0.0\n", @@ -486,38 +442,51 @@ "DMRG energy = -107.654122447524614\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## The ``SZ`` Mode\n", - "\n", - "Here we use ``get_uhf_integrals`` function to get the integrals." ], - "metadata": { - "id": "-auHBxs_5KpK" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", + "\n", + "# write integrals to file\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "driver.write_fcidump(h1e, g2e, ecore, filename='N2.STO3G.FCIDUMP', h1e_symm=True, pg='d2h')\n", "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "# read integrals from file\n", + "driver.read_fcidump(filename='N2.STO3G.FCIDUMP', pg='d2h')\n", + "driver.initialize_system(n_sites=driver.n_sites, n_elec=driver.n_elec,\n", + " spin=driver.spin, orb_sym=driver.orb_sym)\n", + "\n", + "bond_dims = [250] * 4 + [500] * 4\n", + "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", + "thrds = [1e-10] * 8\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=driver.h1e, g2e=driver.g2e, ecore=driver.ecore, iprint=1)\n", "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-auHBxs_5KpK" + }, + "source": [ + "## The ``SZ`` Mode\n", + "\n", + "Here we use ``get_uhf_integrals`` function to get the integrals." + ] + }, + { + "cell_type": "code", + "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -525,11 +494,10 @@ "id": "dQ_84lHJ3Zbw", "outputId": "15c0188e-5949-4520-d54b-299f88651a0c" }, - "execution_count": 7, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 1.5366482610151817e-13\n", "integral cutoff error = 0.0\n", @@ -581,30 +549,16 @@ "DMRG energy = -107.654122447524529\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## The ``SGF`` Mode\n", - "\n", - "Here we use ``get_ghf_integrals`` function to get the integrals." ], - "metadata": { - "id": "xBptlc0J5m7x" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_ghf_integrals(mf,\n", + "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", @@ -612,7 +566,22 @@ "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xBptlc0J5m7x" + }, + "source": [ + "## The ``SGF`` Mode\n", + "\n", + "Here we use ``get_ghf_integrals`` function to get the integrals." + ] + }, + { + "cell_type": "code", + "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -620,11 +589,10 @@ "id": "4aRS3PNz5iCK", "outputId": "5be98ef4-5317-4af5-de6f-a52896f3d48c" }, - "execution_count": 8, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 2.1082787907764326e-13\n", "integral cutoff error = 0.0\n", @@ -686,23 +654,7 @@ "DMRG energy = -107.654122431266543\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## The ``SGB`` Mode\n", - "\n", - "In this section, we try to solve the problem by first transfroming the model into a qubit (spin) model. The code will automatically use Jordan-Wigner transform to change the fermionic operators in the Hamiltonian into spin operators, before constructing the MPO.\n", - "\n", - "To use the ``SGB`` mode for ab initio systems, remember to add the ``heis_twos=1`` parameter (indicating the 1/2 spin at each site) in ``driver.initialize_system``." ], - "metadata": { - "id": "R_uMrwZk_eY9" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", @@ -711,15 +663,32 @@ "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_ghf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGB, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym, heis_twos=1)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "R_uMrwZk_eY9" + }, + "source": [ + "## The ``SGB`` Mode\n", + "\n", + "In this section, we try to solve the problem by first transfroming the model into a qubit (spin) model. The code will automatically use Jordan-Wigner transform to change the fermionic operators in the Hamiltonian into spin operators, before constructing the MPO.\n", + "\n", + "To use the ``SGB`` mode for ab initio systems, remember to add the ``heis_twos=1`` parameter (indicating the 1/2 spin at each site) in ``driver.initialize_system``." + ] + }, + { + "cell_type": "code", + "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -727,11 +696,10 @@ "id": "4YxKU9N-_xom", "outputId": "2c2bc416-4f57-45a5-9f97-6325140f46ac" }, - "execution_count": 9, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 2.140864794887064e-13\n", "integral cutoff error = 0.0\n", @@ -793,40 +761,41 @@ "DMRG energy = -107.654122437940899\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_ghf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGB, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym, heis_twos=1)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", + "metadata": { + "id": "yM7OGJQV556O" + }, "source": [ "## Relativistic DMRG\n", "\n", "For relativistic DMRG, we use ``get_dhf_integrals`` function to get the integrals. We use the ``SGFCPX`` Mode in ``block2`` to execute DMRG. Note that the integrals, MPO, and MPS will all contain complex numbers in this mode.\n", "\n", "The ``symm_type`` parameter ``SymmetryTypes.SGFCPX`` can also be written as ``SymmetryTypes.SGF | SymmetryTypes.CPX``." - ], - "metadata": { - "id": "yM7OGJQV556O" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.DHF(mol).set(with_gaunt=True, with_breit=True).run(conv_tol=1E-12)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_dhf_integrals(mf,\n", - " ncore=0, ncas=None, pg_symm=False)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGFCPX, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -834,11 +803,10 @@ "id": "16tFcwdw50gU", "outputId": "747910db-d6fd-4239-a496-7b7495fd8d6e" }, - "execution_count": 10, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "integral symmetrize error = 0.0\n", "integral cutoff error = 1.5501285354427146e-20\n", @@ -900,10 +868,30 @@ "DMRG energy = -107.692920949170755\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.DHF(mol).set(with_gaunt=True, with_breit=True).run(conv_tol=1E-12)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_dhf_integrals(mf,\n", + " ncore=0, ncas=None, pg_symm=False)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGFCPX, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", + "metadata": { + "id": "xZEMwvUYrfXT" + }, "source": [ "## The ``LZ`` Mode\n", "\n", @@ -912,34 +900,11 @@ "The ``LZ`` mode can be combined with ``SU2``, ``SZ`` or ``SGF`` spin symmetries, and the ``SAny`` prefix in ``SymmetryTypes``. To activate the ``SAny`` prefix, the ``block2`` code needs to be compiled with the ``-DUSE_SANY=ON`` option (this option is ON by default in the ``pip`` precompiled binaries). Optionally, when ``-DUSE_SANY=ON``, one can also set ``-DUSE_SG=OFF -DUSE_SU2SZ=OFF`` to disable the normal ``SU2/SZ/SGF`` modes. One can use ``SymmetryTypes.SAnySU2/SymmetryTypes.SAnySZ/SymmetryTypes.SAnySGF`` instead for normal symmetries (with some limitations) when ``-DUSE_SG=OFF -DUSE_SU2SZ=OFF`` is used.\n", "\n", "With ``SU2`` (spin-adapted DMRG):" - ], - "metadata": { - "id": "xZEMwvUYrfXT" - } + ] }, { "cell_type": "code", - "source": [ - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"dooh\", verbose=0)\n", - "mol.symm_orb, z_irrep, g_irrep = itg.lz_symm_adaptation(mol)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=1, irrep_id=z_irrep)\n", - "print(orb_sym_z)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySU2LZ, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym_z, pg_irrep=0)\n", - "\n", - "bond_dims = [250] * 4 + [500] * 4\n", - "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", - "thrds = [1e-10] * 8\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -947,11 +912,10 @@ "id": "r_QeMxLzvcD8", "outputId": "7ee79743-45fd-4226-ecca-b5466f0316f3" }, - "execution_count": 11, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "[ 0 0 0 0 -1 1 0 1 -1 0]\n", "integral symmetrize error = 2.0562981879479644e-15\n", @@ -1004,28 +968,16 @@ "DMRG energy = -107.654122447523761\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "With ``SZ`` (non-spin-adapted DMRG):" ], - "metadata": { - "id": "s2TkncgDvl6v" - } - }, - { - "cell_type": "code", "source": [ "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"dooh\", verbose=0)\n", "mol.symm_orb, z_irrep, g_irrep = itg.lz_symm_adaptation(mol)\n", - "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_uhf_integrals(mf,\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=1, irrep_id=z_irrep)\n", "print(orb_sym_z)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySZLZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySU2LZ, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym_z, pg_irrep=0)\n", "\n", "bond_dims = [250] * 4 + [500] * 4\n", @@ -1037,7 +989,20 @@ "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "s2TkncgDvl6v" + }, + "source": [ + "With ``SZ`` (non-spin-adapted DMRG):" + ] + }, + { + "cell_type": "code", + "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1045,11 +1010,10 @@ "id": "wTX3hBE1vniu", "outputId": "11a55e49-7674-4ef3-b5e9-55749a7a84da" }, - "execution_count": 12, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "[ 0 0 0 0 -1 1 0 1 -1 0]\n", "integral symmetrize error = 8.030340066584701e-15\n", @@ -1102,71 +1066,41 @@ "DMRG energy = -107.654122445468332\n" ] } + ], + "source": [ + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"dooh\", verbose=0)\n", + "mol.symm_orb, z_irrep, g_irrep = itg.lz_symm_adaptation(mol)\n", + "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_uhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=1, irrep_id=z_irrep)\n", + "print(orb_sym_z)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySZLZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym_z, pg_irrep=0)\n", + "\n", + "bond_dims = [250] * 4 + [500] * 4\n", + "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", + "thrds = [1e-10] * 8\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", - "source": [ - "With ``SGF`` (spin-orbital DMRG):" - ], "metadata": { "id": "Xvb_7dJKvwBo" - } + }, + "source": [ + "With ``SGF`` (spin-orbital DMRG):" + ] }, { "cell_type": "code", - "source": [ - "from pyscf.scf.ghf_symm import GHF\n", - "from pyscf import symm, lib\n", - "from pyscf.scf import hf_symm\n", - "import scipy.linalg\n", - "import numpy as np\n", - "\n", - "# fix pyscf 2.3.0 bug in ghf_symm for complex orbtials\n", - "def ghf_eig(self, h, s, symm_orb=None, irrep_id=None):\n", - " if symm_orb is None or irrep_id is None:\n", - " mol = self.mol\n", - " symm_orb = mol.symm_orb\n", - " irrep_id = mol.irrep_id\n", - " nirrep = len(symm_orb)\n", - " symm_orb = [scipy.linalg.block_diag(c, c) for c in symm_orb]\n", - " h = symm.symmetrize_matrix(h, symm_orb)\n", - " s = symm.symmetrize_matrix(s, symm_orb)\n", - " cs = []\n", - " es = []\n", - " orbsym = []\n", - " for ir in range(nirrep):\n", - " e, c = self._eigh(h[ir], s[ir])\n", - " cs.append(c)\n", - " es.append(e)\n", - " orbsym.append([irrep_id[ir]] * e.size)\n", - " e = np.hstack(es)\n", - " c = hf_symm.so2ao_mo_coeff(symm_orb, cs)\n", - " c = lib.tag_array(c, orbsym=np.hstack(orbsym))\n", - " return e, c\n", - "\n", - "GHF.eig = ghf_eig\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"dooh\", verbose=0)\n", - "mol.symm_orb, z_irrep, g_irrep = itg.lz_symm_adaptation(mol)\n", - "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_ghf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=1, irrep_id=z_irrep)\n", - "print(orb_sym_z)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySGFLZ, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym_z, pg_irrep=0)\n", - "\n", - "bond_dims = [250] * 4 + [500] * 4\n", - "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", - "thrds = [1e-10] * 8\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1174,11 +1108,10 @@ "id": "h-v3TPOjv0JX", "outputId": "4277a6f6-c33f-4f52-a752-4e5434fddcb7" }, - "execution_count": 13, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "[ 0 0 0 0 0 0 0 0 -1 -1 1 1 0 0 1 1 -1 -1 0 0]\n", "integral symmetrize error = 9.305335353847714e-15\n", @@ -1241,63 +1174,83 @@ "DMRG energy = -107.654122445469270\n" ] } + ], + "source": [ + "from pyscf.scf.ghf_symm import GHF\n", + "from pyscf import symm, lib\n", + "from pyscf.scf import hf_symm\n", + "import scipy.linalg\n", + "import numpy as np\n", + "\n", + "# fix pyscf 2.3.0 bug in ghf_symm for complex orbtials\n", + "def ghf_eig(self, h, s, symm_orb=None, irrep_id=None):\n", + " if symm_orb is None or irrep_id is None:\n", + " mol = self.mol\n", + " symm_orb = mol.symm_orb\n", + " irrep_id = mol.irrep_id\n", + " nirrep = len(symm_orb)\n", + " symm_orb = [scipy.linalg.block_diag(c, c) for c in symm_orb]\n", + " h = symm.symmetrize_matrix(h, symm_orb)\n", + " s = symm.symmetrize_matrix(s, symm_orb)\n", + " cs = []\n", + " es = []\n", + " orbsym = []\n", + " for ir in range(nirrep):\n", + " e, c = self._eigh(h[ir], s[ir])\n", + " cs.append(c)\n", + " es.append(e)\n", + " orbsym.append([irrep_id[ir]] * e.size)\n", + " e = np.hstack(es)\n", + " c = hf_symm.so2ao_mo_coeff(symm_orb, cs)\n", + " c = lib.tag_array(c, orbsym=np.hstack(orbsym))\n", + " return e, c\n", + "\n", + "GHF.eig = ghf_eig\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"dooh\", verbose=0)\n", + "mol.symm_orb, z_irrep, g_irrep = itg.lz_symm_adaptation(mol)\n", + "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym_z = itg.get_ghf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=1, irrep_id=z_irrep)\n", + "print(orb_sym_z)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SAnySGFLZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym_z, pg_irrep=0)\n", + "\n", + "bond_dims = [250] * 4 + [500] * 4\n", + "noises = [1e-4] * 4 + [1e-5] * 4 + [0]\n", + "thrds = [1e-10] * 8\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", - "source": [ - "## Expectation and N-Particle Density Matrices" - ], "metadata": { "id": "r8wd-wIq7pKV" - } + }, + "source": [ + "## Expectation and N-Particle Density Matrices" + ] }, { "cell_type": "markdown", + "metadata": { + "id": "Q2jepYQu7vOW" + }, "source": [ "Once the optimized MPS is obtained, we can compute the expectation value on it, including its norm, the energy expectation, $\\langle S^2 \\rangle$, N-particle density matrix, or any operator that can be constructed as an MPO.\n", "\n", "In this example, we compute the triplet state." - ], - "metadata": { - "id": "Q2jepYQu7vOW" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "spin = 2\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)\n", - "\n", - "impo = driver.get_identity_mpo()\n", - "\n", - "norm = driver.expectation(ket, impo, ket)\n", - "ener = driver.expectation(ket, mpo, ket)\n", - "\n", - "print('Norm = %20.15f' % norm)\n", - "print('Energy expectation = %20.15f' % (ener / norm))\n", - "\n", - "# [ in spin-adapted mode this is always S(S+1) ]\n", - "ssq_mpo = driver.get_spin_square_mpo(iprint=0)\n", - "ssq = driver.expectation(ket, ssq_mpo, ket)\n", - "print(' expectation = %20.15f' % (ssq / norm))" - ], + "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1305,11 +1258,10 @@ "id": "sYihDUiI6mTn", "outputId": "f5c207d9-c177-4bcb-df29-03d10a134b54" }, - "execution_count": 14, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1345,10 +1297,46 @@ " expectation = 2.000000000000000\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "spin = 2\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", + "\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)\n", + "\n", + "impo = driver.get_identity_mpo()\n", + "\n", + "norm = driver.expectation(ket, impo, ket)\n", + "ener = driver.expectation(ket, mpo, ket)\n", + "\n", + "print('Norm = %20.15f' % norm)\n", + "print('Energy expectation = %20.15f' % (ener / norm))\n", + "\n", + "# [ in spin-adapted mode this is always S(S+1) ]\n", + "ssq_mpo = driver.get_spin_square_mpo(iprint=0)\n", + "ssq = driver.expectation(ket, ssq_mpo, ket)\n", + "print(' expectation = %20.15f' % (ssq / norm))" ] }, { "cell_type": "markdown", + "metadata": { + "id": "5uw83pUS9hkY" + }, "source": [ "We can also evaluate expectation of arbitray operator such as the occupancy in the first orbital\n", "\n", @@ -1356,21 +1344,11 @@ "\\hat{N}_0 = a^\\dagger_{0\\alpha} a_{0\\alpha} + a^\\dagger_{0\\beta} a_{0\\beta}\n", "= \\sqrt{2} \\big(a_0^\\dagger\\big)^{[1/2]} \\otimes_{[0]} \\big(a_0\\big)^{[1/2]}\n", "$$" - ], - "metadata": { - "id": "5uw83pUS9hkY" - } + ] }, { "cell_type": "code", - "source": [ - "b = driver.expr_builder()\n", - "b.add_term(\"(C+D)0\", [0, 0], np.sqrt(2))\n", - "n_mpo = driver.get_mpo(b.finalize(), iprint=0)\n", - "\n", - "n_0 = driver.expectation(ket, n_mpo, ket)\n", - "print('N0 expectation = %20.15f' % (n_0 / norm))" - ], + "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1378,32 +1356,36 @@ "id": "gRqEzZnK8d8h", "outputId": "ad42a465-fc27-4ba2-b1d9-52fdec3a164c" }, - "execution_count": 15, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "N0 expectation = 1.999995824361892\n" ] } + ], + "source": [ + "b = driver.expr_builder()\n", + "b.add_term(\"(C+D)0\", [0, 0], np.sqrt(2))\n", + "n_mpo = driver.get_mpo(b.finalize(), iprint=0)\n", + "\n", + "n_0 = driver.expectation(ket, n_mpo, ket)\n", + "print('N0 expectation = %20.15f' % (n_0 / norm))" ] }, { "cell_type": "markdown", - "source": [ - "We can then verify this number using 1PDM:" - ], "metadata": { "id": "axO7Quw3-L9v" - } + }, + "source": [ + "We can then verify this number using 1PDM:" + ] }, { "cell_type": "code", - "source": [ - "pdm1 = driver.get_1pdm(ket)\n", - "print('N0 expectation from 1pdm = %20.15f' % pdm1[0, 0])" - ], + "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1411,19 +1393,25 @@ "id": "AiPieq3Z-JrA", "outputId": "f1bc42fc-8892-4380-ffaa-8a16980faf9b" }, - "execution_count": 16, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "N0 expectation from 1pdm = 1.999995824361892\n" ] } + ], + "source": [ + "pdm1 = driver.get_1pdm(ket)\n", + "print('N0 expectation from 1pdm = %20.15f' % pdm1[0, 0])" ] }, { "cell_type": "markdown", + "metadata": { + "id": "xdFhzPE7-rb6" + }, "source": [ "We can compute the 3PDM and compare the result with the FCI 3PDM. Note that in ``pyscf`` the 3PDM is defined as\n", "\n", @@ -1432,25 +1420,11 @@ "$$\n", "\n", "So we have to use the same convention in ``block2`` by setting the ``npdm_expr`` parameter in ``block2`` to ``((C+D)0+((C+D)0+(C+D)0)0)0``.\n" - ], - "metadata": { - "id": "xdFhzPE7-rb6" - } + ] }, { "cell_type": "code", - "source": [ - "pdm3_b2 = driver.get_3pdm(ket, iprint=0, npdm_expr=\"((C+D)0+((C+D)0+(C+D)0)0)0\")\n", - "\n", - "from pyscf import fci\n", - "\n", - "mx = fci.addons.fix_spin_(fci.FCI(mf), ss=2)\n", - "mx.kernel(h1e, g2e, ncas, nelec=n_elec, nroots=3, tol=1E-12)\n", - "print(mx.e_tot)\n", - "pdm3_fci = fci.rdm.make_dm123('FCI3pdm_kern_sf', mx.ci[0], mx.ci[0], ncas, n_elec)[2]\n", - "\n", - "print('diff = ', np.linalg.norm(pdm3_fci - pdm3_b2))" - ], + "execution_count": 17, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1458,53 +1432,45 @@ "id": "NIxjfBJP-byp", "outputId": "ab007aea-f900-4655-8e29-69dec7ff35cd" }, - "execution_count": 17, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "[-106.93913286 -106.85412245 -106.70055113]\n", "diff = 4.622993128790701e-06\n" ] } + ], + "source": [ + "pdm3_b2 = driver.get_3pdm(ket, iprint=0, npdm_expr=\"((C+D)0+((C+D)0+(C+D)0)0)0\")\n", + "\n", + "from pyscf import fci\n", + "\n", + "mx = fci.addons.fix_spin_(fci.FCI(mf), ss=2)\n", + "mx.kernel(h1e, g2e, ncas, nelec=n_elec, nroots=3, tol=1E-12)\n", + "print(mx.e_tot)\n", + "pdm3_fci = fci.rdm.make_dm123('FCI3pdm_kern_sf', mx.ci[0], mx.ci[0], ncas, n_elec)[2]\n", + "\n", + "print('diff = ', np.linalg.norm(pdm3_fci - pdm3_b2))" ] }, { "cell_type": "markdown", + "metadata": { + "id": "j5ywJ3n9xaQx" + }, "source": [ "## Extract CSF and Determinant Coefficients\n", "\n", "We can extract CSF (or determinant) coefficients from the spin-adapted MPS (or the non-spin-adapted MPS). The algorithm can compute all CSF or determinant with the absolute value of the coefficient above a threshold (called ``cutoff``). The square of coefficient is the probability (weight) of the CSF or determinant.\n", "\n", "Extracting CSF coefficients from spin-adapted MPS in the ``SU2`` mode:" - ], - "metadata": { - "id": "j5ywJ3n9xaQx" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)\n", - "\n", - "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)" - ], + "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1512,11 +1478,10 @@ "id": "wlUvVFbTxUxt", "outputId": "eccfad81-b7e8-4184-f61e-19222ad56b2d" }, - "execution_count": 18, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1562,28 +1527,16 @@ "CSF 8 22222++-0- = 0.053881215166769\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "Extracting determinant coefficients from spin-adapted MPS in the ``SZ`` mode:" ], - "metadata": { - "id": "Xo2eVRUfy7xE" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", @@ -1594,7 +1547,20 @@ "print('DMRG energy = %20.15f' % energy)\n", "\n", "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Xo2eVRUfy7xE" + }, + "source": [ + "Extracting determinant coefficients from spin-adapted MPS in the ``SZ`` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1602,11 +1568,10 @@ "id": "JEGGNKwBy0Rj", "outputId": "f51b236b-eb13-4bdf-e103-5400f7ff29a9" }, - "execution_count": 19, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1650,32 +1615,16 @@ "DET 6 2220222020 = -0.054710439530678\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Construct MPS from CSFs or Determinants\n", - "\n", - "If we know important CSFs or determinants in the state and their coefficients, we can also use this information to construct MPS, and this can be used as an initial guess and further optimized. Note that this initial guess can generate very good initial energies, but if the given CSFs have many doubly occupied and empty orbitals, the MPS will very likely optimize to a local minima.\n", - "\n", - "In the ``SU2`` mode:" ], - "metadata": { - "id": "NhiNjmry-D8D" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", @@ -1685,17 +1634,25 @@ " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)\n", "\n", - "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", + "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NhiNjmry-D8D" + }, + "source": [ + "## Construct MPS from CSFs or Determinants\n", "\n", - "mps = driver.get_mps_from_csf_coefficients(csfs, coeffs, tag=\"CMPS\", dot=2)\n", - "impo = driver.get_identity_mpo()\n", - "print(driver.expectation(mps, impo, mps))\n", - "print(driver.expectation(mps, mpo, mps) / driver.expectation(mps, impo, mps))\n", + "If we know important CSFs or determinants in the state and their coefficients, we can also use this information to construct MPS, and this can be used as an initial guess and further optimized. Note that this initial guess can generate very good initial energies, but if the given CSFs have many doubly occupied and empty orbitals, the MPS will very likely optimize to a local minima.\n", "\n", - "energy = driver.dmrg(mpo, mps, n_sweeps=5, bond_dims=[500] * 5, noises=[1E-5],\n", - " thrds=[1E-10] * 5, iprint=1)\n", - "print('Ground state energy = %20.15f' % energy)" - ], + "In the ``SU2`` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1703,11 +1660,10 @@ "id": "Xu_MA3r3Mb5g", "outputId": "fa80d736-d770-4e5c-e0cf-e711dcdee6f2" }, - "execution_count": 20, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1769,28 +1725,16 @@ "Ground state energy = -107.628901971339317\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "In the ``SZ`` mode:" ], - "metadata": { - "id": "zCHMLB2kOGOY" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", @@ -1800,9 +1744,9 @@ " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)\n", "\n", - "dets, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", + "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", "\n", - "mps = driver.get_mps_from_csf_coefficients(dets, coeffs, tag=\"CMPS\", dot=2)\n", + "mps = driver.get_mps_from_csf_coefficients(csfs, coeffs, tag=\"CMPS\", dot=2)\n", "impo = driver.get_identity_mpo()\n", "print(driver.expectation(mps, impo, mps))\n", "print(driver.expectation(mps, mpo, mps) / driver.expectation(mps, impo, mps))\n", @@ -1810,7 +1754,20 @@ "energy = driver.dmrg(mpo, mps, n_sweeps=5, bond_dims=[500] * 5, noises=[1E-5],\n", " thrds=[1E-10] * 5, iprint=1)\n", "print('Ground state energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zCHMLB2kOGOY" + }, + "source": [ + "In the ``SZ`` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1818,11 +1775,10 @@ "id": "MGIr2B15OHoq", "outputId": "054476e8-8c98-490b-ba23-9592c9f8b0ad" }, - "execution_count": 21, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1882,10 +1838,42 @@ "Ground state energy = -107.610475947024796\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", + "\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)\n", + "\n", + "dets, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", + "\n", + "mps = driver.get_mps_from_csf_coefficients(dets, coeffs, tag=\"CMPS\", dot=2)\n", + "impo = driver.get_identity_mpo()\n", + "print(driver.expectation(mps, impo, mps))\n", + "print(driver.expectation(mps, mpo, mps) / driver.expectation(mps, impo, mps))\n", + "\n", + "energy = driver.dmrg(mpo, mps, n_sweeps=5, bond_dims=[500] * 5, noises=[1E-5],\n", + " thrds=[1E-10] * 5, iprint=1)\n", + "print('Ground state energy = %20.15f' % energy)" ] }, { "cell_type": "markdown", + "metadata": { + "id": "lKczQwpW-KzH" + }, "source": [ "## MPS Initial Guess from Occupancies\n", "\n", @@ -1894,34 +1882,11 @@ "Note that this initial guess can generate very good energies in the first few sweeps, but if the given occupancies have many doubly occupied and empty orbitals, the MPS will very likely optimize to a local minima. One can shift the occupancies into the equal probability occupancies (for example, setting ``bias=0.4`` in the example below) to randomize the initial guess.\n", "\n", "In the ``SU2`` mode:" - ], - "metadata": { - "id": "lKczQwpW-KzH" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf, cc\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "bias = 0.1 # make it more random\n", - "occs = np.diag(cc.CCSD(mf).run().make_rdm1())\n", - "occs = occs + bias * (occs < 1) - bias * (occs > 1)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, occs=occs, nroots=1)\n", - "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", - " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)" - ], + "execution_count": 22, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1929,11 +1894,10 @@ "id": "89CYdAQERbng", "outputId": "e5467ea7-8556-4cf0-ca29-382f2bec616e" }, - "execution_count": 22, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -1966,32 +1930,20 @@ "DMRG energy = -107.586815246376730\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "In the ``SZ`` mode:" ], - "metadata": { - "id": "MBBhzM1DRlEC" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf, cc\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", "bias = 0.1 # make it more random\n", - "occs = np.diag(np.sum(cc.UCCSD(mf).run().make_rdm1(), axis=0))\n", + "occs = np.diag(cc.CCSD(mf).run().make_rdm1())\n", "occs = occs + bias * (occs < 1) - bias * (occs > 1)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", @@ -1999,7 +1951,20 @@ "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MBBhzM1DRlEC" + }, + "source": [ + "In the ``SZ`` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -2007,11 +1972,10 @@ "id": "EFggxZINRmky", "outputId": "2f628385-bc32-4746-8221-3c89711c57a9" }, - "execution_count": 23, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2044,32 +2008,20 @@ "DMRG energy = -107.586815246376730\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "In the ``SGF`` mode:" ], - "metadata": { - "id": "QEmsn2bvSDPv" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf, cc\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_ghf_integrals(mf,\n", + "mf = scf.UHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_uhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "bias = 0.25 # make it more random\n", - "occs = np.sum(cc.GCCSD(mf).run().make_rdm1(), axis=0)\n", - "occs = occs + bias * (occs < 0.5) - bias * (occs > 0.5)\n", + "bias = 0.1 # make it more random\n", + "occs = np.diag(np.sum(cc.UCCSD(mf).run().make_rdm1(), axis=0))\n", + "occs = occs + bias * (occs < 1) - bias * (occs > 1)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", @@ -2077,7 +2029,20 @@ "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QEmsn2bvSDPv" + }, + "source": [ + "In the ``SGF`` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -2085,11 +2050,10 @@ "id": "5ov6ybDJSEqY", "outputId": "97325ac1-7c03-467e-8051-de10f7802d13" }, - "execution_count": 24, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2122,51 +2086,45 @@ "DMRG energy = -107.653950682884570\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Change from SU2 MPS to SZ MPS\n", - "\n", - "We can also transform the spin-adapted MPS generated in the ``SU2`` mode to the non-spin-adapted MPS, which can be used in the ``SZ`` mode. After obtaining the non-spin-adapted MPS, one need to redo ``driver.initialize_system``, ``driver.get_qc_mpo``, etc. to make sure every object is now represented in the ``SZ`` mode, then you can operate on the ``SZ`` non-spin-adapted MPS.\n", - "\n", - "In the following example, we first compute the spin-adapted MPS, then translate it into the non-spin-adapted MPS to extract the determinant coefficients." ], - "metadata": { - "id": "pHzJ0eA09yM3" - } - }, - { - "cell_type": "code", "source": [ - "from pyscf import gto, scf\n", + "from pyscf import gto, scf, cc\n", "\n", "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + "mf = scf.GHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_ghf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", + "bias = 0.25 # make it more random\n", + "occs = np.sum(cc.GCCSD(mf).run().make_rdm1(), axis=0)\n", + "occs = occs + bias * (occs < 0.5) - bias * (occs > 0.5)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SGF, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "\n", - "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, occs=occs, nroots=1)\n", "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", " thrds=thrds, iprint=1)\n", - "print('DMRG energy = %20.15f' % energy)\n", + "print('DMRG energy = %20.15f' % energy)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pHzJ0eA09yM3" + }, + "source": [ + "## Change from SU2 MPS to SZ MPS\n", "\n", - "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", - "zket = driver.mps_change_to_sz(ket, \"ZKET\")\n", + "We can also transform the spin-adapted MPS generated in the ``SU2`` mode to the non-spin-adapted MPS, which can be used in the ``SZ`` mode. After obtaining the non-spin-adapted MPS, one need to redo ``driver.initialize_system``, ``driver.get_qc_mpo``, etc. to make sure every object is now represented in the ``SZ`` mode, then you can operate on the ``SZ`` non-spin-adapted MPS.\n", "\n", - "driver.symm_type = SymmetryTypes.SZ\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "impo = driver.get_identity_mpo()\n", - "print(driver.expectation(zket, mpo, zket) / driver.expectation(zket, impo, zket))\n", - "csfs, vals = driver.get_csf_coefficients(zket, cutoff=0.05, iprint=1)" - ], + "In the following example, we first compute the spin-adapted MPS, then translate it into the non-spin-adapted MPS to extract the determinant coefficients." + ] + }, + { + "cell_type": "code", + "execution_count": 25, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -2174,11 +2132,10 @@ "id": "bshiEyU9TIcg", "outputId": "7d23f0e3-a348-422a-c3f1-53c48d0500c0" }, - "execution_count": 25, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2235,24 +2192,8 @@ "DET 5 2220222020 = 0.054710523921704\n", "DET 6 2220222200 = 0.054710517406346\n" ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Change between Real and Complex MPS\n", - "\n", - "We can also change between the MPS with complex numbers and the MPS with real numbers. For complex MPS to real MPS, the imaginary part will be discarded (and the norm of the transformed MPS may decrease). This may be useful when you do a ground state calculation in the real domain and then do the real time evolution in the complex domain.\n", - "\n", - "From real to complex:" - ], - "metadata": { - "id": "DI9giYpoVAl4" - } - }, - { - "cell_type": "code", + } + ], "source": [ "from pyscf import gto, scf\n", "\n", @@ -2264,7 +2205,6 @@ "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", - "impo = driver.get_identity_mpo()\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", "\n", "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", @@ -2272,17 +2212,33 @@ " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)\n", "\n", - "print(driver.expectation(ket, impo, ket))\n", - "print(driver.expectation(ket, mpo, ket) / driver.expectation(ket, impo, ket))\n", - "zket = driver.mps_change_complex(ket, \"ZKET\")\n", + "csfs, coeffs = driver.get_csf_coefficients(ket, cutoff=0.05, iprint=1)\n", + "zket = driver.mps_change_to_sz(ket, \"ZKET\")\n", "\n", - "driver.symm_type = driver.symm_type ^ SymmetryTypes.CPX\n", + "driver.symm_type = SymmetryTypes.SZ\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", "impo = driver.get_identity_mpo()\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, integral_cutoff=1E-8, iprint=1)\n", - "print(driver.expectation(zket, impo, zket))\n", - "print(driver.expectation(zket, mpo, zket) / driver.expectation(zket, impo, zket))" - ], + "print(driver.expectation(zket, mpo, zket) / driver.expectation(zket, impo, zket))\n", + "csfs, vals = driver.get_csf_coefficients(zket, cutoff=0.05, iprint=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DI9giYpoVAl4" + }, + "source": [ + "## Change between Real and Complex MPS\n", + "\n", + "We can also change between the MPS with complex numbers and the MPS with real numbers. For complex MPS to real MPS, the imaginary part will be discarded (and the norm of the transformed MPS may decrease). This may be useful when you do a ground state calculation in the real domain and then do the real time evolution in the complex domain.\n", + "\n", + "From real to complex:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -2290,11 +2246,10 @@ "id": "POXO7BS5TjuT", "outputId": "73ad27dd-0f5a-4c88-d55e-fba1c85b4416" }, - "execution_count": 26, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2350,19 +2305,7 @@ "(-107.65412244752457+0j)\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "From complex to real:" ], - "metadata": { - "id": "8lXIUcWqUYvQ" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", @@ -2371,7 +2314,7 @@ "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2 | SymmetryTypes.CPX, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", "impo = driver.get_identity_mpo()\n", @@ -2384,15 +2327,28 @@ "\n", "print(driver.expectation(ket, impo, ket))\n", "print(driver.expectation(ket, mpo, ket) / driver.expectation(ket, impo, ket))\n", - "rket = driver.mps_change_complex(ket, \"rket\")\n", + "zket = driver.mps_change_complex(ket, \"ZKET\")\n", "\n", "driver.symm_type = driver.symm_type ^ SymmetryTypes.CPX\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "impo = driver.get_identity_mpo()\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, integral_cutoff=1E-8, iprint=1)\n", - "print(driver.expectation(rket, impo, rket))\n", - "print(driver.expectation(rket, mpo, rket) / driver.expectation(rket, impo, rket))" - ], + "print(driver.expectation(zket, impo, zket))\n", + "print(driver.expectation(zket, mpo, zket) / driver.expectation(zket, impo, zket))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8lXIUcWqUYvQ" + }, + "source": [ + "From complex to real:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -2400,11 +2356,10 @@ "id": "J5F8UhOzUaoQ", "outputId": "3d4f9f89-6402-43da-b44b-3979ea522ffa" }, - "execution_count": 27, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2460,21 +2415,7 @@ "-107.65412244752437\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## MPS Bipartite Entanglement\n", - "\n", - "We can get the the bipartite entanglement $S_k=-\\sum_i \\Lambda_k^2 \\log \\Lambda_k^2$ at each virtual bond (at site $k$) in MPS in the ``SZ`` mode, where $\\Lambda_k$ are singular values in the bond at site $k$." ], - "metadata": { - "id": "HL8LI5zk0B4V" - } - }, - { - "cell_type": "code", "source": [ "from pyscf import gto, scf\n", "\n", @@ -2483,9 +2424,10 @@ "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", " ncore=0, ncas=None, g2e_symm=8)\n", "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SU2 | SymmetryTypes.CPX, n_threads=4)\n", "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", "\n", + "impo = driver.get_identity_mpo()\n", "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", "\n", "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", @@ -2493,15 +2435,32 @@ " thrds=thrds, iprint=1)\n", "print('DMRG energy = %20.15f' % energy)\n", "\n", - "bip_ent = driver.get_bipartite_entanglement()\n", + "print(driver.expectation(ket, impo, ket))\n", + "print(driver.expectation(ket, mpo, ket) / driver.expectation(ket, impo, ket))\n", + "rket = driver.mps_change_complex(ket, \"rket\")\n", "\n", - "import matplotlib.pyplot as plt\n", - "plt.plot(np.arange(len(bip_ent)), bip_ent, linestyle='-', marker='o',\n", - " mfc='white', mec=\"#7FB685\", color=\"#7FB685\")\n", - "plt.xlabel(\"site index $k$\")\n", - "plt.ylabel(\"bipartite entanglement $S_k$\")\n", - "plt.show()" - ], + "driver.symm_type = driver.symm_type ^ SymmetryTypes.CPX\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "impo = driver.get_identity_mpo()\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, integral_cutoff=1E-8, iprint=1)\n", + "print(driver.expectation(rket, impo, rket))\n", + "print(driver.expectation(rket, mpo, rket) / driver.expectation(rket, impo, rket))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HL8LI5zk0B4V" + }, + "source": [ + "## MPS Bipartite Entanglement\n", + "\n", + "We can get the the bipartite entanglement $S_k=-\\sum_i \\Lambda_k^2 \\log \\Lambda_k^2$ at each virtual bond (at site $k$) in MPS in the ``SZ`` mode, where $\\Lambda_k$ are singular values in the bond at site $k$." + ] + }, + { + "cell_type": "code", + "execution_count": 28, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -2510,11 +2469,10 @@ "id": "sk-lJfw0zBlV", "outputId": "a9d54b06-209d-4b59-fcb8-a4437be9090b" }, - "execution_count": 28, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 250 | Noise = 1.00e-04 | Dav threshold = 1.00e-10\n", @@ -2548,38 +2506,58 @@ ] }, { - "output_type": "display_data", "data": { + "image/png": "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", "text/plain": [ "
" - ], - "image/png": "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\n" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", + "\n", + "ket = driver.get_random_mps(tag=\"GS\", bond_dim=250, nroots=1)\n", + "energy = driver.dmrg(mpo, ket, n_sweeps=20, bond_dims=bond_dims, noises=noises,\n", + " thrds=thrds, iprint=1)\n", + "print('DMRG energy = %20.15f' % energy)\n", + "\n", + "bip_ent = driver.get_bipartite_entanglement()\n", + "\n", + "import matplotlib.pyplot as plt\n", + "plt.plot(np.arange(len(bip_ent)), bip_ent, linestyle='-', marker='o',\n", + " mfc='white', mec=\"#7FB685\", color=\"#7FB685\")\n", + "plt.xlabel(\"site index $k$\")\n", + "plt.ylabel(\"bipartite entanglement $S_k$\")\n", + "plt.show()" ] }, { "cell_type": "markdown", + "metadata": { + "id": "G31uZ79j2jgo" + }, "source": [ "## Orbital Entropy and Mutual Information\n", "\n", "For the optimized MPS in the ``SZ`` mode, we can compute the 1- and 2- orbital density matrices and mutual information for pairs of orbitals." - ], - "metadata": { - "id": "G31uZ79j2jgo" - } + ] }, { "cell_type": "code", - "source": [ - "odm1 = driver.get_orbital_entropies(ket, orb_type=1)\n", - "odm2 = driver.get_orbital_entropies(ket, orb_type=2)\n", - "minfo = 0.5 * (odm1[:, None] + odm1[None, :] - odm2) * (1 - np.identity(len(odm1)))\n", - "\n", - "import matplotlib.pyplot as plt\n", - "plt.matshow(minfo)" - ], + "execution_count": 29, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -2588,79 +2566,62 @@ "id": "I9tuVN4o2auM", "outputId": "d990c72a-2b88-4cc6-92fd-39f1d85f4e4d" }, - "execution_count": 29, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ "" ] }, + "execution_count": 29, "metadata": {}, - "execution_count": 29 + "output_type": "execute_result" }, { - "output_type": "display_data", "data": { + "image/png": "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", "text/plain": [ "
" - ], - "image/png": "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\n" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "odm1 = driver.get_orbital_entropies(ket, orb_type=1)\n", + "odm2 = driver.get_orbital_entropies(ket, orb_type=2)\n", + "minfo = 0.5 * (odm1[:, None] + odm1[None, :] - odm2) * (1 - np.identity(len(odm1)))\n", + "\n", + "import matplotlib.pyplot as plt\n", + "plt.matshow(minfo)" ] }, { "cell_type": "markdown", + "metadata": { + "id": "reC2RWqDOihl" + }, "source": [ "## Excited States\n", "\n", "To obtain the excited states and their energies, we can perform DMRG for a state-averged MPS, optionally followed by a state-specific refinement." - ], - "metadata": { - "id": "reC2RWqDOihl" - } + ] }, { "cell_type": "code", - "source": [ - "from pyscf import gto, scf\n", - "\n", - "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", - "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", - "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", - " ncore=0, ncas=None, g2e_symm=8)\n", - "\n", - "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", - "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", - "\n", - "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", - "\n", - "ket = driver.get_random_mps(tag=\"KET\", bond_dim=100, nroots=3)\n", - "energies = driver.dmrg(mpo, ket, n_sweeps=10, bond_dims=[100], noises=[1e-5] * 4 + [0],\n", - " thrds=[1e-10] * 8, iprint=1)\n", - "print('State-averaged MPS energies = [%s]' % \" \".join(\"%20.15f\" % x for x in energies))\n", - "\n", - "kets = [driver.split_mps(ket, ir, tag=\"KET-%d\" % ir) for ir in range(ket.nroots)]\n", - "for ir in range(ket.nroots):\n", - " energy = driver.dmrg(mpo, kets[ir], n_sweeps=10, bond_dims=[200], noises=[1e-5] * 4 + [0],\n", - " thrds=[1e-10] * 8, iprint=0, proj_weights=[5.0] * ir, proj_mpss=kets[:ir])\n", - " print('State-specific MPS E[%d] = %20.15f' % (ir, energy))" - ], + "execution_count": 30, "metadata": { - "id": "A2BXFBnJ3baF", "colab": { "base_uri": "https://localhost:8080/" }, + "id": "A2BXFBnJ3baF", "outputId": "afe6a20f-eb6c-4c6e-ec50-05466717c8be" }, - "execution_count": 30, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\n", "Sweep = 0 | Direction = forward | Bond dimension = 100 | Noise = 1.00e-05 | Dav threshold = 1.00e-10\n", @@ -2687,7 +2648,46 @@ "State-specific MPS E[2] = -106.959626154678844\n" ] } + ], + "source": [ + "from pyscf import gto, scf\n", + "\n", + "mol = gto.M(atom=\"N 0 0 0; N 0 0 1.1\", basis=\"sto3g\", symmetry=\"d2h\", verbose=0)\n", + "mf = scf.RHF(mol).run(conv_tol=1E-14)\n", + "ncas, n_elec, spin, ecore, h1e, g2e, orb_sym = itg.get_rhf_integrals(mf,\n", + " ncore=0, ncas=None, g2e_symm=8)\n", + "\n", + "driver = DMRGDriver(scratch=\"./tmp\", symm_type=SymmetryTypes.SZ, n_threads=4)\n", + "driver.initialize_system(n_sites=ncas, n_elec=n_elec, spin=spin, orb_sym=orb_sym)\n", + "\n", + "mpo = driver.get_qc_mpo(h1e=h1e, g2e=g2e, ecore=ecore, iprint=0)\n", + "\n", + "ket = driver.get_random_mps(tag=\"KET\", bond_dim=100, nroots=3)\n", + "energies = driver.dmrg(mpo, ket, n_sweeps=10, bond_dims=[100], noises=[1e-5] * 4 + [0],\n", + " thrds=[1e-10] * 8, iprint=1)\n", + "print('State-averaged MPS energies = [%s]' % \" \".join(\"%20.15f\" % x for x in energies))\n", + "\n", + "kets = [driver.split_mps(ket, ir, tag=\"KET-%d\" % ir) for ir in range(ket.nroots)]\n", + "for ir in range(ket.nroots):\n", + " energy = driver.dmrg(mpo, kets[ir], n_sweeps=10, bond_dims=[200], noises=[1e-5] * 4 + [0],\n", + " thrds=[1e-10] * 8, iprint=0, proj_weights=[5.0] * ir, proj_mpss=kets[:ir])\n", + " print('State-specific MPS E[%d] = %20.15f' % (ir, energy))" ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}