Skip to content

Commit

Permalink
fix tutorial 03
Browse files Browse the repository at this point in the history
* streamline usage of forecaster
  • Loading branch information
maurerle committed Nov 22, 2024
1 parent 9652686 commit 03e69b1
Showing 1 changed file with 69 additions and 43 deletions.
112 changes: 69 additions & 43 deletions examples/notebooks/03_custom_unit_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"\n",
"**We will cover the following topics:**\n",
"\n",
"1. Essential concepts and terminology in electricity market modeling\n",
"2. Setting up the ASSUME framework\n",
"3. Developing a new Demand Side Unit\n",
"4. Formulating a rule-based bidding strategy\n",
"5. Integrating the new unit and strategy into the ASSUME simulation"
"1. [Essential concepts and terminology in electricity market modeling](#1-introduction-to-unit-agents-and-bidding-strategy)\n",
"2. [Setting up the ASSUME framework](#2-setting-up-assume)\n",
"3. [Developing a new Demand Side Unit](#3-developing-a-new-demand-side-unit)\n",
"4. [Formulating a rule-based bidding strategy](#4-rule-based-bidding-strategy)\n",
"5. [Integrating the new unit and strategy into the ASSUME simulation](#5-integrating-the-new-unit-and-strategy-into-assume)"
]
},
{
Expand Down Expand Up @@ -50,8 +50,12 @@
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"execution_count": 12,
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [
{
"data": {
Expand All @@ -65,7 +69,7 @@
}
],
"source": [
"# this cell is used to display the image in the notebook when using collab\n",
"# this cell is used to display the image in the notebook when using colab\n",
"# or running the notebook locally\n",
"\n",
"import os\n",
Expand Down Expand Up @@ -126,27 +130,25 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"metadata": {},
"outputs": [],
"source": [
"!pip install assume-framework"
"import importlib.util\n",
"\n",
"# Check if 'google.colab' is available\n",
"IN_COLAB = importlib.util.find_spec(\"google.colab\") is not None\n",
"if IN_COLAB:\n",
" !pip install assume-framework"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"metadata": {},
"outputs": [],
"source": [
"!git clone --depth=1 https://github.com/assume-framework/assume.git assume-repo"
"if IN_COLAB:\n",
" !git clone --depth=1 https://github.com/assume-framework/assume.git assume-repo"
]
},
{
Expand All @@ -171,11 +173,6 @@
"metadata": {},
"outputs": [],
"source": [
"import importlib.util\n",
"\n",
"# Check if 'google.colab' is available\n",
"IN_COLAB = importlib.util.find_spec(\"google.colab\") is not None\n",
"\n",
"colab_inputs_path = \"assume-repo/examples/inputs\"\n",
"local_inputs_path = \"../inputs\"\n",
"\n",
Expand Down Expand Up @@ -205,7 +202,7 @@
"- **Bidding Strategies**: The strategies used by the unit for bidding in the electricity market.\n",
"- **Max Power and Min Power**: The maximum and minimum electrical power that the unit can handle.\n",
"- **Max Hydrogen and Min Hydrogen**: The maximum and minimum hydrogen production levels.\n",
"- **Fixed Cost**: The fixed operational cost for the unit."
"- **Additional Cost**: The fixed operational cost for the unit."
]
},
{
Expand All @@ -216,6 +213,8 @@
"source": [
"# Initialize the Electrolyser class with core attributes\n",
"\n",
"from datetime import datetime\n",
"\n",
"import pandas as pd\n",
"\n",
"from assume.common.base import BaseStrategy, SupportsMinMax\n",
Expand All @@ -230,11 +229,11 @@
" technology: str,\n",
" unit_operator: str,\n",
" bidding_strategies: str,\n",
" forecaster: Forecaster,\n",
" max_power: float,\n",
" min_power: float,\n",
" max_hydrogen: float,\n",
" min_hydrogen: float,\n",
" forecaster: Forecaster,\n",
" additional_cost: float,\n",
" **kwargs,\n",
" ):\n",
Expand All @@ -261,8 +260,8 @@
" # and is executed after each market clearing\n",
" def execute_current_dispatch(\n",
" self,\n",
" start: pd.Timestamp,\n",
" end: pd.Timestamp,\n",
" start: datetime,\n",
" end: datetime,\n",
" ):\n",
" # Calculate mean power for this time period\n",
" avg_power = abs(self.outputs[\"energy\"].loc[start:end]).mean()\n",
Expand Down Expand Up @@ -347,12 +346,12 @@
"class Electrolyser(Electrolyser):\n",
" def calculate_min_max_power(\n",
" self,\n",
" start: pd.Timestamp,\n",
" end: pd.Timestamp,\n",
" hydrogen_demand=0,\n",
" start: datetime,\n",
" end: datetime,\n",
" ):\n",
" # check if hydrogen_demand is within min and max hydrogen production\n",
" # and adjust accordingly\n",
" hydrogen_demand = self.forecaster[\"hydrogen_demand\"][start]\n",
" if hydrogen_demand < self.min_hydrogen:\n",
" hydrogen_production = self.min_hydrogen\n",
"\n",
Expand All @@ -368,7 +367,20 @@
" )\n",
" power = hydrogen_production * dynamic_conversion_factor\n",
"\n",
" return power, hydrogen_production"
" return power, hydrogen_production\n",
"\n",
" def calculate_marginal_cost(self, start: datetime, power: float = 0) -> float:\n",
" \"\"\"\n",
" Calculate the marginal cost of the unit returns the marginal cost of the unit based on the provided time and power.\n",
"\n",
" Args:\n",
" start (pandas.Timestamp): The start time of the dispatch.\n",
" power (float): The power output of the unit.\n",
"\n",
" Returns:\n",
" float: the marginal cost of the unit for the given power.\n",
" \"\"\"\n",
" return self.forecaster[\"fuel_price\"].at[start]"
]
},
{
Expand Down Expand Up @@ -440,7 +452,7 @@
"source": [
"The `NaiveStrategyElectrolyser` class inherits from the `BaseStrategy` class and implements the `calculate_bids` method, which is responsible for formulating the market bids:\n",
"\n",
"`calculate_bids` method takes several arguments, including the unit to be dispatched (`unit`), the market configuration (`market_config`), and a list of products (`product_tuples`). It returns an `Orderbook` containing the bids.\n",
"The `calculate_bids` method takes several arguments, including the unit to be dispatched (`unit`), the market configuration (`market_config`), and a list of products (`product_tuples`). It returns an `Orderbook` containing the bids.\n",
"\n",
"In this case, we use **Marginal Revenue** to determine the price at which the unit should make its bid. The equation used in the code is as follows:\n",
"\n",
Expand Down Expand Up @@ -492,15 +504,13 @@
"\n",
" # Get hydrogen demand and price for the product start time\n",
" # in this case for the start hour of the product\n",
" hydrogen_demand = unit.forecaster[f\"{unit.id}_h2demand\"].loc[start]\n",
" hydrogen_price = unit.forecaster[f\"{unit.id}_h2price\"].loc[start]\n",
" hydrogen_price = unit.calculate_marginal_cost(start=start)\n",
"\n",
" # Calculate the required power and the actual possible hydrogen production\n",
" # given the hydrogen demand\n",
" power, hydrogen_production = unit.calculate_min_max_power(\n",
" start=start,\n",
" end=end,\n",
" hydrogen_demand=hydrogen_demand,\n",
" )\n",
"\n",
" # Calculate the marginal revenue of producing hydrogen\n",
Expand Down Expand Up @@ -553,7 +563,7 @@
"from dateutil import rrule as rr\n",
"\n",
"from assume import World\n",
"from assume.common.forecasts import CsvForecaster, NaiveForecast\n",
"from assume.common.forecasts import NaiveForecast\n",
"from assume.common.market_objects import MarketConfig, MarketProduct\n",
"\n",
"logger = logging.getLogger(__name__)\n",
Expand Down Expand Up @@ -588,6 +598,7 @@
" end=end,\n",
" save_frequency_hours=None,\n",
" simulation_id=sim_id,\n",
" index=index,\n",
")\n",
"\n",
"# define market design and add it to a market\n",
Expand Down Expand Up @@ -658,9 +669,12 @@
"\n",
"# add the electrolyser unit to the world\n",
"world.add_unit_operator(id=\"electrolyser_operator\")\n",
"hydrogen_plant_forecaster = CsvForecaster(index=index)\n",
"hydrogen_plant_forecaster.set_forecast(data=hydrogen_forecasts)\n",
"hydrogen_plant_forecaster.convert_forecasts_to_fast_series()\n",
"\n",
"hydrogen_plant_forecaster = NaiveForecast(\n",
" index=index,\n",
" demand=hydrogen_forecasts[\"electrolyser_01_h2demand\"],\n",
" fuel_cost=hydrogen_forecasts[\"electrolyser_01_h2price\"],\n",
")\n",
"\n",
"world.add_unit(\n",
" id=\"electrolyser_01\",\n",
Expand All @@ -676,8 +690,15 @@
" \"additional_cost\": 10,\n",
" },\n",
" forecaster=hydrogen_plant_forecaster,\n",
")\n",
"\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# run the simulation\n",
"world.run()"
]
Expand Down Expand Up @@ -767,6 +788,11 @@
"source": [
"This concludes our tutorial. By following these steps, you have successfully created a Demand Side Unit with a Rule-Based Bidding Strategy and integrated it into the ASSUME framework."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
Expand Down

0 comments on commit 03e69b1

Please sign in to comment.