String method (flake.string_method)
String method for minimum energy path (MEP) search.
Two usage modes
2D translational \((x_\mathrm{cm}, y_\mathrm{cm})\) — fixed orientation: pre-rotate the cluster before calling:
from flake.cluster import rotate
pos_rot = rotate(pos, theta_deg)
result = find_mep(pos_rot, calc_en_f, en_params,
p0=[x0, y0], p1=[x1, y1])
result['points'] has shape (n_pt, 2).
3D roto-translational \((x_\mathrm{cm}, y_\mathrm{cm}, \theta)\) — pos in reference frame; the method rotates internally:
result = find_mep(pos, calc_en_f, en_params,
p0=[x0, y0, th0], p1=[x1, y1, th1],
scale=[lx, ly, ltheta])
result['points'] has shape (n_pt, 3); \(\theta\) is in degrees.
Typical scales: \(\lambda_x = \lambda_y =\) substrate lattice spacing;
\(\lambda_\theta = 60°\) for 6-fold contact, \(30°\) for 12-fold.
Gradient and string step
The gradient of \(E\) with respect to path coordinates is:
Each interior point steps along \(-\nabla E\):
Scale parameter
scale affects only arc-length reparametrization, not the gradient step.
It ensures coordinates with different physical units contribute equally:
Pass scale=None (default) for pure 2D: all coordinates share the same units.
Algorithm
Reference: E, Ren, Vanden-Eijnden, J. Chem. Phys. 126, 164103 (2007).
Initialise \(n_\mathrm{pt}\) points on a straight line from \(p_0\) to \(p_1\).
Each interior point steps along the gradient: \(\mathbf{p}_i \mathrel{+}= dt \cdot \nabla_i(-E)\).
Reparametrize to equal arc-length (scaled, linear interpolation).
Repeat until convergence or
max_steps.
Classes: StringPath, StringPotential
Function: find_mep
- class flake.string_method.StringPath(p0, p1, n_pt, fix_ends=True, scale=None)
Bases:
objectA discrete path in dim-dimensional configuration space.
- Attributes:
points: (n_pt, dim) float64 ndarray – current path coordinates. fix_ends: bool – if True, endpoints are frozen during steps. scale: (dim,) float64 ndarray – coordinate scales for arc length.
- property arc_length
Total arc length of the path in the scaled metric.
- reparametrize()
Redistribute points to equal arc-length spacing (scaled metric).
Linear interpolation is used to avoid cubic overshoot near saddle points, which can prevent convergence.
The scale is applied only to arc-length computation; interpolation is performed on the unscaled coordinates.
- Raises:
RuntimeError: if the path has collapsed to a point.
- step(gradients, dt)
Move each interior point along the gradient, then reparametrize.
- Args:
gradients: (n_pt, dim) ndarray – -dE/dp at each point. dt: float – step size.
- class flake.string_method.StringPotential(pos, calc_en_f, en_params)
Bases:
objectEvaluate substrate energy and gradient along a path.
- Args:
pos: (N, 2) ndarray – cluster positions (reference frame, theta=0). calc_en_f: callable – total energy function from substrate_from_params. en_params: list – extra arguments for calc_en_f.
- evaluate(path_points, n_jobs=1)
Compute energy and gradient (-dE/dp) at every point along the path.
- The dimension of path_points determines the evaluation mode:
dim=2: translational (x_cm, y_cm); pos already oriented by caller. dim=3: roto-translational (x_cm, y_cm, theta_deg); pos rotated here.
- Args:
path_points: (n_pt, dim) ndarray – path coordinates. n_jobs: int – joblib parallel workers.
- Returns:
energies: (n_pt,) ndarray gradients: (n_pt, dim) ndarray – (-dE/dx, -dE/dy) for dim=2;
(-dE/dx, -dE/dy, -dE/dtheta) = (Fx, Fy, tau) for dim=3.
- flake.string_method.find_mep(pos, calc_en_f, en_params, p0, p1, n_pt=100, max_steps=3000, dt=0.0001, fix_ends=True, tol=1e-08, scale=None, n_jobs=1)
Find the minimum energy path between p0 and p1.
- The dimension of the search is inferred from len(p0):
dim=2: translational (x_cm, y_cm); caller pre-rotates pos if theta != 0. dim=3: roto-translational (x_cm, y_cm, theta_deg); pos is the reference
frame (theta=0); rotation is applied internally at each path point.
- Args:
pos: (N, 2) ndarray – cluster positions (reference frame). calc_en_f: callable – total energy function. en_params: list – extra arguments for calc_en_f. p0: (dim,) array-like – start point. p1: (dim,) array-like – end point. n_pt: int – number of points along path. max_steps: int – maximum gradient-descent iterations. dt: float – step size. fix_ends: bool – freeze endpoints (default True). tol: float – convergence: max pointwise displacement
between iterations < tol.
- scale: (dim,) array-like or None – coordinate scales for the
arc-length reparametrization. Default None (ones).
n_jobs: int – parallel workers for potential eval.
- Returns:
- dict with keys:
‘points’ : (n_pt, dim) – final path in configuration space. ‘energy’ : (n_pt,) – energy along final path. ‘gradient’ : (n_pt, dim) – -dE/dp along final path. ‘converged’: bool ‘n_steps’ : int – actual iterations taken. ‘barrier’ : float – max(energy) - min(energy). ‘dim’ : int – 2 or 3.