Fokker-Planck Equation
The Fokker-Planck equation (FPE) governs the time evolution of the probability density of a stochastic process. It is the deterministic counterpart to the Langevin equation -- tracking the distribution rather than individual realisations. We derive the Chang-Cooper scheme for numerically solving the FPE with guaranteed positivity and correct steady state.
1. Derivation from the Langevin Equation
Given the Itô SDE:
$$dx = a(x)\,dt + b(x)\,dW_t$$
the probability density \(P(x, t)\) satisfies the Fokker-Planck equation:
$$\frac{\partial P}{\partial t} = -\frac{\partial}{\partial x}\bigl[a(x) P\bigr] + \frac{1}{2}\frac{\partial^2}{\partial x^2}\bigl[b^2(x) P\bigr]$$
Derivation via Characteristic Function
Define the characteristic function \(\phi(k,t) = \langle e^{ikx_t} \rangle\). By Itô's lemma with \(f(x) = e^{ikx}\):
$$d(e^{ikx}) = \left(ika \, e^{ikx} - \frac{k^2 b^2}{2} e^{ikx}\right)dt + ikb \, e^{ikx} \, dW$$
Taking expectations (the \(dW\) term vanishes):
$$\frac{\partial \phi}{\partial t} = \langle ik \, a(x) e^{ikx} \rangle - \frac{k^2}{2}\langle b^2(x) e^{ikx} \rangle$$
Inverse Fourier transforming and using integration by parts twice yields the Fokker-Planck equation. The first term \(-\partial(aP)/\partial x\) is the drift (probability current), and the second \(\frac{1}{2}\partial^2(b^2 P)/\partial x^2\) is the diffusion.
Written in conservation form with probability current \(J\):
$$\frac{\partial P}{\partial t} = -\frac{\partial J}{\partial x}, \qquad J(x,t) = a(x)P - \frac{1}{2}\frac{\partial}{\partial x}\bigl[b^2(x)P\bigr]$$
2. Stationary Solution
Setting \(\partial P / \partial t = 0\) and \(J = 0\) (detailed balance):
$$a(x) P_{\text{st}} = \frac{1}{2}\frac{d}{dx}\bigl[b^2(x) P_{\text{st}}\bigr]$$
This is a first-order ODE. Expanding the right side:
$$a \, P_{\text{st}} = \frac{1}{2}\bigl[2b b' P_{\text{st}} + b^2 P_{\text{st}}'\bigr]$$
Rearranging:
$$\frac{P_{\text{st}}'}{P_{\text{st}}} = \frac{2a - 2bb'}{b^2} = \frac{2a}{b^2} - \frac{2b'}{b}$$
Integrating:
$$\boxed{P_{\text{st}}(x) = \frac{\mathcal{N}}{b^2(x)} \exp\!\left(2\int^x \frac{a(x')}{b^2(x')}\,dx'\right)}$$
where \(\mathcal{N}\) is the normalisation constant. For constant diffusion \(b = \sigma\) and gradient drift \(a(x) = -V'(x)\), this reduces to the Boltzmann distribution \(P_{\text{st}} \propto \exp(-2V/\sigma^2)\).
3. Chang-Cooper Numerical Scheme
Standard finite-difference schemes for the FPE can produce negative probabilities or fail to converge to the correct steady state. The Chang-Cooper scheme (1970) cures both issues by interpolating between upwind and downwind differencing.
Discretise the domain \([x_{\min}, x_{\max}]\) into \(N_x\) cells with spacing \(\Delta x\). The discrete probability current at cell boundary \(j+1/2\) is:
$$J_{j+1/2} = a_{j+1/2}\bigl[(1-\delta_j)P_j + \delta_j P_{j+1}\bigr] - \frac{D_{j+1/2}}{\Delta x}(P_{j+1} - P_j)$$
where \(D_{j+1/2} = b^2_{j+1/2}/2\) and the Chang-Cooper parameter \(\delta_j\) is chosen so that the scheme exactly preserves the stationary distribution. Define:
$$w_j = \frac{a_{j+1/2} \, \Delta x}{D_{j+1/2}}$$
Then the optimal interpolation parameter is:
$$\delta_j = \frac{1}{w_j} - \frac{1}{e^{w_j} - 1}$$
This is the Bernoulli function. When \(w \to 0\),\(\delta \to 1/2\) (central differencing); when \(|w| \gg 1\), it approaches upwind differencing. The time update uses the tridiagonal system:
$$\frac{P_j^{n+1} - P_j^n}{\Delta t} = -\frac{J_{j+1/2} - J_{j-1/2}}{\Delta x}$$
4. Python: Chang-Cooper FPE Solver
We solve the Fokker-Planck equation for the bistable potential and compare the evolving distribution to histograms from Langevin simulations.
Chang-Cooper Fokker-Planck Solver
PythonClick Run to execute the Python code
Code will be executed with Python 3 on the server
5. Fortran: Chang-Cooper with Tridiagonal System
For large-scale problems, a Fortran implementation with the Thomas algorithm provides optimal performance. The tridiagonal solver runs in \(O(N)\) operations.
Thomas Algorithm (Tridiagonal Solver) for Chang-Cooper FPE
PythonClick Run to execute the Python code
Code will be executed with Python 3 on the server