Example #1
0
def test_selfenergy_interpolation(atoms, ntk, filename, begin, end, base, scale, direction=0):
    from gpaw.transport.sparse_matrix import Banded_Sparse_HSD, CP_Sparse_HSD, Se_Sparse_Matrix
    from gpaw.transport.selfenergy import LeadSelfEnergy
    from gpaw.transport.contour import Contour
    hl_skmm, sl_kmm = get_hs(atoms)
    dl_skmm = get_lcao_density_matrix(atoms.calc)
    fermi = atoms.calc.get_fermi_level()
    wfs = atoms.calc.wfs
    hl_spkmm, sl_pkmm, dl_spkmm,  \
    hl_spkcmm, sl_pkcmm, dl_spkcmm = get_pk_hsd(2, ntk,
                                                wfs.kd.ibzk_qc,
                                                hl_skmm, sl_kmm, dl_skmm,
                                                None, wfs.dtype,
                                                direction=direction)    
    my_npk = len(wfs.kd.ibzk_qc) / ntk
    my_nspins = len(wfs.kpt_u) / ( my_npk * ntk)
    
    lead_hsd = Banded_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    lead_couple_hsd = CP_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    for pk in range(my_npk):
        lead_hsd.reset(0, pk, sl_pkmm[pk], 'S', init=True)
        lead_couple_hsd.reset(0, pk, sl_pkcmm[pk], 'S', init=True)
        for s in range(my_nspins):
            lead_hsd.reset(s, pk, hl_spkmm[s, pk], 'H', init=True)     
            lead_hsd.reset(s, pk, dl_spkmm[s, pk], 'D', init=True)
            lead_couple_hsd.reset(s, pk, hl_spkcmm[s, pk], 'H', init=True)     
            lead_couple_hsd.reset(s, pk, dl_spkcmm[s, pk], 'D', init=True)          
    lead_se = LeadSelfEnergy(lead_hsd, lead_couple_hsd)
    begin += fermi
    end += fermi
    
    ee = np.linspace(begin, end, base)
    cmp_ee = np.linspace(begin, end, base * scale)
  
    se = []
    cmp_se = []
    from scipy import interpolate

    for e in ee:
        se.append(lead_se(e).recover())
    se = np.array(se)
    ne, ny, nz= se.shape
    nie = len(cmp_ee)
    data = np.zeros([nie, ny, nz], se.dtype)
    for yy in range(ny):
        for zz in range(nz):
            ydata = se[:, yy, zz]
            f = interpolate.interp1d(ee, ydata)
            data[:, yy, zz] = f(cmp_ee)
    inter_se_linear = data
    
    for e in cmp_ee:
        cmp_se.append(lead_se(e).recover())
    
    fd = file(filename, 'w')
    cPickle.dump((cmp_se, inter_se_linear, ee, cmp_ee), fd, 2)
    fd.close()
    
    for i,e in enumerate(cmp_ee):
        print(e, np.max(abs(cmp_se[i] - inter_se_linear[i])), 'linear', np.max(abs(cmp_se[i])))
Example #2
0
    def initialize_selfenergy_and_green_function(self, tp):
        self.selfenergies = []
        if tp.use_lead:
            for i in range(tp.lead_num):
                self.selfenergies.append(
                    LeadSelfEnergy(tp.lead_hsd[i], tp.lead_couple_hsd[i]))

                self.selfenergies[i].set_bias(tp.bias[i])
Example #3
0
def generate_selfenergy_database(atoms,
                                 ntk,
                                 filename,
                                 direction=0,
                                 kt=0.1,
                                 bias=[-3, 3],
                                 depth=3,
                                 comm=None):
    from gpaw.transport.sparse_matrix import Banded_Sparse_HSD, CP_Sparse_HSD, Se_Sparse_Matrix
    from gpaw.transport.selfenergy import LeadSelfEnergy
    from gpaw.transport.contour import Contour
    hl_skmm, sl_kmm = get_hs(atoms)
    dl_skmm = get_lcao_density_matrix(atoms.calc)
    fermi = atoms.calc.get_fermi_level()
    wfs = atoms.calc.wfs
    hl_spkmm, sl_pkmm, dl_spkmm,  \
    hl_spkcmm, sl_pkcmm, dl_spkcmm = get_pk_hsd(2, ntk,
                                                wfs.ibzk_qc,
                                                hl_skmm, sl_kmm, dl_skmm,
                                                None, wfs.dtype,
                                                direction=direction)
    my_npk = len(wfs.ibzk_qc) / ntk
    my_nspins = len(wfs.kpt_u) / (my_npk * ntk)

    lead_hsd = Banded_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    lead_couple_hsd = CP_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    for pk in range(my_npk):
        lead_hsd.reset(0, pk, sl_pkmm[pk], 'S', init=True)
        lead_couple_hsd.reset(0, pk, sl_pkcmm[pk], 'S', init=True)
        for s in range(my_nspins):
            lead_hsd.reset(s, pk, hl_spkmm[s, pk], 'H', init=True)
            lead_hsd.reset(s, pk, dl_spkmm[s, pk], 'D', init=True)
            lead_couple_hsd.reset(s, pk, hl_spkcmm[s, pk], 'H', init=True)
            lead_couple_hsd.reset(s, pk, dl_spkcmm[s, pk], 'D', init=True)
    lead_se = LeadSelfEnergy(lead_hsd, lead_couple_hsd)
    contour = Contour(kt, [fermi] * 2, bias, depth, comm=comm)
    path = contour.get_plot_path(ex=True)
    for nid, energy in zip(path.my_nids, path.my_energies):
        for kpt in wfs.kpt_u:
            if kpt.q % ntk == 0:
                flag = str(kpt.k // ntk) + '_' + str(nid)
                lead_se.s = kpt.s
                lead_se.pk = kpt.q // ntk
                data = lead_se(energy)
                fd = file(flag, 'w')
                cPickle.dump(data, fd, 2)
                fd.close()
Example #4
0
def path_selfenergy(atoms, ntk, filename, begin, end, num=257, direction=0):
    from gpaw.transport.sparse_matrix import Banded_Sparse_HSD, CP_Sparse_HSD, Se_Sparse_Matrix
    from gpaw.transport.selfenergy import LeadSelfEnergy
    from gpaw.transport.contour import Contour
    hl_skmm, sl_kmm = get_hs(atoms)
    dl_skmm = get_lcao_density_matrix(atoms.calc)
    fermi = atoms.calc.get_fermi_level()
    wfs = atoms.calc.wfs
    hl_spkmm, sl_pkmm, dl_spkmm,  \
    hl_spkcmm, sl_pkcmm, dl_spkcmm = get_pk_hsd(2, ntk,
                                                wfs.ibzk_qc,
                                                hl_skmm, sl_kmm, dl_skmm,
                                                None, wfs.dtype,
                                                direction=direction)
    my_npk = len(wfs.ibzk_qc) / ntk
    my_nspins = len(wfs.kpt_u) / (my_npk * ntk)

    lead_hsd = Banded_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    lead_couple_hsd = CP_Sparse_HSD(wfs.dtype, my_nspins, my_npk)
    for pk in range(my_npk):
        lead_hsd.reset(0, pk, sl_pkmm[pk], 'S', init=True)
        lead_couple_hsd.reset(0, pk, sl_pkcmm[pk], 'S', init=True)
        for s in range(my_nspins):
            lead_hsd.reset(s, pk, hl_spkmm[s, pk], 'H', init=True)
            lead_hsd.reset(s, pk, dl_spkmm[s, pk], 'D', init=True)
            lead_couple_hsd.reset(s, pk, hl_spkcmm[s, pk], 'H', init=True)
            lead_couple_hsd.reset(s, pk, dl_spkcmm[s, pk], 'D', init=True)
    lead_se = LeadSelfEnergy(lead_hsd, lead_couple_hsd)
    begin += fermi
    end += fermi

    ee = np.linspace(begin, end, num)
    se = []

    for e in ee:
        se.append(lead_se(e).recover())
    se = np.array(se)

    fd = file(filename + '_' + str(world.rank), 'w')
    cPickle.dump((se, ee), fd, 2)
    fd.close()
Example #5
0
    def initialize(self, srf_atoms, tip_atoms, srf_coupling_atoms, tip_coupling_atoms, 
                   srf_pl_atoms, tip_pl_atoms, energies, bias=0):
        """
        srf_atoms: the atom index of onsite surface atoms 
        tip_atoms: the atom index of onsite tip atoms
        energies: list of energies, for which the transmission function should be evaluated
        bias: will be used to precalculate the greenfunctions of surface and tip
        """
        self.bias = bias
        self.energies = energies
        self.tip_atoms = tip_atoms
        self.srf_atoms = srf_atoms
        self.srf_coupling_atoms = srf_coupling_atoms
        self.tip_coupling_atoms = tip_coupling_atoms
        #align potentials for onsite surface, onsite tip and tip principle layers according to surface_pl
        srf_alignv = self.align_v(calc1 = self.srf_pl, index1=srf_pl_atoms[0], calc2=self.srf, index2=srf_atoms[0])         
        tip_alignv = srf_alignv + self.tip.get_fermi_level() - self.srf.get_fermi_level() #- bias
        tip_pl_alignv = self.align_v(calc1=self.tip, index1=tip_atoms[-1], calc2=self.tip_pl, index2=tip_pl_atoms[-1])
        tip_pl_alignv += tip_alignv
        self.srf_alignv = srf_alignv
        self.tip_alignv = tip_alignv

        #hamiltoian and overlap matrix of onsite tip and srf
        self.h1, self.s1 = Lead_HS(calc = self.tip, atom_list = tip_atoms, shift = srf_alignv-bias).get_HS()
        print 'shape of onsite tip', np.shape(self.h1), np.shape(self.s1)
        self.h2, self.s2 = Lead_HS(calc = self.srf, atom_list = srf_atoms, shift = tip_alignv).get_HS()        
        print 'shape of onsite srf', np.shape(self.h2), np.shape(self.s2)

        #hamiltoian and overlap matrix of two tip and srf principle layers
        self.h10, self.s10 = Lead_HS(calc = self.tip_pl, atom_list = tip_pl_atoms, shift = tip_pl_alignv).get_HS() #2 and only 2 principle layers
        print 'shape of pl tip', np.shape(self.h10), np.shape(self.s10) 
        self.h20, self.s20 = Lead_HS(calc = self.srf_pl, atom_list = srf_pl_atoms, shift = -bias).get_HS() #2 and only 2 principle layers
        print 'shape of pl srf', np.shape(self.h20), np.shape(self.s20)

        nbf1, nbf2 = len(self.h1), len(self.h2)       #No. of basis functions of onsite tip and surface atoms
        pl1, pl2 = len(self.h10)/2, len(self.h20)/2   #No. of basis functions per principle layer of tip and srf
        nenergies = len(energies)        

        #periodic part of the tip
        hs1_dii = self.h10[:pl1, :pl1], self.s10[:pl1, :pl1]
        hs1_dij = self.h10[:pl1, pl1:2*pl1], self.s10[:pl1, pl1:2*pl1]
        #coupling betwen per. and non. per part of the tip
        h1_im = np.zeros((pl1, nbf1), complex)
        s1_im = np.zeros((pl1, nbf1), complex)
        h1_im[:pl1, :pl1], s1_im[:pl1, :pl1] = hs1_dij
        hs1_dim = [h1_im, s1_im]

        #periodic part the surface 
        hs2_dii = self.h20[:pl2, :pl2], self.s20[:pl2, :pl2]
        hs2_dij = self.h20[pl2:2*pl2, :pl2], self.s20[pl2:2*pl2, :pl2]
        #coupling betwen per. and non. per part of the surface
        h2_im = np.zeros((pl2, nbf2), complex)
        s2_im = np.zeros((pl2, nbf2), complex)
        h2_im[-pl2:, -pl2:], s2_im[-pl2:, -pl2:] = hs2_dij
        hs2_dim = [h2_im, s2_im]
        #tip and surface greenfunction 
        self.selfenergy1 = LeadSelfEnergy(hs1_dii, hs1_dij, hs1_dim)
        self.selfenergy2 = LeadSelfEnergy(hs2_dii, hs2_dij, hs2_dim)
        self.greenfunction1 = GreenFunction(self.h1, self.s1,[self.selfenergy1])
        self.greenfunction2 = GreenFunction(self.h2, self.s2,[self.selfenergy2])
        #print 'shape of greenfunction tip:', np.shape(self.greenfunction1)
        #print 'shape of greenfunction srf:', np.shape(self.greenfunction2)
        #shift the bands due to the bias
        self.selfenergy1.set_bias(0.0)
        self.selfenergy2.set_bias(bias)

        # extend the surface potentials and basis functions
        self.setup_stm()


        #tip and surface greenfunction matrices.
        nbf1_small = self.ni #XXX Change this for efficiency in the future
        nbf2_small = self.nj #XXX -||-
        coupling_list1 = range(nbf1-nbf1_small,nbf1)# XXX -||-
        coupling_list2 = range(0,nbf2_small)# XXX -||-
        self.gft1_emm = np.zeros((nenergies, nbf1_small, nbf1_small), complex)
        self.gft2_emm = np.zeros((nenergies, nbf2_small, nbf2_small), complex)

        for e, energy in enumerate(self.energies):
            gft1_mm = self.greenfunction1(energy)[coupling_list1]
            gft1_mm = np.take(gft1_mm, coupling_list1, axis=1)

            gft2_mm = self.greenfunction2(energy)[coupling_list2]
            gft2_mm = np.take(gft2_mm, coupling_list2, axis=1)

            self.gft1_emm[e] = gft1_mm
            self.gft2_emm[e] = gft2_mm