root / ase / transport / calculators.py @ 7
Historique | Voir | Annoter | Télécharger (15,15 ko)
| 1 | 1 | tkerber | import numpy as np |
|---|---|---|---|
| 2 | 1 | tkerber | |
| 3 | 1 | tkerber | from numpy import linalg |
| 4 | 1 | tkerber | from ase.transport.selfenergy import LeadSelfEnergy, BoxProbe |
| 5 | 1 | tkerber | from ase.transport.greenfunction import GreenFunction |
| 6 | 1 | tkerber | from ase.transport.tools import subdiagonalize, cutcoupling, tri2full, dagger,\ |
| 7 | 1 | tkerber | rotate_matrix
|
| 8 | 1 | tkerber | |
| 9 | 1 | tkerber | |
| 10 | 1 | tkerber | class TransportCalculator: |
| 11 | 1 | tkerber | """Determine transport properties of a device sandwiched between
|
| 12 | 1 | tkerber | two semi-infinite leads using a Green function method.
|
| 13 | 1 | tkerber | """
|
| 14 | 1 | tkerber | |
| 15 | 1 | tkerber | def __init__(self, **kwargs): |
| 16 | 1 | tkerber | """Create the transport calculator.
|
| 17 | 1 | tkerber |
|
| 18 | 1 | tkerber | Parameters
|
| 19 | 1 | tkerber | ==========
|
| 20 | 1 | tkerber | h : (N, N) ndarray
|
| 21 | 1 | tkerber | Hamiltonian matrix for the central region.
|
| 22 | 1 | tkerber | s : {None, (N, N) ndarray}, optional
|
| 23 | 1 | tkerber | Overlap matrix for the central region.
|
| 24 | 1 | tkerber | Use None for an orthonormal basis.
|
| 25 | 1 | tkerber | h1 : (N1, N1) ndarray
|
| 26 | 1 | tkerber | Hamiltonian matrix for lead1.
|
| 27 | 1 | tkerber | h2 : {None, (N2, N2) ndarray}, optional
|
| 28 | 1 | tkerber | Hamiltonian matrix for lead2. You may use None if lead1 and lead2
|
| 29 | 1 | tkerber | are identical.
|
| 30 | 1 | tkerber | s1 : {None, (N1, N1) ndarray}, optional
|
| 31 | 1 | tkerber | Overlap matrix for lead1. Use None for an orthonomormal basis.
|
| 32 | 1 | tkerber | hc1 : {None, (N1, N) ndarray}, optional
|
| 33 | 1 | tkerber | Hamiltonian coupling matrix between the first principal
|
| 34 | 1 | tkerber | layer in lead1 and the central region.
|
| 35 | 1 | tkerber | hc2 : {None, (N2, N} ndarray), optional
|
| 36 | 1 | tkerber | Hamiltonian coupling matrix between the first principal
|
| 37 | 1 | tkerber | layer in lead2 and the central region.
|
| 38 | 1 | tkerber | sc1 : {None, (N1, N) ndarray}, optional
|
| 39 | 1 | tkerber | Overlap coupling matrix between the first principal
|
| 40 | 1 | tkerber | layer in lead1 and the central region.
|
| 41 | 1 | tkerber | sc2 : {None, (N2, N) ndarray}, optional
|
| 42 | 1 | tkerber | Overlap coupling matrix between the first principal
|
| 43 | 1 | tkerber | layer in lead2 and the central region.
|
| 44 | 1 | tkerber | energies : {None, array_like}, optional
|
| 45 | 1 | tkerber | Energy points for which calculated transport properties are
|
| 46 | 1 | tkerber | evaluated.
|
| 47 | 1 | tkerber | eta : {1.0e-5, float}, optional
|
| 48 | 1 | tkerber | Infinitesimal for the central region Green function.
|
| 49 | 1 | tkerber | eta1/eta2 : {1.0e-5, float}, optional
|
| 50 | 1 | tkerber | Infinitesimal for lead1/lead2 Green function.
|
| 51 | 1 | tkerber | align_bf : {None, int}, optional
|
| 52 | 1 | tkerber | Use align_bf=m to shift the central region
|
| 53 | 1 | tkerber | by a constant potential such that the m'th onsite element
|
| 54 | 1 | tkerber | in the central region is aligned to the m'th onsite element
|
| 55 | 1 | tkerber | in lead1 principal layer.
|
| 56 | 1 | tkerber | logfile : {None, str}, optional
|
| 57 | 1 | tkerber | Write a logfile to file with name `logfile`.
|
| 58 | 1 | tkerber | Use '-' to write to std out.
|
| 59 | 1 | tkerber | eigenchannels: {0, int}, optional
|
| 60 | 1 | tkerber | Number of eigenchannel transmission coefficients to
|
| 61 | 1 | tkerber | calculate.
|
| 62 | 1 | tkerber | pdos : {None, (N,) array_like}, optional
|
| 63 | 1 | tkerber | Specify which basis functions to calculate the
|
| 64 | 1 | tkerber | projected density of states for.
|
| 65 | 1 | tkerber | dos : {False, bool}, optional
|
| 66 | 1 | tkerber | The total density of states of the central region.
|
| 67 | 1 | tkerber | box: XXX
|
| 68 | 1 | tkerber | YYY
|
| 69 | 1 | tkerber |
|
| 70 | 1 | tkerber | If hc1/hc2 are None, they are assumed to be identical to
|
| 71 | 1 | tkerber | the coupling matrix elements between neareste neighbor
|
| 72 | 1 | tkerber | principal layers in lead1/lead2.
|
| 73 | 1 | tkerber |
|
| 74 | 1 | tkerber | Examples
|
| 75 | 1 | tkerber | ========
|
| 76 | 1 | tkerber | >>> import numpy as np
|
| 77 | 1 | tkerber | >>> h = np.array((0,)).reshape((1,1))
|
| 78 | 1 | tkerber | >>> h1 = np.array((0, -1, -1, 0)).reshape(2,2)
|
| 79 | 1 | tkerber | >>> energies = np.arange(-3, 3, 0.1)
|
| 80 | 1 | tkerber | >>> calc = TransportCalculator(h=h, h1=h1, energies=energies)
|
| 81 | 1 | tkerber | >>> T = calc.get_transmission()
|
| 82 | 1 | tkerber |
|
| 83 | 1 | tkerber | """
|
| 84 | 1 | tkerber | |
| 85 | 1 | tkerber | # The default values for all extra keywords
|
| 86 | 1 | tkerber | self.input_parameters = {'energies': None, |
| 87 | 1 | tkerber | 'h': None, |
| 88 | 1 | tkerber | 'h1': None, |
| 89 | 1 | tkerber | 'h2': None, |
| 90 | 1 | tkerber | 's': None, |
| 91 | 1 | tkerber | 's1': None, |
| 92 | 1 | tkerber | 's2': None, |
| 93 | 1 | tkerber | 'hc1': None, |
| 94 | 1 | tkerber | 'hc2': None, |
| 95 | 1 | tkerber | 'sc1': None, |
| 96 | 1 | tkerber | 'sc2': None, |
| 97 | 1 | tkerber | 'box': None, |
| 98 | 1 | tkerber | 'align_bf': None, |
| 99 | 1 | tkerber | 'eta1': 1e-5, |
| 100 | 1 | tkerber | 'eta2': 1e-5, |
| 101 | 1 | tkerber | 'eta': 1e-5, |
| 102 | 1 | tkerber | 'logfile': None, # '-', |
| 103 | 1 | tkerber | 'eigenchannels': 0, |
| 104 | 1 | tkerber | 'dos': False, |
| 105 | 1 | tkerber | 'pdos': [],
|
| 106 | 1 | tkerber | } |
| 107 | 1 | tkerber | self.initialized = False # Changed Hamiltonians? |
| 108 | 1 | tkerber | self.uptodate = False # Changed energy grid? |
| 109 | 1 | tkerber | self.set(**kwargs)
|
| 110 | 1 | tkerber | |
| 111 | 1 | tkerber | def set(self, **kwargs): |
| 112 | 1 | tkerber | for key in kwargs: |
| 113 | 1 | tkerber | if key in ['h', 'h1', 'h2', 'hc1', 'hc2', |
| 114 | 1 | tkerber | 's', 's1', 's2', 'sc1', 'sc2', |
| 115 | 1 | tkerber | 'eta', 'eta1', 'eta2', 'align_bf', 'box']: |
| 116 | 1 | tkerber | self.initialized = False |
| 117 | 1 | tkerber | self.uptodate = False |
| 118 | 1 | tkerber | break
|
| 119 | 1 | tkerber | elif key in ['energies', 'eigenchannels', 'dos', 'pdos']: |
| 120 | 1 | tkerber | self.uptodate = False |
| 121 | 1 | tkerber | elif key not in self.input_parameters: |
| 122 | 1 | tkerber | raise KeyError, '\'%s\' not a vaild keyword' % key |
| 123 | 1 | tkerber | |
| 124 | 1 | tkerber | self.input_parameters.update(kwargs)
|
| 125 | 1 | tkerber | log = self.input_parameters['logfile'] |
| 126 | 1 | tkerber | if log is None: |
| 127 | 1 | tkerber | class Trash: |
| 128 | 1 | tkerber | def write(self, s): |
| 129 | 1 | tkerber | pass
|
| 130 | 1 | tkerber | def flush(self): |
| 131 | 1 | tkerber | pass
|
| 132 | 1 | tkerber | self.log = Trash()
|
| 133 | 1 | tkerber | elif log == '-': |
| 134 | 1 | tkerber | from sys import stdout |
| 135 | 1 | tkerber | self.log = stdout
|
| 136 | 1 | tkerber | elif 'logfile' in kwargs: |
| 137 | 1 | tkerber | self.log = open(log, 'w') |
| 138 | 1 | tkerber | |
| 139 | 1 | tkerber | def initialize(self): |
| 140 | 1 | tkerber | if self.initialized: |
| 141 | 1 | tkerber | return
|
| 142 | 1 | tkerber | |
| 143 | 1 | tkerber | print >> self.log, '# Initializing calculator...' |
| 144 | 1 | tkerber | |
| 145 | 1 | tkerber | p = self.input_parameters
|
| 146 | 1 | tkerber | if p['s'] == None: |
| 147 | 1 | tkerber | p['s'] = np.identity(len(p['h'])) |
| 148 | 1 | tkerber | |
| 149 | 1 | tkerber | identical_leads = False
|
| 150 | 1 | tkerber | if p['h2'] == None: |
| 151 | 1 | tkerber | p['h2'] = p['h1'] # Lead2 is idendical to lead1 |
| 152 | 1 | tkerber | identical_leads = True
|
| 153 | 1 | tkerber | |
| 154 | 1 | tkerber | if p['s1'] == None: |
| 155 | 1 | tkerber | p['s1'] = np.identity(len(p['h1'])) |
| 156 | 1 | tkerber | |
| 157 | 1 | tkerber | if p['s2'] == None and not identical_leads: |
| 158 | 1 | tkerber | p['s2'] = np.identity(len(p['h2'])) # Orthonormal basis for lead 2 |
| 159 | 1 | tkerber | else: # Lead2 is idendical to lead1 |
| 160 | 1 | tkerber | p['s2'] = p['s1'] |
| 161 | 1 | tkerber | |
| 162 | 1 | tkerber | |
| 163 | 1 | tkerber | h_mm = p['h']
|
| 164 | 1 | tkerber | s_mm = p['s']
|
| 165 | 1 | tkerber | pl1 = len(p['h1']) / 2 |
| 166 | 1 | tkerber | pl2 = len(p['h2']) / 2 |
| 167 | 1 | tkerber | h1_ii = p['h1'][:pl1, :pl1]
|
| 168 | 1 | tkerber | h1_ij = p['h1'][:pl1, pl1:2 * pl1] |
| 169 | 1 | tkerber | s1_ii = p['s1'][:pl1, :pl1]
|
| 170 | 1 | tkerber | s1_ij = p['s1'][:pl1, pl1:2 * pl1] |
| 171 | 1 | tkerber | h2_ii = p['h2'][:pl2, :pl2]
|
| 172 | 1 | tkerber | h2_ij = p['h2'][pl2: 2 * pl2, :pl2] |
| 173 | 1 | tkerber | s2_ii = p['s2'][:pl2, :pl2]
|
| 174 | 1 | tkerber | s2_ij = p['s2'][pl2: 2 * pl2, :pl2] |
| 175 | 1 | tkerber | |
| 176 | 1 | tkerber | if p['hc1'] is None: |
| 177 | 1 | tkerber | nbf = len(h_mm)
|
| 178 | 1 | tkerber | h1_im = np.zeros((pl1, nbf), complex)
|
| 179 | 1 | tkerber | s1_im = np.zeros((pl1, nbf), complex)
|
| 180 | 1 | tkerber | h1_im[:pl1, :pl1] = h1_ij |
| 181 | 1 | tkerber | s1_im[:pl1, :pl1] = s1_ij |
| 182 | 1 | tkerber | p['hc1'] = h1_im
|
| 183 | 1 | tkerber | p['sc1'] = s1_im
|
| 184 | 1 | tkerber | else:
|
| 185 | 1 | tkerber | h1_im = p['hc1']
|
| 186 | 1 | tkerber | if p['sc1'] is not None: |
| 187 | 1 | tkerber | s1_im = p['sc1']
|
| 188 | 1 | tkerber | else:
|
| 189 | 1 | tkerber | s1_im = np.zeros(h1_im.shape, complex)
|
| 190 | 1 | tkerber | p['sc1'] = s1_im
|
| 191 | 1 | tkerber | |
| 192 | 1 | tkerber | if p['hc2'] is None: |
| 193 | 1 | tkerber | h2_im = np.zeros((pl2, nbf), complex)
|
| 194 | 1 | tkerber | s2_im = np.zeros((pl2, nbf), complex)
|
| 195 | 1 | tkerber | h2_im[-pl2:, -pl2:] = h2_ij |
| 196 | 1 | tkerber | s2_im[-pl2:, -pl2:] = s2_ij |
| 197 | 1 | tkerber | p['hc2'] = h2_im
|
| 198 | 1 | tkerber | p['sc2'] = s2_im
|
| 199 | 1 | tkerber | else:
|
| 200 | 1 | tkerber | h2_im = p['hc2']
|
| 201 | 1 | tkerber | if p['sc2'] is not None: |
| 202 | 1 | tkerber | s2_im = p['sc2']
|
| 203 | 1 | tkerber | else:
|
| 204 | 1 | tkerber | s2_im = np.zeros(h2_im.shape, complex)
|
| 205 | 1 | tkerber | p['sc2'] = s2_im
|
| 206 | 1 | tkerber | |
| 207 | 1 | tkerber | align_bf = p['align_bf']
|
| 208 | 1 | tkerber | if align_bf != None: |
| 209 | 1 | tkerber | diff = (h_mm[align_bf, align_bf] - h1_ii[align_bf, align_bf]) \ |
| 210 | 1 | tkerber | / s_mm[align_bf, align_bf] |
| 211 | 1 | tkerber | print >> self.log, '# Aligning scat. H to left lead H. diff=', diff |
| 212 | 1 | tkerber | h_mm -= diff * s_mm |
| 213 | 1 | tkerber | |
| 214 | 1 | tkerber | # Setup lead self-energies
|
| 215 | 1 | tkerber | # All infinitesimals must be > 0
|
| 216 | 1 | tkerber | assert np.all(np.array((p['eta'], p['eta1'], p['eta2'])) > 0.0) |
| 217 | 1 | tkerber | self.selfenergies = [LeadSelfEnergy((h1_ii, s1_ii),
|
| 218 | 1 | tkerber | (h1_ij, s1_ij), |
| 219 | 1 | tkerber | (h1_im, s1_im), |
| 220 | 1 | tkerber | p['eta1']),
|
| 221 | 1 | tkerber | LeadSelfEnergy((h2_ii, s2_ii), |
| 222 | 1 | tkerber | (h2_ij, s2_ij), |
| 223 | 1 | tkerber | (h2_im, s2_im), |
| 224 | 1 | tkerber | p['eta2'])]
|
| 225 | 1 | tkerber | box = p['box']
|
| 226 | 1 | tkerber | if box is not None: |
| 227 | 1 | tkerber | print 'Using box probe!' |
| 228 | 1 | tkerber | self.selfenergies.append(
|
| 229 | 1 | tkerber | BoxProbe(eta=box[0], a=box[1], b=box[2], energies=box[3], |
| 230 | 1 | tkerber | S=s_mm, T=0.3))
|
| 231 | 1 | tkerber | |
| 232 | 1 | tkerber | #setup scattering green function
|
| 233 | 1 | tkerber | self.greenfunction = GreenFunction(selfenergies=self.selfenergies, |
| 234 | 1 | tkerber | H=h_mm, |
| 235 | 1 | tkerber | S=s_mm, |
| 236 | 1 | tkerber | eta=p['eta'])
|
| 237 | 1 | tkerber | |
| 238 | 1 | tkerber | self.initialized = True |
| 239 | 1 | tkerber | |
| 240 | 1 | tkerber | def update(self): |
| 241 | 1 | tkerber | if self.uptodate: |
| 242 | 1 | tkerber | return
|
| 243 | 1 | tkerber | |
| 244 | 1 | tkerber | p = self.input_parameters
|
| 245 | 1 | tkerber | self.energies = p['energies'] |
| 246 | 1 | tkerber | nepts = len(self.energies) |
| 247 | 1 | tkerber | nchan = p['eigenchannels']
|
| 248 | 1 | tkerber | pdos = p['pdos']
|
| 249 | 1 | tkerber | self.T_e = np.empty(nepts)
|
| 250 | 1 | tkerber | if p['dos']: |
| 251 | 1 | tkerber | self.dos_e = np.empty(nepts)
|
| 252 | 1 | tkerber | if pdos != []:
|
| 253 | 1 | tkerber | self.pdos_ne = np.empty((len(pdos), nepts)) |
| 254 | 1 | tkerber | if nchan > 0: |
| 255 | 1 | tkerber | self.eigenchannels_ne = np.empty((nchan, nepts))
|
| 256 | 1 | tkerber | |
| 257 | 1 | tkerber | for e, energy in enumerate(self.energies): |
| 258 | 1 | tkerber | Ginv_mm = self.greenfunction.retarded(energy, inverse=True) |
| 259 | 1 | tkerber | lambda1_mm = self.selfenergies[0].get_lambda(energy) |
| 260 | 1 | tkerber | lambda2_mm = self.selfenergies[1].get_lambda(energy) |
| 261 | 1 | tkerber | a_mm = linalg.solve(Ginv_mm, lambda1_mm) |
| 262 | 1 | tkerber | b_mm = linalg.solve(dagger(Ginv_mm), lambda2_mm) |
| 263 | 1 | tkerber | T_mm = np.dot(a_mm, b_mm) |
| 264 | 1 | tkerber | if nchan > 0: |
| 265 | 1 | tkerber | t_n = linalg.eigvals(T_mm).real |
| 266 | 1 | tkerber | self.eigenchannels_ne[:, e] = np.sort(t_n)[-nchan:]
|
| 267 | 1 | tkerber | self.T_e[e] = np.sum(t_n)
|
| 268 | 1 | tkerber | else:
|
| 269 | 1 | tkerber | self.T_e[e] = np.trace(T_mm).real
|
| 270 | 1 | tkerber | |
| 271 | 1 | tkerber | print >> self.log, energy, self.T_e[e] |
| 272 | 1 | tkerber | self.log.flush()
|
| 273 | 1 | tkerber | |
| 274 | 1 | tkerber | if p['dos']: |
| 275 | 1 | tkerber | self.dos_e[e] = self.greenfunction.dos(energy) |
| 276 | 1 | tkerber | |
| 277 | 1 | tkerber | if pdos != []:
|
| 278 | 1 | tkerber | self.pdos_ne[:, e] = np.take(self.greenfunction.pdos(energy), |
| 279 | 1 | tkerber | pdos) |
| 280 | 1 | tkerber | |
| 281 | 1 | tkerber | self.uptodate = True |
| 282 | 1 | tkerber | |
| 283 | 1 | tkerber | def print_pl_convergence(self): |
| 284 | 1 | tkerber | self.initialize()
|
| 285 | 1 | tkerber | pl1 = len(self.input_parameters['h1']) / 2 |
| 286 | 1 | tkerber | |
| 287 | 1 | tkerber | h_ii = self.selfenergies[0].h_ii |
| 288 | 1 | tkerber | s_ii = self.selfenergies[0].s_ii |
| 289 | 1 | tkerber | ha_ii = self.greenfunction.H[:pl1, :pl1]
|
| 290 | 1 | tkerber | sa_ii = self.greenfunction.S[:pl1, :pl1]
|
| 291 | 1 | tkerber | c1 = np.abs(h_ii - ha_ii).max() |
| 292 | 1 | tkerber | c2 = np.abs(s_ii - sa_ii).max() |
| 293 | 1 | tkerber | print 'Conv (h,s)=%.2e, %2.e' % (c1, c2) |
| 294 | 1 | tkerber | |
| 295 | 1 | tkerber | def plot_pl_convergence(self): |
| 296 | 1 | tkerber | self.initialize()
|
| 297 | 1 | tkerber | pl1 = len(self.input_parameters['h1']) / 2 |
| 298 | 1 | tkerber | hlead = self.selfenergies[0].h_ii.real.diagonal() |
| 299 | 1 | tkerber | hprincipal = self.greenfunction.H.real.diagonal[:pl1]
|
| 300 | 1 | tkerber | |
| 301 | 1 | tkerber | import pylab as pl |
| 302 | 1 | tkerber | pl.plot(hlead, label='lead')
|
| 303 | 1 | tkerber | pl.plot(hprincipal, label='principal layer')
|
| 304 | 1 | tkerber | pl.axis('tight')
|
| 305 | 1 | tkerber | pl.show() |
| 306 | 1 | tkerber | |
| 307 | 1 | tkerber | def get_transmission(self): |
| 308 | 1 | tkerber | self.initialize()
|
| 309 | 1 | tkerber | self.update()
|
| 310 | 1 | tkerber | return self.T_e |
| 311 | 1 | tkerber | |
| 312 | 1 | tkerber | def get_dos(self): |
| 313 | 1 | tkerber | self.initialize()
|
| 314 | 1 | tkerber | self.update()
|
| 315 | 1 | tkerber | return self.dos_e |
| 316 | 1 | tkerber | |
| 317 | 1 | tkerber | def get_eigenchannels(self, n=None): |
| 318 | 1 | tkerber | """Get ``n`` first eigenchannels."""
|
| 319 | 1 | tkerber | self.initialize()
|
| 320 | 1 | tkerber | self.update()
|
| 321 | 1 | tkerber | if n is None: |
| 322 | 1 | tkerber | n = self.input_parameters['eigenchannels'] |
| 323 | 1 | tkerber | return self.eigenchannels_ne[:n] |
| 324 | 1 | tkerber | |
| 325 | 1 | tkerber | def get_pdos(self): |
| 326 | 1 | tkerber | self.initialize()
|
| 327 | 1 | tkerber | self.update()
|
| 328 | 1 | tkerber | return self.pdos_ne |
| 329 | 1 | tkerber | |
| 330 | 1 | tkerber | def subdiagonalize_bfs(self, bfs, apply=False): |
| 331 | 1 | tkerber | self.initialize()
|
| 332 | 1 | tkerber | bfs = np.array(bfs) |
| 333 | 1 | tkerber | p = self.input_parameters
|
| 334 | 1 | tkerber | h_mm = p['h']
|
| 335 | 1 | tkerber | s_mm = p['s']
|
| 336 | 1 | tkerber | ht_mm, st_mm, c_mm, e_m = subdiagonalize(h_mm, s_mm, bfs) |
| 337 | 1 | tkerber | if apply: |
| 338 | 1 | tkerber | self.uptodate = False |
| 339 | 1 | tkerber | h_mm[:] = ht_mm |
| 340 | 1 | tkerber | s_mm[:] = st_mm |
| 341 | 1 | tkerber | # Rotate coupling between lead and central region
|
| 342 | 1 | tkerber | for alpha, sigma in enumerate(self.selfenergies): |
| 343 | 1 | tkerber | sigma.h_im[:] = np.dot(sigma.h_im, c_mm) |
| 344 | 1 | tkerber | sigma.s_im[:] = np.dot(sigma.s_im, c_mm) |
| 345 | 1 | tkerber | |
| 346 | 1 | tkerber | c_mm = np.take(c_mm, bfs, axis=0)
|
| 347 | 1 | tkerber | c_mm = np.take(c_mm, bfs, axis=1)
|
| 348 | 1 | tkerber | return ht_mm, st_mm, e_m, c_mm
|
| 349 | 1 | tkerber | |
| 350 | 1 | tkerber | def cutcoupling_bfs(self, bfs, apply=False): |
| 351 | 1 | tkerber | self.initialize()
|
| 352 | 1 | tkerber | bfs = np.array(bfs) |
| 353 | 1 | tkerber | p = self.input_parameters
|
| 354 | 1 | tkerber | h_pp = p['h'].copy()
|
| 355 | 1 | tkerber | s_pp = p['s'].copy()
|
| 356 | 1 | tkerber | cutcoupling(h_pp, s_pp, bfs) |
| 357 | 1 | tkerber | if apply: |
| 358 | 1 | tkerber | self.uptodate = False |
| 359 | 1 | tkerber | p['h'][:] = h_pp
|
| 360 | 1 | tkerber | p['s'][:] = s_pp
|
| 361 | 1 | tkerber | for alpha, sigma in enumerate(self.selfenergies): |
| 362 | 1 | tkerber | for m in bfs: |
| 363 | 1 | tkerber | sigma.h_im[:, m] = 0.0
|
| 364 | 1 | tkerber | sigma.s_im[:, m] = 0.0
|
| 365 | 1 | tkerber | return h_pp, s_pp
|
| 366 | 1 | tkerber | |
| 367 | 1 | tkerber | def lowdin_rotation(self, apply=False): |
| 368 | 1 | tkerber | p = self.input_parameters
|
| 369 | 1 | tkerber | h_mm = p['h']
|
| 370 | 1 | tkerber | s_mm = p['s']
|
| 371 | 1 | tkerber | eig, rot_mm = linalg.eigh(s_mm) |
| 372 | 1 | tkerber | eig = np.abs(eig) |
| 373 | 1 | tkerber | rot_mm = np.dot(rot_mm / np.sqrt(eig), dagger(rot_mm)) |
| 374 | 1 | tkerber | if apply: |
| 375 | 1 | tkerber | self.uptodate = False |
| 376 | 1 | tkerber | h_mm[:] = rotate_matrix(h_mm, rot_mm) # rotate C region
|
| 377 | 1 | tkerber | s_mm[:] = rotate_matrix(s_mm, rot_mm) |
| 378 | 1 | tkerber | for alpha, sigma in enumerate(self.selfenergies): |
| 379 | 1 | tkerber | sigma.h_im[:] = np.dot(sigma.h_im, rot_mm) # rotate L-C coupl.
|
| 380 | 1 | tkerber | sigma.s_im[:] = np.dot(sigma.s_im, rot_mm) |
| 381 | 1 | tkerber | |
| 382 | 1 | tkerber | return rot_mm
|
| 383 | 1 | tkerber | |
| 384 | 1 | tkerber | def get_left_channels(self, energy, nchan=1): |
| 385 | 1 | tkerber | self.initialize()
|
| 386 | 1 | tkerber | g_s_ii = self.greenfunction.retarded(energy)
|
| 387 | 1 | tkerber | lambda_l_ii = self.selfenergies[0].get_lambda(energy) |
| 388 | 1 | tkerber | lambda_r_ii = self.selfenergies[1].get_lambda(energy) |
| 389 | 1 | tkerber | |
| 390 | 1 | tkerber | if self.greenfunction.S is None: |
| 391 | 1 | tkerber | s_s_qsrt_ii = s_s_isqrt = np.identity(len(g_s_ii))
|
| 392 | 1 | tkerber | else:
|
| 393 | 1 | tkerber | s_mm = self.greenfunction.S
|
| 394 | 1 | tkerber | s_s_i, s_s_ii = linalg.eig(s_mm) |
| 395 | 1 | tkerber | s_s_i = np.abs(s_s_i) |
| 396 | 1 | tkerber | s_s_sqrt_i = np.sqrt(s_s_i) # sqrt of eigenvalues
|
| 397 | 1 | tkerber | s_s_sqrt_ii = np.dot(s_s_ii * s_s_sqrt_i, dagger(s_s_ii)) |
| 398 | 1 | tkerber | s_s_isqrt_ii = np.dot(s_s_ii / s_s_sqrt_i, dagger(s_s_ii)) |
| 399 | 1 | tkerber | |
| 400 | 1 | tkerber | lambdab_r_ii = np.dot(np.dot(s_s_isqrt_ii, lambda_r_ii),s_s_isqrt_ii) |
| 401 | 1 | tkerber | a_l_ii = np.dot(np.dot(g_s_ii, lambda_l_ii), dagger(g_s_ii)) |
| 402 | 1 | tkerber | ab_l_ii = np.dot(np.dot(s_s_sqrt_ii, a_l_ii), s_s_sqrt_ii) |
| 403 | 1 | tkerber | lambda_i, u_ii = linalg.eig(ab_l_ii) |
| 404 | 1 | tkerber | ut_ii = np.sqrt(lambda_i / (2.0 * np.pi)) * u_ii
|
| 405 | 1 | tkerber | m_ii = 2 * np.pi * np.dot(np.dot(dagger(ut_ii), lambdab_r_ii),ut_ii)
|
| 406 | 1 | tkerber | T_i,c_in = linalg.eig(m_ii) |
| 407 | 1 | tkerber | T_i = np.abs(T_i) |
| 408 | 1 | tkerber | |
| 409 | 1 | tkerber | channels = np.argsort(-T_i)[:nchan] |
| 410 | 1 | tkerber | c_in = np.take(c_in, channels, axis=1)
|
| 411 | 1 | tkerber | T_n = np.take(T_i, channels) |
| 412 | 1 | tkerber | v_in = np.dot(np.dot(s_s_isqrt_ii, ut_ii), c_in) |
| 413 | 1 | tkerber | |
| 414 | 1 | tkerber | return T_n, v_in |