Cloud Calculator
CloudCalculator wraps Atomiverse SinglePointEnergy jobs behind ASE's calculator interface so you can attach it directly to an ase.Atoms object.
This integration is intentionally convenient, not maximally efficient. Each fresh ASE evaluation submits a remote single-point job, so this is usually not the best choice for tight geometry optimization loops, molecular dynamics, or other high-throughput workflows.
Basic Usage
from ase import Atoms
from atomiverse import CloudCalculator
from atomiverse.levels import GFN2_XTB
atoms = Atoms(
"H2O",
positions=[
[0.000, 0.000, 0.119],
[0.000, 0.763, -0.477],
[0.000, -0.763, -0.477],
],
)
atoms.calc = CloudCalculator(level_of_theory=GFN2_XTB)
energy = atoms.get_potential_energy() # eV
forces = atoms.get_forces() # eV/Angstrom
print(energy)
print(forces)
CloudCalculator exposes the standard ASE properties:
| Property | ASE Units |
|---|---|
energy | eV |
forces | eV/Angstrom |
Under the hood, Atomiverse runs a single-point energy calculation and converts the result from Hartree / Hartree-Angstrom units into ASE's expected units. If ASE asks only for the potential energy, CloudCalculator submits an energy-only job. If ASE asks for forces, it submits a force-capable job.
energy = atoms.get_potential_energy() # submits an energy-only job
forces = atoms.get_forces() # submits a job with forces when needed
Preferred Use Cases
Use CloudCalculator when you want:
- a clean ASE-native interface
- to attach Atomiverse directly to an existing
ase.Atomsworkflow - convenient energy / force evaluation without managing jobs manually
Use direct SinglePointEnergy(...) jobs instead when you want:
- one-off single-point calculations
- explicit access to job IDs, dashboard naming, refresh, cancellation, or deletion
- tighter control over large submission loops or higher-throughput workflows
Managed Cloud And BYOC
By default, CloudCalculator submits to Atomiverse managed cloud compute.
If you need to target your own registered BYOC controller, pass compute_target:
from atomiverse import CloudCalculator
atoms.calc = CloudCalculator(
level_of_theory=GFN2_XTB,
compute_target="my-cluster",
wait_for_capacity=True,
)
The same pass-through options available on SinglePointEnergy.submit() are supported:
compute_targetwait_for_capacitymax_waittimeout
Accessing The Underlying Job
After a calculation, calc.last_job holds the submitted SinglePointEnergy instance:
calc = CloudCalculator(level_of_theory=GFN2_XTB)
atoms.calc = calc
atoms.get_potential_energy()
print(calc.last_job.job_id)
print(calc.last_job.compute_forces) # False for an energy-only call
print(calc.last_job.require_result().energy) # Hartree
This is useful when you want ASE for execution but still want access to the Atomiverse job metadata afterward.
If you need forces from the underlying job, request forces through ASE first:
atoms.get_forces()
result = calc.last_job.require_result()
print(result.forces) # Hartree/Angstrom
ASE Optimizer Example
This works and can be a nice integration point, but each new optimizer step may trigger a fresh remote single-point submission. For many-step optimizations, using Atomiverse jobs directly is usually the better choice.
from ase import Atoms
from ase.optimize import BFGS
from atomiverse import CloudCalculator
from atomiverse.levels import GFN2_XTB
atoms = Atoms(
"H2",
positions=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.80]],
)
atoms.calc = CloudCalculator(level_of_theory=GFN2_XTB)
optimizer = BFGS(atoms)
optimizer.run(fmax=0.05)