{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "62b21eed-fcab-4ad8-be9a-438dde08af5d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "# Path to the root directory of the repository\n",
    "root_dir = Path().resolve().parent\n",
    "sys.path.append(str(root_dir / 'src' / 'python'))\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pybamm\n",
    "import dandeliion.client as dandeliion\n",
    "\n",
    "# The following lines enable logging output in this notebook\n",
    "import logging\n",
    "logging.basicConfig(stream=sys.stdout, level=logging.INFO)\n",
    "\n",
    "# check if pybamm was detected\n",
    "dandeliion.__has_pybamm__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "160c7ba0-1205-4a06-bdc6-4d4c64102245",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.1'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dandeliion.__version__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "160c7ba0-1205-4a06-bdc6-4d4c64102245",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.0.0rc2'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dandeliion.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b38282b-c158-4def-bc9a-f5d565e82299",
   "metadata": {},
   "source": [
    "### Authentication\n",
    "One of the ways to define the simulator object can be the following:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "424cfefd-19b2-4e2a-83dd-a306ead4ff98",
   "metadata": {},
   "outputs": [],
   "source": [
    "api_url = Path(\"/tmp/test_params.json\")\n",
    "api_key = \"some_hash\"\n",
    "\n",
    "simulator = dandeliion.Simulator(api_url, api_key)\n",
    "\n",
    "# The following sets up a mock simulator (to be used instead of actual simulator for testing)\n",
    "sys.path.append(str(root_dir / 'tests' / 'python' / 'dandeliion' / 'client'))\n",
    "\n",
    "from mock_simulator import MockSimulator\n",
    "simulator = MockSimulator(api_url, api_key)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec0b6b20-bf68-4e00-bcb9-49f6987b47bd",
   "metadata": {},
   "source": [
    "### Parameters\n",
    "A valid BPX file with battery cell parameters (json-file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8fe2f5ef-1c2d-4259-8e45-ce592a122b91",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Can be a file or already read-in valid BPX as dict or BPX object\n",
    "params = root_dir / 'examples' / 'AE_gen1_BPX.json'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "251b4538-abf6-438b-b2f4-ae0b6b433378",
   "metadata": {},
   "source": [
    "### Experiment\n",
    "PyBaMM Experiment object, for example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "041b9b60-c797-47c8-982c-6f78b3526929",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = np.linspace(0, 1, 60)\n",
    "sin_t = 0.5 * np.sin(2 * np.pi * t)\n",
    "drive_cycle_power = np.column_stack([t, sin_t])\n",
    "    \n",
    "experiment = dandeliion.Experiment(\n",
    "    [\n",
    "        (\n",
    "            \"Discharge at 6 A for 100 seconds\",\n",
    "            \"Rest for 10 seconds\",\n",
    "            \"Charge at 1 A for 10 seconds\",\n",
    "        ),\n",
    "        (\n",
    "            \"Discharge at 1 A for 20 seconds\",\n",
    "            \"Rest for 10 seconds\",\n",
    "            \"Charge at 1 A for 20 seconds\",\n",
    "        ),\n",
    "        pybamm.step.power(drive_cycle_power),\n",
    "    ] * 2,\n",
    "    period=\"1 second\",  # Optional\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abb95e28-8293-49b4-87ed-6739f39ca65a",
   "metadata": {},
   "source": [
    "### Additional model/backend-specific parameters\n",
    "A dictionary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "55c1d753-029a-44e6-8a6c-5fdf34a2a1b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "extra_params = {}\n",
    "\n",
    "# Number of mesh points in PyBaMM format (default is 16 mesh points everywhere):\n",
    "extra_params['Mesh'] = {\"x_n\": 16, \"x_s\": 8, \"x_p\": 16, \"r_n\": 16, \"r_p\": 16}\n",
    "\n",
    "# Initial state of charge (default is 1):\n",
    "extra_params['Initial SOC'] = 1.0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "709bd5a4-f0b0-40c5-95d9-88d3aa35438a",
   "metadata": {},
   "source": [
    "### Calculating solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d22442eb-c0bf-41bc-b9ee-25d19800d1d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:mock_simulator:Submitted parameters written to file: /tmp/test_params.json\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/maximedeckers/opt/anaconda3/envs/dev-env/lib/python3.9/site-packages/pydantic/_internal/_decorators_v1.py:171: UserWarning: The minimum voltage computed from the STO limits (2.4988861558265327 V) is less than the lower voltage cut-off (2.5 V) with the absolute tolerance v_tol = 0.001 V\n",
      "  model_dict_new = validator(model_dict)\n"
     ]
    }
   ],
   "source": [
    "solution = dandeliion.solve(\n",
    "    simulator=simulator,\n",
    "    params=params,\n",
    "    experiment=experiment,  # Optional, default is 1C discharge. Translates into the \"DandeLiion: Experiment\" section\n",
    "    is_blocking=True, \n",
    "    extra_params=extra_params\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "987aa8e4-98c2-4b1e-8e16-b38f49a31241",
   "metadata": {},
   "outputs": [],
   "source": [
    "solution._data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51db6e34-b7ed-4ca7-ac5c-0cc06d8faf68",
   "metadata": {},
   "source": [
    "### Accessing the log file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "412b09ce-dc47-45e6-8319-f53bdcf70f8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(solution.log)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51db6e34-b7ed-4ca7-ac5c-0cc06d8faf68",
   "metadata": {},
   "source": [
    "### Accessing the log file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "412b09ce-dc47-45e6-8319-f53bdcf70f8d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2025-04-30 14:04:31.497] [info] Starting dandeliion-models v0.1.0...\n",
      "[2025-04-30 14:04:31.497] [info] Parsing input JSON file parameters.json...\n",
      "[2025-04-30 14:04:31.499] [info] Input JSON file parsing time: 2.054 ms\n",
      "[2025-04-30 14:04:31.499] [info] Initialising simulation parameters...\n",
      "[2025-04-30 14:04:31.500] [info] Title: About:Energy Gen1 Demo 21700 NMC811|graphite 5 Ah cell\n",
      "[2025-04-30 14:04:31.500] [info] Model: DFN\n",
      "[2025-04-30 14:04:31.508] [info] Thermal model: Isothermal\n",
      "[2025-04-30 14:04:31.508] [info] Found DandeLiion Experiment...\n",
      "[2025-04-30 14:04:31.508] [info] Number of instructions to parse: 12\n",
      "[2025-04-30 14:04:31.508] [info] Solver mode: Fast (default)\n",
      "[2025-04-30 14:04:31.508] [info] Simulation parameters initialisation time: 8.559 ms\n",
      "[2025-04-30 14:04:31.508] [info] Starting the simulation...\n",
      "[2025-04-30 14:04:31.508] [info] Computational mesh: 15x15 + 7 + 15x15 finite volumes\n",
      "[2025-04-30 14:04:31.508] [info] Total number of equations: 588\n",
      "[2025-04-30 14:04:31.508] [info] Updating inconsistent initial conditions...\n",
      "[2025-04-30 14:04:31.511] [info] Initial conditions settled in: 2.396 ms\n",
      "[2025-04-30 14:04:31.511] [info] Instruction #1 of 12: Discharge at 6 [A] for 100 [s]...\n",
      "[2025-04-30 14:04:31.559] [info] - Completed in 48.543 ms. Charge/discharge time: 100.000 s\n",
      "[2025-04-30 14:04:31.559] [info] Instruction #2 of 12: Rest for 10 [s]...\n",
      "[2025-04-30 14:04:31.565] [info] - Completed in 6.114 ms. Charge/discharge time: 110.000 s\n",
      "[2025-04-30 14:04:31.565] [info] Instruction #3 of 12: Charge at 1 [A] for 10 [s]...\n",
      "[2025-04-30 14:04:31.572] [info] - Completed in 6.358 ms. Charge/discharge time: 120.000 s\n",
      "[2025-04-30 14:04:31.572] [info] Instruction #4 of 12: Discharge at 1 [A] for 20 [s]...\n",
      "[2025-04-30 14:04:31.581] [info] - Completed in 9.523 ms. Charge/discharge time: 140.000 s\n",
      "[2025-04-30 14:04:31.581] [info] Instruction #5 of 12: Rest for 10 [s]...\n",
      "[2025-04-30 14:04:31.587] [info] - Completed in 5.427 ms. Charge/discharge time: 150.000 s\n",
      "[2025-04-30 14:04:31.587] [info] Instruction #6 of 12: Charge at 1 [A] for 20 [s]...\n",
      "[2025-04-30 14:04:31.596] [info] - Completed in 9.815 ms. Charge/discharge time: 170.000 s\n",
      "[2025-04-30 14:04:31.596] [info] Instruction #7 of 12: Discharge at 6 [A] for 100 [s]...\n",
      "[2025-04-30 14:04:31.630] [info] - Completed in 33.864 ms. Charge/discharge time: 270.000 s\n",
      "[2025-04-30 14:04:31.630] [info] Instruction #8 of 12: Rest for 10 [s]...\n",
      "[2025-04-30 14:04:31.636] [info] - Completed in 5.740 ms. Charge/discharge time: 280.000 s\n",
      "[2025-04-30 14:04:31.636] [info] Instruction #9 of 12: Charge at 1 [A] for 10 [s]...\n",
      "[2025-04-30 14:04:31.641] [info] - Completed in 5.393 ms. Charge/discharge time: 290.000 s\n",
      "[2025-04-30 14:04:31.641] [info] Instruction #10 of 12: Discharge at 1 [A] for 20 [s]...\n",
      "[2025-04-30 14:04:31.650] [info] - Completed in 9.069 ms. Charge/discharge time: 310.000 s\n",
      "[2025-04-30 14:04:31.650] [info] Instruction #11 of 12: Rest for 10 [s]...\n",
      "[2025-04-30 14:04:31.656] [info] - Completed in 5.197 ms. Charge/discharge time: 320.000 s\n",
      "[2025-04-30 14:04:31.656] [info] Instruction #12 of 12: Charge at 1 [A] for 20 [s]...\n",
      "[2025-04-30 14:04:31.665] [info] - Completed in 9.291 ms. Charge/discharge time: 340.000 s\n",
      "[2025-04-30 14:04:31.665] [info] Simulation completed successfully\n",
      "[2025-04-30 14:04:31.665] [info] Simulation time: 156.849 ms\n",
      "[2025-04-30 14:04:31.665] [info] Writing the output to output.json...\n",
      "[2025-04-30 14:04:31.668] [info] Output JSON file writing time: 3.106 ms\n",
      "[2025-04-30 14:04:31.668] [info] Total time: 170.714 ms\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(solution.log)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3c7b5e7-e0e4-44d9-ba44-bd978e8974fb",
   "metadata": {},
   "source": [
    "### Results\n",
    "Print all available keys in the solution object.\n",
    "Here method `keys()` is used to get all available keys in the solution object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf329a1e-fd4f-47a8-81f3-4e3130804616",
   "metadata": {},
   "outputs": [],
   "source": [
    "for key in sorted(solution.keys()):\n",
    "    print(key)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84abbcab-168c-4175-8f3e-9a9555857f30",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Print the final values of time, voltage, and temperature\n",
    "print(f\"Final time [s]: {solution['Time [s]'][-1]}\")\n",
    "print(f\"Final voltage [V]: {solution['Voltage [V]'][-1]}\")\n",
    "print(f\"Final temperature [K]: {solution['Temperature [K]'][-1]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ac018b7-b201-466c-adef-0aff6e624ab1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot current and voltage vs time.\n",
    "# Here we access scalar values vs time.\n",
    "fig, axs = plt.subplots(2, 1, figsize=(10, 8))\n",
    "axs[0].plot(solution[\"Time [s]\"], solution[\"Current [A]\"], label=\"Dandeliion\")\n",
    "axs[0].set_xlabel(\"time [s]\")\n",
    "axs[0].set_title(\"Current [A]\")\n",
    "axs[0].legend()\n",
    "axs[0].grid()\n",
    "axs[1].plot(solution[\"Time [s]\"], solution[\"Voltage [V]\"], label=\"Dandeliion\")\n",
    "axs[1].set_xlabel(\"time [s]\")\n",
    "axs[1].set_title(\"Voltage [V]\")\n",
    "axs[1].legend()\n",
    "axs[1].grid()\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9d0531c-8c29-442d-9890-fcf73fa2f238",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Concentration in the electrolyte vs `x` at the last time step.\n",
    "# Here we access spatially dependent values vs time.\n",
    "plt.plot(\n",
    "    solution[\"Electrolyte x-coordinate [m]\"] * 1e6,\n",
    "    solution[\"Electrolyte concentration [mol.m-3]\"][-1],\n",
    "    label=\"Dandeliion\",\n",
    ")\n",
    "plt.xlabel(r\"x [$\\mu$m]\")\n",
    "plt.title(\"Electrolyte conc. (end of experiment) [mol.m-3]\")\n",
    "plt.legend()\n",
    "plt.grid()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4bd77010-99e8-4efb-b026-a594e45e893d",
   "metadata": {},
   "outputs": [],
   "source": [
    "solution[\"Electrolyte x-coordinate [m]\"][-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "816148d3-13c6-468d-a118-3fb9a273ee81",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A list of output times (optional)\n",
    "t_eval = np.arange(0, 3600, 1)\n",
    "\n",
    "# If the user needs the solution at the `t_eval` times, the following code can be used (works only correctly on columns with timeline data)\n",
    "# This is a linear interpolation with constant extrapolation\n",
    "solution[\"Voltage [V]\"](t=t_eval)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9f06ea0-88c7-42db-a3ae-ba5dc2bd44fc",
   "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.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
