Skip to content

Commit

Permalink
Merge pull request #63 from Gertian/master
Browse files Browse the repository at this point in the history
Define arithmetic operators for LocalOperators
  • Loading branch information
pbrehmer authored Aug 21, 2024
2 parents dd7e707 + 51e4b96 commit 76e25d9
Showing 1 changed file with 74 additions and 10 deletions.
84 changes: 74 additions & 10 deletions src/operators/localoperator.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,62 @@

# Hamiltonian consisting of local terms
# -------------------------------------
"""
struct LocalOperator{T<:Tuple,S}
A sum of local operators acting on a lattice. The lattice is stored as a matrix of vector spaces,
and the terms are stored as a tuple of pairs of indices and operators.
# Fields
- `lattice::Matrix{S}`: The lattice on which the operator acts.
- `terms::T`: The terms of the operator, stored as a tuple of pairs of indices and operators.
# Constructors
LocalOperator(lattice::Matrix{S}, terms::Pair...)
LocalOperator{T,S}(lattice::Matrix{S}, terms::T) where {T,S} # expert mode
# Examples
```julia
lattice = fill(ℂ^2, 1, 1) # single-site unitcell
O1 = LocalOperator(lattice, ((1, 1),) => σx, ((1, 1), (1, 2)) => σx ⊗ σx, ((1, 1), (2, 1)) => σx ⊗ σx)
```
"""
struct LocalOperator{T<:Tuple,S}
lattice::Matrix{S}
terms::T
end
function LocalOperator(lattice::Matrix{S}, terms::Pair...) where {S}
lattice′ = PeriodicArray(lattice)
for (inds, operator) in terms
@assert operator isa AbstractTensorMap
@assert numout(operator) == numin(operator) == length(inds)
for i in 1:length(inds)
@assert space(operator, i) == lattice′[inds[i]]
function LocalOperator{T,S}(lattice::Matrix{S}, terms::T) where {T,S}
plattice = PeriodicArray(lattice)
# Check if the indices of the operator are valid with themselves and the lattice
for (inds, operator) in terms
@assert operator isa AbstractTensorMap
@assert numout(operator) == numin(operator) == length(inds)
@assert spacetype(operator) == S

for i in 1:length(inds)
@assert space(operator, i) == plattice[inds[i]]
end
end
return new{T,S}(lattice, terms)
end
return LocalOperator{typeof(terms),S}(lattice, terms)
end
function LocalOperator(
lattice::Matrix,
terms::Pair...;

This comment has been minimized.

Copy link
@Gertian

Gertian Aug 22, 2024

Contributor

@lkdvos This seems to have broken (or at least changed) some things.
Before I could do :

H_AFM = LocalOperator([ph ph;ph ph], (  (CartesianIndex(1,1), )=> mz*N ,  
                                           (CartesianIndex(1,2), )=>-mz*N ,  
                                           (CartesianIndex(2,1), )=>-mz*N ,  
                                           (CartesianIndex(2,2), )=> mz*N  )  )          

but now I need

H_AFM = LocalOperator([ph ph;ph ph], (  (CartesianIndex(1,1), )=> mz*N ,
                                           (CartesianIndex(1,2), )=>-mz*N ,  
                                           (CartesianIndex(2,1), )=>-mz*N ,  
                                           (CartesianIndex(2,2), )=> mz*N  )...  )         

This comment has been minimized.

Copy link
@lkdvos

lkdvos Aug 22, 2024

Member

The previous syntax was somewhat unintended. Note that you are manually packing things in a tuple, and then unpacking them, so you should just get rid of the brackets around all operators (I added some linebreaks to make things more obvious):

H_AFM = LocalOperator([ph ph;ph ph],
    (CartesianIndex(1,1), )=> mz*N ,  
    (CartesianIndex(1,2), )=>-mz*N ,  
    (CartesianIndex(2,1), )=>-mz*N ,  
    (CartesianIndex(2,2), )=> mz*N
)          

This being said, I can add that back in if you really want?

This comment has been minimized.

Copy link
@Gertian

Gertian Aug 22, 2024

Contributor

For me it's fine like this. I just wanted to make sure that you were aware of this :)

atol=maximum(x -> eps(real(scalartype(x[2])))^(3 / 4), terms),
)
allinds = getindex.(terms, 1)
alloperators = getindex.(terms, 2)

relevant_terms = []
for inds in unique(allinds)
operator = sum(alloperators[findall(==(inds), allinds)])
norm(operator) > atol && push!(relevant_terms, inds => operator)
end

terms_tuple = Tuple(relevant_terms)
return LocalOperator{typeof(terms_tuple),eltype(lattice)}(lattice, terms_tuple)
end

"""
Expand All @@ -27,6 +69,9 @@ while the second version throws an error if the lattices do not match.
function checklattice(args...)
return checklattice(Bool, args...) || throw(ArgumentError("Lattice mismatch."))
end
function checklattice(::Type{Bool}, H1::LocalOperator, H2::LocalOperator)
return H1.lattice == H2.lattice
end
function checklattice(::Type{Bool}, peps::InfinitePEPS, O::LocalOperator)
return size(peps) == size(O.lattice)
end
Expand Down Expand Up @@ -57,3 +102,22 @@ function Base.repeat(O::LocalOperator, m::Int, n::Int)
end
return LocalOperator(lattice, terms...)
end

# Linear Algebra
# --------------
function Base.:*::Number, O::LocalOperator)
scaled_terms = map(((inds, operator),) -> (inds => α * operator), O.terms)
return LocalOperator{typeof(scaled_terms),eltype(O.lattice)}(O.lattice, scaled_terms)
end
Base.:*(O::LocalOperator, α::Number) = α * O

Base.:/(O::LocalOperator, α::Number) = O * inv(α)
Base.:\::Number, O::LocalOperator) = inv(α) * O

function Base.:+(O1::LocalOperator, O2::LocalOperator)
checklattice(O1, O2)
return LocalOperator(O1.lattice, O1.terms..., O2.terms...)
end

Base.:-(O::LocalOperator) = -1 * O
Base.:-(O1::LocalOperator, O2::LocalOperator) = O1 + (-O2)

0 comments on commit 76e25d9

Please sign in to comment.