Skip to main content

Pure-Python in-memory interface to FHI-aims via ctypes, for seamless integration with DeepX/DeepH.

Project description

aimspy

PyPI Version Python Versions License GitHub Issues GitHub Stars

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, unified modify_init_ham() API (direct + deferred), forces export, and overlap capture are implemented and tested.

Features

  • In-memory SCF — load libaims.so once, drive SCF from Python via ctypes
  • 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 sourcesExternalMatrixSource protocol; DeepHData ships 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 patchaimspy patch CLI 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 with blocks dict, from_aims_csr() / to_aims_csr() converters.
  • AimspyStructure — structure + orbital descriptor (cached phase_factor, basis_subidx, atom_permutation).
  • ExternalMatrixSourceProtocol with to_aimspy(structure).
  • DeepHData — DeepH format reader/writer; see aimspy.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 for tests/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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aimspy-0.2.0.tar.gz (80.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aimspy-0.2.0-py3-none-any.whl (71.1 kB view details)

Uploaded Python 3

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

Hashes for aimspy-0.2.0.tar.gz
Algorithm Hash digest
SHA256 46d946677b65634355771c9e87c0b60505f5d010165236685436e84f1c1b36cc
MD5 eb7ad37882793abedb0efc68a67bb51a
BLAKE2b-256 0359d73519f812616fd237cbc06049ef650c98a163c8ae5ac4a2300b949b38f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for aimspy-0.2.0.tar.gz:

Publisher: publish.yaml on kYangLi/aimspy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for aimspy-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c529db87f708e03997db2c9419c7295738ade465bed0cc26ee0dc967dbe9a04f
MD5 784e5a4ce49d7aa9755dd9c85feefce9
BLAKE2b-256 c73251cc1cd094ad39f7d6b34b52713a53d2d58fa818d91b63eac68f98655d24

See more details on using hashes here.

Provenance

The following attestation bundles were made for aimspy-0.2.0-py3-none-any.whl:

Publisher: publish.yaml on kYangLi/aimspy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page