Thank you for your guidance.
I successfully have built an MPO. But I want an MPO with open boundary.
Python: Select all
import tenpy
from tenpy.models.model import CouplingMPOModel
from tenpy.networks.site import SpinHalfSite, SpinSite
import numpy as np
from utils import compute_J
class MyModel(CouplingMPOModel):
def init_sites(self, model_params):
# TODO: could optionally enable Sz conservation here...
return (SpinHalfSite(None), SpinSite(S=1.0, conserve=None))
def init_lattice(self, model_params):
N_one = model_params.get("N_one", 3)
N_half = model_params.get("N_half", 2)
bc_MPS = model_params.get("bc_MPS", "finite")
S_half, S_one = self.init_sites(model_params)
lattice = tenpy.models.lattice.TrivialLattice(
[S_one] * N_one + [S_half] * N_half
)
lattice.bc_MPS = "finite"
self.bc_MPS = "open"
self.bc_x = "open"
return lattice
def init_terms(self, model_params):
# read out parameters
S_name_arr = ["Sx", "Sy", "Sz"]
N_one = model_params["N_one"]
N_half = model_params["N_half"]
N = N_one + N_half
D = model_params.get("D", [0.0] * 3) # D: x, y, z (1d array of length 3)
B0 = model_params.get("B0", 0.0)
gamma_one = model_params["gamma_one"]
gamma_half = model_params["gamma_half"]
pos_one = model_params["pos_one"]
pos_half = model_params["pos_half"]
pos_one = [np.array(x) for x in pos_one]
pos_half = [np.array(x) for x in pos_half]
# H_one terms
for i in range(N_one - 1):
for j in range(i + 1, N_one):
pos1 = pos_one[i]
pos2 = pos_one[j]
J_one_ij = compute_J(pos1, pos2, gamma_one, gamma_one)
for k in range(3):
for l in range(3):
op1 = S_name_arr[k]
op2 = S_name_arr[l]
self.add_coupling_term(J_one_ij[k, l], i, j, op1, op2)
for s in range(3):
self.add_onsite_term(
2.0 * np.pi * D[s], i, " ".join([S_name_arr[s]] * 2)
)
# self.add_onsite_term(D, i, "Sz Sz") # op='Sz Sz' is Sz^2
self.add_onsite_term(-B0 * gamma_one, i, "Sz")
for s in range(3):
self.add_onsite_term(
2.0 * np.pi * D[s], N_one - 1, " ".join([S_name_arr[s]] * 2)
)
# self.add_onsite_term(D, i, "Sz Sz") # op='Sz Sz' is Sz^2
self.add_onsite_term(-B0 * gamma_one, N_one - 1, "Sz")
# H_half
# J_half_ij = model_params.get("J_ij", np.zeros((N_half, N_half)))
for i in range(N_half - 1):
for j in range(i + 1, N_half):
pos1 = pos_half[i]
pos2 = pos_half[j]
J_half_ij = compute_J(pos1, pos2, gamma_half, gamma_half)
for k in range(3):
for l in range(3):
op1 = S_name_arr[k]
op2 = S_name_arr[l]
self.add_coupling_term(
J_half_ij[k, l], N_one + i, N_one + j, op1, op2
)
self.add_onsite_term(-B0 * gamma_half, N_one + i, "Sz")
self.add_onsite_term(-B0 * gamma_half, N - 1, "Sz")
# H_int
for i in range(N_one):
for j in range(N_half):
pos1 = pos_one[i]
pos2 = pos_half[j]
A_ij = compute_J(pos1, pos2, gamma_one, gamma_half)
for k in range(3):
for l in range(3):
op1 = S_name_arr[k]
op2 = S_name_arr[l]
self.add_coupling_term(A_ij[k, l], i, N_one + j, op1, op2)
Running the code above, I get the following output.
Code: Select all
>>> model
<MPO.MyModel object at 0x13f89a880>
>>> model.H_MPO.get_W(0)
<npc.Array shape=(2, 5, 3, 3) labels=['wL', 'wR', 'p', 'p*']>
>>> model.H_MPO.get_W(-1)
<npc.Array shape=(23, 2, 2, 2) labels=['wL', 'wR', 'p', 'p*']>
I want the bond dimension of 'wL' for
MPO.get_W(0) is 1 and 'wR' for
MPO.get_W(-1) is also 1.
[Simulation Description]
I want to perform real-time evolution of the all-to-all Hamiltonian composed of \(N\) spin-one and \(M\) spin-half system.
We perform the MPS time-evolution code for the 3 spin-one and 2 spin-half system with two-site TDVP engine.
Maximum bond dimension is set to 30.
The result is quite different from the exact time evolution result (Exact Diagonalization).
I guess that this is due to the connection of the first site to the last site in the MPO.