To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit 85d5440b authored by Valerio's avatar Valerio
Browse files

Solution ex 11 and text last exercise ;)

parent 0583f9b8
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from tenpy.models.lattice import Lattice\n",
"from tenpy.models.model import CouplingMPOModel\n",
"from tenpy.networks.site import SpinSite\n",
"from tenpy.tools.params import get_parameter\n",
"from tenpy.algorithms import dmrg\n",
"from tenpy.networks.mps import MPS\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import time\n",
"import random"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Model Definition"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Create a ComplingMPOModel to describe the system.\n",
"#The parameters are passed via model_params\n",
"class Heisenberg(CouplingMPOModel):\n",
"\n",
" def __init__(self,model_params):\n",
" CouplingMPOModel.__init__(self,model_params)\n",
" \n",
" def init_lattice(self, model_params):\n",
" #Here initialize the type of lattice considered\n",
" lattice = get_parameter(model_params, 'lattice', self.name, False)\n",
" return lattice\n",
" \n",
" def init_terms(self, model_params):\n",
" D= get_parameter(model_params, 'D', 0., self.name, True)\n",
" #Try to get also the J and lambda paramter in the same way\n",
" #J= ...\n",
" #lam= ...\n",
" \n",
" #Here implement the couplings of the chain\n",
" \n",
" #D term\n",
" self.add_onsite(D, 0, 'Sz Sz') \n",
" \n",
" #Heisenberg interaction\n",
" self.add_coupling(J, 0, 'Sx', 0, 'Sx', 1,) \n",
" #Implement the remaining couplings for the Heisenberg exchange\n",
" #Have a look at the documentation of the function add_coupling()\n",
" #\n",
" #\n",
" \n",
" #Quadratic Heisenberg term, the one with lambda\n",
" #Implement this term yourself\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Phase diagram for $\\lambda=0$ and varying $D$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define the model "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L=2 #Chain length (2 for the iMPS)\n",
"J=1 #Anitferromagnetic interaction\n",
"lam=0 #Quadratic term\n",
"Dmin=-1\n",
"Dmax=2\n",
"points=30\n",
"d=np.linspace(Dmin,Dmax,points,endpoint=True) #Values considered for D\n",
"\n",
"#Definition of the lattice model\n",
"#Define the local Hilbert space, have a look at the documentation of SpinSite\n",
"#site=SpinSite(...)\n",
"#Define the lattice by looking at the documentation of Lattice\n",
"#Inifinite MPS requires periodic boundaries for the lattice\n",
"#lat=Lattice(...) #We choose an infinite MPS "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Perform iDMRG"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"entEnt=[]\n",
"entSp=[]\n",
"stagMag=[]\n",
"for D in d:\n",
" \n",
" #Define the paramters of the model\n",
" model_params={\n",
" 'verbose':0,\n",
" 'J':J,\n",
" 'D':D,\n",
" 'lambda':lam, \n",
" 'lattice':lat \n",
" }\n",
"\n",
" #Create the model\n",
" chain=Heisenberg(model_params)\n",
"\n",
" #Define the paramters for the DMRG\n",
" dmrg_paramsGs = {\n",
" 'trunc_params': {\n",
" 'chi_max': 20 #Maximum bond dimension\n",
" },\n",
" 'verbose': 1\n",
" }\n",
" \n",
" #Initialize the MPS with an arbitrary product state\n",
" product_state=['up',0] \n",
" #Have a look at the documentation MPS.from_product_state()\n",
" #psiGs=MPS.from_product_state(...)\n",
" \n",
" #Perform iDMRG\n",
" #Check documentation of dmrg.run\n",
" #info=dmrg.run(...)\n",
" \n",
" #Check documentation for expectation_value(). Which operator do you want to measure for magnetization?\n",
" #mag=psiGs.expectation_value(...) #Measure magnetization\n",
" #Implement function to compute staggered magnetization from mag\n",
" #staggered=...\n",
" stagMag.append(staggered) #Compute staggered magnetization\n",
" \n",
" #Check documentation of entanglement_spectrum() and compute it\n",
" #spectrum=...\n",
" entSp.append(spectrum[0])\n",
" \n",
" #Check documentation of entanglement_entropy() and compute it\n",
" #entropy=...\n",
" entEnt.append(entropy[0])\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Study staggered magnetization"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(14,5))\n",
"plt.plot(d,stagMag,'o',ls='-',c='k')\n",
"plt.xlabel('D');\n",
"plt.ylabel('Staggered magnetization');\n",
"plt.axvspan(-1, -0.33, alpha=0.2, color='red')\n",
"plt.axvspan(-0.33, 1, alpha=0.2, color='b')\n",
"plt.axvspan(1, 2, alpha=0.2, color='g')\n",
"plt.xlim(-1,2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Study of the entanglement entropy"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(14,5))\n",
"plt.tight_layout()\n",
"plt.plot(d,entEnt,'o',ls='-',c='k')\n",
"plt.xlabel('D');\n",
"plt.ylabel('Entanglement Entropy');\n",
"plt.axvspan(-1, -0.33, alpha=0.2, color='red')\n",
"plt.axvspan(-0.33, 1, alpha=0.2, color='b')\n",
"plt.axvspan(1, 2, alpha=0.2, color='g')\n",
"plt.xlim(-1,2);"
]
},
{
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from scipy import integrate\n",
"from scipy.linalg import expm \n",
"from pylab import *\n",
"import numpy as np\n",
"from svd_robust import svd\n",
"from ed_ising import ising_gs\n",
"import scipy.sparse.linalg.eigen.arpack as arp"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"\"\"\" Conventions:\n",
"B[i,a,b] has axes (physical, left virtual, right virtual),\n",
"W[a,b,i,j] has axes (virtual left, virtual right, physical out, physical in)\n",
"S[i] are schmidt values between sites (i, i+1),\n",
"H_bond[i] is the bond hamiltonian between (i,i+1) with (only physical)\n",
"axes (out left, out right, in left, in right)\"\"\"\n",
"\n",
"def init_fm_mps(L):\n",
" \"\"\" Return FM Ising MPS\"\"\"\n",
" d = 2\n",
" B = []\n",
" s = []\n",
" for i in range(L):\n",
" B.append(np.zeros([2,1,1])); B[-1][0,0,0]=1\n",
" s.append(np.ones([1]))\n",
" s.append(np.ones([1]))\n",
" return B,s\n",
"\n",
"def init_ising_H_mpo(g,J,L):\n",
" \"\"\" Returns hamiltonian in MPO form\"\"\"\n",
" s0 = np.eye(2)\n",
" sx = np.array([[0.,1.],[1.,0.]])\n",
" sy = np.array([[0.,-1j],[1j,0.]])\n",
" sz = np.array([[1.,0.],[0.,-1.]])\n",
" d = 2\n",
" \n",
" w_list = []\n",
" for i in range(L):\n",
" w = np.zeros((3,3,d,d),dtype=np.float)\n",
" w[0,:2] = [s0,sz]\n",
" w[0:,2] = [g*sx, -J*sz, s0]\n",
" w_list.append(np.real(w))\n",
" return w_list\n",
"\n",
"def init_ising_H_bond(g,J,L):\n",
" \"\"\" Returns bond hamiltonian \"\"\"\n",
" sx = np.array([[0.,1.],[1.,0.]])\n",
" sy = np.array([[0.,-1j],[1j,0.]])\n",
" sz = np.array([[1.,0.],[0.,-1.]])\n",
" d = 2\n",
" \n",
" H_bond = []\n",
" for i in range(L-2):\n",
" H_bond.append(np.reshape(-J*np.kron(sz,sz) + g*np.kron(sx,np.eye(2)),(d,d,d,d)))\n",
" H_bond.append(np.reshape(-J*np.kron(sz,sz)+g*np.kron(sx,np.eye(2))+g*np.kron(np.eye(2),sx),(d,d,d,d)))\n",
" \n",
" return H_bond"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def bond_expectation(B,s,H_bond):\n",
" \" Expectation value for a bond operator \"\n",
" E=[]\n",
" L = len(B)\n",
" for i_bond in range(L-1):\n",
" BB = np.tensordot(B[i_bond],B[i_bond+1],axes=(2,1))\n",
" sBB = np.tensordot(np.diag(s[i_bond]),BB,axes=(1,1))\n",
" C = np.tensordot(sBB,H_bond[i_bond],axes=([1,2],[2,3]))\n",
" sBB=np.conj(sBB)\n",
" E.append(np.squeeze(np.tensordot(sBB,C,axes=([0,3,1,2],[0,1,2,3]))).item()) \n",
" return E\n",
"\n",
"def entanglement_entropy(s):\n",
" \" Returns the half chain entanglement entropy \"\n",
" S=[]\n",
" L = len(s)\n",
" for i_bond in range(L):\n",
" x=s[i_bond][s[i_bond]>10**(-20)]**2\n",
" S.append(-np.inner(np.log(x),x))\n",
" return(S)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class H_mixed(object):\n",
" \" Class of the mixed DMRG hamiltonian \"\n",
" def __init__(self,Lp,Rp,M1,M2,dtype=float):\n",
" self.Lp = Lp\n",
" self.Rp = Rp\n",
" self.M1 = M1\n",
" self.M2 = M2\n",
" self.d = M1.shape[3]\n",
" self.chi1 = Lp.shape[0]\n",
" self.chi2 = Rp.shape[0]\n",
" self.shape = np.array([self.d**2*self.chi1*self.chi2,self.d**2*self.chi1*self.chi2])\n",
" self.dtype = dtype\n",
" \n",
" def matvec(self,x):\n",
" x=np.reshape(x,(self.d,self.chi1,self.d,self.chi2)) # i a j b\n",
" x=np.tensordot(self.Lp,x,axes=(0,1)) # ap m i j b\n",
" x=np.tensordot(x,self.M1,axes=([1,2],[0,2])) # ap j b mp ip\n",
" x=np.tensordot(x,self.M2,axes=([3,1],[0,2])) # ap b ip m jp\n",
" x=np.tensordot(x,self.Rp,axes=([1,3],[0,2])) # ap ip jp bp\n",
" x=np.transpose(x,(1,0,2,3))\n",
" x=np.reshape(x,((self.d*self.d)*(self.chi1*self.chi2)))\n",
" if(self.dtype==float):\n",
" return np.real(x)\n",
" else:\n",
" return(x)\n",
" \n",
"def update(theta,B,s,chi,H_mpo,Lp_list,Rp_list,chi1,chi3,i1,i2,i3,direction):\n",
" \"\"\"Updates the environment and the MPS\"\"\"\n",
" X, Y, Z = svd(theta); Z = Z.T\n",
" d = B[0].shape[0]\n",
" # Truncate and get the new Environment and MPS\n",
" chi2 = np.min([np.sum(Y>10.**(-12)), chi])\n",
" X=np.reshape(X[:d*chi1,:chi2],(d,chi1,chi2))\n",
" Z=np.transpose(np.reshape(Z[:d*chi3,:chi2],(d,chi3,chi2)),(0,2,1))\n",
"\n",
" if direction == 'R':\n",
" Lp = np.tensordot(Lp_list[-1], H_mpo[i1], axes=(2,0))\n",
" Lp = np.tensordot(Lp, X, axes=([0,3],[1,0]))\n",
" Lp = np.tensordot(Lp, np.conj(X), axes=([0,2],[1,0]))\n",
" Lp = np.transpose(Lp,(1,2,0))\n",
" Lp_list.append(Lp)\n",
"\n",
" if direction == 'L':\n",
" Rp = np.tensordot(H_mpo[i2], Rp_list[-1], axes=(1,2))\n",
" Rp = np.tensordot(np.conj(Z),Rp, axes=([0,2],[2,4]))\n",
" Rp = np.tensordot(Z,Rp, axes=([0,2],[2,3]))\n",
" Rp_list.append(Rp)\n",
"\n",
" s[i2]=Y[:chi2]/np.sqrt(sum(Y[:chi2]**2))\n",
" B[i1]=np.transpose(np.tensordot(np.diag(s[i1]**(-1)),X,axes=(1,1)),(1,0,2))\n",
" B[i1]=np.tensordot(B[i1], np.diag(s[i2]),axes=(2,1))\n",
" B[i2] = Z\n",
"\n",
"def diag(B,s,H,i1,i2,chi1,chi3):\n",
" \"\"\" Diagonalizes the mixed hamiltonian \"\"\"\n",
" # Get a guess for the ground state based on the old MPS \n",
" d = B[0].shape[0]\n",
" theta0 = np.tensordot(np.diag(s[i1]),np.tensordot(B[i1],B[i2],axes=(2,1)),axes=(1,1))\n",
" theta0 = np.reshape(np.transpose(theta0,(1,0,2,3)),((chi1*chi3)*(d**2)))\n",
"\n",
" # Diagonalize the sparse matrix \n",
" e,v = arp.eigsh(H,k=1,which='SA',return_eigenvectors=True,v0=theta0)\n",
" v = v.squeeze()\n",
" return np.reshape(v,(d*chi1,d*chi3))\n",
"\n",
"def sweep(B,s,chi,H_mpo,Rp_list = None):\n",
" \"\"\" Performs a Left-Right-Left sweep \"\"\"\n",
" d = B[0].shape[0]\n",
" D = H_mpo[0].shape[0]\n",
" L = len(B)\n",
" dtype = B[0].dtype\n",
" \n",
" if Rp_list == None:\n",
" Rp = np.zeros([1,1,D],dtype=dtype)\n",
" Rp[0,0,D-1] = 1.\n",
"\n",
" Rp_list = [Rp]\n",
" for i in np.arange(L-1,0,-1):\n",
" Rp = np.tensordot(B[i], Rp, axes=(2,0))\n",
" Rp = np.tensordot(H_mpo[i], Rp, axes=([1,2],[3,0]))\n",
" Rp = np.tensordot(np.conj(B[i]), Rp, axes=([0,2],[1,3]))\n",
" Rp = np.transpose(Rp,(2,0,1))\n",
" Rp_list.append(Rp)\n",
" \n",
" # Right Sweep\n",
" Lp = np.zeros([1,1,D],dtype=dtype)\n",
" Lp[0,0,0] = 1.\n",
" Lp_list = [Lp]\n",
" for i_bond in range(L-1):\n",
" i1=i_bond\n",
" i2=i_bond+1\n",
" i3=i_bond+2\n",
"\n",
" chi1 = Lp_list[-1].shape[1]\n",
" chi3 = Rp_list[L-2-i1].shape[1]\n",
"\n",
" H = H_mixed(Lp_list[-1],Rp_list[L-2-i1],H_mpo[i1],H_mpo[i2],dtype=float)\n",
"\n",
" theta = diag(B,s,H,i1,i2,chi1,chi3)\n",
" update(theta,B,s,chi,H_mpo,Lp_list,Rp_list,chi1,chi3,i1,i2,i3,'R')\n",
" \n",
" # Left Sweep\n",
" Rp = np.zeros([1,1,D],dtype=dtype)\n",
" Rp[0,0,D-1] = 1.\n",
" Rp_list = [Rp]\n",
" for i_bond in range(L-2,-1,-1):\n",
" i1=i_bond\n",
" i2=i_bond+1\n",
" i3=i_bond+2\n",
" \n",
" chi1 = Lp_list[i1].shape[1]\n",
" chi3 = Rp_list[-1].shape[1]\n",
" \n",
" H = H_mixed(Lp_list[i1],Rp_list[-1],H_mpo[i1],H_mpo[i2],dtype=float)\n",
"\n",
" theta = diag(B,s,H,i1,i2,chi1,chi3)\n",
" update(theta,B,s,chi,H_mpo,Lp_list,Rp_list,chi1,chi3,i1,i2,i3,'L')\n",
" return Rp_list"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"######## Define the simulation parameter ######################\n",
"chi = 10\n",
"N = 10\n",
"\n",
"######## Define the Spin operators ###########################\n",
"J = 1.\n",
"g = 1.\n",
This diff is collapsed.
%% Cell type:code id: tags:
``` python
from tenpy.models.lattice import Lattice
from tenpy.models.model import CouplingMPOModel
from tenpy.networks.site import SpinSite
from tenpy.tools.params import get_parameter
from tenpy.algorithms import dmrg
from tenpy.networks.mps import MPS
import numpy as np
import matplotlib.pyplot as plt
import time
import random
```
%% Cell type:markdown id: tags:
# Model Definition
%% Cell type:code id: tags:
``` python
#Create a ComplingMPOModel to describe the system.
#The parameters are passed via model_params
class Heisenberg(CouplingMPOModel):
def __init__(self,model_params):
CouplingMPOModel.__init__(self,model_params)
def init_lattice(self, model_params):
#Here initialize the type of lattice considered
lattice = get_parameter(model_params, 'lattice', self.name, False)
return lattice
def init_terms(self, model_params):
D= get_parameter(model_params, 'D', 0., self.name, True)
#Try to get also the J and lambda paramter in the same way
#J= ...
#lam= ...
#Here implement the couplings of the chain
#D term
self.add_onsite(D, 0, 'Sz Sz')
#Heisenberg interaction
self.add_coupling(J, 0, 'Sx', 0, 'Sx', 1,)
#Implement the remaining couplings for the Heisenberg exchange
#Have a look at the documentation of the function add_coupling()
#
#
#Quadratic Heisenberg term, the one with lambda
#Implement this term yourself
```
%% Cell type:markdown id: tags:
# Phase diagram for $\lambda=0$ and varying $D$
%% Cell type:markdown id: tags:
## Define the model
%% Cell type:code id: tags:
``` python
L=2 #Chain length (2 for the iMPS)
J=1 #Anitferromagnetic interaction
lam=0 #Quadratic term
Dmin=-1
Dmax=2
points=30
d=np.linspace(Dmin,Dmax,points,endpoint=True) #Values considered for D
#Definition of the lattice model
#Define the local Hilbert space, have a look at the documentation of SpinSite
#site=SpinSite(...)
#Define the lattice by looking at the documentation of Lattice
#Inifinite MPS requires periodic boundaries for the lattice
#lat=Lattice(...) #We choose an infinite MPS
```
%% Cell type:markdown id: tags:
## Perform iDMRG
%% Cell type:code id: tags:
``` python
entEnt=[]
entSp=[]
stagMag=[]
for D in d:
#Define the paramters of the model
model_params={
'verbose':0,
'J':J,
'D':D,
'lambda':lam,
'lattice':lat
}
#Create the model
chain=Heisenberg(model_params)
#Define the paramters for the DMRG
dmrg_paramsGs = {
'trunc_params': {
'chi_max': 20 #Maximum bond dimension
},
'verbose': 1
}
#Initialize the MPS with an arbitrary product state
product_state=['up',0]
#Have a look at the documentation MPS.from_product_state()
#psiGs=MPS.from_product_state(...)
#Perform iDMRG
#Check documentation of dmrg.run
#info=dmrg.run(...)
#Check documentation for expectation_value(). Which operator do you want to measure for magnetization?
#mag=psiGs.expectation_value(...) #Measure magnetization
#Implement function to compute staggered magnetization from mag
#staggered=...
stagMag.append(staggered) #Compute staggered magnetization
#Check documentation of entanglement_spectrum() and compute it
#spectrum=...
entSp.append(spectrum[0])
#Check documentation of entanglement_entropy() and compute it
#entropy=...
entEnt.append(entropy[0])