Hybrid Eigenvector Following

The single_ended_search module contains methods for locating transition states starting from a single point

class topsearch.transition_states.hybrid_eigenvector_following.HybridEigenvectorFollowing(potential: Potential, ts_conv_crit: float, ts_steps: int, pushoff: float, steepest_descent_conv_crit: float = 1e-06, min_uphill_step_size: float = 1e-07, max_uphill_step_size: float = 1.0, positive_eigenvalue_step: float = 0.1, eigenvalue_conv_crit: float = 1e-05, output_level: int = 0, tag: str = '')

Description

Class for single-ended transition state searches. Starting from a given position the hybrid eigenvector-following algorithm (https://doi.org/10.1103/PhysRevB.59.3969) is used to take steps uphill until a Hessian index one point is found. i) Finds eigenvector corresponding to the lowest eigenvalue ii) Take a step along that eigenvector iii) Minimise in the remaining subspace iv) Repeat until convergence

potential

Function on which we are attempting to find transition states

Type:

class instance

conv_crit

The value the norm of the gradient must be less than before the transition state is considered converged

Type:

float

ts_steps

Allowed number of steps before giving up on transition state

Type:

int

max_uphill_step_size

Maximum size of a step that goes in the uphill direction following the eigenvector corresponding to the negative eigenvalue

Type:

float

positive_eigenvalue_step

The size of a step along the eigenvector corresponding to the smallest eigenvalue, when it is still positive

Type:

float

pushoff

The size of the displacement along the eigenvector when finding connected minima for each transition state

Type:

float

eig_bounds

Bounds placed on the eigenvector during minimisation, updated throughout the search based on active bounds

Type:

list

failure

Contains the reason for failure to find a transition state to report

Type:

string

remove_trans_rot

Flag as to whether to remove eigenvectors that correspond to overall translation and rotation, needed for atomic and molecular systems

Type:

bool

analytic_step_size(grad: NDArray[Any, Any], eigenvector: NDArray[Any, Any], eigenvalue: float) float

Analytical expression to compute an optimal step length from coords along eigenvector, given its eigenvalue. Return the appropriate step length in the uphill direction

check_eigenvector_direction(eigenvector: NDArray[Any, Any], position: NDArray[Any, Any]) NDArray[Any, Any]

Check the eigenvector is pointing in the uphill direction, and if not, flip it so it is

check_valid_eigenvector(eigenvector: NDArray[Any, Any], eigenvalue: float, coords: StandardCoordinates) bool

Test that an eigenvector is valid. It cannot contain only zeros or any nans

do_pushoff(ts_position: StandardCoordinates, eigenvector: NDArray[Any, Any], increment: float, iteration: int) NDArray[Any, Any]

Take a step along the pushoff. Return the new position after performing pushoff

find_pushoff(transition_state: StandardCoordinates, eigenvector: NDArray[Any, Any]) tuple[NDArray[Any, Any], NDArray[Any, Any]]

Given the transition state location and direction of its single negative eigenvalue. We compute a step length in this direction before beginning a steepest-descent path. Returns the points to begin steepest-descent paths in the forwards and backwards direction

generate_random_vector(ndim: int) NDArray[Any, Any]

Return random uniform vector on sphere

get_local_bounds(coords: StandardCoordinates) list

Create a box around the given point that ensures that subspace minimisation is bounded to a small region to avoid moving to a different basin. Still respect total function bounds

get_smallest_eigenvector(initial_vector: NDArray[Any, Any], coords: StandardCoordinates, lower_bounds: NDArray[Any, Any], upper_bounds: NDArray[Any, Any]) NDArray[Any, Any]

Routine to find the smallest eigenvalue and the associated eigenvector of the Hessian at a given point coords. Method tests for validity and deals with bounds

parallel_component(vec1: NDArray[Any, Any], vec2: NDArray[Any, Any]) NDArray[Any, Any]

Return parallel component of vec1 relative to vec2

perpendicular_component(vec1: NDArray[Any, Any], vec2: NDArray[Any, Any]) NDArray[Any, Any]

Return perpendicular component of vector vec1 relative to vec2

project_onto_bounds(vector: NDArray[Any, Any], lower_bounds: NDArray[Any, Any], upper_bounds: NDArray[Any, Any]) NDArray[Any, Any]

Project vector back to within the bounds if pointing outside

rayleigh_ritz_function_gradient(vec: NDArray[Any, Any], *args: list) tuple[float, NDArray[Any, Any]]

Evaluate the Rayleigh-Ritz ratio to find the value of the eigenvalue for a given eigenvector vec computed at point coords, and the gradient with respect to changes in vec

remove_zero_eigenvectors(vec: NDArray[Any, Any], position: NDArray[Any, Any]) NDArray[Any, Any]

Make vec orthogonal to eigenvectors of the Hessian corresponding to overall translations and rotations at given position

run(coords: StandardCoordinates, tag: str = '') tuple

Perform a single-ended transition state search starting from coords. Returns the information about transition states and their connected minima that is needed for testing similarity and adding to stationary point network

steepest_descent(transition_state: StandardCoordinates, eigenvector: NDArray[Any, Any]) tuple

Perturb away from the transition state along the eigenvector corresponding to the negative eigenvalue and minimise to produce the two connected minima and their energies Returns the coordinates and energy of both connected minima

steepest_descent_paths(coords: StandardCoordinates) tuple

Perform local minimisation to get the result of a steepest descent path beginning from position. To avoid very large initial steps in LBFGS we constrain the local minimisation into several short steps

subspace_function_gradient(position: NDArray[Any, Any], *args: list) tuple[float, NDArray[Any, Any]]

Return the function value and the component of the gradient perpendicular to self.eigenvector at point coords

subspace_minimisation(coords: StandardCoordinates, eigenvector: NDArray[Any, Any]) tuple

Perform minimisation in the subspace orthogonal to eigenvector. The distance is limited to be at most 2% of the range of the space to avoid very large initial steps in scipy.lbfgs

take_uphill_step(coords: StandardCoordinates, eigenvector: NDArray[Any, Any], eigenvalue: float) NDArray[Any, Any]

Take uphill step of appropriate length given an eigenvector that defines the step direction, and an eigenvalue that determines if the step is uphill or not. Return coords after step is taken

test_convergence(position: NDArray[Any, Any], lower_bounds: NDArray[Any, Any], upper_bounds: NDArray[Any, Any]) bool

Test for convergence accounting for active bounds. Only consider the gradient components in dimensions not at bounds. Return True if points passes convergence test

update_eigenvector_bounds(lower_bounds: NDArray[Any, Any], upper_bounds: NDArray[Any, Any]) None

Update the bounds on eigenvector to ensure it remains in certain portion of the sphere that points within the function bounds