Hello Karl thanks for your reply. In the end I have solved my problem. Specifically, I had to create the following “thermal” density matrix
\rho = \rho_{\mu_L}\otimes \rho_{\mu_R}
where
\rho_\mu = \frac{1}{Z}\prod_{x=1}^{N-1}(e^{-\mu/2} \ket{\uparrow_{x} \uparrow_{x+1}} + e^{\mu/2}\ket{\downarrow_x\downarrow_{x+1}})(e^{-\mu/2} \bra{\uparrow_{x} \uparrow_{x+1}} + e^{\mu/2}\bra{\downarrow_x\downarrow_{x+1}})
with Z= 2 \cosh(\mu/2) . In particular choosing N=n/2 with n even, we are looking for a state with different (average) magnetisation on the left and the right of the middle of the chain. This state is also known as domain wall, or variations of this name. My approach has been the following:
function initial_state(Nphys::Int64, μL::Float64, μR::Float64)
N = 2Nphys
sites = siteinds("S=1/2", N)
state = MPS(sites)
#create the tensors on the two sites in the first half
for x in 1:2:Nphys-1
# copy the tensors
t1 = state[x]
t2 = state[x+1]
# create new indices
x_physical1 = sites[x] # first physical index
i_virtual = Index(2, tags(commonind(t1, t2))) # bond connecting the two tensors
x_physical2 = sites[x+1] #second physical index (the ancilla)
# construct the tensors
A = ITensor(x_physical1, i_virtual)
B = ITensor(x_physical2, i_virtual)
# x_physical = 1 is up, x_physical = 0 is down
A[x_physical1 => 1, i_virtual => 1] = 1/(2cosh(μL)) * exp(-μL) |> sqrt
A[x_physical1 => 1, i_virtual => 2] = 1/(2cosh(μL)) * exp(-μL) |> sqrt
A[x_physical1 => 2, i_virtual => 1] = 1/(2cosh(μL)) * exp(μL) |> sqrt
A[x_physical1 => 2, i_virtual => 2] = 1/(2cosh(μL)) * exp(μL) |> sqrt
B[x_physical2 => 1, i_virtual => 1] = 1/(2cosh(μL)) * exp(-μL) |> sqrt
B[x_physical2 => 1, i_virtual => 2] = 1/(2cosh(μL)) * exp(-μL) |> sqrt
B[x_physical2 => 2, i_virtual => 1] = 1/(2cosh(μL)) * exp(μL) |> sqrt
B[x_physical2 => 2, i_virtual => 2] = 1/(2cosh(μL)) * exp(μL) |> sqrt
# put these tensor into the MPS
state[x], state[x+1] = A, B
sites[x], sites[x+1] = x_physical1, x_physical2
end
print("Finished first half...\n")
# second half
for x in Nphys+1:2:N-1
# copy the tensors
t1 = state[x]
t2 = state[x+1]
# create new indices
x_physical1 = sites[x] # first physical index
i_virtual = Index(2, tags(commonind(t1, t2))) # bond connecting the two tensors
x_physical2 = sites[x+1] #second physical index (the ancilla)
# construct the tensors
A = ITensor(x_physical1, i_virtual)
B = ITensor(x_physical2, i_virtual)
# x_physical = 1 is up, x_physical = 0 is down
A[x_physical1 => 1, i_virtual => 1] = 1/(2cosh(μR)) * exp(-μR) |> sqrt
A[x_physical1 => 1, i_virtual => 2] = 1/(2cosh(μR)) * exp(-μR) |> sqrt
A[x_physical1 => 2, i_virtual => 1] = 1/(2cosh(μR)) * exp(μR) |> sqrt
A[x_physical1 => 2, i_virtual => 2] = 1/(2cosh(μR)) * exp(μR) |> sqrt
B[x_physical2 => 1, i_virtual => 1] = 1/(2cosh(μR)) * exp(-μR) |> sqrt
B[x_physical2 => 1, i_virtual => 2] = 1/(2cosh(μR)) * exp(-μR) |> sqrt
B[x_physical2 => 2, i_virtual => 1] = 1/(2cosh(μR)) * exp(μR) |> sqrt
B[x_physical2 => 2, i_virtual => 2] = 1/(2cosh(μR)) * exp(μR) |> sqrt
# put these tensor into the MPS
state[x], state[x+1] = A, B
sites[x], sites[x+1] = x_physical1, x_physical2
end
print("Finished second half...\n")
sites, state
end
You can check that computing the expectation value of S^z_x results in the correct thing. Maybe there’s a smarter way though but at the moment the function looks very efficient…
Thank you!