Exemple #1
0
 def rotate_matrix(self, A_o, A_MM):
     assert A_o.ndim == 1
     A_ww = dots(self.U_ow.T.conj() * A_o, self.V_oM, self.U_Mw)
     A_ww += np.conj(A_ww.T)
     A_ww += np.dot(self.U_ow.T.conj() * A_o, self.U_ow)
     A_ww += dots(self.U_Mw.T.conj(), A_MM, self.U_Mw)
     return A_ww
Exemple #2
0
def get_lcao_xc(calc, P_aqMi, bfs=None, spin=0):
    nq = len(calc.wfs.ibzk_qc)
    nao = calc.wfs.setups.nao
    dtype = calc.wfs.dtype
    if bfs is None:
        bfs = get_bfs(calc)

    if calc.density.nt_sg is None:
        calc.density.interpolate()
    nt_sg = calc.density.nt_sg
    vxct_sg = calc.density.finegd.zeros(calc.wfs.nspins)
    calc.hamiltonian.xc.calculate(calc.density.finegd, nt_sg, vxct_sg)
    vxct_G = calc.wfs.gd.zeros()
    calc.hamiltonian.restrict(vxct_sg[spin], vxct_G)
    Vxc_qMM = np.zeros((nq, nao, nao), dtype)
    for q, Vxc_MM in enumerate(Vxc_qMM):
        bfs.calculate_potential_matrix(vxct_G, Vxc_MM, q)
        tri2full(Vxc_MM, "L")

    # Add atomic PAW corrections
    for a, P_qMi in P_aqMi.items():
        D_sp = calc.density.D_asp[a][:]
        H_sp = np.zeros_like(D_sp)
        calc.wfs.setups[a].xc_correction.calculate(calc.hamiltonian.xc, D_sp, H_sp)
        H_ii = unpack(H_sp[spin])
        for Vxc_MM, P_Mi in zip(Vxc_qMM, P_qMi):
            Vxc_MM += dots(P_Mi, H_ii, P_Mi.T.conj())
    return Vxc_qMM * Hartree
Exemple #3
0
 def get_Fcore(self, q=0, indices=None):
     if indices is None:
         Fcore_ww = np.zeros_like(self.H_qww[q])
     else:
         Fcore_ww = np.zeros((len(indices), len(indices)))
     for a, P_wi in self.get_projections(q, indices).items():
         X_ii = unpack(self.calc.wfs.setups[a].X_p)
         Fcore_ww -= dots(P_wi, X_ii, P_wi.T.conj())
     return Fcore_ww * Hartree
Exemple #4
0
 def get_Fcore(self, q=0, indices=None):
     if indices is None:
         Fcore_ww = np.zeros_like(self.H_qww[q])
     else:
         Fcore_ww = np.zeros((len(indices), len(indices)))
     for a, P_wi in self.get_projections(q, indices).items():
         X_ii = unpack(self.calc.wfs.setups[a].X_p)
         Fcore_ww -= dots(P_wi, X_ii, P_wi.T.conj())
     return Fcore_ww * Hartree
Exemple #5
0
def get_rot(F_MM, V_oM, L):
    eps_M, U_MM = np.linalg.eigh(F_MM)
    indices = eps_M.real.argsort()[-L:]
    U_Ml = U_MM[:, indices]
    U_Ml /= np.sqrt(dots(U_Ml.T.conj(), F_MM, U_Ml).diagonal())

    U_ow = V_oM.copy()
    U_lw = np.dot(U_Ml.T.conj(), F_MM)
    for col1, col2 in zip(U_ow.T, U_lw.T):
        norm = np.linalg.norm(np.hstack((col1, col2)))
        col1 /= norm
        col2 /= norm
    return U_ow, U_lw, U_Ml
Exemple #6
0
def get_rot(F_MM, V_oM, L):
    eps_M, U_MM = np.linalg.eigh(F_MM)
    indices = eps_M.real.argsort()[-L:]
    U_Ml = U_MM[:, indices]
    U_Ml /= np.sqrt(dots(U_Ml.T.conj(), F_MM, U_Ml).diagonal())

    U_ow = V_oM.copy()
    U_lw = np.dot(U_Ml.T.conj(), F_MM)
    for col1, col2 in zip(U_ow.T, U_lw.T):
        norm = np.linalg.norm(np.hstack((col1, col2)))
        col1 /= norm
        col2 /= norm
    return U_ow, U_lw, U_Ml
Exemple #7
0
    def __init__(self, V_nM, No, ortho=False):
        Nw = V_nM.shape[1]
        assert No <= Nw

        V_oM, V_uM = V_nM[:No], V_nM[No:]
        F_MM = np.dot(V_uM.T.conj(), V_uM)
        U_ow, U_lw, U_Ml = get_rot(F_MM, V_oM, Nw - No)
        self.U_nw = np.vstack((U_ow, dots(V_uM, U_Ml, U_lw)))

        # stop here ?? XXX
        self.S_ww = self.rotate_matrix(np.ones(1))
        if ortho:
            lowdin(self.U_nw, self.S_ww)
            self.S_ww = np.identity(Nw)
        self.norms_n = np.dot(self.U_nw, np.linalg.solve(self.S_ww, self.U_nw.T.conj())).diagonal()
Exemple #8
0
    def __init__(self, V_nM, No, ortho=False):
        Nw = V_nM.shape[1]
        assert No <= Nw
        
        V_oM, V_uM = V_nM[:No], V_nM[No:]
        F_MM = np.dot(V_uM.T.conj(), V_uM)
        U_ow, U_lw, U_Ml = get_rot(F_MM, V_oM, Nw - No)
        self.U_nw = np.vstack((U_ow, dots(V_uM, U_Ml, U_lw)))

        # stop here ?? XXX
        self.S_ww = self.rotate_matrix(np.ones(1))
        if ortho:
            lowdin(self.U_nw, self.S_ww)
            self.S_ww = np.identity(Nw)
        self.norms_n = np.dot(self.U_nw, np.linalg.solve(
            self.S_ww, self.U_nw.T.conj())).diagonal()
Exemple #9
0
def get_xc2(calc, w_wG, P_awi, spin=0):
    if calc.density.nt_sg is None:
        calc.density.interpolate()
    nt_g = calc.density.nt_sg[spin]
    vxct_g = calc.density.finegd.zeros()
    calc.hamiltonian.xc.get_energy_and_potential(nt_g, vxct_g)
    vxct_G = calc.wfs.gd.empty()
    calc.hamiltonian.restrict(vxct_g, vxct_G)

    # Integrate pseudo part
    Nw = len(w_wG)
    xc_ww = np.empty((Nw, Nw))
    r2k(0.5 * calc.wfs.gd.dv, w_wG, vxct_G * w_wG, 0.0, xc_ww)
    tri2full(xc_ww, "L")

    # Add atomic PAW corrections
    for a, P_wi in P_awi.items():
        D_sp = calc.density.D_asp[a][:]
        H_sp = np.zeros_like(D_sp)
        calc.wfs.setups[a].xc_correction.calculate_energy_and_derivatives(D_sp, H_sp)
        H_ii = unpack(H_sp[spin])
        xc_ww += dots(P_wi, H_ii, P_wi.T.conj())
    return xc_ww * Hartree
Exemple #10
0
def get_xc2(calc, w_wG, P_awi, spin=0):
    if calc.density.nt_sg is None:
        calc.density.interpolate_pseudo_density()
    nt_g = calc.density.nt_sg[spin]
    vxct_g = calc.density.finegd.zeros()
    calc.hamiltonian.xc.get_energy_and_potential(nt_g, vxct_g)
    vxct_G = calc.wfs.gd.empty()
    calc.hamiltonian.restrict_and_collect(vxct_g, vxct_G)

    # Integrate pseudo part
    Nw = len(w_wG)
    xc_ww = np.empty((Nw, Nw))
    r2k(.5 * calc.wfs.gd.dv, w_wG, vxct_G * w_wG, .0, xc_ww)
    tri2full(xc_ww, 'L')

    # Add atomic PAW corrections
    for a, P_wi in P_awi.items():
        D_sp = calc.density.D_asp[a][:]
        H_sp = np.zeros_like(D_sp)
        calc.wfs.setups[a].xc_correction.calculate_energy_and_derivatives(
            D_sp, H_sp)
        H_ii = unpack(H_sp[spin])
        xc_ww += dots(P_wi, H_ii, P_wi.T.conj())
    return xc_ww * Hartree
Exemple #11
0
 def rotate_matrix(self, A_nn):
     if A_nn.ndim == 1:
         return np.dot(self.U_nw.T.conj() * A_nn, self.U_nw)
     else:
         return dots(self.U_nw.T.conj(), A_nn, self.U_nw)
Exemple #12
0
 def rotate_matrix(self, A_nn):
     if A_nn.ndim == 1:
         return np.dot(self.U_nw.T.conj() * A_nn, self.U_nw)
     else:
         return dots(self.U_nw.T.conj(), A_nn, self.U_nw)
Exemple #13
0
    def get_M(self, modes, log=None, q=0):
        """Calculate el-ph coupling matrix for given modes(s).

        XXX:
        kwarg "q=0" is an ugly hack for k-points.
        There shuold be loops over q!

        Note that modes must be given as a dictionary with mode
        frequencies in eV and corresponding mode vectors in units
        of 1/sqrt(amu), where amu = 1.6605402e-27 Kg is an atomic mass unit.
        In short frequencies and mode vectors must be given in ase units.

        ::

                  d                   d  ~
            < w | -- v | w' > = < w | -- v | w'>
                  dP                  dP

                               _
                              \        ~a     d   .       ~a
                            +  ) < w | p  >   -- /_\H   < p | w' >
                              /_        i     dP     ij    j
                              a,ij

                               _
                              \        d  ~a     .        ~a
                            +  ) < w | -- p  >  /_\H    < p | w' >
                              /_       dP  i        ij     j
                              a,ij

                               _
                              \        ~a     .        d  ~a
                            +  ) < w | p  >  /_\H    < -- p  | w' >
                              /_        i        ij    dP  j
                              a,ij

        """
        if log is None:
            timer = nulltimer
        elif log == '-':
            timer = StepTimer(name='EPCM')
        else:
            timer = StepTimer(name='EPCM', out=open(log, 'w'))

        modes1 = modes.copy()
        #convert to atomic units
        amu = 1.6605402e-27  # atomic unit mass [Kg]
        me = 9.1093897e-31  # electron mass    [Kg]
        modes = {}
        for k in modes1.keys():
            modes[k / Hartree] = modes1[k] / np.sqrt(amu / me)

        dvt_Gx, ddH_aspx = self.get_gradient()

        from gpaw import restart
        atoms, calc = restart('eq.gpw', txt=None)
        if calc.wfs.S_qMM is None:
            calc.initialize(atoms)
            calc.initialize_positions(atoms)

        wfs = calc.wfs
        nao = wfs.setups.nao
        bfs = wfs.basis_functions
        dtype = wfs.dtype
        spin = 0  # XXX

        M_lii = {}
        timer.write_now('Starting gradient of pseudo part')
        for f, mode in modes.items():
            mo = []
            M_ii = np.zeros((nao, nao), dtype)
            for a in self.indices:
                mo.append(mode[a])
            mode = np.asarray(mo).flatten()
            dvtdP_G = np.dot(dvt_Gx, mode)
            bfs.calculate_potential_matrix(dvtdP_G, M_ii, q=q)
            tri2full(M_ii, 'L')
            M_lii[f] = M_ii
        timer.write_now('Finished gradient of pseudo part')

        P_aqMi = calc.wfs.P_aqMi
        # Add the term
        #  _
        # \        ~a     d   .       ~a
        #  ) < w | p  >   -- /_\H   < p | w' >
        # /_        i     dP     ij    j
        # a,ij

        Ma_lii = {}
        for f, mode in modes.items():
            Ma_lii[f] = np.zeros_like(M_lii.values()[0])

        timer.write_now('Starting gradient of dH^a part')
        for f, mode in modes.items():
            mo = []
            for a in self.indices:
                mo.append(mode[a])
            mode = np.asarray(mo).flatten()

            for a, ddH_spx in ddH_aspx.items():
                ddHdP_sp = np.dot(ddH_spx, mode)
                ddHdP_ii = unpack2(ddHdP_sp[spin])
                Ma_lii[f] += dots(P_aqMi[a][q], ddHdP_ii, P_aqMi[a][q].T)
        timer.write_now('Finished gradient of dH^a part')

        timer.write_now('Starting gradient of projectors part')
        dP_aMix = self.get_dP_aMix(calc.spos_ac, wfs, q, timer)
        timer.write_now('Finished gradient of projectors part')

        dH_asp = pickle.load(open('v.eq.pckl', 'rb'))[1]

        Mb_lii = {}
        for f, mode in modes.items():
            Mb_lii[f] = np.zeros_like(M_lii.values()[0])

        for f, mode in modes.items():
            for a, dP_Mix in dP_aMix.items():
                dPdP_Mi = np.dot(dP_Mix, mode[a])
                dH_ii = unpack2(dH_asp[a][spin])
                dPdP_MM = dots(dPdP_Mi, dH_ii, P_aqMi[a][q].T)
                Mb_lii[f] -= dPdP_MM + dPdP_MM.T
                # XXX The minus sign here is quite subtle.
                # It is related to how the derivative of projector
                # functions in GPAW is calculated.
                # More thorough explanations, anyone...?

        # Units of M_lii are Hartree/(Bohr * sqrt(m_e))
        for mode in M_lii.keys():
            M_lii[mode] += Ma_lii[mode] + Mb_lii[mode]

        # conversion to eV. The prefactor 1 / sqrt(hb^2 / 2 * hb * f)
        # has units Bohr * sqrt(me)
        M_lii_1 = M_lii.copy()
        M_lii = {}

        for f in M_lii_1.keys():
            M_lii[f * Hartree] = M_lii_1[f] * Hartree / np.sqrt(2 * f)

        return M_lii
Exemple #14
0
    def get_M(self, modes, log=None, q=0):
        """Calculate el-ph coupling matrix for given modes(s).

        XXX:
        kwarg "q=0" is an ugly hack for k-points.
        There shuold be loops over q!

        Note that modes must be given as a dictionary with mode
        frequencies in eV and corresponding mode vectors in units
        of 1/sqrt(amu), where amu = 1.6605402e-27 Kg is an atomic mass unit.
        In short frequencies and mode vectors must be given in ase units.

        ::
        
                  d                   d  ~
            < w | -- v | w' > = < w | -- v | w'>
                  dP                  dP

                               _
                              \        ~a     d   .       ~a
                            +  ) < w | p  >   -- /_\H   < p | w' >
                              /_        i     dP     ij    j
                              a,ij

                               _
                              \        d  ~a     .        ~a
                            +  ) < w | -- p  >  /_\H    < p | w' >
                              /_       dP  i        ij     j
                              a,ij

                               _
                              \        ~a     .        d  ~a
                            +  ) < w | p  >  /_\H    < -- p  | w' >
                              /_        i        ij    dP  j
                              a,ij

        """
        if log is None:
            timer = nulltimer
        elif log == '-':
            timer = StepTimer(name='EPCM')
        else:
            timer = StepTimer(name='EPCM', out=open(log, 'w'))

        modes1 = modes.copy()
        #convert to atomic units
        amu = 1.6605402e-27 # atomic unit mass [Kg]
        me = 9.1093897e-31  # electron mass    [Kg]
        modes = {}
        for k in modes1.keys():        
            modes[k / Hartree] = modes1[k] / np.sqrt(amu / me)

        dvt_Gx, ddH_aspx = self.get_gradient()

        from gpaw import restart
        atoms, calc = restart('eq.gpw', txt=None)
        spos_ac = atoms.get_scaled_positions()
        if calc.wfs.S_qMM is None:
            calc.initialize(atoms)
            calc.initialize_positions(atoms)

        wfs = calc.wfs
        nao = wfs.setups.nao
        bfs = wfs.basis_functions
        dtype = wfs.dtype
        spin = 0 # XXX

        M_lii = {}
        timer.write_now('Starting gradient of pseudo part')
        for f, mode in modes.items():
            mo = []    
            M_ii = np.zeros((nao, nao), dtype)
            for a in self.indices:
                mo.append(mode[a])
            mode = np.asarray(mo).flatten()
            dvtdP_G = np.dot(dvt_Gx, mode)   
            bfs.calculate_potential_matrix(dvtdP_G, M_ii, q=q)
            tri2full(M_ii, 'L')
            M_lii[f] = M_ii               
        timer.write_now('Finished gradient of pseudo part')

        P_aqMi = calc.wfs.P_aqMi
        # Add the term
        #  _
        # \        ~a     d   .       ~a
        #  ) < w | p  >   -- /_\H   < p | w' >
        # /_        i     dP     ij    j
        # a,ij

        Ma_lii = {}
        for f, mode in modes.items():
            Ma_lii[f] = np.zeros_like(M_lii.values()[0])
        
        timer.write_now('Starting gradient of dH^a part')
        for f, mode in modes.items():
            mo = []
            for a in self.indices:
                mo.append(mode[a])
            mode = np.asarray(mo).flatten()
            
            for a, ddH_spx in ddH_aspx.items():
                ddHdP_sp = np.dot(ddH_spx, mode)
                ddHdP_ii = unpack2(ddHdP_sp[spin])
                Ma_lii[f] += dots(P_aqMi[a][q], ddHdP_ii, P_aqMi[a][q].T)
        timer.write_now('Finished gradient of dH^a part')

        timer.write_now('Starting gradient of projectors part')
        spos_ac = self.atoms.get_scaled_positions() % 1.0
        dP_aMix = self.get_dP_aMix(spos_ac, wfs, q, timer)
        timer.write_now('Finished gradient of projectors part')

        dH_asp = pickle.load(open('v.eq.pckl'))[1]
        
        Mb_lii = {}
        for f, mode in modes.items():
            Mb_lii[f] = np.zeros_like(M_lii.values()[0])

        for f, mode in modes.items():
            for a, dP_Mix in dP_aMix.items():
                dPdP_Mi = np.dot(dP_Mix, mode[a])
                dH_ii = unpack2(dH_asp[a][spin])    
                dPdP_MM = dots(dPdP_Mi, dH_ii, P_aqMi[a][q].T)
                Mb_lii[f] -= dPdP_MM + dPdP_MM.T 
                # XXX The minus sign here is quite subtle.
                # It is related to how the derivative of projector
                # functions in GPAW is calculated.
                # More thorough explanations, anyone...?
                
        # Units of M_lii are Hartree/(Bohr * sqrt(m_e))
        for mode in M_lii.keys():
            M_lii[mode] += Ma_lii[mode] + Mb_lii[mode]

        # conversion to eV. The prefactor 1 / sqrt(hb^2 / 2 * hb * f)
        # has units Bohr * sqrt(me)
        M_lii_1 = M_lii.copy()
        M_lii = {}

        for f in M_lii_1.keys():
            M_lii[f * Hartree] =  M_lii_1[f] * Hartree / np.sqrt(2 * f)

        return M_lii