Coverage for /builds/ase/ase/ase/transport/selfenergy.py: 82.14%
56 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3import numpy as np
6class LeadSelfEnergy:
7 conv = 1e-8 # Convergence criteria for surface Green function
9 def __init__(self, hs_dii, hs_dij, hs_dim, eta=1e-4):
10 self.h_ii, self.s_ii = hs_dii # onsite principal layer
11 self.h_ij, self.s_ij = hs_dij # coupling between principal layers
12 self.h_im, self.s_im = hs_dim # coupling to the central region
13 self.nbf = self.h_im.shape[1] # nbf for the scattering region
14 self.eta = eta
15 self.energy = None
16 self.bias = 0
17 self.sigma_mm = np.empty((self.nbf, self.nbf), complex)
19 def retarded(self, energy):
20 """Return self-energy (sigma) evaluated at specified energy."""
21 if energy != self.energy:
22 self.energy = energy
23 z = energy - self.bias + self.eta * 1.j
24 tau_im = z * self.s_im - self.h_im
25 a_im = np.linalg.solve(self.get_sgfinv(energy), tau_im)
26 tau_mi = z * self.s_im.T.conj() - self.h_im.T.conj()
27 self.sigma_mm[:] = np.dot(tau_mi, a_im)
29 return self.sigma_mm
31 def set_bias(self, bias):
32 self.bias = bias
34 def get_lambda(self, energy):
35 """Return the lambda (aka Gamma) defined by i(S-S^d).
37 Here S is the retarded selfenergy, and d denotes the hermitian
38 conjugate.
39 """
40 sigma_mm = self.retarded(energy)
41 return 1.j * (sigma_mm - sigma_mm.T.conj())
43 def get_sgfinv(self, energy):
44 """The inverse of the retarded surface Green function"""
45 z = energy - self.bias + self.eta * 1.j
47 v_00 = z * self.s_ii.T.conj() - self.h_ii.T.conj()
48 v_11 = v_00.copy()
49 v_10 = z * self.s_ij - self.h_ij
50 v_01 = z * self.s_ij.T.conj() - self.h_ij.T.conj()
52 delta = self.conv + 1
53 while delta > self.conv:
54 a = np.linalg.solve(v_11, v_01)
55 b = np.linalg.solve(v_11, v_10)
56 v_01_dot_b = np.dot(v_01, b)
57 v_00 -= v_01_dot_b
58 v_11 -= np.dot(v_10, a)
59 v_11 -= v_01_dot_b
60 v_01 = -np.dot(v_01, a)
61 v_10 = -np.dot(v_10, b)
62 delta = abs(v_01).max()
64 return v_00
67class BoxProbe:
68 """Box shaped Buttinger probe.
70 Kramers-kroning: real = H(imag); imag = -H(real)
71 """
73 def __init__(self, eta, a, b, energies, S, T=0.3):
74 from Transport.Hilbert import hilbert
75 se = np.empty(len(energies), complex)
76 se.imag = .5 * (np.tanh(.5 * (energies - a) / T) -
77 np.tanh(.5 * (energies - b) / T))
78 se.real = hilbert(se.imag)
79 se.imag -= 1
80 self.selfenergy_e = eta * se
81 self.energies = energies
82 self.S = S
84 def retarded(self, energy):
85 return self.selfenergy_e[self.energies.searchsorted(energy)] * self.S