Esempio n. 1
0
    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
Esempio n. 2
0
    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)
Esempio n. 3
0
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)
Esempio n. 4
0
 def get_forces(self):
     return calculate_forces(self.calc.wfs,
                             self.calc.td_density.get_density(),
                             self.calc.td_hamiltonian.hamiltonian,
                             self.calc.log)