import numpy as np from ase import Atoms from gpaw import GPAW from gpaw.xc.sic import SIC from gpaw.test import equal a = 7.0 atom = Atoms('N', magmoms=[3], cell=(a, a, a)) molecule = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.14)], cell=(a, a, a)) atom.center() molecule.center() calc = GPAW(xc=SIC(), txt='n2.sic.new3b.txt', setups='hgh') atom.set_calculator(calc) e1 = atom.get_potential_energy() molecule.set_calculator(calc) e2 = molecule.get_potential_energy() F_ac = molecule.get_forces() print 2 * e1 - e2 print F_ac
def calculate(self): ESIC = 0 xc = self.paw.hamiltonian.xc assert xc.type == 'LDA' # Calculate the contribution from the core orbitals for a in self.paw.density.D_asp: setup = self.paw.density.setups[a] # TODO: Use XC which has been used to calculate the actual # calculation. # TODO: Loop over setups, not atoms. print('Atom core SIC for ', setup.symbol) print('%10s%10s%10s' % ('E_xc[n_i]', 'E_Ha[n_i]', 'E_SIC')) g = Generator(setup.symbol, xcname='LDA', nofiles=True, txt=None) g.run(**parameters[setup.symbol]) njcore = g.njcore for f, l, e, u in zip(g.f_j[:njcore], g.l_j[:njcore], g.e_j[:njcore], g.u_j[:njcore]): # Calculate orbital density # NOTE: It's spherically symmetrized! #n = np.dot(self.f_j, assert l == 0, ('Not tested for l>0 core states') na = np.where(abs(u) < 1e-160, 0, u)**2 / (4 * pi) na[1:] /= g.r[1:]**2 na[0] = na[1] nb = np.zeros(g.N) v_sg = np.zeros((2, g.N)) e_g = np.zeros(g.N) vHr = np.zeros(g.N) Exc = xc.calculate_spherical(g.rgd, np.array([na, nb]), v_sg) hartree(0, na * g.r * g.dr, g.r, vHr) EHa = 2 * pi * np.dot(vHr * na * g.r, g.dr) print( ('%10.2f%10.2f%10.2f' % (Exc * Hartree, EHa * Hartree, -f * (EHa + Exc) * Hartree))) ESIC += -f * (EHa + Exc) sic = SIC(finegrid=True, coulomb_factor=1, xc_factor=1) sic.initialize(self.paw.density, self.paw.hamiltonian, self.paw.wfs) sic.set_positions(self.paw.atoms.get_scaled_positions()) print('Valence electron sic ') print('%10s%10s%10s%10s%10s%10s' % ('spin', 'k-point', 'band', 'E_xc[n_i]', 'E_Ha[n_i]', 'E_SIC')) assert len( self.paw.wfs.kpt_u) == 1, ('Not tested for bulk calculations') for s, spin in sic.spin_s.items(): spin.initialize_orbitals() spin.update_optimal_states() spin.update_potentials() n = 0 for xc, c in zip(spin.exc_m, spin.ecoulomb_m): print(('%10i%10i%10i%10.2f%10.2f%10.2f' % (s, 0, n, -xc * Hartree, -c * Hartree, 2 * (xc + c) * Hartree))) n += 1 ESIC += spin.esic print('Total correction for self-interaction energy:') print('%10.2f eV' % (ESIC * Hartree)) print('New total energy:') total = (ESIC * Hartree + self.paw.get_potential_energy() + self.paw.get_reference_energy()) print('%10.2f eV' % total) return total
def calculate(self): ESIC = 0 xc = self.paw.hamiltonian.xc assert xc.type == 'LDA' # Calculate the contribution from the core orbitals for a in self.paw.density.D_asp: setup = self.paw.density.setups[a] # TODO: Use XC which has been used to calculate the actual # calculation. # TODO: Loop over setups, not atoms. print('Atom core SIC for ', setup.symbol) print('%10s%10s%10s' % ('E_xc[n_i]', 'E_Ha[n_i]', 'E_SIC')) g = Generator(setup.symbol, xcname='LDA', nofiles=True, txt=None) g.run(**parameters[setup.symbol]) njcore = g.njcore for f, l, e, u in zip(g.f_j[:njcore], g.l_j[:njcore], g.e_j[:njcore], g.u_j[:njcore]): # Calculate orbital density # NOTE: It's spherically symmetrized! #n = np.dot(self.f_j, assert l == 0, ('Not tested for l>0 core states') na = np.where(abs(u) < 1e-160, 0,u)**2 / (4 * pi) na[1:] /= g.r[1:]**2 na[0] = na[1] nb = np.zeros(g.N) v_sg = np.zeros((2, g.N)) e_g = np.zeros(g.N) vHr = np.zeros(g.N) Exc = xc.calculate_spherical(g.rgd, np.array([na, nb]), v_sg) hartree(0, na * g.r * g.dr, g.r, vHr) EHa = 2*pi*np.dot(vHr*na*g.r , g.dr) print(('%10.2f%10.2f%10.2f' % (Exc * Hartree, EHa * Hartree, -f*(EHa+Exc) * Hartree))) ESIC += -f*(EHa+Exc) sic = SIC(finegrid=True, coulomb_factor=1, xc_factor=1) sic.initialize(self.paw.density, self.paw.hamiltonian, self.paw.wfs) sic.set_positions(self.paw.atoms.get_scaled_positions()) print('Valence electron sic ') print('%10s%10s%10s%10s%10s%10s' % ('spin', 'k-point', 'band', 'E_xc[n_i]', 'E_Ha[n_i]', 'E_SIC')) assert len(self.paw.wfs.kpt_u)==1, ('Not tested for bulk calculations') for s, spin in sic.spin_s.items(): spin.initialize_orbitals() spin.update_optimal_states() spin.update_potentials() n = 0 for xc, c in zip(spin.exc_m, spin.ecoulomb_m): print(('%10i%10i%10i%10.2f%10.2f%10.2f' % (s, 0, n, -xc * Hartree, -c * Hartree, 2 * (xc + c) * Hartree))) n += 1 ESIC += spin.esic print('Total correction for self-interaction energy:') print('%10.2f eV' % (ESIC * Hartree)) print('New total energy:') total = (ESIC * Hartree + self.paw.get_potential_energy() + self.paw.get_reference_energy()) print('%10.2f eV' % total) return total
from __future__ import print_function from ase import Atoms from gpaw import GPAW from gpaw.xc.sic import SIC a = 7.0 atom = Atoms('N', magmoms=[3], cell=(a, a, a)) molecule = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.14)], cell=(a, a, a)) atom.center() molecule.center() calc = GPAW(xc=SIC(), eigensolver='rmm-diis', h=0.17, txt='n2.sic.new3b.txt', setups='hgh') atom.set_calculator(calc) e1 = atom.get_potential_energy() molecule.set_calculator(calc) e2 = molecule.get_potential_energy() F_ac = molecule.get_forces() print(2 * e1 - e2) print(F_ac)
def XC(kernel, parameters=None, atoms=None, collinear=True): """Create XCFunctional object. kernel: XCKernel object, dict or str Kernel object or name of functional. parameters: ndarray Parameters for BEE functional. Recognized names are: LDA, PW91, PBE, revPBE, RPBE, BLYP, HCTH407, TPSS, M06-L, revTPSS, vdW-DF, vdW-DF2, EXX, PBE0, B3LYP, BEE, GLLBSC. One can also use equivalent libxc names, for example GGA_X_PBE+GGA_C_PBE is equivalent to PBE, and LDA_X to the LDA exchange. In this way one has access to all the functionals defined in libxc. See xc_funcs.h for the complete list. """ if isinstance(kernel, basestring): kernel = xc_string_to_dict(kernel) kwargs = {} if isinstance(kernel, dict): kwargs = kernel.copy() name = kwargs.pop('name') backend = kwargs.pop('backend', None) if backend == 'libvdwxc' or name == 'vdW-DF-cx': # Must handle libvdwxc before old vdw implementation to override # behaviour for 'name'. Also, cx is not implemented by the old # vdW module, so that always refers to libvdwxc. from gpaw.xc.libvdwxc import get_libvdwxc_functional return get_libvdwxc_functional(name=name, **kwargs) elif backend: error_msg = "A special backend for the XC functional was given, "\ "but not understood. Please check if there's a typo." raise ValueError(error_msg) if name in ['vdW-DF', 'vdW-DF2', 'optPBE-vdW', 'optB88-vdW', 'C09-vdW', 'mBEEF-vdW', 'BEEF-vdW']: from gpaw.xc.vdw import VDWFunctional return VDWFunctional(name, **kwargs) elif name in ['EXX', 'PBE0', 'B3LYP', 'CAMY-BLYP', 'CAMY-B3LYP', 'LCY-BLYP', 'LCY-PBE']: from gpaw.xc.hybrid import HybridXC return HybridXC(name, **kwargs) elif name.startswith('LCY-') or name.startswith('CAMY-'): parts = name.split('(') from gpaw.xc.hybrid import HybridXC return HybridXC(parts[0], omega=float(parts[1][:-1])) elif name in ['HSE03', 'HSE06']: from gpaw.xc.exx import EXX return EXX(name, **kwargs) elif name == 'BEE1': from gpaw.xc.bee import BEE1 kernel = BEE1(parameters) elif name == 'BEE2': from gpaw.xc.bee import BEE2 kernel = BEE2(parameters) elif name.startswith('GLLB'): from gpaw.xc.gllb.nonlocalfunctionalfactory import \ NonLocalFunctionalFactory # Pass kwargs somewhere? xc = NonLocalFunctionalFactory().get_functional_by_name(name) xc.print_functional() return xc elif name == 'LB94': from gpaw.xc.lb94 import LB94 kernel = LB94() elif name == 'TB09': from gpaw.xc.tb09 import TB09 return TB09(**kwargs) elif name.endswith('PZ-SIC'): from gpaw.xc.sic import SIC return SIC(xc=name[:-7], **kwargs) elif name in ['TPSS', 'M06-L', 'M06L', 'revTPSS']: if name == 'M06L': name = 'M06-L' warnings.warn('Please use M06-L instead of M06L') from gpaw.xc.kernel import XCKernel kernel = XCKernel(name) elif name.startswith('old'): from gpaw.xc.kernel import XCKernel kernel = XCKernel(name[3:]) elif name == 'PPLDA': from gpaw.xc.lda import PurePythonLDAKernel kernel = PurePythonLDAKernel() elif name in ['pyPBE', 'pyPBEsol', 'pyRPBE', 'pyzvPBEsol']: from gpaw.xc.gga import PurePythonGGAKernel kernel = PurePythonGGAKernel(name) elif name == '2D-MGGA': from gpaw.xc.mgga import PurePython2DMGGAKernel kernel = PurePython2DMGGAKernel(name, parameters) elif name[0].isdigit(): from gpaw.xc.parametrizedxc import ParametrizedKernel kernel = ParametrizedKernel(name) elif name == 'null': from gpaw.xc.kernel import XCNull kernel = XCNull() elif name == 'QNA': from gpaw.xc.qna import QNA return QNA(atoms, kernel['parameters'], kernel['setup_name'], alpha=kernel['alpha'], stencil=kwargs.get('stencil', 2)) else: kernel = LibXC(name) if kernel.type == 'LDA': if not collinear: kernel = NonCollinearLDAKernel(kernel) xc = LDA(kernel, **kwargs) return xc elif kernel.type == 'GGA': return GGA(kernel, **kwargs) else: return MGGA(kernel, **kwargs)