Skip to main content

Pysisyphus AFIR DE-TS

A Pysisyphus AFIR double-ended transition-state (AFIR DE-TS) job locates the transition state connecting a reactant and a product geometry using the Artificial Force Induced Reaction (AFIR) method. This method applies an artificial force to drive the reactant and product together toward a common TS region, identifies the highest-energy point on the resulting path as the transition state.

What AFIR DE-TS Runs

For each submitted job, Atomiverse executes:

  1. Atom mapping — reorders the product atoms to match the reactant ordering, which is required for the AFIR method.
  2. Endpoint evaluation at the chosen level of theory.
  3. AFIR path search — runs the Pysisyphus AFIR algorithm to find the minimum-energy path between reactant and product.
  4. TS identification — the highest-energy node on the AFIR path is taken as the TS.

Your First AFIR DE-TS Job

import atomiverse
from atomiverse import (
Atoms,
JobFailedError,
PysisyphusAFIRDETS,
)
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 = PysisyphusAFIRDETS(
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"Path nodes: {len(result.afir_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 AFIR method uses the Pysisyphus AFIR algorithm internally. No manual tuning of the artificial force or path parameters is needed.

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

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

Result

job.require_result() returns a PysisyphusAFIRDETSResult.

FieldTypeDescription
ts_atomsAtomsConverged TS geometry.
ts_energyfloatTS energy in Hartree.
reactant_energyfloatReactant endpoint energy in Hartree.
product_energyfloatProduct endpoint energy in Hartree.
afir_pathlist[TrajectoryStep]AFIR path with positions, energy, and forces.
convergedboolWhether the AFIR search converged.

Convenience accessors:

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

for step in result.afir_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 AFIR search crashes or cannot converge, the job transitions to FAILED with a user-facing error message. Partial AFIR 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"AFIR DE-TS failed: {failure.error}")

if failure.partial_afir_path:
print(f"Partial path frames: {len(failure.partial_afir_path)}")
last = failure.partial_afir_path[-1]
print(last.energy)
else:
print(f"TS energy: {result.ts_energy:.6f} Ha")
print(f"AFIR nodes: {len(result.afir_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_afir_path)} frames")