Source code for wannierberri.formula.covariant

import numpy as np
from ..utility import alpha_A, beta_A, delta_f
from .formula import Formula_ln, Matrix_ln, Matrix_GenDer_ln, FormulaProduct, FormulaSum, DeltaProduct
from ..symmetry.point_symmetry import transform_ident, transform_odd


[docs] class Identity(Formula_ln): def __init__(self, data_K=None, **parameters): super().__init__(data_K, **parameters) self.ndim = 0 self.transformTR = transform_ident self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): return np.eye(len(inn))
[docs] def ln(self, ik, inn, out): return np.zeros((len(out), len(inn)))
[docs] class Eavln(Matrix_ln): """ be careful : this is not a covariant matrix""" def __init__(self, data_K): super().__init__(0.5 * (data_K.E_K[:, :, None] + data_K.E_K[:, None, :])) self.ndim = 0 self.transformTR = transform_ident self.transformInv = transform_ident
[docs] class DEinv_ln(Matrix_ln): """DEinv_ln.matrix[ik, m, n] = 1 / (E_mk - E_nk)""" def __init__(self, data_K): super().__init__(data_K.dEig_inv)
[docs] def nn(self, ik, inn, out): raise NotImplementedError("dEinv_ln should not be called within inner states")
[docs] class Dcov(Matrix_ln): def __init__(self, data_K): super().__init__(data_K.D_H)
[docs] def nn(self, ik, inn, out): raise ValueError("Dln should not be called within inner states")
[docs] class DerDcov(Dcov): def __init__(self, data_K): self.W = data_K.covariant('Ham', commader=2) self.V = data_K.covariant('Ham', gender=1) self.D = data_K.Dcov self.dEinv = DEinv_ln(data_K)
[docs] def ln(self, ik, inn, out): summ = self.W.ln(ik, inn, out) tmp = np.einsum("lpb,pnd->lnbd", self.V.ll(ik, inn, out), self.D.ln(ik, inn, out)) summ += tmp + tmp.swapaxes(2, 3) tmp = -np.einsum("lmb,mnd->lnbd", self.D.ln(ik, inn, out), self.V.nn(ik, inn, out)) summ += tmp + tmp.swapaxes(2, 3) summ *= -self.dEinv.ln(ik, inn, out)[:, :, None, None] return summ
[docs] class Der2Dcov(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.WV = DerWln(data_K) self.dV = InvMass(data_K) self.V = data_K.covariant('Ham', commader=1) self.D = Dcov(data_K) self.dEinv = DEinv_ln(data_K)
[docs] def ln(self, ik, inn, out): summ = self.WV.ln(ik, inn, out) summ += np.einsum("lpbe,pnd->lnbde", self.dV.ll(ik, inn, out), self.D.ln(ik, inn, out)) summ += np.einsum("lpde,pnb->lnbde", self.dV.ll(ik, inn, out), self.D.ln(ik, inn, out)) summ += np.einsum("lpe,pnbd->lnbde", self.V.ll(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("lpd,pnbe->lnbde", self.V.ll(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("lpb,pnde->lnbde", self.V.ll(ik, inn, out), self.dD.ln(ik, inn, out)) summ += -np.einsum("lmde,mnb->lnbde", self.dD.ln(ik, inn, out), self.V.nn(ik, inn, out)) summ += -np.einsum("lmbd,mne->lnbde", self.dD.ln(ik, inn, out), self.V.nn(ik, inn, out)) summ += -np.einsum("lmbe,mnd->lnbde", self.dD.ln(ik, inn, out), self.V.nn(ik, inn, out)) summ += -np.einsum("lmb,mnde->lnbde", self.D.ln(ik, inn, out), self.dV.nn(ik, inn, out)) summ += -np.einsum("lmd,mnbe->lnbde", self.D.ln(ik, inn, out), self.dV.nn(ik, inn, out)) summ *= -self.dEinv.ln(ik, inn, out)[:, :, None, None, None] return summ
[docs] def nn(self, ik, inn, out): raise ValueError("Dln should not be called within inner states")
# TODO Der2A,B,O,H,S can be merged to one class.
[docs] class Der2A(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.A = data_K.covariant('AA') self.dA = data_K.covariant('AA', gender=1) self.Abar_de = Matrix_GenDer_ln(data_K.covariant('AA', commader=1), data_K.covariant('AA', commader=2), Dcov(data_K))
[docs] def nn(self, ik, inn, out): summ = self.Abar_de.nn(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.nl(ik, inn, out), self.A.ln(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.nl(ik, inn, out), self.dA.ln(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.A.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dA.nl(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] def ln(self, ik, inn, out): summ = self.Abar_de.ln(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.ln(ik, inn, out), self.A.nn(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.ln(ik, inn, out), self.dA.nn(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.A.ll(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dA.ll(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] class Der2B(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.B = data_K.covariant('BB') self.dB = data_K.covariant('BB', gender=1) self.Bbar_de = Matrix_GenDer_ln(data_K.covariant('BB', commader=1), data_K.covariant('BB', commader=2), Dcov(data_K))
[docs] def nn(self, ik, inn, out): summ = self.Bbar_de.nn(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.nl(ik, inn, out), self.B.ln(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.nl(ik, inn, out), self.dB.ln(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.B.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dB.nl(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] def ln(self, ik, inn, out): summ = self.Bbar_de.ln(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.ln(ik, inn, out), self.B.nn(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.ln(ik, inn, out), self.dB.nn(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.B.ll(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dB.ll(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] class Der2O(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.O = data_K.covariant('OO') self.dO = data_K.covariant('OO', gender=1) self.Obar_de = Matrix_GenDer_ln(data_K.covariant('OO', commader=1), data_K.covariant('OO', commader=2), Dcov(data_K))
[docs] def nn(self, ik, inn, out): summ = self.Obar_de.nn(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.nl(ik, inn, out), self.O.ln(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.nl(ik, inn, out), self.dO.ln(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.O.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dO.nl(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
[docs] class Der2H(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.H = data_K.covariant('CC') self.dH = data_K.covariant('CC', gender=1) self.Hbar_de = Matrix_GenDer_ln(data_K.covariant('CC', commader=1), data_K.covariant('CC', commader=2), Dcov(data_K))
[docs] def nn(self, ik, inn, out): summ = self.Hbar_de.nn(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.nl(ik, inn, out), self.H.ln(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.nl(ik, inn, out), self.dH.ln(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.H.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dH.nl(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
[docs] class InvMass(Matrix_GenDer_ln): r""" :math:`\overline{V}^{b:d}`""" def __init__(self, data_K): super().__init__(data_K.covariant('Ham', commader=1), data_K.covariant('Ham', commader=2), data_K.Dcov) self.transformTR = transform_ident self.transformInv = transform_ident
[docs] class DerWln(Matrix_GenDer_ln): r""" :math:`\overline{W}^{bc:d}`""" def __init__(self, data_K): super().__init__(data_K.covariant('Ham', 2), data_K.covariant('Ham', 3), data_K.Dcov) self.transformTR = transform_odd self.transformInv = transform_odd
############################# # Third derivative of E # #############################
[docs] class Der3E(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.V = data_K.covariant('Ham', commader=1) self.D = data_K.Dcov self.dV = InvMass(data_K) self.dD = DerDcov(data_K) self.dW = DerWln(data_K) self.ndim = 3 self.transformTR = transform_odd self.transformInv = transform_odd
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3, 3), dtype=complex) summ += 1 * self.dW.nn(ik, inn, out) summ += 1 * np.einsum("mlac,lnb->mnabc", self.dV.nl(ik, inn, out), self.D.ln(ik, inn, out)) summ += 1 * np.einsum("mla,lnbc->mnabc", self.V.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += -1 * np.einsum("mlbc,lna->mnabc", self.dD.nl(ik, inn, out), self.V.ln(ik, inn, out)) summ += -1 * np.einsum("mlb,lnac->mnabc", self.D.nl(ik, inn, out), self.dV.ln(ik, inn, out)) # TODO: alternatively: add factor 0.5 to first term, remove 4th and 5th, and ad line below. # Should give the same, I think, but needs to be tested # summ+=summ.swapaxes(0,1).conj() return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
######################## # Berry curvature # ########################
[docs] class Omega(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.D = data_K.Dcov if self.external_terms: self.A = data_K.covariant('AA') self.O = data_K.covariant('OO') self.ndim = 1 self.transformTR = transform_odd self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3), dtype=complex) if self.internal_terms: summ += -1j * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, alpha_A], self.D.ln(ik, inn, out)[:, :, beta_A]) if self.external_terms: summ += 0.5 * self.O.nn(ik, inn, out) summ += -1 * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, alpha_A], self.A.ln(ik, inn, out)[:, :, beta_A]) summ += +1 * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, beta_A], self.A.ln(ik, inn, out)[:, :, alpha_A]) summ += -1j * np.einsum( "mlc,lnc->mnc", self.A.nn(ik, inn, out)[:, :, alpha_A], self.A.nn(ik, inn, out)[:, :, beta_A]) summ += summ.swapaxes(0, 1).conj() return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
######################## # derivative of # # Berry curvature # ########################
[docs] class DerOmega(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.dD = DerDcov(data_K) self.D = data_K.Dcov if self.external_terms: self.A = data_K.covariant('AA') self.dA = data_K.covariant('AA', gender=1) self.dO = data_K.covariant('OO', gender=1) self.ndim = 2 self.transformTR = transform_ident self.transformInv = transform_odd
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3), dtype=complex) if self.external_terms: summ += 0.5 * self.dO.nn(ik, inn, out) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): if self.internal_terms: summ += -1j * s * np.einsum( "mlc,lncd->mncd", self.D.nl(ik, inn, out)[:, :, a], self.dD.ln(ik, inn, out)[:, :, b]) pass if self.external_terms: summ += -1 * s * np.einsum( "mlc,lncd->mncd", self.D.nl(ik, inn, out)[:, :, a], self.dA.ln(ik, inn, out)[:, :, b, :]) summ += -1 * s * np.einsum( "mlcd,lnc->mncd", self.dD.nl(ik, inn, out)[:, :, a, :], self.A.ln(ik, inn, out)[:, :, b]) summ += -1j * s * np.einsum( "mlc,lncd->mncd", self.A.nn(ik, inn, out)[:, :, a], self.dA.nn(ik, inn, out)[:, :, b, :]) pass summ += summ.swapaxes(0, 1).conj() return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
############################### ### second derivative of #### ### Berry curvature #### ###############################
[docs] class Der2Omega(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.ddD = Der2Dcov(data_K) self.dD = DerDcov(data_K) self.D = Dcov(data_K) if self.external_terms: self.A = data_K.covariant('AA') self.dA = data_K.covariant('AA', gender=1) self.ddA = Der2A(data_K) self.ddO = Der2O(data_K) self.ndim = 3 self.transformTR = transform_odd self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3, 3), dtype=complex) if self.external_terms: summ += 0.5 * self.ddO.nn(ik, inn, out) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): if self.internal_terms: summ += -1j * s * np.einsum("mlce,lncd->mncde", self.dD.nl(ik, inn, out)[:, :, a], self.dD.ln(ik, inn, out)[:, :, b]) summ += -1j * s * np.einsum("mlc,lncde->mncde", self.D.nl(ik, inn, out)[:, :, a], self.ddD.ln(ik, inn, out)[:, :, b]) pass if self.external_terms: summ += -1 * s * np.einsum("mlce,lncd->mncde", self.dD.nl(ik, inn, out)[:, :, a], self.dA.ln(ik, inn, out)[:, :, b, :]) summ += -1 * s * np.einsum("mlc,lncde->mncde", self.D.nl(ik, inn, out)[:, :, a], self.ddA.ln(ik, inn, out)[:, :, b, :]) summ += -1 * s * np.einsum("mlcde,lnc->mncde", self.ddD.nl(ik, inn, out)[:, :, a, :], self.A.ln(ik, inn, out)[:, :, b]) summ += -1 * s * np.einsum("mlcd,lnce->mncde", self.dD.nl(ik, inn, out)[:, :, a, :], self.dA.ln(ik, inn, out)[:, :, b]) summ += -1j * s * np.einsum("mlce,lncd->mncde", self.dA.nn(ik, inn, out)[:, :, a], self.dA.nn(ik, inn, out)[:, :, b, :]) summ += -1j * s * np.einsum("mlc,lncde->mncde", self.A.nn(ik, inn, out)[:, :, a], self.ddA.nn(ik, inn, out)[:, :, b, :]) pass summ += summ.swapaxes(0, 1).conj() return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
[docs] class Hamiltonian(Matrix_ln): def __init__(self, data_K): v = data_K.covariant('Ham', gender=0) self.__dict__.update(v.__dict__)
[docs] class Velocity(Matrix_ln): def __init__(self, data_K, external_terms=False): v = data_K.covariant('Ham', gender=1) self.__dict__.update(v.__dict__) if external_terms: self.matrix = self.matrix + 1j * data_K.Xbar('AA') * ( data_K.E_K[:, :, None, None] - data_K.E_K[:, None, :, None])
[docs] class Spin(Matrix_ln): def __init__(self, data_K): s = data_K.covariant('SS') self.__dict__.update(s.__dict__)
[docs] class DerSpin(Matrix_GenDer_ln): def __init__(self, data_K): s = data_K.covariant('SS', gender=1) self.__dict__.update(s.__dict__)
[docs] class Der2Spin(Formula_ln): def __init__(self, data_K): self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.S = data_K.covariant('SS') self.dS = data_K.covariant('SS', gender=1) self.Sbar_de = Matrix_GenDer_ln(data_K.covariant('SS', commader=1), data_K.covariant('SS', commader=2), Dcov(data_K)) self.ndim = 3 self.transformTR = transform_odd self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): summ = self.Sbar_de.nn(ik, inn, out) summ -= np.einsum("mlde,lnb...->mnb...de", self.dD.nl(ik, inn, out), self.S.ln(ik, inn, out)) summ -= np.einsum("mld,lnb...e->mnb...de", self.D.nl(ik, inn, out), self.dS.ln(ik, inn, out)) summ += np.einsum("mlb...,lnde->mnb...de", self.S.nl(ik, inn, out), self.dD.ln(ik, inn, out)) summ += np.einsum("mlb...e,lnd->mnb...de", self.dS.nl(ik, inn, out), self.D.ln(ik, inn, out)) return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
######################## # orbital moment # ########################
[docs] class Morb_H(Formula_ln): def __init__(self, data_K, **parameters): r""" :math:`\varepcilon_{abc} \langle \partial_a u | H | \partial_b \rangle` """ super().__init__(data_K, **parameters) if self.external_terms: self.A = data_K.covariant('AA') self.B = data_K.covariant('BB') self.C = data_K.covariant('CC') self.D = data_K.Dcov self.E = data_K.E_K self.ndim = 1 self.transformTR = transform_odd self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3), dtype=complex) if self.internal_terms: summ += -1j * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, alpha_A] * self.E[ik][out][None, :, None], self.D.ln(ik, inn, out)[:, :, beta_A]) if self.external_terms: summ += 0.5 * self.C.nn(ik, inn, out) summ += -1 * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, alpha_A], self.B.ln(ik, inn, out)[:, :, beta_A]) summ += +1 * np.einsum( "mlc,lnc->mnc", self.D.nl(ik, inn, out)[:, :, beta_A], self.B.ln(ik, inn, out)[:, :, alpha_A]) summ += -1j * np.einsum( "mlc,lnc->mnc", self.A.nn(ik, inn, out)[:, :, alpha_A] * self.E[ik][inn][None, :, None], self.A.nn(ik, inn, out)[:, :, beta_A]) summ += summ.swapaxes(0, 1).conj() return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
@property def additive(self): return False
[docs] class Morb_Hpm(Formula_ln): def __init__(self, data_K, sign=+1, **parameters): r""" Morb_H +- (En+Em)/2 * Omega """ super().__init__(data_K, **parameters) self.H = Morb_H(data_K, **parameters) self.sign = sign if self.sign != 0: self.O = Omega(data_K, **parameters) self.Eav = Eavln(data_K) self.ndim = 1 self.transformTR = transform_odd self.transformInv = transform_ident @property def additive(self): return False
[docs] def nn(self, ik, inn, out): res = self.H.nn(ik, inn, out) if self.sign != 0: res += self.sign * self.Eav.nn(ik, inn, out)[:, :, None] * self.O.nn(ik, inn, out) return res
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
[docs] class morb(Morb_Hpm): def __init__(self, data_K, **parameters): super().__init__(data_K, sign=-1, **parameters)
######################## # derivative of # # orbital moment # ########################
[docs] class DerMorb_H(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.V = data_K.covariant('Ham', commader=1) self.E = data_K.E_K if self.external_terms: self.A = data_K.covariant('AA') self.dA = data_K.covariant('AA', gender=1) self.B = data_K.covariant('BB') self.dB = data_K.covariant('BB', gender=1) self.dH = data_K.covariant('CC', gender=1) self.ndim = 2 self.transformTR = transform_ident self.transformInv = transform_odd
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3), dtype=complex) if self.internal_terms: summ += -2j * np.einsum( "mpc,pld,lnc->mncd", self.D.nl(ik, inn, out)[:, :, alpha_A], self.V.ll(ik, inn, out), self.D.ln(ik, inn, out)[:, :, beta_A]) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): summ += -2j * s * np.einsum( "mlc,lncd->mncd", self.D.nl(ik, inn, out)[:, :, a], self.E[ik][out][:, None, None, None] * self.dD.ln(ik, inn, out)[:, :, b]) if self.external_terms: summ += 1 * self.dH.nn(ik, inn, out) summ += -2j * np.einsum( "mpc,pld,lnc->mncd", self.A.nn(ik, inn, out)[:, :, alpha_A], self.V.nn(ik, inn, out), self.A.nn(ik, inn, out)[:, :, beta_A]) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): summ += -2j * s * np.einsum( "mlc,lncd->mncd", self.A.nn(ik, inn, out)[:, :, a] * self.E[ik][inn][None, :, None], self.dA.nn(ik, inn, out)[:, :, b, :]) summ += -2 * s * np.einsum( "mlc,lncd->mncd", self.D.nl(ik, inn, out)[:, :, a], self.dB.ln(ik, inn, out)[:, :, b, :]) summ += -2 * s * np.einsum( "mlc,lncd->mncd", (self.B.ln(ik, inn, out)[:, :, a]).transpose(1, 0, 2).conj(), self.dD.ln(ik, inn, out)[:, :, b, :]) return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
@property def additive(self): return False
[docs] class DerMorb(Formula_ln): def __init__(self, data_K, sign=+1, **parameters): super().__init__(data_K, **parameters) self.dermorb_H = DerMorb_H(data_K, **parameters) self.sign = sign if self.sign != 0: self.V = data_K.covariant('Ham', commader=1) self.dO = DerOmega(data_K, **parameters) self.O = Omega(data_K, **parameters) self.E = data_K.E_K self.ndim = 2 self.transformTR = transform_ident self.transformInv = transform_odd
[docs] def nn(self, ik, inn, out): res = self.dermorb_H.nn(ik, inn, out) if self.sign != 0: res += self.sign * np.einsum("mlc,lnd->mncd", self.O.nn(ik, inn, out), self.V.nn(ik, inn, out)) res += self.sign * self.E[ik][inn][:, None, None, None] * self.dO.nn(ik, inn, out) return res
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
@property def additive(self): return False
[docs] class Dermorb(DerMorb): def __init__(self, data_K, **parameters): super().__init__(data_K, sign=-1, **parameters)
############################## ### second derivative of #### ### orbital moment #### ##############################
[docs] class Der2Morb_H(Formula_ln): def __init__(self, data_K, **parameters): super().__init__(data_K, **parameters) self.ddD = Der2Dcov(data_K) self.dD = DerDcov(data_K) self.D = Dcov(data_K) self.dV = InvMass(data_K) self.V = data_K.covariant('Ham', commader=1) self.E = data_K.E_K if self.external_terms: self.A = data_K.covariant('AA') self.dA = data_K.covariant('AA', gender=1) self.ddA = Der2A(data_K) self.B = data_K.covariant('BB') self.dB = data_K.covariant('BB', gender=1) self.ddB = Der2B(data_K) self.dH = data_K.covariant('CC', gender=1) self.ddH = Der2H(data_K) self.ndim = 3 self.transformTR = transform_odd self.transformInv = transform_ident # TODO merge term if possible.
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3, 3), dtype=complex) if self.internal_terms: summ += -2j * np.einsum("mpc,plde,lnc->mncde", self.D.nl(ik, inn, out)[:, :, alpha_A], self.dV.ll(ik, inn, out), self.D.ln(ik, inn, out)[:, :, beta_A]) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): summ += -1j * s * np.einsum("mpce,pld,lnc->mncde", self.dD.nl(ik, inn, out)[:, :, a, :], self.V.ll(ik, inn, out), self.D.ln(ik, inn, out)[:, :, b]) summ += -1j * s * np.einsum("mpc,pld,lnce->mncde", self.D.nl(ik, inn, out)[:, :, a], self.V.ll(ik, inn, out), self.dD.ln(ik, inn, out)[:, :, b, :]) summ += -2j * s * np.einsum("mlce,lncd->mncde", self.dD.nl(ik, inn, out)[:, :, a, :], self.E[ik][out][:, None, None, None] * self.dD.ln(ik, inn, out)[:, :, b]) summ += -2j * s * np.einsum("mlc,lncde->mncde", self.D.nl(ik, inn, out)[:, :, a], self.E[ik][out][:, None, None, None, None] * self.ddD.ln(ik, inn, out)[:, :, b]) summ += -2j * s * np.einsum("mpc,ple,lncd->mncde", self.D.nl(ik, inn, out)[:, :, a], self.V.ll(ik, inn, out), self.dD.ln(ik, inn, out)[:, :, b]) if self.external_terms: summ += 1 * self.ddH.nn(ik, inn, out) summ += -2j * np.einsum("mpc,plde,lnc->mncde", self.A.nn(ik, inn, out)[:, :, alpha_A], self.dV.nn(ik, inn, out), self.A.nn(ik, inn, out)[:, :, beta_A]) for s, a, b in (+1, alpha_A, beta_A), (-1, beta_A, alpha_A): summ += -1j * np.einsum("mpce,pld,lnc->mncde", self.dA.nn(ik, inn, out)[:, :, a], self.V.nn(ik, inn, out), self.A.nn(ik, inn, out)[:, :, b]) summ += -1j * np.einsum("mpc,pld,lnce->mncde", self.A.nn(ik, inn, out)[:, :, a], self.V.nn(ik, inn, out), self.dA.nn(ik, inn, out)[:, :, b]) summ += -2j * s * np.einsum("mlce,lncd->mncde", self.dA.nn(ik, inn, out)[:, :, a] * self.E[ik][inn][None, :, None, None], self.dA.nn(ik, inn, out)[:, :, b]) summ += -2j * s * np.einsum("mlc,lncde->mncde", self.A.nn(ik, inn, out)[:, :, a] * self.E[ik][inn][None, :, None], self.ddA.nn(ik, inn, out)[:, :, b]) summ += -2j * s * np.einsum("mlc,ple,lncd->mncde", self.A.nn(ik, inn, out)[:, :, a], self.V.nn(ik, inn, out), self.dA.nn(ik, inn, out)[:, :, b]) summ += -2 * s * np.einsum("mlce,lncd->mncde", self.dD.nl(ik, inn, out)[:, :, a], self.dB.ln(ik, inn, out)[:, :, b, :]) summ += -2 * s * np.einsum("mlc,lncde->mncde", self.D.nl(ik, inn, out)[:, :, a], self.ddB.ln(ik, inn, out)[:, :, b, :]) summ += -2 * s * np.einsum("mlce,lncd->mncde", (self.dB.ln(ik, inn, out)[:, :, a]).transpose(1, 0, 2, 3).conj(), self.dD.ln(ik, inn, out)[:, :, b]) summ += -2 * s * np.einsum("mlc,lncde->mncde", (self.B.ln(ik, inn, out)[:, :, a]).transpose(1, 0, 2).conj(), self.ddD.ln(ik, inn, out)[:, :, b]) return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
@property def additive(self): return False
[docs] class Der2Morb(Formula_ln): def __init__(self, data_K, sign=+1, **parameters): super().__init__(data_K, **parameters) self.der2morb_H = Der2Morb_H(data_K, **parameters) self.sign = sign if self.sign != 0: self.V = data_K.covariant('Ham', commader=1) self.dV = InvMass(data_K) self.dO = DerOmega(data_K, **parameters) self.ddO = Der2Omega(data_K, **parameters) self.O = Omega(data_K, **parameters) self.E = data_K.E_K self.ndim = 3 self.transformTR = transform_odd self.transformInv = transform_ident @property def additive(self): return False
[docs] def nn(self, ik, inn, out): res = self.der2morb_H.nn(ik, inn, out) if self.sign != 0: res += self.sign * np.einsum("mlce,lnd->mncde", self.dO.nn(ik, inn, out), self.V.nn(ik, inn, out)) res += self.sign * np.einsum("mlc,lnde->mncde", self.O.nn(ik, inn, out), self.dV.nn(ik, inn, out)) res += self.sign * np.einsum("mle,lncd->mncde", self.V.nn(ik, inn, out), self.dO.nn(ik, inn, out)) res += self.sign * self.E[ik][inn][:, None, None, None, None] * self.ddO.nn(ik, inn, out) return res
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
[docs] class Der2morb(Der2Morb): def __init__(self, data_K, **parameters): super().__init__(data_K, sign=-1, **parameters)
######################## # spin transport # ######################## def _spin_velocity_einsum_opt(C, A, B): # Optimized version of C += np.einsum('knls,klma->knmas', A, B). Used in shc_B_H. nk = C.shape[0] nw = C.shape[1] for ik in range(nk): # Performing C[ik] += np.einsum('nls,lma->nmas', A[ik], B[ik]) tmp_a = np.swapaxes(A[ik], 1, 2) # nls -> nsl tmp_a = np.reshape(tmp_a, (nw * 3, nw)) # nsl -> (ns)l tmp_b = np.reshape(B[ik], (nw, nw * 3)) # lma -> l(ma) tmp_c = tmp_a @ tmp_b # (ns)l, l(ma) -> (ns)(ma) tmp_c = np.reshape(tmp_c, (nw, 3, nw, 3)) # (ns)(ma) -> nsma C[ik] += np.transpose(tmp_c, (0, 2, 3, 1)) # nsma -> nmas
[docs] class SpinVelocity(Matrix_ln): """spin current matrix elements. SpinVelocity.matrix[ik, m, n, a, s] = <u_mk|{v^a S^s}|u_nk> / 2""" def __init__(self, data_K, spin_current_type, external_terms=True): if spin_current_type == "simple": # tight-binding case super().__init__(self._J_H_simple(data_K, external_terms=external_terms)) elif spin_current_type == "qiao": # J. Qiao et al PRB (2018) super().__init__(self._J_H_qiao(data_K, external_terms=external_terms)) elif spin_current_type == "ryoo": # J. H. Ryoo et al PRB (2019) super().__init__(self._J_H_ryoo(data_K, external_terms=external_terms)) else: raise ValueError(f"spin_current_type must be `qiao` or `ryoo` or `simple`, not {spin_current_type}") self.transformTR = transform_ident self.transformInv = transform_odd def _J_H_simple(self, data_K, external_terms=True): # Spin current operator, J. Qiao et al PRB (2019) # J_H[k,m,n,a,s] = <mk| {S^s, v^a} |nk> / 2 S = data_K.Xbar('SS') V = Velocity(data_K, external_terms=external_terms).matrix J = np.einsum("klms,kmna->klnas", S, V) return (J + J.swapaxes(1, 2).conj()) / 2 def _J_H_qiao(self, data_K, external_terms=True): if not external_terms: raise NotImplementedError( "spin Hall qiao without external terms is not implemented yet. Use `SHC_type='simple'`") # Spin current operator, J. Qiao et al PRB (2019) # J_H_qiao[k,m,n,a,s] = <mk| {S^s, v^a} |nk> / 2 SS_H = data_K.Xbar('SS') SH_H = data_K.Xbar("SH") shc_K_H = -1j * data_K.Xbar("SR") _spin_velocity_einsum_opt(shc_K_H, SS_H, data_K.D_H) shc_L_H = -1j * data_K._R_to_k_H(data_K.get_R_mat('SHR'), hermitian=False) _spin_velocity_einsum_opt(shc_L_H, SH_H, data_K.D_H) J = ( data_K.delE_K[:, None, :, :, None] * SS_H[:, :, :, None, :] + data_K.E_K[:, None, :, None, None] * shc_K_H[:, :, :, :, :] - shc_L_H) return (J + J.swapaxes(1, 2).conj()) / 2 def _J_H_ryoo(self, data_K, external_terms=True): if not external_terms: raise NotImplementedError( "spin Hall ryoo without external terms is not implemented yet. Use `SHC_type='simple'`") # Spin current operator, J. H. Ryoo et al PRB (2019) # J_H_ryoo[k,m,n,a,s] = <mk| {S^s, v^a} |nk> / 2 SA_H = data_K.Xbar("SA") SHA_H = data_K.Xbar("SHA") J = -1j * (data_K.E_K[:, None, :, None, None] * SA_H - SHA_H) _spin_velocity_einsum_opt(J, data_K.Xbar('SS'), data_K.Xbar('Ham', 1)) return (J + J.swapaxes(1, 2).conj()) / 2
[docs] class SpinOmega(Formula_ln): """spin Berry curvature""" def __init__(self, data_K, spin_current_type="ryoo", **parameters): super().__init__(data_K, **parameters) if self.external_terms: self.A = data_K.covariant('AA') self.D = data_K.Dcov self.J = SpinVelocity(data_K, spin_current_type, external_terms=self.external_terms) self.dEinv = DEinv_ln(data_K) self.ndim = 3 self.transformTR = transform_ident self.transformInv = transform_ident
[docs] def nn(self, ik, inn, out): summ = np.zeros((len(inn), len(inn), 3, 3, 3), dtype=complex) # v_over_de[l,n,b] = v[l,n,b] / (e[n] - e[l]) = D[l,n,b] - 1j * A[l,n,b] v_over_de = self.D.ln(ik, inn, out) if self.external_terms: v_over_de += - 1j * self.A.ln(ik, inn, out) # j_over_de[m,l,a,s] = j[m,l,a,s] / (e[m] - e[l]) j_over_de = self.J.nl(ik, inn, out) * self.dEinv.nl(ik, inn, out)[:, :, None, None] summ += -2 * np.einsum("mlas,lnb->mnabs", j_over_de, v_over_de).imag return summ
[docs] def ln(self, ik, inn, out): raise NotImplementedError()
#################################### # # # Some Prooducts # # # ####################################
[docs] class VelOmega(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), Omega(data_K, **kwargs_formula)], name='VelOmega')
[docs] class VelHplus(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), Morb_Hpm(data_K, sign=+1, **kwargs_formula)], name='VelHplus')
[docs] class VelSpin(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), Spin(data_K)], name='VelSpin')
[docs] class VelVel(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), data_K.covariant('Ham', commader=1)], name='VelVel')
[docs] class VelVelVel(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), data_K.covariant('Ham', commader=1), data_K.covariant('Ham', commader=1)], name='VelVelVel')
[docs] class MassVel(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([InvMass(data_K), data_K.covariant('Ham', commader=1)], name='MassVel')
[docs] class MassMass(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([InvMass(data_K), InvMass(data_K)], name='MassMass')
[docs] class VelMassVel(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([data_K.covariant('Ham', commader=1), InvMass(data_K), data_K.covariant('Ham', commader=1)], name='VelMassVel')
[docs] class OmegaS(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([Omega(data_K, **kwargs_formula), Spin(data_K)], name='SpinOmega')
[docs] class OmegaOmega(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([Omega(data_K, **kwargs_formula), Omega(data_K, **kwargs_formula)], name='OmegaOmega')
[docs] class OmegaHplus(FormulaProduct): def __init__(self, data_K, **kwargs_formula): super().__init__([Omega(data_K, **kwargs_formula), Morb_Hpm(data_K, sign=+1, **kwargs_formula)], name='OmegaHplus')
[docs] class emcha_surf(FormulaSum): def __init__(self, data_K, **kwargs_formula): velocity = data_K.covariant('Ham', commader=1) formula1 = FormulaProduct([InvMass(data_K), Omega(data_K, **kwargs_formula), velocity], name='mass-berry-vel (apus)(psua) ([au]bpbs) ([us]abbp)') formula2 = FormulaProduct([velocity, DerOmega(data_K, **kwargs_formula), velocity], name='v-derberry-vel (aups) ([au]bbps) ([us]abpb)') tmp = FormulaSum([formula2, formula1], [1, 1], ['aups', 'apus']) super().__init__([ tmp, DeltaProduct(delta_f, formula1, 'us,MLabbp->MLaups'), DeltaProduct(delta_f, tmp, 'au,MLbbps->MLaups'), DeltaProduct(delta_f, formula2, 'us,MLabpb->MLaups'), formula2, # romove antisymmatric part # DeltaProduct(Levi_Civita # DeltaProduct(Levi_Civita,tmp,'pta,MLxtbs->MLaxpbs'), # 'xub,MLaxpbs->MLaups') ], # [2,-2,-1,1,-1,-1],['aups','aups','aups','aups','aups','aups']) [2, -2, -1, 1, -1], ['aups', 'aups', 'aups', 'aups', 'aups'])
[docs] class NLDrude_Z_spin(FormulaSum): def __init__(self, data_K, **kwargs_formula): term1 = FormulaProduct([Der3E(data_K), Spin(data_K)], name='Der3ESpin') term2 = FormulaProduct([Der2Spin(data_K), data_K.covariant('Ham', commader=1)], name='Der2SpinVel') super().__init__([term1, term2], [-1, 1], ['apsu', 'uaps'])
[docs] class NLDrude_Z_orb_Hplus(FormulaSum): def __init__(self, data_K, **kwargs_formula): term1 = FormulaProduct([Der3E(data_K), Morb_Hpm(data_K, sign=+1, **kwargs_formula)], name='Der3EHplus') term2 = FormulaProduct([Der2Morb(data_K, **kwargs_formula), data_K.covariant('Ham', commader=1)], name='Der2HplusVel') super().__init__([term1, term2], [-1, 1], ['apsu', 'uaps'])
[docs] class NLDrude_Z_orb_Omega(FormulaSum): def __init__(self, data_K, **kwargs_formula): term1 = FormulaProduct([Der3E(data_K), Omega(data_K, **kwargs_formula)], name='Der3EOmega') term2 = FormulaProduct([Der2Omega(data_K, **kwargs_formula), data_K.covariant('Ham', commader=1)], name='Der2OmegaVel') super().__init__([term1, term2], [-1, 1], ['apsu', 'uaps'])