def g1(setup, chlsi, k0, q0, i): (i1, i2) = chlsi E1 = setup.eigenenergies(1) _, Sk1 = smatrix.one_particle(setup, i1, i, np.array([k0 + q0])) _, Sk2 = smatrix.one_particle(setup, i2, i, np.array([k0 - q0])) fij_sqrd = np.abs(Sk1)**2 + np.abs(Sk2)**2 fij2_sqrd = 0 # EE = E1[None, :].conj() - E1[:, None] pp, pm = [], [] nchan = len(setup.channels) for j in xrange(nchan): pp.append(phi(setup, k0, q0, i, j, i1, i2)) pm.append(phi(setup, k0, q0, j, i, i1, i2)) # fij2_sqrd += np.sum((pp[j].conj().T*pp[j] + pm[j].conj().T*pm[j])/EE) for ll in xrange(len(E1)): for lp in xrange(len(E1)): fij2_sqrd += (pp[j][lp].conj() * pp[j][ll] + pm[j][lp].conj() * pm[j][ll]) / (E1[lp].conj() - E1[ll]) # add a prefactor fij2_sqrd *= 2 * np.pi * 1j croff = 0 for j in xrange(len(setup.channels)): croff += fijm(setup, k0, q0, i, j, i1, i2).conj() * fij2(k0 + q0, k0 - q0, pp[j], pm[j], E1) \ + fijp(setup, k0, q0, i, j, i1, i2).conj() * fij2(k0 - q0, k0 + q0, pp[j], pm[j], E1) return fij_sqrd + fij2_sqrd + 2 * np.real(croff)
def coherent_state_tau0_quasilocal(setup, chlsi, chlso, E=0): """ g2 from Mikhails formula Parameters ---------- se : Setup Scattering setup object chlsi : list list of incoming channels (must be identical!) chlso : list list of outgoing channels E : float or list Incoming two photon state energ(y/ies) """ (i1, i2) = chlsi (o1, o2) = chlso assert i1 == i2, 'Photons in an incoming coherent state **must** all belong to the same channel.' # convert to numpy array k0s = np.atleast_1d(E) / 2 # k0s = E / 2 if util.isarray(E) else np.array([E / 2]) _, S00 = smatrix.one_particle(setup, i1, o1, k0s) _, S11 = smatrix.one_particle(setup, i2, o2, k0s) g2a = 1 - (S11 - (i2 == o2)) * (S00 - (i1 == o1)) / (S11 * S00) g2b = np.zeros(k0s.shape, np.complex128) for i, k0 in enumerate(k0s): setup.reset() # remove cache # eigen-energies E1 = setup.eigenenergies(1, phi=k0) E2 = setup.eigenenergies(2, phi=k0) # creation operator in n = 0-1-2 eigenbasis representation A01 = setup.transition(1, o1, 0, k0) A12 = setup.transition(2, o2, 1, k0) A21 = setup.transition(1, i1, 2, k0) A10 = setup.transition(0, i2, 1, k0) # g2 g2b[i] = A01 \ .dot(A12) \ .dot(np.diag(1 / (2 * k0 - E2))) \ .dot(A21) \ .dot(A10 / (k0 - E1[:, None]))[0][0] prefactor = 4 * np.pi**2 # * np.prod([setup.gs[ch] for ch in chlsi + chlso]) return { 'g2': np.abs(g2a - prefactor / (S11 * S00) * g2b)**2, 'phi2': np.abs(g2a * S11 * S00 - prefactor * g2b)**2, 'normalization': S11 * S00, 'phi2_reducible': g2a * S11 * S00, 'phi2_irreducible': -prefactor * g2b }
def test_smatrix_oneparticle2(): m = scattering.Model([0] * 2, [[0, 1, 1]], [0] * 2) channels = [ scattering.Channel(site=0, strength=1), scattering.Channel(site=0, strength=1), ] s = scattering.Setup(m, channels) E = 0 _, S1 = smatrix.one_particle(s, 0, 0, np.array([E])) assert (np.isclose(np.abs(S1[0])**2, 1, 1e-3)) _, S1 = smatrix.one_particle(s, 0, 1, np.array([E])) assert np.isclose(np.abs(S1[0]) ** 2, 0, 1e-3), \ 'S(1) fails for two sites which are sidecoupled. S(1) = {0} != 0.'.format(np.abs(S1[0]) ** 2)
def g2(s, chlsi, chlso, E, dE): """ Calculate the intensity-intensity correlation function as a function of total energy, E, and energy discrepancy, dE. Parameters ---------- s : Setup Scattering setup object. chlsi : list Input state channel indices. chlso : list Output state channel indices. E : float Total energy of input photonic state. dE : float Energy difference between the two photons in the input state. """ qs, D2, S2, S2in = smatrix.two_particle(s, chlsi=chlsi, chlso=chlso, E=E, dE=dE) Ee = np.array([.5 * (E - dE), .5 * (E + dE)]) _, S10 = smatrix.one_particle(s, chlsi[0], chlso[0], Ee) _, S11 = smatrix.one_particle(s, chlsi[1], chlso[1], Ee) # denominator dFS2 = np.sum(np.abs(S10)**2 * np.abs(S11)**2) # Fourier transform FS2 = np.fft.fft(S2) * (qs[1] - qs[0]) # frequencies freqs = np.fft.fftfreq(len(qs), d=qs[1] - qs[0]) # add delta function contribution FS2 += np.exp(np.pi * 1j * E * freqs) * D2[0] + np.exp( np.pi * 1j * E * freqs) * D2[1] return FS2, dFS2
def g2_coherent_s(s, chlsi, chlso, E, qs=None): """ g2 for a coherent state (or partially coherent) Parameters ---------- s : Setup Scattering setup chlsi : list List of incoming channel indices chlso : list List of outgoing channel indices E : float Energy of the two-particle state """ qs, D2, S2, _ = smatrix.two_particle(s, chlsi=chlsi, chlso=chlso, E=E, dE=0, qs=qs) # Single particle scattering Ee = np.array([.5 * E]) _, S10 = smatrix.one_particle(s, chlsi[0], chlso[0], Ee) _, S11 = smatrix.one_particle(s, chlsi[1], chlso[1], Ee) dFS2 = np.abs(S10[0])**2 * np.abs(S11[0])**2 # Fourier transform FS2 = np.fft.fft(S2) * (qs[1] - qs[0]) # times times = np.fft.fftfreq(len(qs), d=qs[1] - qs[0]) # add delta function contribution FS2 += np.exp(2 * np.pi * 1j * E / 2 * times) * np.sum(D2) return np.abs(FS2[0])**2, dFS2
def nonlinear(se, chli, chlo, Es, p=0.1): """ Non-linear correction to the transmittance. Parameters ---------- se : scattering.Setup object Scattering setup object. chli : int Incoming channel index. chlo : int Outgoing channel index. Es : ndarray Single particle energies. p : float The power = alpha**2/L (number of photons per time/pulse length) """ tr = np.zeros((len(Es), ), dtype=np.complex128) t2 = np.zeros((len(Es), ), dtype=np.complex128) for chl in xrange(len(se.channels)): # single particle contribution s1ij = smatrix.one_particle(se, chli, chl, Es)[1] # The t2 contribution for i, E in enumerate(Es): t2[i] = tmatrix.two_particle(se, (chli, chli), (chlo, chl), E=2 * E, dE=0, qs=np.array([E]))[1][0, 0] # result tr += 8 * 1j * (np.pi**2) * p * np.conjugate(s1ij) * t2 s1 = smatrix.one_particle(se, chli, chlo, Es)[1] return np.abs(s1 - tr)**2, s1, tr
def linear(se, chli, chlo, Es): """ Linear component of the single particle transmittance. Parameters ---------- se : scattering.Setup object Scattering setup object. chli : int Incoming channel. chlo : int Outgoing channel. Es : ndarray Single particle energies. """ return np.abs(smatrix.one_particle(se, chli, chlo, Es)[1])**2
def g1(se, chli, chlo, Es): """ Plots g1-correlation function. Parameters ---------- se : scattering.Setup object The scattering setup chli : int Incoming channel chlo : int Outgoing channel Es : array-like List of single-photon energies """ return np.abs(smatrix.one_particle(se, chli, chlo, Es)[1])**2
def test_smatrix_oneparticle(): """ Test the S(1) matrix for one example system """ m = scattering.Model([0] * 2, [[0, 1, 1]], [0] * 2) channels = [ scattering.Channel(site=0, strength=1), scattering.Channel(site=1, strength=1), ] s = scattering.Setup(m, channels) E = 0 _, S1 = smatrix.one_particle(s, 0, 1, np.array([E])) S10num = np.abs(S1[0])**2 S10ana = (2 * np.pi / (1 + (np.pi)**2))**2 assert np.isclose(S10num, S10ana, 1e-3), \ 'S(1) fails for two-sites coupled in series. S(1) = {0} != {1}.'.format(S10num, S01ana)
def fijp(setup, k0, q0, i, j, i1, i2): _, Si = smatrix.one_particle(setup, i1, j, np.array([k0 + q0])) _, Sj = smatrix.one_particle(setup, i2, i, np.array([k0 - q0])) return Si * Sj
def fock_state_local(setup, chlsi, chlso, E, dE, tau=0): """ Compute g^2 correlation function for a general two-photon state. Parameters ---------- se : scattering.Model A given scattering model chlsi : list List of incoming two-photon state channel indices. chlso : list List of outgoing two-photon state channel indices. E : float Total two-photon energy dE : float Energy difference between the two photons. tau : float Time """ # channel indices (i1, i2) = chlsi (o1, o2) = chlso # single photon energies k0, q0 = .5 * E, .5 * dE k1, k2 = k0 + q0, k0 - q0 # times taus = np.atleast_1d(tau) _, S11 = smatrix.one_particle(setup, i1, o1, np.array([k1])) _, S22 = smatrix.one_particle(setup, i2, o2, np.array([k2])) _, S12 = smatrix.one_particle(setup, i1, o2, np.array([k1])) _, S21 = smatrix.one_particle(setup, i2, o1, np.array([k2])) g2a = S11 * S22 * np.exp(-1j * q0 * taus) + S21 * S12 * np.exp( 1j * q0 * taus) # eigen energies E1, E2 = [setup.eigenenergies(nb) for nb in (1, 2)] # creation operator in n = 0-1 eigenbasis representation A10, A01, A21, A12 = transitions(setup) prefactor = (2 * np.pi)**2 * np.prod([setup.gs[c] for c in chlsi + chlso]) At = A01[o1] * np.exp(-1j * (E1[None, :] - k0) * taus[:, None]) g2b = At.dot(A12[o2]).dot(np.diag(1 / (E - E2))).dot(A21[i2]).dot(A10[i1] / (k1 - E1[:, None])) \ + At.dot(A12[o2]).dot(np.diag(1 / (E - E2))).dot(A21[i1]).dot(A10[i2] / (k2 - E1[:, None])) \ - (At / (k2 - E1)).dot(A10[i2]).dot(A01[o2]).dot(A10[i1] / (k1 - E1[:, None])) \ - (At / (k1 - E1)).dot(A10[i1]).dot(A01[o2]).dot(A10[i2] / (k2 - E1[:, None])) g2 = np.abs(g2a - prefactor * g2b.T)[:][0]**2 # normalization if o2 == o1: g1ig1j = g1(setup, chlsi, k0, q0, o1)**2 else: g1ig1j = g1(setup, chlsi, k0, q0, o1) * g1(setup, chlsi, k0, q0, o2) # return return g2 / np.abs(g1ig1j[0]), g2, g1ig1j[0]
def coherent_state_quasilocal(setup, chlsi, chlso, E=0, tau=0): """ g2(E, tau) correlation as a function of incoming energy, E, and delay time, tau. Here specifically for quasi-local systems. Parameters ---------- se : Setup Scattering setup object chlsi : list list of incoming channels (must be identical!) chlso : list list of outgoing channels E : float or list Two photon state energ(y/ies) """ # channels # two incoming photons from same channel assert chlsi[0] == chlsi[ 1], 'Photons in an incoming coherent state must all belong to the same channel.' (i1, _) = chlsi (o1, o2) = chlso # numpy arraify k0s, taus = np.atleast_1d(E / 2, tau) # smatrix single photon _, S00 = smatrix.one_particle(setup, i1, o1, k0s) _, S11 = smatrix.one_particle(setup, i1, o2, k0s) g2 = np.zeros((len(k0s), len(taus)), dtype=np.float64) S2 = np.zeros((len(k0s), len(taus)), dtype=np.complex128) for i, k0 in enumerate(k0s): # eigen energies E1 = setup.eigenenergies(1, phi=k0) E2 = setup.eigenenergies(2, phi=k0) # creation operator in n = 0-1 eigenbasis representation A01_i = setup.transition(1, o1, 0, k0) A12_j = setup.transition(2, o2, 1, k0) A01_j = setup.transition(1, o2, 0, k0) A21_0 = setup.transition(1, i1, 2, k0) A10_0 = setup.transition(0, i1, 1, k0) prefactor = 4 * np.pi**2 * np.prod( [setup.gs[c] for c in chlsi + chlso]) op = (A12_j.dot(np.diag(1 / (2 * k0 - E2))).dot(A21_0) - np.diag(1 / (k0 - E1)).dot(A10_0).dot(A01_j)) \ .dot(A10_0 / (k0 - E1[:, None])) S2[i, :] = prefactor * np.dot( A01_i * np.exp(-1j * (E1[None, :] - k0) * taus[:, None]), op)[:, 0] g2[i, :] = np.abs(1 - S2[i, :] / (S00[i] * S11[i]))**2 # np.abs(1 - (prefactor/(S00[i]*S11[i]) # * np.dot(A01_i*np.exp(-1j*(E1[None, :] - k0)*taus[:, None]), op)) # )[:, 0]**2 return { 'g2': g2, 'phi2': np.abs(np.tile(S00 * S11, (len(taus), 1)) - S2)**2, 'normalization': S11 * S00, 'phi2_irreducible': S2 }