Add a GFN-xTB engine (tblite) alongside DFTB+ - #68
Merged
Merged
Conversation
Add xTB as a second engine for the screening pipeline, running in-process through tblite (no external binary, no Slater-Koster files -- GFN-xTB parameters are built in for H-Rn). The geometry is optimised with an ASE optimiser and frequencies come from ASE's finite-difference vibrations, so the result feeds the existing thermochemistry exactly like the DFTB+ path. - calculator/xtb.py: `optimise_and_frequencies` (ASE optimiser + vibrations, returning energy in Hartree and sorted real frequencies in cm^-1) and `xtb_calculator` (a tblite GFN-xTB ASE calculator). tblite is imported lazily, so it is only required when the xTB engine is actually used. - thermo/api.py: `xtb_thermo`, mirroring `dftbplus_thermo`. Charge and the minimum-spin electron-count guess are passed through as xTB charge/unpaired electrons, so radicals run open-shell automatically. quasi-RRHO composes. - thermo/thermo.py: accept `engine="xtb"` (same Hartree/cm^-1 units as dftb+). - thermo/screening.py, cli/thermo.py: `screen(engine=..., method=...)` and `screen --engine xtb --method GFN2-xTB`; parameter-set/solvent stay DFTB+-only. Implicit solvation is not wired up: the tblite ASE calculator does not expose GBSA/ALPB, so xTB runs gas-phase for now. Validated against real GFN2-xTB: water gives S = 45.05 cal/mol/K (experiment ~45.1) and an OH radical runs open-shell.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #68 +/- ##
==========================================
+ Coverage 96.47% 96.57% +0.09%
==========================================
Files 22 23 +1
Lines 1419 1459 +40
==========================================
+ Hits 1369 1409 +40
Misses 50 50
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
galjos
added a commit
that referenced
this pull request
Jul 6, 2026
#70) Closes the gap the last two discussions surfaced: **neither prior xTB path can do open-shell + solvation together.** - The tblite in-process engine (#68) can't do solvation — tblite's ASE calculator exposes no ALPB/GBSA (its C-API has no solvation entry point). - Running xTB *through* DFTB+ can't do open-shell — spin-polarized xTB is a [known unresolved DFTB+ limitation](dftbplus/dftbplus#972). The **native `xtb` binary does all of it**, so this adds it as the `xtb-cli` engine — covering **charged radicals in solution** with method-consistent parameters. ## Usage ``` thermo screen mols/ --engine xtb-cli --solvent water # radical anions in solvent ``` ## What changed - **`calculator/xtb_cli.py`** (new) — runs `xtb --ohess --gfn <n> --chrg <c> --uhf <2S> [--alpb <solvent>]`, then parses the energy (`xtbopt.xyz`), optimised geometry, and frequencies (`vibspectrum`, wavenumber = 3rd-from-last token). The executable is found via `$XTB_COMMAND` or PATH; **nothing is imported from xtb**, so the package still imports without it. - **`thermo/api.py`** — `xtb_cli_thermo`, resolving the electron-count spin guess to `--uhf` (radicals open-shell automatically) and `solvent` → `--alpb`. - **`thermo/screening.py`, `cli/thermo.py`** — `screen(engine="xtb-cli")` / `--engine xtb-cli`; `solvent` now applies to both dftb+ and xtb-cli. ## Validation Real xtb 6.7.1: gas-phase water **S = 45.05 cal/mol/K** (experiment ~45.1); an OH radical runs **open-shell** and is stabilised by **~6.5 kcal/mol in water** (`--alpb`) — `ΔG_solv` on an open-shell radical, the exact case that motivated this. Energy/frequencies match the tblite path. Offline suite **223 passed / 6 skipped**; real DFTB+ + xtb integration **45 passed**. CI-safe tests cover parsing, command construction (mocked subprocess), dispatch, and the missing-binary error; a real end-to-end test runs when `xtb` is present and skips otherwise. Patch coverage verified **without** the xtb binary (0 uncovered). ## Dependency `xtb-cli` needs the native `xtb` binary (optional): `conda install -c conda-forge xtb`. Without it, the other engines work unchanged and the xtb-cli tests skip.
This was referenced Jul 6, 2026
galjos
added a commit
that referenced
this pull request
Jul 6, 2026
Follow-up to the xtb engines (#68, #70): `thermo doctor` only checked the DFTB+ toolchain. Now it also reports the xTB backends, so `doctor` reflects all three engines. ## What it reports - **`xtb`** — the native binary for `--engine xtb-cli` (resolved via `$XTB_COMMAND`, then PATH). - **`tblite`** — the Python package for `--engine xtb`. ``` dftb+ found /.../bin/dftb+ modes found /.../bin/modes DFTB_PREFIX found /.../3ob/skfiles C-C.skf found /.../3ob/skfiles/C-C.skf xtb found /.../xtbcli/bin/xtb tblite found importable ``` When missing, the detail line gives the fix: ``` xtb missing not found (set XTB_COMMAND or `conda install -c conda-forge xtb`; needed for --engine xtb-cli) (optional) tblite missing not importable (`conda install -c conda-forge tblite-python`; needed for --engine xtb) (optional) ``` ## Design: optional, so DFTB+-only users are unaffected - The xTB checks are marked `(optional)` and **do not change the doctor exit code** — it still fails only on a missing *required* DFTB+ backend (`dftb+`/`modes`/`DFTB_PREFIX`/`C-C.skf`). - `Diagnostic` gains an `optional` flag; `run_doctor` filters optional items from the pass/fail decision. This is a small step toward the "helpful doctor" idea — the detail now includes the exact `conda install` command for whatever's missing. ## Note This was originally committed onto the #70 branch, but #70 merged before its CI picked up the extra commit — so it's re-based here as its own PR off the current main. Offline suite: 252 passed / 11 skipped.
galjos
added a commit
that referenced
this pull request
Jul 6, 2026
`environment.yml` already installed DFTB+ but predates the xTB engines (#68, #70). Add the xTB backends so `conda env create -f environment.yml` provisions **every** calculation engine in one command. ```yaml dependencies: - python>=3.12 - dftbplus # DFTB+ engine: `dftb+` and `modes` - xtb # native xtb binary, for --engine xtb-cli - tblite-python # GFN-xTB via tblite, for --engine xtb - pip - pip: - "-e .[test,lint]" ``` After `conda env create -f environment.yml && conda activate thermoscreening`, `thermo doctor` reports every backend as found (pairs with #71). README updated to say the env covers all backends. Verified the three backends resolve on conda-forge (dftbplus-25.1 nompi, xtb-6.6.1, tblite-python-0.3.0); YAML validated. This is the "installable through the project" follow-up: the compiled backends (DFTB+/modes/xtb/tblite) can't be pip-installed, so the conda env is how the project bundles them, while `thermo setup-dftb` handles the Slater-Koster and GBSA parameter files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds xTB (GFN-xTB via tblite) as a second engine for the screening pipeline. It runs in-process — no external binary and no Slater-Koster files, since GFN-xTB parameters are built in for H–Rn.
Usage
(
parameter-set/solventapply only to--engine dftb+.)What changed
calculator/xtb.py(new) —optimise_and_frequencies(ASE optimiser + finite-difference vibrations → energy in Hartree + sorted real frequencies in cm⁻¹) andxtb_calculator(a tblite GFN-xTB ASE calculator). tblite is imported lazily, so it's only needed when the xTB engine is actually used — the package imports fine without it.thermo/api.py—xtb_thermo, mirroringdftbplus_thermo. Charge and the minimum-spin electron-count guess become xTB's charge / unpaired electrons (atoms.info), so radicals run open-shell automatically. quasi-RRHO composes.thermo/thermo.py— acceptengine="xtb"(same Hartree/cm⁻¹ units as dftb+).thermo/screening.py,cli/thermo.py—screen(engine=…, method=…)dispatch +--engine/--method.Frequency handling
ASE's
Vibrationsreturns3Ncomplex frequencies; imaginary modes are mapped to negative reals and the array is sorted ascending, soSystemkeeps the topdofreal vibrations (trans/rot and any imaginary modes drop out) — the same contract as the DFTB+modespath.Scope note
Solvation isn't wired up: the tblite ASE calculator doesn't expose GBSA/ALPB (the
alpb/gbsakwargs are silently ignored — energy unchanged), so xTB runs gas-phase. Adding it would need the lower-level tblite API; a clean follow-up.Validation
optimise_and_frequenciesis covered offline with ASE's built-in EMT (no tblite);xtb_thermo/dispatch are covered by mocked tests; a real GFN2 test runs when tblite is present and skips otherwise.Dependency
The xTB engine needs
tblite-python(optional):conda install -c conda-forge tblite-python. Without it, DFTB+ works unchanged and the xTB tests skip.