0 votes
asked by (440 points)

Hi all,

I am studying the ground state of a Heisenberg antiferromagnets on a 2D lattice (one periodic and one open), and I want to calculate the transfer matrix which is defined like this:

//got the ground state wave function psi through dmrg;
psi.position(N/2);
ITensor wf = psi(N/2 - Ny + 1);
for (int i = 2; i <= Ny; i++){
wf = wf * psi(N/2 - Ny + i);
}

then contract the wf with its own copy but keep the "Link" indices open,

wf *= prime(wf, "Link");

and I should get the transfer matrix where I want to calculate its largest eigenvalues and eigenvectors. However the second step throws an error of "std::bad_alloc" because the "Link" index dimension is too large ( around 3000), if I try 300 as "Link" index dimension it works well.

I have found a similar post http://itensor.org/support/1254/std-bad_alloc-in-spin-polarized-system where the solution is to avoid such large dimensions, but I can not think of a way to do that in my problem. Will it be better if I use a larger memory (like 512GB)? Any help would be much appreciated.

Best,

Yixuan

1 Answer

0 votes
answered by (34.5k points)

Hi Yixuan,
Yes, the reason for this error message is that your system has run out of memory / RAM. So one solution is definitely to try a system with more RAM if possible.

But another solution could be to write any large tensors you are not using at a particular step to disk. You can estimate the size of various tensors by multiplying the dimension of their indices together. Using this estimate, you might find that individual MPS tensors themselves aren't using a lot of memory, but tensors formed from the MPS can use a very large amount. (Or you might find that the MPS tensors alone are using a lot of memory; it depends on the details.)

We have some automatic facilities to write parts of an MPS to disk. But these may not work ideally for a transfer matrix calculation and are designed mostly to be used inside a DMRG calculation.

But you can even do writing to disk manually by just writing a tensor to a particular file with a good file name, then overwriting the tensor with an empty tensor to 'free' it from memory. Later, when you need the tensor again you can read it back in from the file and overwrite the read-in tensor onto your empty tensor to restore it.

If you decide to follow one of the three approaches above and run into issues, please post a comment below or a new question.

Best regards,
Miles

commented by (440 points)
Dear Miles,

Thank you for the prompt reply. Now that I have estimated roughly the size of that tensor, it seems like an impossible task because 3000^4 numbers * 64 Bytes per number ~ 4000 TB, although I am using conserved quantum number so the matrix should be sparse. I will let you know if I have questions about writing a tensor to disk.

Best,

Yixuan
commented by (34.5k points)
Yes, if you are trying to make a tensor with 4 indices of size 3000 I'm afraid it is rather hopeless on current machines.

*However*, if your goal is to study the MPS transfer matrix, then what people usually do is not to actually make this matrix. Instead, they try to find its dominant eigenvectors and eigenvalues (just two of these are enough to estimate the correlation length, for example). This is done by using an iterative eigensolver method such as Arnoldi where at each iteration, you multiply the current guess for the eigenvector by the transfer matrix. This multiplication can be done by contracting one tensor at a time such that no intermediate tensor ever has more than 3 large indices. In this way you can reduce the memory usage by a factor of 3000 in your case.

Maybe you already knew all that, though, but just wanted to make sure.

Best regards,
Miles
commented by (440 points)
That is exactly what I want! Thank you so much!! Actually I was looking at the Arnoldi part added in ITensor v3 recently (https://github.com/ITensor/ITensor/blob/v3/unittest/iterativesolvers_test.cc#L252) and thought it was meant for the non-Hermitian matrix, but you are right this should be the best way to get the dominant eigenvector.

Best regards,
Yixuan
commented by (34.5k points)
Hi Yixuan, great - glad that's what you were looking for. It's definitely the best way to go about extracting transfer matrix information.

I believe that in general the transfer matrix is not Hermitian, though it can be in certain cases. Best not to assume it is unless you can prove that it must be.

Miles
commented by (440 points)
Dear Miles,

Thanks for the explanation. I have tried and successfully run the Arnoldi to find the dominant eigenvector of a simple random ITensor with (i,j,k...) and (i',j',k'...) but I run into an error when I deal with the transfer matrix which is an ITensor pulled from the ground state MPS (with quantum number). I need to change the "Link" index of it in order to look like (i,j) and (i',j') to use Arnoldi, so I use the replaceInds(ITensor T, IndexSet is1, IndexSet is2) function:

auto lf = leftLinkIndex(psi, XX - Ny + 1);
auto rt = rightLinkIndex(psi, XX);
wf.replaceInds({rt}, {dag(prime(lf))});

and the error is "Diagonal elements of QDiag ITensor would have inconsistent divergence". I  know I could also replace the index by the delta function

wf *= dag(delta(rt, prime(lf)));

but unfortunately that gives out the same error.  I thought the diagonal tensor made from delta() should always have divergence of 0 because it only has non-zero diagonal elements. Why would it have inconsistent divergence with the original ITensor?
commented ago by (34.5k points)
Hi, so I'm not sure why you are getting this error. I think I would need to see a printout of the wf tensor, its indices, and its flux to know what is happening.

It could be a bug in the replaceInds function. If so, one alternative which could be easier for you and more transparent to debug is to make delta tensors yourself, and contract them with wf to replace the indices (I think this is all replaceInds does anyway). Then you could be sure the delta tensors are properly defined, *especially* regarding the index arrow directions. I suspect that could be the source of the problem, namely that replaceInds might not be handling arrows properly either in general or for your case.
Welcome to ITensor Support Q&A, where you can ask questions and receive answers from other members of the community.

Formatting Tips:
  • To format code, indent by four spaces
  • To format inline LaTeX, surround it by @@ on both sides
  • To format LaTeX on its own line, surround it by $$ above and below
  • For LaTeX, it may be necessary to backslash-escape underscore characters to obtain proper formatting. So for example writing \sum\_i to represent a sum over i.
If you cannot register due to firewall issues (e.g. you cannot see the capcha box) please email Miles Stoudenmire to ask for an account.

To report ITensor bugs, please use the issue tracker.

Categories

...