diff --git a/teaching/03_Energy_system_expansion_planning.ipynb b/teaching/03_Sector_coupling.ipynb
similarity index 80%
rename from teaching/03_Energy_system_expansion_planning.ipynb
rename to teaching/03_Sector_coupling.ipynb
index 90bf6c8f..2eb813a3 100644
--- a/teaching/03_Energy_system_expansion_planning.ipynb
+++ b/teaching/03_Sector_coupling.ipynb
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Example 3: Energy system expansion planning"
+ "# Example 3: Sector coupling"
]
},
{
@@ -93,8 +93,8 @@
" mydata[\"sites\"] = [\"OldTown\", \"NewTown\", \"FutureTown\"]\n",
" mydata[\"commodities\"] = [\"Elec\", \"Heat\", \"Gas\", \"SolarPV\", \"SolarThermal\", \"CO2\", \"AmbientTemp\"]\n",
" mydata[\"com_type\"] = [\"Demand\", \"Stock\", \"Env\", \"SupIm\"] # (i.e. SupIm, Demand, Stock, Env)\n",
- " mydata[\"process\"] = [\"Gas plant\", \"PV plant\", \n",
- " \"Gas boiler\", \"Solar thermal\",\n",
+ " mydata[\"process\"] = [\"Gas CC\", \"PV plant\", \n",
+ " \"Gas heating plant\", \"Solar thermal\",\n",
" \"Gas CHP\", # CHP: combined heat and power\n",
" \"Heat pump\", \"Electric resistance\"] \n",
" mydata[\"cost_type\"] = ['Invest', 'Fixed', 'Variable', 'Fuel', 'Environmental']\n",
@@ -104,7 +104,7 @@
" mydata[\"com_max\"] = {}\n",
" for stf in mydata[\"support_timeframes\"]:\n",
" for sit in mydata[\"sites\"]:\n",
- " mydata[\"com_prices\"].update({(stf, sit, \"Gas\", \"Stock\"): 24.8,\n",
+ " mydata[\"com_prices\"].update({(stf, sit, \"Gas\", \"Stock\"): 25.2,\n",
" (stf, sit, \"SolarPV\", \"SupIm\"): 0,\n",
" (stf, sit, \"SolarThermal\", \"SupIm\"): 0,\n",
" (stf, sit, \"AmbientTemp\", \"SupIm\"): 0,\n",
@@ -122,18 +122,18 @@
"\n",
" # Dictionaries - processes\n",
" mydata[\"pro_capup\"] = {\n",
- " (2021, \"OldTown\", \"Gas boiler\"): np.inf, # for heat\n",
+ " (2021, \"OldTown\", \"Gas heating plant\"): np.inf, # for heat\n",
" (2021, \"OldTown\", \"Solar thermal\"): np.inf, # for heat\n",
- " (2021, \"OldTown\", \"Gas plant\"): np.inf, # for electricity\n",
+ " (2021, \"OldTown\", \"Gas CC\"): np.inf, # for electricity\n",
" (2021, \"OldTown\", \"PV plant\"): np.inf, # for electricity\n",
" \n",
- " (2021, \"NewTown\", \"Gas boiler\"): np.inf, # for heat\n",
+ " (2021, \"NewTown\", \"Gas heating plant\"): np.inf, # for heat\n",
" (2021, \"NewTown\", \"Solar thermal\"): np.inf, # for heat\n",
- " (2021, \"NewTown\", \"Gas plant\"): np.inf, # for electricity\n",
+ " (2021, \"NewTown\", \"Gas CC\"): np.inf, # for electricity\n",
" (2021, \"NewTown\", \"PV plant\"): np.inf, # for electricity\n",
" (2021, \"NewTown\", \"Gas CHP\"): np.inf, # for electricity and heat\n",
" \n",
- " (2021, \"FutureTown\", \"Gas plant\"): np.inf, # for electricity\n",
+ " (2021, \"FutureTown\", \"Gas CC\"): np.inf, # for electricity\n",
" (2021, \"FutureTown\", \"PV plant\"): np.inf, # for electricity\n",
" (2021, \"FutureTown\", \"Heat pump\"): np.inf, # for heat from electricity\n",
" (2021, \"FutureTown\", \"Electric resistance\"): np.inf, # for heat from electricity\n",
@@ -153,22 +153,22 @@
" mydata[\"pro_depreciation\"] = mydata[\"pro_instcap\"].copy()\n",
" \n",
" for (stf, sit, pro) in mydata[\"pro_invcost\"].keys():\n",
- " mydata[\"pro_wacc\"][(stf, sit, pro)] = 0.07 # weigthed average cost of capital (in % of capital cost)\n",
- " if pro == \"Gas plant\":\n",
- " mydata[\"pro_invcost\"][(stf, sit, pro)] = 850000\n",
- " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 21250\n",
- " mydata[\"pro_varcost\"][(stf, sit, pro)] = 2\n",
+ " mydata[\"pro_wacc\"][(stf, sit, pro)] = 0.05 # weigthed average cost of capital (in % of capital cost)\n",
+ " if pro == \"Gas CC\":\n",
+ " mydata[\"pro_invcost\"][(stf, sit, pro)] = 900000\n",
+ " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 22000\n",
+ " mydata[\"pro_varcost\"][(stf, sit, pro)] = 4\n",
" mydata[\"pro_depreciation\"][(stf, sit, pro)] = 30\n",
" if pro == \"PV plant\":\n",
- " mydata[\"pro_invcost\"][(stf, sit, pro)] = 800000\n",
- " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 13600\n",
+ " mydata[\"pro_invcost\"][(stf, sit, pro)] = 700000\n",
+ " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 22000\n",
" mydata[\"pro_varcost\"][(stf, sit, pro)] = 0\n",
" mydata[\"pro_depreciation\"][(stf, sit, pro)] = 25\n",
- " if pro == \"Gas boiler\":\n",
- " mydata[\"pro_invcost\"][(stf, sit, pro)] = 500000\n",
- " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 25000\n",
- " mydata[\"pro_varcost\"][(stf, sit, pro)] = 3\n",
- " mydata[\"pro_depreciation\"][(stf, sit, pro)] = 15\n",
+ " if pro == \"Gas heating plant\":\n",
+ " mydata[\"pro_invcost\"][(stf, sit, pro)] = 400000\n",
+ " mydata[\"pro_fixcost\"][(stf, sit, pro)] = 12000\n",
+ " mydata[\"pro_varcost\"][(stf, sit, pro)] = 6.7\n",
+ " mydata[\"pro_depreciation\"][(stf, sit, pro)] = 35\n",
" if pro == \"Solar thermal\":\n",
" mydata[\"pro_invcost\"][(stf, sit, pro)] = 800000\n",
" mydata[\"pro_fixcost\"][(stf, sit, pro)] = 13600\n",
@@ -185,16 +185,16 @@
" mydata[\"pro_varcost\"][(stf, sit, pro)] = 0\n",
" mydata[\"pro_depreciation\"][(stf, sit, pro)] = 15\n",
" if pro == \"Electric resistance\":\n",
- " mydata[\"pro_invcost\"][(stf, sit, pro)] = 100000\n",
+ " mydata[\"pro_invcost\"][(stf, sit, pro)] = 150000\n",
" mydata[\"pro_fixcost\"][(stf, sit, pro)] = 5000\n",
" mydata[\"pro_varcost\"][(stf, sit, pro)] = 0\n",
" mydata[\"pro_depreciation\"][(stf, sit, pro)] = 10\n",
"\n",
" # Dictionaries - conversion ratios\n",
" mydata[\"ratio_in\"] = {\n",
- " (2021, \"Gas plant\", \"Gas\"): 1.67,\n",
+ " (2021, \"Gas CC\", \"Gas\"): 1.67,\n",
" (2021, \"PV plant\", \"SolarPV\"): 1,\n",
- " (2021, \"Gas boiler\", \"Gas\"): 1.09,\n",
+ " (2021, \"Gas heating plant\", \"Gas\"): 1.25,\n",
" (2021, \"Solar thermal\", \"SolarThermal\"): 1,\n",
" (2021, \"Gas CHP\", \"Gas\"): 2.22,\n",
" (2021, \"Heat pump\", \"Elec\"): 1,\n",
@@ -202,17 +202,17 @@
" (2021, \"Electric resistance\", \"Elec\"): 1,\n",
" }\n",
" mydata[\"ratio_out\"] = {\n",
- " (2021, \"Gas plant\", \"Elec\"): 1,\n",
- " (2021, \"Gas plant\", \"CO2\"): 0.3,\n",
+ " (2021, \"Gas CC\", \"Elec\"): 1,\n",
+ " (2021, \"Gas CC\", \"CO2\"): 0.3,\n",
" (2021, \"PV plant\", \"Elec\"): 1,\n",
- " (2021, \"Gas boiler\", \"Heat\"): 1,\n",
- " (2021, \"Gas boiler\", \"CO2\"): 0.2,\n",
+ " (2021, \"Gas heating plant\", \"Heat\"): 1,\n",
+ " (2021, \"Gas heating plant\", \"CO2\"): 0.23,\n",
" (2021, \"Solar thermal\", \"Heat\"): 1,\n",
" (2021, \"Gas CHP\", \"Elec\"): 1,\n",
" (2021, \"Gas CHP\", \"Heat\"): 0.88,\n",
" (2021, \"Gas CHP\", \"CO2\"): 0.4,\n",
" (2021, \"Heat pump\", \"Heat\"): 5,\n",
- " (2021, \"Electric resistance\", \"Heat\"): 2.7,\n",
+ " (2021, \"Electric resistance\", \"Heat\"): 0.95,\n",
" }\n",
"\n",
" # Dictionaries - time series\n",
@@ -222,13 +222,14 @@
" ts_SolarPV = [0, 0, 0, 0, 0, 0.05, 0.1, 0.15, 0.22, 0.35, 0.4, 0.55, 0.5, 0.45, 0.39, 0.35, 0.3, 0.2, 0.05, 0, 0, 0, 0, 0]\n",
" ts_SolarThermal = [0, 0, 0, 0, 0, 0.05, 0.1, 0.15, 0.22, 0.35, 0.4, 0.55, 0.5, 0.45, 0.39, 0.35, 0.3, 0.2, 0.05, 0, 0, 0, 0, 0]\n",
"\n",
- " # Scale the ambient temperature time series so that the efficiency is 1 if temperature <= 5°C,\n",
- " # and decreases to 0.2 if >= 25°C\n",
+ " # Scale the ambient temperature time series so that the efficiency increases almost linearly with the temperature\n",
+ " # for the range that we are interested in.\n",
+ " # Approximation: https://www.researchgate.net/publication/273458507_A_new_two-degree-of-freedom_space_heating_model_for_demand_response/figures?lo=1\n",
" ts_AmbientTemp = np.array(ts_AmbientTemp, dtype=float)\n",
- " ts_AmbientTemp[np.array(ts_AmbientTemp)<=5] = 1\n",
- " ts_AmbientTemp[ts_AmbientTemp>=25] = 0.2\n",
- " ts_filter = ((ts_AmbientTemp>5) & (ts_AmbientTemp<25))\n",
- " ts_AmbientTemp[ts_filter] = np.exp(np.log(5)/20*(5-ts_AmbientTemp[ts_filter]))\n",
+ " ts_AmbientTemp = 0.03 * (ts_AmbientTemp + 15) + 3.1\n",
+ " ts_AmbientTemp[ts_AmbientTemp<=1] = 1\n",
+ " # What we have here is a COP... let's scale it so that it is lower than 1\n",
+ " ts_AmbientTemp = ts_AmbientTemp / 5\n",
"\n",
" mydata[\"demand\"] = {}\n",
" mydata[\"supim\"] = {}\n",
@@ -264,8 +265,8 @@
"outputs": [],
"source": [
"# Generate the data for the reference scenario\n",
- "data_ref = generate_scenario()\n",
- "%matplotlib inline"
+ "%matplotlib inline\n",
+ "data_ref = generate_scenario()"
]
},
{
@@ -324,7 +325,7 @@
"ax2.set_title(\"Temperature\")\n",
"plt.plot(AmbientTemp, color=\"red\")\n",
"ax2b = ax2.twinx()\n",
- "ax2b.set_ylim(0, 6)\n",
+ "ax2b.set_ylim(3.5, 4.5)\n",
"ax2b.set_ylabel(\"Heat pump COP [1]\")\n",
"ax2b.plot(ts_AmbientTemp[1:], color=\"black\")"
]
@@ -345,7 +346,31 @@
"metadata": {},
"outputs": [],
"source": [
- "data_ref[\"pro_invcost\"]"
+ "# Retrieve the SolarPV and SolarThermal timeseries\n",
+ "ts_SolarPV = []\n",
+ "ts_SolarThermal = []\n",
+ "for (stf, sit, com, tm), v in data_ref[\"supim\"].items():\n",
+ " if ((sit==\"OldTown\") and (com==\"SolarPV\")):\n",
+ " ts_SolarPV.append(v)\n",
+ " if ((sit==\"OldTown\") and (com==\"SolarThermal\")):\n",
+ " ts_SolarThermal.append(v)\n",
+ "# Plot them side by side\n",
+ "fig1 = plt.figure(figsize=[12, 5])\n",
+ "ax1a = fig1.add_subplot(1,2,1)\n",
+ "ax1a.set_xlim(1, 24)\n",
+ "ax1a.set_xlabel(\"tm\")\n",
+ "ax1a.set_ylim(0, 1)\n",
+ "ax1a.set_ylabel(\"SE Elec [MWh]\")\n",
+ "ax1a.set_title(\"SolarPV\")\n",
+ "plt.plot(ts_SolarPV, color=\"blue\")\n",
+ "fig1.add_subplot(1,2,2)\n",
+ "ax1b = fig1.add_subplot(1,2,2)\n",
+ "ax1b.set_xlim(1, 24)\n",
+ "ax1b.set_xlabel(\"tm\")\n",
+ "ax1b.set_ylim(0, 1)\n",
+ "ax1b.set_ylabel(\"SE Heat [MWh]\")\n",
+ "ax1b.set_title(\"SolarThermal\")\n",
+ "plt.plot(ts_SolarThermal, color=\"orange\")"
]
},
{
@@ -412,23 +437,24 @@
"# You can access the variables, for example the output of the processes\n",
"supply_data = {}\n",
"for (tm, stf, sit, com, com_type), x in model_ref.e_pro_out.items():\n",
- " supply_data[(tm, stf, sit, com, com_type)] = pyo.value(x)\n",
+ " supply_data[(tm, sit, com, com_type)] = pyo.value(x)\n",
"\n",
- "df_supply = pd.DataFrame.from_dict(supply_data, orient=\"index\", columns=[\"SE [MWh]\"])\n",
- "df_supply.index = pd.MultiIndex.from_tuples(df_supply.index, names=('t', 'stf', 'Site', 'Technology', 'Commodity'))\n",
- "df_supply.reorder_levels([2,4,3,0,1])"
+ "df_supply = pd.DataFrame.from_dict(supply_data, orient=\"index\", columns=[\"SE [MWh] or emissions [t_CO2]\"])\n",
+ "df_supply.index = pd.MultiIndex.from_tuples(df_supply.index, names=('t', 'Site', 'Technology', 'Commodity'))\n",
+ "df_supply = df_supply.reorder_levels([1,3,2,0])\n",
+ "df_supply.head()"
]
},
{
- "cell_type": "markdown",
+ "cell_type": "code",
+ "execution_count": null,
"metadata": {},
+ "outputs": [],
"source": [
- "***\n",
- "### Task\n",
- "1. Report the most important results (new capacities, costs, power mix over time) using the techniques that we learned on Day 01.\n",
- "2. Experiment with different scenarios (i.e. vary the settings when generating the data and solve the different models).\n",
- "3. Analyze the results and draw some conclusions.\n",
- "***"
+ "df_supply_elec = df_supply[df_supply.index.get_level_values(1) == 'Elec']\n",
+ "df_supply_elec = df_supply_elec.droplevel(1)\n",
+ "df_supply_elec.rename({\"SE [MWh] or emissions [kgCO2]\": \"SE [MWh]\"}, axis=1, inplace=True)\n",
+ "df_supply_elec.head()"
]
},
{
@@ -437,11 +463,9 @@
"source": [
"***\n",
"## Homework\n",
- "1. Add another energy sector (transportation). The demand of transportation can be expressed in vehicle-kilometers. The processes that convert gasoline/gas or electricity to vehicle-kilometers are conventional cars or battery electric vehicles (BEVs). Beware that we have not modeled storage so far.\n",
- "2. Perform a sensitivity analysis:
\n",
- " a. Experiment with different investment cost assumptions for BEVs
\n",
- " b. Experiment with different CO2 prices
\n",
- "3. In which town is it cheaper to decarbonize the system?\n",
+ "1. Report the most important results (new capacities, costs, power mix over time) using the techniques that we learned on Day 01.\n",
+ "2. Experiment with different scenarios (i.e. vary the settings when generating the data and solve the different models).\n",
+ "3. Analyze the results and draw some conclusions.\n",
"***"
]
}