Skip to main content

Fast numerical ODE solvers (RK4, RK45, DOP853) optimized with Numba.

Project description

YENNEFER ODE SOLVER

Yennefer is a high-performance Python library for solving ordinary differential equations (ODEs), built on top of NumPy and accelerated via Numba JIT compilation.


Features

  • Three integration methods covering fixed-step and adaptive workflows.
  • Numba @njit-compiled solver cores.
  • Unified, minimal API across all solvers.
  • Pass arbitrary physical parameters to the RHS without global state.
  • Works seamlessly with @njit-decorated right-hand sides for maximum performance.

Installation

pip install yennefer

Solvers

Class Method Order Step control
RK4Solver Classical Runge–Kutta 4 Fixed
RK45Solver Runge–Kutta–Fehlberg 4(5) 4/5 Adaptive
DOP853Solver Dormand–Prince 8(5,3) 8 Adaptive

Example — Josephson Junction (RCSJ model)

The RCSJ model of a Josephson junction:

$$ \begin{cases} \frac{dV}{dt} = I_c + A\sin(u) - \beta V - \sin\varphi\ \frac{d\varphi}{dt} = V \ \frac{du}{dt} = \omega \end{cases} \tag{1} $$

import numpy as np
import matplotlib.pyplot as plt
from numba import njit
from yennefer import RK4Solver, RK45Solver, DOP853Solver

@njit
def jj_system(t, y, p):
    V, ph, u = y
    Ic, A, beta, omega = p[0], p[1], p[2], p[3]
    return np.array([
        Ic + A * np.sin(u) - beta * V - np.sin(ph),
        V,
        omega,
    ])

y0     = np.array([0.0, 0.0, 0.0])
params = np.array([0.1, 0.5, 0.2, 2.0])  # Ic, A, beta, omega

Fixed step with RK4

solver = RK4Solver(jj_system, y0, params)
T, Y = solver.solve(300.0, 5e-2)

Adaptive step with RK45

solver = RK45Solver(jj_system, y0, params)
T, Y = solver.solve(300.0, dt_initial=5e-2)

High-accuracy with DOP853

solver = DOP853Solver(jj_system, y0, params)
T, Y = solver.solve(300.0, dt_init=5e-2)

Plot

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

ax1.plot(T, Y[:, 0], label="V(t)")
ax1.set_xlabel("t"); ax1.set_ylabel("V"); ax1.legend()

ax2.plot(T, Y[:, 1], label="φ(t)")
ax2.set_xlabel("t"); ax2.set_ylabel("φ"); ax2.legend()

plt.tight_layout()
plt.show()

More precise example is presenter in example usage IPython notebook.


RK4Solver — Fixed-Step 4th-Order Runge–Kutta

The classical RK4 method. Every step uses exactly 4 RHS evaluations. Best suited for smooth problems where you know the required step size in advance, or when uniform output is needed.

solver = RK4Solver(function, y0, params)
t, y = solver.solve(t_max, dt)
Parameter Description
function RHS f(t, y, params) -> dy
y0 Initial state vector (np.float64 array)
params Parameter vector passed verbatim to f
t_max Integration horizon
dt Fixed step size

RK45Solver — Adaptive Runge–Kutta–Fehlberg 4(5)

Embedded 4(5) pair with automatic step-size control. The 5th-order solution advances the state; the difference between 4th and 5th order estimates drives the error controller. 6 RHS evaluations per accepted step. Good general-purpose choice for moderate accuracy requirements.

solver = RK45Solver(function, y0, params, atol=1e-6, rtol=1e-3, max_step=np.inf)
t, y = solver.solve(t_max, dt_initial=1e-3)
Parameter Description
atol Absolute error tolerance (default 1e-6)
rtol Relative error tolerance (default 1e-3)
max_step Maximum allowed step size (default )
dt_initial Initial step size guess

DOP853Solver — Dormand–Prince 8(5,3)

Implementation of the classic Hairer–Nørsett–Wanner DOP853 method from Solving ODEs I (1993), based on the original Fortran source by Hairer & Williams. Dual embedded error estimators (5th and 3rd order), FSAL reuse (effectively 11 new RHS calls per accepted step). The go-to solver for high-accuracy and stiff-sensitive problems.

solver = DOP853Solver(function, y0, params, rtol=1e-9, atol=1e-9, n_max_steps=10000)
t, y = solver.solve(t_max, dt_init)
Parameter Description
rtol Relative error tolerance (default 1e-9)
atol Absolute error tolerance (default 1e-9)
n_max_steps Maximum number of accepted steps (default 10000)
dt_init Initial step size guess

Common API

All solvers share the same RHS signature convention and output contract.

Right-hand side signature

@njit
def f(t: float, y: np.ndarray, params: np.ndarray) -> np.ndarray:
    ...

Decorating f with @njit is optional but strongly recommended — it eliminates the Python call overhead inside the inner loop and yields the best performance.

Output

solver.solve(...) returns a tuple (t, y):

Name Shape Description
t (N,) Time grid
y (N, n_vars) Solution at each time point

Both are also available as .t and .y properties after the call.


Performance tips

  • Always decorate the RHS with @njit. The first call triggers compilation (warm-up); subsequent calls run at native speed.
  • If you benchmark solvers against each other or against SciPy, run a short warm-up integration first to exclude JIT compilation time from the measurement.
  • For adaptive solvers, tighter tolerances (1e-121e-14) with DOP853 are often faster than the same accuracy with RK45, because DOP853 accepts far fewer steps.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yennefer-0.2.5.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yennefer-0.2.5-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file yennefer-0.2.5.tar.gz.

File metadata

  • Download URL: yennefer-0.2.5.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for yennefer-0.2.5.tar.gz
Algorithm Hash digest
SHA256 b37e759860fd7a262f331ccb435c43098602772f4382913c40af1374a8e01f8d
MD5 410bcaf3112006b6a7868a1b59a8d6e2
BLAKE2b-256 00908f27aaa6340f0385b2ae649a1d0d4dfed150331c5deacf7516c7df80989f

See more details on using hashes here.

File details

Details for the file yennefer-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: yennefer-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 13.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for yennefer-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 ad78dac295eacf9f51b0c6eae837b11e31c727f1e13c6ac5af3c88414612c89e
MD5 93f473ac5bc548c60580b61fa70b17ee
BLAKE2b-256 d8dc9b911af69262f153ff0d509b5e8a6a67c8aa126a75722963c300641703f1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page