{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f225380f",
   "metadata": {},
   "source": [
    "# Maxwell-Boltzmann distribution\n",
    "\n",
    "Plot the Maxwell-Boltzmann distribution\n",
    "\n",
    "$$ f(v_x) = \\left ( \\frac{m}{2 \\pi kT} \\right )^{1/2} e^{-mv_x^2/2kT} $$\n",
    "\n",
    "Eric Furst  \n",
    "September 2023\n",
    "\n",
    "Updated:\\\n",
    "October 2024 to include velocity averages and comparision to kT"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28594ad2",
   "metadata": {},
   "source": [
    "As ususal, we import the *numpy* and *matplotlib* libraries. We'll also use the *SciPy* constants library."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8ba8e9f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from scipy import constants"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9cacacf5",
   "metadata": {},
   "source": [
    "We'll plot the distribution over a range of velocities. By equiparition, the average (mean-squared) velocity is \n",
    "$$ \\langle v_x^2 \\rangle = \\frac{kT}{m} $$\n",
    "\n",
    "When the exponential term is on the order of \n",
    "$$ \\frac{m v_x^2}{2kT} \\sim \\mathcal{O}(5) $$\n",
    "then the exponential function will be close to zero. So, we should choose a range of velocities \n",
    "$$ 0 \\le v_x \\le \\left ( \\frac{10kT}{m} \\right )^{1/2}$$\n",
    "or so."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f3d2f917",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Specify mass (in kg) and temperature (in K)\n",
    "# This is the mass for nitrogen\n",
    "\n",
    "m = 14.007/1000/constants.N_A\n",
    "T = 298\n",
    "kT = constants.k*T\n",
    "\n",
    "# Make a range of velocities\n",
    "vx = np.linspace(0,np.sqrt(10*kT/m),100)\n",
    "\n",
    "# Calculate the distribution\n",
    "fvx = np.sqrt(m/2/np.pi/kT)*np.exp(-m*vx**2/2/kT)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4133d8cd",
   "metadata": {},
   "source": [
    "Now we can plot the function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7579e5f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Maxwell-Boltzmann Distribution')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 32956 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the data\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "ax.plot(vx, fvx)\n",
    "plt.xlabel('vx (m/s)')\n",
    "plt.ylabel('f(vx)')\n",
    "plt.title('Maxwell-Boltzmann Distribution')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db1cf3ea",
   "metadata": {},
   "source": [
    "We should plot this at a few different temperatures!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "0843f5d1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Maxwell-Boltzmann Distribution')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 66944 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots()\n",
    "\n",
    "for T in range(50, 350, 50) :\n",
    "    kT = constants.k*T\n",
    "    vx = np.linspace(0,1200,100)\n",
    "    fvx = np.sqrt(m/2/np.pi/kT)*np.exp(-m*vx**2/2/kT)\n",
    "    ax.plot(vx, fvx,label='{} K'.format(T))\n",
    "\n",
    "plt.legend(frameon=False)\n",
    "plt.xlabel('vx (m/s)')\n",
    "plt.ylabel('f(vx)')\n",
    "plt.title('Maxwell-Boltzmann Distribution')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1be1e27",
   "metadata": {},
   "source": [
    "## Maxwell Distribution of Speed\n",
    "\n",
    "We can do a similar calcuation for the total velocity, or *speed*. The distribution function is\n",
    "\n",
    "$$ f(v_x,v_y,v_z) = \\left ( \\frac{m}{2 \\pi kT} \\right )^{3/2} e^{-mv^2/2kT} $$\n",
    "\n",
    "The probability of observing a velocity $v$ is within\n",
    "\n",
    "$$ f(v)dv = f(v_x, v_y, v_z)dv_xdv_ydv_z $$\n",
    "\n",
    "which is a volume integral represented by a spherical shell (since $v^2 = v_x^2 + v_y^2 +v_z^2$).\n",
    "\n",
    "Thus,\n",
    "\n",
    "$$ f(v)dv = \\int_0^{2\\pi} \\int_0^\\pi \\left ( \\frac{m}{2 \\pi kT} \\right )^{3/2} e^{-mv^2/2kT} v^2 \\sin \\theta d\\phi d\\theta dv $$\n",
    "\n",
    "$$ f(v) = 4\\pi \\left ( \\frac{m}{2 \\pi kT} \\right )^{3/2} v^2 e^{-mv^2/2kT} $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "bbce3bda",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Maxwell Distribution of Speeds')"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 87876 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots()\n",
    "\n",
    "for T in range(20, 300, 40) :\n",
    "    kT = constants.k*T\n",
    "    v = np.linspace(0,1200,100)\n",
    "\n",
    "    fvxsq = 4 * np.pi * (np.sqrt(m / (2 * np.pi * kT)))**3 \\\n",
    "        * v**2 * np.exp(-m * v**2 / (2 * kT))\n",
    "\n",
    "    ax.plot(v, fvxsq, label='{} K'.format(T))\n",
    "\n",
    "plt.legend(frameon=False)\n",
    "plt.xlabel('v (m/s)')\n",
    "plt.ylabel('f(v)')\n",
    "plt.title('Maxwell Distribution of Speeds')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6619255d-41ec-4cd4-9da0-321d5fa0ae17",
   "metadata": {},
   "source": [
    "## What is the average velocity and kinetic energy? \n",
    "\n",
    "How does the K.E. compare with kT?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ecd7dfd3-2dcc-4634-a98a-60c33c3a1a7a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "At T = 200 K:\n",
      "\n",
      "The average value of v is 550 m/s\n",
      "m<v>^2/kT = 0.849 m/s\n",
      "\n",
      "The average rms v is: 597 m/s\n",
      "m<v^2>/3kT = 1.000\n"
     ]
    }
   ],
   "source": [
    "from scipy.integrate import quad\n",
    "\n",
    "# Define the function fn_fvxsq\n",
    "# The Maxwell-Boltzmann ditribution\n",
    "def fn_fvxsq(v, m, kT):\n",
    "    factor = 4 * np.pi * (np.sqrt(m / (2 * np.pi * kT)))**3\n",
    "    return factor * v**2 * np.exp(-m * v**2 / (2 * kT))\n",
    "\n",
    "# Average value function <v>\n",
    "def average_value_of_fvx(m, kT):\n",
    "    # Define the limits for integration (0 to infinity)\n",
    "    lower_limit = 0\n",
    "    upper_limit = np.inf\n",
    "\n",
    "    # Numerator: Integral of fvx(v) * v\n",
    "    numerator_v, _ = quad(lambda v: fn_fvxsq(v, m, kT) * v, lower_limit, upper_limit)\n",
    "\n",
    "    # Numerator: Integral of fvx(v) * v * v\n",
    "    numerator_vv, _ = quad(lambda v: fn_fvxsq(v, m, kT) * v * v, lower_limit, upper_limit)\n",
    "\n",
    "    # Denominator: Integral of fvx(v)\n",
    "    denominator, _ = quad(lambda v: fn_fvxsq(v, m, kT), lower_limit, upper_limit)\n",
    "\n",
    "    # Calculate the average value\n",
    "    average_v = numerator_v / denominator\n",
    "    average_vv = numerator_vv / denominator\n",
    "\n",
    "    return average_v, average_vv\n",
    "\n",
    "m = 14.007/1000/constants.N_A\n",
    "T = 200\n",
    "kT = constants.k*T\n",
    "\n",
    "avg_v, avg_vv = average_value_of_fvx(m, kT)\n",
    "\n",
    "print(f\"At T = {T} K:\")\n",
    "print()\n",
    "print(f\"The average value of v is {avg_v:.0f} m/s\")\n",
    "print(f\"m<v>^2/kT = {m*avg_v**2/3/kT:.3f} m/s\")\n",
    "print()\n",
    "print(f\"The average rms v is: {np.sqrt(avg_vv):.0f} m/s\")\n",
    "print(f\"m<v^2>/3kT = {m*avg_vv/3/kT:.3f}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "270cf425-244a-435c-8df8-1f2f0e457249",
   "metadata": {},
   "source": [
    "Notice that we have to use the mean-squared velocity, not the average velocity, in our calculation. The root mean-squared velocity is about 10% higher than the average velocity."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b06bd12-f93c-4cb0-91f8-0072c96733fa",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
