Overview of ITensorVisualizationCore
mainITensorVisualization package. It serves as the foundational layer for visualizing ITensors and related objects within the ITensors.jl ecosystem.repository·main·Indexed 20 days ago
https://github.com/itensor/itensors.jlA Julia library for creating efficient tensor network algorithms. It provides a flexible interface for tensor operations where indices are first-class objects, supporting construction, contraction, SVD, and element-wise operations. The library includes tools for optimizing contraction sequences via TensorOperations.jl and provides the ITensorVisualizationCore for visualization. Note that MPS and MPO functionality is located in the separate ITensorMPS.jl library.
ITensorVisualization package. It serves as the foundational layer for visualizing ITensors and related objects within the ITensors.jl ecosystem.The Expose module is designed to unwrap complex types to facilitate generic programming for type-based functions. It is primarily used to intercept workflows and prevent unexpected behavior that can occur when functions interact with arbitrary type wrappers.
Use Expose when you are developing generic algorithms that need to access the underlying data or structure of wrapped types without being blocked by the wrapper itself.
ITensor uses package extensions to support various GPU backends. The following backends are supported:
CUDA.jl that provides accelerated binary tensor contractions. If loaded, ITensors with CuArray data use cuTENSOR; otherwise, they fall back to cuBLAS via matrix multiplication.Important Considerations:
svd, eigen, and qr may fall back to the CPU if the specific GPU backend lacks native support. CUDA generally has good support, while Metal and AMD have more limited support.Float32) is generally fastest on GPUs. Metal does not support Float64.To merge multiple indices into a single index (where the new dimension is the product of the original dimensions), use the combiner function. This is done by contracting the original ITensor with a 'combiner' ITensor.
C = combiner(i, k; tags="...").CT = C * T.UT = dag(C) * CT.You can retrieve the new combined index using combinedind(C).
# Setup indices
i = Index(4,"i"); j = Index(3,"j"); k = Index(2,"k")
T = random_itensor(i,j,k)
# Create and apply combiner
C = combiner(i, k; tags="c")
CT = C * T
# Access the new index
ci = combinedind(C)
@show inds(CT)
# Uncombine
UT = dag(C) * CT
@show inds(UT)An Index object is more than just a dimension; it carries metadata used for matching and identification during tensor operations.
Index has a unique, immutable id. Two Index objects are considered equal (==) if they share the same ID (e.g., a copy of an index).Index can have up to four tag strings (e.g., Index(2, "Site")). You can check for the presence of a tag using hastags(index, "tag_name"). Indices with different tags are not equal, even if they have the same dimension.prime(i) creates a new index with a different primelevel. Even if all other properties (dimension, tags, ID) are identical, indices with different prime levels are not equal.Note: For two indices to be considered equal in tensor operations, they must match in ID, tags, and prime level.
using ITensors
let
i = Index(3)
@show dim(i) # dimension
@show id(i) # unique identifier
# Tags
j = Index(5,"j")
s = Index(2,"n=1,Site")
@show hastags(s,"Site") # true
# Prime levels
i1 = prime(i)
@show i1 == i # false (prime levels differ)
endIn v0.2, plain ITensor constructors (e.g., ITensor(i, j, k)) return an ITensor with EmptyStorage instead of Dense or BlockSparse storage filled with zeros.
Behavioral Notes
EmptyStorage ITensors results in another EmptyStorage ITensor.A[i' => 1, i => 1] = 0.0.ComplexF64 value will convert the storage to ComplexF64).i = Index(2)
A = ITensor(i', dag(i)) # Returns EmptyStorage
# Allocate storage by setting a value
A[i' => 1, i => 1] = 1.0 + 0.0im
# A is now Dense{ComplexF64, ...}To contribute to ITensor.jl, follow these steps:
support@itensor.org to discuss your design before implementation.JuliaFormatter.jl or use pre-commit hooks.# To format code using JuliaFormatter
using JuliaFormatter
format(".")
# To run all unit tests
# Navigate to the test/ folder and run:
julia runtests.jl
# To run an individual test script from a Julia REPL:
include("itensor.jl")The ITensor type now directly wraps a tensor and no longer has separate .inds and .store fields.
Task: Update Field Access
Do not access A.inds or A.store directly. Instead, use the following functions:
inds(A) to get the indices (now returns a Tuple of Index instead of an IndexSet).storage(A) to access the underlying storage.Example of the change:
# Instead of:
A.inds
# Use:
inds(A)i = Index(2)
j = Index(3)
A = random_itensor(i, j)
# Returns a Tuple of Indices
inds(A) # ((dim=2|id=770), (dim=3|id=272))To use the ITensors.compile() function, you must install PackageCompiler.jl and include it in your code alongside ITensors. This is necessary because compile() relies on running MPS/MPO functionality as example code for Julia to compile.
using Pkg; Pkg.add("PackageCompiler")
using PackageCompiler
using ITensorsYou can persist ITensors to disk using the HDF5 format. This requires the HDF5.jl package (install via using Pkg; Pkg.add("HDF5")).
Writing to HDF5
Use h5open in write mode ("w") and call write(f, "key", ITensor).
Reading from HDF5
Use h5open in read mode ("r") and call read(f, "key", ITensor). Note that you must explicitly pass the ITensor type to the read function so Julia knows how to interpret the data.
using ITensors, HDF5
# Writing
i = Index(2)
T = random_itensor(i)
f = h5open("myfile.h5", "w") do f
write(f, "T", T)
end
# Reading
T_loaded = h5open("myfile.h5", "r") do f
read(f, "T", ITensor)
endYou can persist ITensors and other ITensors types to HDF5 files using the HDF5.jl library. Use write(f, "name", object) to save and read(f, "name", Type) to load. You can also apply compression during the write process using the compress keyword argument.
Note that the HDF5 format used by ITensors.jl is designed for interoperability with the C++ version of ITensor.
using ITensors, HDF5
i = Index(2)
T = random_itensor(i)
# Writing to HDF5 with optional compression
f = h5open("myfile.h5","w") do f
write(f,"T",T; compress=3)
end
# Reading from HDF5
T2 = h5open("myfile.h5","r") do f
read(f,"T",ITensor)
end
T == T2