def collect_errors(self, dens, ham, wfs): """Check convergence of eigenstates, energy and density.""" errors = {'eigenstates': wfs.eigensolver.error, 'density': dens.error, 'force': np.inf, 'energy': np.inf} if dens.fixed: errors['density'] = 0.0 if len(self.old_energies) >= 3: errors['energy'] = np.ptp(self.old_energies[-3:]) if self.max_errors['force'] < np.inf: F_av = calculate_forces(wfs, dens, ham) if self.old_F_av is not None: errors['force'] = ((F_av - self.old_F_av)**2).sum(1).max()**0.5 self.old_F_av = F_av return errors
def calculate(self, atoms=None, properties=['energy'], system_changes=['cell']): """Calculate things.""" Calculator.calculate(self, atoms) atoms = self.atoms if system_changes: self.log('System changes:', ', '.join(system_changes), '\n') if system_changes == ['positions']: # Only positions have changed: self.density.reset() else: # Drastic changes: self.wfs = None self.occupations = None self.density = None self.hamiltonian = None self.scf = None self.initialize(atoms) self.set_positions(atoms) if not self.initialized: self.initialize(atoms) self.set_positions(atoms) if not (self.wfs.positions_set and self.hamiltonian.positions_set): self.set_positions(atoms) if not self.scf.converged: print_cell(self.wfs.gd, self.atoms.pbc, self.log) with self.timer('SCF-cycle'): self.scf.run(self.wfs, self.hamiltonian, self.density, self.occupations, self.log, self.call_observers) self.log('\nConverged after {0} iterations.\n'.format( self.scf.niter)) e_free = self.hamiltonian.e_total_free e_extrapolated = self.hamiltonian.e_total_extrapolated self.results['energy'] = e_extrapolated * Ha self.results['free_energy'] = e_free * Ha if not self.atoms.pbc.all(): dipole_v = self.density.calculate_dipole_moment() * Bohr self.log( 'Dipole moment: ({0:.6f}, {1:.6f}, {2:.6f}) |e|*Ang\n'. format(*dipole_v)) self.results['dipole'] = dipole_v if self.wfs.nspins == 2: magmom = self.occupations.magmom magmom_a = self.density.estimate_magnetic_moments(total=magmom) self.log('Total magnetic moment: %f' % magmom) self.log('Local magnetic moments:') symbols = self.atoms.get_chemical_symbols() for a, mom in enumerate(magmom_a): self.log('{0:4} {1:2} {2:.6f}'.format(a, symbols[a], mom)) self.log() self.results['magmom'] = self.occupations.magmom self.results['magmoms'] = magmom_a self.summary() self.call_observers(self.scf.niter, final=True) if 'forces' in properties: with self.timer('Forces'): F_av = calculate_forces(self.wfs, self.density, self.hamiltonian, self.log) self.results['forces'] = F_av * (Ha / Bohr) if 'stress' in properties: with self.timer('Stress'): try: stress = calculate_stress(self).flat[[0, 4, 8, 5, 2, 1]] except NotImplementedError: # Our ASE Calculator base class will raise # PropertyNotImplementedError for us. pass else: self.results['stress'] = stress * (Ha / Bohr**3)
def run(formula='H2O', vacuum=1.5, cell=None, pbc=1, **morekwargs): print(formula, parallel) system = molecule(formula) kwargs = dict(basekwargs) kwargs.update(morekwargs) calc = GPAW(**kwargs) system.set_calculator(calc) system.center(vacuum) if cell is None: system.center(vacuum) else: system.set_cell(cell) system.set_pbc(pbc) try: system.get_potential_energy() except KohnShamConvergenceError: pass E = calc.hamiltonian.e_total_free F_av = calculate_forces(calc.wfs, calc.density, calc.hamiltonian) global Eref, Fref_av if Eref is None: Eref = E Fref_av = F_av eerr = abs(E - Eref) ferr = abs(F_av - Fref_av).max() if calc.wfs.world.rank == 0: print('Energy', E) print() print('Forces') print(F_av) print() print('Errs', eerr, ferr) if eerr > tolerance or ferr > tolerance: if calc.wfs.world.rank == 0: stderr = sys.stderr else: stderr = devnull if eerr > tolerance: print('Failed!', file=stderr) print('E = %f, Eref = %f' % (E, Eref), file=stderr) msg = 'Energy err larger than tolerance: %f' % eerr if ferr > tolerance: print('Failed!', file=stderr) print('Forces:', file=stderr) print(F_av, file=stderr) print(file=stderr) print('Ref forces:', file=stderr) print(Fref_av, file=stderr) print(file=stderr) msg = 'Force err larger than tolerance: %f' % ferr print(file=stderr) print('Args:', file=stderr) print(formula, vacuum, cell, pbc, morekwargs, file=stderr) print(parallel, file=stderr) raise AssertionError(msg)
def get_forces(self): return calculate_forces(self.calc.wfs, self.calc.td_density.get_density(), self.calc.td_hamiltonian.hamiltonian, self.calc.log)