Coverage for /builds/ase/ase/ase/transport/greenfunction.py: 82.50%
40 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 GreenFunction:
7 """Equilibrium retarded Green function."""
9 def __init__(self, H, S=None, selfenergies=[], eta=1e-4):
10 self.H = H
11 self.S = S
12 self.selfenergies = selfenergies
13 self.eta = eta
14 self.energy = None
15 self.Ginv = np.empty(H.shape, complex)
17 def retarded(self, energy, inverse=False):
18 """Get retarded Green function at specified energy.
20 If 'inverse' is True, the inverse Green function is returned (faster).
21 """
22 if energy != self.energy:
23 self.energy = energy
24 z = energy + self.eta * 1.j
26 if self.S is None:
27 self.Ginv[:] = 0.0
28 self.Ginv.flat[:: len(self.S) + 1] = z
29 else:
30 self.Ginv[:] = z
31 self.Ginv *= self.S
32 self.Ginv -= self.H
34 for selfenergy in self.selfenergies:
35 self.Ginv -= selfenergy.retarded(energy)
37 if inverse:
38 return self.Ginv
39 else:
40 return np.linalg.inv(self.Ginv)
42 def calculate(self, energy, sigma):
43 """XXX is this really needed"""
44 ginv = energy * self.S - self.H - sigma
45 return np.linalg.inv(ginv)
47 def apply_retarded(self, energy, X):
48 """Apply retarded Green function to X.
50 Returns the matrix product G^r(e) . X
51 """
52 return np.linalg.solve(self.retarded(energy, inverse=True), X)
54 def dos(self, energy):
55 """Total density of states -1/pi Im(Tr(GS))"""
56 if self.S is None:
57 return -self.retarded(energy).imag.trace() / np.pi
58 else:
59 GS = self.apply_retarded(energy, self.S)
60 return -GS.imag.trace() / np.pi
62 def pdos(self, energy):
63 """Projected density of states -1/pi Im(SGS/S)"""
64 if self.S is None:
65 return -self.retarded(energy).imag.diagonal() / np.pi
66 else:
67 S = self.S
68 SGS = np.dot(S, self.apply_retarded(energy, S))
69 return -(SGS.diagonal() / S.diagonal()).imag / np.pi