feat: add hyper-xtb NN-xTB back-end (hyper-crest)#1
Open
Conversation
New back-end `nnxtb` calls hyper-xtb's hxtb_nnxtb_* C API (persistent engine = MACE weights loaded once per crest invocation) via a Fortran iso_c_binding wrapper. Architecture mirrors the existing tblite_api plumbing so the rest of CREST (optimizer, metadynamics, CREGEN, etc.) sees it as just another engine. - src/calculator/hyperxtb_api.F90: new module. hyperxtb_data owns the HxtbNNxtbEngine* and the MACE model path. hyperxtb_setup is called on the first energy/gradient request; hyperxtb_singlepoint is the per-frame dispatch (flattens mol%xyz/at → zs+xyz buffers, calls hxtb_nnxtb_compute, unflattens grad). - src/calculator/api_engrad.f90: hyperxtb_engrad — same loadnew/OMP critical pattern as tblite_engrad. - src/calculator/calculator.F90: new jobtype%hyperxtb case in the per-calculation dispatch switch. - src/calculator/calc_type.f90: jobtype enum + jobdescription entry, hyperxtb / hyperxtb_model fields on calculation_settings, deallocate paths, and create_calclevel_shortcut aliases (nnxtb, hyperxtb). - src/parsing/parse_calcdata.f90: method=nnxtb|hyperxtb accepted in TOML; mace_model/hyperxtb_model/nnxtb_model key sets the .mxtb path. - CMakeLists.txt + config/CMakeLists.txt: WITH_HYPERXTB option (default OFF). When ON, requires -DHYPERXTB_ROOT and -DHYPER_MACE_ROOT; builds an hyperxtb::hyperxtb INTERFACE target carrying include/libs and defines WITH_HYPERXTB so the Fortran source compiles with the real bindings (stub error-stops otherwise). - docs/hyper_crest.md: build + usage walkthrough. Default build (WITH_HYPERXTB=OFF) is unchanged.
5 tasks
Downstream libcrest (static + shared) and the crest-exe target were failing to link with undefined references to cudaMalloc / cudaFree / cudaStreamCreate / mace_xtb_compute_cuda when hyper-xtb was built against a CUDA hyper-mace, because libhyperxtb_core.a now carries GPU code from the new src/nnxtb_capi_cuda.cu TU (via hyper-xtb#2/feat/nnxtb-capi). Probe for libmace_cuda alongside libmace, pull in CUDA::cudart when present, and wrap the three static archives plus -lgomp/-lpthread in a --start-group/--end-group so the symbol ordering is stable regardless of which sub-archive the linker walks first.
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.
Summary
Adds
nnxtbas a first-class CREST back-end, powered by the hyper-xtb NN-xTBC API (hxtb_nnxtb_*) landing in talo/hyper-xtb#2.
Goal: CREST-speed conformer sampling at DFT-level accuracy by swapping the
underlying GFN2-xTB engine for the MACE-corrected one in hyper-xtb.
The MACE weights are loaded exactly once per `crest` invocation — a
persistent `HxtbNNxtbEngine*` lives on `calculation_settings%hyperxtb`
for the duration of the sampling run and is reused by every conformer
energy/gradient call, matching the NN-xTB deployment constraint.
What's in here
Architecturally this mirrors the existing `tblite_api` plumbing so the rest
of CREST (ancopt, metadynamics, CREGEN, ensemble ops) treats it as just
another engine — no downstream changes needed.
engine handle and MACE model path. `hyperxtb_setup` calls
`hxtb_nnxtb_init` (loads MACE weights). `hyperxtb_singlepoint` flattens
`coord%xyz`/`coord%at` into the C API's Z/xyz arrays, calls
`hxtb_nnxtb_compute`, unflattens the gradient. `hyperxtb_cleanup` frees
the engine. All wrapped in `#ifdef WITH_HYPERXTB` so the stub compiles
without the hyper-xtb headers.
critical pattern as `tblite_engrad`.
`hyperxtb` / `hyperxtb_model` fields on `calculation_settings`,
deallocate paths (cleans up C engine before freeing), and
`create_calclevel_shortcut` aliases.
and `mace_model = "/path/to/model.mxtb"` in TOML input.
(default OFF). When ON, requires `-DHYPERXTB_ROOT` and
`-DHYPER_MACE_ROOT` pointing at built trees; builds an
`hyperxtb::hyperxtb` INTERFACE target carrying include + libs.
Test plan
default CREST build identical (byte-level, for anything except the
new srcs list) — the new `.F90` compiles its no-`#ifdef` stub path.
`bind(C, name=...)` interfaces present, no warnings).
against hyper-xtb#2 + hyper-mace xtb-implementation — target for
CI once we have a runner with GPUs + a .mxtb model file.
compared to standard `method = "gfn2"` — happens in the follow-up
benchmark PR (DFT rescore of top conformers from both).
Dependencies
This PR only compiles in the NN-xTB path when paired with:
of that onto `gpu-nn-xtb-deltas`
Base branch is upstream `master`. We can rebase onto a hyper-crest main
branch if we cut one from `master`, but since this repo was just forked
for the NN-xTB work the two are identical right now.
Validation (RunPod A6000, 2026-04-18)
All four checklist items green. Built hyper-mace (xtb-implementation, PIC) + hyper-xtb (feat/nnxtb-capi, WITH_NNXTB=ON) + this branch (WITH_HYPERXTB=ON) end-to-end.
crest input.tomlwithmethod = "nnxtb"on water:Plumbing confirmed via
nm(5 new symbols resolved:hxtb_nnxtb_{init,compute,free}+__hyperxtb_api_MOD_hyperxtb_{setup,singlepoint}) and a fault-injection run with a bogus.mxtbthat produced a clean error trace all the way frommace_xtb_loadback up tocrest_main. Full benchmark numbers in PR #2.