I’m wondering if I can calculate something similar to the built in CCmatrix function but with different states, that is, in my case \langle \psi_1 |c^{\dagger}_i c_j|\psi_2 \rangle .
My very naive (and presumably very inefficient) first attempt doesn’t seem to agree with the built-in function when psi1=psi2, so I must have been doing something wrong here. If you could point it out that would be very helpful. Or let me know if I should just do modify the built-in function and carry out the site-by-site calculation.
For your reference, psi are various excited states from a DMRG calculation of a 1-D fermionic chain with QN conservation.
L = length(psi1)
# type? fix if necessary
corr = zeros( (L, L) )
# get site indices
s1 = siteinds(psi1)
s2 = siteinds(psi2)
for j = 1:L
replaceind!(psi1[j], s1[j], s2[j])
end
# init post-operated state array
allleft = []
allright = []
operator = "C"
for site in 1:L
psileft = deepcopy(psi1)
psiright = deepcopy(psi2)
orthogonalize!(psileft,site)
orthogonalize!(psiright, site)
# using s2 since indices are set the same
curleft = op( operator, s2, site) * psileft[site]
curright = op( operator, s2, site) * psiright[site]
#noprime!(curleft)
psileft[site] = curleft
psiright[site] = curright
operator = "$operator * F"
append!(allleft, [psileft])
append!(allright, [psiright])
end
# explicitly calculate inner product of post-operated states
for i in 1:L
for j in 1:L
corr[ i, j] = inner( allleft[i]', allright[j])
end
end
return corr
Good question – your approach here seems reasonable in terms of a method that could work, though it will be a lot slower for larger systems or bigger (larger bond dimension) states that the method we use inside the correlation_matrix function. In terms of why it’s giving different results, I would bet its something to do with the handling of the Jordan-Wigner string (F operators) here, which can be very tricky to do correctly.
Another way to go, especially if you get your code above to work but find it’s too slow, would be to take the code from inside the correlation_matrix function and generalize it so that everywhere the tensors from the state psi are conjugated to make the “bra” tensors, you instead use tensors from a different MPS psi2. But there would be one additional subtlety, which is that because they are two different MPS, you can’t take advantage of the orthogonality conditions to “cancel” any tensors so you would need to include the overlaps all the way from the left and right edges of the system at each step of the calculation.
Going back to your code, I would suggest first testing it on a case where the operators don’t carry any J-W string (so operators like \hat{n}_i and \hat{n}_j) and compare to what correlation_matrix gives just to make sure that case is working. Perhaps you already did that. Then you can be pretty sure that if the c and c^\dagger correlator isn’t working that it’s an issue with the string.
Thanks for the advice. Indeed, after benchmarking with N_iN_j the problem seems to be the Jordan Wigner String.
I then realized the string that I used was basically a product of -1s acting on one site, which was problematic, so I added this section that applies the F operator to each site individually
for prev in 1:site-1
prevleft = op("F", s2, prev) * psileft[prev]
psileft[prev] = prevleft
prevright = op("F", s2, prev) * psiright[prev]
psiright[prev] = prevright
end
Now the code seems to work properly. Again, this is a lot of repeated calculations, so I will look into the ccmatrix source code to see if I can get any speedups.