def get_number_of_grid_points(cell_cv, h=None, mode=None, realspace=None, symmetry=None): if mode is None: mode = FD() if realspace is None: realspace = mode.name != 'pw' if h is None: if mode.name == 'pw': h = np.pi / (4 * mode.ecut)**0.5 elif mode.name == 'lcao' and not realspace: h = np.pi / (4 * 340 / Hartree)**0.5 else: h = 0.2 / Bohr if realspace or mode.name == 'fd': N_c = h2gpts(h, cell_cv, 4) else: N_c = h2gpts(h, cell_cv, 1) if symmetry is None: N_c = np.array([get_efficient_fft_size(N) for N in N_c]) else: N_c = np.array([get_efficient_fft_size(N, n) for N, n in zip(N_c, symmetry.gcd_c)]) return N_c
def get_number_of_grid_points(cell_cv, h=None, mode=None, realspace=None, symmetry=None): if mode is None: mode = FD() if realspace is None: realspace = mode.name != 'pw' if h is None: if mode.name == 'pw': h = np.pi / (4 * mode.ecut)**0.5 elif mode.name == 'lcao' and not realspace: h = np.pi / (4 * 340 / Hartree)**0.5 else: h = 0.2 / Bohr if realspace or mode.name == 'fd': N_c = h2gpts(h, cell_cv, 4) else: N_c = h2gpts(h, cell_cv, 1) if symmetry is None: N_c = np.array([get_efficient_fft_size(N) for N in N_c]) else: N_c = np.array([ get_efficient_fft_size(N, n) for N, n in zip(N_c, symmetry.gcd_c) ]) return N_c
def set_calculator(self, config, filename): kwargs = {} kwargs.update(self.input_parameters) if self.write_gpw_file is not None: self.gpwfilename = filename[:-4] + 'gpw' if 'txt' not in kwargs: kwargs['txt'] = filename[:-4] + 'txt' if not config.pbc.any(): # Isolated atom or molecule: config.center(vacuum=self.vacuum) if (len(config) == 1 and config.get_initial_magnetic_moments().any()): kwargs['hund'] = True # Use fixed number of gpts: if 'gpts' not in kwargs: h = kwargs.get('h', 0.2) gpts = h2gpts(h, config.cell) kwargs['h'] = None kwargs['gpts'] = gpts self.calc = GPAW(**kwargs) config.set_calculator(self.calc)
def relaxGPAW(structure, label): ''' Relax a structure and saves the trajectory based in the index i Parameters ---------- structure : ase Atoms object to be relaxed i : index which the trajectory is saved under ranks: ranks of the processors to relax the structure Returns ------- structure : relaxed Atoms object ''' # Create calculator calc = GPAW(poissonsolver=PoissonSolver(relax='GS', eps=1.0e-7), mode='lcao', basis='dzp', xc='PBE', gpts=h2gpts(0.2, structure.get_cell(), idiv=8), occupations=FermiDirac(0.1), maxiter=99, mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, kpts=(1, 1, 1), txt=label + '_lcao.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls forcemax = 0.1 niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis=1).max()**0.5 < forcemax: return structure traj = Trajectory(label + '_lcao.traj', 'w', structure) while (structure.get_forces()** 2).sum(axis=1).max()**0.5 > forcemax and niter < 1: dyn = BFGS(structure, logfile=label + '.log') vb = VariansBreak(structure, dyn, min_stdev=0.01, N=15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax=forcemax, steps=10) niter += 1 return structure
def relaxGPAW(structure, label, calc=None, forcemax=0.1, niter_max=1, steps=10): # Create calculator if calc is None: calc = GPAW( poissonsolver=PoissonSolver(relax='GS', eps=1.0e-7), # C mode='lcao', basis='dzp', xc='PBE', gpts=h2gpts(0.2, structure.get_cell(), idiv=8), # C occupations=FermiDirac(0.1), maxiter=99, # C #maxiter=49, # Sn3O3 mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, #kpts=(1,1,1), # C kpts=(2, 2, 1), # Sn3O3 txt=label + '_lcao.txt') else: calc.set(txt=label + '_true.txt') # Set calculator structure.set_calculator(calc) # loop a number of times to capture if minimization stops with high force # due to the VariansBreak calls niter = 0 # If the structure is already fully relaxed just return it if (structure.get_forces()**2).sum(axis=1).max()**0.5 < forcemax: return structure traj = Trajectory(label + '_lcao.traj', 'w', structure) while (structure.get_forces()** 2).sum(axis=1).max()**0.5 > forcemax and niter < niter_max: dyn = BFGS(structure, logfile=label + '.log') vb = VariansBreak(structure, dyn, min_stdev=0.01, N=15) dyn.attach(traj) dyn.attach(vb) dyn.run(fmax=forcemax, steps=steps) niter += 1 E = structure.get_potential_energy() F = structure.get_forces() return structure, E, F
def get_number_of_grid_points(cell_cv, h=None, mode=None, realspace=None): if mode == 'pw': mode = PW() elif mode is None: mode = 'fd' if realspace is None: realspace = not isinstance(mode, PW) if h is None: if isinstance(mode, PW): h = np.pi / (4 * mode.ecut)**0.5 elif mode == 'lcao' and not realspace: h = np.pi / (4 * 340 / Hartree)**0.5 else: h = 0.2 / Bohr if realspace or mode == 'fd': N_c = h2gpts(h, cell_cv, 4) else: N_c = h2gpts(h, cell_cv, 1) N_c = np.array([get_efficient_fft_size(N) for N in N_c]) return N_c
def singleGPAW(structure, label): # Create calculator calc = GPAW(poissonsolver=PoissonSolver(relax='GS', eps=1.0e-7), mode='lcao', basis='dzp', xc='PBE', gpts=h2gpts(0.2, structure.get_cell(), idiv=8), occupations=FermiDirac(0.1), maxiter=99, mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, kpts=(1, 1, 1), txt=label + '_single_lcao.txt') # Set calculator structure.set_calculator(calc) return structure.get_potential_energy(), structure.get_forces()
def main(): a = 8.467 atoms = read('g1_001.xyz') atoms.cell = (a, a, 3) atoms.pbc = False atoms.center() print(atoms.get_cell()) calc = GPAW(xc='M06-L', txt='C_groundstate_M06L_6.txt', gpts=h2gpts(0.20, atoms.get_cell(), idiv=8)) atoms.set_calculator(calc) atoms.get_potential_energy() #calc.diagonalize_full_hamiltonian() # determine all bands calc.write('C_groundstate.gpw', 'all') # write out wavefunctions
def main(): a = 8.267 atoms = read('g1_001.xyz') atoms.cell = (a, a, 2.6) atoms.pbc = (True, True, False) atoms.center() print(atoms.get_cell()) calc = GPAW(xc='PBE', txt='C_groundstate_PBE_10_b.txt', gpts=h2gpts(0.10, atoms.get_cell(), idiv=8)) atoms.set_calculator(calc) atoms.get_potential_energy() #calc.diagonalize_full_hamiltonian() # determine all bands calc.write('C_groundstate_PBE_10_b.gpw', 'all') # write out wavefunctions
def interpolate_weight(calc, weight, h=0.05, n=2): '''interpolates cdft weight function, gd is the fine grid ''' gd = calc.density.finegd weight = gd.collect(weight, broadcast=True) weight = gd.zero_pad(weight) w = np.zeros_like(weight) gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm) gd1.distribute(weight, w) N_c = h2gpts(h / Bohr, gd.cell_cv) N_c = np.array([get_efficient_fft_size(N, n) for N in N_c]) gd2 = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm) interpolator = Interpolator(gd1, gd2) W = interpolator.interpolate(w) return W
def __init__(self, calc, h=0.05, n=2): """Create transformation object. calc: GPAW calculator object The calcalator that has the wave functions. h: float Desired grid-spacing in Angstrom. n: int Force number of points to be a mulitiple of n. """ self.calc = calc gd = calc.wfs.gd gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm) # Descriptor for the final grid: N_c = h2gpts(h / Bohr, gd.cell_cv) N_c = np.array([get_efficient_fft_size(N, n) for N in N_c]) gd2 = self.gd = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm) self.interpolator = Interpolator(gd1, gd2, self.calc.wfs.dtype) self.dphi = None # PAW correction (will be initialized when needed)
def singleGPAW(structure, label, calc=None): # Create calculator if calc is None: calc=GPAW(poissonsolver = PoissonSolver(relax = 'GS',eps = 1.0e-7), # C mode = 'lcao', basis = 'dzp', xc='PBE', gpts = h2gpts(0.2, structure.get_cell(), idiv = 8), # C occupations=FermiDirac(0.1), maxiter=99, # C #maxiter=49, # Sn3O3 mixer=Mixer(nmaxold=5, beta=0.05, weight=75), nbands=-50, #kpts=(1,1,1), # C kpts=(2,2,1), # Sn3O3 txt = label+ '_lcao.txt') else: calc.set(txt=label+'_true.txt') # Set calculator structure.set_calculator(calc) return structure.get_potential_energy(), structure.get_forces()
H = Atoms('H', cell=gra.cell, positions=projpos) # Combine target and projectile atoms = gra + H atoms.set_pbc(True) # Specify the charge state of the projectile, either # 0 (neutral) or 1 (singly charged ion) charge = 0 # default for neutral projectile # Two-stage convergence is needed for the charged system conv_fast = {'energy': 1.0, 'density': 1.0, 'eigenstates': 1.0} conv_par = {'energy': 0.001, 'density': 1e-3, 'eigenstates': 1e-7} if charge == 0: calc = GPAW(gpts=h2gpts(0.2, gra.get_cell(), idiv=8), nbands=110, xc='LDA', txt=name + '_gs.txt', convergence=conv_par) atoms.set_calculator(calc) atoms.get_potential_energy() calc.write(name + '.gpw', mode='all') if charge == 1: const_pot = ConstantPotential(1.0) calc = GPAW(gpts=h2gpts(0.2, gra.get_cell(), idiv=8), nbands=110, xc='LDA',
xc = 'PBE' beef = 'BEEF-vdW' cell = vac * np.array([1, 1, 1]) parprint('completed') #Each calculation will be converged with PBE, then, using same calculator, be run with BEEF. #This enables the PBE WFs to be used as initial guesses for BEEF convergence, hopefully enabling large box sizes. #Data is stored in a dictionary with key: input sys.argv string "s" indicating ion-species. value : tuple of one value and one array, #indicating Gsol and dGsol. output = {} #Perform solvent-only (gas phase) calculation solvent.set_cell(cell) solvent.center() #set box size calc = GPAW(xc=xc, gpts=h2gpts(h, solvent.get_cell(), idiv=16)) solvent.calc = calc solvent.get_potential_energy() #converge WFs with PBE calc.set(xc=beef) solvent.calc = calc E_sv = solvent.get_potential_energy() #BEEF best fit energy ense = BEEFEnsemble(calc) dE_sv = ense.get_ensemble_energies( ) #N=2000 non-self-consist calculation to generate uncertainty spread #Perform solvent-only (solvated phase) calculation scalc = SolvationGPAW(xc=xc, gpts=h2gpts(h, solvent.get_cell(), idiv=16), cavity=EffectivePotentialCavity( effective_potential=Power12Potential(
ncpus = 4 from ase.build import fcc100 from gpaw import GPAW from gpaw.utilities import h2gpts atoms = fcc100(symbol='Ni', size=(1, 1, 9), a=3.52, vacuum=5.5) atoms.set_initial_magnetic_moments([0.6] * len(atoms)) gpts = h2gpts(0.18, atoms.cell, idiv=8) atoms.calc = GPAW(gpts=gpts, kpts=(8, 8, 1), xc='PBE')
def initialize(self, atoms=None): """Inexpensive initialization.""" if atoms is None: atoms = self.atoms else: # Save the state of the atoms: self.atoms = atoms.copy() par = self.input_parameters world = par.communicator if world is None: world = mpi.world elif hasattr(world, 'new_communicator'): # Check for whether object has correct type already # # Using isinstance() is complicated because of all the # combinations, serial/parallel/debug... pass else: # world should be a list of ranks: world = mpi.world.new_communicator(np.asarray(world)) self.wfs.world = world self.set_text(par.txt, par.verbose) natoms = len(atoms) pos_av = atoms.get_positions() / Bohr cell_cv = atoms.get_cell() pbc_c = atoms.get_pbc() Z_a = atoms.get_atomic_numbers() magmom_a = atoms.get_initial_magnetic_moments() magnetic = magmom_a.any() spinpol = par.spinpol if par.hund: if natoms != 1: raise ValueError('hund=True arg only valid for single atoms!') spinpol = True if spinpol is None: spinpol = magnetic elif magnetic and not spinpol: raise ValueError('Non-zero initial magnetic moment for a ' 'spin-paired calculation!') nspins = 1 + int(spinpol) if isinstance(par.xc, str): xc = XC(par.xc) else: xc = par.xc setups = Setups(Z_a, par.setups, par.basis, par.lmax, xc, world) # K-point descriptor kd = KPointDescriptor(par.kpts, nspins) width = par.width if width is None: if kd.gamma: width = 0.0 else: width = 0.1 # eV else: assert par.occupations is None if par.gpts is not None and par.h is None: N_c = np.array(par.gpts) else: if par.h is None: self.text('Using default value for grid spacing.') h = 0.2 else: h = par.h N_c = h2gpts(h, cell_cv) cell_cv /= Bohr if hasattr(self, 'time') or par.dtype==complex: dtype = complex else: if kd.gamma: dtype = float else: dtype = complex kd.set_symmetry(atoms, setups, par.usesymm, N_c) nao = setups.nao nvalence = setups.nvalence - par.charge nbands = par.nbands if nbands is None: nbands = nao elif nbands > nao and par.mode == 'lcao': raise ValueError('Too many bands for LCAO calculation: ' + '%d bands and only %d atomic orbitals!' % (nbands, nao)) if nvalence < 0: raise ValueError( 'Charge %f is not possible - not enough valence electrons' % par.charge) M = magmom_a.sum() if par.hund: f_si = setups[0].calculate_initial_occupation_numbers( magmom=0, hund=True, charge=par.charge, nspins=nspins) Mh = f_si[0].sum() - f_si[1].sum() if magnetic and M != Mh: raise RuntimeError('You specified a magmom that does not' 'agree with hunds rule!') else: M = Mh if nbands <= 0: nbands = int(nvalence + M + 0.5) // 2 + (-nbands) if nvalence > 2 * nbands: raise ValueError('Too few bands! Electrons: %d, bands: %d' % (nvalence, nbands)) if par.width is not None: self.text('**NOTE**: please start using ' 'occupations=FermiDirac(width).') if par.fixmom: self.text('**NOTE**: please start using ' 'occupations=FermiDirac(width, fixmagmom=True).') if self.occupations is None: if par.occupations is None: # Create object for occupation numbers: self.occupations = occupations.FermiDirac(width, par.fixmom) else: self.occupations = par.occupations self.occupations.magmom = M cc = par.convergence if par.mode == 'lcao': niter_fixdensity = 0 else: niter_fixdensity = None if self.scf is None: self.scf = SCFLoop( cc['eigenstates'] * nvalence, cc['energy'] / Hartree * max(nvalence, 1), cc['density'] * nvalence, par.maxiter, par.fixdensity, niter_fixdensity) parsize, parsize_bands = par.parallel['domain'], par.parallel['band'] if parsize_bands is None: parsize_bands = 1 # TODO delete/restructure so all checks are in BandDescriptor if nbands % parsize_bands != 0: raise RuntimeError('Cannot distribute %d bands to %d processors' % (nbands, parsize_bands)) if not self.wfs: if parsize == 'domain only': #XXX this was silly! parsize = world.size domain_comm, kpt_comm, band_comm = mpi.distribute_cpus(parsize, parsize_bands, nspins, kd.nibzkpts, world, par.idiotproof) kd.set_communicator(kpt_comm) parstride_bands = par.parallel['stridebands'] bd = BandDescriptor(nbands, band_comm, parstride_bands) if (self.density is not None and self.density.gd.comm.size != domain_comm.size): # Domain decomposition has changed, so we need to # reinitialize density and hamiltonian: if par.fixdensity: raise RuntimeError("I'm confused - please specify parsize." ) self.density = None self.hamiltonian = None # Construct grid descriptor for coarse grids for wave functions: gd = self.grid_descriptor_class(N_c, cell_cv, pbc_c, domain_comm, parsize) # do k-point analysis here? XXX args = (gd, nvalence, setups, bd, dtype, world, kd, self.timer) if par.mode == 'lcao': # Layouts used for general diagonalizer sl_lcao = par.parallel['sl_lcao'] if sl_lcao is None: sl_lcao = par.parallel['sl_default'] lcaoksl = get_KohnSham_layouts(sl_lcao, 'lcao', gd, bd, dtype, nao=nao, timer=self.timer) self.wfs = LCAOWaveFunctions(lcaoksl, *args) elif par.mode == 'fd' or isinstance(par.mode, PW): # buffer_size keyword only relevant for fdpw buffer_size = par.parallel['buffer_size'] # Layouts used for diagonalizer sl_diagonalize = par.parallel['sl_diagonalize'] if sl_diagonalize is None: sl_diagonalize = par.parallel['sl_default'] diagksl = get_KohnSham_layouts(sl_diagonalize, 'fd', gd, bd, dtype, buffer_size=buffer_size, timer=self.timer) # Layouts used for orthonormalizer sl_inverse_cholesky = par.parallel['sl_inverse_cholesky'] if sl_inverse_cholesky is None: sl_inverse_cholesky = par.parallel['sl_default'] if sl_inverse_cholesky != sl_diagonalize: message = 'sl_inverse_cholesky != sl_diagonalize ' \ 'is not implemented.' raise NotImplementedError(message) orthoksl = get_KohnSham_layouts(sl_inverse_cholesky, 'fd', gd, bd, dtype, buffer_size=buffer_size, timer=self.timer) # Use (at most) all available LCAO for initialization lcaonbands = min(nbands, nao) lcaobd = BandDescriptor(lcaonbands, band_comm, parstride_bands) assert nbands <= nao or bd.comm.size == 1 assert lcaobd.mynbands == min(bd.mynbands, nao) #XXX # Layouts used for general diagonalizer (LCAO initialization) sl_lcao = par.parallel['sl_lcao'] if sl_lcao is None: sl_lcao = par.parallel['sl_default'] initksl = get_KohnSham_layouts(sl_lcao, 'lcao', gd, lcaobd, dtype, nao=nao, timer=self.timer) if par.mode == 'fd': self.wfs = FDWaveFunctions(par.stencils[0], diagksl, orthoksl, initksl, *args) else: # Planewave basis: self.wfs = par.mode(diagksl, orthoksl, initksl, gd, nvalence, setups, bd, world, kd, self.timer) else: self.wfs = par.mode(self, *args) else: self.wfs.set_setups(setups) if not self.wfs.eigensolver: # Number of bands to converge: nbands_converge = cc['bands'] if nbands_converge == 'all': nbands_converge = nbands elif nbands_converge != 'occupied': assert isinstance(nbands_converge, int) if nbands_converge < 0: nbands_converge += nbands eigensolver = get_eigensolver(par.eigensolver, par.mode, par.convergence) eigensolver.nbands_converge = nbands_converge # XXX Eigensolver class doesn't define an nbands_converge property self.wfs.set_eigensolver(eigensolver) if self.density is None: gd = self.wfs.gd if par.stencils[1] != 9: # Construct grid descriptor for fine grids for densities # and potentials: finegd = gd.refine() else: # Special case (use only coarse grid): finegd = gd self.density = Density(gd, finegd, nspins, par.charge + setups.core_charge) self.density.initialize(setups, par.stencils[1], self.timer, magmom_a, par.hund) self.density.set_mixer(par.mixer) if self.hamiltonian is None: gd, finegd = self.density.gd, self.density.finegd self.hamiltonian = Hamiltonian(gd, finegd, nspins, setups, par.stencils[1], self.timer, xc, par.poissonsolver, par.external) xc.initialize(self.density, self.hamiltonian, self.wfs, self.occupations) self.text() self.print_memory_estimate(self.txt, maxdepth=memory_estimate_depth) self.txt.flush() if dry_run: self.dry_run() self.initialized = True
for name in names: # save all steps in one traj file in addition to the database # we should only used the database c.reserve, but here # traj file is used as another lock ... fd = opencew(name + '_' + code + '.traj') if fd is None: continue traj = Trajectory(name + '_' + code + '.traj', 'w') atoms = collection[name] cell = atoms.get_cell() kpts = tuple(kpts2mp(atoms, kptdensity, even=True)) kwargs = {} if mode == 'fd': if constant_basis: # gives more smooth EOS in fd mode kwargs.update({'gpts': h2gpts(e, cell)}) else: kwargs.update({'h': e}) elif mode == 'pw': if constant_basis: kwargs.update({'mode': PW(e, cell=cell)}) else: kwargs.update({'mode': PW(e)}) if name in ['He', 'Ne', 'Ar', 'Kr', 'Xe', 'Rn', 'Ca', 'Sr', 'Ba']: # results wrong / scf slow with minimal basis kwargs.update({'basis': 'dzp'}) kwargs.update({'nbands': -5}) # loop over EOS linspace for n, x in enumerate(np.linspace(linspace[0], linspace[1], linspace[2])): id = c.reserve(category=category, name=name, e=e, linspacestr=linspacestr,
def setup_gpts(self): self.gpts = h2gpts(self.inp.get('spacing') or 0.20, self.atoms.get_cell(), idiv=self.inp.get('idiv') or 8)
system1 = molecule('H2O') system1.set_pbc((True, True, False)) system1.cell = 4.0 * np.array([[1.0, -1.5, 0.0], [1.0, 1.0, 0.0], [0., 0., 1.]]) system1.center(vacuum=10.0, axis=2) system2 = system1.copy() system2.positions *= [1.0, 1.0, -1.0] system2 += system1 system2.center(vacuum=6.0, axis=2) convergence = dict(density=1e-5) calc1 = GPAW(mode='lcao', convergence=convergence, gpts=h2gpts(0.25, system1.cell, idiv=8), poissonsolver=DipoleCorrection(PoissonSolver(relax='GS', eps=1e-11), 2)) system1.set_calculator(calc1) system1.get_potential_energy() v1 = calc1.get_effective_potential(pad=False) calc2 = GPAW(mode='lcao', convergence=convergence, gpts=h2gpts(0.25, system2.cell, idiv=8), poissonsolver=PoissonSolver(relax='GS', eps=1e-11)) system2.set_calculator(calc2)
# But we want to test the pseudopotential search mechanism, therefore # we immediately write it to a file: fd = open('H_ONCV_PBE-1.0.upf', 'w') fd.write(pp_text) fd.close() # All right... system = molecule('H2') system.center(vacuum=2.5) def getkwargs(): return dict(eigensolver='cg', xc='oldPBE', poissonsolver=PoissonSolver(relax='GS', eps=1e-8)) calc1 = GPAW(setups='sg15', gpts=h2gpts(0.16, system.get_cell(), idiv=8), **getkwargs()) system.set_calculator(calc1) system.get_potential_energy() eps1 = calc1.get_eigenvalues() calc2 = GPAW(gpts=h2gpts(0.22, system.get_cell(), idiv=8), **getkwargs()) system.set_calculator(calc2) system.get_potential_energy() eps2 = calc2.get_eigenvalues() err = eps2[0] - eps1[0] # It is not the most accurate calculation ever, let's just make sure things # are not completely messed up.
from ase import Atoms from gpaw import GPAW, PoissonSolver, FermiDirac, Mixer, MixerSum from gpaw.utilities import h2gpts from ase.structure import molecule #s = UPFSetupData('/home/askhl/parse-upf/h_lda_v1.uspp.F.UPF') upfsetups = {'H': UPFSetupData('H.pz-hgh.UPF'), 'O': UPFSetupData('O.pz-hgh.UPF')} system = molecule('H2O') system.center(vacuum=3.5) calc = GPAW(txt='-', nbands=6, #setups=upfsetups, setups='paw', #hund=True, #mixer=MixerSum(0.1, 5, 20.0), #eigensolver='cg', #occupations=FermiDirac(0.1), #charge=1-1e-12, #eigensolver='rmm-diis', gpts=h2gpts(0.12, system.get_cell(), idiv=8), poissonsolver=PoissonSolver(relax='GS', eps=1e-7), xc='oldLDA', #nbands=4 ) system.set_calculator(calc) system.get_potential_energy()
def test(cellno, cellname, cell_cv, idiv, pbc, nn): N_c = h2gpts(0.12, cell_cv, idiv=idiv) if idiv == 1: N_c += 1 - N_c % 2 # We want especially to test uneven grids gd = GridDescriptor(N_c, cell_cv, pbc_c=pbc) rho_g = gd.zeros() phi_g = gd.zeros() rho_g[:] = -0.3 + rng.rand(*rho_g.shape) # Neutralize charge: charge = gd.integrate(rho_g) magic = gd.get_size_of_global_array().prod() rho_g -= charge / gd.dv / magic charge = gd.integrate(rho_g) assert abs(charge) < 1e-12 # Check use_cholesky=True/False ? from gpaw.poisson import FDPoissonSolver ps = FastPoissonSolver(nn=nn) #print('setgrid') # Will raise BadAxesError for some pbc/cell combinations ps.set_grid_descriptor(gd) ps.solve(phi_g, rho_g) laplace = Laplace(gd, scale=-1.0 / (4.0 * np.pi), n=nn) def get_residual_err(phi_g): rhotest_g = gd.zeros() laplace.apply(phi_g, rhotest_g) residual = np.abs(rhotest_g - rho_g) # Residual is not accurate at end of non-periodic directions # except for nn=1 (since effectively we use the right stencil # only for nn=1 at the boundary). # # To do this check correctly, the Laplacian should have lower # nn at the boundaries. Therefore we do not test the residual # at these ends, only in between, by zeroing the bad ones: if nn > 1: exclude_points = nn - 1 for c in range(3): if nn > 1 and not pbc[c]: # get view ehere axis c refers becomes zeroth dimension: X = residual.transpose(c, (c + 1) % 3, (c + 2) % 3) if gd.beg_c[c] == 1: X[:exclude_points] = 0.0 if gd.end_c[c] == gd.N_c[c]: X[-exclude_points:] = 0.0 return residual.max() maxerr = get_residual_err(phi_g) pbcstring = '{}{}{}'.format(*pbc) if 0: ps2 = FDPoissonSolver(relax='J', nn=nn, eps=1e-18) ps2.set_grid_descriptor(gd) phi2_g = gd.zeros() ps2.solve(phi2_g, rho_g) phimaxerr = np.abs(phi2_g - phi_g).max() maxerr2 = get_residual_err(phi2_g) msg = ('{:2d} {:8s} pbc={} err={:8.5e} err[J]={:8.5e} ' 'err[phi]={:8.5e} nn={:1d}' .format(cellno, cellname, pbcstring, maxerr, maxerr2, phimaxerr, nn)) state = 'ok' if maxerr < tolerance else 'FAIL' msg = ('{:2d} {:8s} grid={} pbc={} err[fast]={:8.5e} nn={:1d} {}' .format(cellno, cellname, N_c, pbcstring, maxerr, nn, state)) if world.rank == 0: print(msg) return maxerr
#s = UPFSetupData('/home/askhl/parse-upf/h_lda_v1.uspp.F.UPF') upfsetups = { 'H': UPFSetupData('H.pz-hgh.UPF'), 'O': UPFSetupData('O.pz-hgh.UPF') } system = molecule('H2O') system.center(vacuum=3.5) calc = GPAW( txt='-', nbands=6, setups=upfsetups, #setups='paw', #hund=True, #mixer=MixerSum(0.1, 5, 20.0), #eigensolver='cg', #occupations=FermiDirac(0.1), #charge=1-1e-12, eigensolver=Davidson(2), #eigensolver='rmm-diis', gpts=h2gpts(0.12, system.get_cell(), idiv=8), poissonsolver=PoissonSolver(relax='GS', eps=1e-7), xc='oldLDA', #nbands=4 ) system.set_calculator(calc) system.get_potential_energy()
def _main(): parser = argparse.ArgumentParser("Build and run Heusler slab", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("atoms", type=str, help="Comma-separated list of XYZ/X2YZ atoms (ex: 'Ni,Mn,Sb' or 'Co,Co,Mn,Si')") parser.add_argument("latconst", type=float, help="Lattice constant in Ang (conventional cell cubic edge)") parser.add_argument("layers", type=int, help="Number of layers in the slab") parser.add_argument("--prefix", type=str, default=None, help="System name (obtained from atoms if not specified)") parser.add_argument("--soc", action="store_true", help="Use spin-orbit coupling") args = parser.parse_args() atoms = args.atoms.split(',') prefix = make_prefix(atoms, args.layers, args.soc) filenames = standard_filenames(prefix) vacuum = 20 # Angstrom surface_normal_cubic = (1, 1, 1) slab = make_surface_system(atoms, args.latconst, args.layers, surface_normal_cubic, vacuum) slab.set_pbc((True, True, False)) parallel_scf = make_parallel_scf() ase.io.write(filenames['structure_xsf'], slab, format='xsf') # Perform self-consistent calculation. h = 0.2 # FD grid spacing (Angstrom). Complains about Poisson grid if too small (h = 0.1). smearing_width = 0.1 # eV Nk_scf = 12 # LCAO documentation strongly encorages ensuring grid points are divisible by 8 # to improve performance. gpts = h2gpts(h, slab.get_cell(), idiv=8) calc = GPAW(mode='lcao', basis='dzp', gpts=gpts, xc='PBE', kpts=(Nk_scf, Nk_scf, 1), occupations=MethfesselPaxton(smearing_width), random=True, parallel=parallel_scf, txt=filenames['scf_calc_out']) slab.set_calculator(calc) E_gs = slab.get_potential_energy() calc.write(filenames['scf_restart']) E_F = calc.get_fermi_level() parprint("E_gs = {}".format(E_gs)) parprint("E_F = {}".format(E_F)) # Perform bands calculation. band_path, band_path_labels = get_band_path(surface_normal_cubic) ks_per_panel = 60 band_ks, band_xs, band_special_xs = bandpath(band_path, slab.get_cell(), len(path)*ks_per_panel + 1) run_bands(prefix, E_F, band_ks, band_xs, band_special_xs, band_path_labels)
#cell = [[a, 0, 0], # [0, a, 0], # [0, 0, a] # ] #bulk.center ( vacuum = 5.0, axis = 2) bulk.pbc = (True, True, True) bulk.set_cell(cell, scale_atoms=True) #print(bulk.positions) conv_fast = {'energy' : 1.0, 'density' : 1.0, 'eigenstates' : 1.0} conv_par = {'energy' : 0.001, 'density' : 1e-3, 'eigenstates' : 1e-7} const_pot = ConstantPotential(1.0) calc = GPAW( gpts = h2gpts(0.1, bulk.get_cell(), idiv=16), xc = 'LDA', occupations = FermiDirac (width=ef), txt = name + '.txt', nbands = 30, charge = 1, convergence=conv_fast, external=const_pot, kpts = {'gamma' : True}, parallel = {'band' : None, 'kpt' : None, 'domain' : None, 'order' : 'kdb'} ) bulk.set_calculator (calc)
Enable if-statement in the bottom for nice plots """ system1 = molecule('H2O') system1.set_pbc((True, True, False)) system1.center(vacuum=3.0) system1.center(vacuum=10.0, axis=2) system2 = system1.copy() system2.positions *= [1.0, 1.0, -1.0] system2 += system1 system2.center(vacuum=6.0, axis=2) calc1 = GPAW(mode='lcao', gpts=h2gpts(0.3, system1.cell, idiv=8), poissonsolver=DipoleCorrection( PoissonSolver(relax='GS', eps=1e-11), 2)) system1.set_calculator(calc1) system1.get_potential_energy() v1 = calc1.get_effective_potential(pad=False) calc2 = GPAW(mode='lcao', gpts=h2gpts(0.3, system2.cell, idiv=8), poissonsolver=PoissonSolver(relax='GS', eps=1e-11)) system2.set_calculator(calc2) system2.get_potential_energy() v2 = calc2.get_effective_potential(pad=False)
for name in names: # save all steps in one traj file in addition to the database # we should only used the database c.reserve, but here # traj file is used as another lock ... fd = opencew(name + '_' + code + '.traj') if fd is None: continue traj = Trajectory(name + '_' + code + '.traj', 'w') atoms = collection[name] cell = atoms.get_cell() kpts = tuple(kpts2mp(atoms, kptdensity, even=True)) kwargs = {} if mode in ['fd', 'lcao']: if constant_basis: # gives more smooth EOS in fd mode kwargs.update({'gpts': h2gpts(e, cell)}) else: kwargs.update({'h': e}) elif mode == 'pw': if constant_basis: kwargs.update({'mode': PW(e, cell=cell)}) kwargs.update({'gpts': h2gpts(0.10, cell)}) else: kwargs.update({'mode': PW(e)}) if mode == 'pw': if name in ['Li', 'Na']: # https://listserv.fysik.dtu.dk/pipermail/gpaw-developers/2012-May/002870.html if constant_basis: kwargs.update({'gpts': h2gpts(0.05, cell)}) else: kwargs.update({'h': 0.05})