{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Temperature Conversions\n",
    "\n",
    "[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/chaobrain/brainunit/blob/master/docs/physical_units/temperature.ipynb)\n",
    "[![Open in Kaggle](https://kaggle.com/static/images/open-in-kaggle.svg)](https://kaggle.com/kernels/welcome?src=https://github.com/chaobrain/brainunit/blob/master/docs/physical_units/temperature.ipynb)\n",
    "\n",
    "Temperature is special in unit systems because Celsius is an *offset* scale — \n",
    "0 degrees C is not \"zero temperature.\" brainunit uses Kelvin as the base temperature\n",
    "unit and provides conversion functions for Celsius."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.464342Z",
     "start_time": "2026-03-04T15:11:04.593288200Z"
    }
   },
   "source": [
    "import brainunit as u\n",
    "import jax.numpy as jnp"
   ],
   "outputs": [],
   "execution_count": 1
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Kelvin — The Base Temperature Unit\n",
    "\n",
    "In brainunit, `kelvin` (K) is the standard SI temperature unit.\n",
    "All temperature `Quantity` objects use kelvin."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.672505800Z",
     "start_time": "2026-03-04T15:11:05.497783400Z"
    }
   },
   "source": [
    "# Create temperature quantities in kelvin\n",
    "room_temp = 293.15 * u.kelvin\n",
    "print('Room temperature:', room_temp)\n",
    "print('Unit:', room_temp.unit)\n",
    "print('Dimension:', room_temp.dim)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Room temperature: 293.15 K\n",
      "Unit: K\n",
      "Dimension: K\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.758282200Z",
     "start_time": "2026-03-04T15:11:05.673825300Z"
    }
   },
   "source": [
    "# Temperature arrays\n",
    "temps = jnp.array([273.15, 293.15, 310.15, 373.15]) * u.kelvin\n",
    "print('Temperature array:', temps)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Temperature array: [273.1499939 293.1499939 310.1499939 373.1499939] K\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.771565700Z",
     "start_time": "2026-03-04T15:11:05.759292Z"
    }
   },
   "source": [
    "# Arithmetic with kelvin quantities\n",
    "delta_T = 10.0 * u.kelvin\n",
    "print('Room temp + 10K:', room_temp + delta_T)\n",
    "print('Temperature difference:', (373.15 * u.kelvin) - room_temp)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Room temp + 10K: 303.15 K\n",
      "Temperature difference: 80. K\n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Celsius to Kelvin: `celsius2kelvin()`\n",
    "\n",
    "Converts a plain numeric value (degrees Celsius) to a `Quantity` in kelvin.\n",
    "\n",
    "Formula: `K = C + 273.15`"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.782728600Z",
     "start_time": "2026-03-04T15:11:05.772567800Z"
    }
   },
   "source": [
    "# Freezing point of water\n",
    "print('0 C =', u.celsius2kelvin(0.0))\n",
    "\n",
    "# Boiling point of water\n",
    "print('100 C =', u.celsius2kelvin(100.0))\n",
    "\n",
    "# Body temperature\n",
    "print('37 C =', u.celsius2kelvin(37.0))\n",
    "\n",
    "# Absolute zero\n",
    "print('-273.15 C =', u.celsius2kelvin(-273.15))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 C = 273.15 K\n",
      "100 C = 373.15 K\n",
      "37 C = 310.15 K\n",
      "-273.15 C = 0. K\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.858930200Z",
     "start_time": "2026-03-04T15:11:05.783726900Z"
    }
   },
   "source": [
    "# Works with arrays too\n",
    "celsius_values = jnp.array([-40., 0., 20., 37., 100.])\n",
    "kelvin_values = u.celsius2kelvin(celsius_values)\n",
    "print('Celsius:', celsius_values)\n",
    "print('Kelvin:', kelvin_values)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Celsius: [-40.   0.  20.  37. 100.]\n",
      "Kelvin: [233.1499939 273.1499939 293.1499939 310.1499939 373.1499939] K\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.868096Z",
     "start_time": "2026-03-04T15:11:05.858930200Z"
    }
   },
   "source": [
    "# The result is a proper Quantity — use it in further computations\n",
    "T = u.celsius2kelvin(25.0)\n",
    "print('Type:', type(T))\n",
    "print('Mantissa:', T.mantissa)\n",
    "print('Unit:', T.unit)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type: <class 'brainunit.Quantity'>\n",
      "Mantissa: 298.15\n",
      "Unit: K\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Kelvin to Celsius: `kelvin2celsius()`\n",
    "\n",
    "Converts a kelvin `Quantity` to a plain numeric Celsius value.\n",
    "\n",
    "Formula: `C = K - 273.15`"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.879573500Z",
     "start_time": "2026-03-04T15:11:05.868096Z"
    }
   },
   "source": [
    "# Convert kelvin Quantities back to Celsius\n",
    "print('273.15 K =', u.kelvin2celsius(273.15 * u.kelvin), 'C')\n",
    "print('373.15 K =', u.kelvin2celsius(373.15 * u.kelvin), 'C')\n",
    "print('310.15 K =', u.kelvin2celsius(310.15 * u.kelvin), 'C')"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "273.15 K = 0.0 C\n",
      "373.15 K = 100.0 C\n",
      "310.15 K = 37.0 C\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.918168900Z",
     "start_time": "2026-03-04T15:11:05.879573500Z"
    }
   },
   "source": [
    "# With arrays\n",
    "kelvin_arr = jnp.array([233.15, 273.15, 293.15, 310.15, 373.15]) * u.kelvin\n",
    "celsius_arr = u.kelvin2celsius(kelvin_arr)\n",
    "print('Kelvin:', kelvin_arr)\n",
    "print('Celsius:', celsius_arr)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Kelvin: [233.1499939 273.1499939 293.1499939 310.1499939 373.1499939] K\n",
      "Celsius: [-40.   0.  20.  37. 100.]\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.928670500Z",
     "start_time": "2026-03-04T15:11:05.918168900Z"
    }
   },
   "source": [
    "# kelvin2celsius returns a plain array (not a Quantity)\n",
    "result = u.kelvin2celsius(300.0 * u.kelvin)\n",
    "print('Result:', result)\n",
    "print('Type:', type(result))"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Result: 26.850000000000023\n",
      "Type: <class 'float'>\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Error Handling\n",
    "\n",
    "Both functions validate their inputs."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.938015200Z",
     "start_time": "2026-03-04T15:11:05.929669700Z"
    }
   },
   "source": [
    "# celsius2kelvin rejects Quantity inputs (expects plain numbers)\n",
    "try:\n",
    "    u.celsius2kelvin(100.0 * u.kelvin)  # Wrong: passing a Quantity\n",
    "except TypeError as e:\n",
    "    print('celsius2kelvin error:', e)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "celsius2kelvin error: The input value should be not be a Quantity.\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.946006200Z",
     "start_time": "2026-03-04T15:11:05.938015200Z"
    }
   },
   "source": [
    "# kelvin2celsius rejects non-Quantity inputs\n",
    "try:\n",
    "    u.kelvin2celsius(100.0)  # Wrong: passing a plain number\n",
    "except TypeError as e:\n",
    "    print('kelvin2celsius error:', e)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "kelvin2celsius error: The input value should be a Quantity with a temperature unit.\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.955186900Z",
     "start_time": "2026-03-04T15:11:05.946999200Z"
    }
   },
   "source": [
    "# kelvin2celsius rejects wrong dimensions\n",
    "try:\n",
    "    u.kelvin2celsius(100.0 * u.meter)  # Wrong: not a temperature\n",
    "except TypeError as e:\n",
    "    print('kelvin2celsius dim error:', e)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "kelvin2celsius dim error: The input value should be a Quantity with a temperature unit, but got unit m.\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `zero_celsius` Constant\n",
    "\n",
    "brainunit provides `zero_celsius` as a predefined constant — the kelvin value of 0 degrees Celsius."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.979505800Z",
     "start_time": "2026-03-04T15:11:05.956202500Z"
    }
   },
   "source": [
    "print('zero_celsius:', u.constants.zero_celsius)\n",
    "\n",
    "# Use it for manual conversion\n",
    "celsius_25 = 25.0\n",
    "kelvin_25 = celsius_25 * u.kelvin + u.constants.zero_celsius\n",
    "print('25 C in K:', kelvin_25)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "zero_celsius: 273.15 K\n",
      "25 C in K: 298.15 K\n"
     ]
    }
   ],
   "execution_count": 14
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practical Example: Ideal Gas Law\n",
    "\n",
    "Use temperature conversion in a real physics calculation:\n",
    "`PV = nRT`"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:05.993340900Z",
     "start_time": "2026-03-04T15:11:05.980501Z"
    }
   },
   "source": [
    "# Ideal gas law: P = nRT/V\n",
    "R_gas = u.constants.gas  # gas constant\n",
    "print('Gas constant R:', R_gas)\n",
    "\n",
    "n = 1.0  # 1 mole\n",
    "V = 0.0224 * u.meter**3  # ~22.4 liters\n",
    "\n",
    "# At different temperatures (in Celsius)\n",
    "for temp_c in [0.0, 25.0, 100.0]:\n",
    "    T = u.celsius2kelvin(temp_c)\n",
    "    P = n * R_gas * T / V\n",
    "    print(f'  T = {temp_c} C ({T}) -> P = {P}')"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Gas constant R: 8.314463 J / (K * mol)\n",
      "  T = 0.0 C (273.15 K) -> P = 101388.19 m^-1 kg s^-2 mol^-1\n",
      "  T = 25.0 C (298.15 K) -> P = 110667.73 m^-1 kg s^-2 mol^-1\n",
      "  T = 100.0 C (373.15 K) -> P = 138506.33 m^-1 kg s^-2 mol^-1\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Roundtrip Conversion"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2026-03-04T15:11:06.007267500Z",
     "start_time": "2026-03-04T15:11:05.993340900Z"
    }
   },
   "source": [
    "# Verify roundtrip: C -> K -> C\n",
    "original = 37.0\n",
    "in_kelvin = u.celsius2kelvin(original)\n",
    "back_to_celsius = u.kelvin2celsius(in_kelvin)\n",
    "print(f'{original} C -> {in_kelvin} -> {back_to_celsius} C')"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "37.0 C -> 310.15 K -> 37.0 C\n"
     ]
    }
   ],
   "execution_count": 16
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Summary\n",
    "\n",
    "| Function | Input | Output | Formula |\n",
    "|----------|-------|--------|---------|\n",
    "| `celsius2kelvin(x)` | Plain number (Celsius) | `Quantity` (kelvin) | K = C + 273.15 |\n",
    "| `kelvin2celsius(q)` | `Quantity` (kelvin) | Plain number (Celsius) | C = K - 273.15 |\n",
    "| `constants.zero_celsius` | — | `273.15 K` | — |"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
