Getting started#
A host builds a band, steps until the projected force is under force_tol, and never lets this crate own the loop.
1. Depend on the published crate#
[dependencies]
rgsaddle = "0.2"
rgmin = "0.3"
ndarray = "0.17"
2. Implement BandSurface#
One eval fills energies and gradients for the rows it receives: the whole band on the first call, the interior images afterwards (the endpoints never move, so their energies are cached). The double-well test surface is the shortest honest example:
impl BandSurface for DoubleWell {
fn eval(
&self,
positions: ArrayView2<f64>,
energies: &mut Array1<f64>,
gradients: &mut Array2<f64>,
) -> Result<(), SaddleError> {
// V = (x² − 1)² + 2y² + 2z²
Ok(())
}
}
3. Step#
let config = BandConfig {
force_tol: 1e-3,
max_move: 0.1,
..BandConfig::default()
};
let mut session = BandSession::new(config, initial)?;
loop {
let report = session.step(&surface)?;
if report.status == BandStatus::Converged {
break;
}
}
Default stepper is FIRE, as in eOn’s velocity NEB stepper. L-BFGS runs under rgmin’s Accept::Step: the projected band force is not conservative, so a step is taken without an energy test.
4. Reset when the surface changes#
BandSession::reset is the model-update boundary. Quasi-Newton history taken on one surface epoch must not survive onto the next.
See tests/double_well.rs for the numbers the crate actually converges.