Johannes,
Thanks for your reply, I know that the transfer matrix method is only well-defined in a case with translational invariance, and for the contracting of the transfer matrix we need right matrice B or left matrice A.
My question is about the implementation of the
charge conservation in the calculation. For example, as said in the note, when we combine the physical leg (p) with the left leg (vL) or the right leg (vR), we map the indices for "vL" and "p" into something like "2*vL+p", so that the charge rule preserved. In this case, the inverse mapping (split combined leg) can be written simply.
In tenpy, theta with combined legs can be obtained by the following code:
Code: Select all
theta = psi.get_theta(0)
theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], qconj=[+1, -1])
theta = theta.to_ndarray()
this is also can be done with:
Code: Select all
theta = psi.get_theta(0).to_ndarray()
combined_theta = np.zeros((2*chi, 2*chi))
for i in range(chi):
for j in range(2):
for k in range(chi):
for l in range(2):
combined_theta[2*i+j, 2*k+l] = theta[i, j, l, k]
If we have a theta in the matrix form (legs combined), we can split physical legs from theta by using the inverse mapping:
start from a theta with combined legs
Code: Select all
theta = psi.get_theta(0)
theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], qconj=[+1, -1])
theta = theta.to_ndarray()
split it
Code: Select all
split_theta = np.zeros((chi, 2, 2, chi))
for i in range(chi):
for j in range(2):
for k in range(chi):
for l in range(2):
split_theta[i, j, l, k] = theta[2*i+j, 2*k+l]
But there is a question is: how to do svd for theta can preserve the block structure? If simply run "U, S, Vh = np.linalg.svd(theta)" (where theta is the wavefunction in matrix from, i.e. it's obtained by
Code: Select all
theta = psi.get_theta(0)
theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], qconj=[+1, -1])
theta = theta.to_ndarray()
), it will return the right matrice B (which is just Vh) but
sorted by the the singular values. Also due to this reason, we cannot split combined leg back into "vR" and "p" by using the inverse mapping mentioned above. In this case, I donot know how to calculate the transfer matrix since I cannot do the tensor product of right matrice B and
trace out the physical leg.
In the note, it said that we can do svd in each charge sector, I'm not sure how to do. For example, for a matrix form theta, it seems we need to do the inverse mapping first (
split combined leg) to get a rank-3 tensor with shape (chi, 4, chi) and do svd in each charege sector "theta[:, 0, :]", "theta[:, 1, :]", "theta[:, 2, :]", and "theta[:, 3, :]", i.e. do svd in sector (-2, 0, 0, 2) respectively? Like in the follwing:
Code: Select all
theta = psi.get_theta(0)
theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], qconj=[+1, -1])
theta = theta.to_ndarray()
split_theta = np.zeros((chi, 4, chi))
for i in range(chi):
for j in range(2):
for k in range(chi):
for l in range(2):
split_theta[i, 2*j+l, k] = theta[2*i+j, 2*k+l]
There will be another question: we have two zero charge sector since (-1) + (+1) = (+1) + (-1) = 0, how to deal with this?
In fact, I think somehow we can calculate the transfer matrix
without using any knowledge of the charge conservation, i.e. with only a given matrix form theta (just the data of theta, extracted by using ".to_ndarray()"), we can obtain the transfer matrix. But I really donot know how to do this.
Thanks,
Qicheng