Pure-Python in-memory interface to FHI-aims via ctypes, for seamless integration with DeepX/DeepH.
Project description
aimspy
In-memory Python interface to FHI-aims via ctypes, for seamless integration with DeepX/DeepH-pack.
AimSpy drives FHI-aims DFT calculations
directly from Python — no subprocess, no file-staged I/O on hot paths — by
loading a patched libaims.so via ctypes and exchanging matrices in memory
through a callback framework.
Status:
v0.2.0(alpha) — Calculator lifecycle, ctypes binding, callback framework, aimspy standard format, DeepH interface layer, unifiedmodify_init_ham()API (direct + deferred), forces export, and overlap capture are implemented and tested.
Features
- In-memory SCF — load
libaims.soonce, drive SCF from Python viactypes - MPI-transparent — works under
mpiexec; rank-0 vs. all-rank APIs documented - Warmstart — inject an external Hamiltonian (e.g. DeepH prediction) to converge SCF in 1 iteration
- Pluggable matrix sources —
ExternalMatrixSourceprotocol;DeepHDataships built-in - DeepH I/O — read/write DeepH format (
POSCAR+info.json+.h5) - Callback framework — 5 hook points (
get_descr,export_ovlp,export_h0,modify_h0,python_func) auto-wrapped to Python - Bundled FHI-aims patch —
aimspy patchCLI applies/reverses versioned diffs; no manual editing of the aims source tree
Installation
From PyPI
pip install aimspy
From source (editable, with dev deps)
git clone https://github.com/kYangLi/aimspy.git
cd aimspy
pip install -e ".[dev]"
Requires Python 3.12–3.14, numpy>=1.24, h5py>=3.0, mpi4py>=3.0, click>=8.0.
Patching FHI-aims
aimspy ships a bundled patch that adapts an FHI-aims source tree to expose
the in-memory interface. Apply it with the aimspy patch command:
cd /path/to/FHI-aims # clean checkout, e.g. on branch `dev`
aimspy patch # applies the latest bundled diff
Common variants:
aimspy patch -v v0.1.0 /path/to/FHI-aims # specific version
aimspy patch --check /path/to/FHI-aims # dry-run
aimspy patch --uninstall /path/to/FHI-aims # reverse the detected patch
aimspy patch --list # show bundled versions
Prerequisites: a clean FHI-aims checkout on the patch's base branch
(currently dev). The tree must be unpatched; applying on top of an
unrelated branch may fail. By default git apply is used on git repos,
falling back to patch -p1 otherwise (--no-git forces patch(1)).
Full CLI reference:
aimspy patch [SOURCE] [OPTIONS]
Arguments:
SOURCE FHI-aims source directory (default: current dir)
Options:
-v, --version TEXT Patch version to apply (default: latest)
-l, --list List bundled patches and exit
--check, --dry-run Dry-run only; do not modify the tree
--uninstall Reverse the currently-detected patch
--no-git Force patch(1) instead of git apply
-y, --yes Skip confirmation prompts
Quick start
Baseline SCF on a prepared work_dir (containing control.in + geometry.in):
from mpi4py import MPI
from aimspy import Calculator, CalculatorConfig
config = CalculatorConfig(lib_path="/path/to/libaims.so")
with Calculator(config) as calc:
calc.do(comm=MPI.COMM_WORLD, work_dir="./MoS2")
H = calc.hamiltonian # AimspyMatrix (block-sparse, Hartree)
E = calc.energy # float (Hartree)
Run with MPI:
mpiexec -np 8 python script.py
Usage
DeepH warmstart (1-iteration SCF)
Inject a pre-trained DeepH Hamiltonian as the initial guess:
from mpi4py import MPI
from aimspy import Calculator, CalculatorConfig, Strategy
from aimspy.interface.deeph import DeepHData
data = DeepHData.from_directory("deeph_warm/")
config = CalculatorConfig(lib_path="/path/to/libaims.so")
calc = Calculator(config)
calc.modify_init_ham(source=data, strategy=Strategy.REPLACE)
calc.do(comm=MPI.COMM_WORLD, work_dir="./MoS2")
Deferred source — generate the source at runtime (after H0/overlap are
available, inside the python_func callback):
config = CalculatorConfig(
lib_path="/path/to/libaims.so",
capture_initial_hamiltonian=True,
)
calc = Calculator(config)
@calc.modify_init_ham(strategy=Strategy.REPLACE, option={"deeph_path": "deeph_warm/"})
def gen_source(calculator, option):
# calculator.initial_hamiltonian / .overlap available here
return DeepHData.from_directory(option["deeph_path"])
calc.do(comm=MPI.COMM_WORLD, work_dir="./MoS2")
Other Strategy values: ADD (add external H to live H0), SCALE (scale
H0 by factor=), CUSTOM (user function via custom_fn=).
Export to DeepH format
from mpi4py import MPI
from aimspy import Calculator, CalculatorConfig
from aimspy.interface.deeph import DeepHData
config = CalculatorConfig(
lib_path="/path/to/libaims.so",
capture_initial_hamiltonian=True,
)
with Calculator(config) as calc:
calc.do(comm=MPI.COMM_WORLD, work_dir="./MoS2")
dd = DeepHData.from_aimspy(
calc.structure,
hamiltonian=calc.hamiltonian,
overlap=calc.overlap,
initial_hamiltonian=calc.initial_hamiltonian,
)
dd.save("deeph_out/")
Error recovery
If SCF crashes, use force_close() (always safe, swallows Fortran errors)
and create a fresh Calculator:
calc = Calculator(CalculatorConfig(lib_path="..."))
try:
calc.do(comm=MPI.COMM_WORLD, work_dir="./bad_input")
except Exception:
calc.force_close()
# create a new Calculator for the next run
API overview
Calculator — main class
| Method / Property | Description |
|---|---|
do(comm, work_dir) |
One-shot: init() + calc(). Common entry point. |
init(comm, work_dir) |
Load libaims, call aimspy_init, wire callbacks. |
calc() |
Run SCF. Raises AimspyCallbackError on callback failure. |
close() / force_close() |
Finalize (graceful / forced from any state). |
modify_init_ham(source, *, strategy, factor, custom_fn, option) |
Configure H0 modification (direct or deferred). |
register_callback(name, fn, aux, extra_ptr) |
Register custom callback. |
info, structure |
Runtime snapshot (all ranks). |
energy, forces |
SCF results (all ranks; Hartree / eV·Å⁻¹). |
hamiltonian, overlap, initial_hamiltonian |
AimspyMatrix (rank 0; opt-in flags). |
rs_hamiltonian, rs_overlap |
Raw CSR flat arrays (rank 0). |
csr_descr, work_dir, comm |
Layout + execution context. |
CalculatorConfig
| Field | Type | Default | Description |
|---|---|---|---|
lib_path |
Path |
required | Path to patched libaims.so. |
control_path, geometry_path |
Path |
None |
Optional inputs to copy into work_dir. |
initializer |
callable |
None |
fn(Calculator) -> None on rank 0 before aimspy_init. |
log_level |
str |
"INFO" |
Python logging level. |
logfile |
Path |
aims.out |
aims log file name. |
capture_initial_hamiltonian |
bool |
False |
Enable export_h0 callback. |
capture_overlap |
bool |
False |
Enable export_ovlp callback (all-rank live overlap). |
Other public symbols
Strategy— enum:REPLACE,ADD,SCALE,CUSTOM.CallbackName— enum:GET_DESCR,EXPORT_OVLP,EXPORT_H0,MODIFY_H0,PYTHON_FUNC.AimspyMatrix— block-sparse matrix withblocksdict,from_aims_csr()/to_aims_csr()converters.AimspyStructure— structure + orbital descriptor (cachedphase_factor,basis_subidx,atom_permutation).ExternalMatrixSource—Protocolwithto_aimspy(structure).DeepHData— DeepH format reader/writer; seeaimspy.interface.deeph.
Development
make install # create .venv, install editable with dev deps
make test # run tests
make lint # ruff check + black --check
make build # build wheel
Environment variables
Integration tests and examples require AIMSPY_TEST_AIMS_LIBPATH to point
at your patched libaims.so:
export AIMSPY_TEST_AIMS_LIBPATH=/path/to/FHI-aims-deeph/build/libaims.so
Optional:
AIMSPY_TEST_NPROC— MPI process count fortests/test_strategies.py(default:8).
License
AimSpy is released under GPL-3.0-or-later (see LICENSE).
FHI-aims itself is not distributed with AimSpy and remains under its own licence agreement with the aims team. Users must obtain FHI-aims source code independently.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aimspy-0.2.0.tar.gz.
File metadata
- Download URL: aimspy-0.2.0.tar.gz
- Upload date:
- Size: 80.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46d946677b65634355771c9e87c0b60505f5d010165236685436e84f1c1b36cc
|
|
| MD5 |
eb7ad37882793abedb0efc68a67bb51a
|
|
| BLAKE2b-256 |
0359d73519f812616fd237cbc06049ef650c98a163c8ae5ac4a2300b949b38f6
|
Provenance
The following attestation bundles were made for aimspy-0.2.0.tar.gz:
Publisher:
publish.yaml on kYangLi/aimspy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aimspy-0.2.0.tar.gz -
Subject digest:
46d946677b65634355771c9e87c0b60505f5d010165236685436e84f1c1b36cc - Sigstore transparency entry: 2195656204
- Sigstore integration time:
-
Permalink:
kYangLi/aimspy@97335a8c5cc9f06035597445015f29123af618e8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kYangLi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@97335a8c5cc9f06035597445015f29123af618e8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file aimspy-0.2.0-py3-none-any.whl.
File metadata
- Download URL: aimspy-0.2.0-py3-none-any.whl
- Upload date:
- Size: 71.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c529db87f708e03997db2c9419c7295738ade465bed0cc26ee0dc967dbe9a04f
|
|
| MD5 |
784e5a4ce49d7aa9755dd9c85feefce9
|
|
| BLAKE2b-256 |
c73251cc1cd094ad39f7d6b34b52713a53d2d58fa818d91b63eac68f98655d24
|
Provenance
The following attestation bundles were made for aimspy-0.2.0-py3-none-any.whl:
Publisher:
publish.yaml on kYangLi/aimspy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aimspy-0.2.0-py3-none-any.whl -
Subject digest:
c529db87f708e03997db2c9419c7295738ade465bed0cc26ee0dc967dbe9a04f - Sigstore transparency entry: 2195656210
- Sigstore integration time:
-
Permalink:
kYangLi/aimspy@97335a8c5cc9f06035597445015f29123af618e8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kYangLi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@97335a8c5cc9f06035597445015f29123af618e8 -
Trigger Event:
release
-
Statement type: