Skip to main content

'Runge-Kutta adaptive-step and constant-step solvers for nonlinear PDEs'

Project description

PyPI Version Build Status Code Coverage Docs Status

rkstiff

Exponential time–differencing (ETD) and integrating factor (IF) Runge–Kutta solvers for stiff semi-linear PDEs:

$u_t = L u + \mathrm{NL}(u)$

  • Fast, adaptive, and pure Python (NumPy/SciPy only)
  • Embedded error control, logging, and flexible operator support
  • Designed for spectral methods and diagonalizable systems

Tested: Python 3.9–3.13 | Dependencies: NumPy, SciPy | Optional: matplotlib, jupyter, pytest

Docs: rkstiff.readthedocs.io


Features

  • Adaptive ETD/IF Runge–Kutta solvers: ETD35, ETD34, IF34, IF45DP (embedded error control)
  • Fixed-step solvers: ETD4, ETD5, IF4
  • Operator flexibility: Diagonal or full matrix (spectral/finite-difference)
  • Spectral methods: Fourier/Chebyshev support
  • Configurable error control: SolverConfig for tolerances, safety factors
  • Logging: Per-solver logging, adjustable verbosity
  • Lightweight API: Pass a linear operator array and a callable nonlinear function
  • Utility modules: Grids, spectral derivatives, transforms, models, logging helpers

Supported equations: Nonlinear Schrödinger, Kuramoto–Sivashinsky, Korteweg–de Vries, Burgers, Allen–Cahn, Sine–Gordon


Installation

pip (recommended):

python -m pip install rkstiff

conda-forge:

conda create -n rkstiff-env -c conda-forge rkstiff
conda activate rkstiff-env

From source:

git clone https://github.com/whalenpt/rkstiff.git
cd rkstiff
python -m pip install .

Extras:

# demos: matplotlib + jupyter; tests: pytest
python -m pip install "rkstiff[demo]"
python -m pip install "rkstiff[test]"

Quickstart Example (Kuramoto–Sivashinsky)

import numpy as np
from rkstiff import grids, if34

# Real-valued grid for rfft
n = 1024
a, b = 0.0, 32.0 * np.pi
x, kx = grids.construct_x_kx_rfft(n, a, b)

# Linear operator in Fourier space
lin_op = kx**2 * (1 - kx**2)

# Nonlinear term: -F{ u * u_x }
def nl_func(u_fft):
    u = np.fft.irfft(u_fft)
    ux = np.fft.irfft(1j * kx * u_fft)
    return -np.fft.rfft(u * ux)

# Initial condition in real space → Fourier space
u0 = np.cos(x / 16) * (1.0 + np.sin(x / 16))
u0_fft = np.fft.rfft(u0)

solver = if34.IF34(lin_op=lin_op, nl_func=nl_func)
uf_fft = solver.evolve(u0_fft, t0=0.0, tf=50.0, store_freq=20)

# Convert stored Fourier snapshots back to real space
U = np.array([np.fft.irfft(s) for s in solver.u])  # shape: (num_snaps, n)
t = np.array(solver.t)

solver.u and solver.t store snapshots every store_freq internal steps; evolve returns the final state.

Kuramoto–Sivashinsky chaotic propagation
Kuramoto–Sivashinsky chaotic field propagation using IF34.

💡 More examples:
Several fully runnable Jupyter notebooks are included in the demos/ folder.
Each notebook illustrates solver usage, adaptive-step control, and visualization for different PDEs
(e.g., Kuramoto–Sivashinsky, NLS, and Allen–Cahn).
To try them:

python -m pip install "rkstiff[demo]"
jupyter notebook demos/

API Overview

Solver Classes

Solver Module Order (embedded) Adaptive Notes
ETD35 etd35 5 (3) Best for diagonalized systems
ETD34 etd34 4 (3) Krogstad 4th order
IF34 if34 4 (3) Integrating factor
IF45DP if45dp 5 (4) Dormand–Prince IF
ETD4 etd4 4 (–) Krogstad fixed-step
ETD5 etd5 5 (–) Same base as ETD35
IF4 if4 4 (–) Fixed-step IF

Constructor Signature (Adaptive Classes)

Solver(lin_op: np.ndarray, nl_func: Callable[[np.ndarray], np.ndarray], config: SolverConfig = ..., loglevel: str = ...)
  • lin_op: array shaped like u, typically diagonal entries in the working basis
  • nl_func(u): returns nonlinear term in same basis
  • config: error control and adaptivity (optional; defaults to SolverConfig())
  • loglevel: logging verbosity (optional; defaults to "INFO")

Configuration & Logging

Adaptive Error Control

Configure embedded error estimation and adaptive step control via SolverConfig:

from rkstiff.if34 import IF34
from rkstiff.solveras import SolverConfig

config = SolverConfig(epsilon=1e-5, incr_f=1.2, decr_f=0.8, safety_f=0.9)
solver = IF34(lin_op, nl_func, config=config, loglevel="INFO")

Parameter notes (typical meanings):

  • epsilon: target local error tolerance for the embedded pair.
  • safety_f: safety factor applied to proposed step-size updates.
  • incr_f / decr_f: bounds on how much dt may grow/shrink on accept/reject.
  • (Implementation-specific fields may exist; see docs for full list and defaults.)

Logging

Set logging level per solver:

solver = IF34(lin_op, nl_func, loglevel="DEBUG")

Utility Modules

  • grids: Grid and wavenumber construction for FFT/RFFT/Chebyshev
  • derivatives: Spectral differentiation (FFT, RFFT, Chebyshev)
  • transforms: Basis transforms
  • models: Example PDEs
  • util.loghelper: Logging setup and control

Usage Tips

  • For spectral methods, pass lin_op in Fourier space and implement nl_func in that same space
  • For diagonalizable systems, pre-diagonalize once and reuse that basis
  • ETD methods may precompute φ-functions; reuse the solver instance for speed
  • Storage: solver.u and solver.t hold snapshots; control frequency with store_freq

Testing & Coverage

Run tests and view coverage:

python -m pip install "rkstiff[test]"
pytest

Citation

If you use rkstiff in academic work, please cite:

P. Whalen, M. Brio, J.V. Moloney, Exponential time-differencing with embedded Runge–Kutta adaptive step control, Journal of Computational Physics 280 (2015) 579–601. DOI: 10.1016/j.jcp.2014.09.038

@article{WhalenBrioMoloney2015,
  title   = {Exponential time-differencing with embedded Runge--Kutta adaptive step control},
  author  = {Whalen, P. and Brio, M. and Moloney, J. V.},
  journal = {Journal of Computational Physics},
  volume  = {280},
  pages   = {579--601},
  year    = {2015},
  doi     = {10.1016/j.jcp.2014.09.038}
}

License

MIT — see LICENSE for details.

Contact

Patrick Whalen — whalenpt@gmail.com

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

rkstiff-1.0.2.tar.gz (204.6 kB view details)

Uploaded Source

Built Distribution

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

rkstiff-1.0.2-py3-none-any.whl (63.2 kB view details)

Uploaded Python 3

File details

Details for the file rkstiff-1.0.2.tar.gz.

File metadata

  • Download URL: rkstiff-1.0.2.tar.gz
  • Upload date:
  • Size: 204.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for rkstiff-1.0.2.tar.gz
Algorithm Hash digest
SHA256 000e1d17eaad71ff31925d024a71fc9838eb25dd493f37852faec9a9296162e9
MD5 bfd6b9aab8a49d84a6f0142c45dece76
BLAKE2b-256 d385b1dfc10b1a55a97f838145f6ca7b4cbfbc59b7639febfe8cd03f05b68b20

See more details on using hashes here.

File details

Details for the file rkstiff-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: rkstiff-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 63.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for rkstiff-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7ee4875e457210412f0f2f8fa4f6d2e387d51243e2a8b7501ec82d9f93c6b293
MD5 359b278ea723e81891766fa2f24cbf37
BLAKE2b-256 033aeff0bf9da0cf426cb96930e1d8ac84aae5845db0482f0463f23570e0c36c

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