{ "cells": [ { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "#### Imports" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [ "exclude" ] }, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\__init__.py\n" ] } ], "source": [ "from datetime import timedelta, datetime\n", "import json\n", "import pprint\n", "from copy import deepcopy\n", "import pytz\n", "\n", "import cufflinks\n", "cufflinks.go_offline()\n", "import numpy as np\n", "from numpy.polynomial import Polynomial\n", "import pandas as pd\n", "from tqdm.notebook import tqdm\n", "\n", "import sys\n", "\n", "import os\n", " \n", "# Path to the folder containing the alternate version of PyRecoy\n", "\n", "alternate_pyrecoy_path = 'C:\\\\Users\\\\z004yn8c\\\\OneDrive - Siemens AG\\\\Documents\\\\GitHub\\\\Mooi-Kickstart\\\\pyrecoy\\\\pyrecoy'\n", " \n", "# Add the path to sys.path\n", "\n", "if alternate_pyrecoy_path not in sys.path:\n", "\n", " sys.path.insert(0, alternate_pyrecoy_path)\n", " \n", "# Now import PyRecoy\n", "\n", "import pyrecoy2\n", "\n", "# Check the version or path to confirm\n", "\n", "print(pyrecoy2.__file__)\n", "\n", "\n", "from pyrecoy2.assets_kickstart import Heatpump, Eboiler, GasBoiler, HotWaterStorage\n", "from pyrecoy2.colors import *\n", "from pyrecoy2.converters import *\n", "from pyrecoy2.financial import calculate_eb_ode, get_tax_tables, get_tax_rate, get_grid_tariffs_electricity\n", "from pyrecoy2.framework import TimeFramework\n", "from pyrecoy2.casestudy import CaseStudy\n", "from pyrecoy2.plotting import ebitda_bar_chart, npv_bar_chart\n", "from pyrecoy2.reports import CaseReport, ComparisonReport, BusinessCaseReport, SingleFigureComparison\n", "from pyrecoy2.sensitivity import SensitivityAnalysis\n", "from pyrecoy2.prices import get_tennet_data, get_afrr_capacity_fees_nl\n", "from pyrecoy2.forecasts import Mipf, Forecast\n", "\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "#### Development backlog" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "* aFRR (can improve the optimisation case)\n", "* Report\n", "* COP seems to have fix values, rather than COP curve" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "#### Meeting Notes" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "##### Meeting 25-11-2020" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "* aFRR can help optimisation case\n", "* SDE++ should be included\n", "* Tsource sensitivity really gives interesting insights\n", "* Sensitivities should be verified (especially CO2, Tsink, Tsource, time period)\n", "* AP TNO: Update/verify COP curve\n", "* AP TNO: Update CAPEX\n", "* AP Mark: \n", " * Create graphs on COP curve with different Tsource, Tsink\n", " * Generate table and output in .csv (send it to Andrew)\n", "* Investigate opportunity to lower the COP and negative electricity prices\n", " * Technically feasible, but not really needed/possible to do it in this project\n", "* Could be interesting to run this model on a usecase with higher delta T\n", "* Conclusion: Finalize this model, but not add too much extra complexity, next steps is to go towards industrial partners with the results" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "# Kickstart: Heatpump Optimisation Framework\n", "\n", "***\n", "© Shahla Huseynova \n", "July 2024\n", "##### Cases\n", "In this model, 4 cases are compared:\n", "* **Baseline** : All heat is supplied by steam turbine\n", "* **Heatpump case** : All heat is supplied by heatpump\n", "* **Hybrid case** : Steam boiler and heatpump run in hybrid mode, and are optimised on costs in real-time\n", "* **Heat pump & storage cases**: Heat pump only case is compared with different setup of storage +heat pump cases" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "#### Loading config" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [ "exclude" ] }, "outputs": [], "source": [ "class Config():\n", " start = '2023-01-01'\n", " end = '2023-12-31'\n", " # year = '2019'\n", " # startdate = year + '-01-01'\n", " # enddate = str(year) + '-12-31'\n", " # start = datetime.strptime(startdate, \"%Y-%m-%d\").astimezone(pytz.timezone('Europe/Amsterdam'))\n", " # end = datetime.strptime(enddate, \"%Y-%m-%d\").astimezone(pytz.timezone('Europe/Amsterdam'))\n", " # start = start.astimezone(pytz.UTC)\n", " # end = end.astimezone(pytz.UTC)\n", " \n", " hp_e_power = 1.5 # MW\n", " # hp_ndg_e_power = 7.7 # MW\n", " hp_min_load = 0\n", " hp_lifetime = 25\n", " hp_capex = 200_000 # EUR/MWth\n", " hp_opex = 0.01 # in % of CAPEX\n", " hp_devex = 0.005 # in % of CAPEX\n", " \n", " gb_power = 5 # MW\n", " gb_efficiency = 0.9\n", " \n", " storage_power = 1\n", " # storage_volume = 1000 *3/50\n", " # storage_cap_per_volume = 50 * 1e-3\n", " rated_capacity = 3\n", " storage_lifetime = 25\n", " storage_temperature = 144\n", " # storage_min_level = storage_volume * storage_cap_per_volume * 0.05\n", " storage_min_level = rated_capacity * 0.00\n", " # storage_min_level = rated_capacity\n", " storage_capex_per_MW = 60_000\n", " storage_capex_per_MWh = 0\n", " storage_opex_perc_of_capex = 0.02\n", " # storage_initial_level = 5\n", " threshold = 0\n", " \n", " tax_bracket_g = 4 \n", " tax_bracket_e = 4\n", " \n", " include_transport_costs = False\n", " grid_operator = 'Liander'\n", " connection_type = 'TS/MS'\n", " \n", " discount_rate = 0.1\n", " project_duration = 12\n", "\n", " forecast = 'ForeNeg'\n", " gas_price_multiplier = 1\n", " e_price_multiplier = 1\n", " e_price_volatility_multiplier = 1\n", " co2_price_multiplier = 1\n", " tsource_delta = 0\n", " tsink_delta = 0\n", " energy_tax_multiplier = 1\n", " \n", " # Review the SDE implementation\n", " sde_base_amount = 81\n", " longterm_gas_price = 24.00\n", " longterm_co2_price = 37.90\n", " sde_switch_price_correction = 40\n", " \n", " day_ahead_buying_perc = 0.3\n", " \n", " afrr_capacity_fee = 25_000\n", "\n", "c = Config()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [ "exclude" ] }, "outputs": [], "source": [ "class Store():\n", " pass" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "exclude" ] }, "source": [ "## Model set-up" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# Define the file paths\n", "excel_file_path = r'C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\Kickstart\\V2\\Demand_Data_Smurfit_Preprocessed3.xlsx'\n", "output_directory = r'C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\Kickstart\\V2\\data'\n", "output_file_name = 'smurfit_demand_preprocessed3.csv'\n", "csv_file_path = os.path.join(output_directory, output_file_name)\n", "\n", "df = pd.read_excel(excel_file_path)\n", "# df = df.fillna(0) \n", "\n", "# # Save the DataFrame to CSV\n", "df.to_csv(csv_file_path, index=False)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "tags": [ "exclude" ] }, "outputs": [], "source": [ "def load_demand_data(c, s):\n", " demand = pd.read_csv('data/smurfit_demand_preprocessed3.csv', delimiter=',', decimal='.')\n", " dt_index = pd.date_range(\n", " start=s.time_fw.start,\n", " end=s.time_fw.start + timedelta(days=365), \n", " freq='1T',\n", " tz='Europe/Amsterdam')\n", " dt_index = dt_index[:len(demand)]\n", " demand.index = dt_index\n", " demand['Total demand'] = demand['MW (VDG)']\n", " \n", " demand = demand[c.start:c.end]\n", " return demand" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "s = Store()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "tags": [ "exclude" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "testetss\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\framework.py:41: UserWarning:\n", "\n", "The chosen timeperiod spans 365.99930555555557 days, which is not a full year. Beware that certain functions that use yearly rates might return incorrect values.\n", "\n", "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\forecasts.py:62: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n", "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\forecasts.py:115: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n", "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\framework.py:54: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n", "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\framework.py:54: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n", "C:\\Users\\z004yn8c\\OneDrive - Siemens AG\\Documents\\GitHub\\Mooi-Kickstart\\pyrecoy\\pyrecoy\\pyrecoy2\\framework.py:54: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n", "C:\\Users\\z004yn8c\\AppData\\Local\\Temp\\ipykernel_7920\\2484316097.py:3: FutureWarning:\n", "\n", "'T' is deprecated and will be removed in a future version, please use 'min' instead.\n", "\n" ] } ], "source": [ "def setup_model(c):\n", " s = Store()\n", " \n", " s.time_fw = TimeFramework(start=c.start, end=c.end)\n", " # s.minute_ix = s.time_fw.dt_index(freq='1T')\n", " mipf = Mipf(None, start=s.time_fw.start, end=s.time_fw.end, from_database=True, add_days_to_start_end=False).data\n", " s.mipf = mipf\n", " s.baseline = CaseStudy(time_fw=s.time_fw, freq='1T', name='Baseline')\n", " s.hpcase = CaseStudy(time_fw=s.time_fw, freq='1T', name='Heatpump only', data=mipf)\n", " #s.hpcase_sde = CaseStudy(time_fw=s.time_fw, freq='1T', name='Heatpump + SDE', data=mipf)\n", " #s.optcase1 = CaseStudy(time_fw=s.time_fw, freq='1T', name='Optimisation', data=mipf)\n", " s.storage_case_PCM = CaseStudy(time_fw=s.time_fw, freq='1T', name='Heatpump + Storage_PCM', data=mipf)\n", " # s.storage_case_TCM = CaseStudy(time_fw=s.time_fw, freq='1T', name='Heatpump + Storage_TCM', data=mipf)\n", " # s.storage_case_battery = CaseStudy(time_fw=s.time_fw, freq='1T', name='Heatpump + Storage_battery', data=mipf)\n", " s.cases = list(CaseStudy.instances.values())\n", " s.optcases = [s.hpcase, s.storage_case_PCM]\n", " s.sde_cases = []\n", " \n", " s.demand = load_demand_data(c, s)\n", " return s\n", "\n", "s = setup_model(c)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "# s.demand.resample('15T').mean()[['Tsource (VDG)', 'Tsink (VDG)']].iplot()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| \n", " | Tsource (VDG) | \n", "Tsink (VDG) | \n", "MW (VDG) | \n", "Total demand | \n", "
|---|---|---|---|---|
| 2023-01-01 00:00:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:01:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:02:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:03:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:04:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 2023-12-31 23:55:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:56:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:57:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:58:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:59:00+01:00 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
525600 rows × 4 columns
\n", "| \n", " | DAM | \n", "POS | \n", "NEG | \n", "ForeNeg | \n", "ForePos | \n", "Gas prices (€/MWh) | \n", "CO2 prices (€/ton) | \n", "CO2 prices (€/MWh) | \n", "Tsource (VDG) | \n", "Tsink (VDG) | \n", "MW (VDG) | \n", "Total demand | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2023-01-01 00:00:00+01:00 | \n", "-3.61 | \n", "-209.40 | \n", "-209.40 | \n", "NaN | \n", "NaN | \n", "63.998 | \n", "5.23 | \n", "1.01 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:01:00+01:00 | \n", "-3.61 | \n", "-209.40 | \n", "-209.40 | \n", "NaN | \n", "NaN | \n", "63.998 | \n", "5.23 | \n", "1.01 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:02:00+01:00 | \n", "-3.61 | \n", "-209.40 | \n", "-209.40 | \n", "NaN | \n", "NaN | \n", "63.998 | \n", "5.23 | \n", "1.01 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:03:00+01:00 | \n", "-3.61 | \n", "-209.40 | \n", "-209.40 | \n", "NaN | \n", "NaN | \n", "63.998 | \n", "5.23 | \n", "1.01 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-01-01 00:04:00+01:00 | \n", "-3.61 | \n", "-209.40 | \n", "-209.40 | \n", "NaN | \n", "NaN | \n", "63.998 | \n", "5.23 | \n", "1.01 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 2023-12-31 23:55:00+01:00 | \n", "3.17 | \n", "-6.81 | \n", "-6.81 | \n", "-7.10 | \n", "-11.16 | \n", "29.927 | \n", "77.25 | \n", "14.90 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:56:00+01:00 | \n", "3.17 | \n", "-6.81 | \n", "-6.81 | \n", "-5.21 | \n", "-8.12 | \n", "29.927 | \n", "77.25 | \n", "14.90 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:57:00+01:00 | \n", "3.17 | \n", "-6.81 | \n", "-6.81 | \n", "-5.61 | \n", "-7.59 | \n", "29.927 | \n", "77.25 | \n", "14.90 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:58:00+01:00 | \n", "3.17 | \n", "-6.81 | \n", "-6.81 | \n", "-5.74 | \n", "-7.87 | \n", "29.927 | \n", "77.25 | \n", "14.90 | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
| 2023-12-31 23:59:00+01:00 | \n", "3.17 | \n", "-6.81 | \n", "-6.81 | \n", "-5.70 | \n", "-7.27 | \n", "NaN | \n", "NaN | \n", "NaN | \n", "70 | \n", "144 | \n", "1 | \n", "1 | \n", "
525600 rows × 12 columns
\n", "