Skip to content

feat(rust): lower expression trees with Symbol.to_rust - #5959

Open
BradyPlanden wants to merge 1 commit into
stack/03-pybamm-rust-packagingfrom
stack/04-to-rust-lowering
Open

BradyPlanden wants to merge 1 commit into
stack/03-pybamm-rust-packagingfrom
stack/04-to-rust-lowering

Conversation

@BradyPlanden

Copy link
Copy Markdown
Member

Description

Adds Symbol.to_rust(graph, rust_symbols=None), which lowers a discretised expression tree into a pybamm.rust.ExprGraph. Each class implements _to_rust, and a subtree shared within the tree is lowered once, cached on its id. Nothing calls it yet; #5960 uses it to compile a model's functions.

  • Leaves: Scalar, Time, InputParameter (at its expected width), and StateVector/StateVectorDot, with several slices concatenated.
  • Array: lowers as dense values, or as a dense matrix when it has more than one column. A sparse array stays a CSR matrix as the left operand of a matrix product, copied into canonical order so that each row sums in ascending column order, as CasADi does. scipy's stored order, which can be unsorted, left residual noise near roundoff that stalled IDA on the DFN.
  • Operators:
    • arithmetic, Power, Inner, Minimum/Maximum, Modulo, Hypot, the Heavisides, Equality and MatrixMultiplication. Modulo truncates like CasADi's fmod, so for a negative operand it matches CasADi rather than evaluate's floored modulo. At a tie, Minimum/Maximum and the max/min reductions take the left operand's or first entry's derivative, as Symbol.jac does, where CasADi splits it 0.5/0.5;
    • Negate, AbsoluteValue, Sign, Floor, Ceiling and Index;
    • NumpyConcatenation, DomainConcatenation, SparseStack, Conditional and VectorField;
    • ExplicitTimeIntegral, DiscreteTimeSum and NotConstant lower their child.
  • Functions:
  • Interpolants:
    • 1D linear, with one interpolant per column for vector-valued data. A repeated interior knot lowers as a step, so step profiles solve on Rust; a table Rust refuses, such as one repeating its first knot, raises pybamm.ModelError naming convert_to_format = 'casadi';
    • 1D cubic and pchip, from the same PPoly coefficients evaluate uses;
    • 2D and 3D linear and cubic.
    • extrapolate=False is ignored, as on CasADi.

Unsupported nodes raise when they are lowered:

  • TypeError, naming the class and convert_to_format = 'casadi', for KroneckerProduct, TensorProduct, Transpose, Magnitude, Component, Norm, spatial operators and a generic Function;
  • NotImplementedError for a strided Index, 1D interpolant data with more than two dimensions, and interpolants in four or more dimensions.

Type of change

New feature, under ## Features in CHANGELOG.md.

Key checklist

  • No style issues: pre-commit run
  • Unit tests pass (N), as do the integration tests (N)
  • Tests added: 152 Python test functions.
    • Lowering:
      • each node lowered and evaluated against evaluate;
      • RegPower bitwise equal across numpy, CasADi MX and SX, and Rust, for exponents 0.5 and 2 at scales 1 and 33133;
      • interpolants in 1D to 3D;
      • Jacobians against CasADi;
      • the errors for unsupported nodes, and step interpolants and refused tables;
      • RegPower with delta = 0, and Modulo with negative operands, against CasADi;
      • the cross-graph guard;
      • max/min subgradients, and abs, sign, Minimum, Maximum and the reductions at ties.
    • Parity: Rust against CasADi on toy models, and on the SPM rhs and named outputs, at rtol 1e-8 to 1e-12.
    • Numerics: multi-slice state vectors, a sparse product summed in column order, a repeated 1+1D DomainConcatenation, and dense-row colouring of the SPMe "voltage as a state" Jacobian.
    • Trajectories and pickling: trajectory methods on lists, float32 time grids and a strided array, and pickled graphs keeping input indices and widths.
    • Fixtures: dual_backend_compare is in tests/conftest_rust.py; feat(rust): evaluate rust models through compiled evaluators #5960 adds rust_backend there, once "rust" is a format.
Rust execution engine stack: proposal #5667, showcase #5732

Each PR is one commit on the one above it.

# PR Adds
0 #5954 Function.create_copy keeps the function's class
0b #5955 CasADi's RegPower and uniform-grid interpolant lookups match evaluate
1 #5956 pybamm-core: expression graph, typed IR, interpreters, forward-mode AD
2 #5957 pybamm-core: CompiledModel, coloured Jacobians, the C ABI
3 #5958 pybamm.rust bindings, built into the pybamm wheel
4 #5959 Symbol.to_rust ← this PR
5 #5960 convert_to_format = "rust" for ScipySolver, AlgebraicSolver and EIS
6 #5961 pybammsolvers: IDAKLU over the C ABI
7 #5962 IDAKLUSolver on rust models
8 #5963 variables and sensitivities read in Rust
9 #5964 pybamm-core: diffsol DAE solver
10 #5965 pybamm.DiffsolSolver
11 #5966 "rust" as the default convert_to_format

@codecov

codecov Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.80882% with 25 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (stack/03-pybamm-rust-packaging@2a667be). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...s/pybamm/src/pybamm/expression_tree/interpolant.py 87.95% 10 Missing ⚠️
...ges/pybamm/src/pybamm/expression_tree/functions.py 89.13% 5 Missing ⚠️
...ybamm/src/pybamm/expression_tree/concatenations.py 88.23% 2 Missing ⚠️
...mm/src/pybamm/expression_tree/discrete_time_sum.py 50.00% 2 Missing ⚠️
...bamm/src/pybamm/expression_tree/unary_operators.py 93.10% 2 Missing ⚠️
...ackages/pybamm/src/pybamm/expression_tree/array.py 95.23% 1 Missing ⚠️
...amm/src/pybamm/expression_tree/binary_operators.py 96.96% 1 Missing ⚠️
.../pybamm/src/pybamm/expression_tree/state_vector.py 90.00% 1 Missing ⚠️
...ckages/pybamm/src/pybamm/expression_tree/symbol.py 94.11% 1 Missing ⚠️
Additional details and impacted files
@@                        Coverage Diff                        @@
##             stack/03-pybamm-rust-packaging    #5959   +/-   ##
=================================================================
  Coverage                                  ?   98.18%           
=================================================================
  Files                                     ?      351           
  Lines                                     ?    36399           
  Branches                                  ?        0           
=================================================================
  Hits                                      ?    35738           
  Misses                                    ?      661           
  Partials                                  ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@BradyPlanden
BradyPlanden force-pushed the stack/04-to-rust-lowering branch from 0c46274 to 64cb90a Compare October 28, 2026 09:55
@BradyPlanden
BradyPlanden force-pushed the stack/04-to-rust-lowering branch 3 times, most recently from d0980ff to bfa1ad0 Compare October 29, 2026 08:01
@BradyPlanden
BradyPlanden marked this pull request as ready for review October 29, 2026 08:55
@BradyPlanden
BradyPlanden requested a review from a team as a code owner October 29, 2026 08:55
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

ProjectPyBaMM
Branchstack/04-to-rust-lowering
Testbedbare-metal

⚠️ WARNING: Truncated view!

The full continuous benchmarking report exceeds the maximum length allowed on this platform.

🐰 View full continuous benchmarking report in Bencher

to_rust on Symbol and every expression-tree class that lowers.
@BradyPlanden
BradyPlanden force-pushed the stack/04-to-rust-lowering branch from bfa1ad0 to 595db2e Compare October 29, 2026 17:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant