{ "cells": [ { "cell_type": "markdown", "id": "3e61d1c6", "metadata": {}, "source": [ "# Parameter layers: swapping a PCM\n", "\n", "A parameter set is the union of independent layers: the operation, the coupling, the heat\n", "transfer fluid, the PCM, the metal of the fins, and the geometry in two parts, the flow path\n", "and the storage element (DESIGN D1). Each layer holds its own parameter names, so one part\n", "of a set, such as the PCM, can be swapped without touching the rest. Each layer lists the\n", "sources of its values in `\"citations\"`, and a composed set is a plain\n", "`pybamm.ParameterValues`.\n", "\n", "[Tutorial 4](getting_started/tutorial_4_parameter_values.ipynb) introduces parameter values and layers." ] }, { "cell_type": "code", "execution_count": 1, "id": "e4b73f16", "metadata": { "execution": { "iopub.execute_input": "2026-10-23T17:48:59.610070Z", "iopub.status.busy": "2026-10-23T17:48:59.609740Z", "iopub.status.idle": "2026-10-23T17:49:00.385361Z", "shell.execute_reply": "2026-10-23T17:49:00.384256Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "operation: Finned tube discharge, Nallusamy2007, Raul2018\n", "coupling: Finned tube default, Packed bed default\n", "heat_transfer_fluid: Water, Hytherm 600\n", "pcm: Paraffin (Nallusamy 2007), A164 (Raul 2018), PCM 10N, PCM 30, PCM 60\n", "metal: Aluminium, Steel, Copper\n", "finned_tube_flow_path: Finned tube default\n", "finned_tube_storage_element: Finned tube default\n", "packed_bed_flow_path: Nallusamy2007, Raul2018\n", "packed_bed_storage_element: Nallusamy2007, Raul2018, Default capsule\n" ] } ], "source": [ "import numpy as np\n", "import pybamm\n", "\n", "import pytes\n", "from pytes import parameter_layers as layers\n", "\n", "for kind in layers.KINDS:\n", " print(f\"{kind}: {', '.join(layers.available(kind))}\")" ] }, { "cell_type": "markdown", "id": "146be728", "metadata": {}, "source": [ "Each family's default parameter values are a named composition. The finned-tube default\n", "uses \"PCM 60\", a representative PCM for hot water melting at 60 °C." ] }, { "cell_type": "code", "execution_count": 2, "id": "cafeb9bf", "metadata": { "execution": { "iopub.execute_input": "2026-10-23T17:49:00.386999Z", "iopub.status.busy": "2026-10-23T17:49:00.386769Z", "iopub.status.idle": "2026-10-23T17:49:00.392057Z", "shell.execute_reply": "2026-10-23T17:49:00.391093Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'operation': 'Finned tube discharge', 'coupling': 'Finned tube default', 'heat_transfer_fluid': 'Water', 'pcm': 'PCM 60', 'metal': 'Aluminium', 'finned_tube_flow_path': 'Finned tube default', 'finned_tube_storage_element': 'Finned tube default'}\n", "citations: ['CRC']\n" ] }, { "data": { "text/plain": [ "{'citations': [],\n", " 'PCM solid phase conductivity [W.m-1.K-1]': 0.6,\n", " 'PCM liquid phase conductivity [W.m-1.K-1]': 0.5,\n", " 'PCM solid phase density [kg.m-3]': 1400,\n", " 'PCM liquid phase density [kg.m-3]': 1300,\n", " 'PCM solid phase specific heat capacity [J.kg-1.K-1]': 2500,\n", " 'PCM liquid phase specific heat capacity [J.kg-1.K-1]': 3000,\n", " 'PCM latent heat [J.kg-1]': 250000.0,\n", " 'PCM melting temperature [K]': 333.15,\n", " 'PCM melting range [K]': 2.0,\n", " 'PCM smoothing width [K]': 0.01}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(layers.SETS[\"Finned tube default\"])\n", "parameter_values = layers.compose_set(\"Finned tube default\")\n", "print(\"citations:\", parameter_values[\"citations\"])\n", "layers.get(\"pcm\", \"PCM 60\")" ] }, { "cell_type": "markdown", "id": "6a00998f", "metadata": {}, "source": [ "## The same battery with another PCM\n", "\n", "`swap` replaces a layer in place, and checks that the set already holds a layer of that\n", "kind. Here the battery is the same, and so is the discharge from 70 °C with water at 10 °C:\n", "only the PCM changes. The set's citations gain the sources of the new layer." ] }, { "cell_type": "code", "execution_count": 3, "id": "8447a2fb", "metadata": { "execution": { "iopub.execute_input": "2026-10-23T17:49:00.393815Z", "iopub.status.busy": "2026-10-23T17:49:00.393647Z", "iopub.status.idle": "2026-10-23T17:49:02.899233Z", "shell.execute_reply": "2026-10-23T17:49:02.898507Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PCM 60: 2.45 kWh between 10 and 70 degC, citations ['CRC']\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Paraffin (Nallusamy 2007): 1.26 kWh between 10 and 70 degC, citations ['CRC', 'Nallusamy2007']\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "PCM 30: 1.42 kWh between 10 and 70 degC, citations ['CRC']\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e5f9caa9ca924f78bfef0a685bc385c0", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=0.0, description='t', max=1.0, step=0.01), Output()), _dom_classes=('w…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model = pytes.SharpFrontModel()\n", "t = np.linspace(0, 3600, 121)\n", "solutions = []\n", "for pcm in [\"PCM 60\", \"Paraffin (Nallusamy 2007)\", \"PCM 30\"]:\n", " values = layers.compose_set(\"Finned tube default\")\n", " layers.swap(values, pcm=pcm)\n", " capacity = pytes.energy_between(model, 273.15 + 10, 273.15 + 70, values)\n", " solution = pybamm.Simulation(model, parameter_values=values).solve(\n", " [0, t[-1]], t_interp=t\n", " )\n", " solutions.append(solution)\n", " print(\n", " f\"{pcm}: {capacity / 3.6e6:.2f} kWh between 10 and 70 degC, citations {values['citations']}\"\n", " )\n", "\n", "pybamm.dynamic_plot(\n", " solutions,\n", " [\"Outlet temperature [degC]\", \"Power [kW]\", \"Average liquid fraction\"],\n", " labels=[\"PCM 60\", \"Paraffin (Nallusamy 2007)\", \"PCM 30\"],\n", ")" ] }, { "cell_type": "markdown", "id": "0dfe7b17", "metadata": {}, "source": [ "The paraffin melts at 60 °C too, but stores less energy in the same volume: it is less\n", "dense and has a lower latent heat. PCM 30 melts at 30 °C, so most of its heat comes out\n", "below the 40 °C a hot-water supply needs.\n", "\n", "## An operation that suits the PCM\n", "\n", "An operation only makes sense relative to the PCM: a discharge starts with the PCM liquid\n", "and cools it below its melting range. `operation.discharge` builds one from a PCM layer and\n", "margins above its liquidus and below its solidus, with the mass flow rate always given." ] }, { "cell_type": "code", "execution_count": 4, "id": "65d54543", "metadata": { "execution": { "iopub.execute_input": "2026-10-23T17:49:02.903450Z", "iopub.status.busy": "2026-10-23T17:49:02.903310Z", "iopub.status.idle": "2026-10-23T17:49:02.907749Z", "shell.execute_reply": "2026-10-23T17:49:02.906610Z" } }, "outputs": [ { "data": { "text/plain": [ "{'citations': [],\n", " 'Reference temperature [K]': 291.65,\n", " 'Initial temperature [K]': 309.65,\n", " 'Inlet temperature [K]': 291.65,\n", " 'Mass flow rate [kg.s-1]': 0.02}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "operation = layers.operation.discharge(\"PCM 30\", 5, 10, mass_flow_rate=0.02)\n", "values = layers.compose_set(\"Finned tube default\")\n", "layers.swap(values, pcm=\"PCM 30\", operation=operation)\n", "operation" ] }, { "cell_type": "markdown", "id": "08ba3c5a", "metadata": {}, "source": [ "## A layer of your own\n", "\n", "`template` gives an empty layer of a kind, with every name it holds; `check` says what is\n", "missing. A new layer can also start from a registered one." ] }, { "cell_type": "code", "execution_count": 5, "id": "6b6221a4", "metadata": { "execution": { "iopub.execute_input": "2026-10-23T17:49:02.909277Z", "iopub.status.busy": "2026-10-23T17:49:02.909121Z", "iopub.status.idle": "2026-10-23T17:49:02.913303Z", "shell.execute_reply": "2026-10-23T17:49:02.912392Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The pcm layer has no value for ['PCM latent heat [J.kg-1]', 'PCM liquid phase conductivity [W.m-1.K-1]', 'PCM liquid phase density [kg.m-3]', 'PCM liquid phase specific heat capacity [J.kg-1.K-1]', 'PCM melting range [K]', 'PCM melting temperature [K]', 'PCM smoothing width [K]', 'PCM solid phase conductivity [W.m-1.K-1]', 'PCM solid phase density [kg.m-3]', 'PCM solid phase specific heat capacity [J.kg-1.K-1]']\n", "latent heat [J.kg-1]: 200000.0\n" ] } ], "source": [ "template = layers.template(\"pcm\")\n", "try:\n", " layers.check(\"pcm\", template)\n", "except ValueError as error:\n", " print(error)\n", "\n", "my_pcm = layers.get(\"pcm\", \"PCM 60\")\n", "my_pcm[\"PCM latent heat [J.kg-1]\"] = 200e3\n", "my_pcm[\"citations\"] = []\n", "layers.check(\"pcm\", my_pcm)\n", "values = layers.compose_set(\"Finned tube default\")\n", "layers.swap(values, pcm=my_pcm)\n", "print(\"latent heat [J.kg-1]:\", values[\"PCM latent heat [J.kg-1]\"])" ] } ], "metadata": { "kernelspec": { "display_name": "pytes (3.14.4)", "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.14.4" } }, "nbformat": 4, "nbformat_minor": 5 }