namespace gpr::neb

Overview

namespace neb {
 
// typedefs
 
typedef std::function<double(const Eigen::VectorXd&positions)> VarianceEstimator;
typedef std::function<std::pair<double, Eigen::VectorXd>(const Eigen::VectorXd&positions)> NEBOracle;
 
// enums
 
enum AcquisitionType;
enum NEBMode;
 
// structs
 
struct GPNEBConfig;
struct GPNEBResult;
struct Image;
 
// classes
 
class NEBPath;
 
// global functions
 
double perpendicularSigma(const Eigen::VectorXd& gradient_variance, const Eigen::VectorXd& tangent);
int selectNextImage(const std::vector<Eigen::VectorXd>& neb_forces, const std::vector<double>& variances, const std::vector<Eigen::VectorXd>& tangents, const std::vector<bool>& evaluated, AcquisitionType strategy, double kappa = 1.0, std::mt19937* rng = nullptr);
std::vector<int> expandToTriplet(int center, int n_total);
GPNEBResult gpNEB(NEBOracle oracle, const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, const GPNEBConfig& config = {});
Eigen::MatrixXd pairwiseDistances(const Eigen::VectorXd& x, int n_atoms);
double idppEnergy(const Eigen::VectorXd& x, const Eigen::MatrixXd& d_target, int n_atoms);
Eigen::VectorXd idppGradient(const Eigen::VectorXd& x, const Eigen::MatrixXd& d_target, int n_atoms);
std::vector<Eigen::VectorXd> idppInterpolation(const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, int n_atoms, int max_iter = 200, double force_tol = 0.01, double step_size = 0.1);
std::vector<Eigen::VectorXd> collectiveIdppInterpolation(const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, int n_atoms, double spring_constant = 0.1, int max_iter = 500, double force_tol = 0.01, double step_size = 0.05);
 
} // namespace neb

Detailed Documentation

Typedefs

typedef std::function<double(const Eigen::VectorXd&positions)> VarianceEstimator
Posterior variance estimator: positions -> scalar predictive variance of the energy (or any monotonic proxy for “how uncertain

is my current surrogate at these positions”). Consumed by OIE acquisition strategies (MaxVariance, UCB, ThompsonSampling).

Default binding: returns 1.0 (constant) which degrades MaxVariance/UCB/ ThompsonSampling to MaxForce + random noise the legacy behaviour.

Production bindings wrap GaussianProcessRegression::calculateVarianceDispatched so the Laplace mixture variance drives OIE image selection (more force calls on genuinely uncertain images, fewer where the GP is already confident).

typedef std::function<std::pair<double, Eigen::VectorXd>(const Eigen::VectorXd&positions)> NEBOracle

Oracle function: positions -> (energy, gradient).

Global Functions

double perpendicularSigma(const Eigen::VectorXd& gradient_variance, const Eigen::VectorXd& tangent)

Compute perpendicular GP variance (variance orthogonal to path tangent).

sigma_perp = sqrt(sum_d sigma_d^2 * (1 - tau_d^2))

Parameters:

gradient_variance

Per-component gradient variance

tangent

Unit tangent vector

Returns:

Perpendicular standard deviation

int selectNextImage(const std::vector<Eigen::VectorXd>& neb_forces, const std::vector<double>& variances, const std::vector<Eigen::VectorXd>& tangents, const std::vector<bool>& evaluated, AcquisitionType strategy, double kappa = 1.0, std::mt19937* rng = nullptr)

Select the next image to evaluate via acquisition strategy.

Parameters:

neb_forces

NEB forces at each intermediate image

variances

GP variance at each intermediate image

tangents

Unit tangent vectors at each intermediate image

evaluated

Which images have been evaluated this iteration

strategy

Acquisition strategy to use

kappa

UCB exploration parameter (for UCB strategy)

rng

Random number generator (for Thompson sampling)

Returns:

Index of the selected image (1-based, intermediate only)

std::vector<int> expandToTriplet(int center, int n_total)

Expand a single image index to a triplet {i-1, i, i+1}.

Triplet evaluation ensures the improved tangent at the center image uses ground-truth neighbors.

Parameters:

center

Center image index

n_total

Total number of images (including endpoints)

Returns:

Vector of image indices to evaluate

GPNEBResult gpNEB(NEBOracle oracle, const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, const GPNEBConfig& config = {})

Run GP-accelerated NEB.

Parameters:

oracle

Energy/gradient evaluation function

initial

Initial state positions (flat)

final_state

Final state positions (flat)

n_images

Number of intermediate images

config

NEB configuration

Returns:

GPNEBResult

Eigen::MatrixXd pairwiseDistances(const Eigen::VectorXd& x, int n_atoms)

Compute pairwise distance matrix for a flat coordinate vector.

Parameters:

x

Flat positions [x1,y1,z1,x2,y2,z2,…], size 3*n_atoms

n_atoms

Number of atoms

Returns:

n_atoms x n_atoms symmetric distance matrix

double idppEnergy(const Eigen::VectorXd& x, const Eigen::MatrixXd& d_target, int n_atoms)

IDPP energy for a single image.

E = 0.5 * sum_{i<j} (r_ij - d_target_ij)^2 / r_ij^4

Parameters:

x

Flat positions

d_target

Target distance matrix

n_atoms

Number of atoms

Returns:

IDPP energy

Eigen::VectorXd idppGradient(const Eigen::VectorXd& x, const Eigen::MatrixXd& d_target, int n_atoms)

IDPP gradient (dE/dR) for a single image.

Parameters:

x

Flat positions

d_target

Target distance matrix

n_atoms

Number of atoms

Returns:

IDPP gradient, same size as x

std::vector<Eigen::VectorXd> idppInterpolation(const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, int n_atoms, int max_iter = 200, double force_tol = 0.01, double step_size = 0.1)

Initialize NEB path via per-image IDPP optimization.

For each intermediate image:

  1. Compute target distances via linear interpolation of endpoint distances

  2. Start from linear interpolation of positions

  3. Steepest descent on IDPP energy

Parameters:

initial

Initial state positions (flat)

final_state

Final state positions (flat)

n_images

Number of intermediate images

n_atoms

Number of atoms

max_iter

Maximum IDPP optimization iterations per image

force_tol

Convergence tolerance (max gradient norm)

step_size

Steepest descent step size

Returns:

Vector of intermediate image positions

std::vector<Eigen::VectorXd> collectiveIdppInterpolation(const Eigen::VectorXd& initial, const Eigen::VectorXd& final_state, int n_images, int n_atoms, double spring_constant = 0.1, int max_iter = 500, double force_tol = 0.01, double step_size = 0.05)

Initialize NEB path via collective IDPP with spring forces (S-IDPP).

All intermediate images optimized collectively with:

  • Perpendicular IDPP forces (towards target distances)

  • Parallel spring forces (even image spacing)

Parameters:

initial

Initial state positions (flat)

final_state

Final state positions (flat)

n_images

Number of intermediate images

n_atoms

Number of atoms

spring_constant

NEB spring constant

max_iter

Maximum collective optimization iterations

force_tol

Convergence tolerance

step_size

Step size

Returns:

Vector of intermediate image positions