atombatch 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. atombatch-0.1.1/.github/workflows/publish.yml +40 -0
  2. atombatch-0.1.1/.github/workflows/tests.yml +34 -0
  3. atombatch-0.1.1/.gitignore +9 -0
  4. atombatch-0.1.1/AGENTS.md +43 -0
  5. atombatch-0.1.1/CHANGELOG.md +19 -0
  6. atombatch-0.1.1/LICENSE +675 -0
  7. atombatch-0.1.1/PKG-INFO +124 -0
  8. atombatch-0.1.1/README.md +87 -0
  9. atombatch-0.1.1/benchmarks/README.md +16 -0
  10. atombatch-0.1.1/benchmarks/bench_batching.py +260 -0
  11. atombatch-0.1.1/benchmarks/results/mace-small-torchsim-cpu-m1max-active16.json +29 -0
  12. atombatch-0.1.1/benchmarks/results/mace-small-torchsim-cpu-m1max.json +71 -0
  13. atombatch-0.1.1/benchmarks/results/symmetrix-cpu-m1max.json +71 -0
  14. atombatch-0.1.1/benchmarks/results/symmetrix-metal-m1max.json +71 -0
  15. atombatch-0.1.1/docs/_static/logo.svg +12 -0
  16. atombatch-0.1.1/docs/api.rst +55 -0
  17. atombatch-0.1.1/docs/conf.py +45 -0
  18. atombatch-0.1.1/docs/custom-tasks.md +77 -0
  19. atombatch-0.1.1/docs/design.md +40 -0
  20. atombatch-0.1.1/docs/index.md +47 -0
  21. atombatch-0.1.1/docs/installation.md +38 -0
  22. atombatch-0.1.1/docs/models.md +68 -0
  23. atombatch-0.1.1/docs/performance.md +64 -0
  24. atombatch-0.1.1/docs/quickstart.md +91 -0
  25. atombatch-0.1.1/docs/workflows.md +95 -0
  26. atombatch-0.1.1/pyproject.toml +48 -0
  27. atombatch-0.1.1/src/atombatch/__init__.py +40 -0
  28. atombatch-0.1.1/src/atombatch/backends.py +178 -0
  29. atombatch-0.1.1/src/atombatch/scheduler.py +296 -0
  30. atombatch-0.1.1/src/atombatch/symmetrix.py +265 -0
  31. atombatch-0.1.1/src/atombatch/tasks.py +303 -0
  32. atombatch-0.1.1/tests/test_import.py +7 -0
  33. atombatch-0.1.1/tests/test_mace_backend.py +90 -0
  34. atombatch-0.1.1/tests/test_scheduler.py +289 -0
  35. atombatch-0.1.1/tests/test_symmetrix_backend.py +124 -0
  36. atombatch-0.1.1/tests/test_torch_sim_backend.py +130 -0
  37. atombatch-0.1.1/tests/test_units.py +486 -0
  38. atombatch-0.1.1/tests/test_workflows.py +250 -0
@@ -0,0 +1,40 @@
1
+ name: publish
2
+
3
+ # Publishes to PyPI when a GitHub release is published, using PyPI trusted
4
+ # publishing (no stored token). The PyPI project must list this repository,
5
+ # this workflow file, and the "pypi" environment as a trusted publisher.
6
+
7
+ on:
8
+ release:
9
+ types: [published]
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v6
17
+ with:
18
+ python-version: "3.12"
19
+ - name: Check that the tag matches the package version
20
+ run: |
21
+ version=$(uv run --no-project python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
22
+ test "v${version}" = "${GITHUB_REF_NAME}"
23
+ - run: uv build
24
+ - uses: actions/upload-artifact@v4
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ publish:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment: pypi
33
+ permissions:
34
+ id-token: write
35
+ steps:
36
+ - uses: actions/download-artifact@v4
37
+ with:
38
+ name: dist
39
+ path: dist/
40
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,34 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.10", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v6
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ activate-environment: true
21
+ - run: uv pip install -e ".[test,phonons]"
22
+ - run: uvx ruff check src tests benchmarks
23
+ - run: pytest -q
24
+
25
+ docs:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - uses: astral-sh/setup-uv@v6
30
+ with:
31
+ python-version: "3.12"
32
+ activate-environment: true
33
+ - run: uv pip install -e ".[docs]"
34
+ - run: sphinx-build -W docs docs/_build/html
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ docs/_build/
@@ -0,0 +1,43 @@
1
+ # AGENTS.md
2
+
3
+ Guidance for coding agents working in this repository. Read `README.md` for the user-facing description and `docs/design.md` for the design decisions behind the code.
4
+
5
+ ## Project
6
+
7
+ atombatch batches the energy and force requests of many independent ASE tasks (single points, relaxations, NEB, molecular dynamics) into one model call per model. The ASE optimizers and integrators run unmodified, and every task receives exactly the result it would get from an independent run. Preserving that equivalence is the central invariant of the project.
8
+
9
+ ## Layout
10
+
11
+ - `src/atombatch/scheduler.py`: `Scheduler`, `BatchCalculator`, `TaskContext`, `TaskResult`. Each task runs in its own worker thread. `BatchCalculator.calculate` submits a request and blocks. The main thread waits until every active task is blocked or finished, then `_serve` groups requests by `(model, needs stress)`, splits them into chunks under the backend's `max_atoms`, evaluates each chunk, and wakes the tasks. Finished tasks are replaced from the queue by `_admit`, bounded by `max_active`.
12
+ - `src/atombatch/backends.py`: `Backend` interface (`evaluate(structures, properties) -> list[dict]`), `SequentialBackend` for any ASE calculator, `SymmetrixBackend`, which uses `Symmetrix.calculate_batch` when the installed Symmetrix has it and otherwise the graph batching in `src/atombatch/symmetrix.py` (adapted from Symmetrix-XL, MIT, and limited to evaluator calls present in Symmetrix-XL 0.1.1), `TorchSimBackend` wrapping a TorchSim `ModelInterface` (MACE, fairchem, SevenNet, ORB, MatterSim, NequIP, Nequix, metatomic), and `FunctionBackend` for a user function with the `evaluate` signature. `as_backend` picks the backend by type and duck typing. It recognizes TorchSim models only when `torch_sim` is already imported, so ASE-only runs never import torch.
13
+ - `src/atombatch/tasks.py`: task factories `single_point`, `relax`, `neb`, `molecular_dynamics`, and the batched workflows `displacement_forces` (phonopy and phono3py), `equation_of_state`, and `swap_monte_carlo`. Each returns a closure `task(context)` that copies its input structures and runs plain ASE code with calculators from the context. Workflows with independent evaluations submit them together through `TaskContext.evaluate`.
14
+ - `tests/test_units.py`: fast unit tests of chunking, backend selection (with a fake `torch_sim` module), result splitting, calculator caching, linked calculators, error paths, and Monte Carlo proposals. They use small fake backends and run in under a second.
15
+ - `tests/test_scheduler.py`: tests against EMT, which needs no MLIP. `tests/test_workflows.py` covers `context.evaluate` and the batched workflows (phonopy and phono3py tests are skipped when those packages are absent). `tests/test_torch_sim_backend.py` uses TorchSim's Lennard-Jones model and is skipped when TorchSim is not installed. `tests/test_mace_backend.py` compares batched MACE through TorchSim with MACE's own ASE calculator and runs only when `ATOMBATCH_MACE_MODEL` names a MACE-MP model (for example `small`) and `mace-torch` is installed. `tests/test_symmetrix_backend.py` is skipped unless `ATOMBATCH_SYMMETRIX_MODEL` points to a Symmetrix JSON model and the installed Symmetrix provides `calculate_batch`.
16
+
17
+ ## Development
18
+
19
+ ```bash
20
+ uv venv && source .venv/bin/activate
21
+ uv pip install -e ".[test]" # add ,torchsim on Python 3.12+ for the TorchSim tests
22
+ pytest
23
+ ```
24
+
25
+ Python 3.10 or later, with `numpy` and `ase>=3.23` as the only runtime dependencies. Symmetrix (`.[symmetrix]`) and TorchSim (`.[torchsim]`, Python 3.12 or later) are optional extras and must stay optional: import them inside the backend, never at module level. Ruff is configured with line length 88 in `pyproject.toml`, and existing `noqa` comments carry the reason in parentheses. Follow that convention.
26
+
27
+ ## Documentation
28
+
29
+ Sphinx with the Furo theme and MyST Markdown, in `docs/` (`conf.py`, guide pages in Markdown, `api.rst` for autodoc). `docs/design.md` is part of the site. Build with `sphinx-build -W docs docs/_build/html`, which must pass without warnings. Code examples in `index.md`, `quickstart.md`, `workflows.md`, and `custom-tasks.md` use EMT so that they run without an MLIP. Run them after changing the API, and keep any printed output quoted in the pages in sync. Docstrings use Sphinx roles (`:class:`, `:meth:`) and double-backtick literals. The logo is `docs/_static/logo.svg`, a flat 3x3 grid of atoms in indigo tones with one amber atom.
30
+
31
+ ## Conventions
32
+
33
+ - Validate every new task type or scheduling change by comparing with an independent ASE run of the same algorithm on EMT: identical step counts and convergence, and positions, energies, and forces equal within `atol=1e-9` (see `assert_same` in `tests/test_scheduler.py`). The tolerance is nonzero only because EMT reuses its neighbor list in an independent run.
34
+ - A request must be evaluated at exactly the state the task asked for. `_evaluate` copies `atoms` at submission time, so later mutation by the task cannot leak into the batch.
35
+ - A workflow whose evaluations do not depend on each other must submit them through `context.evaluate` in one request rather than one at a time, otherwise it contributes one structure per round.
36
+ - Tasks that query several structures in turn, such as an NEB band, use `TaskContext.linked_calculators` so that one request covers every stale member of the group. Tasks that read stress (cell filters) pass `properties` including `"stress"` so that each state is evaluated once.
37
+ - Exceptions raised in a task are captured in its `TaskResult.error` and do not stop other tasks. A backend failure is raised in every task of the failing chunk.
38
+ - New MLIP backends are added one at a time, each validated against that model's own ASE calculator. A backend returns one dict per structure with `energy`, `forces`, and `stress` in ASE Voigt order when requested.
39
+ - Public API changes must be reflected in `src/atombatch/__init__.py` (`__all__`), the README example, and `docs/design.md` where the design changes.
40
+
41
+ ## Status
42
+
43
+ Early development (version 0.1.1). The version is set in both `pyproject.toml` and `src/atombatch/__init__.py`, and `CHANGELOG.md` records each release. Correctness is tested. `benchmarks/bench_batching.py` measures model throughput against batch size and end-to-end relaxations against a sequential ASE loop, and its results are quoted in `docs/performance.md` with the JSON in `benchmarks/results/`. When quoting new numbers, state the hardware, model, precision, structure size, and `max_active`, and repeat CPU runs, which vary by about 20 %.
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## 0.1.1 (2026-10-15)
4
+
5
+ - The `symmetrix` extra installs matscipy. Without it, Symmetrix uses ASE's Python neighbor list, and batched relaxations with the `metal-preview-1` wheel ran three times slower than a sequential loop. atombatch now warns when Symmetrix has fallen back to the ASE neighbor list.
6
+ - Tested with the `metal-preview-1` Symmetrix-XL wheels (Metal, no `calculate_batch`): batched results match the Symmetrix calculator, and 64 FIRE relaxations ran 2.0 times faster than a sequential loop with identical step counts.
7
+ - Releases are published to PyPI from GitHub Actions with trusted publishing.
8
+
9
+ ## 0.1.0 (2026-10-15)
10
+
11
+ First public release.
12
+
13
+ - Scheduler that runs unmodified ASE tasks in worker threads and evaluates their pending energy and force requests in one batched call per model, with refill from a queue (`max_active`) and a per-model atom budget (`max_atoms`).
14
+ - Tasks: single points, relaxations with any ASE optimizer and cell filter, NEB (regular and climbing image), and molecular dynamics with any ASE integrator.
15
+ - Batched workflows: `TaskContext.evaluate` for independent structures, force sets for phonopy and phono3py (`displacement_forces`), equations of state (`equation_of_state`), and swap Monte Carlo with replica exchange (`swap_monte_carlo`).
16
+ - Backends: Symmetrix-XL from 0.1.1 (native `calculate_batch` when available, otherwise one joined neighbor graph per call), TorchSim models (MACE, fairchem, SevenNet, ORB, MatterSim, NequIP, Nequix, metatomic), user functions, and any ASE calculator evaluated sequentially.
17
+ - Results agree with independent ASE runs and with the models' own ASE calculators to rounding.
18
+ - Benchmarks: on an Apple M1 Max GPU with Symmetrix, 6.2 times higher model throughput at 64 structures per call and 3.0 times faster FIRE relaxations than a sequential ASE loop.
19
+ - Documentation (Sphinx), unit and integration tests, and a benchmark script.