ITensor Support Q&A - Recent questions and answers
http://itensor.org/support/qa
Powered by Question2AnswerSVD an ITensor with QN in Julia?
http://itensor.org/support/2560/svd-an-itensor-with-qn-in-julia
<p>Hi Miles,</p>
<p>I am using the latest Julia version ITensors.</p>
<p>1.I defined an Index with QN. When I set "dir = In", the Index is not ordered, e.g. qn(s(2)) = QN("N",4,5). When I set "dir = Neither", qn(s(j)) always gives QN("N",0,5). Is this a bug?</p>
<pre><code>s = Index([QN(("N",i,5)) => 1 for i = 0:4];dir = ITensors.Arrow(0))
qn(s(2))
</code></pre>
<p>BTW, the direction name "Out", "In" conflict with Out and In in Jupyter Notebook.</p>
<p>2.I wanted to svd an ITensor with QN, but it says "In <code>setindex!</code>, the element you are trying to set is in a block that does not have the same flux as the other blocks of the ITensor. You may be trying to create an ITensor that does not have a well defined quantum number flux."</p>
<pre><code>dim0 = 4
s = Index([QN(("N",i,dim0))=>1 for i = 0:(dim0-1)];dir = ITensors.Arrow(1))
#s = Index(dim0)
l = addtags(s,"left")
r = addtags(s,"right")
u = addtags(s,"up")
d = addtags(s,"down")
A = emptyITensor(l,r,u,d)
for sl = 1:dim0, sd = 1:dim0, sr = 1:dim0, su = 1:dim0
#if sl+sd == sr+su || abs(sl+sd-sr-su) == dim0
if val(qn(l(sl))+qn(d(sd))-qn(r(sr))-qn(u(su)),"N") == 0
A[l(sl),r(sr),u(su),d(sd)] = 1
end
end
svd(A, (l,d))
</code></pre>
<p>Am I doing wrong?</p>
<p>Thanks.</p>
<p>Jin</p>
http://itensor.org/support/2560/svd-an-itensor-with-qn-in-juliaSun, 27 Sep 2020 06:50:37 +0000Answered: Can ITensor calculate 2D Heisenberg model real-time correlation function?
http://itensor.org/support/2558/itensor-calculate-heisenberg-model-correlation-function?show=2559#a2559
<p>Hi, thanks for the question. I think the core of your question is: what are the best ways to use ITensor to time-evolve systems which don't have nearest-neighbor interactions (in a 1D, MPS path order sense, which includes 2D systems).</p>
<p>To understand all of these methods, I'd recommend the review article by Paeckel:<br>
<a rel="nofollow" href="https://arxiv.org/abs/1901.05824">https://arxiv.org/abs/1901.05824</a><br>
as well as some of the material adapted from it on the tensornetwork.org website:<br>
<a rel="nofollow" href="http://tensornetwork.org/mps/algorithms/timeevo/">http://tensornetwork.org/mps/algorithms/timeevo/</a></p>
<p>There are three main methods available in connection with ITensor, and let me briefly list the pros and cons:</p>
<ol>
<li><p>using an MPO representation of the time evolution operator U=exp(-i tau H):</p>
<p>Pros: it is easy to set this up using AutoMPO and the toExpH function, so it is good for testing the other methods too</p>
<p>Cons: it is not very accurate in a few different ways, including having a large sensitivity to finite-time-step effects and also can result in MPS with rather large bond dimensions, more than what more accurate methods can provide</p>
<p>More information including a paper reference here: <br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=cppv3&page=formulas/tevol_mps_mpo">http://itensor.org/docs.cgi?vers=cppv3&page=formulas/tevol_mps_mpo</a></p></li>
<li><p>using the Trotter method but with additional "swaps" or "swap gates":</p>
<p>Pros: this method is the most reliable, in terms of being sure of convergence once it is implemented in a correct way. It is also not too hard to program. It can give very good accuracy too.</p>
<p>Cons: we don't have this available in a fully automatic way in the C++ version of ITensor (we do now in the Julia version, though). So you will have to implement the "swap" moves yourself, which temporarily bring further-neighbor sites together to become nearest neighbor.</p></li>
<li><p>using the TDVP method</p>
<p>Pros: this method is the best one to use, if you want the most state-of-the-art accuracy and efficiency. It has a very small time-step error and gives very accurate results, with relatively low bond dimensions. You can take rather large time steps for efficiency while still getting good results.</p>
<p>Cons: it is the most technical of the three to program. Also <em>caution</em> it can fail to converge if the initial state of the MPS has a poor basis, such as a product state or a state which has small overlap with the ideal state at a slightly later time. One way to overcome this initial-state problem is to start by using one of the other techniques above (Trotter is recommended for this) for a short time, then switch to TDVP. Or switch from one-site to two-site TDVP. Finally, one can use newer, more sophisticated TDVP convergence techniques such as in this recent paper: <a rel="nofollow" href="https://arxiv.org/abs/2005.06104">https://arxiv.org/abs/2005.06104</a></p>
<p>The TDVP method has been implemented in ITensor as an external code, and is available here:<br>
<a rel="nofollow" href="https://github.com/ITensor/TDVP">https://github.com/ITensor/TDVP</a></p></li>
</ol>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2558/itensor-calculate-heisenberg-model-correlation-function?show=2559#a2559Fri, 25 Sep 2020 19:37:43 +0000Answered: Error loading MPS from file
http://itensor.org/support/2555/error-loading-mps-from-file?show=2556#a2556
<p>Hi, thanks for the question. The way the write-to-disk system works in the C++ version, currently, results in us being only able to guarantee that files are readable within the same version of the code and on the same machine (due to the use of a non-portable binary format). So it's not really intended for long-term or portable storage of results, so much as for techniques like write-to-disk within DMRG to prevent running out of RAM.</p>
<p>Because of these limitations, we're working on HDF5 support and it's pretty far along but not quite done yet. (Another reason for the HDF5 support is so files can be read and written between the C++ and Julia versions of ITensor.)</p>
<p>More specifically to your issue: were the files you were reading definitely written with a different version of the library? This would be especially relevant if the older version was version 2.x and the newer one version 3.x. I couldn't tell from your question if that was definitely the case, but it would be an important detail to know. My best guess at the moment is that this was the case, and that a change we made to the internal layout of a data type from one version to another made those older files not readable by the latest version.</p>
<p>Finally, yes the Electron site set and Hubbard site sets are identical in terms of their physical meaning and purpose, as well as which operators they offer and QN's they support etc. But one crucial (though small) difference is that the Index tags generated by the Electron site set include the tag "Electron". (Actually I think the change from Hubbard to Electron coincided with the introduction of Index tags so there weren't any tags per se associated to the Hubbard site set.)</p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2555/error-loading-mps-from-file?show=2556#a2556Thu, 24 Sep 2020 19:15:41 +0000Answered: error message in the code formula for DRMG computing excited states
http://itensor.org/support/2546/error-message-code-formula-for-drmg-computing-excited-states?show=2553#a2553
<p>(Question answered in discussion comments above.)</p>
http://itensor.org/support/2546/error-message-code-formula-for-drmg-computing-excited-states?show=2553#a2553Wed, 23 Sep 2020 17:50:29 +0000Answered: Contraction of Multiple ITensors?
http://itensor.org/support/2538/contraction-of-multiple-itensors?show=2543#a2543
<p>Hi Jin,<br>
Thanks for the question. So this is the intended, and expected behavior of the ITensor * operator, namely that first A and B are contracted, then the result of that is contracted with C.</p>
<p>One reason for this is that this is just how operators work in C++. There is no notation in C++ that would allow simultaneous contraction of three or more ITensors in that language using operator overloading (*,+, and similar), apart from defining a function call such as <code>multicontract(A,B,C,D,...)</code> (which we might do in the future).</p>
<p>Another reason is that this behavior is quite often the desired behavior that one does want, so it is not in any way a bad thing. It just may not have been what you were expecting. The ITensor interface is based on tensor diagram notation which also uses a pairwise contraction convention. Contracting over an index shared between three or more tensors requires the notion of a "hyperedge" in a tensor network graph, which is perfectly fine to introduce but I'm just mentioning it to say it's not the standard thing that diagrams express.</p>
<p>We do offer something like a hyperedge in ITensor though: it is the <code>delta(m,n,p)</code> ITensor, which is a special ITensor with all its (multi-)diagonal elements set to 1.0. Not all routines involving <code>delta</code> tensors are as optimized as they could be, though some are and in general it's a useful tool.</p>
<p>Hope that helps -</p>
<p>Miles</p>
http://itensor.org/support/2538/contraction-of-multiple-itensors?show=2543#a2543Tue, 22 Sep 2020 15:53:38 +0000Answered: Extended hubbard model ground state energy not converging for negative V
http://itensor.org/support/2432/extended-hubbard-ground-state-energy-converging-negative?show=2537#a2537
<p>Hi Streetama,</p>
<p>When I was computing E.H.M. ground states for V > U > 0, which nearly approaches a product state as V >>> U, the entanglement goes down.</p>
<p>This sounds to us as a good thing, but in fact with DMRG it is a bad thing because it takes an extremely large number of fast sweeps in order to converge. In essence, the small number of nonzero entries in the SVD leads to poor communication of information across the lattice with each sweep.</p>
<p>For instance, I believe I needed to run hundreds of sweeps to get the energy to settle down, even for small system sizes, and I observed the entanglement entropy changed very slowly with each sweep.</p>
<p>In order to test this, I'd recommend changing your sweeps parameters so that you stay at a single maxdim for several hundred sweeps and wait until the energy settles down before increasing maxdim.</p>
<p>On the other hand, if your boundary conditions are incorrect (for instance, anti-periodic instead of periodic) you can also see wild changes in sweep to sweep energy; I experienced this error one time due to a mistake in my definition of the Hamiltonian.</p>
<p>If you figure it out please post back here as I'm interested to know what you find, as I am continuing to use these methods.</p>
<p>Good luck!</p>
http://itensor.org/support/2432/extended-hubbard-ground-state-energy-converging-negative?show=2537#a2537Mon, 21 Sep 2020 14:18:02 +0000Answered: How ITensor simulate Kitaev honeycomb model?
http://itensor.org/support/2532/how-itensor-simulate-kitaev-honeycomb-model?show=2533#a2533
<p>Hi, thanks for the question. Are you interested in doing this for the C++ or Julia version? I’ll assume C++ and for Julia it’s actually quite similar.</p>
<p>We have an example code of doing a 2D system you can use here:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=cppv3&page=formulas/2d_dmrg">http://itensor.org/docs.cgi?vers=cppv3&page=formulas/2d_dmrg</a></p>
<p>The only difference from a 1D code in that example is that the AutoMPO part of the code runs over site numberings which are obtained from an array of “LatticeBond” objects that are returned from the <code>triangularLattice</code> function. You can see the code for this function here:<br>
<a rel="nofollow" href="https://github.com/ITensor/ITensor/blob/v3/itensor/mps/lattice/triangular.h">https://github.com/ITensor/ITensor/blob/v3/itensor/mps/lattice/triangular.h</a></p>
<p>Despite the apparent complexity of that function (<code>triangularLattice</code>) it is actually doing something really simple: it is making an array of pairs of integers, such as (n,n+1) and (n,n+Ny-1), etc. which define the sites on which the Hamiltonian terms should act, using a 1D ordering of the sites. This is because an MPS always has a 1D ordering of its sites, so to implement a 2D Hamiltonian you have to define some mapping of the 2D bonds (pairs of sites) to pairs of sites in the 1D, MPS ordering. The AutoMPO system takes care of the rest. Usually the 2D to 1D mapping used is just a “zig zag” pattern that goes up each column of the 2D system.</p>
<p>To implement the honeycomb lattice, then, all you have to do is come up with such a 2D to 1D mapping. I would recommend reshaping the honeycomb lattice first to a square lattice but with some bonds missing and perhaps some bonds added if necessary. Then on paper enumerate the sites from 1,2,...,N where N=Nx*Ny. Now make a function which generates the integer pairs of all the 2D Hamiltonian bonds following this enumeration and returns an array of structs (data structures) of these integer pairs.</p>
<p>A helpful practice step is to modify the 2D DMRG code linked above to just print out the values <code>bnd.s1</code> and <code>bnd.s2</code>. Compare these values to the numberings of sites of the triangular lattice following the zig zag convention I mentioned above.</p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2532/how-itensor-simulate-kitaev-honeycomb-model?show=2533#a2533Sun, 20 Sep 2020 18:09:03 +0000Answered: Details of How DMRG works
http://itensor.org/support/2529/details-of-how-dmrg-works?show=2530#a2530
<p>Hi Arnab,<br>
Thanks for the question. It seems like it has multiple parts. Let me briefly answer each below.</p>
<ol>
<li><p>DMRG is globally a type of variational algorithm, yes. So it can get stuck in a local minimum, and this can be prevented by choosing a good initial state (such as a very random initial state or one close to the ground state in some way), as well as by using the "DMRG noise term" which we provide as one of the DMRG parameters you can set through the Sweeps object. However, this does not mean that DMRG is much like gradient descent. For one thing, it is usually much faster to converge than gradient descent and is more reliable for obtaining high precision results.</p></li>
<li><p>As far as how DMRG works in the details, it would be hard to give a satisfactory answer here, and could be the topic of a semester-long course. I have written a pretty detailed article at the following link you could use though:<br>
<a rel="nofollow" href="http://tensornetwork.org/mps/algorithms/dmrg/">http://tensornetwork.org/mps/algorithms/dmrg/</a><br>
Also there are some articles you could find on DMRG. Finally, there are some slides for a series of talks I gave, linked from this page:<br>
<a rel="nofollow" href="http://tensornetwork.org/reviews_resources.html">http://tensornetwork.org/reviews_resources.html</a></p></li>
</ol>
<p>Lastly, how did you find the tutorial page you linked to? Was it through a Google search? I ask because that page is rather out of date and no longer linked from anywhere on the current ITensor website as far as I know, so I should probably remove those files. </p>
<p>Thanks,<br>
Miles</p>
http://itensor.org/support/2529/details-of-how-dmrg-works?show=2530#a2530Fri, 18 Sep 2020 16:41:58 +0000How to implement symmetry which anticommutes with hamiltonian
http://itensor.org/support/2510/how-implement-symmetry-which-anticommutes-with-hamiltonian
<p>Dear community,</p>
<p>How is it possible to implement the conservation of an anti-block structure for {H,U} = 0? </p>
<p>Let us consider for instance the example H = ∑ σˣᵢ + ∑ σˣᵢ σˣⱼ σˣₖ with U = ∏ σˣᵢ where the z-parity only anticommutes with the hamiltonian. Right now I am implementing this using the square of the Hamiltonian, since then [H²,U]=0 and we can use regular quantum numbers; however, this is a very bad solution. Can you think of a better way?</p>
<p>Best,</p>
<p>v.</p>
http://itensor.org/support/2510/how-implement-symmetry-which-anticommutes-with-hamiltonianFri, 11 Sep 2020 09:53:01 +0000Answered: How do we take into account QN conservation in self-writing an MPO?
http://itensor.org/support/2502/how-do-take-into-account-qn-conservation-self-writing-an-mpo?show=2503#a2503
<p>Hi Sergi,<br>
Thanks for the question. This is definitely a rather more complicated, technical topic that we have documentation for at the moment. </p>
<p>To begin with, please look at the question and answer here, which is similar to yours:<br>
<a rel="nofollow" href="http://itensor.org/support/2083/properly-handle-quantum-number-for-system-spin-half-moments">http://itensor.org/support/2083/properly-handle-quantum-number-for-system-spin-half-moments</a></p>
<p>If you understand everything in the discussion there, then you will be a long way toward understanding all of the aspects of the code in Heisenber.h. If not, then please ask some more questions in the comments below about the parts you do not yet understand.</p>
<p>To answer some of your questions above more specifically:</p>
<ul>
<li><p>the convention for the blocking of the tensors in the Heisenberg.h code (and in QN conserving ITensors more generally) is set by how the Index objects are constructed. The ordering and arrangement of QN blocks (QN subspaces) determines, ahead of time, the blocking pattern of the tensors</p></li>
<li><p>when various terms are added into the W tensors in that code, the addition operator of ITensor automatically figures out where the terms should go into the existing W tensor. So if the term being added in has certain non-zero blocks, then because the Index objects are the same (and carry all of the QN details), the ITensor system can figure out on its own how to correctly place the tensor being added into the block structure of the W tensor. So you don’t really have to manage this yourself; you just have to add ITensors together that carry the same total QN flux and it always works correctly (or you get an error if the flux is different).</p></li>
<li><p>for your Jordan-Wigner strings, it is a complication but you may find it’s not too bad of one. In a normal (non fermionic) MPO, there will be identity operators that go before a set of non-identity operators, or after. These will remain identity operators in your case. But there will be some identity operators which go in between a pair of fermionic operators (operators which change the fermion parity, such as C and Cdag). These should be replaced by F operators.</p></li>
<li><p>the 2D aspect is more of a serious complication, but I’m sure you know how to handle it, just mapping terms in 2D into various 1D distances. E.g. on a square lattice of “width” Ny, horizontal, nearest-neighbor terms (which have a 2D distance of 1) have a 1D distance of Ny (assuming you are using the “zig zag” MPS path which always goes up each column, rather than a snaking path which goes up odd columns and down even columns. I recommend the zig zag path.)</p></li>
</ul>
<p>Hope that helps you make some progress. One thing I like to do is to devise a bunch of tests of a new MPO I’m making by using the ITensor function <code>inner</code> to compute matrix elements between various product states. Like you can make a product state |phi<em>j> which has a single fermion on some site j and |phi</em>k> which has a single fermion on site k, then compute <phi<em>k|H|phi</em>j> and work out by hand what it should be for your H. Then you can check whether you get the right thing from inner. Often you can do this for every single term in the Hamiltonian and thus be nearly sure that it’s bug free. (I say nearly because checking the JW string requires at least two particles to be present, but you can do checks for that too.) Also of course you can do some DMRG calculations in limits where you know what the answer should be.</p>
<p>Best,<br>
Miles</p>
<p>P.S. as mentioned please ask more question in the comments below if you have them</p>
http://itensor.org/support/2502/how-do-take-into-account-qn-conservation-self-writing-an-mpo?show=2503#a2503Mon, 07 Sep 2020 16:48:41 +0000Answered: Implementing Jaynes–Cummings–Hubbard model using Julia
http://itensor.org/support/2491/implementing-jaynes-cummings-hubbard-model-using-julia?show=2498#a2498
<p>Hi, so yes you can definitely implement this model, but with one major limitation, which is that for any degree of freedom which is a boson (such as a photon mode), you'll have to limit the maximum number of states of the Hilbert space of that boson. This is just because ITensor and tensor network methods generally (barring some very specialized approaches) are formulated in tensor products of finite-dimensional vector spaces.</p>
<p>We have not yet defined a boson degree of freedom that gets included with ITensor, but we have made it straightforward to define custom site types or Hilbert spaces. For a detailed walkthrough of how to do this, you can see the following two example pages:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=julia&page=formulas/sitetype_basic">http://itensor.org/docs.cgi?vers=julia&page=formulas/sitetype_basic</a><br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=julia&page=formulas/sitetype_qns">http://itensor.org/docs.cgi?vers=julia&page=formulas/sitetype_qns</a></p>
<p>Once you define overloads of the <code>op</code> function which specify operator names associated to your custom site type or Hilbert space, you can use these within the AutoMPO feature of ITensor to include your custom operator names, similar to other examples of using AutoMPO where there are operator names like "Sz", "S+", "S-" for the case of spin Hilbert spaces.</p>
<p>I'd recommend testing everything out on the smallest possible system and comparing to (numerically) exact calculations to check that it's all working the way you expect.</p>
<p>If you do end up making a boson Hilbert space definition, please consider contributing it to our library by sending us a pull request on Github. We can work with you to make it ready to include into the library if you think it would be a good idea.</p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2491/implementing-jaynes-cummings-hubbard-model-using-julia?show=2498#a2498Sat, 05 Sep 2020 02:42:02 +0000Answered: Inconsistency between DMRG ground state energy and <psi|H|psi>
http://itensor.org/support/2477/inconsistency-between-dmrg-ground-state-energy-and-psi-psi?show=2480#a2480
<p>Hi,</p>
<p>Thanks for the question. It looks like a problem with how the AutoMPO is defined. It should work if you change the definition to:</p>
<pre><code> ampo += "Cdag",j+1,"C",j
ampo += "Cdag",j,"C",j+1
</code></pre>
<p>This is pretty tricky, and easy to mess up, but for the sake of getting the correct Fermion signs in your Hamiltonian the order of the operators matters. Please look over the nice tutorial on Fermions by Miles here: <a rel="nofollow" href="https://itensor.org/docs.cgi?page=tutorials/fermions">https://itensor.org/docs.cgi?page=tutorials/fermions</a> to understand this better.</p>
<p>Cheers,<br>
Matt</p>
http://itensor.org/support/2477/inconsistency-between-dmrg-ground-state-energy-and-psi-psi?show=2480#a2480Thu, 03 Sep 2020 22:04:54 +0000Answered: Selecting specific rows, columns, i.e. fancy indexing in ITensor
http://itensor.org/support/2430/selecting-specific-rows-columns-fancy-indexing-in-itensor?show=2472#a2472
<p>The answer Miles gave above in the comments is correct. Unfortunately right now this feature is a work in progress (something we think about periodically but haven't taken the time to implement). To explain some of the complications, the design is fairly straightforward for slicing dense ITensors, but for block sparse ITensors the slicing becomes a bit more subtle (i.e., do you only only allow slicing entire blocks, or also subblocks, of a block sparse ITensor). In addition, the design we were thinking of would involve the indices themselves also getting sliced (i.e. in your example, the <code>U_new</code> tensor would have indices <code>(u, v => 1:dim_cn)</code> where <code>v = commonind(V,Σ)</code>, instead of an entirely new index <code>c</code>). Sorry for the inconvenience, the strategy you take above seems fine for now. If you find that it is not fast enough for any reason, or need something more sophisticated that is not available right now, we may be able to help by pointing out certain functions or providing helper functions for certain operations.</p>
http://itensor.org/support/2430/selecting-specific-rows-columns-fancy-indexing-in-itensor?show=2472#a2472Wed, 02 Sep 2020 15:27:12 +0000Answered: About the excited state of electron wave packet using the toMPO
http://itensor.org/support/2459/about-the-excited-state-electron-wave-packet-using-the-tompo?show=2463#a2463
<p>Hi, I'm not sure I totally see what you are asking, but is your question about doing the following steps:<br>
1. compute the ground state<br>
2. act on the ground state with an operator that creates an electron wave packet?</p>
<p>I think I see from your sample code that this is what you are trying to do. </p>
<p>Unfortunately there you may be running into a long-standing limitation of the AutoMPO system, which is that it does not correctly create a sum of single, <em>fermionic</em> C or Cdag operators. This is due to the necessity of including Jordan-Wigner string on all sites to the left of the operator, which is correctly handled for a pair of such operators but not currently for a single operator. So unfortunately it is a bug in ITensor just for this one case.</p>
<p>As a workaround for now, I could help you to make a custom code that creates the MPO you want, of the form \sum<em>i a</em>i C<em>i where a</em>i is any set of coefficients and C_i is the electron annihilation operator. If you email me at mstoudenmire@flatironinstitute.org we can correspond about how to make this code. It is actually rather short code but you may need my help to make it correctly.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2459/about-the-excited-state-electron-wave-packet-using-the-tompo?show=2463#a2463Mon, 31 Aug 2020 15:30:08 +0000Create a symmetric copy of a MPS: How to transpose QN?
http://itensor.org/support/2460/create-a-symmetric-copy-of-a-mps-how-to-transpose-qn
<p>Hi folks, <br>
I am trying to copy the first 1...L÷2 matrices of an MPS to the last L÷2+1...L matrices (in order to get the symmetric copy of the MPS). the layout is as following:</p>
<pre><code>A - B - C - U λ - V - D - E - F
| | | | | | | |
=> A - B - C - U λ - U - C - B - A
| | | | | | | |
</code></pre>
<p>The problem I am having right now is that I am not able to link Uλ with U. However, since λ is diagonal, this should be possible in principle. In particular, this works without quantum numbers, but with quantum numbers somehow the order of the blocks is reversed. Do you have an idea how I could go on in that situation? Here some code:</p>
<pre><code>L = 8
maxdim = 20
sites = siteinds("S=1/2",L,conserve_szparity=true)
ψ = randomMPS(sites,[rand(Bool) ? "↑" : "↓" for i in 1:L]);
truncate!(ψ,maxdim=maxdim)
orthogonalize!(ψ,L÷2);
U, λ, V = svd(ψ[L÷2]*ψ[L÷2+1], uniqueinds(ψ[L÷2],ψ[L÷2+1]))
ψ_new = copy(ψ)
s_ind1 = siteindex(ψ,L)
s_ind2 = siteindex(ψ,1)
bondL = commonind(ψ[1],ψ[2])
ψ_new[L] = prime(replaceind(ψ[1],s_ind2,s_ind1),bondL)
for i in 2:L÷2-1
s_ind1 = siteindex(ψ,L-i+1)
s_ind2 = siteindex(ψ,i)
bondL = commonind(ψ[i],ψ[i+1])
bondR = commonind(ψ[i],ψ[i-1])
ψ_new[L-i+1] = replaceind(ψ[i],s_ind2,s_ind1)
prime!(ψ_new[L-i+1],bondL)
prime!(ψ_new[L-i+1],bondR)
end
ψ_new[L÷2] = U*λ
linku = commonind(U,λ)
linkv = commonind(V,λ)
bondL = commonind(ψ[L÷2],ψ[L÷2-1])
s_ind1 = siteindex(ψ,L÷2+1)
s_ind2 = siteindex(ψ,L÷2)
ψ_new[L÷2+1] = replaceind(U,s_ind2,s_ind1)
prime!(ψ_new[L÷2+1],bondL)
replaceind!(ψ_new[L÷2+1],linku,linkv)
</code></pre>
<p>The error I get in the last line here is</p>
<pre><code>Indices must have the same spaces to be replaced
</code></pre>
<p>If we look at linku and linkv, it becomes apparent that they do not coincide (in dimensionality and quantum numbers), even though λ is diagonal. This is something I do not quite understand, does this diagonality somehow change when using quantum numbers?</p>
<p>Best,</p>
<p>v.</p>
http://itensor.org/support/2460/create-a-symmetric-copy-of-a-mps-how-to-transpose-qnMon, 31 Aug 2020 10:11:05 +0000Answered: Hubbard model in magnetic field
http://itensor.org/support/2456/hubbard-model-in-magnetic-field?show=2457#a2457
<p>Hi Streetmanda,<br>
By default, the indices created in an Electron site set keep track of the Sz quantum number. So then an MPS made from these indices will be a state of well-defined Sz that will not be changed, since your Hamiltonian conserves total Sz. Throughout the calculation, the total Sz will remain at the value of the input state psi0 used to initialize the calculation. This is how DMRG calculations with conserved total quantum numbers are carried out in ITensor.</p>
<p>So if you'd like the magnetic field to be able to alter the magnetization, you'll need to turn off Sz conservation, like this:</p>
<pre><code>auto sites = Electron(N,{"ConserveSz=",false});
</code></pre>
<p>when making your site set <code>sites</code>.</p>
<p>For a list of the available options to the Electron site set you can see the documentation here:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=cppv3&page=classes/electron">http://itensor.org/docs.cgi?vers=cppv3&page=classes/electron</a></p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2456/hubbard-model-in-magnetic-field?show=2457#a2457Sun, 30 Aug 2020 14:45:31 +0000Answered: dmrg function not accepting MPO obtained by using nmultMPO
http://itensor.org/support/2453/dmrg-function-not-accepting-mpo-obtained-by-using-nmultmpo?show=2454#a2454
<p>Thanks for the question. So the issue here is that the site indices of the MPO HH do not have the prime levels expected for an MPO that is used as input to the dmrg function. If you print out HH, you'll see that each tensor has a site index with prime level 0 and a site index with prime level 2. That's in contrast to a usual MPO for a Hamiltonian in ITensor, where the prime levels of the site indices are 0 and 1. </p>
<p>The reason it's 0 and 2 in your case is that prime(H) raises the prime levels from 0 and 1 to 1 and 2, then contracting that MPO with H contracts over the prime-level-1 indices, leaving only the prime level 0 and 2 indices.</p>
<p>So a solution is just to add the line </p>
<pre><code>HH.mapPrime(2,1);
</code></pre>
<p>after you make HH, which will map any prime-level-2 indices to have prime level of 1 instead.</p>
<p>I'd encourage you to print out the MPO you are inputting into dmrg to make sure it has the structure and prime levels you want.</p>
<p>The more surprising thing here is that <code>inner(psi,HH,psi)</code> works. It might be a good idea in the future for us to make that more restrictive, but the current way that function works is that as long as one set of site indices of the MPO matches the MPS on the right, then the other site indices get automatically modified to match those of the MPS on the left. This is mentioned in the documentation here: <a rel="nofollow" href="http://itensor.org/docs.cgi?vers=cppv3&page=classes/mps_mpo_algs">http://itensor.org/docs.cgi?vers=cppv3&page=classes/mps_mpo_algs</a><br>
But I agree it can be a bit surprising in cases like this.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2453/dmrg-function-not-accepting-mpo-obtained-by-using-nmultmpo?show=2454#a2454Fri, 28 Aug 2020 15:40:44 +0000Answered: Commutators of MPO's
http://itensor.org/support/2446/commutators-of-mpos?show=2450#a2450
<p>Hi, so I'd recommend the following approach instead:</p>
<ol>
<li><p>expand the commutator into two terms (H on the left, H on the right) and compute these separately and/or use a symmetry to relate one to the other (on paper)</p></li>
<li><p>for each of these terms, say <Phi|H c^\dag<em>p c</em>q |Phi> compute an MPS "ccPhi" by acting c<em>q and c^\dag</em>p onto Phi. You can do this by acting those operators on the site index of the appropriate MPS tensor and re-setting the prime level back to zero for those indices. You'll also need to act with Jordan-Wigner string on the sites between p and q. (Same kind of operation, but just act with the operator named "F".)</p></li>
<li><p>compute the overlap <Phi|H|ccPhi> by using the inner(Phi,H,ccPhi) function</p></li>
</ol>
<p>That approach ought to be a lot faster than making an MPO for each c^\dag<em>p c</em>q pair. The only downside is needing to explicitly deal with Jordan-Wigner string though.</p>
<hr>
<p>On the other hand, if you do prefer to stick with the MPO based approach, and if it's fast enough for you (at a minimum it's a good check on the other approach) then I'd recommend not using nmultMPO to multiply MPOs together, but instead take advantage of the fact that you are ultimately taking an expectation value with MPS. So you will find it works better to do applyMPO to multiply each MPO onto |Phi> until only one MPO is left, then use the <code>inner</code> function to compute the matrix element of that leftover MPO.</p>
<p>So act the "Cdagup",i,"Cup",j MPO onto |Phi> using applyMPO, to get |ccPhi>, then compute <Phi|H|ccPhi>.</p>
<p>Hope that works well for you!</p>
<p>Miles</p>
http://itensor.org/support/2446/commutators-of-mpos?show=2450#a2450Thu, 27 Aug 2020 15:53:33 +0000Answered: Error regarding cmake samples
http://itensor.org/support/2439/error-regarding-cmake-samples?show=2448#a2448
<p>(Please see discussion above.)</p>
http://itensor.org/support/2439/error-regarding-cmake-samples?show=2448#a2448Thu, 27 Aug 2020 02:18:12 +0000Answered: removeqns(ITensor) in Julia
http://itensor.org/support/2440/removeqns-itensor-in-julia?show=2443#a2443
<p>Hi Junsen,<br>
This is a good question. For the Julia version of ITensor, we are soon planning to implement <code>removeqns</code> for the ITensor level but haven't just yet. </p>
<p>But if what you want for now is to map block sparse ITensors to dense ITensors, you can call the function <code>dense</code> on an ITensor and it will do the behavior that you are wanting.</p>
<p>The plan for <code>removeqns</code> is that it will keep other sparsity (such as diagonal sparsity) while removing QN information. This is in contrast to the <code>dense</code> functiono which removes all sparsity, whether associated with QNs or not.</p>
<p>So in short, please try <code>dense</code> on your ITensors. I'm implementing a version of that you can call directly on an MPS too right now, but with the current version you'll need to call it on each tensor yourself.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2440/removeqns-itensor-in-julia?show=2443#a2443Tue, 25 Aug 2020 17:23:57 +0000Answered: Forcing S=0 and total number of electrons in the Fermi-Hubbard model (Julia)
http://itensor.org/support/2431/forcing-total-number-electrons-the-fermi-hubbard-model-julia?show=2436#a2436
<p>No problem! This is a common question since the way the total quantum numbers (QNs), such as particle number, is fixed is kind of subtle in ITensor. It is fixed by your choice of initial state. So if you prepare the MPS you are using as an initial guess for DMRG (I assume you are planning to do a DMRG calculation) to be a state with a certain particle number, then that particle number will remain the same as long as you construct your MPS using site indices that carry QN information.</p>
<p>The line of code</p>
<pre><code>sites = siteinds("Electron",N)
</code></pre>
<p>is actually creating an array of N objects of type <code>Index</code>, so N electron sites, not N electrons.</p>
<p>To make these sites carry QN information, you need to change this line to:</p>
<pre><code>sites = siteinds("Electron",N,conserve_qns=true)
</code></pre>
<p>Then, to prepare an initial state with two electrons, say one being an up-spin electron and the other being a down-spin electron, you can use code such as:</p>
<pre><code>states = ["0" for n=1:N]
states[1] = "Up"
states[2] = "Dn"
psi = productMPS(sites,states)
</code></pre>
<p>You can also call <code>psi = randomMPS(sites,states,10)</code> to create a randomized MPS which has the site indices <code>sites</code>, the same total QN as given by the product state <code>states</code>, and a bond dimension of 10.</p>
<p>Then if you plug this <code>psi</code> MPS into DMRG as an initial state together with a Hamiltonian that conserves particle number, the way ITensor works is that the particle number is guaranteed not to change. This is because when you use Index objects that have QNs in them, only operations which change these QNs by a definite amount are allowed, and your Hamiltonian will change them by an amount which is zero if it conserves them.</p>
<pre><code>energy,psi = dmrg(H,psi,sweeps)
</code></pre>
<p>Please post a comment if you have any follow-up questions.</p>
<p>There is a full example of doing DMRG for the extended Hubbard model with QN conservation here:<br>
<a rel="nofollow" href="https://github.com/ITensor/ITensors.jl/blob/master/examples/dmrg/exthubbard.jl">https://github.com/ITensor/ITensors.jl/blob/master/examples/dmrg/exthubbard.jl</a></p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2431/forcing-total-number-electrons-the-fermi-hubbard-model-julia?show=2436#a2436Sun, 23 Aug 2020 22:57:59 +0000Answered: How to calculate Sz=1 sector magnetization?
http://itensor.org/support/2434/how-to-calculate-sz-1-sector-magnetization?show=2435#a2435
<p>Hi, thanks for the question. It's giving me some good ideas of how we can improve the documentation on the website.</p>
<p>To compute the ground state in the Sz=1 sector and measure its magnetization, you'll need to do the following three things:</p>
<ol>
<li><p>initialize your site set with the {"ConserveQNs=",true} option. (Note that you had a mistake in the code you put, with an extra "1" that shouldn't be there.) What this does is to make the Index objects in the 'sites' array carry QN information.</p></li>
<li><p>initialize your MPS to be a product state with a total Sz of 1. You can use the "InitState" feature of ITensor to do this. If you look at the sample code sample/dmrg.cc it shows a use of this feature, and you can change the rule of how "Up" and "Dn" are set to make the Sz be 1. (Note that this means the total QN is QN("Sz",2) actually, since we measure spin in units of 1/2.) You can call totalQN(psi) on an MPS psi to see what its total QN is.</p></li>
<li><p>after computing the ground state using DMRG, check that the totalQN is still QN("Sz",2). </p></li>
<li><p>measure the magnetization using code similar to on the front page of the itensor.org website. Here I copy that code below:</p></li>
</ol>
<p>for(int j = 1; j <= N; ++j)<br>
{<br>
//Make site j the MPS "orthogonality center"<br>
psi.position(j);<br>
//Measure magnetization<br>
Real Szj = elt(psi(j)<br>
* op(sites,"Sz",j)<br>
* dag(prime(psi(j),"Site")));<br>
println("Sz_",j," = ",Szj);<br>
}</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2434/how-to-calculate-sz-1-sector-magnetization?show=2435#a2435Sun, 23 Aug 2020 18:05:30 +0000Answered: Jordan wigner fermi string in self-writing AutoMPO
http://itensor.org/support/2422/jordan-wigner-fermi-string-in-self-writing-autompo?show=2433#a2433
<p>Matt's answer is the right one, and do please see that article about fermions and how they are handled in ITensor.</p>
<p>To provide some additional information, there is currently only one place in ITensor where fermions are handled automatically for you, and that is in the AutoMPO system. So if you input Hamiltonian terms which contain fermionic operators (such as C and Cdag for spinless fermions, or Cup, Cdagup, Cdn, Cdagdn for electrons) then the AutoMPO system will use special rewriting rules and insert Jordan-Wigner string for you. (In the Julia version of ITensor, you can also extend this system for custom physical site types.) So the resulting MPO will be guaranteed to be correct in terms of treating fermionic operators.</p>
<p>On the other hand, when working with an MPS such as the one obtained after a DMRG calculation, you must insert Jordan-Wigner string operators yourself when measuring fermionic correlation functions, such as between a c-dagger and c operator acting on spatially separated sites. We have an example of how to do this for spinless fermions in the C++ version linked here:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=cppv3&page=formulas/spinless_correlator_mps">http://itensor.org/docs.cgi?vers=cppv3&page=formulas/spinless_correlator_mps</a></p>
<p>Hope that helps -</p>
<p>Miles</p>
http://itensor.org/support/2422/jordan-wigner-fermi-string-in-self-writing-autompo?show=2433#a2433Fri, 21 Aug 2020 15:47:41 +0000Answered: SVD swapping index arrow in TEBD algorithm with conserved quantum numbers
http://itensor.org/support/2421/swapping-index-arrow-algorithm-conserved-quantum-numbers?show=2429#a2429
<p>Hi Pietro,</p>
<p>I think using ITensor's MPS class is not necessary here, and makes it a bit confusing to keep track of the indices. Here is a minimal example of the step you are trying to reproduce from the paper, just in terms of ITensors:</p>
<pre><code>// Site indices
auto s = SpinHalf(2,{"ConserveQNs=",true});
auto sA = s(1);
auto sB = s(2);
// Link indices
auto lA = Index(QN(), 1, "lA");
auto lB = Index(QN(), 1, "lB");
// Gamma tensors
auto GammaA = randomITensor(QN(), dag(prime(lB)), sA, dag(lA));
auto GammaB = randomITensor(QN(), dag(prime(lA)), sB, dag(lB));
// Lambda tensors
auto lambdaA = randomITensor(QN(), lA, prime(lA));
auto lambdaB = randomITensor(QN(), lB, prime(lB));
// Fig. 3 (ii)
auto theta = lambdaB * GammaA * lambdaA * GammaB * lambdaB;
PrintData(inds(theta));
// Fig. 3 (iii)
auto [X, lambdaA_tilde, Y] = svd(theta, {lB, sA}, {"LeftTags = ", "lA_new", "RightTags = ", "lA_new_p"});
PrintData(inds(X));
PrintData(inds(lambdaA_tilde));
PrintData(inds(Y));
</code></pre>
<p>You can see there should be no Index mismatch, and if you are a bit careful with the indices you should be able to follow along with the next steps of the algorithm in the paper.</p>
<p>Cheers,<br>
Matt</p>
http://itensor.org/support/2421/swapping-index-arrow-algorithm-conserved-quantum-numbers?show=2429#a2429Sun, 09 Aug 2020 15:35:47 +0000Answered: A Question for the Input Tensor
http://itensor.org/support/2410/a-question-for-the-input-tensor?show=2427#a2427
<p>Hi Jiawen,</p>
<p>I'm working on a response to the email thread to send some examples of generating sparse ITensors.</p>
<p>It is not such an easy question to answer, since different physics problems and tensor network algorithms can lead to very different levels of sparsity, block sizes, tensor orders, etc. Often in ITensor we do not create large sparse tensors directly. Instead, they result organically from algorithms like DMRG, where blocks are generated on the fly in the SVD. Therefore, a good place to start would be to run common calculations like DMRG and extract tensors from the resulting MPS (like one in the middle of the system) for a variety of different problems. Note that specifying different symmetries of your problem (for example for the Hubbard model, choosing parity conservation vs. particle number conservation) is another way to generate tensors with different levels of sparsity.</p>
<p>Cheers,<br>
Matt</p>
http://itensor.org/support/2410/a-question-for-the-input-tensor?show=2427#a2427Fri, 07 Aug 2020 21:57:54 +0000Answered: Using IQTensor for general states
http://itensor.org/support/2395/using-iqtensor-for-general-states?show=2426#a2426
<p>(See the comments for an answer)</p>
http://itensor.org/support/2395/using-iqtensor-for-general-states?show=2426#a2426Fri, 07 Aug 2020 21:48:31 +0000Answered: Entanglement entropy (Julia)
http://itensor.org/support/2423/entanglement-entropy-julia?show=2424#a2424
<p>Hi Jacopo,</p>
<p>Here's a code for computing the von Neumann entropy in Julia:</p>
<pre><code>using ITensors
function entropy_von_neumann(psi::MPS, b::Int)
orthogonalize!(psi, b)
_,S = svd(psi[b], (linkind(psi, b-1), s[b]))
SvN = 0.0
for n in dim(S, 1)
p = S[n,n]^2
SvN -= p * log(p)
end
return SvN
end
N = 10
s = siteinds("S=1/2", N)
psi = randomMPS(s, 4)
SvN = entropy_von_neumann(psi, b)
</code></pre>
<p>Hopefully we will find time to create code formulas for common operations like this in Julia.</p>
<p>Cheers,<br>
Matt</p>
http://itensor.org/support/2423/entanglement-entropy-julia?show=2424#a2424Wed, 05 Aug 2020 20:01:11 +0000Answered: Purpose of various actions and parameters in replacebond! function?
http://itensor.org/support/2418/purpose-various-actions-parameters-replacebond-function?show=2419#a2419
<p>Hi Sujay,</p>
<p>1) The Spectrum object returns the eigenspectrum of the density matrix (the squared singular values). The idea is that, in the process of calculating the factors <code>L</code> and <code>R</code>, the eigenspectrum is often easily calculated as well, and it is a useful quantity for determining things like the entanglement entropy. It is returned so that you don't have to do extra work to calculate the eigenspectrum from either <code>L</code> or <code>R</code>, and users may want to print the eigenspectrum or return it from dmrg and perform calculation with it.</p>
<p>2) You may want to set normalize to true in cases like imaginary time evolution with TEBD, where if you don't normalize then the state's normalization will approach zero after some number of steps. <code>replacebond!</code> is a convenient place for that normalization to occur. By default it is chosen to be false, since it is application-dependent when someone may want that to occur, and users might want to normalize manually in case they want to save the norm (if it is physically relevant, for example).</p>
<p>3) The MPS/MPO types in ITensor can mostly be thought of as just vectors of ITensors that make up the MPS/MPO. However, they are a little more sophisticated than that, since they keep track of the orthogonality of the MPS/MPO. Information about the orthogonality is useful in various functions, where if you know the orthogonality than you can simplify certain expressions. So <code>l = leftlim(M)</code> is supposed to be set to <code>l</code>, such that sites <code>1:l</code> are guaranteed to be left orthogonal, and <code>r = rightlim(M)</code> is supposed to be set to <code>r</code>, such that sites <code>r:length(M)</code> are guaranteed to be right orthogonal.</p>
<p>This is helpful so that certain functions can assume that an MPS has a certain orthogonality so that they don't have to do extra work to reorthogonalize. For example, the <code>sample</code> function, which takes random samples of an MPS, assumes a certain orthogonality of the MPS that is input. In functions that manipulate tensors of an MPS/MPO, it is therefore good practice to keep track of the orthogonality so that extra work doesn't have to be done to unnecessarily reorthogonalize the MPS (or check for the orthogonality, which would be nearly as much work). Not keeping track of the orthogonality wouldn't lead to wrong code, but in general would require extra unnecessary work to be done.</p>
<p>-Matt</p>
http://itensor.org/support/2418/purpose-various-actions-parameters-replacebond-function?show=2419#a2419Wed, 29 Jul 2020 13:21:24 +0000Answered: How do you separate product of two ITensor objects if the two tensors do not have any common indices? (Julia)
http://itensor.org/support/2403/separate-product-itensor-objects-tensors-common-indices-julia?show=2416#a2416
<p>(Please see answer to question in discussion above.)</p>
http://itensor.org/support/2403/separate-product-itensor-objects-tensors-common-indices-julia?show=2416#a2416Tue, 28 Jul 2020 17:32:15 +0000Answered: Julia script for calculating energy gaps
http://itensor.org/support/2411/julia-script-for-calculating-energy-gaps?show=2412#a2412
<p>Hi Arnab,<br>
Thanks for the question - we do need to post a code example for this. Here is a short explanation though, and using it you ought to be able to adapt one of the other DMRG code examples to do excited states.</p>
<ol>
<li><p>say you calculate the ground state as follows:</p>
<p>energy0,psi0 = dmrg(H,psi0_i,sweeps)</p></li>
</ol>
<p>where here psi0_i is the initial guess for the ground state and psi0 is the optimized ground state.</p>
<ol>
<li><p>now you can calculate the first excited state as:</p>
<p>energy1,psi1 = dmrg(H,[psi0],psi1_i,sweeps;weight=weight)</p></li>
</ol>
<p>where psi1_i is the initial guess for the first excited state and <code>weight</code> is a positive number that you can adjust to penalize non-orthogonality of the ground and first excited state by different amounts (like a Lagrange multiplier).</p>
<ol>
<li><p>you can continue to calculate the second excited state as:</p>
<p>energy2,psi2 = dmrg(H,[psi0,psi1],psi2_i,sweeps; weight=weight)</p></li>
</ol>
<p>One tip is to do lots more sweeps for excited states than for ground states. Use your best judgement, and make sure that the energy is no longer changing over multiple sweeps before being sure things have converged. People often ask what value to take for the weight and I do not know because it is problem-dependent. Taking the weight to be 1.0 (the default) is good for most purposes though you can try other values to see if it speeds up convergence.</p>
<p>Hope that helps!</p>
<p>Miles</p>
http://itensor.org/support/2411/julia-script-for-calculating-energy-gaps?show=2412#a2412Tue, 28 Jul 2020 16:04:44 +0000Answered: Swapping indices of an MPS for Hubbard
http://itensor.org/support/2379/swapping-indices-of-an-mps-for-hubbard?show=2409#a2409
<p>See the comments for an answer.</p>
http://itensor.org/support/2379/swapping-indices-of-an-mps-for-hubbard?show=2409#a2409Tue, 28 Jul 2020 00:59:29 +0000Answered: Intel MKL error
http://itensor.org/support/2345/intel-mkl-error?show=2389#a2389
<p>(Please see the discussion above.)</p>
http://itensor.org/support/2345/intel-mkl-error?show=2389#a2389Fri, 24 Jul 2020 02:55:35 +0000Answered: Looking for recommendations for applying Tensor Networks for simple problems (Julia).
http://itensor.org/support/2362/looking-recommendations-applying-networks-simple-problems?show=2388#a2388
<p>Hi, thanks for the reply above. I’m still not totally sure what you are looking for, because applying DMRG to the Ising model does seem like a good way to start. But if you are looking for some other activities to practice using DMRG and MPS here is another thing you can do.</p>
<ol>
<li><p>take the example DMRG code from here:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=julia&page=formulas/mixed_sites_dmrg">http://itensor.org/docs.cgi?vers=julia&page=formulas/mixed_sites_dmrg</a></p></li>
<li><p>modify it to measure on every site at the end, after the MPS is optimized, using code similar to that in this “code formula” page:<br>
<a rel="nofollow" href="http://itensor.org/docs.cgi?vers=julia&page=formulas/measure_mps">http://itensor.org/docs.cgi?vers=julia&page=formulas/measure_mps</a></p></li>
</ol>
<p>The resulting magnetization should be rather flat!</p>
<ol>
<li>now change the logic of how the “siteinds” function is called at the top by changing the condition <code>isodd(n)</code> to <code>(n==1)</code> which will set the spin to be “S=1/2” only on the first site. The bulk sites and site N will be S=1 spins. Rerun the calculation. What’s changed about the magnetization? Can you explain why it’s still very flat on the right-hand side? (It has to do with the physics of SPT’s and the “AKLT” picture of the physics of the S=1 Heisenberg chain.)</li>
</ol>
<p>For something resembling a walk through, have you looked at the paper “DMRG in the Age of Matrix Product States” by Schollwoeck? It is essential reading for anyone wanting to become an expert in MPS techniques. </p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2362/looking-recommendations-applying-networks-simple-problems?show=2388#a2388Fri, 24 Jul 2020 02:54:50 +0000Answered: Why is a ProjMPO callable but an ITensor not? (Julia)
http://itensor.org/support/2376/why-is-a-projmpo-callable-but-an-itensor-not-julia?show=2384#a2384
<p>It sounds like you are trying to pass the ITensor <code>M</code> as the operator directly to eigsolve. If that is the case, we have not defined the operation <code>M(v)</code>, since it is not clear what the definition of that should be in general (it makes sense if ITensor M has pairs of primed and unprimed indices, but doesn't for other ITensors). I had been considering defining <code>M(v)</code> for certain kinds of ITensors, but we were being conservative about it to start out.</p>
<p>In the meantime, you can define your own callable ITensor wrapper, which here I call an ITensorMap:</p>
<pre><code>using ITensors
using KrylovKit
i = Index(2)
M = randomITensor(i', dag(i))
v0 = randomITensor(i)
# λs, vs = eigsolve(M, v0)
# Gives:
# ERROR: MethodError: objects of type ITensor{2} are not callable
struct ITensorMap
A::ITensor
end
(M::ITensorMap)(v::ITensor) = noprime(M.A * v)
λs, vs = eigsolve(ITensorMap(M), v0)
@show norm(noprime(M * vs[1]) - vs[1] * λs[1])
</code></pre>
<p>This will be a way to test if you are making your custom projected MPO correctly.</p>
<p>However, in general, it is not as efficient to form the operator and then contract it with the ITensor <code>v</code>. Instead, you should define something like the ProjMPO that contains the ITensors of the projected Hamiltonian you are interested in (in your case, H[1], H[N], and then the contraction of the bulk tensors 2...N-1), and define your own function like the product function here:</p>
<p><a rel="nofollow" href="https://github.com/ITensor/ITensors.jl/blob/master/src/mps/projmpo.jl#L71">https://github.com/ITensor/ITensors.jl/blob/master/src/mps/projmpo.jl#L71</a></p>
<p>which takes the ITensor "vector" and applies the appropriate tensors. In the end the two approaches are equivalent, but the order of contraction is different, which can make a big difference in the efficiency of your algorithm.</p>
http://itensor.org/support/2376/why-is-a-projmpo-callable-but-an-itensor-not-julia?show=2384#a2384Thu, 23 Jul 2020 14:38:50 +0000Answered: When ITensors in dev mode, modifications to existing functions are recognized but new functions are not
http://itensor.org/support/2375/itensors-modifications-existing-functions-recognized-functions?show=2380#a2380
<p>Hi Sujay,<br>
I believe the reason you are seeing this is because you are creating new functions inside of the ITensors module (which is fine) but then not listing these function names as "exported". So they are only remaining accessible as <code>ITensors.function_name</code> rather than just <code>function_name</code>. Or you can explicitly import them by doing <code>import ITensors: function_name</code> in your driver code.</p>
<p>We keep all of the ITensors exports in the file src/exports.jl</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2375/itensors-modifications-existing-functions-recognized-functions?show=2380#a2380Wed, 22 Jul 2020 17:51:21 +0000Answered: non-Hermitian DMRG in Julia
http://itensor.org/support/2367/non-hermitian-dmrg-in-julia?show=2371#a2371
<p>Hi Terry,<br>
The short answer is that this is not currently available in the Julia version at the level of an option you can pass to the <code>dmrg</code> function, if that's what you are asking. Similarly for the C++ version there is no such option, though as you noted we do offer an Arnoldi algorithm code.</p>
<p>But for both versions you could modify the DMRG code to use Arnoldi. For the Julia version this should actually be pretty straightforward, because the <code>eigsolve</code> function we call from Julia is a function offered by the package KrylovKit.jl and that same <code>eigsolve</code> function offers the ability to change the algorithm to Arnoldi. Here is a documentation page on eigsolve explaining about this:<br>
<a rel="nofollow" href="https://jutho.github.io/KrylovKit.jl/stable/man/eig/">https://jutho.github.io/KrylovKit.jl/stable/man/eig/</a></p>
<p>However, not having written non-Hermitian DMRG myself, I'm not sure off hand what other changes might be needed to the rest of the DMRG algorithm. Perhaps not very many other than changing the eigen solver? </p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2367/non-hermitian-dmrg-in-julia?show=2371#a2371Mon, 20 Jul 2020 17:57:00 +0000Answered: Cluster Hamiltonian ground state MPS bond dimension
http://itensor.org/support/2369/cluster-hamiltonian-ground-state-mps-bond-dimension?show=2370#a2370
<p>Hi Arnab,<br>
Thanks for the question. I believe the reason for the bond dimension of 4 you're seeing is because you are using periodic boundary conditions. If you envision the MPS as going around a circle and having bond dimension 2 on every bond, but then flattening this topology into a line, now with the bond N->1 "folded" through or "doubled over" so that it overlaps with all of the bulk bonds then each bulk bond is now carrying both the usual local entanglement (requiring bond dimension 2) as well as the extra entanglement which is going from site 1 to site N, roughly speaking.</p>
<p>Another way of putting this is that while your Hamiltonian is periodic, your MPS isn't, so this mismatch leads to a larger bond dimension.</p>
<p>I tried your code, deleting the N->1 bond terms and sure enough I do get a bond dimension of 2 afterward.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2369/cluster-hamiltonian-ground-state-mps-bond-dimension?show=2370#a2370Mon, 20 Jul 2020 14:47:35 +0000Answered: How to calculate spectrum function by using ITensor?
http://itensor.org/support/2366/how-to-calculate-spectrum-function-by-using-itensor?show=2368#a2368
<p>Hi，SugarYu </p>
<p>the definition C^{z}(x,t)=<g.s|exp{iHt}S^{z}(x)exp(-iHt)S^{z}(0)|g.s> is right， but<br>
C^{z}(x,t)=innerC(psi,psi4) is not correct！ <br>
You need C^{z}(x,t)=innerC(psi,psi4) <em>(Exp(energy</em>tstep*n)), where energy is the groud-state energy, and n is Time evolve number( or n-1 , dependent on measurement before Time evolve or not)</p>
<p>Then Fourier transform will be performed to obtain S(q,\omega）.</p>
<p>p.s. the S^{z}{1} often acts on central spin，N/2 or N/2+1 to avoid the boundary effects.</p>
<p>Hope it can help you</p>
http://itensor.org/support/2366/how-to-calculate-spectrum-function-by-using-itensor?show=2368#a2368Mon, 20 Jul 2020 09:16:43 +0000Answered: Trying to understand "product" function in projmps.jl and how to generalize to n-site DMRG (Julia)
http://itensor.org/support/2344/trying-understand-product-function-projmps-generalize-julia?show=2361#a2361
<p>Hi Sujay,<br>
To answer your question I thought it would be easier to show you some diagrams, which I uploaded to this link:</p>
<p><a rel="nofollow" href="https://itensor.org/miles/ProjMPS.pdf">https://itensor.org/miles/ProjMPS.pdf</a></p>
<p>Can you please let me know if those notes answer your question and give a clear enough idea of what the code there is doing? </p>
<p>The purpose of this ProjMPS overall is to make a Hamiltonian term that is equal to |M><M| for some state M (represented as an MPS) then include this Hamiltonian term in an efficient way within a DMRG calculation that's optimizing an MPS psi.</p>
<p>I think the code there already partially works for n-site DMRG, because you can see that makeL! and makeR! (which are called by position!) query a parameter P.nsite which right now is always set to 2 but could be adjusted. Then the code in <code>product</code> would need to be extended to multiply on the center "n" tensors of M in the lower part of the diagram in the notes, rather than just the two center tensors right now. These two tensors right now are getting included by the lines:</p>
<pre><code>Lpm = dag(prime(P.M[P.lpos+1],"Link"))
</code></pre>
<p>and </p>
<pre><code>Rpm = dag(prime(P.M[P.rpos-1],"Link"))
</code></pre>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2344/trying-understand-product-function-projmps-generalize-julia?show=2361#a2361Thu, 16 Jul 2020 20:00:28 +0000Answered: Copying MPS into vector
http://itensor.org/support/2354/copying-mps-into-vector?show=2356#a2356
<p>Hi, I’d recommend Matt’s answer above as the correct one:</p>
<p>1) yes, the copy of an MPS does not copy the data right away. (Actually this is true even at the ITensor level, so applies to any container holding ITensors too.) So the copying only happens at the last possible minute, when you modify one of the MPS tensors and then have to copy it anyway.</p>
<p>2) most important is what Matt said about the timing. It’s not slow to copy data, or to do any operation, unless you can measure that it takes a significant percentage of your code’s running time. So if your code copies MPS thousands of times, or if the MPS itself is on a system with thousands of sites or has a bond dimension in the 10’s of thousands, then it might be a slow part of your code. But otherwise it should take probably only a handful of microseconds or at worst milliseconds at most for normal MPS sizes.</p>
<p>Please let us know if you are able to measure a slowdown of your code that is due to copying MPS and we can discuss ways to mitigate it in that case.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2354/copying-mps-into-vector?show=2356#a2356Sat, 11 Jul 2020 19:58:02 +0000Answered: Storing MPS Tensors as Text/HDF5 file in Julia
http://itensor.org/support/2347/storing-mps-tensors-as-text-hdf5-file-in-julia?show=2351#a2351
<p>Hi, thanks for the question. This is something we need to document even more about the Julia version of ITensor to make it clear it’s available and that you can use it for MPS too. </p>
<p>Here are the steps to write an ITensor to an HDF5 file, and you can use exactly the same steps to write a whole MPS to HDF5, just with T being an object of type MPS instead of type ITensor:</p>
<p><a rel="nofollow" href="http://itensor.org/docs.cgi?vers=julia&page=formulas/itensor_hdf5">http://itensor.org/docs.cgi?vers=julia&page=formulas/itensor_hdf5</a></p>
<p>Please let me know if you have any questions about that or if you run into any issues and I’d be happy to discuss. </p>
<p>Miles</p>
http://itensor.org/support/2347/storing-mps-tensors-as-text-hdf5-file-in-julia?show=2351#a2351Fri, 10 Jul 2020 15:22:21 +0000Answered: Non-consecutive swap gates
http://itensor.org/support/2330/non-consecutive-swap-gates?show=2333#a2333
<p>Thanks for the good question. To officially answer the question, I agree with Matt's answer above. Unless you have a very specific understanding of the entanglement properties of the wavefunction you're working with, such that it can be compactly represented as an MPS in both site orderings (which is very unlikely given how non-locally they are related to each other) then probably you will encounter very large bond dimensions going to the non-local site order.</p>
<p>If you are definitely going to stick to nnn interactions at most, though, and if you are interesting in doing some by-hand coding beyond just using the ITensor gateTEvol function, then there are some other things you may want to try. No guarantee these are faster though the first one probably is:</p>
<ol>
<li><p>instead of applying an explicit swap gate, do a "virtual swap gate" by just contracting the MPS tensors for sites j+1,j+2 then SVD'ing them back apart so that the "U" tensor carries the j+2 site index (and the left link index from the original j+1 MPS tensor). ITensor lets you control which indices end up on U by which indices you pass to the <code>svd</code> function. Then do a similar contract-and-SVD to 'swap' back. It saves the extra computation time of applying an explicit gate to the MPS.</p></li>
<li><p>try contracting 3 MPS tensors in a row, so j,j+1,j+2 and then applying all possible nn and nnn gates acting on those 3 sites. This has an advantage that it can reduce the total truncation errors incurred because no truncation is needed while applying those gates. Now use the SVD to factorize off the "j" site and left link index into an update MPS tensor for site j. Save the remaining (S*V) tensor from the SVD and contract it with the MPS tensor for site j+3 to go to the next configuration. This approach may not be the most efficient, though, due to working with the larger "core" tensor having one extra site index. But it could be more efficient due to less swapping and more accurate due to fewer truncations.</p></li>
</ol>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2330/non-consecutive-swap-gates?show=2333#a2333Tue, 07 Jul 2020 14:29:14 +0000Answered: How to implement a truly periodic MPS? (Julia)
http://itensor.org/support/2327/how-to-implement-a-truly-periodic-mps-julia?show=2331#a2331
<p>Hi Sujay,<br>
This is a worthy goal to think about, but let me discuss what I know about the status of periodic MPS and a possible alternative.</p>
<p>First, would your technical issue with quantum numbers be solved also if you were to consider an infinitely-long system? As you likely know, MPS methods work well in an infinite setup and there are some very advanced and efficient algorithms for optimizing infinite MPS.</p>
<p>Truly periodic MPS, on the other hand, run into a number of crucial technical problems that to my knowledge have never been satisfactorily solved. They include:<br>
1. poor scaling or of periodic algorithms, which either involve a step that scales as bond dimension to the fourth power (so much worse that finite DMRG)<br>
2. alternatively, better scaling methods but at the cost slow updates like gradient descent optimization<br>
3. inability to efficiently compute a canonical form of periodic MPS, making steps like SVD'ing a two-site tensor or otherwise adapting the bond dimension either uncontrolled / inaccurate or inefficient</p>
<p>At the same time, for many systems either open boundary conditions are as good or an even better choice (believe it or not) though I do get that yours is a special case. But then there is the case of infinite MPS which of course is even better in some ways than periodic because it's completely free of finite-size effects.</p>
<p>Regarding the specific algorithm you sketched, I bet if you write it out in more detail you will see that it suffers from the first and third issues above, namely it will scale as the fourth power of bond dimension (thus hundreds of times slower than open DMRG) and the replacebond step will not occur in an orthogonal basis, making it an uncontrolled method.</p>
<p>Hope that helps -</p>
<p>Miles</p>
http://itensor.org/support/2327/how-to-implement-a-truly-periodic-mps-julia?show=2331#a2331Mon, 06 Jul 2020 12:03:44 +0000Answered: size() in gmres
http://itensor.org/support/2313/size-in-gmres?show=2326#a2326
<p>(Marked as answered by discussion in comments above)</p>
http://itensor.org/support/2313/size-in-gmres?show=2326#a2326Fri, 03 Jul 2020 16:11:32 +0000Answered: convert a quantum-number MPS to a no-quantum-number MPS
http://itensor.org/support/2320/convert-a-quantum-number-mps-to-a-no-quantum-number-mps?show=2325#a2325
<p>Hi Chiamin,<br>
Thanks for the question. I realized we hadn't documented this feature well enough so I just added some information about it to the website.</p>
<p>The feature I'd recommend you use for this is the function <code>removeQNs(psi)</code> where <code>psi</code> is an MPS. You can call a similar function on an MPO. The <code>removeQNs</code> function returns an MPS (or MPO) with all of the zeros filled in and QN information removed from the indices.</p>
<p>So if you are able to make your operator as an MPO and your MPS as well, then you can call <code>removeQNs</code> on all of them to get dense versions and compute the quantity you want with <code>inner</code>. Note that depending on how you made each MPS or the MPO you may need to modify their site indices to be the same. But if e.g. you made the MPO with AutoMPO using the same site set as for the MPS then you should be fine.</p>
<p>Best,<br>
Miles</p>
http://itensor.org/support/2320/convert-a-quantum-number-mps-to-a-no-quantum-number-mps?show=2325#a2325Fri, 03 Jul 2020 16:11:05 +0000How to measure the momentum of an MPS?
http://itensor.org/support/2319/how-to-measure-the-momentum-of-an-mps
<p>Hi,</p>
<p>I was trying to measure the momenta of some MPSs in the Electron site class. Here is my attempt:</p>
<p>I got the desired results when I measure the momentum @@P@@ using toMPO. However, when I used the function toExpH to exponentiate the momentum operator and get the usual translation operator @@T@@, I got the following error message:</p>
<pre><code>From line 885, file itensor.cc
div(T1)=QN({"Nf",0,-1},{"Sz",0}) must equal div(T2)=QN({"Nf",1,-1},{"Sz",-1}) when adding T1+T2
div(T1)=QN({"Nf",0,-1},{"Sz",0}) must equal div(T2)=QN({"Nf",1,-1},{"Sz",-1}) when adding T1+T2
Aborted (core dumped)
</code></pre>
<p>I wasn't able to figure out what this message is saying? Also is this the right way to measure the momenta of some MPSs, and is this the best way to exponentiate some MPO? Below is the code for obtaining the MPOs for the operators @@P@@ and @@T@@.</p>
<pre><code># define PI 3.1415926535897932
MPO Momentum(Electron const& sites)
{
auto N = length(sites);
auto ampo = AutoMPO(sites);
for(int k = 1; k <= N; ++k)
{
for(int i = 1; i <= N; ++i)
{
for(int j = 1; j <= N; ++j)
{
ampo += 2.0*PI/(N*N)*k*std::exp(Cplx_i*2.0*PI/N*k*(i-j)),"Cdagup",j,"Cup",i;
ampo += 2.0*PI/(N*N)*k*std::exp(Cplx_i*2.0*PI/N*k*(i-j)),"Cdagdn",j,"Cdn",i;
}
}
}
auto T = toExpH(ampo,1.0,{"Cutoff=",1E-20});
auto P = toMPO(ampo,{"Cutoff=",1E-20});
return T; //or P
}
</code></pre>
<p>Thanks,<br>
WunderNatur</p>
http://itensor.org/support/2319/how-to-measure-the-momentum-of-an-mpsThu, 02 Jul 2020 07:23:23 +0000Answered: Sweeping algorithm utilizing ITensor capabilities as best as possible.
http://itensor.org/support/2305/sweeping-algorithm-utilizing-itensor-capabilities-possible?show=2311#a2311
<p>Hi Nick,<br>
I think this is a good question - no problem. First of all, I wouldn't say there's much about ITensor specifically you can use to make this algorithm faster. By this I mean that the main things you can improve are mostly to do with the algorithm itself, and you would get the same characteristics (scaling, speed) with any reasonably efficient tensor library. So I'm just answering that part of your question first. Of course we do hope and believe that ITensor's interface makes such algorithms nice to write :^)</p>
<p>Now in terms of what you could do to make this faster, let me list a few ideas. Please note that I may have missed something in your code here or there, and I didn't run it or do a detailed sketch of the steps, so please discard or do not take too seriously any comments which you think don't apply or make sense:</p>
<ol>
<li><p>instead of building the L[i] and R[i] arrays across the whole system, do you not just need R[2] for the first step, then L[1] and R[3] for the second step, and so on? (Maybe I'm off-by-one on those numberings there but hopefully you see what I'm suggesting.) So potentially you could save a big factor here by only building the L's and R's needed at each step, and updating them as you do one sweep across rather than building them all up front.</p></li>
<li><p>the other thing I'd note is more vague, but I'm concerned by your statement that the code gets a lot slower as you increase the bond dimension. This kind of task should be rather fast for MPS of dimensions approaching 1000 at least, where I'd still expect it to take only 10's of minutes at most. So if it's much slower than that, then probably it's not scaling correctly. So then I'd recommend you print out each intermediate tensor and inspect its indices. Work out the scaling of each step and make sure it scales as chi^3 where chi is the typical bond dimension of the two MPS involved (just here assuming they have the same bond dimension for simplicity).</p></li>
</ol>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2305/sweeping-algorithm-utilizing-itensor-capabilities-possible?show=2311#a2311Tue, 30 Jun 2020 16:56:49 +0000Answered: Questions about checks for ITensors.jl pull request
http://itensor.org/support/2290/questions-about-checks-for-itensors-jl-pull-request?show=2298#a2298
<p>Hi Sujay, thanks for the question.</p>
<p>(1) a broken test is one that is known to fail, and is marked as broken meaning "don't mark the whole test run as failing just because this test does, and we should fix this test later". It could be either because the test is out of date or was written incorrectly. For more information you can read about @test_broken here: <a rel="nofollow" href="https://docs.julialang.org/en/v1/stdlib/Test/#Broken-Tests-1">https://docs.julialang.org/en/v1/stdlib/Test/#Broken-Tests-1</a></p>
<p>(2) I'm not sure why that particular test was failing. As you know, the tests get run automatically with each pull request on 3 different operating systems, and have recently been working there. So it's hard to comment on this failure without detailed steps to reproduce. If you think it's a bug in the tests or the library, could you please file an issue with steps to reproduce? We'd definitely like to fix this if it's a bug.</p>
<p>Please let me know if I didn't answer one of your questions -</p>
<p>Best regards,<br>
Miles</p>
http://itensor.org/support/2290/questions-about-checks-for-itensors-jl-pull-request?show=2298#a2298Mon, 29 Jun 2020 14:23:49 +0000Unable to adjust last site due to local constraint with neighbors --> Is it possible to "rotate" a state? (Julia)
http://itensor.org/support/2295/unable-adjust-constraint-neighbors-possible-rotate-julia
<p>I am interested in developing on ITensors.jl the lattice Schwinger model with alternating (anti)fermion sites and links (representing electric flux). Each spatial site has 4 ITensors sites--first a fermion site, then a link, then an antifermion site, and then another link. It incorporates a local constraint given by Gauss's Law, and I've gotten it to mostly work (I think) by using a few tricks.</p>
<p>However, I am still running into one problem. Basically, the smallest "unit" that you can change without changing anything else is a unit consisting of two (anti)fermion sites and the link between them. For example, I can change sites 1-3 without changing anything else; similar for 3-5, 5-7, etc. This is why I run 3-site DMRG (this isn't natively in ITensors; I developed this code and have put a pull request for it here: <a rel="nofollow" href="https://github.com/ITensor/ITensors.jl/pull/434).">https://github.com/ITensor/ITensors.jl/pull/434).</a> However, this spells trouble when you reach the end. One of the "units" that you should be able to change is that consisting of sites 4N-1, 4N, and 1, where N is the number of spatial sites. However, DMRG doesn't do such a thing, because it only works on a bundle of adjacent sites. This means that, due to the Gauss's Law constraint enforced by sites 4N, 1, and 2, site 4N is stuck unless one also changes either site 1 or site 2, which only happens if one uses k-site DMRG for k=4N-1 or 4N (i.e. adjusting the whole state, minus at most one site, in each step). For example, for 2 spatial sites, I need 7-site DMRG to be able to change site 8 at all, and for 3 spatial sites, I need 11-site DMRG. This is simply infeasible for any lattice larger than 3 spatial sites.</p>
<p>I am wondering whether anyone has any ideas about how to handle this or has dealt with something similar before. One idea I had was "rotating" the state between or during sweeps in the DMRG process, so that every site has at least some time not being the one at the end, which is stuck in place. As an example, one could "rotate" the state so that the last two sites are now the first two, and then sites 4N, 1, and 2 (which are now sites 2-4), are together and can be optimized. And then one can rotate the state back and complete the rest of the sweep. But I'm not sure how one would do such a thing, or whether it would really produce the desired results. Does anyone know of a feasible fix for this, whether by rotating the state or by any other means?</p>
<p>It is true that this error should in principle become relatively small for a sufficiently large number of spatial sites, but in my research, I will mostly be working with fairly small lattices, for which such limits won't apply. Also, I need my code to be accurate in finding the ground state so that I can accurately evaluate excited states, as well as assess my code against existing results on the Schwinger model produced using other computational methods (e.g. exact diagonalization). Any help on this would be greatly appreciated.</p>
http://itensor.org/support/2295/unable-adjust-constraint-neighbors-possible-rotate-juliaMon, 29 Jun 2020 05:04:14 +0000Loop over Args
http://itensor.org/support/2293/loop-over-args
<p>Hello, </p>
<p>Is there a way to loop over the Args elements?</p>
<pre><code>for(Val const & a: args){
//Do something with a
}
</code></pre>
<p>I'm using Args to simplify the construction of operators. Since this construction is quite general, I don't know what Args have been added so I would like to loop over all elements. Thank you very much.</p>
<p>Best,<br>
João</p>
http://itensor.org/support/2293/loop-over-argsSun, 28 Jun 2020 17:12:56 +0000