Metadata-Version: 2.5
Name: faster-diffbloch
Version: 0.1.6
Summary: Drop-in Metal GPU (macOS) and optimized CPU (macOS/Linux) acceleration for diffBloch
Project-URL: Homepage, https://godofecht.github.io/diffFlow/
Project-URL: Documentation, https://godofecht.github.io/diffFlow/
Project-URL: Repository, https://github.com/godofecht/diffFlow
Project-URL: Issues, https://github.com/godofecht/diffFlow/issues
Project-URL: PyPI, https://pypi.org/project/faster-diffbloch/
Project-URL: piwheels, https://www.piwheels.org/project/faster-diffbloch/
Project-URL: Original diffBloch, https://diffbloch.com
Author-email: Abhishek Shivakumar <abhishek.shivakumar@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: Metal GPU,PyTorch acceleration,diffBloch,electron crystallography,electron diffraction,structure refinement
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Requires-Dist: torch>=2.0
Provides-Extra: diffbloch
Requires-Dist: diffbloch; extra == 'diffbloch'
Description-Content-Type: text/markdown

# faster-diffbloch

Drop-in Apple Silicon Metal GPU and optimized CPU acceleration for [diffBloch](https://diffbloch.com) electron crystallography structure refinement.

**2.59x faster than PyTorch** on the forward-plus-backward pass at 579 beams, through the Metal path on Apple Silicon. An optimized CPU path covers macOS and Linux.

| Package | Documentation | Source repository | Original project |
| :--- | :--- | :--- | :--- |
| [PyPI](https://pypi.org/project/faster-diffbloch/) · [piwheels](https://www.piwheels.org/project/faster-diffbloch/) | [diffFlow documentation and benchmarks](https://godofecht.github.io/diffFlow/) | [github.com/godofecht/diffFlow](https://github.com/godofecht/diffFlow) | [diffbloch.com](https://diffbloch.com) |

---

## Operating System and Platform Support

| Operating System / Hardware | CPU Acceleration (`device="cpu"`) | GPU Acceleration (`device="gpu"`) | Backend Runtime |
| :--- | :---: | :---: | :--- |
| **macOS Apple Silicon (M1/M2/M3/M4/Max/Ultra)** | **Supported** | **Supported** | Native Metal Compute Shaders + Apple Accelerate BLAS |
| **macOS Intel (x86_64)** | **Supported** | Fallback to CPU | Apple Accelerate BLAS |
| **Linux (x86_64 / aarch64)** | **Supported** | Fallback to CPU | OpenBLAS / C11 BLAS |
| **Windows** | PyTorch Reference | PyTorch Reference | Pure PyTorch Reference Fallback |

Runtime platform guards automatically detect your operating system and hardware configuration. When `device="gpu"` is requested on Linux, `faster-diffbloch` automatically selects the optimized CPU backend with an informative warning.

---

## Why faster-diffBloch?

`faster-diffbloch` keeps the diffBloch workflow and public API intact while moving
the expensive propagation and gradient work onto an accelerated native backend.
You get the same scientific calculation, with a faster path on supported hardware
and a safe PyTorch fallback when the native backend is unavailable.

The package is validated against diffBloch's own test suite. With acceleration
enabled it passes all 738 diffBloch tests and 55 conformance tests that compare
the accelerated results against diffBloch's, field by field, including gradients.
The diffBloch run makes 4855 calls into the native matrix exponential, so the
accelerated path is exercised rather than skipped.

It also reproduces the published quartz result. Running `diffbloch-fast infer`
over the 99-rotation Colmey et al. 2026 quartz dataset through the Metal path
scores every rotation and gives a mean R_obs of 0.0485, against the 0.0486 the
example documents.

---

## Performance

Forward-plus-backward timing on an Apple M4 Max, single-threaded PyTorch, over
the same diffBloch quartz workload at five beam counts. Both device paths, best
of three runs each.

| Beams | PyTorch | CPU path | Metal path | CPU | Metal |
| :---: | :---: | :---: | :---: | :---: | :---: |
| 31 | 1.52 ms | 1.42 ms | 1.95 ms | 1.07x | 0.78x |
| 61 | 2.11 ms | 2.07 ms | 2.20 ms | 1.02x | 0.96x |
| 91 | 3.87 ms | 3.61 ms | 3.70 ms | 1.07x | 1.05x |
| 163 | 10.46 ms | 8.60 ms | 6.27 ms | 1.22x | 1.67x |
| 579 | 123.30 ms | 89.17 ms | 47.63 ms | 1.38x | **2.59x** |

The speedup grows with beam count, and this is the shape of the result rather
than noise. The package replaces the matrix exponential, which costs O(N^3),
while structure factors and the loss stay in PyTorch. As the system grows the
exponential takes a larger share of the runtime, so there is more for the
accelerated path to reach.

That has two practical consequences. At 579 beams, CsPbBr3 scale, Metal runs the
forward-plus-backward pass in 47.63 ms against PyTorch's 123.30 ms. Below about
91 beams Metal is slower than PyTorch, because the dispatch cost outweighs a
small exponential, so `enable(device="cpu")` is the better choice for small
systems.

Forward pass alone at 579 beams: PyTorch 25.90 ms, Metal 15.58 ms, a factor of
1.66. PyTorch MPS has no native kernel for `aten::linalg_matrix_exp` and falls
back to the CPU with host transfers, which is the gap this closes.

### The standalone Flow port

The diffFlow repository also holds a standalone port of the whole calculation,
compiled from Flow rather than bridged into PyTorch. It avoids the framework
overhead and goes further. At 579 beams, forward plus backward, minimum of five
runs:

| Implementation | Forward + Backward |
| :--- | :---: |
| PyTorch | 117.21 ms |
| Mojo port | 85.52 ms |
| Flow port, C backend | 82.84 ms |
| Flow port, MLIR backend | 79.74 ms |

Running the port directly is how those are reached. See the
[diffFlow documentation](https://godofecht.github.io/diffFlow/).

These figures come from one workload on one machine. Other crystals, hardware
configurations and beam counts will differ.

---

## Installation

```bash
pip install faster-diffbloch
```

---

## Usage

### 1. Drop-in CLI

Use `diffbloch-fast` or `faster-diffbloch` anywhere you would use `diffbloch`:

```bash
diffbloch-fast infer examples/Colmey_et_al_2026/data/quartz-no-abs
diffbloch-fast refine examples/Colmey_et_al_2026/data/quartz-no-abs
```

### 2. Python API Injection

Enable acceleration inside any existing diffBloch script:

```python
import faster_diffbloch

# Enable Metal GPU acceleration (macOS Apple Silicon)
faster_diffbloch.enable(device="gpu")

# Or CPU acceleration (macOS and Linux)
faster_diffbloch.enable(device="cpu")

# Run standard diffBloch code
import diffBloch
# All propagate and matrix_exp calls now route through faster-diffBloch
```
