8181Creation operator for the i-th mode of the many-body basis `b`.
8282"""
8383function create (:: Type{T} , b:: ManyBodyBasis , index) where T
84- result = SparseOperator (T, b)
84+ Is = Int[]
85+ Js = Int[]
86+ Vs = T[]
8587 # <{m}_i| at |{m}_j>
8688 for i= 1 : length (b)
8789 occ_i = b. occupations[i]
@@ -90,11 +92,13 @@ function create(::Type{T}, b::ManyBodyBasis, index) where T
9092 end
9193 for j= 1 : length (b)
9294 if isnonzero (occ_i, b. occupations[j], index)
93- result. data[i, j] = sqrt (occ_i[index])
95+ push! (Is, i)
96+ push! (Js, j)
97+ push! (Vs, sqrt (occ_i[index]))
9498 end
9599 end
96100 end
97- result
101+ return SparseOperator (b, sparse (Is, Js, Vs, length (b), length (b)))
98102end
99103create (b:: ManyBodyBasis , index) = create (ComplexF64, b, index)
100104
@@ -104,7 +108,9 @@ create(b::ManyBodyBasis, index) = create(ComplexF64, b, index)
104108Annihilation operator for the i-th mode of the many-body basis `b`.
105109"""
106110function destroy (:: Type{T} , b:: ManyBodyBasis , index) where T
107- result = SparseOperator (T, b)
111+ Is = Int[]
112+ Js = Int[]
113+ Vs = T[]
108114 # <{m}_j| a |{m}_i>
109115 for i= 1 : length (b)
110116 occ_i = b. occupations[i]
@@ -113,11 +119,13 @@ function destroy(::Type{T}, b::ManyBodyBasis, index) where T
113119 end
114120 for j= 1 : length (b)
115121 if isnonzero (occ_i, b. occupations[j], index)
116- result. data[j, i] = sqrt (occ_i[index])
122+ push! (Is, j)
123+ push! (Js, i)
124+ push! (Vs, sqrt (occ_i[index]))
117125 end
118126 end
119127 end
120- result
128+ return SparseOperator (b, sparse (Is, Js, Vs, length (b), length (b)))
121129end
122130destroy (b:: ManyBodyBasis , index) = destroy (ComplexF64, b, index)
123131
@@ -127,11 +135,7 @@ destroy(b::ManyBodyBasis, index) = destroy(ComplexF64, b, index)
127135Particle number operator for the i-th mode of the many-body basis `b`.
128136"""
129137function number (:: Type{T} , b:: ManyBodyBasis , index) where T
130- result = SparseOperator (T, b)
131- for i= 1 : length (b)
132- result. data[i, i] = b. occupations[i][index]
133- end
134- result
138+ diagonaloperator (b, T[b. occupations[i][index] for i in 1 : length (b)])
135139end
136140number (b:: ManyBodyBasis , index) = number (ComplexF64, b, index)
137141
@@ -141,11 +145,7 @@ number(b::ManyBodyBasis, index) = number(ComplexF64, b, index)
141145Total particle number operator.
142146"""
143147function number (:: Type{T} , b:: ManyBodyBasis ) where T
144- result = SparseOperator (T, b)
145- for i= 1 : length (b)
146- result. data[i, i] = sum (b. occupations[i])
147- end
148- result
148+ diagonaloperator (b, T[sum (b. occupations[i]) for i in 1 : length (b)])
149149end
150150number (b:: ManyBodyBasis ) = number (ComplexF64, b)
151151
178178Operator ``|\\ mathrm{to}⟩⟨\\ mathrm{from}|`` transferring particles between modes.
179179"""
180180function transition (:: Type{T} , b:: ManyBodyBasis , to, from) where T
181- result = SparseOperator (T, b)
181+ Is = Int[]
182+ Js = Int[]
183+ Vs = T[]
182184 # <{m}_j| at_to a_from |{m}_i>
183185 for i= 1 : length (b)
184186 occ_i = b. occupations[i]
@@ -188,11 +190,13 @@ function transition(::Type{T}, b::ManyBodyBasis, to, from) where T
188190 for j= 1 : length (b)
189191 occ_j = b. occupations[j]
190192 if isnonzero (occ_j, occ_i, to, from)
191- result. data[j, i] = sqrt (occ_i[from])* sqrt (occ_j[to])
193+ push! (Is, j)
194+ push! (Js, i)
195+ push! (Vs, sqrt (occ_i[from]) * sqrt (occ_j[to]))
192196 end
193197 end
194198 end
195- result
199+ return SparseOperator (b, sparse (Is, Js, Vs, length (b), length (b)))
196200end
197201transition (b:: ManyBodyBasis , to, from) = transition (ComplexF64, b, to, from)
198202
@@ -240,7 +244,7 @@ function manybodyoperator_1(basis::ManyBodyBasis, op::Operator)
240244 result = DenseOperator (basis)
241245 @inbounds for n= 1 : N, m= 1 : N
242246 for j= 1 : S, i= 1 : S
243- C = coefficient (basis. occupations[m], basis. occupations[n], [i], [j] )
247+ C = coefficient (basis. occupations[m], basis. occupations[n], i, j )
244248 if C != 0.
245249 result. data[m,n] += C* op. data[i,j]
246250 end
@@ -252,22 +256,25 @@ manybodyoperator_1(basis::ManyBodyBasis, op::AdjointOperator) = dagger(manybodyo
252256
253257function manybodyoperator_1 (basis:: ManyBodyBasis , op:: SparseOpPureType )
254258 N = length (basis)
255- S = length (basis. onebodybasis)
256- result = SparseOperator (basis)
257259 M = op. data
260+ Is = Int[]
261+ Js = Int[]
262+ Vs = ComplexF64[]
258263 @inbounds for colindex = 1 : M. n
259264 for i= M. colptr[colindex]: M. colptr[colindex+ 1 ]- 1
260265 row = M. rowval[i]
261266 value = M. nzval[i]
262267 for m= 1 : N, n= 1 : N
263- C = coefficient (basis. occupations[m], basis. occupations[n], [ row], [ colindex] )
268+ C = coefficient (basis. occupations[m], basis. occupations[n], row, colindex)
264269 if C != 0.
265- result. data[m, n] += C* value
270+ push! (Is, m)
271+ push! (Js, n)
272+ push! (Vs, C * value)
266273 end
267274 end
268275 end
269276 end
270- return result
277+ return SparseOperator (basis, sparse (Is, Js, Vs, N, N))
271278end
272279
273280function manybodyoperator_2 (basis:: ManyBodyBasis , op:: Operator )
@@ -280,7 +287,7 @@ function manybodyoperator_2(basis::ManyBodyBasis, op::Operator)
280287 occupations = basis. occupations
281288 @inbounds for m= 1 : N, n= 1 : N
282289 for l= 1 : S, k= 1 : S, j= 1 : S, i= 1 : S
283- C = coefficient (occupations[m], occupations[n], [ i, j], [ k, l] )
290+ C = coefficient (occupations[m], occupations[n], ( i, j), ( k, l) )
284291 result. data[m,n] += C* op_data[i, j, k, l]
285292 end
286293 end
290297function manybodyoperator_2 (basis:: ManyBodyBasis , op:: SparseOpType )
291298 N = length (basis)
292299 S = length (basis. onebodybasis)
293- result = SparseOperator (basis)
300+ Is = Int[]
301+ Js = Int[]
302+ Vs = ComplexF64[]
294303 occupations = basis. occupations
295304 rows = rowvals (op. data)
296305 values = nonzeros (op. data)
@@ -302,11 +311,13 @@ function manybodyoperator_2(basis::ManyBodyBasis, op::SparseOpType)
302311 index = Tuple (CartesianIndices ((S, S, S, S))[(column- 1 )* S^ 2 + row])
303312 C = coefficient (occupations[m], occupations[n], index[1 : 2 ], index[3 : 4 ])
304313 if C!= 0.
305- result. data[m,n] += C* value
314+ push! (Is, m)
315+ push! (Js, n)
316+ push! (Vs, C * value)
306317 end
307318 end
308319 end
309- return result
320+ return SparseOperator (basis, sparse (Is, Js, Vs, N, N))
310321end
311322
312323
@@ -354,7 +365,7 @@ function onebodyexpect_1(op::Operator, state::Ket)
354365 for m= 1 : N, n= 1 : N
355366 value = conj (state. data[m])* state. data[n]
356367 for i= 1 : S, j= 1 : S
357- C = coefficient (occupations[m], occupations[n], [i], [j] )
368+ C = coefficient (occupations[m], occupations[n], i, j )
358369 if C != 0.
359370 result += C* op. data[i,j]* value
360371 end
@@ -371,7 +382,7 @@ function onebodyexpect_1(op::Operator, state::Operator)
371382 @inbounds for s= 1 : N, t= 1 : N
372383 value = state. data[t,s]
373384 for i= 1 : S, j= 1 : S
374- C = coefficient (occupations[s], occupations[t], [i], [j] )
385+ C = coefficient (occupations[s], occupations[t], i, j )
375386 if ! iszero (C)
376387 result += C* op. data[i,j]* value
377388 end
@@ -391,7 +402,7 @@ function onebodyexpect_1(op::SparseOpPureType, state::Ket)
391402 row = M. rowval[i]
392403 value = M. nzval[i]
393404 for m= 1 : N, n= 1 : N
394- C = coefficient (occupations[m], occupations[n], [ row], [ colindex] )
405+ C = coefficient (occupations[m], occupations[n], row, colindex)
395406 if C != 0.
396407 result += C* value* conj (state. data[m])* state. data[n]
397408 end
@@ -412,7 +423,7 @@ function onebodyexpect_1(op::SparseOpPureType, state::Operator)
412423 row = M. rowval[i]
413424 value = M. nzval[i]
414425 for s= 1 : N, t= 1 : N
415- C = coefficient (occupations[s], occupations[t], [ row], [ colindex] )
426+ C = coefficient (occupations[s], occupations[t], row, colindex)
416427 if C != 0.
417428 result += C* value* state. data[t,s]
418429 end
@@ -426,29 +437,18 @@ end
426437"""
427438Calculate the matrix element <{m}|at_1...at_n a_1...a_n|{n}>.
428439"""
429- function coefficient (occ_m, occ_n, at_indices, a_indices)
430- occ_m = copy (occ_m)
431- occ_n = copy (occ_n)
432- C = 1.
433- for i= at_indices
434- if occ_m[i] == 0
435- return 0.
436- end
437- C *= sqrt (occ_m[i])
438- occ_m[i] -= 1
439- end
440- for i= a_indices
441- if occ_n[i] == 0
442- return 0.
443- end
444- C *= sqrt (occ_n[i])
445- occ_n[i] -= 1
446- end
447- if occ_m == occ_n
448- return C
449- else
450- return 0.
440+ Base. @propagate_inbounds function coefficient (occ_m, occ_n, at_indices, a_indices)
441+ any (== (0 ), (occ_m[m] for m in at_indices)) && return 0.
442+ any (== (0 ), (occ_n[n] for n in a_indices)) && return 0.
443+ C = prod (√ , (occ_m[m] for m in at_indices)) * prod (√ , (occ_n[n] for n in a_indices))
444+ for i in 1 : length (occ_m)
445+ vm = occ_m[i]
446+ vn = occ_n[i]
447+ i in at_indices && (vm -= 1 )
448+ i in a_indices && (vn -= 1 )
449+ vm != vn && return zero (C)
451450 end
451+ return C
452452end
453453
454454function _distribute_bosons (Nparticles, Nmodes, index, occupations, results)
0 commit comments