Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0a53860
switch to rye for dependency management
johnaparker Nov 20, 2023
afd5170
ruff formatter
johnaparker Nov 20, 2023
6f34a8a
pre-commit
johnaparker Nov 20, 2023
fb3b037
github action updated for rye
johnaparker Nov 20, 2023
1d443a1
bunch of type checks
johnaparker Nov 20, 2023
ca760db
bunch of type checks (2)
johnaparker Nov 20, 2023
a5f522d
github action 3.12
johnaparker Nov 20, 2023
0c9833b
fplanck version 1.0.0
johnaparker Nov 20, 2023
32779c6
formatting changes
johnaparker Feb 20, 2024
6bc0bc9
ruff format
johnaparker Feb 20, 2024
ba7c05d
ruff --fix
johnaparker Feb 20, 2024
6310e04
migrate to uv
johnaparker Oct 9, 2025
f4a8ddf
claude md
johnaparker Oct 9, 2025
88c73ce
ruff unsafe fixes
johnaparker Oct 9, 2025
450ce4a
ruff passing
johnaparker Oct 9, 2025
d4d838e
ty checks in src/
johnaparker Oct 9, 2025
d51eb13
examples type checking
johnaparker Oct 9, 2025
2de5270
remove brownian example
johnaparker Oct 9, 2025
f64019c
type checking tests
johnaparker Oct 9, 2025
efcba84
expm fix
johnaparker Oct 9, 2025
171c3cc
working ring example
johnaparker Oct 9, 2025
d32e930
passing tests using numerical stability
johnaparker Oct 9, 2025
57f922d
example: legend + resolution
johnaparker Oct 9, 2025
572117a
matplotlib dep
johnaparker Oct 9, 2025
7e29fc6
bump version 1.0.1
johnaparker Oct 9, 2025
7fe9f78
move examples to src
johnaparker Oct 9, 2025
85a6c7b
bump version 1.0.2
johnaparker Oct 9, 2025
9712735
README updates
johnaparker Oct 9, 2025
7897cda
Readme updated with uvx
johnaparker Oct 9, 2025
df4e170
pre-commit
johnaparker Oct 9, 2025
db5a83e
updated pr gh workflow
johnaparker Oct 9, 2025
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
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
watch_file uv.lock
uv sync
export VIRTUAL_ENV="$PWD/.venv"
PATH_add "$VIRTUAL_ENV/bin"
31 changes: 0 additions & 31 deletions .github/workflows/github-actions-pytest.yml

This file was deleted.

51 changes: 51 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: tests

on: [pull_request]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.12"

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: uv sync

- name: Run pre-commit hooks
run: uv run pre-commit run --all-files

build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install project
run: uv sync

- name: Test with pytest
run: uv run pytest tests
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ __pycache__
build/
dist/
play/
.venv/

# latex files
*.aux
Expand All @@ -12,3 +13,6 @@ play/
*.log
*.pdf
*.gz

# llm
.claude
14 changes: 14 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
repos:
- repo: local
hooks:
- name: lint (ruff)
id: lint
language: system
entry: ruff check
types: [python]
args: [ --fix ]
- name: format (ruff)
id: format
language: system
types: [python]
entry: ruff format
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
89 changes: 89 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

FPlanck is a Python library for numerically solving the Fokker-Planck partial differential equation (also known as the Smoluchowski equation) in N dimensions using a matrix numerical method. The implementation is based on the paper "Physically consistent numerical solver for time-dependent Fokker-Planck equations" by V. Holubec, K. Kroy, and S. Steffenoni.

## Development Setup

This project uses `uv` for package and dependency management:

- **Install dependencies**: `uv sync`
- **Run tests**: `uv run pytest`
- **Run a specific test**: `uv run pytest tests/test_harmonic_potential.py::test_harmonic_1d_steady_state`
- **Lint with ruff**: `uv run ruff check .`
- **Format with ruff**: `uv run ruff format .`
- **Auto-fix linting issues**: `uv run ruff check --fix .`
- **Type check with ty**: `ty check`
- Disable specific type checking rules inline with comments: `# ty: ignore[unsupported-operator]`
- This is useful for types that are difficult to handle (e.g., many numpy, pandas types)

The project uses pre-commit hooks (ruff linter and formatter). When developing, ensure ruff formatting and linting passes before committing.

## Core Architecture

### Solver Structure (src/fplanck/solver.py)

The `FokkerPlanck` class is the central solver that:

1. **Builds a spatial grid** based on extent and resolution parameters
2. **Computes transition rates** (Rt and Lt arrays) for each dimension based on:
- Conservative forces (from potential gradients)
- Non-conservative forces (from force fields)
- Diffusion coefficients
- Boundary conditions
3. **Constructs a master equation matrix** as a sparse matrix representing the time evolution operator
4. **Provides solving methods**:
- `steady_state()`: computes steady-state probability distribution using eigenvalue decomposition
- `propagate()`: evolves an initial distribution forward in time using matrix exponential
- `propagate_interval()`: propagates over a time interval returning distributions at each step
- `probability_current()`: calculates probability currents from a given distribution

### Key Concepts

**Boundary Conditions** (src/fplanck/utility.py):
- `Boundary.REFLECTING`: particles bounce at edges (transition rates set to 0 at boundaries)
- `Boundary.PERIODIC`: particles wrap around (transition rates connect opposite edges)
- Boundaries can be mixed across different dimensions

**Forces and Potentials**:
- The solver accepts both `potential` (conservative field) and `force` (non-conservative field)
- Potentials are converted to forces via gradient calculation
- Both contribute to the transition rate matrices (Rt and Lt)
- Pre-defined convenience functions in `potentials.py` and `forces.py`

**Probability Functions** (src/fplanck/functions.py):
- Initial conditions are specified as callable functions of grid coordinates
- Common PDFs: `delta_function()`, `gaussian_pdf()`, `uniform_pdf()`
- The `combine()` utility (src/fplanck/utility.py) allows composing multiple functions

### Module Organization

- **src/fplanck/solver.py**: Main `FokkerPlanck` solver class
- **src/fplanck/utility.py**: Boundary enum, vector utilities, function composition
- **src/fplanck/potentials.py**: Pre-defined potential functions (harmonic, gaussian, uniform, from data)
- **src/fplanck/forces.py**: Pre-defined force functions (from data)
- **src/fplanck/functions.py**: Pre-defined probability distribution functions
- **examples/**: Demonstration scripts showing various physical scenarios
- **tests/**: Unit tests validating against analytical solutions

### Testing Strategy

Tests validate numerical solutions against known analytical solutions for:
- 1D harmonic oscillator (steady-state and time-evolved)
- Free space diffusion
- Driven periodic systems
- Uniform force fields

Tests use `np.allclose()` with appropriate tolerances to account for discretization errors. Time limits of propagation should converge to steady-state solutions.

## Important Implementation Details

- The solver uses sparse matrix representation (scipy.sparse.csc_matrix) for memory efficiency
- Transition rates (Rt/Lt) are computed using exponentials of potential differences to ensure physical consistency
- Grid is centered around origin by default (average of each axis is adjusted to zero)
- Resolution can be scalar (same for all dimensions) or vector (different per dimension)
- Temperature, drag, and boundary conditions can also be specified per-dimension
- The master matrix encodes the full time-evolution dynamics of the system
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,48 @@
FPlanck is a Python library for numerically solving the Fokker-Planck partial differential equation (also known as the Smoluchowski equation) in N dimensions using a matrix numerical method:

<p align="center">
<img src="https://github.com/johnaparker/fplanck/blob/master/img/fokker_planck.svg">
<img src="https://github.com/johnaparker/fplanck/blob/master/img/FokkerPlanck.svg">
</p>

The method is based on the paper *"Physically consistent numerical solver for time-dependent Fokker-Planck equations"* by V. Holubec, K. Kroy, and S. Steffenoni, available on [arXiv](https://arxiv.org/pdf/1804.01285.pdf) and published in [APS](https://journals.aps.org/pre/abstract/10.1103/PhysRevE.99.032117).

## Features
+ Can specify an external potential (conservative) and force field (non-conservative) in N-dimensions
+ Declare external potentials (conservative) and force fields (non-conservative) in N-dimensions
+ Solve for the steady-state probability distribution and probability currents
+ Propagate any initial probability distribution to the solution at any later time
+ Periodic and reflecting boundary conditions (can be mixed along different dimensions)

## Installation
FPlanck can be installed with pip
## Installation and Usage
```shell
pip install fplanck
```
or conda
```shell
conda install -c japarker fplanck
```

## Examples
![](https://github.com/johnaparker/fplanck/blob/master/img/ratchet.gif)
![](https://github.com/johnaparker/fplanck/blob/master/img/harmonic.gif)
See the [examples](src/fplanck/examples) folder for how to use FPlanck.

Run any of the available [examples](src/fplanck/examples) without explicit installation using `uv`:

**On the left**: a single particle in a titled periodic potential with periodic boundary conditions.
| Command | Description |
|---------|-------------|
| `uvx fplanck free_space` | Free diffusion in 1D with periodic boundary conditions |
| `uvx fplanck harmonic` | 1D harmonic potential with time evolution |
| `uvx fplanck harmonic_2d` | 2D harmonic potential showing restoration to equilibrium |
| `uvx fplanck periodic` | Particle in a periodic cosine potential with reflecting boundaries |
| `uvx fplanck ratchet` | Tilted periodic potential (Brownian ratchet) with periodic boundaries |
| `uvx fplanck ring` | 2D particle driven by non-conservative force field in a ring pattern |
| `uvx fplanck nonuniform_diffusion` | Position-dependent drag coefficient |
| `uvx fplanck tilted_bigaussian` | Double-well potential with linear tilt |


## Demos
![](https://github.com/johnaparker/fplanck/blob/master/img/ratchet.gif)
A single particle in a titled periodic potential with periodic boundary conditions.
The animation shows the time evolution of the probability distribution for the particle location.
The PDF is driven in the positive direction due to the tilted potential.

**On the right**: a single particle in a 2D harmonic potential.
![](https://github.com/johnaparker/fplanck/blob/master/img/harmonic.gif)
A single particle in a 2D harmonic potential.
The particle is initially away from the center of the harmonic well, and over time is restored to the center.

## Usage
See the examples folder for how to use FPlanck.

## License
FPlanck is licensed under the terms of the MIT license.
Expand Down
41 changes: 0 additions & 41 deletions examples/brownian.py

This file was deleted.

41 changes: 0 additions & 41 deletions examples/free_space.py

This file was deleted.

40 changes: 0 additions & 40 deletions examples/harmonic.py

This file was deleted.

Loading