Passing ITensor to a function in C++

+1 vote
asked Nov 28 by oguzumut (140 points)

Hello,

I had problems passing Sensor structure from main to a function to carry out operations inside the function and return it. It behaves as the indexing are changing inside the function which makes erroneous to perform other operations like contractions inside the main function.

I would be glad if you have any guidance on this problem.

Best

commented Nov 28 by miles (19,650 points)
Hi, could you provide some sample code? If you pass the tensor as a reference, then changes made to it inside the function will affect the tensor after the function returns. Also by Sensor did you mean tensor?
commented Nov 28 by oguzumut (140 points)
Hi,
Sorry for the typing error.  Sensor means ITensor obviously:)
I first checked that my code is working properly before I've tried to create Itensors inside different functions. For example:

void jacobian(const struct cella_stru& c, ITensor& dPhi ){


        auto k = Index("index k",2);
        auto l = Index("index l",2);


    struct cella_stru stress = stress_easy (c);
        dPhi.set(k(1),l(1),stress.c11);
        dPhi.set(k(1),l(2),0.5*stress.c12);
        dPhi.set(k(2),l(1),0.5*stress.c12);
        dPhi.set(k(2),l(2),stress.c22);

}

If I use dPhi returned by this function inside the main, the tensor contraction does not work properly. When I try to contract it  with another matrix  (with index k and index l initiated inside the main), instead of contracting the tensors, the rank of the resulting tensor increases.
I think somehow it is related to the way I use k and l but I couldn't figure it out.

Thanks

1 Answer

+1 vote
answered Nov 28 by miles (19,650 points)

Hi, so based on the sample code you posted above (thanks for that) the issue is that to use the .set method, you need to pass indices that are the actual indices the ITensor has.

So the correct code depends on a few things. If you constructed the ITensor dPhi like this:

auto dPhi = ITensor(k,l);

then it is those k and l indices (the ones used to construct dPhi) which you need to use in the .set method inside your function. The new k and l indices you create inside of your function will be different in this case from the ones used to construct dPhi even though they have the same variable names and perhaps other similar properties.

This can be a confusing aspect of indices in ITensor: the main thing that distinguishes is an internal id number which is automatically fixed when an index is constructed and which can't be changed. The id number is made by the constructor and any copies of that index will have the same id.

I'd recommend printing out some indices using the command Print(k); and Print(l); You'll see the id numbers in the output as the last number inside the parenthesis.

On the other hand if you didn't construct dPhi outside of your function, you'll need to do so in order to call the .set method the way you're doing.

So most likely you need to expand the definition of your function to allow you to pass the indices of dPhi as additional function parameters.

Best regards,
Miles

commented Nov 28 by oguzumut (140 points)
OK, I got it. This is exactly what I thought.
What is the type of indices in ITensor library? So that I can pass them as arguments.
Thanks a lot.
Regards.
commented Nov 28 by oguzumut (140 points)
It is working as it is supposed to work if I do:

void jacobian(const struct cella_stru& c, ITensor& dPhi, Index k , Index l ){
  struct cella_stru stress = stress_easy (c,1.,BLK1::beta_Var);
        dPhi.set(k(1),l(1),stress.c11);
        dPhi.set(k(1),l(2),0.5*stress.c12);
        dPhi.set(k(2),l(1),0.5*stress.c12);
        dPhi.set(k(2),l(2),stress.c22);

}
commented Nov 28 by miles (19,650 points)
Great - yes that's the correct idea. As a technical detail, it can be faster to pass arguments as const references as you do with your "c" argument. But Index objects are small and cheap to copy so passing them by value is fine and should be very fast.
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.
...