xtb¶
xtb: the semiempirical GFN-xTB, GFN-FF, and g-xTB program, run on the command line.
The codec writes structure.xyz and runs::
xtb structure.xyz --<runtype> --chrg <charge> --uhf <unpaired> <method flags> <keywords>
model.method selects the Hamiltonian: gfn0, gfn1, gfn2, gfnff, or
gxtb. g-xTB needs the xtb build distributed with g-xTB
(https://github.com/grimme-lab/g-xtb); point qccompute at it with
executables={"xtb": ...} or QCCOMPUTE_XTB_EXECUTABLE. GFN0 reads its parameter
file from the directory named by XTBPATH.
Keywords become command-line flags in xtb's own spelling: {"alpb": "water"} gives
--alpb water, {"etemp": 1000} gives --etemp 1000, a list gives several
values ({"alpb": ["water", "bar1M"]}), True gives a bare flag, and False or
None leaves the flag out. For optimizations, {"opt": "tight"} sets the
optimization level. Detailed input ($constrain, $fix, $wall, ...) goes in
an xcontrol file supplied through files and named with {"input":
"xcontrol"}; such files are passed through verbatim, so atom indices in them are
1-based as xtb expects.
Examples¶
Each script runs as written. Copy it, delete the options you don't need, and run it
with python script.py. They live in the repository's
examples/ folder.
Single point: energy, gradient, Hessian¶
"""xtb single point: energy, gradient, or Hessian with GFN-xTB, GFN-FF, or g-xTB.
Requires: ``pip install qccompute`` (it installs qccodec) and xtb on PATH, e.g.
``conda install -c conda-forge xtb``. For g-xTB (``method="gxtb"``) use the xtb build
from https://github.com/grimme-lab/g-xtb instead; it also runs every other method.
GFN0-xTB reads its parameter file from the directory named by ``XTBPATH``.
How the codec talks to xtb (https://xtb-docs.readthedocs.io/):
- ``model.method`` picks the Hamiltonian: "gfn0", "gfn1", "gfn2", "gfnff", or "gxtb".
There is no basis set.
- Charge and multiplicity come from ``structure`` (passed as ``--chrg`` and ``--uhf``).
- ``keywords`` become xtb command-line flags (``xtb --help``): ``{"alpb": "water"}``
gives ``--alpb water``, ``True`` gives a bare flag, and ``False``/``None`` drop it.
Flags the codec sets itself (``chrg``, ``uhf``, ``gfn``, ``sp``, ``hess``, ...)
are rejected.
- xtb only warns about options it does not know and runs without them; the codec
turns that warning into a failure, so a typo never silently changes the method.
- Detailed settings (``$scc``, ``$wall``, ``$constrain``, ...) go in an xcontrol file
(``man 7 xcontrol``); see the commented example below. Atom indices in it are
1-based, as xtb expects.
- g-xTB has no ALPB/GBSA parameters (xtb stops with "No ALPB/GBSA parameters found")
and xtb 6.7.1 silently ignores ``cpcmx`` with g-xTB, so run g-xTB in the gas phase.
- xtb's Hessian is numerical (finite differences of analytic gradients) and comes
with harmonic frequencies and normal modes. Do not pass ``cma``: it moves the
molecule to its principal axes, so results would not match ``structure``.
"""
from qccompute import compute
from qcdata import CalcType, Model, ProgramInput, Structure
calctype = CalcType.gradient # or CalcType.energy, CalcType.hessian
# Coordinates are in bohr (Structure.from_xyz / Structure.open read angstrom files).
structure = Structure(
symbols=["O", "H", "H"],
geometry=[[0.0, 0.0, 0.0], [0.524, 1.687, 0.48], [1.146, -0.45, -1.354]],
charge=0,
multiplicity=1, # open shells: xtb gets multiplicity - 1 unpaired electrons
)
prog_input = ProgramInput(
program="xtb",
calctype=calctype,
structure=structure,
model=Model(method="gfn2"), # or "gfn1", "gfn0", "gfnff", "gxtb" (g-xTB build)
keywords={
# Any xtb command-line flag, without the leading dashes:
"parallel": 1, # threads
"acc": 1.0, # SCC accuracy; lower is tighter (0.0001 to 1000)
"iterations": 250, # maximum SCC iterations
# "etemp": 300, # electronic temperature (K); raise it for difficult SCCs
#
# Implicit solvent; pick one model (GFN1/GFN2/GFN-FF only, not g-xTB):
"alpb": "water", # ALPB; ["water", "bar1M"] also sets the reference state
# "gbsa": "h2o", # GBSA (its own solvent names)
# "cpcmx": "water", # CPCM-X
#
# Extra output, found in the logs or with collect_files=True:
# "molden": True, # orbitals in molden.input
# "wbo": True, # Wiberg bond orders in wbo
# "json": True, # xtbout.json
#
# Detailed settings from an xcontrol file (pass it in `files` below):
# "input": "xcontrol",
},
# files={"xcontrol": "$scc\n temp=500\n$end\n"},
)
output = compute(
prog_input,
# timeout=600, # seconds before xtb is killed
# collect_files=True, # keep every output file in output.results.files
# executables={"xtb": "/path/to/g-xtb/bin/xtb"}, # or QCCOMPUTE_XTB_EXECUTABLE
)
results = output.results
print("Energy (Hartree):", results.energy)
if results.gradient is not None:
print("Gradient (Hartree/bohr):\n", results.gradient)
if results.hessian is not None:
print("Frequencies (cm^-1):", results.freqs_wavenumber)
print("Normal modes (modes, atoms, xyz):", results.normal_modes_cartesian.shape)
print("Partial charges:", results.atomic_charges)
print("xtb version:", results.provenance.program_version)
Optimization¶
"""xtb geometry optimization with its built-in optimizer, ANCopt.
Requires: ``pip install qccompute`` (it installs qccodec) and xtb on PATH, e.g.
``conda install -c conda-forge xtb`` (or the g-xTB build of xtb for ``method="gxtb"``,
https://github.com/grimme-lab/g-xtb).
Notes for xtb optimizations (https://xtb-docs.readthedocs.io/en/latest/optimization.html):
- ``{"opt": "tight"}`` sets the convergence level: "crude", "sloppy", "loose",
"normal" (default), "tight", "verytight", or "extreme". ``cycles`` caps the steps.
- xtb exits normally when it runs out of cycles; the codec reports that as a failure
("failed to converge geometry optimization").
- Each step in ``results.trajectory`` has its structure and energy but no gradient:
xtb's log records only those.
- Constraints go in an xcontrol file (``$fix``, ``$constrain``, ``$wall``; see
https://xtb-docs.readthedocs.io/en/latest/xcontrol.html). Its atom indices are
1-based, unlike the 0-based indices used elsewhere in qcdata.
- Other keywords become xtb command-line flags, as in single_point.py: solvent,
accuracy, electronic temperature, threads.
- For transition states, or an optimizer that records gradients at every step, drive
xtb gradients with geomeTRIC (examples/geometric/).
"""
from qccompute import compute
from qcdata import CalcType, Model, ProgramInput, Structure
# Coordinates are in bohr.
structure = Structure(
symbols=["O", "H", "H"],
geometry=[[0.0, 0.0, 0.0], [0.524, 1.687, 0.48], [1.146, -0.45, -1.354]],
charge=0,
multiplicity=1,
)
prog_input = ProgramInput(
program="xtb",
calctype=CalcType.optimization,
structure=structure,
model=Model(method="gfn2"), # or "gfn1", "gfnff", "gxtb" (g-xTB build)
keywords={
# ANCopt settings:
"opt": "tight", # convergence level
"cycles": 100, # maximum optimization steps
#
"parallel": 1, # threads
"alpb": "water", # implicit solvent; or "gbsa": "h2o"
# "etemp": 300, # electronic temperature (K)
#
# Constraints from an xcontrol file (pass it in `files` below):
# "input": "xcontrol",
},
# Keep the first O-H bond at its starting length and freeze the oxygen atom.
# xcontrol atom indices are 1-based: atom 1 is structure.symbols[0].
# files={
# "xcontrol": (
# "$constrain\n"
# " force constant=1.0\n"
# " distance: 1, 2, auto\n"
# "$fix\n"
# " atoms: 1\n"
# "$end\n"
# )
# },
)
output = compute(
prog_input,
# timeout=600, # seconds before xtb is killed
# collect_files=True, # keep every output file (xtbopt.xyz, ...) in results.files
# executables={"xtb": "/path/to/xtb"}, # or QCCOMPUTE_XTB_EXECUTABLE
)
results = output.results
print("Steps:", len(results.trajectory))
print("Energies (Hartree):", results.energies)
print("Final structure (bohr):\n", results.final_structure.geometry)
# Save the trajectory, e.g. to view in a molecule viewer:
# results.save("optimization.json"); results.final_structure.save("final.xyz")