mod potentials

module potentials

Cluster potentials as objectives.

Every cluster example in this crate used to define its own energy and gradient as loose functions. That made the potential an implementation detail of a demonstration: not reusable, not tested, and not the potential any consumer of this crate would actually run. A campaign reported against a potential written inside its own example is reporting on something no one else can obtain.

These are Objective and Gradient implementations instead, so the cluster driver takes them by the same trait it takes anything else, and crate::methods::cluster_search can be handed a potential from rgpot without knowing the difference.

They are reference implementations. rgpot is where potentials belong, and it reaches this crate as an eindir_objective_t; what these are for is to be a second implementation of the same functions, so the two can be checked against each other. Two independent implementations agreeing to six decimals says more about both than either says alone.

Enums

enum PairKind

Which pair form a PairPotential carries.

LennardJones

4 (r^-12 - r^-6), depth 1 at r = 2^(1/6).

Morse

e^{rho (1 - r)} (e^{rho (1 - r)} - 2), depth 1 at r = 1.

Doye and Wales’ form with epsilon = 1 and r_0 = 1, so rho is the only parameter and sets the range of the force. Their published global minima are in these units.

rho: f64

Range parameter; larger is shorter ranged.

Implementations

impl PairKind

Functions

fn pair(&self, r2: f64) -> (f64, f64)

Pair energy and (dV/dr) / r at squared separation r2.

The derivative is returned divided by r because every caller multiplies it by the separation vector, and dividing once here avoids a square root in the Lennard-Jones case entirely.

fn r_min(&self) -> f64

Separation at the pair minimum, which sets the natural length scale.

Structs and Unions

struct PairPotential

A pairwise cluster potential over n free points in three dimensions.

The state is a flat 3n vector, point-major, which is what the cluster driver and the shape machinery both assume.

n_points: usize

Points in a configuration.

Implementations

impl PairPotential

Functions

fn kind(&self) -> PairKind

The pair form.

fn lennard_jones(n_points: usize) -> Self

Lennard-Jones over n_points, with a domain scaled to the size.

fn morse(n_points: usize, rho: f64) -> Self

Morse over n_points at range rho.

fn new(n_points: usize, kind: PairKind, extent: f64) -> Self

A potential over n_points points, in a box of half-width extent.

The bounds are the search domain the objective declares, not a physical container: a cluster is unbounded, and what keeps it together is the potential. They are set wide enough that a compact structure never touches them.

fn value_and_gradient(&self, x: ArrayView1<f64>) -> (f64, Array1<f64>)

Energy and gradient in one pass.

Fused because a cluster search spends its budget here: the pair loop is the same for both, so computing them separately doubles the cost of every relaxation step.

Traits implemented

impl Objective<f64> for PairPotential
impl Gradient<f64> for PairPotential