.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/statphys/stochastic_processes/plot_einstein_brownian_motion_mobility.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_statphys_stochastic_processes_plot_einstein_brownian_motion_mobility.py: Einstein's Brownian motion: diffusion equals mobility times temperature ========================================================================= Einstein's 1905 paper made two separate claims about a suspended particle. First, its random wandering spreads as :math:`\langle\Delta x^2\rangle = 2Dt`. Second, the diffusion coefficient is not a free parameter: it equals the particle's mobility :math:`\mu`, the drift speed per unit applied force, times the temperature, .. math:: D = \mu\,k_BT. Einstein got this by balancing the diffusion current against the drift caused by a force, such as gravity acting on sedimenting particles. The relation ties a fluctuation (the spread) to a response (the drift). Perrin used it with Stokes' :math:`\mu = 1/6\pi\eta a` to count molecules. This example simulates overdamped Brownian particles with :class:`~physicskit.statphys.BrownianMotion`. It measures :math:`D` from the spread and :math:`\mu` from the drift under a pull, for several frictions and temperatures, and checks that :math:`D/(\mu k_BT) = 1` in every case. Units have :math:`k_B = 1`. .. GENERATED FROM PYTHON SOURCE LINES 26-32 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from physicskit.statphys import BrownianMotion, stokes_einstein_diffusion_coefficient .. GENERATED FROM PYTHON SOURCE LINES 33-37 Spread and drift of one driven ensemble --------------------------------------- A constant force :math:`F` moves the cloud's center at :math:`\mu F`. The cloud's width still grows as :math:`2Dt`, exactly as without the force. .. GENERATED FROM PYTHON SOURCE LINES 37-46 .. code-block:: Python gamma, kT, F = 2.0, 1.0, 1.5 bm = BrownianMotion(n_particles=4000, dim=1, gamma=gamma, kT=kT, force=F, seed=1905) t, x = bm.run(t_max=10.0, dt=0.01, n_frames=100) center = x[:, :, 0].mean(axis=1) spread = x[:, :, 0].var(axis=1) print(f"mobility: measured {bm.measured_mobility():.4f}, 1/gamma = {1 / gamma:.4f}") print(f"diffusion: measured {bm.measured_diffusion_coefficient():.4f}, kT/gamma = {kT / gamma:.4f}") .. rst-class:: sphx-glr-script-out .. code-block:: none mobility: measured 0.4953, 1/gamma = 0.5000 diffusion: measured 0.5024, kT/gamma = 0.5000 .. GENERATED FROM PYTHON SOURCE LINES 47-52 The Einstein relation across frictions and temperatures ------------------------------------------------------- Changing the friction changes :math:`D` and :math:`\mu` together. Changing the temperature changes only :math:`D`. Their ratio is always :math:`k_BT`. .. GENERATED FROM PYTHON SOURCE LINES 52-63 .. code-block:: Python rows = [] for g in (0.5, 1.0, 2.0, 4.0): for T in (0.5, 1.0, 2.0): run = BrownianMotion(n_particles=3000, gamma=g, kT=T, force=1.0, seed=int(100 * g + 10 * T)) run.run(t_max=5.0, dt=0.01, n_frames=25) rows.append((g, T, run.measured_diffusion_coefficient(), run.measured_mobility())) rows = np.array(rows) ratio = rows[:, 2] / (rows[:, 3] * rows[:, 1]) print(f"D / (mu kT) over {len(rows)} runs: mean {ratio.mean():.3f}, spread {ratio.std():.3f}") .. rst-class:: sphx-glr-script-out .. code-block:: none D / (mu kT) over 12 runs: mean 1.007, spread 0.022 .. GENERATED FROM PYTHON SOURCE LINES 64-69 Perrin's numbers ---------------- For a 0.5 micron bead in water at 20 C, the Stokes-Einstein coefficient is a fraction of a square micron per second, so it takes seconds to wander a micron: exactly the scale Perrin followed under his microscope. .. GENERATED FROM PYTHON SOURCE LINES 69-100 .. code-block:: Python D_bead = stokes_einstein_diffusion_coefficient(1.380649e-23 * 293.15, 1.0e-3, 0.5e-6) print(f"Stokes-Einstein D for a 0.5 um bead in water: {D_bead * 1e12:.3f} um^2/s") fig, axes = plt.subplots(1, 3, figsize=(15, 4.3)) for i in range(12): axes[0].plot(t, x[:, i, 0], lw=0.7) axes[0].plot(t, F / gamma * t, "k--", lw=1.5, label=r"drift $\mu F t$") axes[0].set_xlabel("t") axes[0].set_ylabel("x") axes[0].set_title("driven Brownian particles") axes[0].legend() axes[1].plot(t, spread, color="steelblue", label=r"Var$[x(t)]$") axes[1].plot(t, 2 * kT / gamma * t, "k--", lw=1, label=r"$2Dt$, $D = k_BT/\gamma$") axes[1].plot(t, center - F / gamma * t, color="firebrick", label=r"$\langle x\rangle - \mu F t$") axes[1].set_xlabel("t") axes[1].set_title("spread grows as 2Dt; the drift is separate") axes[1].legend() sc = axes[2].scatter(rows[:, 3] * rows[:, 1], rows[:, 2], c=rows[:, 1], cmap="viridis", s=50, edgecolors="k") line = np.linspace(0, (rows[:, 3] * rows[:, 1]).max() * 1.05, 10) axes[2].plot(line, line, "k--", lw=1, label=r"$D = \mu k_BT$") axes[2].set_xlabel(r"$\mu\,k_BT$ (mobility from drift)") axes[2].set_ylabel(r"$D$ (from spread)") axes[2].set_title("Einstein relation, 12 runs") fig.colorbar(sc, ax=axes[2], label=r"$k_BT$") axes[2].legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/statphys/stochastic_processes/images/sphx_glr_plot_einstein_brownian_motion_mobility_001.png :alt: driven Brownian particles, spread grows as 2Dt; the drift is separate, Einstein relation, 12 runs :srcset: /api/gallery/statphys/stochastic_processes/images/sphx_glr_plot_einstein_brownian_motion_mobility_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Stokes-Einstein D for a 0.5 um bead in water: 0.429 um^2/s .. GENERATED FROM PYTHON SOURCE LINES 101-105 Check ----- mu = 1/gamma, D = kT/gamma, so D = mu kT for every friction and temperature (Einstein 1905); Stokes-Einstein for a 0.5 um bead in water. .. GENERATED FROM PYTHON SOURCE LINES 105-109 .. code-block:: Python assert abs(bm.measured_mobility() * gamma - 1) < 0.03 assert abs(bm.measured_diffusion_coefficient() / (kT / gamma) - 1) < 0.03 assert abs(ratio.mean() - 1) < 0.03 and ratio.std() < 0.05 assert abs(D_bead - 1.380649e-23 * 293.15 / (6 * np.pi * 1.0e-3 * 0.5e-6)) < 1e-18 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.462 seconds) .. _sphx_glr_download_api_gallery_statphys_stochastic_processes_plot_einstein_brownian_motion_mobility.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_einstein_brownian_motion_mobility.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_einstein_brownian_motion_mobility.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_einstein_brownian_motion_mobility.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_