RDF-Rust
Partial and total radial distribution functions for crystal structures. Rust backend, Python API, native support for partially occupied sites.
- Fast — 144 ms on one thread (42 ms on four) for a 13,720-atom cell where matminer needs 14.3 s.
- Light — memory does not grow with the structure; under 1 MB at any size.
- Disorder-aware — a CIF with fractional occupancies is handled directly, with no supercell and no random seed.
Install
pip install rdf-rust
The distribution is rdf-rust; the import name is rdfrust.
From a checkout:
pip install maturin
maturin develop --release
Example
import rdfrust
s = rdfrust.read("BaSrTiO3.cif") # reports disorder on stderr
r, partials, total = s.prdf(cutoff=10.0, bin_size=0.1, n_threads=0)
partials[("Ba", "O")] # numpy array, g_BaO(r)
total # number-weighted total RDF
r # left edge of each bin
cutoff is the maximum pair length r_max in Å, bin_size the histogram width,
n_threads=0 means every core. A complete runnable script is in
examples/run_prdf.py:
python examples/run_prdf.py examples/BaSrTiO3_sym.cif
Elements are never specified
Every element pair is computed automatically. There is no element list to pass — RDF-Rust reads which elements are present and returns all of them. A five-element alloy gives 25 partials:
s = rdfrust.read("CoCrFeMnNi.cif")
_r, partials, _t = s.prdf(cutoff=6.0, bin_size=0.1)
len(partials) # 25 = 5 x 5, every ordered combination
sorted(partials)[:3] # [('Co','Co'), ('Co','Cr'), ('Co','Fe')]
Both (A, B) and (B, A) are present. g_AB counts neighbours of type B
around centres of type A, normalised by N_A, so the two are related by
N_A·g_AB = N_B·g_BA rather than being equal.
Speed
RDF-Rust on 1 thread (same as Matminer and Vesin) and on 4 threads:
| 1 thread | 4 threads |
|---|---|
| atoms | Matminer | Vesin | RDF-Rust, 1 thread | RDF-Rust, 4 threads |
|---|---|---|---|---|
| 320 | 313 ms / 77 MB | 15 ms / 10 MB | 6.3 ms | 1.8 ms |
| 2,560 | 2,840 ms / 592 MB | 47 ms / 93 MB | 25 ms | 6.6 ms |
| 13,720 | 14,322 ms / 3,178 MB | 276 ms / 454 MB | 144 ms | 42 ms |
RDF-Rust stays under 1 MB at every size, because pairs go straight from the cell list into a histogram and are never stored. On one thread it is 1.5–2.2× faster than Vesin; 4 threads add another 3.4–4.0×.
Ordered structures match matminer to 3.6 × 10⁻¹⁵ — double-precision noise — across cubic, hexagonal, triclinic, sheared and slab-like cells. The one exception is a lattice whose spacing is an exact multiple of the bin width (a = 3.600 Å with 0.1 Å bins), where distances sit on bin edges and a few ulp decide the bin; counts are conserved, only their split between two adjacent bins moves.
Numbers, per-structure-type results, thermal-disorder tests and every CSV behind these figures: BENCHMARKS.md.
Partial occupancies
Most RDF tools need an ordered structure, so a disordered CIF must first become a random supercell — which rounds the occupancies to whatever the cell allows and commits to one arrangement. RDF-Rust weights each pair by the product of its occupancies instead:
$$g_{AB}(r) = \frac{1}{N_A}\sum_{i \neq j} c_i^A c_j^B \frac{\delta(r - r_{ij})}{4\pi r^2 \Delta r}$$
That is the exact ensemble average over an ideally mixed lattice — no
supercell, no seed, no rounding — and it reduces to the ordinary counting
definition when every occupancy is 1, so ordered results match matminer bin for
bin. It is checked against the mean of hundreds of explicitly sampled random
supercells in tests/test_disorder_physics.py.
When you do want an explicit structure:
ordered, info = s.expand_occupancies(max_sites=4096, seed=42)
info["scale"], info["occupancy_report"], info["warnings"]
API
rdfrust.read(path, verbose=True, fmt=None) # -> Structure, reports disorder
rdfrust.from_pymatgen(pmg_structure)
rdfrust.available_threads()
on a Structure |
|
|---|---|
prdf(cutoff, bin_size, n_threads) |
(r, {(A,B): g_AB}, total) |
total_rdf(cutoff, bin_size, n_threads) |
(r, total) |
expand_occupancies(max_sites, seed) |
(ordered Structure, info) |
disorder_summary() |
per-site occupancies; [] when ordered |
make_supercell(a, b, c) |
|
n_sites, n_atoms, is_ordered, elements, composition, volume |
|
frac_coords, cart_coords, species, lattice_matrix |
Formats
| format | partial occupancies |
|---|---|
| CIF | yes |
| VASP POSCAR / CONTCAR | no (format cannot express them) |
extended XYZ (needs Lattice="...") |
no |
| anything else | via pymatgen or ASE, if installed |
CIF is the only one that carries fractional occupancies. Space groups must be given as an explicit symmetry-operation loop; a CIF naming only a Hermann–Mauguin symbol is read as P1.
Graphical interface
pip install "rdfrust[app]"
streamlit run app.py
Upload a CIF, set r_max, bin size, an optional supercell and the core count; see the structure summary, any partial occupancies, the curves, and the time and memory each run took.
Online (P)RDF app
prdf_app.py is the XRDlicious (P)RDF calculator, with RDF-Rust, Vesin and
Matminer as selectable backends. It runs on its own from this repository:
pip install -r requirements.txt
streamlit run prdf_app.py
requirements.txt is also what Streamlit Community Cloud reads when the app is
deployed from GitHub.
Tests
cargo test --lib # symmetry parsing
pytest tests/ -q # CIF, formats, neighbours, RDF, disorder physics
License
MIT
Metadata
Release files for rdf-rust 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rdf_rust-0.1.0.tar.gz | 66.0 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rdf_rust-0.1.0-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details |
| rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| rdf_rust-0.1.0-cp38-abi3-macosx_11_0_arm64.whl | CPython 3.8 | abi3 | macOS 11.0+ ARM64 | Details |
| rdf_rust-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl | CPython 3.8 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 2.0 MB
Release files / rdf_rust-0.1.0.tar.gz
| Download URL | rdf_rust-0.1.0.tar.gz |
|---|---|
| Size | 66.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9f021921aed6a9d1f9b99048caf38672cd2ab09c7f71e665521700ce36cd4ce9
|
|
BLAKE2b-256 checksum How to use checksums |
b5dc186345a6500f56b037dc5af80ae8c2746b8906901d39ad408990155ea680
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / rdf_rust-0.1.0-cp38-abi3-win_amd64.whl
| Download URL | rdf_rust-0.1.0-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 313.5 kB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
386dfbae0f6d0db96a7a78a1ca95800b58ca0a531dbb461857ad8908ea4e64a1
|
|
BLAKE2b-256 checksum How to use checksums |
c1de518158e38b2ef243fd47e40ba18de7982c7a4797f4aad4bfac0c99e696c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 434.1 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
a2e9c2447ef2202c2c3c4e5786843e4a8387a9a0da47fdbebda03cace6185d89
|
|
BLAKE2b-256 checksum How to use checksums |
4a11f4ad2cccc6aa85e62892cf0bdea314257b4901228ce1e5bb943fc9a9eb10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rdf_rust-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 414.6 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
7dc8504b831cbc43fa54d4037e923b3fac9251e2f807cc2067cd5e008063c5fd
|
|
BLAKE2b-256 checksum How to use checksums |
7914ce7dc94ffa183b9b292bed691c8c43e52ecab76843a805a5070df7931666
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / rdf_rust-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | rdf_rust-0.1.0-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 381.7 kB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ba7673160553f8bed44fb032c4392248840abc7acf5763e371b1cb7bf0eefb67
|
|
BLAKE2b-256 checksum How to use checksums |
6f3227d712ccffbf2fdf334ede85c1bfd411aac8817b51733b05c1091a97b54d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / rdf_rust-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl
| Download URL | rdf_rust-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 403.2 kB |
| Tags | CPython 3.8 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
fe8cd98163943ec930476014c7023ef79fbc894058c11756ba40a6f89786dedb
|
|
BLAKE2b-256 checksum How to use checksums |
4a0587f625328498e82a72b0fa1650aa3c93758a25ed5cc9626e36e6966d28a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|