+1 vote
asked by (540 points)
edited by

Is there a way to use the storage pointer of a tensor like a pointer of std::vector? The .store() method get a pointer of "ITData" type and can not be used directly.
Currently, I can pass the Vector class in ITensor library to other library by .data() method because the data is held by storage_type = std::vector. But this does not work for a vector like ITensor (rank one). Is there a workaround?

Find workaround at http://itensor.org/docs.cgi?page=formulas/extractdense
Can anyone give a template example so there is no need to use isComplex() to determine to call ExtractReal or ExtractCplx.

Remember to use T.scaleTo(1) before Extract the Storage of Tensor T because of the designed feature(see for example https://github.com/ITensor/ITensor/issues/139 ).


commented by (70.1k points)
Hi, I didn't quite follow the part from Update 2 to Update 3. Is it a bug you think? Or was it the expected behavior. Thanks!
commented by (540 points)
Thank you for your reply. I think its a bug in the applyFunc and doTask subsystem.
Update 2 is a practice of converting Dense ITensors store to std::vector.
As you can see from the output of mat[i], each element is 8.37(the norm of Tc) times smaller than Tc.  Seems that the applyFunc(extractReal,Tc.store()) normalizes Tc for me (normalize is wrong in my case).
commented by (70.1k points)
Hi, so I forgot if we discussed this in another thread, but if you are seeing that every element in the store is different by a factor from when you access the elements using .real or .cplx, the reason is because of the .scale() factor of the ITensor. The elements are really defined as the values in the store times the scale factor. If the scale factor is 1.0 they match, but otherwise the store elements will be different by a factor, which is by design and is an optimization for certain cases.
commented by (540 points)
Yes, we discussed at github. By realizing scale feature, everything works fine now.

1 Answer

0 votes
answered by (70.1k points)
selected by
Best answer

Hi, glad you have figured it out for the most part.

To answer your question about not needing to check isComplex() to decide to call extractReal or extractComplex, the way around this is rather than defining a function (or a lambda function) which by definition can only take a single set of arguments, you can define a function object: an object which has multiple overloads of the operator()(...) method.

So if you define (outside of your function, although inside may work too):

struct GetSize
operator()(DenseReal & d) { return d.size(); }

operator()(DenseCplx & d) { return d.size(); }


Then doing:
auto size = applyFunc(GetSize(),T.store());

However, your use case of wanting to get the pointer to the data falls outside of this approach more because of a C++ issue rather than an ITensor issue. The reason is that the pointer type would be different anyway between DenseReal and DenseCplx storage, so there can't be a common return type for the function returning the pointer. So you might as well call isComplex() and then specialize to a different function for each case.

(On a side note though, you may be able to define function objects whose operator() overloads return different types and still use them. I forget if I covered that case but I probably did. Try it out!)


commented by (540 points)
edited by
Thank you for your sample code. In your case the return type is size_t, what should I use for d.stroe, I tried std::vector<Real> and std::vector<Cplx> but the compiler said "no viable
      overloaded '='
        ret_ = doTask(std::forward<VArgs>(vargs)...);".
Anyway, call isComplex() is enough for me currently.
commented by (70.1k points)
Yes, that is what I meant about your case falling outside the approach in my example i.e. because the storage of DenseReal and DenseCplx is of a different type, so you can't return two different types from the same function. So my example was intended just to show how one can define a function object and overload the operator() method then put this overloaded function object into applyFunc. Glad to hear that your code is working!
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.