|
1 |
| -export Lattice, SingleSiteOperator, DissipativeIsing |
| 1 | +export Lattice, MultiSiteOperator, DissipativeIsing |
2 | 2 |
|
3 | 3 | @doc raw"""
|
4 | 4 | Lattice
|
|
15 | 15 |
|
16 | 16 | #Definition of many-body operators
|
17 | 17 | @doc raw"""
|
18 |
| - SingleSiteOperator(O::QuantumObject, i::Integer, N::Integer) |
| 18 | + MultiSiteOperator(dims::Union{AbstractVector, Tuple}, pairs::Pair{<:Integer,<:QuantumObject}...) |
19 | 19 |
|
20 |
| -A Julia constructor for a single-site operator. `s` is the operator acting on the site. `i` is the site index, and `N` is the total number of sites. The function returns a `QuantumObject` given by ``\\mathbb{1}^{\\otimes (i - 1)} \\otimes \hat{O} \\otimes \\mathbb{1}^{\\otimes (N - i)}``. |
| 20 | +A Julia function for generating a multi-site operator ``\\hat{O} = \\hat{O}_i \\hat{O}_j \\cdots \\hat{O}_k``. The function takes a vector of dimensions `dims` and a list of pairs `pairs` where the first element of the pair is the site index and the second element is the operator acting on that site. |
| 21 | +
|
| 22 | +# Arguments |
| 23 | +- `dims::Union{AbstractVector, Tuple}`: A vector of dimensions of the lattice. |
| 24 | +- `pairs::Pair{<:Integer,<:QuantumObject}...`: A list of pairs where the first element of the pair is the site index and the second element is the operator acting on that site. |
| 25 | + |
| 26 | +# Returns |
| 27 | +`QuantumObject`: A `QuantumObject` representing the multi-site operator. |
| 28 | +
|
| 29 | +# Example |
| 30 | +```jldoctest |
| 31 | +julia> op = MultiSiteOperator(Val(8), 5=>sigmax(), 7=>sigmaz()); |
| 32 | +
|
| 33 | +julia> op.dims |
| 34 | +8-element SVector{8, Int64} with indices SOneTo(8): |
| 35 | + 2 |
| 36 | + 2 |
| 37 | + 2 |
| 38 | + 2 |
| 39 | + 2 |
| 40 | + 2 |
| 41 | + 2 |
| 42 | + 2 |
| 43 | +``` |
21 | 44 | """
|
22 |
| -function SingleSiteOperator(O::QuantumObject{DT,OperatorQuantumObject}, i::Integer, N::Integer) where {DT} |
23 |
| - T = O.dims[1] |
24 |
| - return QuantumObject(kron(eye(T^(i - 1)), O, eye(T^(N - i))); dims = ntuple(j -> 2, Val(N))) |
| 45 | +function MultiSiteOperator(dims::Union{AbstractVector,Tuple}, pairs::Pair{<:Integer,<:QuantumObject}...) |
| 46 | + sites_unsorted = collect(first.(pairs)) |
| 47 | + idxs = sortperm(sites_unsorted) |
| 48 | + _sites = sites_unsorted[idxs] |
| 49 | + _ops = collect(last.(pairs))[idxs] |
| 50 | + _dims = collect(dims) # Use this instead of a Tuple, to avoid type instability when indexing on a slice |
| 51 | + |
| 52 | + sites, ops = _get_unique_sites_ops(_sites, _ops) |
| 53 | + |
| 54 | + collect(dims)[sites] == [op.dims[1] for op in ops] || throw(ArgumentError("The dimensions of the operators do not match the dimensions of the lattice.")) |
| 55 | + |
| 56 | + data = kron(I(prod(_dims[1:sites[1]-1])), ops[1].data) |
| 57 | + for i in 2:length(sites) |
| 58 | + data = kron(data, I(prod(_dims[sites[i-1]+1:sites[i]-1])), ops[i].data) |
| 59 | + end |
| 60 | + data = kron(data, I(prod(_dims[sites[end]+1:end]))) |
| 61 | + |
| 62 | + return QuantumObject(data; type = Operator, dims = dims) |
| 63 | +end |
| 64 | +function MultiSiteOperator(N::Union{Integer,Val}, pairs::Pair{<:Integer,<:QuantumObject}...) |
| 65 | + dims = ntuple(j -> 2, makeVal(N)) |
| 66 | + |
| 67 | + return MultiSiteOperator(dims, pairs...) |
| 68 | +end |
| 69 | +function MultiSiteOperator(latt::Lattice, pairs::Pair{<:Integer,<:QuantumObject}...) |
| 70 | + return MultiSiteOperator(makeVal(latt.N), pairs...) |
25 | 71 | end
|
26 |
| -SingleSiteOperator(O::QuantumObject{DT,OperatorQuantumObject}, i::Integer, latt::Lattice) where {DT} = |
27 |
| - SingleSiteOperator(O, i, latt.N) |
28 |
| -SingleSiteOperator(O::QuantumObject{DT,OperatorQuantumObject}, row::Integer, col::Integer, latt::Lattice) where {DT} = |
29 |
| - SingleSiteOperator(O, latt.idx[row, col], latt.N) |
30 |
| -SingleSiteOperator(O::QuantumObject{DT,OperatorQuantumObject}, x::CartesianIndex, latt::Lattice) where {DT} = |
31 |
| - SingleSiteOperator(O, latt.idx[x], latt.N) |
32 | 72 |
|
33 | 73 | #Definition of nearest-neighbour sites on lattice
|
34 | 74 | periodic_boundary_conditions(i::Integer, N::Integer) = 1 + (i - 1 + N) % N
|
@@ -87,27 +127,34 @@ function DissipativeIsing(
|
87 | 127 | boundary_condition::Union{Symbol,Val} = Val(:periodic_bc),
|
88 | 128 | order::Integer = 1,
|
89 | 129 | )
|
90 |
| - S = [SingleSiteOperator(sigmam(), i, latt) for i in 1:latt.N] |
| 130 | + S = [MultiSiteOperator(latt, i => sigmam()) for i in 1:latt.N] |
91 | 131 | c_ops = sqrt(γ) .* S
|
92 | 132 |
|
93 | 133 | op_sum(S, i::CartesianIndex) =
|
94 | 134 | S[latt.lin_idx[i]] * sum(S[latt.lin_idx[nearest_neighbor(i, latt, makeVal(boundary_condition); order = order)]])
|
95 | 135 |
|
96 | 136 | H = 0
|
97 | 137 | if (Jx != 0 || hx != 0)
|
98 |
| - S = [SingleSiteOperator(sigmax(), i, latt) for i in 1:latt.N] |
| 138 | + S = [MultiSiteOperator(latt, i => sigmax()) for i in 1:latt.N] |
99 | 139 | H += Jx / 2 * mapreduce(i -> op_sum(S, i), +, latt.car_idx) #/2 because we are double counting
|
100 | 140 | H += hx * sum(S)
|
101 | 141 | end
|
102 | 142 | if (Jy != 0 || hy != 0)
|
103 |
| - S = [SingleSiteOperator(sigmay(), i, latt) for i in 1:latt.N] |
| 143 | + S = [MultiSiteOperator(latt, i => sigmay()) for i in 1:latt.N] |
104 | 144 | H += Jy / 2 * mapreduce(i -> op_sum(S, i), +, latt.car_idx)
|
105 | 145 | H += hy * sum(S)
|
106 | 146 | end
|
107 | 147 | if (Jz != 0 || hz != 0)
|
108 |
| - S = [SingleSiteOperator(sigmaz(), i, latt) for i in 1:latt.N] |
| 148 | + S = [MultiSiteOperator(latt, i => sigmaz()) for i in 1:latt.N] |
109 | 149 | H += Jz / 2 * mapreduce(i -> op_sum(S, i), +, latt.car_idx)
|
110 | 150 | H += hz * sum(S)
|
111 | 151 | end
|
112 | 152 | return H, c_ops
|
113 | 153 | end
|
| 154 | + |
| 155 | +function _get_unique_sites_ops(sites, ops) |
| 156 | + unique_sites = unique(sites) |
| 157 | + unique_ops = map(i -> prod(ops[findall(==(i), sites)]), unique_sites) |
| 158 | + |
| 159 | + return unique_sites, unique_ops |
| 160 | +end |
0 commit comments