Source code for riigid.convergence.displacement

import numpy as np

from riigid.convergence.criterion import Criterion


[docs] class Criterion_Displacement(Criterion): """RIIGID convergence criterion: Displacement If all atoms move less than cutoff, the criterion is fulfilled. Note ---- This criterion could theoretically be fulfilled, even if the calculation is not actually converged. This is, because the displacement of the atoms not only depends on the force and torque acting on each fragment, but also on the stepsize. If the stepsize is very small, the atoms may move only very little, even though the forces and torques are still large. If you set the stepsize by hand, make sure not to choose a too small value, or use a different/additional convergence criterion. If you use an optimizer with automatic stepsize, the optimizer should prevent this from happening. Attributes ---------- is_converged: bool Whether or not the convergence criterion is fulfilled. cutoff: number If all atoms move less than cutoff, the criterion is fulfilled; [Å] """ def __init__(self, cutoff=1e-3): """Initialize the Displacement convergence criterion. Parameters ---------- cutoff: number, default:1e-3 If all atoms move less than cutoff, the criterion is fulfilled; [Å] """ super().__init__() self.cutoff = cutoff
[docs] def check(self, optimization_history): """Check if the convergence criterion is fulfilled. If yes, self.is_converged is set to True. Parameters ---------- optimization_history: list of riigid.Optimization_Step The history of the optimization, which shall be checked for convergence. (The optimization history is an attribute of the optimizer.) """ # Compare initial and updated structure from last optimization step last_step = optimization_history[-1] old_positions = last_step.structure.atoms.positions new_positions = last_step.updated_structure.atoms.positions # Scalar displacement of all individual atoms displacements = np.linalg.norm(new_positions - old_positions, axis=1) # Maximal scalar displacement of an atom max_displacement = np.max(displacements) if max_displacement < self.cutoff: self.is_converged = True