def __init__(self, bee, xcoefs, ldac, ggac): """BEEVDW kernel. parameters: bee : str choose BEE1 or BEE2 exchange basis expansion. xcoefs : array coefficients for exchange. ldac : float coefficient for LDA correlation. pbec : float coefficient for PBE correlation. """ if bee == 'BEE2': self.BEE = BEE2(xcoefs) self.GGAc = LibXC('GGA_C_PBE') self.xtype = 'GGA' self.type = 'GGA' elif bee == 'BEE3': self.BEE = LibXC('MGGA_X_MBEEFVDW') self.GGAc = LibXC('GGA_C_PBE_SOL') self.xtype = 'MGGA' self.type = 'MGGA' else: raise ValueError('Unknown BEE exchange: %s', bee) self.LDAc = LibXC('LDA_C_PW') self.ldac = ldac self.ggac = ggac if bee in ['BEE1', 'BEE2']: self.ggac -= 1.0 self.name = 'BEEVDW'
def VDWFunctional(name, fft=True, **kwargs): if name == 'vdW-DF': kernel = LibXC('GGA_X_PBE_R+LDA_C_PW') elif name == 'vdW-DF2': kernel = LibXC('GGA_X_RPW86+LDA_C_PW') kwargs['Zab'] = -1.887 elif name == 'optPBE-vdW': kernel = LibXC('GGA_X_OPTPBE_VDW+LDA_C_PW') elif name == 'optB88-vdW': kernel = LibXC('GGA_X_OPTB88_VDW+LDA_C_PW') elif name == 'C09-vdW': kernel = LibXC('GGA_X_C09X+LDA_C_PW') elif name == 'BEEF-vdW': from gpaw.xc.bee import BEEVDWKernel kernel = BEEVDWKernel('BEE2', None, 0.600166476948828631066, 0.399833523051171368934) kwargs['Zab'] = -1.887 kwargs['setup_name'] = 'PBE' elif name == 'mBEEF-vdW': from gpaw.xc.bee import BEEVDWKernel kernel = BEEVDWKernel('BEE3', None, 0.405258352, 0.356642240) kwargs['Zab'] = -1.887 kwargs['vdwcoef'] = 0.886774972 kwargs['Nr'] = 4096 kwargs['setup_name'] = 'PBEsol' assert fft return MGGAFFTVDWFunctional(name, kernel, **kwargs) else: 2 / 0 if fft: return GGAFFTVDWFunctional(name, kernel, **kwargs) return GGARealSpaceVDWFunctional(name, kernel, **kwargs)
def __init__(self, just_kidding=False): self.just_kidding = just_kidding self.type = 'GGA' self.lda_c = LibXC('LDA_C_PW') if self.just_kidding: self.name = 'purepython rPW86_with_%s' % self.lda_c.name else: self.name = 'purepython cx'
def __init__(self, c=None): self.tb09 = LibXC('MGGA_X_TB09').xc.tb09 self.ldac = LibXC('LDA_C_PW') self.fixedc = c is not None # calculate c or use fixed value self.c = c # amount of "exact exchange" self.n = 0 # Lebedev quadrature point number (0-49) self.sign = 1.0 # sign of PAW correction: +1 for AE and -1 for PS self.I = None # integral from Eq. (3)
def __init__(self, xcoefs, ldac, pbec, lyp): self.BEE1 = BEE1(xcoefs) self.LDAc = LibXC('LDA_C_PW') self.PBEc = LibXC('GGA_C_PBE') self.LYP = LibXC('GGA_C_LYP') self.ldac = ldac self.pbec = pbec self.lyp = lyp self.type = 'GGA' self.name = 'BEEVDW'
def vdw_df2(**kwargs): kwargs1 = dict(name='vdW-DF2', setup_name='PBE', semilocal_xc=GGA(LibXC('GGA_X_RPW86+LDA_C_PW'), stencil=kwargs.pop('stencil', 2))) kwargs1.update(kwargs) return VDWXC(**kwargs1)
def create_xc(func, mode): isinstance(func, str) isinstance(mode, int) if mode == 0: xc = LibXC(func) else: xc = XCKernel(func) return xc
def calculate(self, e_g, n_sg, dedn_sg, sigma_xg=None, dedsigma_xg=None, tau_sg=None, dedtau_sg=None): n_g = n_sg[0] m_vg = n_sg[1:4] m_g = (m_vg**2).sum(0)**0.5 nnew_sg = np.empty((2,) + n_g.shape) nnew_sg[:] = n_g nnew_sg[0] += m_g nnew_sg[1] -= m_g nnew_sg *= 0.5 vnew_sg = np.zeros_like(nnew_sg) LibXC.calculate(self, e_g, nnew_sg, vnew_sg) dedn_sg[0] += 0.5 * vnew_sg.sum(0) vnew_sg /= np.where(m_g < 1e-15, 1, m_g) dedn_sg[1:4] += 0.5 * vnew_sg[0] * m_vg dedn_sg[1:4] -= 0.5 * vnew_sg[1] * m_vg
def vdw_C09(**kwargs): kwargs1 = dict(name='vdW-C09', libvdwxc_name='vdW-DF', setup_name='PBE', semilocal_xc=GGA(LibXC('GGA_X_C09X+LDA_C_PW'), stencil=kwargs.pop('stencil', 2))) kwargs1.update(kwargs) return VDWXC(**kwargs1)
def test_selfconsistent(): from gpaw import GPAW from ase.build import molecule from gpaw.xc.gga import GGA system = molecule('H2O') system.center(vacuum=3.) def test(xc): calc = GPAW( mode='lcao', xc=xc, setups='sg15', txt='gpaw.%s.txt' % str(xc) # .kernel.name ) system.set_calculator(calc) return system.get_potential_energy() libxc_results = {} for name in ['GGA_X_PBE_R+LDA_C_PW', 'GGA_X_RPW86+LDA_C_PW']: xc = GGA(LibXC(name)) e = test(xc) libxc_results[name] = e cx_gga_results = {} cx_gga_results['rpw86'] = test(GGA(CXGGAKernel(just_kidding=True))) cx_gga_results['lv_rpw86'] = test(GGA(CXGGAKernel(just_kidding=False))) vdw_results = {} vdw_coef0_results = {} for vdw in [vdw_df(), vdw_df2(), vdw_df_cx()]: vdw.vdwcoef = 0.0 vdw_coef0_results[vdw.__class__.__name__] = test(vdw) vdw.vdwcoef = 1.0 # Leave nicest text file by running real calc last vdw_results[vdw.__class__.__name__] = test(vdw) from gpaw.mpi import world # These tests basically verify that the LDA/GGA parts of vdwdf # work correctly. if world.rank == 0: print('Now comparing...') err1 = cx_gga_results['rpw86'] - libxc_results['GGA_X_RPW86+LDA_C_PW'] print('Our rpw86 must be identical to that of libxc. Err=%e' % err1) print('RPW86 interpolated with Langreth-Vosko stuff differs by %f' % (cx_gga_results['lv_rpw86'] - cx_gga_results['rpw86'])) print('Each vdwdf with vdwcoef zero must yield same result as gga' 'kernel') err_df1 = vdw_coef0_results['VDWDF'] - libxc_results['GGA_X_PBE_R+' 'LDA_C_PW'] print(' df1 err=%e' % err_df1) err_df2 = vdw_coef0_results['VDWDF2'] - libxc_results['GGA_X_RPW86+' 'LDA_C_PW'] print(' df2 err=%e' % err_df2) err_cx = vdw_coef0_results['VDWDFCX'] - cx_gga_results['lv_rpw86'] print(' cx err=%e' % err_cx)
def XC(kernel, parameters=None): """Create XCFunctional object. kernel: XCKernel object 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, M06L, 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 gpaw.xc.libxc_functionals.py for the complete list. """ if isinstance(kernel, str): name = kernel if name in ['vdW-DF', 'vdW-DF2']: from gpaw.xc.vdw import FFTVDWFunctional return FFTVDWFunctional(name) elif name in ['EXX', 'PBE0', 'B3LYP']: from gpaw.xc.hybrid import HybridXC return HybridXC(name) elif name == 'BEE1': from gpaw.xc.bee import BEE1 kernel = BEE1(parameters) elif name.startswith('GLLB'): from gpaw.xc.gllb.nonlocalfunctionalfactory import \ NonLocalFunctionalFactory 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.startswith('ODD_'): from ODD import ODDFunctional return ODDFunctional(name[4:]) elif name.endswith('PZ-SIC'): try: from ODD import PerdewZungerSIC as SIC return SIC(xc=name[:-7]) except: from gpaw.xc.sic import SIC return SIC(xc=name[:-7]) elif name.startswith('old'): from gpaw.xc.kernel import XCKernel kernel = XCKernel(name[3:]) else: kernel = LibXC(kernel) if kernel.type == 'LDA': return LDA(kernel) elif kernel.type == 'GGA': return GGA(kernel) else: return MGGA(kernel)
def __init__(self, name): self.name = name self.kernels = [] self.coefs = [] self.type = 'LDA' for x in name.split('+'): c, n = x.split('_', 1) self.coefs.append(float(c)) kernel = LibXC(n) self.kernels.append(kernel) if kernel.type == 'GGA': self.type = 'GGA'
def vdw_df_cx(**kwargs): # cx semilocal exchange is in libxc 2.2.2 or newer (or maybe from older) kernel = kwargs.get('kernel') if kernel is None: kernel = LibXC('GGA_X_LV_RPW86+LDA_C_PW') kwargs1 = dict( name='vdW-DF-cx', setup_name='PBE', # PBEsol is most correct but not distributed by default. semilocal_xc=GGA(kernel, stencil=kwargs.pop('stencil', 2))) kwargs1.update(kwargs) return VDWXC(**kwargs1)
def calculate(self, e_g, n_sg, dedn_sg, sigma_xg=None, dedsigma_xg=None, tau_sg=None, dedtau_sg=None): n_g = n_sg[0] m_vg = n_sg[1:4] m_g = (m_vg**2).sum(0)**0.5 nnew_sg = np.empty((2, ) + n_g.shape) nnew_sg[:] = n_g nnew_sg[0] += m_g nnew_sg[1] -= m_g nnew_sg *= 0.5 vnew_sg = np.zeros_like(nnew_sg) LibXC.calculate(self, e_g, nnew_sg, vnew_sg) dedn_sg[0] += 0.5 * vnew_sg.sum(0) vnew_sg /= np.where(m_g < 1e-15, 1, m_g) dedn_sg[1:4] += 0.5 * vnew_sg[0] * m_vg dedn_sg[1:4] -= 0.5 * vnew_sg[1] * m_vg
def vdw_df_cx(*args, **kwargs): try: # Exists in libxc 2.2.2 or newer (or maybe from older) kernel = LibXC('GGA_X_LV_RPW86+LDA_C_PW') except NameError: kernel = CXGGAKernel() # Hidden debug feature if kwargs.get('gga_backend') == 'purepython': kernel = CXGGAKernel() kwargs.pop('gga_backend') assert 'gga_backend' not in kwargs return VDWXC(semilocal_xc=GGA(kernel), name='vdW-DF-CX', *args, **kwargs)
def test_derivatives(): gen = np.random.RandomState(1) shape = (1, 20, 20, 20) ngpts = np.product(shape) n_sg = gen.rand(*shape) sigma_xg = np.zeros(shape) sigma_xg[:] = gen.rand(*shape) qe_kernel = CXGGAKernel(just_kidding=True) libxc_kernel = LibXC('GGA_X_RPW86+LDA_C_PW') cx_kernel = CXGGAKernel(just_kidding=False) def check(kernel, n_sg, sigma_xg): e_g = np.zeros(shape[1:]) dedn_sg = np.zeros(shape) dedsigma_xg = np.zeros(shape) kernel.calculate(e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg) return e_g, dedn_sg, dedsigma_xg def check_and_write(kernel): n1_sg = n_sg.copy() e_g, dedn_sg, dedsigma_xg = check(kernel, n_sg, sigma_xg) dedn = dedn_sg[0, 0, 0, 0] dedsigma = dedsigma_xg[0, 0, 0, 0] dn = 1e-6 n1_sg = n_sg.copy() n1_sg[0, 0, 0, 0] -= dn / 2. e1_g, _, _ = check(kernel, n1_sg, sigma_xg) n1_sg[0, 0, 0, 0] += dn e2_g, _, _ = check(kernel, n1_sg, sigma_xg) dedn_fd = (e2_g[0, 0, 0] - e1_g[0, 0, 0]) / dn dedn_err = abs(dedn - dedn_fd) print('e', e_g.sum() / ngpts) print('dedn', dedn, 'fd', dedn_fd, 'err %e' % dedn_err) sigma1_xg = sigma_xg.copy() sigma1_xg[0, 0, 0, 0] -= dn / 2. e1s_g, _, _ = check(kernel, n_sg, sigma1_xg) sigma1_xg[0, 0, 0, 0] += dn e2s_g, _, _ = check(kernel, n_sg, sigma1_xg) dedsigma_fd = (e2s_g[0, 0, 0] - e1s_g[0, 0, 0]) / dn dedsigma_err = dedsigma - dedsigma_fd print('dedsigma', dedsigma, 'fd', dedsigma_fd, 'err %e' % dedsigma_err) return e_g, dedn_sg, dedsigma_xg print('pw86r libxc') e_lxc_g, dedn_lxc_g, dedsigma_lxc_g = check_and_write(libxc_kernel) print() print('pw86r ours') e_qe_g, dedn_qe_g, dedsigma_qe_g = check_and_write(qe_kernel) print() print('cx') check_and_write(cx_kernel) print() print('lxc vs qe discrepancies') print('=======================') e_err = np.abs(e_lxc_g - e_qe_g).max() print('e', e_err) dedn_err = np.abs(dedn_qe_g - dedn_lxc_g).max() dedsigma_err = np.abs(dedsigma_lxc_g - dedsigma_qe_g).max() print('dedn', dedn_err) print('dedsigma', dedsigma_err)
class CXGGAKernel: def __init__(self, just_kidding=False): self.just_kidding = just_kidding self.type = 'GGA' self.lda_c = LibXC('LDA_C_PW') if self.just_kidding: self.name = 'purepython rPW86_with_%s' % self.lda_c.name else: self.name = 'purepython cx' def calculate(self, e_g, n_sg, v_sg, sigma_xg, dedsigma_xg): e_g[:] = 0.0 dedsigma_xg[:] = 0.0 self.lda_c.calculate(e_g, n_sg, v_sg, sigma_xg, dedsigma_xg) for arr in [n_sg, v_sg, sigma_xg, dedsigma_xg]: assert len(arr) == 1 self._exchange(n_sg[0], sigma_xg[0], e_g, v_sg[0], dedsigma_xg[0]) def _exchange(self, rho, grho, sx, v1x, v2x): """Calculate cx local exchange. Note that this *adds* to the energy density sx so that it can be called after LDA correlation part without ruining anything. Also it adds to v1x and v2x as is normal in GPAW.""" tol = 1e-20 rho[rho < tol] = tol grho[grho < tol] = tol alp = 0.021789 beta = 1.15 a = 1.851 b = 17.33 c = 0.163 mu_LM = 0.09434 s_prefactor = 6.18733545256027 Ax = -0.738558766382022 # = -3./4. * (3./pi)**(1./3) four_thirds = 4. / 3. grad_rho = np.sqrt(grho) # eventually we need s to power 12. Clip to avoid overflow # (We have individual tolerances on both rho and grho, but # they are not sufficient to guarantee this) s_1 = (grad_rho / (s_prefactor * rho**four_thirds)).clip(0.0, 1e20) s_2 = s_1 * s_1 s_3 = s_2 * s_1 s_4 = s_3 * s_1 s_5 = s_4 * s_1 s_6 = s_5 * s_1 fs_rPW86 = (1.0 + a * s_2 + b * s_4 + c * s_6)**(1. / 15.) if self.just_kidding: fs = fs_rPW86 else: fs = (1.0 + mu_LM * s_2) / (1.0 + alp * s_6) \ + alp * s_6 / (beta + alp * s_6) * fs_rPW86 # the energy density for the exchange. sx[:] += Ax * rho**four_thirds * fs df_rPW86_ds = (1. / (15. * fs_rPW86**14.0)) * \ (2 * a * s_1 + 4 * b * s_3 + 6 * c * s_5) if self.just_kidding: df_ds = df_rPW86_ds # XXXXXXXXXXXXXXXXXXXX else: df_ds = 1. / (1. + alp * s_6)**2 \ * (2.0 * mu_LM * s_1 * (1. + alp * s_6) - 6.0 * alp * s_5 * (1. + mu_LM * s_2)) \ + alp * s_6 / (beta + alp * s_6) * df_rPW86_ds \ + 6.0 * alp * s_5 * fs_rPW86 / (beta + alp * s_6) \ * (1. - alp * s_6 / (beta + alp * s_6)) # de/dn. This is the partial derivative of sx wrt. n, for s constant v1x[:] += Ax * four_thirds * (rho**(1. / 3.) * fs - grad_rho / (s_prefactor * rho) * df_ds) # de/d(nabla n). The other partial derivative v2x[:] += 0.5 * Ax * df_ds / (s_prefactor * grad_rho)
def __init__(self, world=None, Zab=-0.8491, vdwcoef=1.0, q0cut=5.0, phi0=0.5, ds=1.0, Dmax=20.0, nD=201, ndelta=21, soft_correction=False, setup_name='revPBE', verbose=False, energy_only=False): """vdW-DF. parameters: name: str Name of functional. world: MPI communicator Communicator to parallelize over. Defaults to gpaw.mpi.world. q0cut: float Maximum value for q0. phi0: float Smooth value for phi(0,0). ds: float Cutoff for smooth kernel. Dmax: float Maximum value for D. nD: int Number of values for D in kernel-table. ndelta: int Number of values for delta in kernel-table. soft_correction: bool Correct for soft kernel. kernel: Which kernel to use. Zab: parameter in nonlocal kernel. vdwcoef: float Scaling of vdW energy. verbose: bool Print useful information. """ if world is None: self.world = mpi.world else: self.world = world self.Zab = Zab self.vdwcoef = vdwcoef self.q0cut = q0cut self.phi0 = phi0 self.ds = ds self.delta_i = np.linspace(0, 1.0, ndelta) self.D_j = np.linspace(0, Dmax, nD) self.verbose = verbose self.read_table() self.soft_correction = soft_correction if soft_correction: dD = self.D_j[1] self.C_soft = np.dot(self.D_j**2, self.phi_ij[0]) * 4 * pi * dD self.gd = None self.energy_only = energy_only self.timer = nulltimer self.LDAc = LibXC('LDA_C_PW') self.setup_name = setup_name
def __init__(self): LibXC.__init__(self, 'LDA')
class TB09Kernel: name = 'TB09' type = 'MGGA' alpha = -0.012 beta = 1.023 def __init__(self, c=None): self.tb09 = LibXC('MGGA_X_TB09').xc.tb09 self.ldac = LibXC('LDA_C_PW') self.fixedc = c is not None # calculate c or use fixed value self.c = c # amount of "exact exchange" self.n = 0 # Lebedev quadrature point number (0-49) self.sign = 1.0 # sign of PAW correction: +1 for AE and -1 for PS self.I = None # integral from Eq. (3) def calculate(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg, tau_sg, dedtau_sg): ns = len(n_sg) n_sg[n_sg < 1e-6] = 1e-6 if n_sg.ndim == 4: if not self.fixedc: if self.c is None: # We don't have the integral yet - just use 1.0: self.c = 1.0 else: self.I = self.world.sum(self.I) self.c = (self.alpha + self.beta * (self.I / self.gd.volume)**0.5) # Start calculation of c for use in the next SCF step: if ns == 1: gradn_g = sigma_xg[0]**0.5 else: gradn_g = (sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2])**0.5 self.I = self.gd.integrate(gradn_g / n_sg.sum(0)) # The domain is not distributed like the PAW corrections: self.I /= self.world.size lapl_sg = self.gd.empty(ns) for n_g, lapl_g in zip(n_sg, lapl_sg): self.lapl.apply(n_g, lapl_g) else: rgd = self.rgd lapl_sg = [] for n_Lg in self.n_sLg: lapl_g = rgd.laplace(np.dot(self.Y_L, n_Lg)) l = 0 L1 = 0 while L1 < len(self.Y_L): L2 = L1 + 2 * l + 1 n_g = np.dot(self.Y_L[L1:L2], n_Lg[L1:L2]) with seterr(divide='ignore', invalid='ignore'): lapl_g -= l * (l + 1) * n_g / rgd.r_g**2 lapl_g[0] = 0.0 L1 = L2 l += 1 lapl_sg.append(lapl_g) if not self.fixedc: # PAW corrections to integral: w = self.sign * weight_n[self.n] if ns == 1: gradn_g = sigma_xg[0]**0.5 else: gradn_g = (sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2])**0.5 self.I += w * rgd.integrate(gradn_g / n_sg.sum(0)) self.n += 1 if self.n == len(weight_n): self.n = 0 self.sign = -self.sign # dedn_sg[:] = 0.0 sigma_xg[sigma_xg < 1e-10] = 1e-10 tau_sg[tau_sg < 1e-10] = 1e-10 for n_g, sigma_g, lapl_g, tau_g, v_g in zip(n_sg, sigma_xg[::2], lapl_sg, tau_sg, dedn_sg): self.tb09(self.c, n_g.ravel(), sigma_g, lapl_g, tau_g, v_g, dedsigma_xg) self.ldac.calculate(e_g, n_sg, dedn_sg) e_g[:] = 0.0 dedsigma_xg[:] = 0.0 dedtau_sg[:] = 0.0
def vdw_C09(*args, **kwargs): return VDWXC(semilocal_xc=GGA(LibXC('GGA_X_C09X+LDA_C_PW')), name='vdW-C09', libvdwxc_name='vdW-DF', *args, **kwargs)
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)
def vdw_optB88(*args, **kwargs): return VDWXC(semilocal_xc=GGA(LibXC('GGA_X_OPTB88_VDW+LDA_C_PW')), name='optB88', libvdwxc_name='vdW-DF', *args, **kwargs)
class BEEVDWKernel(XCKernel): """Kernel for BEEVDW functionals.""" def __init__(self, bee, xcoefs, ldac, ggac): """BEEVDW kernel. parameters: bee : str choose BEE1 or BEE2 exchange basis expansion. xcoefs : array coefficients for exchange. ldac : float coefficient for LDA correlation. pbec : float coefficient for PBE correlation. """ if bee == 'BEE2': self.BEE = BEE2(xcoefs) self.GGAc = LibXC('GGA_C_PBE') self.xtype = 'GGA' self.type = 'GGA' elif bee == 'BEE3': self.BEE = LibXC('MGGA_X_MBEEFVDW') self.GGAc = LibXC('GGA_C_PBE_SOL') self.xtype = 'MGGA' self.type = 'MGGA' else: raise ValueError('Unknown BEE exchange: %s', bee) self.LDAc = LibXC('LDA_C_PW') self.ldac = ldac self.ggac = ggac if bee in ['BEE1', 'BEE2']: self.ggac -= 1.0 self.name = 'BEEVDW' def calculate(self, e_g, n_sg, dedn_sg, sigma_xg=None, dedsigma_xg=None, tau_sg=None, dedtau_sg=None): if debug: self.check_arguments(e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg, tau_sg, dedtau_sg) if self.xtype == 'GGA': self.BEE.calculate(e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg) elif self.xtype == 'MGGA': self.BEE.calculate(e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg, tau_sg, dedtau_sg) else: raise ValueError('Unexpected value of xtype:', self.xtype) e0_g = np.empty_like(e_g) dedn0_sg = np.empty_like(dedn_sg) dedsigma0_xg = np.empty_like(dedsigma_xg) for coef, kernel in [(self.ldac, self.LDAc), (self.ggac, self.GGAc)]: dedn0_sg[:] = 0.0 kernel.calculate(e0_g, n_sg, dedn0_sg, sigma_xg, dedsigma0_xg) e_g += coef * e0_g dedn_sg += coef * dedn0_sg if kernel.type == 'GGA': dedsigma_xg += coef * dedsigma0_xg
def XC(kernel, parameters=None): """Create XCFunctional object. kernel: XCKernel object 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): name = kernel 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) elif name in ['EXX', 'PBE0', 'B3LYP']: from gpaw.xc.hybrid import HybridXC return HybridXC(name) elif name in ['HSE03', 'HSE06']: from gpaw.xc.exx import EXX return EXX(name) 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 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() elif name.startswith('ODD_'): from ODD import ODDFunctional return ODDFunctional(name[4:]) elif name.endswith('PZ-SIC'): try: from ODD import PerdewZungerSIC as SIC return SIC(xc=name[:-7]) except: from gpaw.xc.sic import SIC return SIC(xc=name[:-7]) 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) else: kernel = LibXC(kernel) if kernel.type == 'LDA': return LDA(kernel) elif kernel.type == 'GGA': return GGA(kernel) else: return MGGA(kernel)
class VDWFunctional(GGA): """Base class for vdW-DF.""" def __init__( self, name, world=None, q0cut=5.0, phi0=0.5, ds=1.0, Dmax=20.0, nD=201, ndelta=21, soft_correction=False, kernel=None, Zab=None, vdwcoef=1.0, verbose=False, energy_only=False, ): """vdW-DF. parameters: name: str Name of functional. world: MPI communicator Communicator to parallelize over. Defaults to gpaw.mpi.world. q0cut: float Maximum value for q0. phi0: float Smooth value for phi(0,0). ds: float Cutoff for smooth kernel. Dmax: float Maximum value for D. nD: int Number of values for D in kernel-table. ndelta: int Number of values for delta in kernel-table. soft_correction: bool Correct for soft kernel. kernel: Which kernel to use. Zab: parameter in nonlocal kernel. vdwcoef: float Scaling of vdW energy. verbose: bool Print useful information. """ if world is None: self.world = mpi.world else: self.world = world self.q0cut = q0cut self.phi0 = phi0 self.ds = ds self.delta_i = np.linspace(0, 1.0, ndelta) self.D_j = np.linspace(0, Dmax, nD) self.verbose = verbose self.read_table() self.soft_correction = soft_correction if soft_correction: dD = self.D_j[1] self.C_soft = np.dot(self.D_j ** 2, self.phi_ij[0]) * 4 * pi * dD self.gd = None self.energy_only = energy_only self.timer = nulltimer if name == "vdW-DF": assert kernel is None and Zab is None kernel = LibXC("GGA_X_PBE_R+LDA_C_PW") Zab = -0.8491 elif name == "vdW-DF2": assert kernel is None and Zab is None kernel = LibXC("GGA_X_RPW86+LDA_C_PW") Zab = -1.887 elif name == "optPBE-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_OPTPBE_VDW+LDA_C_PW") Zab = -0.8491 elif name == "optB88-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_OPTB88_VDW+LDA_C_PW") Zab = -0.8491 elif name == "C09-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_C09X+LDA_C_PW") Zab = -0.8491 else: assert kernel is not None and Zab is not None self.Zab = Zab GGA.__init__(self, kernel) self.vdwcoef = vdwcoef self.name = name self.LDAc = LibXC("LDA_C_PW") def get_setup_name(self): return "revPBE" def initialize(self, density, hamiltonian, wfs, occupations): self.timer = wfs.timer def get_Ecnl(self): return self.Ecnl def calculate_gga(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg): GGA.calculate_gga(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg) eLDAc_g = self.gd.empty() vLDAc_sg = self.gd.zeros(1) if self.vdwcoef == 0.0: return if len(n_sg) == 1: self.LDAc.calculate(eLDAc_g, n_sg, vLDAc_sg) e = self.get_non_local_energy(n_sg[0], sigma_xg[0], eLDAc_g, vLDAc_sg[0], dedn_sg[0], dedsigma_xg[0]) else: n_sg = n_sg.sum(0) n_sg.shape = (1,) + n_sg.shape self.LDAc.calculate(eLDAc_g, n_sg, vLDAc_sg) v_g = np.zeros_like(e_g) deda2nl_g = np.zeros_like(e_g) a2_g = sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2] e = self.get_non_local_energy(n_sg[0], a2_g, eLDAc_g, vLDAc_sg[0], v_g, deda2nl_g) dedsigma_xg[0] += self.vdwcoef * deda2nl_g dedsigma_xg[1] += self.vdwcoef * 2 * deda2nl_g dedsigma_xg[2] += self.vdwcoef * deda2nl_g dedn_sg += self.vdwcoef * v_g if self.gd.comm.rank == 0: e_g[0, 0, 0] += self.vdwcoef * e / self.gd.dv def get_non_local_energy(self, n_g=None, a2_g=None, e_LDAc_g=None, v_LDAc_g=None, v_g=None, deda2_g=None): """Calculate non-local correlation energy. parameters: n_g: ndarray Density. a2_g: ndarray Absolute value of the gradient of the density - squared. e_LDAc_g: ndarray LDA correlation energy density. """ gd = self.gd n_g = n_g.clip(1e-7, np.inf) # Calculate q0 and cut it off smoothly at q0cut: kF_g = (3 * pi ** 2 * n_g) ** (1.0 / 3.0) q0_g, dhdx_g = hRPS(kF_g - 4 * pi / 3 * e_LDAc_g / n_g - self.Zab / 36 / kF_g * a2_g / n_g ** 2, self.q0cut) if self.verbose: print ("VDW: q0 (min, mean, max): (%f, %f, %f)" % (q0_g.min(), q0_g.mean(), q0_g.max())) if self.soft_correction: dEcnl = gd.integrate(n_g ** 2 / q0_g ** 3) * 0.5 * self.C_soft else: dEcnl = 0.0 # Distribute density and q0 to all processors: n_g = gd.collect(n_g, broadcast=True) q0_g = gd.collect(q0_g, broadcast=True) if not self.energy_only: self.dhdx_g = gd.collect(dhdx_g, broadcast=True) Ecnl = self.calculate_6d_integral(n_g, q0_g, a2_g, e_LDAc_g, v_LDAc_g, v_g, deda2_g) Ecnl += dEcnl self.Ecnl = Ecnl return Ecnl def read_table(self): name = "phi-%.3f-%.3f-%.3f-%d-%d.pckl" % (self.phi0, self.ds, self.D_j[-1], len(self.delta_i), len(self.D_j)) if "GPAW_VDW" in os.environ: print "Use of GPAW_VDW is deprecated." print "Put", name, "in your GPAW_SETUP_PATH directory." dirs = [os.environ["GPAW_VDW"]] else: dirs = setup_paths + ["."] for dir in dirs: filename = os.path.join(dir, name) if os.path.isfile(filename): self.phi_ij = pickle.load(open(filename)) if self.verbose: print "VDW: using", filename return print "VDW: Could not find table file:", name self.make_table(name) def make_table(self, name): print "VDW: Generating vdW-DF kernel ..." print "VDW:", ndelta = len(self.delta_i) nD = len(self.D_j) self.phi_ij = np.zeros((ndelta, nD)) for i in range(self.world.rank, ndelta, self.world.size): print ndelta - i, sys.stdout.flush() delta = self.delta_i[i] for j in range(nD - 1, -1, -1): D = self.D_j[j] d = D * (1.0 + delta) dp = D * (1.0 - delta) if d ** 2 + dp ** 2 > self.ds ** 2: self.phi_ij[i, j] = phi(d, dp) else: P = np.polyfit( [0, self.D_j[j + 1] ** 2, self.D_j[j + 2] ** 2], [self.phi0, self.phi_ij[i, j + 1], self.phi_ij[i, j + 2]], 2, ) self.phi_ij[i, : j + 3] = np.polyval(P, self.D_j[: j + 3] ** 2) break self.world.sum(self.phi_ij) print print "VDW: Done!" if self.world.rank == 0: pickle.dump(self.phi_ij, open(name, "w"), pickle.HIGHEST_PROTOCOL) def make_prl_plot(self, multiply_by_4_pi_D_squared=True): import pylab as plt x = np.linspace(0, 8.0, 100) for delta in [0, 0.5, 0.9]: y = [self.phi(D * (1.0 + delta), D * (1.0 - delta)) for D in x] if multiply_by_4_pi_D_squared: y *= 4 * pi * x ** 2 plt.plot(x, y, label=r"$\delta=%.1f$" % delta) plt.legend(loc="best") plt.plot(x, np.zeros(len(x)), "k-") plt.xlabel("D") plt.ylabel(r"$4\pi D^2 \phi(\rm{Hartree})$") plt.show() def phi(self, d, dp): """Kernel function. Uses bi-linear interpolation and returns zero for D > Dmax. """ P = self.phi_ij D = (d + dp) / 2.0 if D < 1e-14: return P[0, 0] if D >= self.D_j[-1]: return 0.0 delta = abs((d - dp) / (2 * D)) ddelta = self.delta_i[1] x = delta / ddelta i = int(x) if i == len(self.delta_i) - 1: i -= 1 x = 1.0 else: x -= i dD = self.D_j[1] y = D / dD j = int(y) y -= j return x * (y * P[i + 1, j + 1] + (1 - y) * P[i + 1, j]) + (1 - x) * (y * P[i, j + 1] + (1 - y) * P[i, j])
from gpaw.xc.libxc import LibXC from math import pi import numpy as np nspins = 1 for name in [ 'LDA', 'PBE', 'revPBE', 'RPBE', 'LDA_X', 'GGA_X_PBE_R', 'GGA_X_RPBE', 'LDA_C_PW', ]: xc = LibXC(name) xc.initialize(nspins) libxc = xc.xc lxc_fxc = libxc.calculate_fxc_spinpaired lxc_fxc_fd = libxc.calculate_fxc_fd_spinpaired na = 2.0 if nspins == 2: nb = 1.0 else: nb = 0.0 print na, nb if (nb > 0.0): assert (nspins == 2) if nspins == 2: sigma0 = 2.0 # (0.0, 1.0, 1.0) sigma1 = 2.0 sigma2 = 5.0 # (1.0, 2.0, 0.0)
import numpy as np from gpaw.xc.libxc import LibXC, short_names from gpaw.xc.kernel import XCKernel, codes from gpaw.xc.bee import BEE1 functionals = [LibXC(name) for name in short_names] functionals += [XCKernel(name) for name in codes] functionals += [BEE1()] #name = 'LDA' #name = 'PBE' #functionals = [LibXC('MGGA_X_TPSS')] # XCKernel(name)] #functionals = [f for f in functionals if f.type=='MGGA'] def f1(n_xg, xc): e_g = np.empty_like(n_xg[0]) n_sg = n_xg[:1] sigma_xg = n_xg[1:2] tau_sg = n_xg[2:] dedn_sg = np.zeros_like(n_sg) dedsigma_xg = np.zeros_like(sigma_xg) dedtau_sg = np.zeros_like(tau_sg) xc.calculate(e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg, tau_sg, dedtau_sg) return e_g, np.concatenate((dedn_sg, dedsigma_xg, dedtau_sg)) def f2(n_xg, xc): e_g = np.empty_like(n_xg[0]) n_sg = n_xg[:2] sigma_xg = n_xg[2:5] tau_sg = n_xg[5:] dedn_sg = np.zeros_like(n_sg)
from gpaw.xc.libxc import LibXC from math import pi import numpy as np nspins = 1 for name in [ 'LDA', 'PBE', 'revPBE', 'RPBE', 'LDA_X', 'GGA_X_PBE_R', 'GGA_X_RPBE', 'LDA_C_PW', ]: xc = LibXC(name) xc.initialize(nspins) libxc = xc.xc lxc_fxc = libxc.calculate_fxc_spinpaired lxc_fxc_fd = libxc.calculate_fxc_fd_spinpaired na = 2.0 if nspins == 2: nb = 1.0 else: nb = 0.0 print na, nb if (nb > 0.0): assert (nspins == 2) if nspins == 2: sigma0 = 2.0 # (0.0, 1.0, 1.0) sigma1 = 2.0 sigma2 = 5.0 # (1.0, 2.0, 0.0) else: sigma0 = 2.0 # (0.0, 1.0, 1.0) sigma1 = 0.0 sigma2 = 0.0 taua=(3.*pi**2)**(2./3.)*na**(5./3.)/2.*sigma0
def vdw_df2(*args, **kwargs): return VDWXC(semilocal_xc=GGA(LibXC('GGA_X_RPW86+LDA_C_PW')), name='vdW-DF2', *args, **kwargs)
import numpy as np from gpaw.xc.libxc import LibXC, short_names from gpaw.xc.kernel import XCKernel, codes from gpaw.test import equal funcs = [] modes = [] for name in short_names: try: LibXC(name) except NameError: continue funcs.append(name) modes.append(0) for name in codes: funcs.append(name) modes.append(1) def create_xc(func, mode): isinstance(func, str) isinstance(mode, int) if mode == 0: xc = LibXC(func) else: xc = XCKernel(func) return xc def f1(n_xg, xc): e_g = np.empty_like(n_xg[0])
class VDWFunctionalBase: """Base class for vdW-DF.""" def __init__(self, world=None, Zab=-0.8491, vdwcoef=1.0, q0cut=5.0, phi0=0.5, ds=1.0, Dmax=20.0, nD=201, ndelta=21, soft_correction=False, setup_name='revPBE', verbose=False, energy_only=False): """vdW-DF. parameters: name: str Name of functional. world: MPI communicator Communicator to parallelize over. Defaults to gpaw.mpi.world. q0cut: float Maximum value for q0. phi0: float Smooth value for phi(0,0). ds: float Cutoff for smooth kernel. Dmax: float Maximum value for D. nD: int Number of values for D in kernel-table. ndelta: int Number of values for delta in kernel-table. soft_correction: bool Correct for soft kernel. kernel: Which kernel to use. Zab: parameter in nonlocal kernel. vdwcoef: float Scaling of vdW energy. verbose: bool Print useful information. """ if world is None: self.world = mpi.world else: self.world = world self.Zab = Zab self.vdwcoef = vdwcoef self.q0cut = q0cut self.phi0 = phi0 self.ds = ds self.delta_i = np.linspace(0, 1.0, ndelta) self.D_j = np.linspace(0, Dmax, nD) self.verbose = verbose self.read_table() self.soft_correction = soft_correction if soft_correction: dD = self.D_j[1] self.C_soft = np.dot(self.D_j**2, self.phi_ij[0]) * 4 * pi * dD self.gd = None self.energy_only = energy_only self.timer = nulltimer self.LDAc = LibXC('LDA_C_PW') self.setup_name = setup_name def get_setup_name(self): return self.setup_name def get_Ecnl(self): return self.Ecnl def calculate_impl(self, gd, n_sg, v_sg, e_g): sigma_xg, dedsigma_xg, gradn_svg = gga_vars(gd, self.grad_v, n_sg) self.calculate_exchange(e_g, n_sg, v_sg, sigma_xg, dedsigma_xg) self.calculate_correlation(e_g, n_sg, v_sg, sigma_xg, dedsigma_xg) add_gradient_correction(self.grad_v, gradn_svg, sigma_xg, dedsigma_xg, v_sg) def calculate_exchange(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg): raise NotImplementedError def calculate_correlation(self, e_g, n_sg, dedn_sg, sigma_xg, dedsigma_xg): eLDAc_g = self.gd.empty() vLDAc_sg = self.gd.zeros(1) if self.vdwcoef == 0.0: return if len(n_sg) == 1: self.LDAc.calculate(eLDAc_g, n_sg, vLDAc_sg) e = self.get_non_local_energy(n_sg[0], sigma_xg[0], eLDAc_g, vLDAc_sg[0], dedn_sg[0], dedsigma_xg[0]) else: n_sg = n_sg.sum(0) n_sg.shape = (1, ) + n_sg.shape self.LDAc.calculate(eLDAc_g, n_sg, vLDAc_sg) v_g = np.zeros_like(e_g) deda2nl_g = np.zeros_like(e_g) a2_g = sigma_xg[0] + 2 * sigma_xg[1] + sigma_xg[2] e = self.get_non_local_energy(n_sg[0], a2_g, eLDAc_g, vLDAc_sg[0], v_g, deda2nl_g) dedsigma_xg[0] += self.vdwcoef * deda2nl_g dedsigma_xg[1] += self.vdwcoef * 2 * deda2nl_g dedsigma_xg[2] += self.vdwcoef * deda2nl_g dedn_sg += self.vdwcoef * v_g if self.gd.comm.rank == 0: e_g[0, 0, 0] += self.vdwcoef * e / self.gd.dv def get_non_local_energy(self, n_g=None, a2_g=None, e_LDAc_g=None, v_LDAc_g=None, v_g=None, deda2_g=None): """Calculate non-local correlation energy. parameters: n_g: ndarray Density. a2_g: ndarray Absolute value of the gradient of the density - squared. e_LDAc_g: ndarray LDA correlation energy density. """ gd = self.gd n_g = n_g.clip(1e-7, np.inf) # Calculate q0 and cut it off smoothly at q0cut: kF_g = (3 * pi**2 * n_g)**(1.0 / 3.0) q0_g, dhdx_g = hRPS( kF_g - 4 * pi / 3 * e_LDAc_g / n_g - self.Zab / 36 / kF_g * a2_g / n_g**2, self.q0cut) if self.verbose: print(('VDW: q0 (min, mean, max): (%f, %f, %f)' % (q0_g.min(), q0_g.mean(), q0_g.max()))) if self.soft_correction: dEcnl = -gd.integrate(n_g**2 / q0_g**3) * 0.5 * self.C_soft else: dEcnl = 0.0 # Distribute density and q0 to all processors: n_g = gd.collect(n_g, broadcast=True) q0_g = gd.collect(q0_g, broadcast=True) if not self.energy_only: self.dhdx_g = gd.collect(dhdx_g, broadcast=True) Ecnl = self.calculate_6d_integral(n_g, q0_g, a2_g, e_LDAc_g, v_LDAc_g, v_g, deda2_g) Ecnl += dEcnl self.Ecnl = Ecnl return Ecnl def read_table(self): name = ('phi-%.3f-%.3f-%.3f-%d-%d.txt' % (self.phi0, self.ds, self.D_j[-1], len( self.delta_i), len(self.D_j))) dirs = setup_paths + ['.'] for dir in dirs: filename = os.path.join(dir, name) if os.path.isfile(filename): self.phi_ij = np.loadtxt(filename) if self.verbose: print('VDW: using', filename) return if sys.version_info[0] == 2: oldname = name[:-3] + 'pckl' for dir in dirs: filename = os.path.join(dir, oldname) if os.path.isfile(filename): self.phi_ij = pickle.load(open(filename, 'rb')) if self.verbose: print('VDW: using', filename) return print('VDW: Could not find table file:', name) self.make_table(name) def make_table(self, name): print('VDW: Generating vdW-DF kernel ...') print('VDW:', end=' ') ndelta = len(self.delta_i) nD = len(self.D_j) self.phi_ij = np.zeros((ndelta, nD)) for i in range(self.world.rank, ndelta, self.world.size): print(ndelta - i, end=' ') sys.stdout.flush() delta = self.delta_i[i] for j in range(nD - 1, -1, -1): D = self.D_j[j] d = D * (1.0 + delta) dp = D * (1.0 - delta) if d**2 + dp**2 > self.ds**2: with seterr(divide='ignore'): self.phi_ij[i, j] = phi(d, dp) else: P = np.polyfit([0, self.D_j[j + 1]**2, self.D_j[j + 2]**2], [ self.phi0, self.phi_ij[i, j + 1], self.phi_ij[i, j + 2] ], 2) self.phi_ij[i, :j + 3] = np.polyval(P, self.D_j[:j + 3]**2) break self.world.sum(self.phi_ij) print() print('VDW: Done!') header = ('phi0={0:.3f}, ds={1:.3f}, Dmax={2:.3f}, nD={3}, ndelta={4}'. format(self.phi0, self.ds, self.D_j[-1], len(self.delta_i), len(self.D_j))) if self.world.rank == 0: np.savetxt(name, self.phi_ij, header=header) def make_prl_plot(self, multiply_by_4_pi_D_squared=True): import pylab as plt x = np.linspace(0, 8.0, 100) for delta in [0, 0.5, 0.9]: y = [self.phi(D * (1.0 + delta), D * (1.0 - delta)) for D in x] if multiply_by_4_pi_D_squared: y *= 4 * pi * x**2 plt.plot(x, y, label=r'$\delta=%.1f$' % delta) plt.legend(loc='best') plt.plot(x, np.zeros(len(x)), 'k-') plt.xlabel('D') plt.ylabel(r'$4\pi D^2 \phi(\rm{Hartree})$') plt.show() def phi(self, d, dp): """Kernel function. Uses bi-linear interpolation and returns zero for D > Dmax. """ P = self.phi_ij D = (d + dp) / 2.0 if D < 1e-14: return P[0, 0] if D >= self.D_j[-1]: return 0.0 delta = abs((d - dp) / (2 * D)) ddelta = self.delta_i[1] x = delta / ddelta i = int(x) if i == len(self.delta_i) - 1: i -= 1 x = 1.0 else: x -= i dD = self.D_j[1] y = D / dD j = int(y) y -= j return (x * (y * P[i + 1, j + 1] + (1 - y) * P[i + 1, j]) + (1 - x) * (y * P[i, j + 1] + (1 - y) * P[i, j]))
from math import pi import numpy as np from gpaw.xc.libxc import LibXC x0 = LibXC('LDA_X') def f0(xc, rs, s): n = 3 / (4 * pi * rs**3) third = 1.0 / 3.0 kF = (3 * pi**2 * n)**third a2 = (2 * kF * n * s)**2 e = np.zeros(1) xc.calculate(e, np.array([[n]]), np.zeros((1, 1)), np.array([[a2]]), np.zeros((1, 1))) exc = n * e[0] x0.calculate(e, np.array([[n]]), np.zeros((1, 1))) ex0 = n * e[0] return exc / ex0 def f1(xc, rs, s): n = 3 / (4 * pi * rs**3) # na = 2 * n third = 1.0 / 3.0 kF = (3 * pi**2 * n)**third a2 = (2 * kF * n * s)**2 e = np.zeros(1) xc.calculate(e, np.array([[n], [0]]), np.zeros((2, 1)), np.array([[a2], [0], [0]]), np.zeros((3, 1))) exc = n * e[0]
def vdw_df(*args, **kwargs): return VDWXC(semilocal_xc=GGA(LibXC('GGA_X_PBE_R+LDA_C_PW')), name='vdW-DF', *args, **kwargs)
def __init__( self, name, world=None, q0cut=5.0, phi0=0.5, ds=1.0, Dmax=20.0, nD=201, ndelta=21, soft_correction=False, kernel=None, Zab=None, vdwcoef=1.0, verbose=False, energy_only=False, ): """vdW-DF. parameters: name: str Name of functional. world: MPI communicator Communicator to parallelize over. Defaults to gpaw.mpi.world. q0cut: float Maximum value for q0. phi0: float Smooth value for phi(0,0). ds: float Cutoff for smooth kernel. Dmax: float Maximum value for D. nD: int Number of values for D in kernel-table. ndelta: int Number of values for delta in kernel-table. soft_correction: bool Correct for soft kernel. kernel: Which kernel to use. Zab: parameter in nonlocal kernel. vdwcoef: float Scaling of vdW energy. verbose: bool Print useful information. """ if world is None: self.world = mpi.world else: self.world = world self.q0cut = q0cut self.phi0 = phi0 self.ds = ds self.delta_i = np.linspace(0, 1.0, ndelta) self.D_j = np.linspace(0, Dmax, nD) self.verbose = verbose self.read_table() self.soft_correction = soft_correction if soft_correction: dD = self.D_j[1] self.C_soft = np.dot(self.D_j ** 2, self.phi_ij[0]) * 4 * pi * dD self.gd = None self.energy_only = energy_only self.timer = nulltimer if name == "vdW-DF": assert kernel is None and Zab is None kernel = LibXC("GGA_X_PBE_R+LDA_C_PW") Zab = -0.8491 elif name == "vdW-DF2": assert kernel is None and Zab is None kernel = LibXC("GGA_X_RPW86+LDA_C_PW") Zab = -1.887 elif name == "optPBE-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_OPTPBE_VDW+LDA_C_PW") Zab = -0.8491 elif name == "optB88-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_OPTB88_VDW+LDA_C_PW") Zab = -0.8491 elif name == "C09-vdW": assert kernel is None and Zab is None kernel = LibXC("GGA_X_C09X+LDA_C_PW") Zab = -0.8491 else: assert kernel is not None and Zab is not None self.Zab = Zab GGA.__init__(self, kernel) self.vdwcoef = vdwcoef self.name = name self.LDAc = LibXC("LDA_C_PW")