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
+
1
8
struct EnrSpace{N} <: AbstractSpace
2
9
size:: Int
3
- dims:: SVector {N,Int}
10
+ dims:: NTuple {N,Int}
4
11
n_excitations:: Int
5
- state2idx:: Dict{}
6
- idx2state:: Dict{}
12
+ state2idx:: Dict{SVector{N,Int},Int }
13
+ idx2state:: Dict{Int,SVector{N,Int} }
7
14
8
- function EnrSpace (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
15
+ function EnrSpace (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
9
16
_non_static_array_warning (" dims" , dims)
10
17
dim_len = length (dims)
11
18
dims_T = NTuple {dim_len} (dims)
12
19
13
20
size, state2idx, idx2state = enr_state_dictionaries (dims, excitations)
14
-
15
21
16
22
return new {dim_len} (size, dims_T, excitations, state2idx, idx2state)
17
23
end
18
24
end
19
25
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 )
21
36
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
24
39
nexc = 0
25
40
26
41
while true
27
42
idx = len
28
43
nvec[end ] += 1
29
44
nexc += 1
30
45
if nvec[idx] < dims[idx]
31
- push! (result, copy ( nvec) )
46
+ push! (result, nvec)
32
47
end
33
48
while (nexc == excitations) || (nvec[idx] == dims[idx])
34
49
# nvec[idx] = 0
35
50
idx -= 1
36
51
if idx < 1
37
52
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)))
43
54
end
44
55
45
56
nexc -= nvec[idx+ 1 ] - 1
46
57
nvec[idx+ 1 ] = 0
47
58
nvec[idx] += 1
48
59
if nvec[idx] < dims[idx]
49
- push! (result, copy ( nvec) )
60
+ push! (result, nvec)
50
61
end
51
62
end
52
63
end
53
-
54
64
end
55
65
56
- function enr_identity (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
66
+ function enr_identity (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
57
67
s_enr = EnrSpace (dims, excitations)
58
68
return QuantumObject (Diagonal (ones (ComplexF64, s_enr. size)), Operator (), Dimensions (s_enr))
59
69
end
60
70
61
71
function 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
+ )
65
77
s_enr = EnrSpace (dims, excitations)
66
78
if getVal (sparse)
67
79
array = sparsevec ([s_enr. state2idx[[state... ]]], [1.0 + 0im ], s_enr. size)
68
80
else
69
81
j = s_enr. state2idx[state]
70
82
array = [i == j ? 1.0 + 0im : 0.0 + 0im for i in 1 : (s_enr. size)]
71
-
83
+
72
84
# s = zeros(ComplexF64, s_enr.size)
73
85
# s[s_enr.state2idx[state]] += 1
74
86
# s
@@ -77,40 +89,38 @@ function enr_fock(
77
89
return QuantumObject (array, Ket (), s_enr)
78
90
end
79
91
80
- function enr_destroy (dims:: Union{Tuple, AbstractVector} , excitations:: Int )
92
+ function enr_destroy (dims:: Union{Tuple,AbstractVector} , excitations:: Int )
81
93
s_enr = EnrSpace (dims, excitations)
82
94
N = s_enr. size
83
95
idx2state = s_enr. idx2state
84
96
state2idx = s_enr. state2idx
85
97
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))
87
99
88
100
for (n1, state1) in idx2state
89
101
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
96
110
end
97
111
end
98
112
99
- return [ QuantumObject (array, Operator (), s_enr) for array in a_ops]
113
+ return a_ops
100
114
end
101
115
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} )
107
117
if n isa Number
108
118
nvec = Vector {typeof(n)} (n, length (dims))
109
119
else
110
120
length (n) == length (dims) || throw (ArgumentError (" The Vector `n` has different length to `dims`." ))
111
121
nvec = n
112
122
end
113
-
123
+
114
124
s_enr = EnrSpace (dims, excitations)
115
125
N = s_enr. size
116
126
idx2state = s_enr. idx2state
0 commit comments