Skip to main content

Growing-String DE-TS

A growing-string double-ended transition-state (GS-DE-TS) job locates the transition state connecting a reactant and a product geometry using the growing-string method. This method builds a chain of interpolated geometries (a "string") and grows it toward the minimum-energy path, taking the highest-energy node as the TS.

What GS-DE-TS Runs

For each submitted job, Atomiverse executes:

  1. Atom mapping — reorders product atoms to match the reactant ordering.
  2. Growing-string search — builds and grows the string between reactant and product using pyGSM.
  3. String path is produced with energies of all nodes; the highest-energy node is taken as the TS.

Your First GS-DE-TS Job

import atomiverse
from atomiverse import Atoms, GrowingStringDETS, JobFailedError
from atomiverse.levels import GFN2_XTB

atomiverse.configure(api_key="your-api-key")

reactant = Atoms.from_smiles("CC")
product = Atoms.from_smiles("C=C")

job = GrowingStringDETS(
reactant_atoms=reactant,
product_atoms=product,
level_of_theory=GFN2_XTB,
)
job.submit()

try:
result = job.require_result()
except JobFailedError as exc:
print(f"Job failed: {exc.failure.error}")
else:
print(f"Converged: {result.converged}")
print(f"TS energy: {result.ts_energy:.6f} Hartree")
print(f"Barrier: {result.reaction_barrier:.6f} Hartree")
print(f"String nodes: {len(result.gsm_path)}")

Input Parameters

Required:

  • reactant_atoms: reactant geometry
  • product_atoms: product geometry
  • level_of_theory: electronic-structure method

Optional:

  • charge (default 0)
  • multiplicity (default 1)

The string resolution is determined adaptively — growth stops automatically once the geometric change between new nodes falls below a convergence threshold. No manual image count is needed.

The reactant and product must have the same number of atoms and the same elemental composition.

job = GrowingStringDETS(
reactant_atoms=reactant,
product_atoms=product,
charge=0,
multiplicity=1,
level_of_theory=GFN2_XTB,
)

Result

job.require_result() returns a GrowingStringDETSResult.

FieldTypeDescription
ts_atomsAtomsConverged TS geometry.
ts_energyfloatTS energy in Hartree.
gsm_pathlist[TrajectoryStep]Final string path with positions, energy, and forces.
ts_optimization_trajectorylist[TrajectoryStep]TS refinement optimization trajectory.
convergedboolWhether the growing-string search converged.
imaginary_frequency_cm1float | NoneImaginary frequency of the converged TS.

Convenience accessors:

PropertyReturns
gsm_path_atomslist[Atoms]
ts_optimization_atomslist[Atoms]
reaction_barrierfloat
result = job.require_result()

for step in result.gsm_path:
print(step.energy)
print(step.forces)

print(f"TS: {result.ts_energy:.6f} Ha")
print(f"Barrier: {result.reaction_barrier:.6f} Ha")

Handling Failures

If the growing-string search crashes or cannot converge, the job transitions to FAILED with a user-facing error message. Partial GSM path frames may be available in the typed failure payload.

from atomiverse import JobFailedError

job.submit()

try:
result = job.require_result()
except JobFailedError as exc:
failure = exc.failure
print(f"GS-DE-TS failed: {failure.error}")

if failure.partial_gsm_path:
print(f"Partial path frames: {len(failure.partial_gsm_path)}")
last = failure.partial_gsm_path[-1]
print(last.energy)
else:
print(f"TS energy: {result.ts_energy:.6f} Ha")
print(f"GSM nodes: {len(result.gsm_path)}")

Non-blocking Submission

from atomiverse import State

job.submit(wait=False)
job.refresh()

if job.state == State.DONE:
result = job.require_result()
print(f"TS energy: {result.ts_energy:.6f} Ha")
elif job.state == State.FAILED:
failure = job.require_failure()
print(failure.error)
print(f"Partial path: {len(failure.partial_gsm_path)} frames")