Hi all,
I need some help on the following problem. I have an MPS with the Fermion site type, representing the state \psi of a many-body fermionic system, and I’d like to use it to create an Electron-type MPS where both spin degrees of freedom are described by \psi.
The procedure is analogous to creating the projector \ket{\psi}\bra{\psi}, and in fact I can do it by hand with the following function, in which I build the MPS matrices manually.
function proj_electron(v::MPS; kwargs...)
T = ITensors.scalartype(v)
N = length(v)
blocks = Vector{Array{T}}(undef, N)
d = dim(siteind(v, 1))^2 # == 4
t = Array{T}(undef, d, linkdim(v, 1)^2);
a1 = array(v[1], siteind(v, 1), linkind(v, 1))
t[1, :] .= kron(a1[1, :], conj(a1[1, :]))
t[2, :] .= kron(a1[2, :], conj(a1[1, :]))
t[3, :] .= kron(a1[1, :], conj(a1[2, :]))
t[4, :] .= kron(a1[2, :], conj(a1[2, :]))
blocks[1] = t
for i in 2:(length(v) - 1)
t = Array{T}(undef, d, linkdim(v, i-1)^2, linkdim(v, i)^2)
ai = array(v[i], siteind(v, i), linkind(v, i-1), linkind(v, i))
t[1, :, :] .= kron(ai[1, :, :], conj(ai[1, :, :]))
t[2, :, :] .= kron(ai[2, :, :], conj(ai[1, :, :]))
t[3, :, :] .= kron(ai[1, :, :], conj(ai[2, :, :]))
t[4, :, :] .= kron(ai[2, :, :], conj(ai[2, :, :]))
blocks[i] = t
end
t = Array{T}(undef, d, linkdim(v, N-1)^2);
aN = array(v[N], siteind(v, N), linkind(v, N-1))
t[1, :] .= kron(aN[1, :], conj(aN[1, :]))
t[2, :] .= kron(aN[2, :], conj(aN[1, :]))
t[3, :] .= kron(aN[1, :], conj(aN[2, :]))
t[4, :] .= kron(aN[2, :], conj(aN[2, :]))
blocks[N] = t
linds_dim = getindex.(size.(blocks), 2)[2:end]
sites = siteinds("Electron", N; kwargs...)
v = Vector{ITensor}(undef, N)
l = [Index(linds_dim[i], "Link,l=$i") for i in 1:(N - 1)]
v[1] = ITensor(blocks[1], sites[1], l[1])
for i in 2:(N - 1)
v[i] = ITensor(blocks[i], sites[i], dag(l[i - 1]), l[i])
end
v[N] = ITensor(blocks[N], sites[N], dag(l[N - 1]))
return MPS(v)
end
This works, and yields the expected results.
The problem lies in the fact that I would like to enable QN conservation in the resulting Electron MPS (it will be used as the starting point of TDVP with a Hamiltonian that conserves the total number of electrons), but I’m completely lost on how to do this. Basically, my way of setting the individual tensors as in the function above doesn’t work as the arrays are now sparse, and I couldn’t find a way to set values of sparse tensors in the ITensor documentation…
Can someone point me in the right direction (or to an useful page of the documentation that I might have missed)?