Quick start
Relax a water molecule with GFN2-xTB and compare its geometry with experiment.
Build a structure
Section titled “Build a structure”Start with O–H bonds of 1.10 Å and an angle of 100°.
import mathfrom atomli import Atoms
bond, half = 1.10, math.radians(100.0) / 2atoms = Atoms("OH2", positions=[ [0.0, 0.0, 0.0], [0.0, bond * math.sin(half), bond * math.cos(half)], [0.0, -bond * math.sin(half), bond * math.cos(half)],])Distances are angstrom and energies are electronvolt everywhere at the Python boundary.
Attach a calculator
Section titled “Attach a calculator”The calculator lives on the Atoms object. Everything downstream, optimizers
and dynamics included, asks that object for energies and forces.
from atomli.calculators.xtb import XTBimport numpy as np
atoms.calc = XTB(method="gfn2")
print(f"{atoms.get_potential_energy():.3f} eV")print(f"{np.linalg.norm(atoms.get_forces(), axis=1).max():.3f} eV/A")-137.320 eV5.208 eV/ARelaxation
Section titled “Relaxation”BFGS follows those forces downhill until the largest one falls below fmax.
logfile="-" prints each step to the terminal.
from atomli.optimize import BFGS
frames = [atoms.copy()] # the guess itselfopt = BFGS(atoms, logfile="-")opt.attach(lambda: frames.append(atoms.copy()), interval=1) # and every stepopt.run(fmax=0.02) Step Time Energy fmaxBFGS: 0 02:35:01 -137.319890 5.208098BFGS: 1 02:35:01 -137.910757 1.785617BFGS: 2 02:35:01 -137.949921 1.460929BFGS: 3 02:35:01 -137.974519 0.224973BFGS: 4 02:35:01 -137.975473 0.115909BFGS: 5 02:35:01 -137.976199 0.110091BFGS: 6 02:35:01 -137.976494 0.059372BFGS: 7 02:35:01 -137.976542 0.0100027 steps. The energy drops 0.657 eV and the force falls by a factor of 521.
Geometry validation
Section titled “Geometry validation”Compare the relaxed bond length and angle with experiment.
oh, oh2 = atoms.get_positions()[1:] - atoms.get_positions()[0]angle = math.degrees(math.acos(oh @ oh2 / (np.linalg.norm(oh) * np.linalg.norm(oh2))))
print(f"O-H {atoms.get_distance(0, 1):.3f} A")print(f"H-O-H {angle:.1f} deg")Atoms has get_distance but no get_angle, so the angle is measured by
hand.
| Your guess | GFN2-xTB | Experiment | |
|---|---|---|---|
| O-H | 1.100 Å | 0.959 Å | 0.958 Å |
| H-O-H | 100.0° | 107.2° | 104.5° |
The bond length lands
0.001 Å from
experiment. The angle is
2.7° too
wide, which is GFN2-xTB’s own error, not a failed relaxation. A tighter fmax
will not move it. Changing method will.
Visualization
Section titled “Visualization”from atomli.visualize import view
view(atoms) # the relaxed moleculeview(frames) # or the whole relaxation, with a scrubberIn a notebook, view() displays the structure in the cell. An atoms object on the last line also displays the structure.
Drag to rotate. Use the playback bar to select a frame.
See Visualization for image export and live updates.
- Optimization for the other optimizers and for relaxing cells rather than just positions.
- Choosing a calculator to swap GFN2-xTB for DFT
or a machine-learned potential. Only the
atoms.calcline changes. - Molecular dynamics to move the atoms instead of minimizing them.
- ASE compatibility if you are porting a
script, including the
import atomli as asedrop-in style.
Import from the public atomli modules. The compiled atomli._core is an
implementation detail and its surface is not stable.