-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtmatrix.py
235 lines (181 loc) · 6.36 KB
/
tmatrix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
from __future__ import division, print_function
import numpy as np
import scattering
# $$$$$$$$\ $$\ $$\
# \__$$ __| $$ | \__|
# $$ | $$$$$$\$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$\
# $$ |$$$$$$\ $$ _$$ _$$\ \____$$\\_$$ _| $$ __$$\ $$ |\$$\ $$ |
# $$ |\______|$$ / $$ / $$ | $$$$$$$ | $$ | $$ | \__|$$ | \$$$$ /
# $$ | $$ | $$ | $$ |$$ __$$ | $$ |$$\ $$ | $$ | $$ $$<
# $$ | $$ | $$ | $$ |\$$$$$$$ | \$$$$ |$$ | $$ |$$ /\$$\
# \__| \__| \__| \__| \_______| \____/ \__| \__|\__/ \__|
def single_particle(sp, chli, chlo, Es=None):
"""alias for one_particle"""
return one_particle(sp, chli, chlo, Es)
def single_photon(sp, chli, chlo, Es=None):
"""alias for one_particle"""
return one_particle(sp, chli, chlo, Es)
def one_photon(sp, chli, chlo, Es=None):
"""alias for one_particle"""
return one_particle(sp, chli, chlo, Es)
def one_particle(sp, chli, chlo, Es=None):
if (sp.local):
return one_particle_local(sp, chli, chlo, Es)
else:
return one_particle_quasilocal(sp, chli, chlo, Es)
def one_particle_local(sp, chli, chlo, Es=None):
"""
Calculate the one-particle irreducible T-matrix T(1).
Parameters
----------
s : Setup
Setup object describing the setup
chi : int
Input schannel
cho : int
Output channel
Es : ndarray
List of particle energies
"""
E1, _, _ = sp.eigenbasis(1)
# numerators
num1 = sp.transition(0, chli, 1)
num2 = sp.transition(1, chlo, 0)
# guess a suitable range of energies to probe
if Es is None:
Es = np.linspace(-np.max(np.abs(E1)) - 1, np.max(np.abs(E1)) + 1, 1000)
# initialize the matrix
T1 = np.zeros((Es.shape), dtype=np.complex128)
# removing copling contants from setup
# num = sp.gs[chli] * sp.gs[chlo] * num2.T * num1
num = num2.T * num1
for k in range(len(E1)):
T1[:] += num[k] / (Es - E1[k])
return Es, T1
def one_particle_quasilocal(sp, chli, chlo, Es=None):
"""
Calculate the one-particle irreducible T-matrix T(1).
Parameters
----------
s : Setup
Setup object describing the setup
chi : int
Input schannel
cho : int
Output channel
Es : ndarray
List of particle energies
"""
T1 = np.zeros((Es.shape), dtype=np.complex128)
# guess a suitable range of energies to probe
if Es is None:
maxt = np.max(np.abs(sp.model.links)) + np.max(np.abs(sp.model.omegas)) + 1
Es = np.linspace(- maxt, maxt, 1000)
for i, E in enumerate(Es):
# single particle eigenenergies
E1, _, _ = sp.eigenbasis(1, E)
# numerators
num1 = sp.transition(0, chli, 1, E)
num2 = sp.transition(1, chlo, 0, E)
# initialize the matrix
# num = sp.gs[chli] * sp.gs[chlo] * num2.T * num1
num = num2.T * num1
for k in range(len(E1)):
T1[i] += num[k] / (E - E1[k])
return Es, T1
# only local implementation
def two_particle_local(se, chlsi, chlso, E, dE, qs=None, verbal=False):
"""
Calculate the two-particle irreducible T-matrix T(2).
Parameters
----------
se : Setup object
Describes the Scattering setup
chlsi : list
Input state channels (in) [k0, k1]
chlso : list
Output state channels (out) [k'0, k'1]
E : float
Total two-particle energy
dE : float
Energy difference between the two input particles
qs : List of scattering energies.
"""
# Energies of the incoming bosons
# Comparing to Mikhails notes:
# nu_1 = E - q
# nu_2 = q
# nu_3 = .5(E - dE)
# nu_4 = .5(E + dE)
# energy of two incoming photons
nu0 = 0.5 * (E - dE)
nu1 = 0.5 * (E + dE)
# creation/annihilation operator in n = 0-1 eigenbasis representation
A10 = [se.transition(0, chl, 1) for chl in chlsi]
A01 = [se.transition(1, chl, 0) for chl in chlso]
# single particle sector eigenbasis
E1, _, _ = se.eigenbasis(1)
# creation/annihilation operator in n = 1-2 eigenbasis representation
A21 = [se.transition(1, chl, 2) for chl in chlsi]
A12 = [se.transition(2, chl, 1) for chl in chlso]
# two-particle sector eigenbasis
E2, _, _ = se.eigenbasis(2)
if verbal:
print('tmatrix')
print(A10[0])
print(A21[0])
print(E2)
# the interactive part
op0123 = (A12[1]
.dot(np.diag(1 / (E - E2)))
.dot(A21[0])
.dot(A10[1] / (nu1 - E1[:, None])))
op0132 = (A12[1]
.dot(np.diag(1 / (E - E2)))
.dot(A21[1])
.dot(A10[0] / (nu0 - E1[:, None])))
# add those two many-body routes
op01aa = op0123 + op0132
if verbal:
print('A')
print(op0123)
op1023 = (A12[0]
.dot(np.diag(1 / (E - E2)))
.dot(A21[0])
.dot(A10[1] / (nu1 - E1[:, None])))
op1032 = (A12[0]
.dot(np.diag(1 / (E - E2)))
.dot(A21[1])
.dot(A10[0] / (nu0 - E1[:, None])))
# add those two many-body routes
op10aa = op1023 + op1032
# reshape E1 vector
E1p = E1[:, None]
# single particle contributions
op00 = A01[0] * A10[0].T
op01 = A01[0].T * A10[1]
op10 = A01[1] * A10[0].T
op11 = A01[1].T * A10[1]
opE = (E - E1p - E1p.T) / ((nu0 - E1p) * (nu1 - E1p.T))
# Output energies for one particle
if qs is None:
qs = scattering.energies(E, dE)
# init matrices
T2s = np.zeros((len(qs), 1), dtype=np.complex128)
N2s = np.zeros((len(qs), 1), dtype=np.complex128)
# calculate for each possible outgoing energy combination
for iq, q in enumerate(qs):
# energy of remaining outgoing particle
Eq = E - q
T2s[iq] = ((A01[0] / (q - E1[None, :])).dot(op01aa))[0]
T2s[iq] += ((A01[1] / (Eq - E1[None, :])).dot(op10aa))[0]
# The non-interactive part
opni = opE / ((q - E1p) * (Eq - E1p.T))
opnis = opE / ((Eq - E1p) * (q - E1p.T))
N2s[iq] = -op00.dot(opni).dot(op11)[0][0]
N2s[iq] -= op10.dot(opnis).dot(op01)[0][0]
prefactor = 0.25
# finalize
T2s *= prefactor
N2s *= prefactor
return qs, T2s + N2s, N2s