def __init__(self, name, hybrid=None, xc=None, finegrid=False): """Mix standard functionals with exact exchange. name: str Name of hybrid functional. hybrid: float Fraction of exact exchange. xc: str or XCFunctional object Standard DFT functional with scaled down exchange. finegrid: boolean Use fine grid for energy functional evaluations? """ if name == 'EXX': assert hybrid is None and xc is None hybrid = 1.0 xc = XC(XCNull()) elif name == 'PBE0': assert hybrid is None and xc is None hybrid = 0.25 xc = XC('HYB_GGA_XC_PBEH') elif name == 'B3LYP': assert hybrid is None and xc is None hybrid = 0.2 xc = XC('HYB_GGA_XC_B3LYP') if isinstance(xc, str): xc = XC(xc) self.hybrid = hybrid self.xc = xc self.type = xc.type self.finegrid = finegrid XCFunctional.__init__(self, name)
def forced_update(self): """Recalc yourself.""" if not self.force_ApmB: Om = OmegaMatrix name = 'LrTDDFT' if self.xc: xc = XC(self.xc) if hasattr(xc, 'hybrid') and xc.hybrid > 0.0: Om = ApmB name = 'LrTDDFThyb' else: Om = ApmB name = 'LrTDDFThyb' self.kss = KSSingles(calculator=self.calculator, nspins=self.nspins, eps=self.eps, istart=self.istart, jend=self.jend, energy_range=self.energy_range, txt=self.txt) self.Om = Om(self.calculator, self.kss, self.xc, self.derivative_level, self.numscale, finegrid=self.finegrid, eh_comm=self.eh_comm, txt=self.txt) self.name = name
def initialize(self): self.occupations = self.nlfunc.occupations self.xc = XC(self.functional) # Always 1 spin, no matter what calculation nspins is self.vt_sg = self.nlfunc.finegd.empty(1) self.e_g = self.nlfunc.finegd.empty() #.ravel()
def create_setup(symbol, xc='LDA', lmax=0, type='paw', basis=None, setupdata=None, filter=None, world=None): if isinstance(xc, str): xc = XC(xc) if isinstance(type, str) and ':' in type: # Parse DFT+U parameters from type-string: # Examples: "type:l,U" or "type:l,U,scale" type, lu = type.split(':') if type == '': type = 'paw' l = 'spdf'.find(lu[0]) assert lu[1] == ',' U = lu[2:] if ',' in U: U, scale = U.split(',') else: scale = True U = float(U) / units.Hartree scale = int(scale) else: U = None if setupdata is None: if type == 'hgh' or type == 'hgh.sc': lmax = 0 from gpaw.hgh import HGHSetupData, setups, sc_setups if type == 'hgh.sc': table = sc_setups else: table = setups parameters = table[symbol] setupdata = HGHSetupData(parameters) elif type == 'ah': from gpaw.ah import AppelbaumHamann ah = AppelbaumHamann() ah.build(basis) return ah elif type == 'ae': from gpaw.ae import HydrogenAllElectronSetup assert symbol == 'H' ae = HydrogenAllElectronSetup() ae.build(basis) return ae elif type == 'ghost': from gpaw.lcao.bsse import GhostSetupData setupdata = GhostSetupData(symbol) else: setupdata = SetupData(symbol, xc.get_setup_name(), type, True, world=world) if hasattr(setupdata, 'build'): setup = LeanSetup(setupdata.build(xc, lmax, basis, filter)) if U is not None: setup.set_hubbard_u(U, l, scale) return setup else: return setupdata
def get_xc_difference(self, xc): if isinstance(xc, str): xc = XC(xc) xc.initialize(self.density, self.hamiltonian, self.wfs, self.occupations) xc.set_positions(self.atoms.get_scaled_positions() % 1.0) if xc.orbital_dependent: self.converge_wave_functions() return self.hamiltonian.get_xc_difference(xc, self.density) * Hartree
def __init__(self, symbol, xc='LDA', spinpol=False, dirac=False, log=sys.stdout): """All-electron calculation for spherically symmetric atom. symbol: str (or int) Chemical symbol (or atomic number). xc: str Name of XC-functional. spinpol: bool If true, do spin-polarized calculation. Default is spin-paired. dirac: bool Solve Dirac equation instead of Schrödinger equation. log: stream Text output.""" if isinstance(symbol, int): symbol = chemical_symbols[symbol] self.symbol = symbol self.Z = atomic_numbers[symbol] self.nspins = 1 + int(bool(spinpol)) self.dirac = bool(dirac) if isinstance(xc, str): self.xc = XC(xc) else: self.xc = xc if log is None: log = devnull self.fd = log self.vr_sg = None # potential * r self.n_sg = 0.0 # density self.gd = None # radial grid descriptor # Energies: self.ekin = None self.eeig = None self.eH = None self.eZ = None self.channels = None self.initialize_configuration() self.log('Z: ', self.Z) self.log('Name: ', atomic_names[self.Z]) self.log('Symbol: ', symbol) self.log('XC-functional: ', self.xc.name) self.log('Equation: ', ['Schrödinger', 'Dirac'][self.dirac])
def update(self, calculator=None, nspins=None, eps=0.001, istart=0, jend=None, energy_range=None, xc=None, derivative_level=None, numscale=0.001): changed = False if self.calculator != calculator or \ self.nspins != nspins or \ self.eps != eps or \ self.istart != istart or \ self.jend != jend : changed = True if not changed: return self.calculator = calculator self.nspins = nspins self.eps = eps self.istart = istart self.jend = jend self.xc = xc self.derivative_level = derivative_level self.numscale = numscale self.kss = KSSingles(calculator=calculator, nspins=nspins, eps=eps, istart=istart, jend=jend, energy_range=energy_range, txt=self.txt) if not self.force_ApmB: Om = OmegaMatrix name = 'LrTDDFT' if self.xc: xc = XC(self.xc) if hasattr(xc, 'hybrid') and xc.hybrid > 0.0: Om = ApmB name = 'LrTDDFThyb' else: Om = ApmB name = 'LrTDDFThyb' self.Om = Om(self.calculator, self.kss, self.xc, self.derivative_level, self.numscale, finegrid=self.finegrid, eh_comm=self.eh_comm, txt=self.txt) self.name = name
def get_xc_difference(self, xc): if isinstance(xc, (str, dict)): xc = XC(xc) xc.set_grid_descriptor(self.density.finegd) xc.initialize(self.density, self.hamiltonian, self.wfs, self.occupations) xc.set_positions(self.spos_ac) if xc.orbital_dependent: self.converge_wave_functions() return self.hamiltonian.get_xc_difference(xc, self.density) * Ha
def get_non_xc_total_energies(self): """Compile non-XC total energy contributions""" if self.e_dft is None: self.e_dft = self.calc.get_potential_energy() if self.e0 is None: from gpaw.xc.kernel import XCNull xc_null = XC(XCNull()) self.e0 = self.e_dft + self.calc.get_xc_difference(xc_null) assert isinstance(self.e_dft, float) assert isinstance(self.e0, float)
def _calculate_fxc(self, gd, n_sG): if self.functional == 'ALDA_x': n_G = np.sum(n_sG, axis=0) fx_G = -1. / 3. * (3. / np.pi)**(1. / 3.) * n_G**(-2. / 3.) return fx_G else: fxc_sG = np.zeros_like(n_sG) xc = XC(self.functional[1:]) xc.calculate_fxc(gd, n_sG, fxc_sG) return fxc_sG[0]
def linearize_to_xc(self, newxc): """Linearize Hamiltonian to difference XC functional. Used in real time TDDFT to perform calculations with various kernels. """ if isinstance(newxc, str): newxc = XC(newxc) self.log('Linearizing xc-hamiltonian to ' + str(newxc)) newxc.initialize(self.density, self.hamiltonian, self.wfs, self.occupations) self.hamiltonian.linearize_to_xc(newxc, self.density)
def propagate_single(self, dt): # -------------- # Predictor step # -------------- # 1. Calculate H(t) self.save_wfs() # kpt.C2_nM = kpt.C_nM # 2. H_MM(t) = <M|H(t)|H> # Solve Psi(t+dt) from (S_MM - 0.5j*H_MM(t)*dt) Psi(t+dt) = # (S_MM + 0.5j*H_MM(t)*dt) Psi(t) for k, kpt in enumerate(self.wfs.kpt_u): if self.fxc is not None: if self.time == 0.0: kpt.deltaXC_H_MM = self.get_hamiltonian(kpt) self.hamiltonian.xc = XC(self.fxc) self.update_hamiltonian() assert len(self.wfs.kpt_u) == 1 kpt.deltaXC_H_MM -= self.get_hamiltonian(kpt) self.update_hamiltonian() # Call registered callback functions self.call_observers(self.niter) for k, kpt in enumerate(self.wfs.kpt_u): kpt.H0_MM = self.get_hamiltonian(kpt) if self.fxc is not None: kpt.H0_MM += kpt.deltaXC_H_MM self.propagate_wfs(kpt.C_nM, kpt.C_nM, kpt.S_MM, kpt.H0_MM, dt) # --------------- # Propagator step # --------------- # 1. Calculate H(t+dt) self.update_hamiltonian() # 2. Estimate H(t+0.5*dt) ~ H(t) + H(t+dT) for k, kpt in enumerate(self.wfs.kpt_u): kpt.H0_MM *= 0.5 if self.fxc is not None: # Store this to H0_MM and maybe save one extra H_MM of # memory? kpt.H0_MM += 0.5 * (self.get_hamiltonian(kpt) + kpt.deltaXC_H_MM) else: # Store this to H0_MM and maybe save one extra H_MM of # memory? kpt.H0_MM += 0.5 * self.get_hamiltonian(kpt) # 3. Solve Psi(t+dt) from # (S_MM - 0.5j*H_MM(t+0.5*dt)*dt) Psi(t+dt) # = (S_MM + 0.5j*H_MM(t+0.5*dt)*dt) Psi(t) self.propagate_wfs(kpt.C2_nM, kpt.C_nM, kpt.S_MM, kpt.H0_MM, dt) self.niter += 1 self.time += dt
def get_density(self, atom_indices=None, gridrefinement=2): """Get sum of atomic densities from the given atom list. All atoms are taken if the list is not given.""" all_atoms = self.calculator.get_atoms() if atom_indices is None: atom_indices = range(len(all_atoms)) density = self.calculator.density spos_ac = all_atoms.get_scaled_positions() rank_a = self.finegd.get_ranks_from_positions(spos_ac) density.set_positions(all_atoms.get_scaled_positions(), AtomPartition(self.finegd.comm, rank_a)) # select atoms atoms = [] D_asp = {} rank_a = [] all_D_asp = self.calculator.density.D_asp all_rank_a = self.calculator.density.atom_partition.rank_a for a in atom_indices: if a in all_D_asp: D_asp[len(atoms)] = all_D_asp.get(a) atoms.append(all_atoms[a]) rank_a.append(all_rank_a[a]) atoms = Atoms(atoms, cell=all_atoms.get_cell(), pbc=all_atoms.get_pbc()) spos_ac = atoms.get_scaled_positions() Z_a = atoms.get_atomic_numbers() par = self.calculator.parameters setups = Setups(Z_a, par.setups, par.basis, XC(par.xc), self.calculator.wfs.world) # initialize self.initialize(setups, self.calculator.timer, np.zeros(len(atoms)), False) self.set_mixer(None) # FIXME nparray causes partitionong.py test to fail self.set_positions(spos_ac, AtomPartition(self.gd.comm, rank_a)) self.D_asp = D_asp basis_functions = BasisFunctions( self.gd, [setup.phit_j for setup in self.setups], cut=True) basis_functions.set_positions(spos_ac) self.initialize_from_atomic_densities(basis_functions) aed_sg, gd = self.get_all_electron_density(atoms, gridrefinement) return aed_sg.sum(axis=0), gd
def beefvdw_energy_contribs_x(self): """Legendre polynomial exchange contributions to BEEF-vdW Etot""" self.get_non_xc_total_energies() e_pbe = (self.e_dft + self.calc.get_xc_difference('GGA_C_PBE') - self.e0) exch = np.zeros(30) for p in range(30): pars = [4, 0, p, 1.0] bee = XC('BEE2', pars) exch[p] = (self.e_dft + self.calc.get_xc_difference(bee) - self.e0 - e_pbe) del bee return exch
def mbeef_exchange_energy_contribs(self): """Legendre polynomial exchange contributions to mBEEF Etot""" self.get_non_xc_total_energies() e_x = np.zeros((self.max_order, self.max_order)) for p1 in range(self.max_order): # alpha for p2 in range(self.max_order): # s2 pars_i = np.array([1, self.trans[0], p2, 1.0]) pars_j = np.array([1, self.trans[1], p1, 1.0]) pars = np.hstack((pars_i, pars_j)) x = XC('2D-MGGA', pars) e_x[p1, p2] = (self.e_dft + self.calc.get_xc_difference(x) - self.e0) del x return e_x
def __init__(self, xc='LDA', finegrid=False, **parameters): """Self-Interaction Corrected Functionals (PZ-SIC). finegrid: boolean Use fine grid for energy functional evaluations? """ if isinstance(xc, str): xc = XC(xc) self.xc = xc self.type = xc.type XCFunctional.__init__(self, xc.name + '-PZ-SIC') self.finegrid = finegrid self.parameters = parameters
def _calculate_pol_fxc(self, gd, n_sG, m_G): """ Calculate polarized fxc """ assert np.shape(m_G) == np.shape(n_sG[0]) if self.functional == 'ALDA_x': fx_G = - (6. / np.pi)**(1. / 3.) \ * (n_sG[0]**(1. / 3.) - n_sG[1]**(1. / 3.)) / m_G return fx_G else: v_sG = np.zeros(np.shape(n_sG)) xc = XC(self.functional[1:]) xc.calculate(gd, n_sG, v_sg=v_sG) return (v_sG[0] - v_sG[1]) / m_G
def get_density(self, atom_indicees=None): """Get sum of atomic densities from the given atom list. All atoms are taken if the list is not given.""" all_atoms = self.calculator.get_atoms() if atom_indicees is None: atom_indicees = range(len(all_atoms)) density = self.calculator.density density.set_positions(all_atoms.get_scaled_positions() % 1.0, self.calculator.wfs.rank_a) # select atoms atoms = [] D_asp = {} rank_a = [] all_D_asp = self.calculator.density.D_asp all_rank_a = self.calculator.density.rank_a for a in atom_indicees: if a in all_D_asp: D_asp[len(atoms)] = all_D_asp.get(a) atoms.append(all_atoms[a]) rank_a.append(all_rank_a[a]) atoms = Atoms(atoms, cell=all_atoms.get_cell()) spos_ac = atoms.get_scaled_positions() % 1.0 Z_a = atoms.get_atomic_numbers() par = self.calculator.input_parameters setups = Setups(Z_a, par.setups, par.basis, par.lmax, XC(par.xc), self.calculator.wfs.world) self.D_asp = D_asp # initialize self.initialize(setups, par.stencils[1], self.calculator.timer, [0] * len(atoms), False) self.set_mixer(None) self.set_positions(spos_ac, rank_a) basis_functions = BasisFunctions( self.gd, [setup.phit_j for setup in self.setups], cut=True) basis_functions.set_positions(spos_ac) self.initialize_from_atomic_densities(basis_functions) aed_sg, gd = Density.get_all_electron_density(self, atoms, gridrefinement=2) return aed_sg[0], gd
def paired(): xc = XC('vdW-DF') n = 0.3 * np.ones((1, N, N, N)) n += 0.01 * np.cos(np.arange(N) * 2 * pi / N) v = 0.0 * n xc.calculate(gd, n, v) n2 = 1.0 * n i = 1 n2[0, i, i, i] += 0.00002 x = v[0, i, i, i] * gd.dv E2 = xc.calculate(gd, n2, v) n2[0, i, i, i] -= 0.00004 E2 -= xc.calculate(gd, n2, v) x2 = E2 / 0.00004 print(i, x, x2, x - x2, x / x2) equal(x, x2, 2e-11)
def __init__(self, xc='LDA', finegrid=False, **parameters): """Self-Interaction Corrected Functionals (PZ-SIC). finegrid: boolean Use fine grid for energy functional evaluations? """ if isinstance(xc, basestring): xc = XC(xc) if xc.orbital_dependent: raise ValueError('SIC does not support ' + xc.name) self.xc = xc XCFunctional.__init__(self, xc.name + '-PZ-SIC', xc.type) self.finegrid = finegrid self.parameters = parameters
def polarized(): xc = XC('vdW-DF') n = 0.04 * np.ones((2, N, N, N)) n[1] = 0.3 n[0] += 0.02 * np.sin(np.arange(N) * 2 * pi / N) n[1] += 0.2 * np.cos(np.arange(N) * 2 * pi / N) v = 0.0 * n xc.calculate(gd, n, v) n2 = 1.0 * n i = 1 n2[0, i, i, i] += 0.00002 x = v[0, i, i, i] * gd.dv E2 = xc.calculate(gd, n2, v) n2[0, i, i, i] -= 0.00004 E2 -= xc.calculate(gd, n2, v) x2 = E2 / 0.00004 print(i, x, x2, x - x2, x / x2) equal(x, x2, 1e-10)
def get_density(self, atom_indices=None, gridrefinement=2): """Get sum of atomic densities from the given atom list. Parameters ---------- atom_indices : list_like All atoms are taken if the list is not given. gridrefinement : 1, 2, 4 Gridrefinement given to get_all_electron_density Returns ------- type spin summed density, grid_descriptor """ all_atoms = self.calculator.get_atoms() if atom_indices is None: atom_indices = range(len(all_atoms)) # select atoms atoms = self.calculator.get_atoms()[atom_indices] spos_ac = atoms.get_scaled_positions() Z_a = atoms.get_atomic_numbers() par = self.calculator.parameters setups = Setups(Z_a, par.setups, par.basis, XC(par.xc), self.calculator.wfs.world) # initialize self.initialize(setups, self.calculator.timer, np.zeros( (len(atoms), 3)), False) self.set_mixer(None) rank_a = self.gd.get_ranks_from_positions(spos_ac) self.set_positions(spos_ac, AtomPartition(self.gd.comm, rank_a)) basis_functions = BasisFunctions( self.gd, [setup.phit_j for setup in self.setups], cut=True) basis_functions.set_positions(spos_ac) self.initialize_from_atomic_densities(basis_functions) aed_sg, gd = self.get_all_electron_density(atoms, gridrefinement) return aed_sg.sum(axis=0), gd
def get_radial_potential(calc, a, ai): """Calculates dV/dr / r for the effective potential. Below, f_g denotes dV/dr = minus the radial force""" rgd = a.xc_correction.rgd r_g = rgd.r_g r_g[0] = 1.0e-12 dr_g = rgd.dr_g Ns = calc.wfs.nspins D_sp = calc.density.D_asp[ai] B_pq = a.xc_correction.B_pqL[:, :, 0] n_qg = a.xc_correction.n_qg D_sq = np.dot(D_sp, B_pq) n_sg = np.dot(D_sq, n_qg) / (4 * np.pi)**0.5 n_sg[:] += a.xc_correction.nc_g / Ns # Coulomb force from nucleus fc_g = a.Z / r_g**2 # Hartree force rho_g = 4 * np.pi * r_g**2 * dr_g * np.sum(n_sg, axis=0) fh_g = -np.array([np.sum(rho_g[:ig]) for ig in range(len(r_g))]) / r_g**2 # xc force xc = XC(calc.get_xc_functional()) v_sg = np.zeros_like(n_sg) xc.calculate_spherical(a.xc_correction.rgd, n_sg, v_sg) fxc_sg = np.array([a.xc_correction.rgd.derivative(v_sg[s]) for s in range(Ns)]) fxc_g = np.sum(fxc_sg, axis=0) / Ns # f_sg = np.tile(fc_g, (Ns, 1)) + np.tile(fh_g, (Ns, 1)) + fxc_sg f_sg = np.tile(fc_g + fh_g + fxc_g, (Ns, 1)) return f_sg[:] / r_g
def get_libvdwxc_functional(name, **kwargs): if 'name' in kwargs: name2 = kwargs.pop('name') assert name == name2 funcs = { 'vdW-DF': vdw_df, 'vdW-DF2': vdw_df2, 'vdW-DF-cx': vdw_df_cx, 'optPBE-vdW': vdw_optPBE, 'optB88-vdW': vdw_optB88, 'C09-vdW': vdw_C09, 'BEEF-vdW': vdw_beef, 'mBEEF-vdW': vdw_mbeef } semilocal_xc = kwargs.pop('semilocal_xc', None) if semilocal_xc is not None: from gpaw.xc import XC semilocal_xc = XC(semilocal_xc) func = funcs[name](**kwargs) if semilocal_xc is not None: assert semilocal_xc.name == func.semilocal_xc.name return func
def initialize_fxc(self, niter): self.has_fxc = self.fxc_name is not None if not self.has_fxc: return self.timer.start('Initialize fxc') # XXX: Similar functionality is available in # paw.py: PAW.linearize_to_xc(self, newxc) # See test/lcaotddft/fxc_vs_linearize.py get_H_MM = self.get_hamiltonian_matrix # Calculate deltaXC: 1. take current H_MM if niter == 0: self.deltaXC_H_uMM = [None] * len(self.wfs.kpt_u) for u, kpt in enumerate(self.wfs.kpt_u): self.deltaXC_H_uMM[u] = get_H_MM(kpt, addfxc=False) # Update hamiltonian.xc if self.fxc_name == 'RPA': xc_name = 'null' else: xc_name = self.fxc_name # XXX: xc is not written to the gpw file # XXX: so we need to set it always xc = XC(xc_name) xc.initialize(self.density, self.hamiltonian, self.wfs, self.occupations) xc.set_positions(self.hamiltonian.spos_ac) self.hamiltonian.xc = xc self.update() # Calculate deltaXC: 2. update with new H_MM if niter == 0: for u, kpt in enumerate(self.wfs.kpt_u): self.deltaXC_H_uMM[u] -= get_H_MM(kpt, addfxc=False) self.timer.stop('Initialize fxc')
def __init__(self, name, hybrid=None, xc=None, omega=None): """Mix standard functionals with exact exchange. name: str Name of hybrid functional. hybrid: float Fraction of exact exchange. xc: str or XCFunctional object Standard DFT functional with scaled down exchange. """ if name == 'EXX': assert hybrid is None and xc is None hybrid = 1.0 xc = XC(XCNull()) elif name == 'PBE0': assert hybrid is None and xc is None hybrid = 0.25 xc = XC('HYB_GGA_XC_PBEH') elif name == 'B3LYP': assert hybrid is None and xc is None hybrid = 0.2 xc = XC('HYB_GGA_XC_B3LYP') elif name == 'HSE03': assert hybrid is None and xc is None and omega is None hybrid = 0.25 omega = 0.106 xc = XC('HYB_GGA_XC_HSE03') elif name == 'HSE06': assert hybrid is None and xc is None and omega is None hybrid = 0.25 omega = 0.11 xc = XC('HYB_GGA_XC_HSE06') if isinstance(xc, str): xc = XC(xc) self.hybrid = float(hybrid) self.xc = xc self.omega = omega self.type = xc.type XCFunctional.__init__(self, name)
def __init__(self, symbol, xc='LDA', spinpol=False, dirac=False, configuration=None, log=None): """All-electron calculation for spherically symmetric atom. symbol: str (or int) Chemical symbol (or atomic number). xc: str Name of XC-functional. spinpol: bool If true, do spin-polarized calculation. Default is spin-paired. dirac: bool Solve Dirac equation instead of Schrödinger equation. configuration: list Electronic configuration for symbol, format as in gpaw.atom.configurations log: stream Text output.""" if isinstance(symbol, int): symbol = chemical_symbols[symbol] self.symbol = symbol self.Z = atomic_numbers[symbol] self.nspins = 1 + int(bool(spinpol)) self.dirac = bool(dirac) if configuration is not None: self.configuration = copy.deepcopy(configuration) else: self.configuration = None self.scalar_relativistic = False if isinstance(xc, str): self.xc = XC(xc) else: self.xc = xc self.fd = log or sys.stdout self.vr_sg = None # potential * r self.n_sg = 0.0 # density self.rgd = None # radial grid descriptor # Energies: self.ekin = None self.eeig = None self.eH = None self.eZ = None self.channels = None self.initialize_configuration(self.configuration) self.log('Z: ', self.Z) self.log('Name: ', atomic_names[self.Z]) self.log('Symbol: ', symbol) self.log('XC-functional: ', self.xc.name) self.log('Equation: ', ['Schrödinger', 'Dirac'][self.dirac]) self.method = 'Gaussian basis-set'
# ------------------------------------------------------------------- from gpaw.test.ut_common import ase_svnversion, shapeopt, TestCase, \ TextTestRunner, CustomTextTestRunner, defaultTestLoader, \ initialTestLoader, create_random_atoms, create_parsize_maxbands memstats = False if memstats: # Developer use of this feature requires ASE 3.1.0 svn.rev. 905 or later. assert ase_svnversion >= 905 # wasn't bug-free untill 973! from ase.utils.memory import MemorySingleton, MemoryStatistics # ------------------------------------------------------------------- p = InputParameters(spinpol=False) xc = XC(p.xc) p.setups = dict([(symbol, SetupData(symbol, xc.name)) for symbol in 'HO']) class UTBandParallelSetup(TestCase): """ Setup a simple band parallel calculation.""" # Number of bands nbands = 36 # Spin-paired, single kpoint nspins = 1 nibzkpts = 1 # Strided or blocked groups
def __init__(self, name, stencil=2, hybrid=None, xc=None, omega=None): """Mix standard functionals with exact exchange. name: str Name of hybrid functional. hybrid: float Fraction of exact exchange. xc: str or XCFunctional object Standard DFT functional with scaled down exchange. """ rsf_functionals = { # Parameters can also be taken from libxc 'CAMY-BLYP': { # Akinaga, Ten-no CPL 462 (2008) 348-351 'alpha': 0.2, 'beta': 0.8, 'omega': 0.44, 'cam': True, 'rsf': 'Yukawa', 'xc': 'HYB_GGA_XC_CAMY_BLYP' }, 'CAMY-B3LYP': { # Seth, Ziegler JCTC 8 (2012) 901-907 'alpha': 0.19, 'beta': 0.46, 'omega': 0.34, 'cam': True, 'rsf': 'Yukawa', 'xc': 'HYB_GGA_XC_CAMY_B3LYP' }, 'LCY-BLYP': { # Seth, Ziegler JCTC 8 (2012) 901-907 'alpha': 0.0, 'beta': 1.0, 'omega': 0.75, 'cam': False, 'rsf': 'Yukawa', 'xc': 'HYB_GGA_XC_LCY_BLYP' }, 'LCY-PBE': { # Seth, Ziegler JCTC 8 (2012) 901-907 'alpha': 0.0, 'beta': 1.0, 'omega': 0.75, 'cam': False, 'rsf': 'Yukawa', 'xc': 'HYB_GGA_XC_LCY_PBE' } } self.omega = None self.cam_alpha = None self.cam_beta = None self.is_cam = False self.rsf = None def _xc(name): return {'name': name, 'stencil': stencil} if name == 'EXX': hybrid = 1.0 xc = XC(XCNull()) elif name == 'PBE0': hybrid = 0.25 xc = XC(_xc('HYB_GGA_XC_PBEH')) elif name == 'B3LYP': hybrid = 0.2 xc = XC(_xc('HYB_GGA_XC_B3LYP')) elif name == 'HSE03': hybrid = 0.25 omega = 0.106 xc = XC(_xc('HYB_GGA_XC_HSE03')) elif name == 'HSE06': hybrid = 0.25 omega = 0.11 xc = XC(_xc('HYB_GGA_XC_HSE06')) elif name in rsf_functionals: rsf_functional = rsf_functionals[name] self.cam_alpha = rsf_functional['alpha'] self.cam_beta = rsf_functional['beta'] self.omega = rsf_functional['omega'] self.is_cam = rsf_functional['cam'] self.rsf = rsf_functional['rsf'] xc = XC(rsf_functional['xc']) hybrid = self.cam_alpha + self.cam_beta if isinstance(xc, (basestring, dict)): xc = XC(xc) self.hybrid = float(hybrid) self.xc = xc if omega is not None: omega = float(omega) if self.omega is not None and self.omega != omega: self.xc.kernel.set_omega(omega) # Needed to tune omega for RSF self.omega = omega XCFunctional.__init__(self, name, xc.type)
E = xc.calculate(gd, n_sg, v_sg) print('E', E) dn = 1e-6 all_indices = itertools.product(range(2), range(1, actual_n[0], 2), range(0, actual_n[1], 2), range(0, actual_n[2], 2)) for testindex in all_indices: n1_sg = n_sg.copy() n2_sg = n_sg.copy() v = v_sg[testindex] * gd.dv n1_sg[testindex] -= dn n2_sg[testindex] += dn E1 = xc.calculate(gd, n1_sg, v_sg.copy()) E2 = xc.calculate(gd, n2_sg, v_sg.copy()) dedn = 0.5 * (E2 - E1) / dn err = abs(dedn - v) print('{}{} v={} fd={} err={}'.format(xc.name, list(testindex), v, dedn, err)) assert err < tol, err test(XC('PBE')) test(vdw_df_cx()) test(vdw_df_cx(vdwcoef=0.0)) test(vdw_df_cx(vdwcoef=1e5), tol=2e-6)