From f8402e58b17dd3a115dd772f3035d3add4d4e29f Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Tue, 18 Feb 2025 13:29:08 -0800 Subject: [PATCH 01/16] feat: start adding battery models --- examples/03_Existing Models.ipynb | 121 ++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 7 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 78ac0a8d..eea33ffc 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -4,9 +4,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Using Provided ProgPy Models\n", + "# 3. Using Provided ProgPy Models" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ProgPy is distributed with a few pre-constructed models that can be used in simulation or prognostics. These models for batteries, pumps, valves, among others, are included in the `progpy.models` package.\n", "\n", - "**A version of this notebook will be added in release v1.8, including:**" + "For a full description of the included models, please refer to the [Included Models](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) documentation." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Table of Contents\n", + "* [Battery Models](#Battery-Models)" ] }, { @@ -20,7 +37,83 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Electric Powertrain Models" + "### BatteryElectroChemEOD" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event.\n", + "\n", + "The default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the Prognostics Center of Excellence [Data Repository](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BatteryElectroChemEOL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Vectorized prognostics model for a battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Combined BatteryElectroChem (BatteryElectroChemEODEOL)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Prognostics model for a battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BatteryCircuit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Vectorized prognostics model for a battery, represented by an equivalent circuit model as described in [[Daigle Sankararaman 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2253)\n", + "\n", + "We will start by importing the model." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "outputs: ['t', 'v']\n", + "inputs: ['i']\n" + ] + } + ], + "source": [ + "from progpy.models import BatteryCircuit\n", + "\n", + "batt = BatteryCircuit()\n", + "\n", + "print('outputs:', batt.outputs)\n", + "print('inputs:', batt.inputs)" ] }, { @@ -30,6 +123,13 @@ "## Centrifugal Pump Model" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Electric Powertrain Models" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -47,15 +147,22 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.10.7 64-bit", + "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", - "version": "3.10.7" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "610c699f0cd8c4f129acd9140687fff6866bed0eb8e82f249fc8848b827b628c" @@ -63,5 +170,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From 8be7ecec30fe0a2d32e54b50c9bb3ea0bd758e94 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Wed, 5 Mar 2025 11:57:53 -0800 Subject: [PATCH 02/16] feat: expand battery circuit example --- examples/03_Existing Models.ipynb | 307 +++++++++++++++++++++++++++--- 1 file changed, 280 insertions(+), 27 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index eea33ffc..4ac9587e 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 3. Using Provided ProgPy Models" + "# 3. Using Included ProgPy Models" ] }, { @@ -13,7 +13,7 @@ "source": [ "ProgPy is distributed with a few pre-constructed models that can be used in simulation or prognostics. These models for batteries, pumps, valves, among others, are included in the `progpy.models` package.\n", "\n", - "For a full description of the included models, please refer to the [Included Models](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) documentation." + "In this notebook, we will be exploring a generalized overview of each included model. For more in-depth descriptions of the included models, please refer to the [Included Models](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) documentation." ] }, { @@ -23,7 +23,11 @@ }, "source": [ "## Table of Contents\n", - "* [Battery Models](#Battery-Models)" + "* [Battery Models](#Battery-Models)\n", + " * [Battery Circuit](#BatteryCircuit)\n", + " * [BatteryElectroChemEOD](#BatteryElectroChemEOD)\n", + " * [BatteryElectroChemEOL](#BatteryElectroChemEOL)\n", + " * [Combined BatteryElectroChem (BatteryElectroChemEODEOL)](#Combined-BatteryElectroChem-(BatteryElectroChemEODEOL))" ] }, { @@ -37,83 +41,332 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### BatteryElectroChemEOD" + "In the following battery models, the default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the Prognostics Center of Excellence [Data Repository](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event.\n", + "### BatteryCircuit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this first example, we will demonstrate how to set up, configure, and use the BatteryCiruit model. The BatteryCircuit model is a vectorized prognostics model for a battery, represented by an equivalent circuit model as described in [[Daigle Sankararaman 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2253).\n", + "\n", + "We will start by importing the model and initializing a battery instance with default settings." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import BatteryCircuit\n", "\n", - "The default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the Prognostics Center of Excellence [Data Repository](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository)." + "batt = BatteryCircuit()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### BatteryElectroChemEOL" + "Information is passed to and from the model using containers that function like dictionaries. The keys of the containers are specific to the model. Let's look at the inputs (loading) and outputs (measurements) for the BatteryCircuit model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print('inputs:', batt.inputs)\n", + "print('outputs:', batt.outputs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Vectorized prognostics model for a battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)" + "If we refer to the [documentation](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html), we can see that the input `i` refers to the current draw on the battery. The outputs `t` refers to the temperature in units Kelvin and `v` refers to voltage.\n", + "\n", + "We can also print out what events we're predicting and the internal states the model uses to represent the system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print('event(s): ', batt.events)\n", + "print('states: ', batt.states)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Combined BatteryElectroChem (BatteryElectroChemEODEOL)" + "We can see that this particular model only predicts one event, called `EOD` (End of Discharge). The states listed include `tb`, the battery temperature in K; `qb`, the charge stored in Capacitor Cb of the equivalent circuit model; `qcp`, the charge stored in Capacitor Ccp of the equivalent circuit model; and `qcs`, the charge stored in Capacitor Ccs of the equivalent circuit model.\n", + "\n", + "Let's now look at the model's configuration parameters, which describe the specific system (in this case, the battery) that the model is simulating." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "print('Model configuration:')\n", + "pprint(batt.parameters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Prognostics model for a battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)." + "We can set the configuration by modifying parameters while initializing the battery or after. The BatteryCircuit default parameters are for a 18650 battery tested in NASA's SHARP lab. If you're using the model for a system other than that one battery, you will need to update the parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "batt.parameters['qMax'] = 7856 \n", + "batt.parameters['process_noise'] = 0 # Turns off default process noise" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### BatteryCircuit" + "We can save or load a model configuration using pickle." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pickle\n", + "pickle.dump(batt.parameters, open('battery123.cfg', 'wb'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can then set your model configuration like below. This is useful for recording and restoring model configurations. Some users store model configuration as picked files to be restored from later." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "batt.parameters = pickle.load(open('battery123.cfg', 'rb'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Vectorized prognostics model for a battery, represented by an equivalent circuit model as described in [[Daigle Sankararaman 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2253)\n", + "Additionally, both pickle and JSON can be used to serialize an entire model for future use. All models include functions to serialize with JSON." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "save_json = batt.to_json()\n", + "serial_batt = BatteryCircuit.from_json(save_json)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's now use the model to do a simulation. To do this, we will first need to set a configuration and define a future load. For more details on future loading, refer to the related section in __[01 Simulation](01_Simulation.ipynb#Future-Loading)__." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'save_freq': 100,\n", + " 'dt': 2,\n", + " 't0': 700,\n", + "}\n", "\n", - "We will start by importing the model." + "def future_loading(t, x=None):\n", + " if (t < 600):\n", + " i = 2\n", + " elif (t < 900):\n", + " i = 1\n", + " elif (t < 1800):\n", + " i = 4\n", + " elif (t < 3000):\n", + " i = 2 \n", + " else:\n", + " i = 3\n", + " return batt.InputContainer({'i': i})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's run the simulation and plot the inputs and outputs. We can do this using the built-in [plot method](https://nasa.github.io/progpy/api_ref/progpy/SimResult.html#progpy.sim_result.SimResult.plot) based on matplotlib or with other imported plotting libraries." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "outputs: ['t', 'v']\n", - "inputs: ['i']\n" - ] - } - ], + "outputs": [], "source": [ - "from progpy.models import BatteryCircuit\n", + "simulated_results = batt.simulate_to_threshold(future_loading, **config)\n", + "\n", + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def print_battery_output_plots(results):\n", + " fig = results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", + " fig2 = results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "\n", + "print_battery_output_plots(simulated_results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BatteryElectroChemEOD" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "BatteryElectroChemEOD is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import BatteryElectroChemEOD\n", + "\n", + "batt = BatteryElectroChemEOD()\n", + "\n", + "print('inputs:', batt.inputs)\n", + "print('outputs:', batt.outputs)\n", + "print('event(s): ', batt.events)\n", + "print('outputs:', batt.states)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, **config)\n", + "\n", + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print_battery_output_plots(simulated_results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BatteryElectroChemEOL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "BatteryElectroChemEOL is a vectorized prognostics model for battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import BatteryElectroChemEOL\n", + "\n", + "batt = BatteryElectroChemEOL()\n", + "\n", + "print('inputs:', batt.inputs)\n", + "print('outputs:', batt.outputs)\n", + "print('event(s): ', batt.events)\n", + "print('outputs:', batt.states)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Combined BatteryElectroChem (BatteryElectroChemEODEOL)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "BatteryElectroChemEODEOL is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import BatteryElectroChem\n", "\n", - "batt = BatteryCircuit()\n", + "batt = BatteryElectroChem()\n", "\n", + "print('inputs:', batt.inputs)\n", "print('outputs:', batt.outputs)\n", - "print('inputs:', batt.inputs)" + "print('event(s): ', batt.events)\n", + "print('outputs:', batt.states)" ] }, { From 996705647dfdf1b8472215564880d6e6d7963159 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Tue, 11 Mar 2025 11:39:21 -0700 Subject: [PATCH 03/16] feat: expand combined battery EODEOL example --- examples/03_Existing Models.ipynb | 100 ++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 4ac9587e..ee50f193 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -270,7 +270,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "BatteryElectroChemEOD is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event." + "BatteryElectroChemEOD is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event. Let's start by examining the model inputs, outputs, event(s), and states." ] }, { @@ -286,27 +286,14 @@ "print('inputs:', batt.inputs)\n", "print('outputs:', batt.outputs)\n", "print('event(s): ', batt.events)\n", - "print('outputs:', batt.states)" + "print('states:', batt.states)" ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, **config)\n", - "\n", - "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" - ] - }, - { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "print_battery_output_plots(simulated_results)" + "Let's now run a simulation using the same configuration and future loading function as the previous example. We will then plot the outputs." ] }, { @@ -350,7 +337,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "BatteryElectroChemEODEOL is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)." + "BatteryElectroChemEODEOL is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). We will start by importing the model and initializing a battery instance." ] }, { @@ -360,6 +347,7 @@ "outputs": [], "source": [ "from progpy.models import BatteryElectroChem\n", + "import matplotlib.pyplot as plt\n", "\n", "batt = BatteryElectroChem()\n", "\n", @@ -369,6 +357,82 @@ "print('outputs:', batt.states)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we will simulating a battery until End of Life (EOL). As battery capacity decreases with use, EOL is when the battery capacity falls below some acceptable threshold (i.e., what we define as useful capacity).\n", + "\n", + "We will now set the configuration and define a future loading function. As we want to predict EOL, we will set the configuration event to `InsufficientCapacity`. The future loading function is designed to charge the battery until 0.95 and then discharge until 0.05." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'save_freq': 1000, # Frequency at which results are saved\n", + " 'dt': 2, # Timestep\n", + " 'events': 'InsufficientCapacity', # Simulate to InsufficientCapacity\n", + " 'print': True\n", + "}\n", + "\n", + "def future_loading(t, x=None):\n", + " load = 1\n", + "\n", + " # Rule for loading after initialization\n", + " if x is not None:\n", + " # Current event state in the form {'EOD': <(0, 1)>, 'InsufficientCapacity': <(0, 1)>}\n", + " event_state = batt.event_state(x)\n", + " if event_state[\"EOD\"] > 0.95:\n", + " load = 1 # Discharge\n", + " elif event_state[\"EOD\"] < 0.05:\n", + " load = -1 # Charge\n", + " \n", + " # Rule for loading at initialization\n", + " return batt.InputContainer({'i': load})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now simulate to the threshold and print the results." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, **config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now plot the inputs and event states. In the input plot, we can see the battery getting charged and discharged." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)')\n", + "simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD': 'State of Charge (SOC)', 'InsufficientCapacity': 'State of Health (SOH)'})\n", + "plt.ylim([0, 1])\n", + "\n", + "#TODO: UPDATE UNITS FOR EVENT STATES\n", + "\n", + "plt.show()" + ] + }, { "cell_type": "markdown", "metadata": {}, From c7d16fb11a14ebae0f3b0dd843c3e361b26ed74d Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Tue, 11 Mar 2025 12:48:11 -0700 Subject: [PATCH 04/16] fix: expand explanations --- examples/03_Existing Models.ipynb | 79 ++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index ee50f193..5ba00d6a 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -27,7 +27,11 @@ " * [Battery Circuit](#BatteryCircuit)\n", " * [BatteryElectroChemEOD](#BatteryElectroChemEOD)\n", " * [BatteryElectroChemEOL](#BatteryElectroChemEOL)\n", - " * [Combined BatteryElectroChem (BatteryElectroChemEODEOL)](#Combined-BatteryElectroChem-(BatteryElectroChemEODEOL))" + " * [Combined BatteryElectroChem (BatteryElectroChemEODEOL)](#Combined-BatteryElectroChem-(BatteryElectroChemEODEOL))\n", + "* [Centrifugal Pump Model](#Centrifugal-Pump-Model)\n", + "* [Electric Powertrain Models](#Electric-Powertrain-Models)\n", + "* [Pneumatic Valve Model](#Pneumatic-Valve-Model)\n", + "* [Aircraft Flight Model](#Aircraft-Flight-Model)" ] }, { @@ -55,7 +59,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this first example, we will demonstrate how to set up, configure, and use the BatteryCiruit model. The BatteryCircuit model is a vectorized prognostics model for a battery, represented by an equivalent circuit model as described in [[Daigle Sankararaman 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2253).\n", + "In this first example, we will demonstrate how to set up, configure, and use the `BatteryCiruit` model. The `BatteryCircuit` model is a vectorized prognostics model for a battery, represented by an equivalent circuit model as described in [[Daigle Sankararaman 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2253).\n", "\n", "We will start by importing the model and initializing a battery instance with default settings." ] @@ -67,6 +71,7 @@ "outputs": [], "source": [ "from progpy.models import BatteryCircuit\n", + "import matplotlib.pyplot as plt\n", "\n", "batt = BatteryCircuit()" ] @@ -75,7 +80,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Information is passed to and from the model using containers that function like dictionaries. The keys of the containers are specific to the model. Let's look at the inputs (loading) and outputs (measurements) for the BatteryCircuit model." + "Information is passed to and from the model using containers that function like dictionaries. The keys of the containers are specific to the model. Let's look at the inputs (loading) and outputs (measurements) for the `BatteryCircuit` model." ] }, { @@ -132,7 +137,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We can set the configuration by modifying parameters while initializing the battery or after. The BatteryCircuit default parameters are for a 18650 battery tested in NASA's SHARP lab. If you're using the model for a system other than that one battery, you will need to update the parameters." + "We can set the configuration by modifying parameters while initializing the battery or after. The `BatteryCircuit` default parameters are for a 18650 battery tested in NASA's SHARP lab. If you're using the model for a system other than that one battery, you will need to update the parameters." ] }, { @@ -232,7 +237,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's run the simulation and plot the inputs and outputs. We can do this using the built-in [plot method](https://nasa.github.io/progpy/api_ref/progpy/SimResult.html#progpy.sim_result.SimResult.plot) based on matplotlib or with other imported plotting libraries." + "Let's run the simulation and plot the inputs and outputs. We can do this using the built-in [plot method](https://nasa.github.io/progpy/api_ref/progpy/SimResult.html#progpy.sim_result.SimResult.plot) based on matplotlib or with other imported plotting libraries.\n", + "\n", + "In the inputs plot, we can see the current drawn change based on the logic we defined in the future loading function." ] }, { @@ -246,17 +253,23 @@ "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the outputs plot, we can observe how different input current draws affect the temperature and voltage curves. Generally, the graphs indicate that drawing a higher current leads to higher temperatures and lower voltage." + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "def print_battery_output_plots(results):\n", - " fig = results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", - " fig2 = results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", + "simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", "\n", - "print_battery_output_plots(simulated_results)" + "plt.show()" ] }, { @@ -270,7 +283,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "BatteryElectroChemEOD is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event. Let's start by examining the model inputs, outputs, event(s), and states." + "`BatteryElectroChemEOD` is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event. Let's start by examining the model inputs, outputs, event(s), and states." ] }, { @@ -307,7 +320,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "BatteryElectroChemEOL is a vectorized prognostics model for battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132)" + "`BatteryElectroChemEOL` is a vectorized prognostics model for battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). Let's go ahead and import the model, initialize a battery instance, and take a closer look at the details." ] }, { @@ -337,7 +350,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "BatteryElectroChemEODEOL is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). We will start by importing the model and initializing a battery instance." + "`BatteryElectroChemEODEOL` is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). We will start by importing the model, initializing a battery instance, and examining the model details." ] }, { @@ -361,9 +374,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this example, we will simulating a battery until End of Life (EOL). As battery capacity decreases with use, EOL is when the battery capacity falls below some acceptable threshold (i.e., what we define as useful capacity).\n", + "In this example, we will simulating a battery until `EOL` (End of Life). As battery capacity decreases with use, `EOL` is when the battery capacity falls below some acceptable threshold (i.e., what we define as useful capacity).\n", "\n", - "We will now set the configuration and define a future loading function. As we want to predict EOL, we will set the configuration event to `InsufficientCapacity`. The future loading function is designed to charge the battery until 0.95 and then discharge until 0.05." + "We will now set the configuration and define a future loading function. As we want to predict `EOL`, we will set the configuration event to `InsufficientCapacity`. The future loading function is designed to charge the battery until event state 0.95 and then discharge until event state 0.05. Note that states represent the progress towards the event occurring. An event state of 0 indicates the event has occurred and 1 indicates no progress towards the event." ] }, { @@ -373,9 +386,9 @@ "outputs": [], "source": [ "config = {\n", - " 'save_freq': 1000, # Frequency at which results are saved\n", - " 'dt': 2, # Timestep\n", - " 'events': 'InsufficientCapacity', # Simulate to InsufficientCapacity\n", + " 'save_freq': 1000,\n", + " 'dt': 2,\n", + " 'events': 'InsufficientCapacity',\n", " 'print': True\n", "}\n", "\n", @@ -387,9 +400,9 @@ " # Current event state in the form {'EOD': <(0, 1)>, 'InsufficientCapacity': <(0, 1)>}\n", " event_state = batt.event_state(x)\n", " if event_state[\"EOD\"] > 0.95:\n", - " load = 1 # Discharge\n", + " load = 1 # Discharge\n", " elif event_state[\"EOD\"] < 0.05:\n", - " load = -1 # Charge\n", + " load = -1 # Charge\n", " \n", " # Rule for loading at initialization\n", " return batt.InputContainer({'i': load})" @@ -415,7 +428,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will now plot the inputs and event states. In the input plot, we can see the battery getting charged and discharged." + "We will now plot the inputs and event states. In the input plot, we can see the current drawn fluctuate between -1 and 1 based on the current load we defined in the future loading function." ] }, { @@ -424,13 +437,25 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)')\n", - "simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD': 'State of Charge (SOC)', 'InsufficientCapacity': 'State of Health (SOH)'})\n", - "plt.ylim([0, 1])\n", - "\n", - "#TODO: UPDATE UNITS FOR EVENT STATES\n", - "\n", - "plt.show()" + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the event states plot, we can see `EOD` incrementally spiking and `InsufficientCapacity` linearly declining until it reaches 0, or when the event has occurred." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD': 'State of Charge (SOC)', 'InsufficientCapacity': 'State of Health (SOH)'})" ] }, { From 4f8fe40789f3660446993d7bd09cdcf436dc14c6 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Tue, 11 Mar 2025 12:59:27 -0700 Subject: [PATCH 05/16] feat: expand on EOD and EOL model examples --- examples/03_Existing Models.ipynb | 70 +++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 5ba00d6a..25e8633b 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -306,7 +306,37 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's now run a simulation using the same configuration and future loading function as the previous example. We will then plot the outputs." + "Let's now run a simulation using the same future loading function as the previous example and specify the `threhold_key` as `EOD`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, threshold_keys=['EOD'])\n", + "\n", + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**TODO: Insert some text here**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", + "simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "\n", + "plt.show()" ] }, { @@ -339,6 +369,41 @@ "print('outputs:', batt.states)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**TODO: Insert some text here**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, threshold_keys=['InsufficientCapacity'])\n", + "\n", + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**TODO: Insert some text here**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'InsufficientCapacity': 'State of Health (SOH)'})\n", + "plt.show()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -389,7 +454,6 @@ " 'save_freq': 1000,\n", " 'dt': 2,\n", " 'events': 'InsufficientCapacity',\n", - " 'print': True\n", "}\n", "\n", "def future_loading(t, x=None):\n", @@ -412,7 +476,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will now simulate to the threshold and print the results." + "We will now simulate to the threshold." ] }, { From 574034dd793da6b42f28d18955b3b9bf99e34045 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Wed, 12 Mar 2025 08:19:58 -0700 Subject: [PATCH 06/16] feat: expand on EODEOL example --- examples/03_Existing Models.ipynb | 158 ++++++++++++------------------ 1 file changed, 62 insertions(+), 96 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 25e8633b..70831ea5 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -133,73 +133,6 @@ "pprint(batt.parameters)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can set the configuration by modifying parameters while initializing the battery or after. The `BatteryCircuit` default parameters are for a 18650 battery tested in NASA's SHARP lab. If you're using the model for a system other than that one battery, you will need to update the parameters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "batt.parameters['qMax'] = 7856 \n", - "batt.parameters['process_noise'] = 0 # Turns off default process noise" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can save or load a model configuration using pickle." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pickle\n", - "pickle.dump(batt.parameters, open('battery123.cfg', 'wb'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can then set your model configuration like below. This is useful for recording and restoring model configurations. Some users store model configuration as picked files to be restored from later." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "batt.parameters = pickle.load(open('battery123.cfg', 'rb'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Additionally, both pickle and JSON can be used to serialize an entire model for future use. All models include functions to serialize with JSON." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "save_json = batt.to_json()\n", - "serial_batt = BatteryCircuit.from_json(save_json)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -216,7 +149,7 @@ "config = {\n", " 'save_freq': 100,\n", " 'dt': 2,\n", - " 't0': 700,\n", + " 't0': 700\n", "}\n", "\n", "def future_loading(t, x=None):\n", @@ -266,10 +199,8 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", - "simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", - "\n", - "plt.show()" + "fig = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", + "fig2 = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))" ] }, { @@ -283,7 +214,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`BatteryElectroChemEOD` is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event. Let's start by examining the model inputs, outputs, event(s), and states." + "`BatteryElectroChemEOD` is a vectorized prognostics model for a battery, represented by an electrochemical equations as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). This model predicts the end of discharge event. Let's start by examining the model inputs, outputs, event(s), and states. We can refer to the [documentation](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) for more details." ] }, { @@ -306,7 +237,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's now run a simulation using the same future loading function as the previous example and specify the `threhold_key` as `EOD`." + "Let's now run a simulation until `EOD`, or end of discharge. We wil use the same future loading function as the previous example and specify the threshold event as `EOD`.\n", + "\n", + "In the input plot, we can see the current draw change based on the future loading function we defined." ] }, { @@ -315,7 +248,7 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, threshold_keys=['EOD'])\n", + "simulated_results = batt.simulate_to_threshold(future_loading, events=['EOD'])\n", "\n", "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] @@ -324,7 +257,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**TODO: Insert some text here**" + "In the output plots, we can see changes in voltage and temperature. We can also print parameters like `VEOD`, or the end of discharge voltage threshold. This value is the voltage at which a battery is considered fully discharged." ] }, { @@ -333,10 +266,26 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", - "simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "print(\"End of discharge voltage threshold:\", batt.parameters['VEOD'])\n", "\n", - "plt.show()" + "fig2 = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (°C)', figsize=(10,4))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the event state plot, we can see `EOD` decline until it reaches 0, or when the end of discharge event has occurred. This event occurence is when the simulation reached threshold and ended." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'EOD'})" ] }, { @@ -350,7 +299,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`BatteryElectroChemEOL` is a vectorized prognostics model for battery degredation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). Let's go ahead and import the model, initialize a battery instance, and take a closer look at the details." + "`BatteryElectroChemEOL` is a vectorized prognostics model for battery degradation, represented by an electrochemical model as described in [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). Let's go ahead and import the model, initialize a battery instance, and take a closer look at the details. We can also refer to the [documentation](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html). Note that the model has no outputs. " ] }, { @@ -366,14 +315,16 @@ "print('inputs:', batt.inputs)\n", "print('outputs:', batt.outputs)\n", "print('event(s): ', batt.events)\n", - "print('outputs:', batt.states)" + "print('states:', batt.states)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**TODO: Insert some text here**" + "Let's now run a simulation to predict when we will reach insufficient battery capacity. We will use the same future loading function as the previous examples and specify the threhold event as `InsufficientCapacity`.\n", + "\n", + "In the input plot, we can once again see the current draw change based on the future loading function we defined." ] }, { @@ -382,7 +333,7 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, threshold_keys=['InsufficientCapacity'])\n", + "simulated_results = batt.simulate_to_threshold(future_loading, events=['InsufficientCapacity'])\n", "\n", "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] @@ -391,7 +342,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**TODO: Insert some text here**" + "In the event state plot, we can see `InsufficientCapacity` linearly decrease until it reaches 0, or when the event has occurred." ] }, { @@ -400,8 +351,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'InsufficientCapacity': 'State of Health (SOH)'})\n", - "plt.show()" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'InsufficientCapacity'})" ] }, { @@ -415,7 +365,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`BatteryElectroChemEODEOL` is a prognostics model for battery degredation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). We will start by importing the model, initializing a battery instance, and examining the model details." + "`BatteryElectroChemEODEOL` is a prognostics model for battery degradation and discharge, represented by an electrochemical model as described in [[Daigle 2013]](https://papers.phmsociety.org/index.php/phmconf/article/view/2252) and [[Daigle 2016]](https://arc.aiaa.org/doi/pdf/10.2514/6.2016-2132). This model combines both the `BatteryElectroChemEOL` and `BatteryElectroChemEOD` models.\n", + "\n", + "We will start by importing the model, initializing a battery instance, and examining the model details. We can once again refer to the [documentation](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) for more details." ] }, { @@ -432,7 +384,7 @@ "print('inputs:', batt.inputs)\n", "print('outputs:', batt.outputs)\n", "print('event(s): ', batt.events)\n", - "print('outputs:', batt.states)" + "print('states:', batt.states)" ] }, { @@ -441,7 +393,7 @@ "source": [ "In this example, we will simulating a battery until `EOL` (End of Life). As battery capacity decreases with use, `EOL` is when the battery capacity falls below some acceptable threshold (i.e., what we define as useful capacity).\n", "\n", - "We will now set the configuration and define a future loading function. As we want to predict `EOL`, we will set the configuration event to `InsufficientCapacity`. The future loading function is designed to charge the battery until event state 0.95 and then discharge until event state 0.05. Note that states represent the progress towards the event occurring. An event state of 0 indicates the event has occurred and 1 indicates no progress towards the event." + "We will now set the configuration and define a future loading function. As we want to simulate until `EOL`, we will set the configuration event to `InsufficientCapacity`. The future loading function is designed to charge the battery until `EOD` is 0.95 and then discharge until `EOD` is 0.05. Note that states represent the progress towards the event occurring. An event state of 0 indicates the event has occurred and 1 indicates no progress towards the event." ] }, { @@ -458,17 +410,14 @@ "\n", "def future_loading(t, x=None):\n", " load = 1\n", - "\n", - " # Rule for loading after initialization\n", + " \n", " if x is not None:\n", - " # Current event state in the form {'EOD': <(0, 1)>, 'InsufficientCapacity': <(0, 1)>}\n", " event_state = batt.event_state(x)\n", " if event_state[\"EOD\"] > 0.95:\n", " load = 1 # Discharge\n", " elif event_state[\"EOD\"] < 0.05:\n", " load = -1 # Charge\n", " \n", - " # Rule for loading at initialization\n", " return batt.InputContainer({'i': load})" ] }, @@ -476,7 +425,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will now simulate to the threshold." + "We will now simulate to the threshold and print the results." ] }, { @@ -492,7 +441,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will now plot the inputs and event states. In the input plot, we can see the current drawn fluctuate between -1 and 1 based on the current load we defined in the future loading function." + "We will now plot the inputs, outputs, and event states. In the input plot, we can see the current drawn fluctuate between -1 and 1 based on the current load we defined in the future loading function." ] }, { @@ -504,6 +453,23 @@ "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)')" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the output plots, we can see changes in the voltage and temperature." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "fig2 = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (°C)', figsize=(10,4))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -519,7 +485,7 @@ }, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD': 'State of Charge (SOC)', 'InsufficientCapacity': 'State of Health (SOH)'})" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'})" ] }, { From 79c08f1e710260b9e81714525b2b54f5ddf7ada3 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Fri, 14 Mar 2025 08:53:56 -0700 Subject: [PATCH 07/16] fix: update explanations and graphs --- examples/03_Existing Models.ipynb | 75 +++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 70831ea5..8b41ce55 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -71,7 +71,6 @@ "outputs": [], "source": [ "from progpy.models import BatteryCircuit\n", - "import matplotlib.pyplot as plt\n", "\n", "batt = BatteryCircuit()" ] @@ -170,9 +169,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's run the simulation and plot the inputs and outputs. We can do this using the built-in [plot method](https://nasa.github.io/progpy/api_ref/progpy/SimResult.html#progpy.sim_result.SimResult.plot) based on matplotlib or with other imported plotting libraries.\n", - "\n", - "In the inputs plot, we can see the current drawn change based on the logic we defined in the future loading function." + "Let's run the simulation and plot the inputs and outputs. We can do this using the built-in [plot method](https://nasa.github.io/progpy/api_ref/progpy/SimResult.html#progpy.sim_result.SimResult.plot) based on matplotlib or with other imported plotting libraries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, **config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the input plot, we can see the current drawn change based on the logic we defined in the future loading function." ] }, { @@ -181,8 +194,6 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, **config)\n", - "\n", "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] }, @@ -190,7 +201,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In the outputs plot, we can observe how different input current draws affect the temperature and voltage curves. Generally, the graphs indicate that drawing a higher current leads to higher temperatures and lower voltage." + "In the output plots, we can observe how different input current draws affect the temperature and voltage curves. Generally, the graphs indicate that drawing a higher current leads to higher temperatures and lower voltage." ] }, { @@ -237,8 +248,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's now run a simulation until `EOD`, or end of discharge. We wil use the same future loading function as the previous example and specify the threshold event as `EOD`.\n", + "Let's now run a simulation until `EOD`, or end of discharge. We wil use the same future loading function as the previous example and specify the configuration threshold event as `EOD`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'save_freq': 100,\n", + " 'dt': 2,\n", + " 'events': ['EOD']\n", + "}\n", "\n", + "simulated_results = batt.simulate_to_threshold(future_loading, **config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "In the input plot, we can see the current draw change based on the future loading function we defined." ] }, @@ -248,8 +279,6 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, events=['EOD'])\n", - "\n", "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] }, @@ -322,8 +351,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's now run a simulation to predict when we will reach insufficient battery capacity. We will use the same future loading function as the previous examples and specify the threhold event as `InsufficientCapacity`.\n", + "Let's now run a simulation to predict when we will reach insufficient battery capacity. We will use the same future loading function as the previous examples and specify the configuration threhold event as `InsufficientCapacity`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'save_freq': 100,\n", + " 'dt': 2,\n", + " 'events': ['InsufficientCapacity']\n", + "}\n", "\n", + "simulated_results = batt.simulate_to_threshold(future_loading, **config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "In the input plot, we can once again see the current draw change based on the future loading function we defined." ] }, @@ -333,8 +382,6 @@ "metadata": {}, "outputs": [], "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, events=['InsufficientCapacity'])\n", - "\n", "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" ] }, @@ -377,7 +424,6 @@ "outputs": [], "source": [ "from progpy.models import BatteryElectroChem\n", - "import matplotlib.pyplot as plt\n", "\n", "batt = BatteryElectroChem()\n", "\n", @@ -406,6 +452,7 @@ " 'save_freq': 1000,\n", " 'dt': 2,\n", " 'events': 'InsufficientCapacity',\n", + " 'print': True\n", "}\n", "\n", "def future_loading(t, x=None):\n", From bc4a83bf773797a72ce719eaf5d9b0ae1edfd3d2 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Mon, 24 Mar 2025 13:22:28 -0700 Subject: [PATCH 08/16] temp --- examples/test.ipynb | 104 ++++++++++++++++++++++++++++++++ src/progpy/prognostics_model.py | 7 +-- 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 examples/test.ipynb diff --git a/examples/test.ipynb b/examples/test.ipynb new file mode 100644 index 00000000..33007920 --- /dev/null +++ b/examples/test.ipynb @@ -0,0 +1,104 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pip list | grep progpy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import BatteryElectroChem\n", + "import matplotlib.pyplot as plt\n", + "\n", + "batt = BatteryElectroChem()\n", + "\n", + "print('inputs:', batt.inputs)\n", + "print('outputs:', batt.outputs)\n", + "print('event(s): ', batt.events)\n", + "print('states:', batt.states)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'save_freq': 1000,\n", + " 'dt': 2,\n", + " 'events': 'InsufficientCapacity',\n", + " # 'print': True\n", + "}\n", + "\n", + "def future_loading(t, x=None):\n", + " load = 1\n", + " \n", + " if x is not None:\n", + " event_state = batt.event_state(x)\n", + " if event_state[\"EOD\"] > 0.95:\n", + " load = 1 # Discharge\n", + " elif event_state[\"EOD\"] < 0.05:\n", + " load = -1 # Charge\n", + " \n", + " return batt.InputContainer({'i': load})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results = batt.simulate_to_threshold(future_loading, **config)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simulated_results.event_states" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/progpy/prognostics_model.py b/src/progpy/prognostics_model.py index 3a8c3c1a..4da71d23 100644 --- a/src/progpy/prognostics_model.py +++ b/src/progpy/prognostics_model.py @@ -1032,6 +1032,7 @@ def update_all(): saved_times.append(t) saved_inputs.append(u) saved_states.append(deepcopy(x)) # Avoid optimization where x is not copied + saved_event_states.append(event_state(x)) # configuring next_time function to define prediction time step, default is constant dt if callable(config['dt']): @@ -1144,11 +1145,9 @@ def output(x): if not saved_outputs: # saved_outputs is empty, so it wasn't calculated in simulation - used cached result saved_outputs = LazySimResult(self.__output, saved_times, saved_states) - saved_event_states = LazySimResult(self.event_state, saved_times, saved_states) else: saved_outputs = SimResult(saved_times, saved_outputs, _copy=False) - saved_event_states = SimResult(saved_times, saved_event_states, _copy=False) - + if 'integration_method' in config: # Reset integration method self.parameters['integration_method'] = old_integration_method @@ -1158,7 +1157,7 @@ def output(x): SimResult(saved_times, saved_inputs, _copy=False), SimResult(saved_times, saved_states, _copy=False), saved_outputs, - saved_event_states + SimResult(saved_times, saved_event_states, _copy=False) ) def __sizeof__(self): From 4acb4cd99a3cf785767180ef761d320c62cfc567 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Fri, 25 Apr 2025 11:00:16 -0700 Subject: [PATCH 09/16] Revert "feat: start adding battery models" This reverts commit f8b88720540b490fe541e841b5febd3399fbebf4. --- examples/03_Existing Models.ipynb | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 8b41ce55..9e2e01f9 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -542,13 +542,6 @@ "## Centrifugal Pump Model" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Electric Powertrain Models" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -566,28 +559,16 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": ".venv", "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.10.5" - }, - "vscode": { - "interpreter": { - "hash": "610c699f0cd8c4f129acd9140687fff6866bed0eb8e82f249fc8848b827b628c" - } - } + "version": "3.12.9" + }, + "orig_nbformat": 4 }, "nbformat": 4, - "nbformat_minor": 4 + "nbformat_minor": 2 } From e7b3cad72c3c3407c0eb654d4640acf119be769c Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Fri, 25 Apr 2025 11:09:14 -0700 Subject: [PATCH 10/16] undo change --- examples/test.ipynb | 104 -------------------------------- src/progpy/prognostics_model.py | 7 ++- 2 files changed, 4 insertions(+), 107 deletions(-) delete mode 100644 examples/test.ipynb diff --git a/examples/test.ipynb b/examples/test.ipynb deleted file mode 100644 index 33007920..00000000 --- a/examples/test.ipynb +++ /dev/null @@ -1,104 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pip list | grep progpy" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from progpy.models import BatteryElectroChem\n", - "import matplotlib.pyplot as plt\n", - "\n", - "batt = BatteryElectroChem()\n", - "\n", - "print('inputs:', batt.inputs)\n", - "print('outputs:', batt.outputs)\n", - "print('event(s): ', batt.events)\n", - "print('states:', batt.states)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "config = {\n", - " 'save_freq': 1000,\n", - " 'dt': 2,\n", - " 'events': 'InsufficientCapacity',\n", - " # 'print': True\n", - "}\n", - "\n", - "def future_loading(t, x=None):\n", - " load = 1\n", - " \n", - " if x is not None:\n", - " event_state = batt.event_state(x)\n", - " if event_state[\"EOD\"] > 0.95:\n", - " load = 1 # Discharge\n", - " elif event_state[\"EOD\"] < 0.05:\n", - " load = -1 # Charge\n", - " \n", - " return batt.InputContainer({'i': load})" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "simulated_results = batt.simulate_to_threshold(future_loading, **config)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "simulated_results.event_states" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'})" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "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.9" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/src/progpy/prognostics_model.py b/src/progpy/prognostics_model.py index 4da71d23..a298b395 100644 --- a/src/progpy/prognostics_model.py +++ b/src/progpy/prognostics_model.py @@ -1032,7 +1032,6 @@ def update_all(): saved_times.append(t) saved_inputs.append(u) saved_states.append(deepcopy(x)) # Avoid optimization where x is not copied - saved_event_states.append(event_state(x)) # configuring next_time function to define prediction time step, default is constant dt if callable(config['dt']): @@ -1144,9 +1143,11 @@ def output(x): if not saved_outputs: # saved_outputs is empty, so it wasn't calculated in simulation - used cached result - saved_outputs = LazySimResult(self.__output, saved_times, saved_states) + saved_outputs = LazySimResult(self.__output, saved_times, saved_states) + saved_event_states = LazySimResult(self.event_state, saved_times, saved_states) else: saved_outputs = SimResult(saved_times, saved_outputs, _copy=False) + saved_event_states = SimResult(saved_times, saved_event_states, _copy=False) if 'integration_method' in config: # Reset integration method @@ -1157,7 +1158,7 @@ def output(x): SimResult(saved_times, saved_inputs, _copy=False), SimResult(saved_times, saved_states, _copy=False), saved_outputs, - SimResult(saved_times, saved_event_states, _copy=False) + saved_event_states ) def __sizeof__(self): From d048c9e3b24aa80f3c5f241a749218a3db6f6992 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Fri, 25 Apr 2025 11:10:14 -0700 Subject: [PATCH 11/16] fix spacing --- src/progpy/prognostics_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/progpy/prognostics_model.py b/src/progpy/prognostics_model.py index a298b395..3a8c3c1a 100644 --- a/src/progpy/prognostics_model.py +++ b/src/progpy/prognostics_model.py @@ -1143,12 +1143,12 @@ def output(x): if not saved_outputs: # saved_outputs is empty, so it wasn't calculated in simulation - used cached result - saved_outputs = LazySimResult(self.__output, saved_times, saved_states) + saved_outputs = LazySimResult(self.__output, saved_times, saved_states) saved_event_states = LazySimResult(self.event_state, saved_times, saved_states) else: saved_outputs = SimResult(saved_times, saved_outputs, _copy=False) saved_event_states = SimResult(saved_times, saved_event_states, _copy=False) - + if 'integration_method' in config: # Reset integration method self.parameters['integration_method'] = old_integration_method From c87542f8f3f4d57c09750fed7a0f55eb037134a8 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Mon, 28 Apr 2025 08:43:35 -0700 Subject: [PATCH 12/16] feat: add simplified battery model --- examples/03_Existing Models.ipynb | 57 +++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 9e2e01f9..d82e86e3 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -28,6 +28,7 @@ " * [BatteryElectroChemEOD](#BatteryElectroChemEOD)\n", " * [BatteryElectroChemEOL](#BatteryElectroChemEOL)\n", " * [Combined BatteryElectroChem (BatteryElectroChemEODEOL)](#Combined-BatteryElectroChem-(BatteryElectroChemEODEOL))\n", + " * [Simplified Battery](#Simplified-Battery)\n", "* [Centrifugal Pump Model](#Centrifugal-Pump-Model)\n", "* [Electric Powertrain Models](#Electric-Powertrain-Models)\n", "* [Pneumatic Valve Model](#Pneumatic-Valve-Model)\n", @@ -45,7 +46,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In the following battery models, the default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the Prognostics Center of Excellence [Data Repository](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository)." + "We will start by introducing the battery models: `BatteryCircuit`, `BatteryElectroChemEOD`, `BatteryElectroChemEOL`, combined `BatteryElectroChem` (`BatteryElectroChemEODEOL`), and `SimplifiedBattery`.\n", + "\n", + "In the following battery models, with the exception of `SimplifiedBattery`, the default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the Prognostics Center of Excellence [Data Repository](https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository)." ] }, { @@ -452,7 +455,6 @@ " 'save_freq': 1000,\n", " 'dt': 2,\n", " 'events': 'InsufficientCapacity',\n", - " 'print': True\n", "}\n", "\n", "def future_loading(t, x=None):\n", @@ -535,6 +537,57 @@ "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'})" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simplified Battery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`SimplifiedBattery` is a model from [[Sierra 2019]](https://www.sciencedirect.com/science/article/abs/pii/S0951832018301406). It was initially introduced in the __[2024 PHM Tutorial](2024PHMTutorial.ipynb)__. Unlike the previous models, the default parameters are for a Tattu battery. Let's start by importing the model, initializing an instance, and examining it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from progpy.models import SimplifiedBattery\n", + "\n", + "batt = SimplifiedBattery()\n", + "\n", + "print('inputs:', batt.inputs)\n", + "print('outputs:', batt.outputs)\n", + "print('event(s): ', batt.events)\n", + "print('states:', batt.states)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now define future loading based on a piecewise function and simulate to a set time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "future_loading = Piecewise(\n", + " dict,\n", + " [600, 900, 1800, 3000, float('inf')],\n", + " {'P': [25, 12, 50, 25, 33]})\n", + "\n", + "result = batt.simulate_to(200, future_loading, {'v': 4.183})" + ] + }, { "cell_type": "markdown", "metadata": {}, From daa1b9db2a666701eb79096036ef09044f078005 Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Mon, 5 May 2025 09:11:27 -0700 Subject: [PATCH 13/16] fix: add example for simplified battery --- examples/03_Existing Models.ipynb | 44 +++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index d82e86e3..53651237 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -548,7 +548,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`SimplifiedBattery` is a model from [[Sierra 2019]](https://www.sciencedirect.com/science/article/abs/pii/S0951832018301406). It was initially introduced in the __[2024 PHM Tutorial](2024PHMTutorial.ipynb)__. Unlike the previous models, the default parameters are for a Tattu battery. Let's start by importing the model, initializing an instance, and examining it." + "`SimplifiedBattery` is a model from [[Sierra 2019]](https://www.sciencedirect.com/science/article/abs/pii/S0951832018301406). It was initially introduced in the __[2024 PHM Tutorial](2024PHMTutorial.ipynb)__. Unlike the previous models, the default parameters are for a Tattu battery. We can refer to the [documentation](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html) for more details.\n", + "\n", + "Let's start by importing the model, initializing an instance, and examining it." ] }, { @@ -558,6 +560,7 @@ "outputs": [], "source": [ "from progpy.models import SimplifiedBattery\n", + "from progpy.loading import Piecewise\n", "\n", "batt = SimplifiedBattery()\n", "\n", @@ -585,7 +588,23 @@ " [600, 900, 1800, 3000, float('inf')],\n", " {'P': [25, 12, 50, 25, 33]})\n", "\n", - "result = batt.simulate_to(200, future_loading, {'v': 4.183})" + "simulated_results = batt.simulate_to(200, future_loading, {'v': 4.183})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's look at the event states plot, where we can see `EOD` and `Low V`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state')" ] }, { @@ -595,6 +614,13 @@ "## Centrifugal Pump Model" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**A version of this section will be added in release v1.9**" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -602,12 +628,26 @@ "## Pneumatic Valve Model" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**A version of this section will be added in release v1.9**" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Aircraft Flight Model" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**A version of this section will be added in release v1.9**" + ] } ], "metadata": { From cd55efddd5689d7f8c93677850ad2d2a1afc439c Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Mon, 5 May 2025 09:15:18 -0700 Subject: [PATCH 14/16] Revert "Revert "feat: start adding battery models"" This reverts commit a1c6b08819b4c7dfda8bc1b70f112bcc6cb95891. --- examples/03_Existing Models.ipynb | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 53651237..71c5317d 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -621,6 +621,13 @@ "**A version of this section will be added in release v1.9**" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Electric Powertrain Models" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -652,16 +659,28 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "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", - "version": "3.12.9" - }, - "orig_nbformat": 4 + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" + }, + "vscode": { + "interpreter": { + "hash": "610c699f0cd8c4f129acd9140687fff6866bed0eb8e82f249fc8848b827b628c" + } + } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From b67b929a8c8825d5c9fd308f454937b2ab3cec4c Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Mon, 5 May 2025 09:19:55 -0700 Subject: [PATCH 15/16] fix: undo metadata --- examples/03_Existing Models.ipynb | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 71c5317d..7ecae087 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -659,22 +659,15 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3.10.7 64-bit", "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.10.5" + "version": "3.10.7" }, + "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "610c699f0cd8c4f129acd9140687fff6866bed0eb8e82f249fc8848b827b628c" @@ -682,5 +675,5 @@ } }, "nbformat": 4, - "nbformat_minor": 4 + "nbformat_minor": 2 } From cba98f8fc2b8c1ea29aacfb25223ec6fd486027d Mon Sep 17 00:00:00 2001 From: Michelle Ly Date: Tue, 6 May 2025 12:14:16 -0700 Subject: [PATCH 16/16] fix: add titles --- examples/03_Existing Models.ipynb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/03_Existing Models.ipynb b/examples/03_Existing Models.ipynb index 7ecae087..c5a50c51 100644 --- a/examples/03_Existing Models.ipynb +++ b/examples/03_Existing Models.ipynb @@ -197,7 +197,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)', title='BatteryCircuit Input')" ] }, { @@ -213,7 +213,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4))\n", + "fig = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (K)', figsize=(10,4), title='BatteryCircuit Outputs')\n", "fig2 = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))" ] }, @@ -282,7 +282,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)', title='BatteryElectroChemEOD Input')" ] }, { @@ -298,7 +298,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4), title='BatteryElectroChemEOD Outputs')\n", "print(\"End of discharge voltage threshold:\", batt.parameters['VEOD'])\n", "\n", "fig2 = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (°C)', figsize=(10,4))" @@ -317,7 +317,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'EOD'})" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'EOD'}, title='BatteryElectroChemEOD Event State')" ] }, { @@ -385,7 +385,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)')" + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current draw (amps)', title='BatteryElectroChemEOL Input')" ] }, { @@ -401,7 +401,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'InsufficientCapacity'})" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', labels={'InsufficientCapacity'}, title='BatteryElectroChemEOL Event State')" ] }, { @@ -499,7 +499,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)')" + "fig = simulated_results.inputs.plot(xlabel='time (s)', ylabel='current drawn (amps)', title='BatteryElectroChem Input')" ] }, { @@ -515,7 +515,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4))\n", + "fig = simulated_results.outputs.plot(keys=['v'], xlabel='time (s)', ylabel='voltage (V)', figsize=(10,4), title='BatteryElectroChem Outputs')\n", "fig2 = simulated_results.outputs.plot(keys=['t'], xlabel='time (s)', ylabel='temperature (°C)', figsize=(10,4))" ] }, @@ -534,7 +534,7 @@ }, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'})" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event states', labels={'EOD', 'InsufficientCapacity'}, title='BatteryElectroChem Event States')" ] }, { @@ -604,7 +604,7 @@ "metadata": {}, "outputs": [], "source": [ - "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state')" + "fig = simulated_results.event_states.plot(xlabel='time (s)', ylabel='event state', title='SimplifiedBattery Event States')" ] }, {