Integrate Atomic Simulation Environment (ASE) as a Job Adapter#836
Integrate Atomic Simulation Environment (ASE) as a Job Adapter#836
Conversation
| import sys | ||
| import yaml | ||
| import numpy as np | ||
| from typing import Optional, Union |
Check notice
Code scanning / CodeQL
Unused import Note
Show autofix suggestion
Hide autofix suggestion
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.
| @@ -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 |
| 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
Show autofix suggestion
Hide autofix suggestion
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, SciPyFminCGshould 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.
| @@ -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 |
There was a problem hiding this comment.
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
asejob 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/.yamlinputs.
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', |
| ASE_CALCULATORS_ENV = {'torchani': 'TANI_PYTHON', | ||
| 'xtb': 'SELLA_PYTHON', |
| 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: |
| 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: |
| 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', |
| class ASEAdapter(JobAdapter): | ||
| """ | ||
| A generic adapter for ASE (Atomic Simulation Environment) jobs. | ||
| Supports multiple calculators and environments. | ||
| """ | ||
| def __init__(self, |
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
environment.
generic ASE calculators.
coordinates).
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.