Custom convergence criteria

Additional convergence keywords

There are additional keywords that you can provide to the convergence dictionary beyond those in the default dictionary. These include 'forces', 'work function', and 'minimum iterations'. (See Built-in criteria for a list of all available criteria and their parameters.) For example, to make sure that the work function changes by no more than 0.001 eV across the last three SCF iterations, you can do:

from gpaw import GPAW

convergence={'work function': 0.001}

calc = GPAW(...,
            convergence=convergence)

In the example above, the default criteria (energy, eigenstates, and density) will still be present and enforced at their default values. The default convergence criteria are always active, but you can effectively turn them off by setting any of them to np.inf.

Changing criteria behavior

You can change things about how some convergence criteria work through an alternative syntax. For example, the default syntax of convergence={'energy': 0.0005} ensures that the last three values of the energy change by no more than 5 meV. If you’d rather have it examine changes in the last four values of the energy, you can set your convergence dictionary to:

from gpaw.convergence_criteria import Energy

convergence = {'energy': Energy(tol=0.0005, n_old=4)}

(In fact, convergence={'energy': 0.0005} is just a shortcut to convergence={'energy': Energy(0.0005)}; the dictionary value 0.0005 becomes the first positional argument to Energy.)

Converging forces

You can ensure that the forces are converged like:

convergence = {'forces': 0.01}

This requires that the maximum change in the magnitude of the vector representing the difference in forces for each atom is less than 0.01 eV/ Angstrom, compared to the previous iteration. Since calculating the atomic forces takes computational time and memory, by default this waits until all other convergence criteria are met before beginning to check the forces. If you’d rather have it check the forces at every SCF iteration you can instead do:

from gpaw.convergence_criteria import Forces

convergence = {'forces': Forces(0.01, calc_last=False)}

You can also choose to converge forces relative to the current maximum force acting on all atoms in your system. This is particularly useful for example in the case of geometry optimizations far from local minima where large forces mean that strict SCF (and therefore forces) convergence is not necessary. For this one can do:

# Converge forces to 10% of the highest force.
convergence = {'forces': Forces(atol=np.inf, rtol=0.1)}

If both atol and rtol are supplied, then forces are converged to whichever is the stricter convergence for that SCF cycle:

# During a geometry optimization, converge forces to 0.01 eV/Ang
# between successive SCF iterations until forces are below
# 0.1 eV/Ang, then 10% of maximum force in system.
convergence = {'forces': Forces(atol=0.01, rtol=0.1)}

Example: fixed iterations

You can use this approach to tell the SCF cycle to run for a fixed number of iterations. To do this, set all the default criteria to np.inf to turn them off, then use the MinIter class to set a minimum number of iterations. (Also be sure your maxiter keyword is set higher than this value!) For example, to run for exactly 10 iterations:

convergence = {'energy': np.inf,
               'eigenstates': np.inf,
               'density': np.inf,
               'minimum iterations': 10}

The MinIter class can work in concert with other convergence criteria as well; that is, it can act simply to define a minimum number of iterations that must be run, even if all other criteria have been met.

Writing your own criteria

You can write your own custom convergence criteria if you structure them like this:

from gpaw.convergence_criteria import Criterion


class MyCriterion(Criterion):
    name = 'my criterion'  # must be a unique name
    tablename = 'mycri'  # <=5 char, prints as header in the SCF table
    calc_last = False  # if True, waits until all other criteria are met
                       # before checking (for expensive criteria)

    def __init__(self, ...):
        ...  # your code here; note if you save all arguments directly
             # (as self.a, self.b, ...) then todict() and __repr__ methods
             # will work automatically.
        # The next line prints at the top of the log file.
        self.description = 'My custom criterion with tolerance ...'

    def __call__(self, context):
        ...  # your code here
             # 'context' is an object containing references to the current
             # state of the calculation, such as the hamiltonian and wave
             # functions
        converged = ...  # True or False if your criterion is met
        entry = ...  # a string with up to 5 characters to print in SCF table
        return converged, entry

    def reset(self):
        ...  # your code here to clear anything saved whenever
             # the SCF restarts



calc = GPAW(...,
            convergence={'custom': [MyCriterion(0.01, 4)]}
           )

All user-written criteria must enter the dictionary through the special custom keyword, and you can include as many criteria as you like in the list.

Note

If you have written your own criterion and you save your calculator instance (that is, calc.write('out.gpw')), GPAW won’t know how to load your custom criterion when it opens”out.gpw”. You will need to add your custom criteria back manually.

Note

If you are running multiple GPAW calculator instances simultaneously, make sure each calculator instance gets its own unique instance of your custom criterion. (You do not need to worry about this for any of the built-in criteria, as it makes an internal copy.)

Built-in criteria

The built-in criteria, along with their shortcut names that you can use to access them in the convergence dictionary, are below. The criteria marked as defaults are present in the default convergence dictionary and will always be present; the others are optional.

class

name attribute

default?

calc_last?

override_others?

Energy

energy

Yes

No

No

Density

density

Yes

No

No

Eigenstates

eigenstates

Yes

No

No

Forces

forces

No

Yes

No

WorkFunction

work function

No

No

No

MinIter

minimum iterations

No

No

No

MaxIter

maximum iterations

No

No

Yes

Full descriptions for the built-in criteria follow.

class gpaw.convergence_criteria.Energy(tol, *, n_old=3, relative=True)[source]

A convergence criterion for the total energy.

Parameters:

tol: float

Tolerance for conversion; that is the maximum variation among the last n_old values of the (extrapolated) total energy.

n_old: int

Number of energy values to compare. I.e., if n_old is 3, then this compares the peak-to-peak difference among the current total energy and the two previous.

relative: bool

Use total energy [eV] or total energy relative to number of valence electrons [eV/(valence electron)].

class gpaw.convergence_criteria.Density(tol)[source]

A convergence criterion for the electron density.

Parameters:

tolfloat

Tolerance for conversion; that is the maximum change in the electron density, calculated as the integrated absolute value of the density change, normalized per valence electron. [electrons/(valence electron)]

class gpaw.convergence_criteria.Eigenstates(tol)[source]

A convergence criterion for the eigenstates.

Parameters:

tolfloat

Tolerance for conversion; that is the maximum change in the eigenstates, calculated as the integration of the square of the residuals of the Kohn–Sham equations, normalized per valence electron. [eV^2/(valence electron)]

class gpaw.convergence_criteria.Forces(atol, rtol=inf, calc_last=True)[source]

A convergence criterion for the forces.

Parameters:

atolfloat

Absolute tolerance for convergence; that is, the force on each atom is compared with its force from the previous iteration, and the change in each atom’s force is calculated as an l2-norm (Euclidean distance). The atom with the largest norm must be less than tol. [eV/Angstrom]

rtolfloat

Relative tolerance for convergence. The difference in the l2-norm of force on each atom is calculated, and convergence is achieved when the largest difference between two iterations is rtol * max force.

calc_lastbool

If True, calculates forces last; that is, it waits until all other convergence criteria are satisfied before checking to see if the forces have converged. (This is more computationally efficient.) If False, checks forces at each SCF step.

class gpaw.convergence_criteria.WorkFunction(tol=0.005, n_old=3)[source]

A convergence criterion for the work function.

Parameters:

tolfloat

Tolerance for conversion; that is the maximum variation among the last n_old values of either work function. [eV]

n_oldint

Number of work functions to compare. I.e., if n_old is 3, then this compares the peak-to-peak difference among the current work function and the two previous.

class gpaw.convergence_criteria.MinIter(n)[source]

A convergence criterion that enforces a minimum number of iterations.

Parameters:

nint

Minimum number of iterations that must be complete before the SCF cycle exits.

class gpaw.convergence_criteria.MaxIter(n)[source]

A convergence criterion that enforces a maximum number of iterations.

Parameters:

nint

Maximum number of iterations that must be complete before the SCF cycle exits.