def get_eigenvalue_contributions(self): if self.reader is not None: self.calc.wfs.read_projections(self.reader) b1, b2 = self.bands e_sin = vxc(self.calc, self.xc)[:, self.kpts, b1:b2] / Hartree e_sin += (self.exxvv_sin + self.exxvc_sin) * self.exx_fraction return e_sin * Hartree
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)) """
def get_exact_exchange(self, ecut=None, communicator=world, file='EXX.pckl'): try: self.ini except: self.initialize() self.printtxt('------------------------------------------------') self.printtxt("calculating Exact exchange and E_XC") calc = GPAW(self.file, communicator=communicator, parallel={'domain':1, 'band':1}, txt=None) v_xc = vxc(calc) if ecut == None: ecut = self.ecut.max() else: ecut /= Hartree if self.pwmode: # planewave mode from gpaw.xc.hybridg import HybridXC self.printtxt('Use planewave ecut from groundstate calculator: %4.1f eV' % (calc.wfs.pd.ecut*Hartree) ) exx = HybridXC('EXX', alpha=5.0, bandstructure=True, bands=self.bands) else: # grid mode from gpaw.xc.hybridk import HybridXC self.printtxt('Planewave ecut (eV): %4.1f' % (ecut*Hartree) ) exx = HybridXC('EXX', alpha=5.0, ecut=ecut, bands=self.bands) calc.get_xc_difference(exx) e_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) f_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) vxc_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) exx_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) for s in range(self.nspins): for i, k in enumerate(self.gwkpt_k): ik = self.kd.bz2ibz_k[k] for j, n in enumerate(self.gwbands_n): e_skn[s][i][j] = self.e_skn[s][ik][n] f_skn[s][i][j] = self.f_skn[s][ik][n] vxc_skn[s][i][j] = v_xc[s][ik][n] / Hartree exx_skn[s][i][j] = exx.exx_skn[s][ik][n] if self.eshift is not None: if e_skn[s][i][j] > self.eFermi: vxc_skn[s][i][j] += self.eshift / Hartree data = { 'e_skn': e_skn, # in Hartree 'vxc_skn': vxc_skn, # in Hartree 'exx_skn': exx_skn, # in Hartree 'f_skn': f_skn, 'gwkpt_k': self.gwkpt_k, 'gwbands_n': self.gwbands_n } if rank == 0: pickle.dump(data, open(file, 'w'), -1) self.printtxt("------------------------------------------------") self.printtxt("non-selfconsistent HF eigenvalues are (eV):") self.printtxt((e_skn - vxc_skn + exx_skn)*Hartree)
def calculate_ks_xc_contribution(self): name = self.filename + '.vxc.npy' fd = opencew(name) if fd is None: print('Reading Kohn-Sham XC contribution from file:', name, file=self.fd) with open(name) as fd: self.vxc_sin = np.load(fd) assert self.vxc_sin.shape == self.shape, self.vxc_sin.shape return print('Calculating Kohn-Sham XC contribution', file=self.fd) vxc_skn = vxc(self.calc, self.calc.hamiltonian.xc) / Hartree n1, n2 = self.bands self.vxc_sin = vxc_skn[:, self.kpts, n1:n2] np.save(fd, self.vxc_sin)
def calculate_ks_xc_contribution(self): name = self.filename + '.vxc.npy' fd = opencew(name) if fd is None: print('Reading Kohn-Sham XC contribution from file:', name, file=self.fd) with open(name) as fd: self.vxc_sin = np.load(fd) assert self.vxc_sin.shape == self.shape, self.vxc_sin.shape return print('Calculating Kohn-Sham XC contribution', file=self.fd) if self.reader is not None: self.calc.wfs.read_projections(self.reader) vxc_skn = vxc(self.calc, self.calc.hamiltonian.xc) / Hartree n1, n2 = self.bands self.vxc_sin = vxc_skn[:, self.kpts, n1:n2] np.save(fd, self.vxc_sin)
communicator=comm, setups={'Mg': '2'}, convergence={'eigenstates': 5.e-9}, kpts=monkhorst_pack((2, 2, 2)) + 0.25) mgo.get_potential_energy() if rank < 3: mgo.calc.write('mgo', 'all') else: mgo.calc.write('dummy_%d' % rank, 'all') world.barrier() for name in ['PBE0', 'HSE03', 'HSE06']: calc = GPAW('mgo', setups={'Mg': '2'}, txt=None, communicator=serial_comm) hyb_calc = HybridXC(name, alpha=5.0, bandstructure=True, world=comm) de_skn = vxc(calc, hyb_calc) - vxc(calc, 'LDA') if name == 'PBE0': de_skn_test = np.array([-1.3700, -1.3643, -1.3777, -24.184590]) if name == 'HSE03': de_skn_test = np.array([-2.4565, -2.4326, -2.4583, -24.405001]) if name == 'HSE06': de_skn_test = np.array([-2.0311, -2.0151, -2.0367, -24.324485]) if rank == 0: print(de_skn[0, 0, 1:4], abs(de_skn[0, 0, 1:4] - de_skn_test[0]).max()) print(de_skn[0, 1, 2:4], abs(de_skn[0, 1, 2:4] - de_skn_test[1]).max()) print(de_skn[0, 2, 2:4], abs(de_skn[0, 2, 2:4] - de_skn_test[2]).max()) print(hyb_calc.exx, abs(hyb_calc.exx - de_skn_test[3])) assert abs(de_skn[0, 0, 1:4] - de_skn_test[0]).max() < 0.02 assert abs(de_skn[0, 1, 2:4] - de_skn_test[1]).max() < 0.008
def get_eigenvalue_contributions(self): b1, b2 = self.bands e_sin = vxc(self.calc, self.xc)[:, self.kpts, b1:b2] / Hartree e_sin += (self.exxvv_sin + self.exxvc_sin) * self.exx_fraction return e_sin * Hartree
(0.75, 0.25, 0.75), (0.75, 0.75, 0.25)], pbc=True) bulk.set_cell((a, a, a), scale_atoms=True) n = 20 calc = GPAW(gpts=(n, n, n), nbands='150%', occupations=FermiDirac(width=0.01), poissonsolver=PoissonSolver(nn='M', relax='J'), kpts=(2, 2, 2), convergence={'energy': 1e-7} ) bulk.set_calculator(calc) f1 = bulk.get_forces()[0, 2] e1 = bulk.get_potential_energy() v_xc = vxc(calc) print(v_xc) niter1 = calc.get_number_of_iterations() f2 = numeric_force(bulk, 0, 2) print((f1, f2, f1 - f2)) equal(f1, f2, 0.005) # Volume per atom: vol = a**3 / 8 de = calc.get_electrostatic_corrections() / vol print(de) assert abs(de[0] - -2.190) < 0.001 print((e1, f1, niter1)) energy_tolerance = 0.00025
idiotproof=False, communicator=comm, setups={'Mg': '2'}, convergence={'eigenstates': 5.e-9}, kpts=monkhorst_pack((2, 2, 2)) + 0.25) mgo.get_potential_energy() if rank < 3: mgo.calc.write('mgo', 'all') else: mgo.calc.write('dummy_%d' % rank, 'all') world.barrier() for name in ['PBE0', 'HSE03', 'HSE06']: calc = GPAW('mgo', setups={'Mg': '2'}, txt=None, communicator=serial_comm) hyb_calc = HybridXC(name, alpha=5.0, bandstructure=True, world=comm) de_skn = vxc(calc, hyb_calc) - vxc(calc, 'LDA') if name == 'PBE0': de_skn_test = np.array([-1.3700, -1.3643, -1.3777, -24.184590]) if name == 'HSE03': de_skn_test = np.array([-2.4565, -2.4326, -2.4583, -24.405001]) if name == 'HSE06': de_skn_test = np.array([-2.0311, -2.0151, -2.0367, -24.324485]) if rank == 0: print(de_skn[0, 0, 1:4], abs(de_skn[0, 0, 1:4] - de_skn_test[0]).max()) print(de_skn[0, 1, 2:4], abs(de_skn[0, 1, 2:4] - de_skn_test[1]).max()) print(de_skn[0, 2, 2:4], abs(de_skn[0, 2, 2:4] - de_skn_test[2]).max()) print(hyb_calc.exx, abs(hyb_calc.exx - de_skn_test[3])) assert abs(de_skn[0, 0, 1:4] - de_skn_test[0]).max() < 0.02 assert abs(de_skn[0, 1, 2:4] - de_skn_test[1]).max() < 0.008
def get_exact_exchange(self, ecut=None, communicator=world, file='EXX.pckl'): try: self.ini except: self.initialize() self.printtxt('------------------------------------------------') self.printtxt("calculating Exact exchange and E_XC") calc = GPAW(self.file, communicator=communicator, parallel={ 'domain': 1, 'band': 1 }, txt=None) v_xc = vxc(calc) if ecut is None: ecut = self.ecut.max() else: ecut /= Hartree if self.pwmode: # planewave mode from gpaw.xc.hybridg import HybridXC self.printtxt( 'Use planewave ecut from groundstate calculator: %4.1f eV' % (calc.wfs.pd.ecut * Hartree)) exx = HybridXC('EXX', alpha=5.0, bandstructure=True, bands=self.bands) else: # grid mode from gpaw.xc.hybridk import HybridXC self.printtxt('Planewave ecut (eV): %4.1f' % (ecut * Hartree)) exx = HybridXC('EXX', alpha=5.0, ecut=ecut, bands=self.bands) calc.get_xc_difference(exx) e_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) f_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) vxc_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) exx_skn = np.zeros((self.nspins, self.gwnkpt, self.gwnband), dtype=float) for s in range(self.nspins): for i, k in enumerate(self.gwkpt_k): ik = self.kd.bz2ibz_k[k] for j, n in enumerate(self.gwbands_n): e_skn[s][i][j] = self.e_skn[s][ik][n] f_skn[s][i][j] = self.f_skn[s][ik][n] vxc_skn[s][i][j] = v_xc[s][ik][n] / Hartree exx_skn[s][i][j] = exx.exx_skn[s][ik][n] if self.eshift is not None: if e_skn[s][i][j] > self.eFermi: vxc_skn[s][i][j] += self.eshift / Hartree data = { 'e_skn': e_skn, # in Hartree 'vxc_skn': vxc_skn, # in Hartree 'exx_skn': exx_skn, # in Hartree 'f_skn': f_skn, 'gwkpt_k': self.gwkpt_k, 'gwbands_n': self.gwbands_n } if rank == 0: pickle.dump(data, open(file, 'w'), -1) self.printtxt("------------------------------------------------") self.printtxt("non-selfconsistent HF eigenvalues are (eV):") self.printtxt((e_skn - vxc_skn + exx_skn) * Hartree)
x, a = data[name][:2] atoms = bulk(name, x, a=a) atoms.calc = GPAW( xc="PBE", mode=PW(500), parallel=dict(band=1), nbands=-8, convergence=dict(bands=-7), kpts=kpts, txt="%s.txt" % name, ) if name in ["MgO", "NaCl"]: atoms.calc.set(eigensolver="cg") atoms.get_potential_energy() pbe0 = HybridXC("PBE0", alpha=5.0, bandstructure=True) de_skn = vxc(atoms.calc, pbe0) - vxc(atoms.calc, "PBE") ibzk_kc = atoms.calc.get_ibz_k_points() n = int(atoms.calc.get_number_of_electrons()) // 2 gamma = None j = 0 for symbol, k_c in zip("GXL", [(0, 0, 0), (0.5, 0.5, 0), (0.5, 0.5, 0.5)]): k = abs(ibzk_kc - k_c).max(1).argmin() if gamma is None: gamma = atoms.calc.get_eigenvalues(k)[n - 1] gamma0 = gamma + de_skn[0, k, n - 1] e = atoms.calc.get_eigenvalues(k)[n] e0 = e + de_skn[0, k, n] if rank == 0: print(name, n, k, symbol, e - gamma, e0 - gamma0) results[i][:2] = [e - gamma, e0 - gamma0] results[i][2:] = data[name][2 + j * 4 : 6 + j * 4]
pbc=False) atoms.positions[:] += a / 2 calc = GPAW(h=0.25, nbands=4, convergence={'eigenstates': 7.8e-10}) atoms.calc = calc energy = atoms.get_potential_energy() niter = calc.get_number_of_iterations() # The three eigenvalues e[1], e[2], and e[3] must be degenerate: e = calc.get_eigenvalues() print(e[1] - e[3]) equal(e[1], e[3], 9.3e-8) energy_tolerance = 0.0003 niter_tolerance = 0 equal(energy, -23.6277, energy_tolerance) # Calculate non-selfconsistent PBE eigenvalues: from gpaw.xc.tools import vxc epbe0 = e - vxc(calc)[0, 0] + vxc(calc, 'PBE')[0, 0] # Calculate selfconsistent PBE eigenvalues: calc.set(xc='PBE') energy = atoms.get_potential_energy() epbe = calc.get_eigenvalues() de = epbe[1] - epbe[0] de0 = epbe0[1] - epbe0[0] print(de, de0) equal(de, de0, 0.001)
n2 = 5 ibzkpts = si.calc.get_ibz_k_points() kpt_indices = [] pbeeigs = [] for kpt in [(0, 0, 0), (0.5, 0.5, 0)]: # Find k-point index: i = abs(ibzkpts - kpt).sum(1).argmin() kpt_indices.append(i) pbeeigs.append(si.calc.get_eigenvalues(i)[n1:n2]) # DFT eigenvalues: pbeeigs = np.array(pbeeigs) # PBE contribution: dpbeeigs = vxc(si.calc, 'PBE')[0, kpt_indices, n1:n2] # Do PBE0 calculation: pbe0 = EXX(name + '.gpw', 'PBE0', kpts=kpt_indices, bands=[n1, n2], txt=name + '.pbe0.txt') pbe0.calculate() dpbe0eigs = pbe0.get_eigenvalue_contributions()[0] pbe0eigs = pbeeigs - dpbeeigs + dpbe0eigs print('{0}, {1:.3f}, {2:.3f}, {3:.3f}, {4:.3f}'.format( k, pbeeigs[0, 1] - pbeeigs[0, 0], pbeeigs[1, 1] - pbeeigs[0, 0], pbe0eigs[0, 1] - pbe0eigs[0, 0], pbe0eigs[1, 1] - pbe0eigs[0, 0]),
import pickle import numpy as np from ase.dft.wannier import Wannier from ase.units import Hartree from ase.dft.kpoints import ibz_points, get_bandpath from gpaw import GPAW from gpaw.xc.tools import vxc from gpaw.xc.hybridk import HybridXC calc = GPAW('Si-PBE.gpw', txt=None) pbe0 = HybridXC('PBE0', alpha=5.0) de_skn = vxc(calc, pbe0) - vxc(calc, 'PBE') de_kn = de_skn[0, calc.wfs.kd.bz2ibz_k] calc.wfs.ibz2bz(calc.atoms) w = Wannier(4, calc, 'rotations.pckl') points = ibz_points['fcc'] G = points['Gamma'] X = points['X'] W = points['W'] K = points['K'] L = points['L'] kpts, x, X = get_bandpath([W, L, G, X, W, K], calc.atoms.cell) epbe_kn = np.array([np.linalg.eigh(w.get_hamiltonian_kpoint(kpt))[0] for kpt in kpts]) for kpt in calc.wfs.kpt_u:
atoms.get_potential_energy() atoms.calc.write(name, mode='all') ibzk_kc = atoms.calc.get_ibz_k_points() n = int(atoms.calc.get_number_of_electrons()) // 2 ibzk = [] eps_kn = [] for k_c in [(0, 0, 0), (0.5, 0.5, 0), (0.5, 0.5, 0.5)]: k = abs(ibzk_kc - k_c).max(1).argmin() ibzk.append(k) eps_kn.append(atoms.calc.get_eigenvalues(k)[n - 1:n + 1]) if name == 'Ar': break deps_kn = vxc(atoms.calc, 'PBE')[0, ibzk, n - 1:n + 1] pbe0 = EXX(name, 'PBE0', ibzk, (n - 1, n + 1), txt=name + '.exx') pbe0.calculate() deps0_kn = pbe0.get_eigenvalue_contributions()[0] eps0_kn = eps_kn - deps_kn + deps0_kn data = {} for k, point in enumerate('GXL'): data[point] = [eps_kn[k][1] - eps_kn[0][0], eps0_kn[k, 1] - eps0_kn[0, 0]] data[point] += bfb[name][2 + k * 4:6 + k * 4] if name == 'Ar': break
atoms.get_potential_energy() atoms.calc.write(name + '.gpw', mode='all') ibzk_kc = atoms.calc.get_ibz_k_points() n = int(atoms.calc.get_number_of_electrons()) // 2 ibzk = [] eps_kn = [] for k_c in [(0, 0, 0), (0.5, 0.5, 0), (0.5, 0.5, 0.5)]: k = abs(ibzk_kc - k_c).max(1).argmin() ibzk.append(k) eps_kn.append(atoms.calc.get_eigenvalues(k)[n - 1:n + 1]) if name == 'Ar': break deps_kn = vxc(atoms.calc, 'PBE')[0, ibzk, n - 1:n + 1] pbe0 = EXX(name + '.gpw', 'PBE0', ibzk, (n - 1, n + 1), txt=name + '.exx') pbe0.calculate() deps0_kn = pbe0.get_eigenvalue_contributions()[0] eps0_kn = eps_kn - deps_kn + deps0_kn data = {} for k, point in enumerate('GXL'): data[point] = [eps_kn[k][1] - eps_kn[0][0], eps0_kn[k, 1] - eps0_kn[0, 0]] data[point] += bfb[name][2 + k * 4:6 + k * 4] if name == 'Ar': break
atoms.positions[:] += a / 2 calc = GPAW(h=0.25, nbands=4, convergence={'eigenstates': 7.8e-10}) atoms.calc = calc energy = atoms.get_potential_energy() niter = calc.get_number_of_iterations() # The three eigenvalues e[1], e[2], and e[3] must be degenerate: e = calc.get_eigenvalues() print(e[1] - e[3]) equal(e[1], e[3], 9.3e-8) energy_tolerance = 0.0003 niter_tolerance = 0 equal(energy, -23.6277, energy_tolerance) # Calculate non-selfconsistent PBE eigenvalues: from gpaw.xc.tools import vxc epbe0 = e - vxc(calc)[0, 0] + vxc(calc, 'PBE')[0, 0] # Calculate selfconsistent PBE eigenvalues: calc.set(xc='PBE') energy = atoms.get_potential_energy() epbe = calc.get_eigenvalues() de = epbe[1] - epbe[0] de0 = epbe0[1] - epbe0[0] print(de, de0) equal(de, de0, 0.001)
def hse(base_dir="./", kdens=6.0): emptybands = 20 convbands = 10 # If pbc in z direction, use vdW for relaxation as default! # if atoms.pbc[-1]: # Do not compare with np.bool_ ! # use_vdW = True # else: # use_vdW = False curr_dir = os.path.dirname(os.path.abspath(__file__)) param_file = os.path.join(curr_dir, "../parameters.json") gpw_file = os.path.join(base_dir, "gs.gpw") hse_file = os.path.join(base_dir, "hse.gpw") hse_nowfs_file = os.path.join(base_dir, "hse_nowfs.gpw") hse_eigen_file = os.path.join(base_dir, "hse_eigenvalues.npz") if not os.path.exists(gpw_file): parprint("No ground state calculation? Exit...") return 0 if os.path.exists(param_file): params = json.load(open(param_file, "r")) else: raise FileNotFoundError("no parameter file!") if not os.path.exists(hse_file): calc = GPAW(gpw_file) # reload the calculation atoms = calc.get_atoms() kpts = get_kpts_size(atoms, kdens) calc.set(nbands=-emptybands, fixdensity=True, kpts=kpts, convergence={'bands': -convbands}) calc.get_potential_energy() calc.write(hse_file, 'all') calc.write(hse_nowfs_file) # no wavefunction mpi.world.barrier() time.sleep(10) # is this needed? calc = GPAW(hse_file, txt=None) ns = calc.get_number_of_spins() nk = len(calc.get_ibz_k_points()) nb = calc.get_number_of_bands() vxc_pbe_skn = vxc(calc, 'PBE') vxc_pbe_nsk = numpy.ascontiguousarray(vxc_pbe_skn.transpose(2, 0, 1)) vxc_pbe_nsk = calc.wfs.bd.collect(vxc_pbe_nsk, broadcast=True) vxc_pbe_skn = vxc_pbe_nsk.transpose(1, 2, 0)[:, :, :-convbands] e_pbe_skn = np.zeros((ns, nk, nb)) for s in range(ns): for k in range(nk): e_pbe_skn[s, k, :] = calc.get_eigenvalues(spin=s, kpt=k) e_pbe_skn = e_pbe_skn[:, :, :-convbands] hse_calc = EXX(hse_file, xc='HSE06', bands=[0, nb - convbands]) hse_calc.calculate() vxc_hse_skn = hse_calc.get_eigenvalue_contributions() e_hse_skn = e_pbe_skn - vxc_pbe_skn + vxc_hse_skn ranks = [0] if mpi.world.rank in ranks: dct = dict(vxc_hse_skn=vxc_hse_skn, e_pbe_skn=e_pbe_skn, vxc_pbe_skn=vxc_pbe_skn, e_hse_skn=e_hse_skn) with open(hse_eigen_file, 'wb') as f: numpy.savez(f, **dct) parprint("Single HSE06 finished!")