{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Further extending MUSE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Adding a search space filter" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from muse.agents import Agent\n", "from muse.filters import register_filter\n", "from xarray import DataArray, Dataset\n", "\n", "\n", "@register_filter\n", "def no_ccgt_filter(\n", " agent: Agent, search_space: DataArray, technologies: Dataset, market: Dataset\n", ") -> DataArray:\n", " \"\"\"Excludes gasCCGT.\"\"\"\n", " dropped_tech = search_space.where(search_space.replacement != \"windturbine\")\n", " return search_space & search_space.replacement.isin(dropped_tech.replacement)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import logging\n", "import os\n", "\n", "from muse import examples\n", "from muse.mca import MCA\n", "\n", "model_path = examples.copy_model(overwrite=True)\n", "logging.getLogger(\"muse\").setLevel(0)\n", "mca = MCA.factory(os.path.join(model_path, \"settings.toml\"))\n", "mca.run();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "mca_capacity = pd.read_csv(\"Results/MCACapacity.csv\")\n", "power_capacity = (\n", " mca_capacity[mca_capacity.sector == \"power\"]\n", " .groupby([\"technology\", \"year\"])\n", " .sum()\n", " .reset_index()\n", ")\n", "ax = power_capacity.pivot(index=\"year\", columns=\"technology\", values=\"capacity\").plot(\n", " kind=\"bar\", stacked=True\n", ")\n", "ax.set_ylabel(\"Capacity (PJ)\")\n", "ax.tick_params(axis=\"x\", labelrotation=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Registering a custom decision function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we would like to add an additional decision function. A decision function is a transformation applied to aggregate multiple objectives into a single objective during agent investment. For example, through the use of a weighted sum. \n", "\n", "In this example, we would like to take the median objective. However, the functions predefined in MUSE don't include this functionality. MUSE contains examples such as the mean, weighted sum and a single objective. Therefore we will have to register and create our own.\n", "\n", "Now, we create our new `median_objective` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from typing import Any\n", "\n", "from muse.decisions import register_decision\n", "from xarray import DataArray, Dataset\n", "\n", "\n", "@register_decision\n", "def median_objective(objectives: Dataset, parameters: Any, **kwargs) -> DataArray:\n", " from xarray import concat\n", "\n", " allobjectives = concat(objectives.data_vars.values(), dim=\"concat_var\")\n", " return allobjectives.median(set(allobjectives.dims) - {\"asset\", \"replacement\"})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After importing the decorator function, `register_decision`, and ensuring that we decorate our new function with `@register_decision`, we are able to create our new function as above.\n", "\n", "Our new function `median_objective` modifies the `mean` function already built into MUSE, with one difference. Replacing the return value, from `allobjectives.mean` to `allobjectives.mean`.\n", "\n", " @register_decision\n", " def mean(objectives: Dataset, *args, **kwargs) -> DataArray:\n", " \"\"\"Mean over objectives.\"\"\"\n", " from xarray import concat\n", "\n", " allobjectives = concat(objectives.data_vars.values(), dim=\"concat_var\")\n", " return allobjectives.mean(set(allobjectives.dims) - {\"asset\", \"replacement\"})\n", " \n", "Of course, you are free to make your functions as complicated as you like, depending on your own requirements.\n", "\n", "Next, we must edit our `Agents.csv` file. We will modify the `default` example for this tutorial. We change the first two entry rows, to be as follows:\n", "\n", " Agent1,A1,1,R1,LCOE,NPV,EAC,1,,,TRUE,,,all,median_objective,1,-1,inf,New\n", " Agent2,A1,2,R1,LCOE,NPV,EAC,1,,,TRUE,,,all,median_objective,1,-1,inf,Retrofit\n", "\n", "Here, we add the NPV and EAC decision metrics, as well as replacing the `singleObj` `DecisionMethod` to `median_objective`.\n", "\n", "Now we are able to run our modified model as before:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "logging.getLogger(\"muse\").setLevel(0)\n", "mca = MCA.factory(\"../tutorial-code/0-new-decision-metric/settings.toml\")\n", "mca.run();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, we visualise the power sector:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "mca_capacity = pd.read_csv(\n", " \"../tutorial-code/0-new-decision-metric/Results/MCACapacity.csv\"\n", ")\n", "power_capacity = (\n", " mca_capacity[mca_capacity.sector == \"power\"]\n", " .groupby([\"technology\", \"year\"])\n", " .sum()\n", " .reset_index()\n", ")\n", "ax = power_capacity.pivot(index=\"year\", columns=\"technology\", values=\"capacity\").plot(\n", " kind=\"bar\", stacked=True\n", ")\n", "ax.set_ylabel(\"Capacity (PJ)\")\n", "ax.tick_params(axis=\"x\", labelrotation=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We see a different scenario emerge through these different decision metrics. This shows the importance of decision metrics when making long-term investment decisions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## End of tutorials\n", "\n", "In these tutorials you have seen the ways in which you can modify MUSE. All of these methods can be combined and extended to make as simple or complex model as you wish. Feel free to experiment and come up with your own ideas for your future work!\n", "\n", "For further information, we refer you to the API in the next section." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.9.0 ('muse39')", "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.18" }, "vscode": { "interpreter": { "hash": "22ff8bbda430c28f07def99f448c0c69dabbaf0c7d993cae69f87b3c458d04b2" } } }, "nbformat": 4, "nbformat_minor": 4 }