How to set customed eltype for op() methods?

Hello!

I’m trying to reduce the memory cost of my program and want to use Float32 rather than Float64 as the major number type throughout my code. How can I assign the ITensor object generated by methods like ITensors.op("Sz", s) to have elements of type Float32.

For example:

using ITensors, ITensorMPS

let
    ss =  siteinds("S=1/2", 10)
    operator = op("Sz", ss[1])
end

The above code will definitely give a Float64 type ITensor, but how can I modify the code to obtain a Float32 type one?

Thank you very much for noticing my stupid question!

It’s definitely not a stupid question, unfortunately it is a little bit more complicated than it should be to do that right now.

Ideally you could use Float32.(operator) since that is the standard way of doing that kind of conversion for Julia arrays:

julia> a = randn(Float64, 2, 2)
2×2 Matrix{Float64}:
 -0.360093  -0.216048
 -0.981239  -1.01513

julia> Float32.(a)
2×2 Matrix{Float32}:
 -0.360093  -0.216048
 -0.981239  -1.01513

but broadcasting of ITensors in ITensors.jl is kind of a mess right now and that particular broadcasting operation is broken for ITensors (we’re fixing that as part of our ongoing rewrite of ITensors.jl but that doesn’t help you right now).

I think the best alternative right now would be to use Adapt.jl:

julia> i = Index(2)
(dim=2|id=619)

julia> a = random_itensor(Float64, i)
ITensor ord=1 (dim=2|id=619)
NDTensors.Dense{Float64, Vector{Float64}}

julia> using Adapt: adapt

julia> adapt(Array{Float32}, a)
ITensor ord=1 (dim=2|id=619)
NDTensors.Dense{Float32, Vector{Float32}}
1 Like

Thanks for your attention!

I tried the methods you suggests and found that Float.(operator) doesn’t work in REPL and Adapt.jl works well. I find a more straightforward way to handle my problem, something like:

using ITensors, ITensorMPS

let
    ss = siteinds("S=1/2", 10)
    M = [0.5f0 0.0f0; 0.0f0 -0.5f0]
    operator = op(M, ss[1])
end
NDTensors.Dense{Float32, Vector{Float32}}

It can generate S_z operator of Float32 type, but requires manually inputting the matrix form of the operators used in the program.

That’s definitely a reasonable way to go if you are ok defining the operators yourself.

It’s a slightly hidden feature, but internally we generally define operators in terms of Julia Matrices, and you can directly construct them like this:

julia> using ITensorMPS: SiteType, op

julia> op("Sz", SiteType("S=1/2"))
2×2 Matrix{Float64}:
 0.5   0.0
 0.0  -0.5

so you could use Float32.(op("Sz", SiteType("S=1/2"))) and then wrap it into an ITensor as you did above.

Ideally we would just allow specifying the element type as the first argument of op . As part of our ongoing rewrite we have something like that planned, though again that doesn’t really help you right now.