1+ #=
2+ This file defines the energy restricted space structure.
3+ =#
4+
5+ export EnrSpace, enr_state_dictionaries
6+ export enr_identity, enr_fock, enr_destroy, enr_thermal_dm
7+
18struct EnrSpace{N} <: AbstractSpace
29 size:: Int
3- dims:: SVector {N,Int}
10+ dims:: NTuple {N,Int}
411 n_excitations:: Int
5- state2idx:: Dict{}
6- idx2state:: Dict{}
12+ state2idx:: Dict{SVector{N,Int},Int }
13+ idx2state:: Dict{Int,SVector{N,Int} }
714
8- function EnrSpace (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
15+ function EnrSpace (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
916 _non_static_array_warning (" dims" , dims)
1017 dim_len = length (dims)
1118 dims_T = NTuple {dim_len} (dims)
1219
1320 size, state2idx, idx2state = enr_state_dictionaries (dims, excitations)
14-
1521
1622 return new {dim_len} (size, dims_T, excitations, state2idx, idx2state)
1723 end
1824end
1925
20- function enr_state_dictionaries (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
26+ function Base. show (io:: IO , s:: EnrSpace )
27+ print (io, " EnrSpace($(s. dims) , $(s. n_excitations) )" )
28+ return nothing
29+ end
30+
31+ Base.:(== )(s_enr1:: EnrSpace , s_enr2:: EnrSpace ) = (all ([s_enr1. size, s_enr1. dims] .== [s_enr2. size, s_enr2. dims]))
32+
33+ dimensions_to_dims (s_enr:: EnrSpace ) = s_enr. dims
34+
35+ function enr_state_dictionaries (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
2136 len = length (dims)
22- nvec = MVector {len} ( zeros (Int, len) )
23- result = [ copy ( nvec)]
37+ nvec = zeros (Int, len)
38+ result = SVector{len,Int}[ nvec] # in the following, all nvec will first be converted (copied) to SVector and then push to result
2439 nexc = 0
2540
2641 while true
2742 idx = len
2843 nvec[end ] += 1
2944 nexc += 1
3045 if nvec[idx] < dims[idx]
31- push! (result, copy ( nvec) )
46+ push! (result, nvec)
3247 end
3348 while (nexc == excitations) || (nvec[idx] == dims[idx])
3449 # nvec[idx] = 0
3550 idx -= 1
3651 if idx < 1
3752 enr_size = length (result)
38- return (
39- enr_size,
40- Dict (zip (result, 1 : enr_size)),
41- Dict (zip (1 : enr_size, result))
42- )
53+ return (enr_size, Dict (zip (result, 1 : enr_size)), Dict (zip (1 : enr_size, result)))
4354 end
4455
4556 nexc -= nvec[idx+ 1 ] - 1
4657 nvec[idx+ 1 ] = 0
4758 nvec[idx] += 1
4859 if nvec[idx] < dims[idx]
49- push! (result, copy ( nvec) )
60+ push! (result, nvec)
5061 end
5162 end
5263 end
53-
5464end
5565
56- function enr_identity (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
66+ function enr_identity (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
5767 s_enr = EnrSpace (dims, excitations)
5868 return QuantumObject (Diagonal (ones (ComplexF64, s_enr. size)), Operator (), Dimensions (s_enr))
5969end
6070
6171function enr_fock (
62- dims:: Union{Tuple, AbstractVector} , excitations:: Int , state:: AbstractVector ;
63- sparse:: Union{Bool,Val} = Val (false )
64- )
72+ dims:: Union{Tuple,AbstractVector} ,
73+ excitations:: Int ,
74+ state:: AbstractVector ;
75+ sparse:: Union{Bool,Val} = Val (false ),
76+ )
6577 s_enr = EnrSpace (dims, excitations)
6678 if getVal (sparse)
6779 array = sparsevec ([s_enr. state2idx[[state... ]]], [1.0 + 0im ], s_enr. size)
6880 else
6981 j = s_enr. state2idx[state]
7082 array = [i == j ? 1.0 + 0im : 0.0 + 0im for i in 1 : (s_enr. size)]
71-
83+
7284 # s = zeros(ComplexF64, s_enr.size)
7385 # s[s_enr.state2idx[state]] += 1
7486 # s
@@ -77,40 +89,38 @@ function enr_fock(
7789 return QuantumObject (array, Ket (), s_enr)
7890end
7991
80- function enr_destroy (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
92+ function enr_destroy (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
8193 s_enr = EnrSpace (dims, excitations)
8294 N = s_enr. size
8395 idx2state = s_enr. idx2state
8496 state2idx = s_enr. state2idx
8597
86- a_ops = [ zeros ( ComplexF64, N, N) for _ in 1 : length (dims)]
98+ a_ops = ntuple (i -> QuantumObject ( spzeros ( ComplexF64, N, N), Operator (), s_enr), length (dims))
8799
88100 for (n1, state1) in idx2state
89101 for (idx, s) in pairs (state1)
90- s > 0 || continue
91-
92- state2 = copy (state1)
93- state2[idx] -= 1
94- n2 = state2idx[state2]
95- a_ops[idx][n2, n1] += √ s
102+ # if s > 0, the annihilation operator of mode idx has a non-zero
103+ # entry with one less excitation in mode idx in the final state
104+ if s > 0
105+ state2 = Vector (state1)
106+ state2[idx] -= 1
107+ n2 = state2idx[state2]
108+ a_ops[idx][n2, n1] = √ s
109+ end
96110 end
97111 end
98112
99- return [ QuantumObject (array, Operator (), s_enr) for array in a_ops]
113+ return a_ops
100114end
101115
102- function enr_thermal_dm (
103- dims:: Union{Tuple, AbstractVector} ,
104- excitations:: Int ,
105- n:: Union{Int, AbstractVector}
106- )
116+ function enr_thermal_dm (dims:: Union{Tuple,AbstractVector} , excitations:: Int , n:: Union{Int,AbstractVector} )
107117 if n isa Number
108118 nvec = Vector {typeof(n)} (n, length (dims))
109119 else
110120 length (n) == length (dims) || throw (ArgumentError (" The Vector `n` has different length to `dims`." ))
111121 nvec = n
112122 end
113-
123+
114124 s_enr = EnrSpace (dims, excitations)
115125 N = s_enr. size
116126 idx2state = s_enr. idx2state
0 commit comments