String correlation function in S=1 chains

Hi,
I am new to iTensor, so forgive me if my question has already been addressed before, I could not find it from searching the categories. I see a couple of very nicely written posts on computing Neel-type Correlation functions like <psi | Sz_i Sz_j |psi> where (i,j) indicates site indices like in (ITensor). However for S=1 chains , if we are interested in String correlation functions of the kind <psi | S_k * exp(i pi \sum_{j=k+1 to m-1} S_j) * S_m | psi> where * is tensor product to indicate different spin space, then what is the protocol/command to implement the MPO of such an operator and contract it against a given MPS (say |psi>). I am using the Julia version of iTensor. Here are few thoughts that I have

  1. Since each term in the exponential commutes with one another and hence the sum in the exponential can be broken down into product of exponential acting on individual spin spaces , one can now write the exponential of individual S=1 operators using Rodrigues expansion (which involves identity, the operator and its square). (Rodrigues' rotation formula - Wikipedia). However , I feel may be a more direct approach exists.

  2. If all Sk operators are Sz, then Is it somehow possible to build MPO s of the form exp (i pi Sz_k) directly for S=1 just as Sz_k can be built directly using ampo op(sites,“Sz”,k). The operator is diagonal, with diagonal elements exponentiated, so I feel there might be simple ways of doing it in Julia version of iTensor atleast for the Sz case

Any help /pointers will be greatly appreciated. Thanks a lot in advance

Hi Manas,
Good question. Many approaches are possible here. How complicated you want to get may depend on whether you want the string correlation function for all values of i <= j or just for some fixed i and then various values of j, say. Which one do you want?

Secondly, since as you said the spin operators commute, it is a straightforward matter to write the exponential as a product. Then each exponential can be computed numerically since the local spin operators are specific 3x3 matrices. I don’t think you need to use anything more fancy than that (such as the Rodrigues formula you mentioned); just matrix exponentiation would do.

Then depending on your answer to my question above about which i and j ranges you need, either a generalization of our correlation_matrix code to handle your case would be a good approach (meaning we could help you to make a code like that yourself, but which includes the string of operators) or an MPO approach could be good if you only need certain i and j values.

Hi Miles,
Thanks a lot for your reply. Here are the answers to your question.

  1. The specific version of String correlation I would need would be the following :
    String corr(0,j) = < Sz_0 * exp ^(i pi \sum_{k=1…(j-1)} Sz_k) * Sz_j >
    In other words, I would want String corr (0, j) i.e. between the 1st spin (index 0) and (j+1)th spin (index j) with the string exponential having all spin-z operators in between for all sites k \in (0,j) . The string exponential is identity for cases when j=0 and j=1 (adjacent site) and the above correlation function becomes Neel type. The index j can be a floating index that runs over the length of the spin-chain (j =0…N-1) . For example for 4 S=1 spins , the following String correlation would be required : String corr(0,0), String corr (0,1), String corr(0,2), String corr(0,3) where String corr(0,0) would just be <Sz_0^2> .

  2. As for the second point, yes a simple matrix exponential (which in this case is diagonal entries only) would suffice. But I dont know how to write that as an MPO in Julia version of iTensor (i presume its a very naive question. Pardon me) . Like given an arbitrary 3*3 matrix (in this case exponential term) how to write that as an MPO object and multiply several such MPO objects together (exp for each spin site) and contract it against an MPS.

Hopefully the point (1) above will clarify the question you asked, if not let me know , I will be more than happy to furnish more details. Thanks a lot for the help

With Regards,
Manas

Hi Miles,
I was wondering if there is any pointer u can provide me for the String correlation issue raised above? I mean how to set up the calculation in an efficient way for getting inner (psi’, A , psi) where A is the String operator MPO defined as S_z0 * expi\pi \sum_k (S_zk) S_zj where k \in (1, j-1) i.e. all sites between 0th site and jth site (for Julia the 0th site is labelled as 1). My primary question is how to construct the A MPO above just as we do for Hamiltonian or other operator construction ? like for Sz_j at jth site in a 10th site spin-1 chain one can use the following :

function one_body_op(sites, Op_str, coeff, index)
     ampo = OpSum()
     ampo += (coeff, Op_str, index)
     return MPO(ampo, sites)

spin_type= 1
no_spins = 10
one_body_op( siteinds("S=$spin_type", no_spins), "Sz", 1.0, j)

What would be the corresponding version in this OpSum() format for constructing the operator A described above with the exponential string ?

Hi Manas,
So the thing you are asking about is a little complicated in terms of finding a simple or “push button” solution where part of ITensor, such as OpSum, can do it for you. Better approaches here would be things such as:

  1. making the MPO you want “by hand” meaning setting the individual tensor elements of each MPO tensor and learning how to do that and how to manually construct MPOs
  2. even better, learning how to code correlation function calculations (basically learning how the code inside of correlation_matrix works and creating a simplified version for your purposes) since in that algorithm it’s actually rather straightforward to include “string” operators between sites i and j, but it’s not something we plan to add as a feature to correlation_matrix

As far as how you would have to do it using the OpSum interface, it would need to be something like (taking the example of i=2 and j=5):

os = OpSum()
os += "Sz",2,"expSz",3,"expSz",4,"Sz",5

where "expSz" would be a custom operator you’d also need to define by overloading the op function which the OpSum system uses to look up operator definitions.

So really I’d say approach (2) above is really your best long-term approach. For more details and training about how to actually do approach (2), while unfortunately we don’t have a Julia tutorial about it, we do have a C++ one where the code you would write in Julia would be very similar to what is shown. Here is the tutorial:
http://itensor.org/docs.cgi?vers=cppv3&page=tutorials/correlations
Does that look like something you’d be up for coding and do you see where there is room to alter the algorithm to put the string operators on the intermediate sites?

Finally, regarding your question about excited states: could you please post that as a separate question? Otherwise it can be hard to keep track of what is being discussed.

1 Like

Hi Miles,
Thanks a lot for the reply. I am in the process of understanding the correlation matrix code for C++ that you referred to. I will get back to you once I have something written which should be by end of today.
I have also edited the post and started a new topic for the excited state calculation convergence here

Thanks for making the separate post and I hope the tutorial I linked above is clear enough and is useful to you.

To translate between the C++ and Julia code, you can use the following (C++ on the left, Julia on the right):

  • op(sites,"Sz",2) becomes op("Sz",sites[2])
  • psi.position(j) becomes orthogonalize!(psi,j)
  • psi(2) becomes psi[2]
  • commonIndex becomes commonindex
  • elt(C) becomes scalar(C)
1 Like