Skip to content

Integrate Atomic Simulation Environment (ASE) as a Job Adapter#836

Open
kfir4444 wants to merge 12 commits intomainfrom
ase_script
Open

Integrate Atomic Simulation Environment (ASE) as a Job Adapter#836
kfir4444 wants to merge 12 commits intomainfrom
ase_script

Conversation

@kfir4444
Copy link
Collaborator

Summary

This PR introduces a new job adapter that allows ARC to utilize the Atomic Simulation Environment (ASE) as a backend engine. By integrating ASE, ARC can now run single-point energy calculations, geometry optimizations, and vibrational (frequency) analyses using any ASE-compatible calculator.

Key Changes

  • ASE Adapter Interface: Added the main ASEAdapter class (arc/job/adapters/ase.py) and registered it in the adapter factory (arc/job/adapters/common.py and init.py).
  • Standalone Execution Script: Introduced arc/job/adapters/scripts/ase_script.py, a standalone Python script designed to standardise the execution of ASE tasks in a robust, isolated
    environment.
  • Multi-Calculator Support: The script natively supports initializing calculators such as TorchANI (with options for ANI1x, ANI1ccx, ANI2x), xTB, and MOPAC, with fallbacks for
    generic ASE calculators.
  • Flexible Geometry Optimization: Enables geometry optimizations via various engines, including Sella, BFGS, LBFGS, and GPMin. Allows defining constraints (e.g., fixing internal
    coordinates).
  • Robust Vibrational Analysis: Implemented a pure NumPy vibrational analysis function that reliably calculates frequencies, normal modes (Mass Deweighted Normalized), reduced
    masses, and force constants directly from the Hessian, matching physical constants and standards used by TorchANI/ASE.

Impact

This integration significantly broadens ARC's computational capabilities by tapping directly into the ASE ecosystem, making it trivial to incorporate Machine Learning Potentials (like TorchANI) and any method that interacts with ASE very easily.

import sys
import yaml
import numpy as np
from typing import Optional, Union

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'Optional' is not used.
Import of 'Union' is not used.

Copilot Autofix

AI 3 days ago

To fix unused imports, remove the specific unused names from the import statement (or delete the whole import if none of its names are used). This reduces unnecessary dependencies and clarifies which types or modules are actually required.

In this file, from typing import Optional, Union appears on line 15, and neither Optional nor Union is referenced in the displayed code. The minimal, behavior-preserving fix is to remove this import line entirely. No additional methods, definitions, or imports are needed, and no other lines must be modified.

Concretely: in arc/job/adapters/scripts/ase_script.py, delete the line from typing import Optional, Union (currently line 15). Leave all surrounding imports unchanged.

Suggested changeset 1
arc/job/adapters/scripts/ase_script.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/arc/job/adapters/scripts/ase_script.py b/arc/job/adapters/scripts/ase_script.py
--- a/arc/job/adapters/scripts/ase_script.py
+++ b/arc/job/adapters/scripts/ase_script.py
@@ -12,7 +12,6 @@
 import sys
 import yaml
 import numpy as np
-from typing import Optional, Union
 
 from ase import Atoms
 from ase.constraints import FixInternals
EOF
@@ -12,7 +12,6 @@
import sys
import yaml
import numpy as np
from typing import Optional, Union

from ase import Atoms
from ase.constraints import FixInternals
Copilot is powered by AI and may make mistakes. Always verify output.
from ase import Atoms
from ase.constraints import FixInternals
from ase.optimize import BFGS, LBFGS, GPMin
from ase.optimize.sciopt import Converged, OptimizerConvergenceError, SciPyFminBFGS, SciPyFminCG

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'Converged' is not used.
Import of 'OptimizerConvergenceError' is not used.

Copilot Autofix

AI 3 days ago

In general, the correct fix for unused imports is to remove only the unused names from the import statement, leaving in place any names that are actually used. This reduces unnecessary dependencies and clarifies which external APIs the file relies on.

Here, the import line

from ase.optimize.sciopt import Converged, OptimizerConvergenceError, SciPyFminBFGS, SciPyFminCG

should be edited to drop Converged and OptimizerConvergenceError, while keeping SciPyFminBFGS and SciPyFminCG intact (since we cannot see whether they are used elsewhere). This change affects only arc/job/adapters/scripts/ase_script.py at line 20, and no additional methods, imports, or definitions are needed.

Suggested changeset 1
arc/job/adapters/scripts/ase_script.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/arc/job/adapters/scripts/ase_script.py b/arc/job/adapters/scripts/ase_script.py
--- a/arc/job/adapters/scripts/ase_script.py
+++ b/arc/job/adapters/scripts/ase_script.py
@@ -17,7 +17,7 @@
 from ase import Atoms
 from ase.constraints import FixInternals
 from ase.optimize import BFGS, LBFGS, GPMin
-from ase.optimize.sciopt import Converged, OptimizerConvergenceError, SciPyFminBFGS, SciPyFminCG
+from ase.optimize.sciopt import SciPyFminBFGS, SciPyFminCG
 from ase.vibrations import Vibrations
 
 # Constants matched to ASE internal units (3.23.0+) for exact numerical matching
EOF
@@ -17,7 +17,7 @@
from ase import Atoms
from ase.constraints import FixInternals
from ase.optimize import BFGS, LBFGS, GPMin
from ase.optimize.sciopt import Converged, OptimizerConvergenceError, SciPyFminBFGS, SciPyFminCG
from ase.optimize.sciopt import SciPyFminBFGS, SciPyFminCG
from ase.vibrations import Vibrations

# Constants matched to ASE internal units (3.23.0+) for exact numerical matching
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for running calculations via ASE (Atomic Simulation Environment) as a new ARC job adapter, along with YAML parsing adjustments to consume ASE-produced YAML outputs.

Changes:

  • Register a new ase job adapter and supporting standalone execution script (ase_script.py) producing YAML outputs.
  • Extend settings to recognize ASE as supported ESS and define ASE-specific filenames/options/environment mappings.
  • Update YAML parsing and XYZ-from-file fallback to better handle .yml/.yaml inputs.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
arc/settings/settings.py Adds ASE to supported ESS + filenames/options; updates cluster delete command and ASE env mapping.
arc/parser/parser.py Adds .yml/.yaml path in parse_xyz_from_file() to parse geometry via YAML adapter.
arc/parser/adapters/yaml.py Expands supported YAML keys; modifies energy parsing logic.
arc/level.py Changes deduce_software() control flow to return early when software is already set.
arc/job/adapters/scripts/ase_script.py New standalone runner for ASE jobs (SP/opt/freq) producing output.yml.
arc/job/adapters/ase.py New ASEAdapter integrating ASE script into ARC job execution (incore/queue).
arc/job/adapters/init.py Imports/registers the new ASE adapter module.
arc/job/adapter.py Adds ase to JobEnum.
.gitignore Ignores spec.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

delete_command = {'OGE': 'export SGE_ROOT=/opt/sge; /opt/sge/bin/lx24-amd64/qdel',
delete_command = {'OGE': 'export SGE_ROOT=/opt/sge; /opt/sge/bin/scancel',
Comment on lines +269 to +270
ASE_CALCULATORS_ENV = {'torchani': 'TANI_PYTHON',
'xtb': 'SELLA_PYTHON',
Comment on lines +94 to +99
if energy is not None:
# If the value is very small, it might already be in kJ/mol (unlikely for E_elect),
# but standard internal representation is Hartree.
if abs(energy) < 1e6: # Arbitrary threshold to detect Hartree vs kJ/mol
return energy * E_h_kJmol
return energy
Args:
job_type (str, optional): An ARC job type, assists in determining the software.
"""
if self.software is not None:
Comment on lines +292 to +316
if job_type in ['sp', 'opt', 'conf_opt', 'freq', 'optfreq', 'directed_scan']:
output['sp'] = to_hartree(atoms.get_potential_energy())

if job_type in ['opt', 'conf_opt', 'optfreq', 'directed_scan']:
fmax = float(settings.get('fmax', 0.001))
steps = int(settings.get('steps', 1000))
engine_name = settings.get('optimizer', 'BFGS').lower()

engine_dict = {
'bfgs': BFGS, 'lbfgs': LBFGS, 'gpmin': GPMin,
'scipyfminbfgs': SciPyFminBFGS, 'scipyfmincg': SciPyFminCG,
'sella': None,
}
if engine_name == 'sella':
from sella import Sella
opt_class = Sella
else:
opt_class = engine_dict.get(engine_name, BFGS)
opt = opt_class(atoms, logfile=os.path.join(os.path.dirname(input_path), 'opt.log'))

try:
opt.run(fmax=fmax, steps=steps)
save_current_geometry(output, atoms, xyz)
output['sp'] = to_hartree(atoms.get_potential_energy())
except Exception as exc:
Comment on lines +273 to +281
job_type = input_dict.get('job_type')
xyz = input_dict.get('xyz')
settings = input_dict.get('settings', {})

atoms = Atoms(symbols=xyz['symbols'], positions=xyz['coords'])
calc = get_calculator(settings)
atoms.calc = calc

apply_constraints(atoms, input_dict.get('constraints'))
# Default mapping if not yet fully defined in settings.py
DEFAULT_ASE_ENV = {
'torchani': 'TANI_PYTHON',
'xtb': 'XTB_PYTHON',
Comment on lines +30 to +35
class ASEAdapter(JobAdapter):
"""
A generic adapter for ASE (Atomic Simulation Environment) jobs.
Supports multiple calculators and environments.
"""
def __init__(self,
@kfir4444 kfir4444 changed the title Title: Integrate Atomic Simulation Environment (ASE) as a Job Adapter Integrate Atomic Simulation Environment (ASE) as a Job Adapter Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants