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? |
---|---|---|---|---|
|
Yes |
No |
No |
|
|
Yes |
No |
No |
|
|
Yes |
No |
No |
|
|
No |
Yes |
No |
|
|
No |
No |
No |
|
|
No |
No |
No |
|
|
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.