op_engine
Operator-Partitioned Engine (OP Engine) is a lightweight multiphysics solver core for time-dependent systems. It supports explicit ODE solvers, IMEX/operator-based schemes for PDE-like models, and exact or approximate stochastic reaction-network solvers while staying framework-agnostic.
Why use it?
- Shared solver surface for ODEs and operator-split PDEs.
- Strong typing and Array-API explicit and dense-implicit paths, including reusable higher-order Runge--Kutta tableaus.
- JAX autodiff and JIT support for the same portable fixed-step methods.
- Separates state/time management (
ModelCore) from stepping logic (CoreSolver). - Optional adapters (e.g., flepimop2) without affecting the core API.
- IMEX paths accept externally supplied operator tuples; defaults remain explicit-only.
Core surface
ModelCore: state/time manager; configure axes, dtype, and optional history.CoreSolver: portable explicit methods through Dormand--Prince 5(4), plus dense IMEX and linearly implicit methods; acceptsRunConfigwithAdaptiveConfig,DtControllerConfig, andOperatorSpecs.DirectSSASolver: exact Gillespie direct-method trajectories with injected, backend-specific exponential and categorical sampling.AdaptiveTauLeapingSolver: bounded adaptive tau-leaping with leap-condition control, exact critical events, and explicit post-leap rejection.TauLeapingSolver: fixed-step stochastic reaction-network integration with injected, backend-specific Poisson sampling.matrix_ops: portable dense advection/diffusion, sparse Laplacian/Crank–Nicolson, implicit Euler/trapezoidal builders, predictor–corrector, implicit solve cache, Kronecker helpers, and grouped aggregations.- Extras:
OperatorSpecs,RunConfig,AdaptiveConfig,DtControllerConfig,Operator,GridGeometry,DiffusionConfig.
See the documentation guides for solver selection, the biogeochemical splitting tutorial, and backend boundaries.
Installation
pip install op_engine
With JAX as the array namespace:
pip install "op_engine[jax]"
With flepimop2 adapter:
pip install flepimop2-op-engine
To use the op_system provider contract as well:
pip install "flepimop2-op-engine[op-system]"
Quickstart
import numpy as np
from op_engine import ModelCore, CoreSolver
# Define RHS
def rhs(t, y):
s, i, r = y
beta, gamma = 0.3, 0.1
return np.array([-beta * s * i, beta * s * i - gamma * i, gamma * i])
# Time grid and state
core = ModelCore(n_states=3, n_subgroups=1, time_grid=np.linspace(0, 10, 101))
core.set_initial_state(np.array([0.999, 0.001, 0.0])[..., None])
solver = CoreSolver(core)
solver.run(rhs) # defaults to Heun/RK2
solution = core.state_array # shape (n_timesteps, state, subgroup)
Array namespaces
ModelCore infers its numerical namespace from the initial state through
array_api_compat.array_namespace(). The state, stored history, solver stages,
and dense solver operations stay in that namespace. There is no xp= or
backend option. This supports standard Array-API objects and native arrays such
as torch.Tensor. Fixed-step methods can be differentiated by JAX; the built-in
adaptive controller is eager Python control flow. See the
backend guide for the precise contract and the
solver guide for method-specific examples.
IMEX with operators (tuple form)
import numpy as np
from op_engine import CoreSolver, ModelCore, OperatorSpecs
n = 4
times = np.linspace(0.0, 1.0, 11)
core = ModelCore(n_states=n, n_subgroups=1, time_grid=times)
core.set_initial_state(np.ones((n, 1)))
# Identity implicit operator along state axis
L = np.eye(n)
R = np.eye(n)
ops = OperatorSpecs(default=(L, R))
def rhs(t, y):
return -0.1 * y
solver = CoreSolver(core, operators=ops.default, operator_axis="state")
solver.run(rhs, config=None) # defaults: method="heun" (explicit)
# For IMEX methods set method and operators via RunConfig:
# from op_engine.core_solver import RunConfig, AdaptiveConfig, DtControllerConfig
Public API
ModelCore: state tensor + time grid manager; supports extra axes and optional history.CoreSolver: portable explicit and dense IMEX/implicit stepping selected by the state array namespace.DirectSSASolver: exact event-by-event stochastic reaction trajectories with NumPy, JAX, or another Array-API namespace supplying random draws.AdaptiveTauLeapingSolver: adaptive non-negative stochastic leaps using explicit reactant stoichiometry and injected Poisson plus exact-event sampling.TauLeapingSolver: portable stoichiometric updates with NumPy, JAX, or another Array-API namespace supplying Poisson samples.- Operator utilities (
matrix_ops): portable upwind advection, Laplacian, Crank–Nicolson/implicit Euler/trapezoidal operators, predictor-corrector builders, implicit solve cache, Kronecker helpers, and grouped aggregation utilities. - Configuration helpers:
RunConfig,OperatorSpecs,AdaptiveConfig,DtControllerConfigfor method/IMEX/adaptive control. - Adapters: optional flepimop2 integration (extra dependency) via entrypoints in the adapter package. The adapter merges any
mixing_kernelsalready computed by op_system (no automatic generation) and consumes config-supplied IMEX operator specs (dict orOperatorSpecs), forwarding the chosenoperator_axistoCoreSolver.
Development
uv sync --dev
just ci
License
MIT License
Metadata
Release files for op-engine 0.3.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 | |
|---|---|---|---|
| op_engine-0.3.0.tar.gz | 418.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| op_engine-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 503.6 kB
Release files / op_engine-0.3.0.tar.gz
| Download URL | op_engine-0.3.0.tar.gz |
|---|---|
| Size | 418.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dcb56c0854a89019045c2ba003491b692986a716fe08cceaf6b1631b1322ae34
|
|
BLAKE2b-256 checksum How to use checksums |
f19de6294c0d8aada08385ebbe4484ef44981944c559ee03000d17c93c9ed6d2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / op_engine-0.3.0-py3-none-any.whl
| Download URL | op_engine-0.3.0-py3-none-any.whl |
|---|---|
| Size | 85.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dde39312a4b142b8acb0425e987858264ad0ea9b374d39f0d363d512ed0da159
|
|
BLAKE2b-256 checksum How to use checksums |
8b42ca083e1ea8ca958989d4ff42bc6da3975efb29b1f57e5041406968dc62eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency log