This project exposes high-performance Rust functions to Python using PyO3 and maturin. It provides simplified utilities to generate 3D atomic point lattices (simple cubic only) and compute a Debye scattering-like intensity using parallel Rust code. This is an educational/demonstration project showing Rust-Python integration for scientific computing.
- Rust module name (as seen from Python):
fast_dse - Python demo entry point:
main.py
src/lib.rs— Rust implementation of the Python module using PyO3 and Rayonmain.py— Example Python script that calls the Rust functions and plots resultspyproject.toml— maturin/PyO3 build configurationCargo.toml— Rust crate configurationLICENSE— MIT License
The Rust library defines a Python module named fast_dse with two functions:
-
crystal(shape: str, lattice_param: float, length: float) -> list[list[float]]- Generates 3D lattice points with a simple step equal to
lattice_param. - Supported
shapevalues:-
"cube": all lattice points in a cube of sidelength. -
"sphere": lattice points inside a sphere of diameterlength(radiuslength/2).
-
- Returns: a list of 3D points
[x, y, z](floats) representing atom positions.
- Generates 3D lattice points with a simple step equal to
-
dse_optimized(min_q: float, max_q: float, q_step: float, crystal: list[list[float]]) -> list[float]-
Computes an intensity profile over
qin[min_q, max_q)with spacingq_step. -
The intensity is calculated using the simplified Debye scattering equation:
$$I(q) = \sum_{i=1}^{N} \sum_{j=1}^{N} \frac{\sin(q \cdot r_{ij})}{q \cdot r_{ij}}$$ where
$N$ is the number of atoms and$r_{ij}$ is the distance between atoms$i$ and$j$ . -
Internally:
- Precomputes all pairwise squared distances between points in
crystal. - For each
q, sumssin(q * r) / (q * r)over all pairs, withr=0contributing1.0. - Uses Rayon for parallelism over
qvalues.
- Precomputes all pairwise squared distances between points in
-
Returns: a list of intensities with length
floor((max_q - min_q) / q_step).
-
These functions are exported to Python with PyO3 via the #[pymodule] named fast_dse.
This is a simplified implementation intended for educational purposes and basic simulations:
-
Crystal structures: The
crystal()function generates simple cubic lattices only. It does not support common crystal structures like FCC (face-centered cubic), BCC (body-centered cubic), HCP (hexagonal close-packed), or other Bravais lattices. -
Atomic scattering factors: The
dse_optimized()function does not account for atomic scattering factors (form factors). This implementation is only accurate (up to a coefficient) for monoatomic crystals with identical scattering atoms. For real materials with different atom types or accurate X-ray/neutron scattering calculations, proper form factors must be included.
For production use in materials science or crystallography, consider using established libraries like pymatgen, ASE, or diffpy.
main.py shows how to:
- Import the Rust functions from Python:
from fast_dse import crystal, dse_optimized - Generate two crystals (sphere and cube)
- Compute intensities for a
qrange - Plot both curves using matplotlib
Snippet:
from fast_dse import crystal, dse_optimized
import matplotlib.pyplot as plt
import numpy as np
lattice_param = 3.89
length = 30
sphere_crystal = crystal("sphere", lattice_param, length)
cube_crystal = crystal("cube", lattice_param, length)
q_0, q_f, q_step = 1.0, 15.0, 0.1
q_array = np.arange(q_0, q_f, q_step)
intensity_sphere = dse_optimized(q_0, q_f, q_step, sphere_crystal)
intensity_cube = dse_optimized(q_0, q_f, q_step, cube_crystal)
plt.plot(q_array, intensity_sphere, label="sphere")
plt.plot(q_array, intensity_cube, label="cube")
plt.legend()
plt.xlabel("q")
plt.ylabel("Intensity")
plt.title("Debye-like Scattering Intensity")
plt.show()Prerequisites:
- Rust toolchain (stable) — install via https://rustup.rs
- Python 3.8+ (matching your environment)
- uv (recommended) — a fast Python package installer and environment manager written in Rust. Install via
pip install uvor see https://github.com/astral-sh/uv - On Windows, ensure your Python architecture (e.g., 64-bit) matches the Rust toolchain target. Using a recent MSVC build chain via Visual Studio Build Tools is recommended.
Setup with uv (recommended):
- Clone the repository:
git clone https://github.com/AlbertKurtz/fast_dse.git
cd fast_dse- Create a virtual environment and install with dev dependencies:
uv venv
# On Windows:
.venv\Scripts\activate
# On macOS/Linux:
source .venv/bin/activate
uv pip install -e .[dev]This will compile the Rust extension and install it into your virtual environment so you can immediately import fast_dse.
Alternative with pip:
python -m venv .venv
# Activate virtual environment (see above)
pip install -e .[dev]Building a wheel manually:
uv pip install maturin
maturin build --release
# find the .whl in target/wheels/ and install it
uv pip install target/wheels/<your_wheel_name>.whlAfter installation with dev dependencies (make sure your virtual environment is activated):
python main.pyThis will open a plot window comparing the intensity for a spherical and cubic crystal with the parameters from the script.
dse_optimizeduses Rayon to parallelize overqvalues and precomputes all pairwise distances for cache efficiency.- For large crystals, the distance matrix is O(N^2) in memory and time to precompute; adjust
lengthandlattice_paramaccordingly.
-
ImportError: No module named
fast_dse- Make sure you installed the package with
uv pip install -e .[dev] - Verify you're using the correct Python environment:
python -c "import sys; print(sys.executable)" - Make sure your virtual environment is activated
- Make sure you installed the package with
-
Linker/build errors on Windows
- Ensure you have the MSVC toolchain installed via Visual Studio Build Tools
- Verify that Rust targets your Python architecture (both should be 64-bit or both 32-bit)
-
ImportError: No module named 'matplotlib' (when running demo)
- Install matplotlib:
uv pip install matplotlibor use dev dependencies:uv pip install -e .[dev]
- Install matplotlib:
MIT