Example #1
0
def calc_es(
        mater,  # make sure high symmetry points contain
        ecut=800,
        nbands=nbs,
        vacuum=12):
    mol = read(traj(mater))
    mol.cell[-1][-1] = vacuum
    mol.center()
    calc = GPAW(mode=PW(ecut=ecut),
                xc="PBE",
                kpts=dict(gamma=True, size=(12, 12, 1)),
                occupations=FermiDirac(0.01),
                poissonsolver=dict(dipolelayer="xy"))
    calc.atoms = mol
    calc.get_potential_energy()
    calc.write(gs_wfs(mater), mode="all")
    # ES
    calc = GPAW(restart=gs_wfs(mater),
                fixdensity=True,
                nbands=nbands,
                kpts=dict(gamma=True, size=(12, 12, 1)),
                convergence=dict(bands=-5),
                parallel=dict(kpt=1))
    calc.get_potential_energy()
    calc.diagonalize_full_hamiltonian(nbands=nbands)
    calc.write(es_wfs(mater), mode="all")
    return True
Example #2
0
 def test_bs(self):
     sb = StructureBuilder()
     atoms, *_ = sb.get_structure("C", "diamond")
     # print(atoms)
     base_dir = os.path.join(os.path.dirname(__file__),
                             "../../tmp/C-class/")
     m_calc = MaterCalc(atoms=atoms,
                        base_dir=base_dir)
     self.assertTrue(m_calc.relax(fmax=0.002))  # Very tight limit!
     self.assertTrue(m_calc.ground_state())
     # get the PBE BS
     lattice_type = get_cellinfo(m_calc.atoms.cell).lattice
     self.assertTrue(lattice_type in special_paths.keys())
     kpts_bs = dict(path=special_paths[lattice_type],
                    npoints=120)
     # HSE06 base generate
     gs_file = os.path.join(base_dir, "gs.gpw")
     _calc = GPAW(restart=gs_file)
     atoms = _calc.atoms.copy()
     calc = GPAW(**_calc.parameters)
     calc.set(kpts=dict(gamma=True,
                        density=4))  # low density calculations
     calc.atoms = atoms
     del _calc
     calc.get_potential_energy()
     calc.write(os.path.join(base_dir, "hse.gpw"), mode="all")
     calc = GPAW(restart=os.path.join(base_dir, "hse.gpw"),
                 txt=None)
     ns = calc.get_number_of_spins()
     nk = len(calc.get_ibz_k_points())
     nbands = calc.get_number_of_bands()
     eigen_pbe = numpy.array([[calc.get_eigenvalues(spin=s,
                                                    kpt=k) \
                               for k in range(nk)]\
                              for s in range(ns)])
     parprint("EIGEN_PBE", eigen_pbe.shape)
     vxc_pbe = vxc(calc, "PBE")
     parprint("VXC_PBE", vxc_pbe.shape)
     # world.barrier()
     # HSE06 now
     calc_hse = EXX(os.path.join(base_dir, "hse.gpw"),
                    xc="HSE06",
                    bands=[0, nbands])
     calc_hse.calculate()
     vxc_hse = calc_hse.get_eigenvalue_contributions()
     parprint(vxc_hse.shape)
     parprint(vxc_hse)
     eigen_hse = eigen_pbe - vxc_pbe + vxc_hse
     
     # HSE bandgap from just kpts
     bg_hse_min, *_ = bandgap(eigenvalues=eigen_hse,
                              efermi=calc.get_fermi_level(),
                              direct=False)
     bg_hse_dir, *_ = bandgap(eigenvalues=eigen_hse,
                              efermi=calc.get_fermi_level(),
                              direct=True)
     parprint("HSE: E_min \t E_dir")
     parprint("{:.3f}\t{:.3f}".format(bg_hse_min, bg_hse_dir))
     """
Example #3
0
    def test_relax_single(self):
        sb = StructureBuilder()
        atoms, *_ = sb.get_structure("C", "diamond")
        # print(atoms)
        m_calc = MaterCalc(atoms=atoms, base_dir="../../tmp/C-class/")
        m_calc.relax(fmax=0.002)  # Very tight limit!
        m_calc.ground_state()

        # self.assertTrue(res)
        base_dir = "../../tmp/C-class/"
        gpw_name = os.path.join(base_dir, "gs.gpw")
        self.assertTrue(os.path.exists(gpw_name))
        calc = GPAW(restart=gpw_name, txt="gp.txt")
        # PBE bandgap
        bg_pbe_min, *_ = bandgap(calc, direct=False)
        bg_pbe_dir, *_ = bandgap(calc, direct=True)
        # gllbsc
        calc_gllb = GPAW(**calc.parameters)
        calc_gllb.atoms = calc.atoms
        calc_gllb.set(xc="GLLBSC", txt="gllb.txt")
        calc_gllb.get_potential_energy()  # SC calculation
        response = calc_gllb.hamiltonian.xc.xcs["RESPONSE"]
        response.calculate_delta_xc()
        EKs, Dxc = response.calculate_delta_xc_perturbation()
        gllb_gap = EKs + Dxc

        parprint("Eg-PBE-min, Eg-PBE-dir, Eg-gllb")
        parprint(bg_pbe_min, bg_pbe_dir, gllb_gap)
        # Use kpts?
        ibz_kpts = calc.get_ibz_k_points()
        e_kn = numpy.array([calc.get_eigenvalues(kpt=k) \
                            for k in range(len(ibz_kpts))])
        efermi = calc.get_fermi_level()
        e_kn[e_kn > efermi] += Dxc
        gllb_gap_min = bandgap(eigenvalues=e_kn, efermi=efermi, direct=False)
        gllb_gap_dir = bandgap(eigenvalues=e_kn, efermi=efermi, direct=True)

        parprint("Efermi", efermi)
        parprint("Eg-gllb-min, Eg-gllb-dir")
        parprint(gllb_gap_min, gllb_gap_dir)
Example #4
0
    def calculate(self, optical=True, ac=1.0):

        if self.spinors:
            """Calculate spinors. Here m is index of eigenvalues with SOC
            and n is the basis of eigenstates withour SOC. Below m is used
            for unoccupied states and n is used for occupied states so be
            careful!"""

            print('Diagonalizing spin-orbit Hamiltonian', file=self.fd)
            param = self.calc.parameters
            if not param['symmetry'] == 'off':
                print('Calculating KS wavefunctions without symmetry ' +
                      'for spin-orbit', file=self.fd)
                if not op.isfile('gs_nosym.gpw'):
                    calc_so = GPAW(**param)
                    calc_so.set(symmetry='off',
                                fixdensity=True,
                                txt='gs_nosym.txt')
                    calc_so.atoms = self.calc.atoms
                    calc_so.density = self.calc.density
                    calc_so.get_potential_energy()
                    calc_so.write('gs_nosym.gpw')
                calc_so = GPAW('gs_nosym.gpw', txt=None,
                               communicator=serial_comm)
                e_mk, v_knm = get_spinorbit_eigenvalues(calc_so,
                                                        return_wfs=True,
                                                        scale=self.scale)
                del calc_so
            else:
                e_mk, v_knm = get_spinorbit_eigenvalues(self.calc,
                                                        return_wfs=True,
                                                        scale=self.scale)
            e_mk /= Hartree

        # Parallelization stuff
        nK = self.kd.nbzkpts
        myKrange, myKsize, mySsize = self.parallelisation_sizes()

        # Calculate exchange interaction
        qd0 = KPointDescriptor([self.q_c])
        pd0 = PWDescriptor(self.ecut, self.calc.wfs.gd, complex, qd0)
        ikq_k = self.kd.find_k_plus_q(self.q_c)
        v_G = get_coulomb_kernel(pd0, self.kd.N_c, truncation=self.truncation,
                                 wstc=self.wstc)
        if optical:
            v_G[0] = 0.0

        self.pair = PairDensity(self.calc, self.ecut, world=serial_comm,
                                txt='pair.txt')

        # Calculate direct (screened) interaction and PAW corrections
        if self.mode == 'RPA':
            Q_aGii = self.pair.initialize_paw_corrections(pd0)
        else:
            self.get_screened_potential(ac=ac)
            if (self.qd.ibzk_kc - self.q_c < 1.0e-6).all():
                iq0 = self.qd.bz2ibz_k[self.kd.where_is_q(self.q_c,
                                                          self.qd.bzk_kc)]
                Q_aGii = self.Q_qaGii[iq0]
            else:
                Q_aGii = self.pair.initialize_paw_corrections(pd0)

        # Calculate pair densities, eigenvalues and occupations
        so = self.spinors + 1
        Nv, Nc = so * self.nv, so * self.nc
        Ns = self.spins
        rhoex_KsmnG = np.zeros((nK, Ns, Nv, Nc, len(v_G)), complex)
        # rhoG0_Ksmn = np.zeros((nK, Ns, Nv, Nc), complex)
        df_Ksmn = np.zeros((nK, Ns, Nv, Nc), float) # -(ev - ec)
        deps_ksmn = np.zeros((myKsize, Ns, Nv, Nc), float) # -(fv - fc)
        if np.allclose(self.q_c, 0.0):
            optical_limit = True
        else:
            optical_limit = False
        get_pair = self.pair.get_kpoint_pair
        get_rho = self.pair.get_pair_density
        if self.spinors:
            # Get all pair densities to allow for SOC mixing
            # Use twice as many no-SOC states as BSE bands to allow mixing
            vi_s = [2 * self.val_sn[0, 0] - self.val_sn[0, -1] - 1]
            vf_s = [2 * self.con_sn[0, -1] - self.con_sn[0, 0] + 2]
            if vi_s[0] < 0:
                vi_s[0] = 0
            ci_s, cf_s = vi_s, vf_s
            ni, nf = vi_s[0], vf_s[0]
            mvi = 2 * self.val_sn[0, 0]
            mvf = 2 * (self.val_sn[0, -1] + 1)
            mci = 2 * self.con_sn[0, 0]
            mcf = 2 * (self.con_sn[0, -1] + 1)
        else:
            vi_s, vf_s = self.val_sn[:, 0], self.val_sn[:, -1] + 1
            ci_s, cf_s = self.con_sn[:, 0], self.con_sn[:, -1] + 1
        for ik, iK in enumerate(myKrange):
            for s in range(Ns):
                pair = get_pair(pd0, s, iK,
                                vi_s[s], vf_s[s], ci_s[s], cf_s[s])
                m_m = np.arange(vi_s[s], vf_s[s])
                n_n = np.arange(ci_s[s], cf_s[s])
                if self.gw_skn is not None:
                    iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0]
                    epsv_m = self.gw_skn[s, iK, :self.nv]
                    epsc_n = self.gw_skn[s, iKq, self.nv:]
                    deps_ksmn[ik] = -(epsv_m[:, np.newaxis] - epsc_n)
                elif self.spinors:
                    iKq = self.calc.wfs.kd.find_k_plus_q(self.q_c, [iK])[0]
                    epsv_m = e_mk[mvi:mvf, iK]
                    epsc_n = e_mk[mci:mcf, iKq]
                    deps_ksmn[ik, s] = -(epsv_m[:, np.newaxis] - epsc_n)
                else:
                    deps_ksmn[ik, s] = -pair.get_transition_energies(m_m, n_n)

                df_mn = pair.get_occupation_differences(self.val_sn[s],
                                                        self.con_sn[s])
                rho_mnG = get_rho(pd0, pair,
                                  m_m, n_n,
                                  optical_limit=optical_limit,
                                  direction=self.direction,
                                  Q_aGii=Q_aGii,
                                  extend_head=False)
                if self.spinors:
                    if optical_limit:
                        deps0_mn = -pair.get_transition_energies(m_m, n_n)
                        rho_mnG[:, :, 0] *= deps0_mn
                    df_Ksmn[iK, s, ::2, ::2] = df_mn
                    df_Ksmn[iK, s, ::2, 1::2] = df_mn
                    df_Ksmn[iK, s, 1::2, ::2] = df_mn
                    df_Ksmn[iK, s, 1::2, 1::2] = df_mn
                    vecv0_nm = v_knm[iK][::2][ni:nf, mvi:mvf]
                    vecc0_nm = v_knm[iKq][::2][ni:nf, mci:mcf]
                    rho_0mnG = np.dot(vecv0_nm.T.conj(),
                                      np.dot(vecc0_nm.T, rho_mnG))
                    vecv1_nm = v_knm[iK][1::2][ni:nf, mvi:mvf]
                    vecc1_nm = v_knm[iKq][1::2][ni:nf, mci:mcf]
                    rho_1mnG = np.dot(vecv1_nm.T.conj(),
                                      np.dot(vecc1_nm.T, rho_mnG))
                    rhoex_KsmnG[iK, s] = rho_0mnG + rho_1mnG
                    if optical_limit:
                        rhoex_KsmnG[iK, s, :, :, 0] /= deps_ksmn[ik, s]
                else:
                    df_Ksmn[iK, s] = pair.get_occupation_differences(m_m, n_n)
                    rhoex_KsmnG[iK, s] = rho_mnG

        if self.eshift is not None:
            deps_ksmn[np.where(df_Ksmn[myKrange] > 1.0e-3)] += self.eshift
            deps_ksmn[np.where(df_Ksmn[myKrange] < -1.0e-3)] -= self.eshift

        world.sum(df_Ksmn)
        world.sum(rhoex_KsmnG)

        self.rhoG0_S = np.reshape(rhoex_KsmnG[:, :, :, :, 0], -1)

        if hasattr(self, 'H_sS'):
            return

        # Calculate Hamiltonian
        t0 = time()
        print('Calculating %s matrix elements at q_c = %s'
              % (self.mode, self.q_c), file=self.fd)
        H_ksmnKsmn = np.zeros((myKsize, Ns, Nv, Nc, nK, Ns, Nv, Nc), complex)
        for ik1, iK1 in enumerate(myKrange):
            for s1 in range(Ns):
                kptv1 = self.pair.get_k_point(s1, iK1, vi_s[s1], vf_s[s1])
                kptc1 = self.pair.get_k_point(s1, ikq_k[iK1], ci_s[s1],
                                              cf_s[s1])
                rho1_mnG = rhoex_KsmnG[iK1, s1]

                #rhoG0_Ksmn[iK1, s1] = rho1_mnG[:, :, 0]
                rho1ccV_mnG = rho1_mnG.conj()[:, :] * v_G
                for s2 in range(Ns):
                    for Q_c in self.qd.bzk_kc:
                        iK2 = self.kd.find_k_plus_q(Q_c, [kptv1.K])[0]
                        rho2_mnG = rhoex_KsmnG[iK2, s2]
                        rho2_mGn = np.swapaxes(rho2_mnG, 1, 2)
                        H_ksmnKsmn[ik1, s1, :, :, iK2, s2, :, :] += (
                            np.dot(rho1ccV_mnG, rho2_mGn))
                        if not self.mode == 'RPA' and s1 == s2:
                            ikq = ikq_k[iK2]
                            kptv2 = self.pair.get_k_point(s1, iK2, vi_s[s1],
                                                          vf_s[s1])
                            kptc2 = self.pair.get_k_point(s1, ikq, ci_s[s1],
                                                          cf_s[s1])
                            rho3_mmG, iq = self.get_density_matrix(kptv1,
                                                                   kptv2)
                            rho4_nnG, iq = self.get_density_matrix(kptc1,
                                                                   kptc2)
                            if self.spinors:
                                vec0_nm = v_knm[iK1][::2][ni:nf, mvi:mvf]
                                vec1_nm = v_knm[iK1][1::2][ni:nf, mvi:mvf]
                                vec2_nm = v_knm[iK2][::2][ni:nf, mvi:mvf]
                                vec3_nm = v_knm[iK2][1::2][ni:nf, mvi:mvf]
                                rho_0mnG = np.dot(vec0_nm.T.conj(),
                                                  np.dot(vec2_nm.T, rho3_mmG))
                                rho_1mnG = np.dot(vec1_nm.T.conj(),
                                                  np.dot(vec3_nm.T, rho3_mmG))
                                rho3_mmG = rho_0mnG + rho_1mnG
                                vec0_nm = v_knm[ikq_k[iK1]][::2][ni:nf, mci:mcf]
                                vec1_nm = v_knm[ikq_k[iK1]][1::2][ni:nf,mci:mcf]
                                vec2_nm = v_knm[ikq][::2][ni:nf, mci:mcf]
                                vec3_nm = v_knm[ikq][1::2][ni:nf, mci:mcf]
                                rho_0mnG = np.dot(vec0_nm.T.conj(),
                                                  np.dot(vec2_nm.T, rho4_nnG))
                                rho_1mnG = np.dot(vec1_nm.T.conj(),
                                                  np.dot(vec3_nm.T, rho4_nnG))
                                rho4_nnG = rho_0mnG + rho_1mnG

                            rho3ccW_mmG = np.dot(rho3_mmG.conj(),
                                                 self.W_qGG[iq])
                            W_mmnn = np.dot(rho3ccW_mmG,
                                            np.swapaxes(rho4_nnG, 1, 2))
                            W_mnmn = np.swapaxes(W_mmnn, 1, 2) * Ns * so
                            H_ksmnKsmn[ik1, s1, :, :, iK2, s1] -= 0.5 * W_mnmn
            if iK1 % (myKsize // 5 + 1) == 0:
                dt = time() - t0
                tleft = dt * myKsize / (iK1 + 1) - dt
                print('  Finished %s pair orbitals in %s - Estimated %s left' %
                      ((iK1 + 1) * Nv * Nc * Ns * world.size,
                       timedelta(seconds=round(dt)),
                       timedelta(seconds=round(tleft))), file=self.fd)

        #if self.mode == 'BSE':
        #    del self.Q_qaGii, self.W_qGG, self.pd_q

        H_ksmnKsmn /= self.vol

        mySsize = myKsize * Nv * Nc * Ns
        if myKsize > 0:
            iS0 = myKrange[0] *  Nv * Nc * Ns

        #world.sum(rhoG0_Ksmn)
        #self.rhoG0_S = np.reshape(rhoG0_Ksmn, -1)
        self.df_S = np.reshape(df_Ksmn, -1)
        if not self.td:
            self.excludef_S = np.where(np.abs(self.df_S) < 0.001)[0]
        # multiply by 2 when spin-paired and no SOC
        self.df_S *= 2.0 / nK / Ns / so
        self.deps_s = np.reshape(deps_ksmn, -1)
        H_sS = np.reshape(H_ksmnKsmn, (mySsize, self.nS))
        for iS in range(mySsize):
            # Multiply by occupations and adiabatic coupling
            H_sS[iS] *= self.df_S[iS0 + iS] * ac
            # add bare transition energies
            H_sS[iS, iS0 + iS] += self.deps_s[iS]

        self.H_sS = H_sS

        if self.write_h:
            self.par_save('H_SS.ulm', 'H_SS', self.H_sS)
Example #5
0
    def test_bs(self):
        sb = StructureBuilder()
        atoms, *_ = sb.get_structure("Si", "diamond")
        # print(atoms)
        base_dir = os.path.join(os.path.dirname(__file__),
                                "../../tmp/Si-class/")
        m_calc = MaterCalc(atoms=atoms, base_dir=base_dir)
        self.assertTrue(m_calc.relax(fmax=0.002))  # Very tight limit!
        self.assertTrue(m_calc.ground_state())
        # get the PBE BS
        lattice_type = get_cellinfo(m_calc.atoms.cell).lattice
        self.assertTrue(lattice_type in special_paths.keys())
        kpts_bs = dict(path=special_paths[lattice_type], npoints=120)
        gpw_name = os.path.join(base_dir, "gs.gpw")
        self.assertTrue(os.path.exists(gpw_name))
        calc_bs = GPAW(restart=gpw_name,
                       kpts=kpts_bs,
                       fixdensity=True,
                       symmetry='off',
                       txt=os.path.join(base_dir, "pbe-bs.txt"))
        calc_bs.get_potential_energy()
        # PBE bandgap
        bg_pbe_min, *_ = bandgap(calc_bs, direct=False)
        bg_pbe_dir, *_ = bandgap(calc_bs, direct=True)
        calc_bs.write(os.path.join(base_dir, "pbe-bs.gpw"))
        bs_pbe = calc_bs.band_structure()
        bs_pbe.plot(emin=-10,
                    emax=10,
                    filename=os.path.join(base_dir, "pbe-bs.png"))

        # get the gllbsc by steps
        calc_ = GPAW(restart=gpw_name)
        calc_gllb = GPAW(**calc_.parameters)
        calc_gllb.set(xc="GLLBSC", txt=os.path.join(base_dir, "gllb-gs.txt"))
        calc_gllb.atoms = calc_.atoms
        del calc_
        calc_gllb.get_potential_energy()  # SC calculation
        calc_gllb.write("gllb-gs.gpw")
        calc_gllb_bs = GPAW(restart="gllb-gs.gpw",
                            kpts=kpts_bs,
                            fixdensity=True,
                            symmetry="off",
                            txt=os.path.join(base_dir, "gllb-bs.txt"))
        world.barrier()
        calc_gllb_bs.get_potential_energy()
        homolumo = calc_gllb_bs.get_homo_lumo()
        bg_gllb_ks = homolumo[1] - homolumo[0]
        response = calc_gllb_bs.hamiltonian.xc.xcs["RESPONSE"]
        response.calculate_delta_xc(homolumo / Ha)
        EKs, Dxc = response.calculate_delta_xc_perturbation()
        bg_gllb_deltaxc = EKs + Dxc

        ibz_kpts = calc_gllb_bs.get_ibz_k_points()
        e_kn = numpy.array([calc_gllb_bs.get_eigenvalues(kpt=k) \
                            for k in range(len(ibz_kpts))])
        efermi = calc_gllb_bs.get_fermi_level()
        e_kn[e_kn > efermi] += Dxc
        bg_gllb_min, *_ = bandgap(eigenvalues=e_kn,
                                  efermi=efermi,
                                  direct=False)
        bg_gllb_dir, *_ = bandgap(eigenvalues=e_kn, efermi=efermi, direct=True)

        parprint("PBE: E_min \t E_dir")
        parprint("{:.3f}\t{:.3f}".format(bg_pbe_min, bg_pbe_dir))
        parprint("Gllb: EKS \t E_deltaxc")
        parprint("{:.3f}\t{:.3f}".format(bg_gllb_ks, bg_gllb_deltaxc))
        parprint("Gllb: E_min \t E_dir")
        parprint("{:.3f}\t{:.3f}".format(bg_gllb_min, bg_gllb_dir))
        bs_gllb = calc_gllb_bs.band_structure()
        bs_gllb.energies[bs_gllb.energies > bs_gllb.reference] += Dxc
        bs_gllb.plot(emin=-10,
                     emax=10,
                     filename=os.path.join(base_dir, "gllb-bs.png"))

        calc_gllb_bs.write(os.path.join(base_dir, "gllb-bs.gpw"))