Repository navigation
feat(rust)!: ship pybamm.rust in the pybamm wheel - #5958
Open
BradyPlanden wants to merge 1 commit into
Open
BradyPlanden wants to merge 1 commit into
BradyPlanden wants to merge 1 commit into
Conversation
This was referenced Oct 22, 2026
This was referenced Oct 22, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## stack/02-rust-core-model-ffi #5958 +/- ##
=============================================================
Coverage 98.24% 98.24%
=============================================================
Files 350 351 +1
Lines 36112 36128 +16
=============================================================
+ Hits 35477 35493 +16
Misses 635 635 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
BradyPlanden
force-pushed
the
stack/03-pybamm-rust-packaging
branch
from
October 28, 2026 09:55
f80ee30 to
aa16ed3
Compare
BradyPlanden
force-pushed
the
stack/03-pybamm-rust-packaging
branch
from
October 28, 2026 11:06
aa16ed3 to
fbf7558
Compare
BradyPlanden
force-pushed
the
stack/03-pybamm-rust-packaging
branch
2 times, most recently
from
October 29, 2026 08:01
40f0970 to
5fd7c6f
Compare
BradyPlanden
marked this pull request as ready for review
October 29, 2026 08:55
Contributor
|
| Project | PyBaMM |
| Branch | stack/03-pybamm-rust-packaging |
| Testbed | bare-metal |
🐰 View full continuous benchmarking report in Bencher
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
The pybamm-python PyO3 crate (ExprGraph, CompiledFunction, CompiledJacobian) built into the pybamm wheel by a hatch hook, with stubs, the cibuildwheel matrix and the build docs.
BradyPlanden
force-pushed
the
stack/03-pybamm-rust-packaging
branch
from
October 29, 2026 17:26
5fd7c6f to
2a667be
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
pybamm-python, a PyO3 crate that bindspybamm-core, and builds it into thepybammwheel aspybamm.rust._core.pybammtherefore becomes a platform-specific wheel, and installing it from source needs a Rust toolchain.import pybammdoes not load the extension; it loads on the first import ofpybamm.rust.Bindings
ExprGraphbuilds an expression throughpybamm-core's checked constructors andParamRegistry, and rejects anExprfrom another graph. A node the IR cannot compile raisesNotImplementedErrornamingconvert_to_format='casadi'. A graph pickles through its arena, and__setstate__restores only into an empty graph.CompiledFunctionis one compiled expression, or a named set fromcompile_outputson one tape, so shared subexpressions run once. It evaluates (__call__,eval,eval_into), takes JVPs, builds and caches its Jacobian with respect toyorp, and evaluates whole trajectories (eval_trajectory,jvp_trajectory,eval_trajectory_hermite) with the GIL released. The value and Hermite trajectories run in lane tiles of about 1 MiB, clamped to 8–64 lanes;jvp_trajectoryis not tiled.eval_intoborrowsoutread-write and its inputs read-only through numpy's borrow checker, so a read-onlyout, or one that shares memory withy,y_dot,por a dict value, raisesValueErrorrather than aPanicException.CompiledJacobianassembles into ascipy.sparse.csc_matrixwhose int32indptrandindicesare cached and read-only, so in-place canonicalisation raises instead of corrupting the shared pattern.FunctionMetadatachecks and packs each call's arguments, takingpas a dict or a flat array.ScratchPoollends each call its own scratch, because&selfmethods on these frozen classes may run concurrently once the GIL is released; it keeps at most 8 items.CoreErroris raised asValueError._core.pyiholds hand-written stubs, whichtest_rust_stubs.pychecks against the built extension withmypy.stubtest. AGENTS.md gains the rule that a change to the bindings updates the stubs in the same commit.pybamm.rustimports_corewithRTLD_GLOBAL, so that pybammsolvers can resolve the C ABI withdlsym(feat(pybammsolvers)!: an IDAKLU backend over the Rust C ABI #5961).Build and release
hatch_build.pyrunsmaturin build --release --locked --features pyo3/abi3-py310, plus--compatibility linux --auditwheel skipon Linux. It then copies the extension intosrc/pybamm/rust/and tags the wheel for the platform, except for editable installs. Withoutcargo, it raises an error explaining how to install Rust or use--only-binary.maturin>=1.14.1,<2.0joins the build requirements. The sdist includes the Rust sources,Cargo.lockand benches.[tool.uv] cache-keyscover the Rust sources, souv syncrebuilds after a change.publish_pypi.ymlbuilds onecp310-abi3wheel per platform with cibuildwheel 4.1.1: manylinux x86_64 and aarch64, macOS arm64 and x86_64, and Windows AMD64.twine check --strictruns on the result.target/. It then builds a wheel from the sdist, which PyPy, musllinux and free-threaded installs depend on.persist-credentials: false, and the release jobs do not cache Cargo, so a poisoned cache cannot reach a wheel.pybamm-v*releases.rust-cache. Read the Docs and both Dockerfiles install Rust (1.89 in the images), and the benchmark image installs a built wheel. The nox and from-source jobs cache Rust builds.benchmarks_pr.ymlalso runs on changes to the Rust sources andhatch_build.py.developer/rust_idaklu_build.mddescribes the build. The installation guide covers the platform wheels and installing from source, andapi/rust.rstdocumentspybamm.rust.The abi3 wheels cover Python 3.10-3.15, the range
requires-pythonallows. The release toolchain is the latest stable Rust.Review on #5732
CompiledFunctionrather than a separate group class: a named set is aCompiledFunctionwith an output layout (also).expr.rskeeps the cross-graph ownership check and thechecked_root,check_read_extentsandcheck_supportedguards.unzip:compile_outputscollects names and ids in one pass.modulecomment is stated once inlib.rs, andCompiledFunctionhas a docstring.compiled_function.rs,scratch_pool.rs, andfunction_metadata.rs, holdingFunctionMetadatawith a docstring.OnceLockrather thanOption: the class is#[pyclass(frozen)]and fills the tangent tapes through&self, which anOptionfield cannot do.Minttrait: there is no trait.ScratchPool<S>holds aMutex<Vec<S>>, andacquiretakes a closure that makes an item when the pool is empty.ScratchPooldocstring says why the pool exists.dataandscratch_poolonCompiledJacobian:datais the Jacobian tape shared by every call, and the pool holds each call's scratch.Type of change
Breaking change:
pybammbecomes a platform-specific wheel and a source install needs Rust (cargo1.89+). This is under## Breaking changes, withpip install --only-binary pybamm pybammas the migration note.pybamm.rustis under## Features.Key checklist
pre-commit runcp310-abi3wheel built with Python 3.10 imports and solves a DFN, and the unit tests (5594), pybammsolvers' tests (70) and the Rust and diffsol integration tests (147) passCompiledFunction:pas a dict or an array, with validation errors;eval_intowith a read-only or aliasedout;jvp_trajectoryand Hermite evaluation;hatch_build.py: wheel tags, extension extraction, missingcargo, the maturin command, and editable builds;RTLD_GLOBALis set and restored;mypy.stubtest.__setstate__only into an empty graph.Rust execution engine stack: proposal #5667, showcase #5732
Each PR is one commit on the one above it.
Function.create_copykeeps the function's classRegPowerand uniform-grid interpolant lookups matchevaluatepybamm-core: expression graph, typed IR, interpreters, forward-mode ADpybamm-core:CompiledModel, coloured Jacobians, the C ABIpybamm.rustbindings, built into thepybammwheel ← this PRSymbol.to_rustconvert_to_format = "rust"forScipySolver,AlgebraicSolverand EISpybammsolvers: IDAKLU over the C ABIIDAKLUSolveron rust modelspybamm-core: diffsol DAE solverpybamm.DiffsolSolver"rust"as the defaultconvert_to_format