I would like to be able to use functions like expect(psi, "Delta") and correlation_matrix(psi, "Deltadag", "Delta") with this operator
My initial approach was to define function ITensors.op!(Op::ITensor, ::OpName"Delta", ::SiteType"tJ", ...). However, I am not sure how to make the operator apply to two indices. Any advice?
A possible way is to first write down the explicit form of \Delta^{\dagger}_i\Delta_j , and then define the operator with the help of AutoMPO(), and calculate the exepctation value by calling inner(psi',delta,psi)
For your case, the code can be like
delta = AutoMPO()
delta += 1/sqrt(2) "Cdndag", i + 1, "Cupdag", i, "Cup", j, "Cdn", j + 1
#other terms here ....#
delta = MPO(delta,sites)
correlation(i,j)= inner(psi',delta,psi)
This may not be the smartest coding but can quickly obtain your correlation function
Thanks for the question, apateonas. You’re on the right track, as be able to use your operator definition in functions like expect or correlation_matrix you need to define it as an op or op! function overload as you are trying to do.
Fortunately it’s pretty easy to do! Here is an example from our “Qubit” site type of a two-site operator (the CNOT gate in this case):
So you just have to have the op method overload take the name of your operator and SiteType that you want it to work for, then have the function return the (appropriately sized) matrix defining your operator.
Please let me know if you need more information than that for your case. Even though your case involves fermions, you shouldn’t have to do anything special since your operator is “bosonic” overall, meaning it involves an even number of c operators.
Hi Miles, thank you for your input! I am new to the ITensor library (and tensor computations in general), so it would help me to go over the specifics in a bit more depth:
I am currently working on the tJ model. As mentioned, the operator I want to implement is:
It operates on two sites: i and the next site i+1. In general, I may want for it to operate on arbitrarily separated sites i and j.
You provided the example of the 2-site CNOT operator for Qubit sites, which is a 4x4 matrix. In my case, I believe I will need to define a 9 x 9 matrix, as each tJ site has 3 dimensions (emp, up, dn). Is this correct? Is it possible to cleanly construct this matrix from the existing definitions of Cup, Cdn, etc?
Once this operator is defined, I will want to run correlation_matrix(psi, "Deltadag", "Delta"). How can I specify that Delta is to be applied to adjacent (or arbitrarily separated) sites? I naively attempted correlation_matrix(psi, "CNOT", "CNOT") from your example just to if I would be able to apply multi-site operators with correlation_matrix, and understandably got a DimensionMismatch error. What am I missing here?
The correlation_matrix currently only works for computing the correlation matrix of single-site operators.
The suggestion above to compute the correlation matrix by turning an OpSum/AutoMPO into an MPO would be the easiest approach. This has worse scaling than the built-in correlation_matrix function in ITensor (the MPO approach scales as N^3 while the correlation_matrix implementation scales as N^2). Otherwise you would have to create your own version of correlation_matrix that works with multi-site operators.
This is one reason why we only recently introduced the correlation_matrix function, since there are many possible extensions to it which would be challenging to cover by a single library function.
Thanks for the tip mtfishman. I will work on implementing my own correlation calculation with the MPO instead. Is it possible to record two-site correlation as a feature request?
It may not be something we are eager to implement soon, since there is potentially endless numbers of measurements people might want (today someone wants correlation_matrix extended to 2-site operators, tomorrow it is 3-site, the next day is 2-local operators on a square lattice, the day after is 2-local operators on a triangular lattice in momentum space, etc.). We would have to think carefully about how we might design it in a general way that covers many use cases but isn’t too burdensome for us to write, maintain, and extend the code.