Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# API Reference

All public routines are exported via the `sdepack` Python module. Only
subroutines declared in the `src/sdepack.pyf` interface file are accessible
from Python.
`sdepack` provides a Python interface to a high-performance Fortran numerical
core compiled via `f2py`. All public routines are exported through the
`sdepack` module; only subroutines declared in the `src/sdepack.pyf`
interface file are accessible from Python. See the [Theory](theory.md) and
[Quickstart](quickstart.md) for mathematical background and usage.

---

Expand Down
106 changes: 43 additions & 63 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,69 @@

---

## What is sdepack?
## Overview

`sdepack` is a Python library for solving scalar
[stochastic differential equations](https://en.wikipedia.org/wiki/Stochastic_differential_equation)
(SDEs) using stochastic Runge-Kutta methods. The numerical core is written in
Fortran and compiled via `f2py`, giving near-native performance while
providing a clean, NumPy-based Python API.
(SDEs) using stochastic Runge-Kutta methods. It allows you to **easily** and **efficiently**
integrate SDEs driven by a Wiener process — from molecular dynamics and population genetics
to option pricing and control systems.

A **stochastic differential equation** is a differential equation in which one
or more terms are stochastic processes, producing a solution that is itself a
random process. SDEs are used to model phenomena across science and engineering
where systems are subject to random influences — from molecular dynamics and
population genetics to option pricing and signal processing.
A **stochastic differential equation** is a differential equation in which one or more terms
are stochastic processes, producing a solution that is itself a random process.

`sdepack` targets **scalar Itô SDEs** of the general form:

$$
dX(t) = \underbrace{a(X, t)}_{\text{drift}}\,dt
+ \underbrace{b(X, t)}_{\text{diffusion}}\,dW(t),
dX(t) = a(X, t)\,dt + b(X, t)\,dW(t),
$$

where $W(t)$ is a [Wiener process](https://en.wikipedia.org/wiki/Wiener_process)
(standard Brownian motion).

## Mathematical model

Within the solvers, the SDE is parameterized as:

**Time-invariant** routines integrate
where $W(t)$ is a [Wiener process](https://en.wikipedia.org/wiki/Wiener_process) (standard
Brownian motion). Within the solvers, the SDE is parameterized as:

$$
dX(t) = F(X)\,dt + Q\,G(X)\,dW(t),
dX(t) = F(X, t)\,dt + Q\,G(X, t)\,dW(t),
$$

**Time-variant** routines integrate
where $F$ is the user-supplied **drift** callback, $G$ is the user-supplied **diffusion**
callback, and $Q$ scales the noise intensity. For **time-invariant** routines, $F$ and $G$
do not depend explicitly on time.

$$
dX(t) = F(X,t)\,dt + Q\,G(X,t)\,dW(t),
$$
## Requirements

where $Q$ scales the noise intensity (spectral density of the driving white
noise), $F$ is the user-supplied **drift** callback and $G$ is the
user-supplied **diffusion** callback.
- [NumPy](http://www.numpy.org/)

Integration is performed with a uniform time step:
## Example Usage

$$
H = \frac{T_N - T_0}{N}.
$$
```python
import numpy as np
import sdepack

Stage noise for the Runge-Kutta stages is drawn from:
# Ornstein-Uhlenbeck process: dX = -X dt + dW
x = np.zeros(1001, dtype=np.float64)
sdepack.rk4_ti_solve(
lambda x: -x, # drift F(X) = -X
lambda x: 1.0, # diffusion G(X) = 1
x,
0.0, # t0
10.0, # tn
1.0, # x0
1000, # n steps
1.0, # Q (noise intensity)
42, # seed
)
print(x[:6])
```

$$
W_i = Z_i\sqrt{\frac{Q_i Q}{H}},\quad Z_i \sim \mathcal{N}(0,1),
$$
## Main Features

where $Q_i$ are method-specific noise coefficients that ensure the correct
stochastic scaling at each Runge-Kutta stage.
1. Seven stochastic Runge-Kutta solvers (orders 1–4).
2. Both time-invariant and time-variant SDE forms.
3. Plain Python callables for drift and diffusion — lambdas work too.
4. Seeded, fully reproducible trajectories via a built-in PRNG.
5. NumPy array output — integrates directly with matplotlib, scipy, and the scientific Python stack.

## Available solvers
**Available solvers:**

| Solver | Stages | Order | Time-dependence | Based on |
|---|---|---|---|---|
Expand All @@ -75,29 +78,6 @@ stochastic scaling at each Runge-Kutta stage.
| `rk4_ti_solve` | 4 | 4 | invariant | Kasdin (1995) |
| `rk4_tv_solve` | 4 | 4 | variant | Kasdin (1995) |

!!! tip "Choosing a solver"
For exploratory work, start with `rk1_ti_solve` (Euler-Maruyama).
For production accuracy, prefer `rk4_ti_solve` or `rk4_tv_solve` — higher-order
methods converge faster and yield smoother trajectories for a given step count.

## Quick example

```python
import numpy as np
import sdepack
## References

# Ornstein-Uhlenbeck process: dX = -X dt + dW
x = np.zeros(1001, dtype=np.float64)
sdepack.rk4_ti_solve(
lambda x: -x, # drift F(X) = -X
lambda x: 1.0, # diffusion G(X) = 1
x,
0.0, # t0
10.0, # tn
1.0, # x0
1000, # n steps
1.0, # Q (noise intensity)
42, # seed
)
print(x[:6]) # first few values of the trajectory
```
- N. J. Kasdin, 1995, *Runge-Kutta algorithm for the numerical integration of stochastic differential equations*, Journal of Guidance, Control, and Dynamics, Vol. 18, No. 1, pp. 114–120.
133 changes: 83 additions & 50 deletions docs/installation.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,69 @@
# Installation

`sdepack` is distributed as a compiled wheel on PyPI and can also be installed
from source via GitHub.
`sdepack` can be installed from PyPI, conda-forge, or directly from git.

---
## [PyPI](https://pypi.org/project/sdepack)

## Prerequisites
For using the PyPI package in your project, you can update your configuration file by adding
the following snippet.

- **Python 3.10+**
- **NumPy** (installed automatically as a dependency)
=== "pyproject.toml"

For source builds you additionally need:
```toml
[project.dependencies]
sdepack = "*" # (1)!
```

- A Fortran compiler (`gfortran` recommended)
- `meson` and `meson-python` build system
- `numpy` (for `f2py` compilation)
1. Specifying a version is recommended

## PyPI (recommended)
=== "requirements.txt"

```
sdepack>=0.1.0
```

### pip

```bash
pip install --upgrade sdepack
```
=== "Installation for user"

### pyproject.toml dependency
```bash
pip install --upgrade --user sdepack # (1)!
```

```toml
[project]
dependencies = [
"sdepack"
]
```
1. You may need to use `pip3` instead of `pip` depending on your Python installation.

### requirements.txt
=== "Installation in virtual environment"

```text
sdepack
```
```bash
python -m venv .venv
source .venv/bin/activate
pip install --require-virtualenv --upgrade sdepack # (1)!
```

1. You may need to use `pip3` instead of `pip` depending on your Python installation.

!!! note
Command to activate the virtual env depends on your platform and shell. [More info](https://docs.python.org/3/library/venv.html#how-venvs-work)

## Package managers
### pipenv

pipenv install sdepack

### uv

```bash
# Add to a uv project
uv add sdepack
=== "Adding to uv project"

# Or install into the current environment
uv pip install sdepack
```
```bash
uv add sdepack
uv sync
```

### pipenv
=== "Installing to uv environment"

```bash
pipenv install sdepack
```
```bash
uv venv
uv pip install sdepack
```

### poetry

Expand All @@ -75,31 +83,59 @@ pdm add sdepack
hatch add sdepack
```

## Installing from source (GitHub)
## [conda-forge](https://anaconda.org/conda-forge/sdepack)

You can update your environment spec file by adding the following snippet.

```yaml title="environment.yml"
channels:
- conda-forge
dependencies:
- pip
- pip:
- sdepack # (1)!
```

1. Specifying a version is recommended

Installation can be done using the updated environment spec file.

=== "conda"

```bash
conda env update --file environment.yml
```

=== "micromamba"

```bash
micromamba env update --file environment.yml
```

!!! note
Replace `environment.yml` with your actual environment spec file name if it's different.

## [git](https://github.com/eggzec/sdepack)

Install the latest development version directly from the repository:

```bash
pip install --upgrade "git+https://github.com/eggzec/sdepack.git#egg=sdepack"
```

### Building locally
### Building from source

Clone and build from source if you want to modify the Fortran code or test
local changes:
Clone and build from source if you want to modify the Fortran code or test local changes:

```bash
git clone https://github.com/eggzec/sdepack.git
cd sdepack
pip install -e .
```

This invokes the `meson` build system to compile the Fortran sources via
`f2py` and install the resulting extension module in development mode.

!!! warning "Fortran compiler required"
Source builds require a working Fortran compiler. On most Linux
distributions install `gfortran`:
Source builds require a working Fortran compiler (`gfortran` recommended) as well as
`meson` and `meson-python`.

```bash
# Debian/Ubuntu
Expand Down Expand Up @@ -129,8 +165,5 @@ print("sdepack is working! Trajectory:", x)

## Dependencies

| Package | Purpose |
|---|---|
| `numpy` | Array handling, `f2py` integration |

No other runtime dependencies are required.
- Python >= 3.10
- [numpy](https://pypi.org/project/numpy)
16 changes: 11 additions & 5 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ theme:
- content.code.copy

markdown_extensions:
- admonition
- attr_list
- md_in_html
- tables
- fenced_code
- toc:
permalink: true
title: Page contents
- admonition
- pymdownx.details
- pymdownx.superfences
- pymdownx.highlight
- pymdownx.highlight:
pygments_lang_class: true
- pymdownx.tabbed:
alternate_style: true
- pymdownx.arithmatex:
generic: true
- toc:
permalink: true

extra_javascript:
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
Expand Down
Loading