Langevin equation and Brownian motion#

import numpy as np
import matplotlib.pyplot as plt
from numpy.linalg import norm
from scipy.constants import c,epsilon_0,e,physical_constants

%config InlineBackend.figure_format = 'retina' 

Langevin Equation#

Langevin theory provides now an equation of motion for objects whoch are subject to fluctuating forces. In the most general way, Newtons equation of motion is written as

mdvdt=F(t)

and contains on the right side the sum of all forces F acting on a particle. This total force can be separated into

  • a viscous drag force, e.g. 6πηRv for a spherical particle

  • a force coming from and external potential U

  • random fluctuating force ζ due to the collisions with the solvent

With the force arising from an external potential we find the Langevin equation

(Langevin Equation)mdvdt=6πηRvU+ζ(t)

The time dependence of the fluctuating force is not known in detail. Thus we can only refer to the statistical properties (e.g. its moments) when solving the Langevin equation. Therefore also not analytical solution for the position can be written down, only average proerties over an ensemble or over time (given ergodicity).

The first moment (the mean) of the fluctuating force gives

ζ(t)=0

i.e. there is no net force acting on average on the particle considered. Yet the mean velocity of the particle is not zero, v0. Considering the mean velocity at short times, for example, yields

mdvdt=6πηRv

giving

v=v(0)exp(tτmr)

with τmr is a characteristic relaxation time for velocity of brownian particle. We can further continue to derive the mean squared position by taking the scalar product of the Langevin equation with r and neglecting the potential. Taking the ensemble average yields

mddtrv=6πηRrv+mv2

since

rdvdt=ddt(rv)v2

and rζ=0. Using our previous result for the mean squared velocity, i.e. v2=3kBT we obtain after integrating over time

rv=Cexp(tτmr)+kBT2πηR

Using the initial condition r(t=0)=0 this gives

rv=kBT2πηR(1exp(tτmr))

A second integration over time of rv can be carried out using

rv=12ddtr2

and we finally obtain the mean squared displacement

r2=kBTπηR[tτmr(1exp(tτmr))]

This is the mean squared displacement for an Ornstein Uhlenbeck process, a process, which has a persistence for a certain time and then is randomized. It described the transition from the ballistic to diffusive regime for a Brownian particle except that it misses the hydrodynamic memory in the intermediate regime.

t=np.logspace(-15,0,1000)
k_B=1.381e-23 #J/K
T=300 #K
eta=1e-3 #mPa s
R=200e-9 #m
gamma=6*np.pi*eta*R
k=1e-9 #N/m

def MSD(t,taumr):
    return(k_B*T/(np.pi*R)*(t-taumr*(1-np.exp(-t/taumr))))
fig=plt.figure()
plt.ion()
plt.loglog(t,MSD(t,1e-9),label=r"$\tau_{mr}=1e-9$ s")
plt.axvline(x=1e-9,linestyle="--")
plt.xlabel(r"$t$")
plt.ylabel(r"$<r^2(t)$")
plt.legend()
plt.tight_layout()
../_images/884937946a8f14028721d53ce39bf5d427574de4081f59189f13af70ff0f79dc.png

We can look at different limits of the process with respect to the momentum relaxation time, ie.

1) long time limits: tτmr

In this regime, the exponential function has already decayed to zero and we obtain

r2=6Dt

with

D=kBT6πηR

1) short times: tτmr

For short times, we can expand the exponential function up to second order

exp(tτmr)1tτmr+t2τmr2

to obtain for

tτmr(1exp(tτmr))t22τmr

and for the mean squared displacement

r2t2

which is the result we expect for ballistic motion. Between both regimes, the MSD could be complicated as the short time motion starts a hydrodynamic flux in the environment which is influencing the particle motion again. These hydrodynamic memory effects cause the so called long time tails in the mean squared displacement.

Fluctuation-dissipation theorem#

While we so far only know that ζ(t)=0, we also know that there must be a certain magnitude of the random force that is connected to the temperature of the sample. The short time autocorrelation of the noise should be of the type

ζ(t1)ζ(t2)=Aδ(t1t2)

stating the the forces are truly random and only correlated, when the times conincide. We would like to determine the prefactor A now. We can write down the Langevin equation with

ddtv(t)=1τmrv(t)+1mζ(t)

and multiply by exp(t/τmr), which results in

exp(tτmr)ddtv(t)+1τmrexp(tτmr)v(t)=ddt(exp(tτmr)v(t))=exp(tτmr)1mζ(t)

Integrating both sides of the two right parts over time results in

v(t)=v(0)exp(tτmr)+exp(tτmr)1m0texp(tτmr)ζ(t)dt

which is the time evolution of the velocity. To obtain ζ(t1)ζ(t2), we need to calculate the product of the velocity at two times and take the ensemble average. The calculation is essentially a writing exercise which at the end yields three different terms.

The first term contains

v02exp(2tτmr)0

which decays to zero for long times. The second term contains two mixed terms of the type

v0mexp(tτmr)0

which also decay to zero for long times. The last term contains

1m2tdttdtexp(ttτmr)exp(ttτmr)ζ(t)ζ(t)

whcih is the only nonzero term. Inserting our initial assumption ζ(t1)ζ(t2)=Aδ(t1t2) results in the mean squared velocity

v2=A2mtdtexp(2(tt)τmr)=Aτmr2m2

Since the velocity also has to comply with equipartition, i.e.

v2=kBTm=Aτmr2m2

we find

A=2γkBT

with γ=6πηR or

ζ(t1)ζ(t2)=2γkBTδ(t1t2)

which is a very fundamental result. It states that the fluctuating force ζ(t) are related to the viscous forces expressed by the friction coefficient γ. This makes sensse, since the friction forces must dissipate energy into heat. The motion would thus come to a rest if heat and dynamics would be decoupled. The law we obtained is thus stateing the dissipated energy goes back again into kinetic energy. This is the statement of the fluctuation dissipation theorem,

Simulating Langevin dynamics#

import numpy as np

def langevin(z, v, tau, eta, dt):
    # Implements numerical solution by means of the Euler-Maruyama method of the Langevin which is known as an SDE (Stochastic Differential equation)
    # dz = v * dt
    # dv = -1/tau * v * dt + eta dW
    
    dW = np.random.normal(loc = 0, scale = np.sqrt(dt), size = z.shape)

    z_new = z + v*dt
    v_new = v - (1/tau)*v*dt + eta*dW
    
    return z_new, v_new
# Numerical parameters and system coefficients
Np   = 10000
Tmax = 1000
tau  = 10
eta  = 0.01
dt   = 0.1
Nt   = int(Tmax/dt) + 1
# Output interval
Nskip = 10

# Initial values
Z   = np.zeros(Np)
V   = np.zeros(Np)
time, var = [], []

for i in range(1, Nt):

    Z, V = langevin(Z, V, tau, eta, dt)
    # write time and variance every Nskip timesteps
    if i % Nskip == 0:
        time.append(i*dt)
        var.append(np.var(Z))
plt.loglog(time, var)
plt.xlabel(r"$t$")
plt.ylabel(r"$<r^2(t)>$")
plt.legend()
plt.tight_layout()
No artists with labels found to put in legend.  Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
../_images/55d0212464dd4826dddbb833ef0b737a1b3625b205fe8199c792fa238d746de4.png