{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Problem 5.1\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Integrated Energy Grids**\n",
"\n",
"**Problem 5.1**\n",
"\n",
"**Assume we have three buses (Denmark, Netherlands and Germany) with nominal voltage $V_{nom}$= 2000 V connected by three transmission lines. In the bus, Denmark there is a wind generator that is producing 100 MW. In the bus Germany, there is a load that is consuming 100 MW of active power and 100 MVAR of reactive power. The transmission lines DK-NL and NL-GE have a unitary resistance $r$=0.01 and reactance $x$=0.1. The transmission lines DK-GE has a unitary resistance $r$=0.02 and reactance $x$=0.1. Using Python for Power System Analysis (PyPSA):**\n",
"\n",
"**a) Calculate the power flows along the transmission lines using AC power flow representation.**\n",
"\n",
"**b) Calculate the power flows along the transmission lines using a linearized approximation (also known as DC optimal power flow) and discuss the results.**\n",
"\n",
"_Hint: It is recommended to follow the [PyPSA tutorial](https://martavp.github.io/integrated-energy-grids/intro-pypsa.html#) before trying this problem._"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{note}\n",
"If you have not yet set up Python on your computer, you can execute this tutorial in your browser via [Google Colab](https://colab.research.google.com/). Click on the rocket in the top right corner and launch \"Colab\". If that doesn't work download the `.ipynb` file and import it in [Google Colab](https://colab.research.google.com/).\n",
"\n",
"Then install the following packages by executing the following command in a Jupyter cell at the top of the notebook.\n",
"\n",
"```sh\n",
"!pip install numpy pypsa\n",
"```\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pypsa"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start by creating the network object and adding the three buses corresponding to Denmark, Netherlands and Germany. \n",
"The added buses can be printed using network.buses"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"network = pypsa.Network()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" v_nom | \n",
" type | \n",
" x | \n",
" y | \n",
" carrier | \n",
" unit | \n",
" v_mag_pu_set | \n",
" v_mag_pu_min | \n",
" v_mag_pu_max | \n",
" control | \n",
" generator | \n",
" sub_network | \n",
"
\n",
" \n",
" Bus | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" bus Denmark | \n",
" 2000.0 | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" AC | \n",
" | \n",
" 1.0 | \n",
" 0.0 | \n",
" inf | \n",
" PQ | \n",
" | \n",
" | \n",
"
\n",
" \n",
" bus Netherlands | \n",
" 2000.0 | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" AC | \n",
" | \n",
" 1.0 | \n",
" 0.0 | \n",
" inf | \n",
" PQ | \n",
" | \n",
" | \n",
"
\n",
" \n",
" bus Germany | \n",
" 2000.0 | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" AC | \n",
" | \n",
" 1.0 | \n",
" 0.0 | \n",
" inf | \n",
" PQ | \n",
" | \n",
" | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" v_nom type x y carrier unit v_mag_pu_set \\\n",
"Bus \n",
"bus Denmark 2000.0 0.0 0.0 AC 1.0 \n",
"bus Netherlands 2000.0 0.0 0.0 AC 1.0 \n",
"bus Germany 2000.0 0.0 0.0 AC 1.0 \n",
"\n",
" v_mag_pu_min v_mag_pu_max control generator sub_network \n",
"Bus \n",
"bus Denmark 0.0 inf PQ \n",
"bus Netherlands 0.0 inf PQ \n",
"bus Germany 0.0 inf PQ "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.add(\"Bus\", \"bus Denmark\", v_nom=2000.0)\n",
"network.add(\"Bus\", \"bus Netherlands\", v_nom=2000.0)\n",
"network.add(\"Bus\", \"bus Germany\", v_nom=2000.0)\n",
"\n",
"network.buses"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We add the three lines connecting the buses"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" bus0 | \n",
" bus1 | \n",
" type | \n",
" x | \n",
" r | \n",
" g | \n",
" b | \n",
" s_nom | \n",
" s_nom_mod | \n",
" s_nom_extendable | \n",
" ... | \n",
" v_ang_min | \n",
" v_ang_max | \n",
" sub_network | \n",
" x_pu | \n",
" r_pu | \n",
" g_pu | \n",
" b_pu | \n",
" x_pu_eff | \n",
" r_pu_eff | \n",
" s_nom_opt | \n",
"
\n",
" \n",
" Line | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" line DK-NL | \n",
" bus Denmark | \n",
" bus Netherlands | \n",
" | \n",
" 0.1 | \n",
" 0.01 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" False | \n",
" ... | \n",
" -inf | \n",
" inf | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" line DK-DE | \n",
" bus Denmark | \n",
" bus Germany | \n",
" | \n",
" 0.1 | \n",
" 0.02 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" False | \n",
" ... | \n",
" -inf | \n",
" inf | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" line NL-DE | \n",
" bus Netherlands | \n",
" bus Germany | \n",
" | \n",
" 0.1 | \n",
" 0.01 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" False | \n",
" ... | \n",
" -inf | \n",
" inf | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
3 rows × 31 columns
\n",
"
"
],
"text/plain": [
" bus0 bus1 type x r g b s_nom \\\n",
"Line \n",
"line DK-NL bus Denmark bus Netherlands 0.1 0.01 0.0 0.0 0.0 \n",
"line DK-DE bus Denmark bus Germany 0.1 0.02 0.0 0.0 0.0 \n",
"line NL-DE bus Netherlands bus Germany 0.1 0.01 0.0 0.0 0.0 \n",
"\n",
" s_nom_mod s_nom_extendable ... v_ang_min v_ang_max \\\n",
"Line ... \n",
"line DK-NL 0.0 False ... -inf inf \n",
"line DK-DE 0.0 False ... -inf inf \n",
"line NL-DE 0.0 False ... -inf inf \n",
"\n",
" sub_network x_pu r_pu g_pu b_pu x_pu_eff r_pu_eff s_nom_opt \n",
"Line \n",
"line DK-NL 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"line DK-DE 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"line NL-DE 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n",
"\n",
"[3 rows x 31 columns]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.add(\"Line\",\" line DK-NL\", bus0 = \"bus Denmark\", bus1= \"bus Netherlands\", x=0.1, r=0.01)\n",
"network.add(\"Line\",\" line DK-DE\", bus0 = \"bus Denmark\", bus1= \"bus Germany\", x=0.1, r=0.02)\n",
"network.add(\"Line\",\" line NL-DE\", bus0 = \"bus Netherlands\", bus1= \"bus Germany\", x=0.1, r=0.01)\n",
"\n",
"network.lines"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add a generator at the Denmark bus."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" bus | \n",
" control | \n",
" type | \n",
" p_nom | \n",
" p_nom_mod | \n",
" p_nom_extendable | \n",
" p_nom_min | \n",
" p_nom_max | \n",
" p_min_pu | \n",
" p_max_pu | \n",
" ... | \n",
" min_up_time | \n",
" min_down_time | \n",
" up_time_before | \n",
" down_time_before | \n",
" ramp_limit_up | \n",
" ramp_limit_down | \n",
" ramp_limit_start_up | \n",
" ramp_limit_shut_down | \n",
" weight | \n",
" p_nom_opt | \n",
"
\n",
" \n",
" Generator | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" generator Denmark | \n",
" bus Denmark | \n",
" PQ | \n",
" | \n",
" 0.0 | \n",
" 0.0 | \n",
" False | \n",
" 0.0 | \n",
" inf | \n",
" 0.0 | \n",
" 1.0 | \n",
" ... | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" NaN | \n",
" NaN | \n",
" 1.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
\n",
"
1 rows × 37 columns
\n",
"
"
],
"text/plain": [
" bus control type p_nom p_nom_mod \\\n",
"Generator \n",
"generator Denmark bus Denmark PQ 0.0 0.0 \n",
"\n",
" p_nom_extendable p_nom_min p_nom_max p_min_pu p_max_pu \\\n",
"Generator \n",
"generator Denmark False 0.0 inf 0.0 1.0 \n",
"\n",
" ... min_up_time min_down_time up_time_before \\\n",
"Generator ... \n",
"generator Denmark ... 0 0 1 \n",
"\n",
" down_time_before ramp_limit_up ramp_limit_down \\\n",
"Generator \n",
"generator Denmark 0 NaN NaN \n",
"\n",
" ramp_limit_start_up ramp_limit_shut_down weight \\\n",
"Generator \n",
"generator Denmark 1.0 1.0 1.0 \n",
"\n",
" p_nom_opt \n",
"Generator \n",
"generator Denmark 0.0 \n",
"\n",
"[1 rows x 37 columns]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.add(\"Generator\", \n",
" \"generator Denmark\", \n",
" bus=\"bus Denmark\",\n",
" p_set=100)\n",
"network.generators"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Generator\n",
"generator Denmark 100.0\n",
"Name: p_set, dtype: float64"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.generators.p_set"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add a load at the Germany bus"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" bus | \n",
" carrier | \n",
" type | \n",
" p_set | \n",
" q_set | \n",
" sign | \n",
" active | \n",
"
\n",
" \n",
" Load | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" load Germany | \n",
" bus Germany | \n",
" | \n",
" | \n",
" 100.0 | \n",
" 100.0 | \n",
" -1.0 | \n",
" True | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" bus carrier type p_set q_set sign active\n",
"Load \n",
"load Germany bus Germany 100.0 100.0 -1.0 True"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.add(\"Load\", \n",
" \"load Germany\", \n",
" bus=\"bus Germany\", \n",
" p_set=100,\n",
" q_set=100)\n",
"network.loads"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now solve the non-linear power flow using a Newton-Raphson method."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network for snapshots Index(['now'], dtype='object', name='snapshot')\n"
]
},
{
"data": {
"text/plain": [
"{'n_iter': SubNetwork 0\n",
" snapshot \n",
" now 2,\n",
" 'error': SubNetwork 0\n",
" snapshot \n",
" now 8.204964e-09,\n",
" 'converged': SubNetwork 0\n",
" snapshot \n",
" now True}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.pf()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ok, the solution converge, we can check now the active power flow on the lines."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" line DK-NL | \n",
" line DK-DE | \n",
" line NL-DE | \n",
"
\n",
" \n",
" snapshot | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" now | \n",
" 31.441059 | \n",
" 68.558996 | \n",
" 31.441054 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" line DK-NL line DK-DE line NL-DE\n",
"snapshot \n",
"now 31.441059 68.558996 31.441054"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.lines_t.p0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also check the voltage angles on the buses. We need to apply a conversion factor if we want to show them in degrees."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" Bus | \n",
" bus Denmark | \n",
" bus Netherlands | \n",
" bus Germany | \n",
"
\n",
" \n",
" snapshot | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" now | \n",
" 0.0 | \n",
" -0.00004 | \n",
" -0.00008 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Bus bus Denmark bus Netherlands bus Germany\n",
"snapshot \n",
"now 0.0 -0.00004 -0.00008"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.buses_t.v_ang * 180 / np.pi"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and their per-unit magnitudes"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" Bus | \n",
" bus Denmark | \n",
" bus Netherlands | \n",
" bus Germany | \n",
"
\n",
" \n",
" snapshot | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" now | \n",
" 1.0 | \n",
" 0.999999 | \n",
" 0.999998 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Bus bus Denmark bus Netherlands bus Germany\n",
"snapshot \n",
"now 1.0 0.999999 0.999998"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.buses_t.v_mag_pu"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**b) Calculate the power flows along the transmission lines using a linearized approximation (DC optimal power flow).**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can use linear power flows and get a similar solution"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:pypsa.pf:Performing linear load-flow on AC sub-network for snapshot(s) Index(['now'], dtype='object', name='snapshot')\n"
]
}
],
"source": [
"network.lpf()"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" line DK-NL | \n",
" line DK-DE | \n",
" line NL-DE | \n",
"
\n",
" \n",
" snapshot | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" now | \n",
" 33.333333 | \n",
" 66.666667 | \n",
" 33.333333 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" line DK-NL line DK-DE line NL-DE\n",
"snapshot \n",
"now 33.333333 66.666667 33.333333"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.lines_t.p0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this simple case, the solution that we obtain are very similar."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"@webio": {
"lastCommId": null,
"lastKernelId": null
},
"kernelspec": {
"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",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}