{ "cells": [ { "cell_type": "markdown", "id": "87d7a34f", "metadata": {}, "source": [ "(power-flow-example)=\n", "# Power flow\n", "SHOP implements PTDF-based power flow. The [busbar](busbar) and [ac_line](ac_line) objects are used to specify the grid topology of the model. The following example demonstrates a simple model with power flow and [thermal](thermal) production units.\n", "\n", "## Set up model\n", "First, we initialize the model" ] }, { "cell_type": "code", "execution_count": 1, "id": "4c378853", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "import pandas as pd\n", "import plotly.graph_objs as go\n", "from pyshop import ShopSession\n", "\n", "shop = ShopSession()\n", "starttime=pd.Timestamp(\"2022-02-27T00\")\n", "endtime=starttime+pd.DateOffset(hours=24)\n", "shop.set_time_resolution(starttime=starttime, endtime=endtime, timeunit=\"hour\")" ] }, { "cell_type": "markdown", "id": "9aafcc78", "metadata": {}, "source": [ "Add busbars and set the [load](busbar:load). The load in busbar 1 is linearly increasing over time in this example, while all other input data is constant." ] }, { "cell_type": "code", "execution_count": 2, "id": "21d04ba5", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "b1=shop.model.busbar.add_object(\"Busbar1\")\n", "b1.load.set(pd.Series([50+i for i in range(24)],index=[starttime+pd.Timedelta(hours=i) for i in range(24)]))\n", "b2=shop.model.busbar.add_object(\"Busbar2\")\n", "b2.load.set(60)\n", "b3=shop.model.busbar.add_object(\"Busbar3\")\n", "b3.load.set(300)" ] }, { "cell_type": "markdown", "id": "7b79fa45", "metadata": {}, "source": [ "Then we define one thermal unit for each busbar and connect them. The marginal cost of the thermal units is equal to the [fuel_cost](thermal:fuel_cost) in this case since [n_segments](thermal:n_segments) is set to 1. Busbar 3 has the largest thermal unit, while busbar 1 has the cheapest one. Only a small and expensive unit is located in busbar 2." ] }, { "cell_type": "code", "execution_count": 3, "id": "8f9ab510", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "t1=shop.model.thermal.add_object(\"Thermal1\")\n", "t1.fuel_cost.set(75)\n", "t1.n_segments.set(1)\n", "t1.min_prod.set(0)\n", "t1.max_prod.set(140)\n", "t1.connect_to(b1)\n", "\n", "t2=shop.model.thermal.add_object(\"Thermal2\")\n", "t2.fuel_cost.set(180)\n", "t2.n_segments.set(1)\n", "t2.min_prod.set(0)\n", "t2.max_prod.set(20)\n", "t2.connect_to(b2)\n", "\n", "t3=shop.model.thermal.add_object(\"Thermal3\")\n", "t3.fuel_cost.set(140)\n", "t3.n_segments.set(1)\n", "t3.min_prod.set(0)\n", "t3.max_prod.set(400)\n", "t3.connect_to(b3)" ] }, { "cell_type": "markdown", "id": "740eee05", "metadata": {}, "source": [ "There are three AC lines that connect the busbars, and there is no power loss in the transmission. The AC line connecting busbar 2 and 3 has the lowest transmission capacity, which is specified in both directions by the [max_forward_flow](ac_line:max_forward_flow) and [max_backward_flow](ac_line:max_backward_flow) attributes. Note that the positive (forward) flow direction on each line is determined by the connections between the busbar and ac_line objects.\n", "\n", "Create AC lines and connect between buses:" ] }, { "cell_type": "code", "execution_count": 4, "id": "3169bc71", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "ac1=shop.model.ac_line.add_object(\"AC_line1\")\n", "ac1.max_forward_flow.set(40)\n", "ac1.max_backward_flow.set(40)\n", "b1.connect_to(ac1)\n", "ac1.connect_to(b2)\n", "\n", "ac2=shop.model.ac_line.add_object(\"AC_line2\")\n", "ac2.max_forward_flow.set(250)\n", "ac2.max_backward_flow.set(250)\n", "b1.connect_to(ac2)\n", "ac2.connect_to(b3)\n", "\n", "ac3=shop.model.ac_line.add_object(\"AC_line3\")\n", "ac3.max_forward_flow.set(10)\n", "ac3.max_backward_flow.set(10)\n", "b2.connect_to(ac3)\n", "ac3.connect_to(b3)" ] }, { "cell_type": "markdown", "id": "68d5afba", "metadata": {}, "source": [ "The we set the [PTDF matrix](busbar:ptdf) that determines the flow on each line as a function of the net power injection in each busbar. Busbar 3 is chosen as the slack bus in this example, which means that the PTDF values for busbar 3 are all zero." ] }, { "cell_type": "code", "execution_count": 5, "id": "54d50344", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "ac_lines=[\"AC_line1\", \"AC_line2\", \"AC_line3\"]\n", "b1.ptdf.set(pd.Series(data=[0.2/0.5, (0.2+0.1)/0.5, 0.2/0.5], index=ac_lines))\n", "b2.ptdf.set(pd.Series(data=[-0.1/0.5, 0.1/0.5, (0.2+0.2)/0.5], index=ac_lines))\n", "b3.ptdf.set(pd.Series(data=[0.0, 0.0, 0.0], index=ac_lines))" ] }, { "cell_type": "markdown", "id": "3f3c43a8", "metadata": {}, "source": [ "The grid topology with the PTDFs visualized for busbars 1 and 2 are shown in the figures below.\n", "\n", "||\n", "|---|\n", "| Grid topology with the PTDF for busbar 1 shown as red numbers. |\n", "\n", "||\n", "|---|\n", "| Grid topology with the PTDF for busbar 2 shown as green numbers. Note that the PTDF for line 2 is negative due to the chosen positive line direction. |\n", "\n", "Run the model:" ] }, { "cell_type": "code", "execution_count": 6, "id": "d65961ba", "metadata": { "Collapsed": "false" }, "outputs": [], "source": [ "shop.start_sim([],[\"1\"])" ] }, { "cell_type": "markdown", "id": "cd300e13", "metadata": {}, "source": [ "## Results\n", "First, we take a look at the production of each unit in the system. The cheapest unit located in busbar 2 does not operate at full capacity until 15 hours after optimization start, this is due to the transmission line constraints and PTDF values used in the example." ] }, { "cell_type": "code", "execution_count": 7, "id": "a553b605", "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "name": "Sum production busbar 1", "type": "scatter", "x": [ "2022-02-27T00:00:00", "2022-02-27T01:00:00", "2022-02-27T02:00:00", "2022-02-27T03:00:00", "2022-02-27T04:00:00", "2022-02-27T05:00:00", "2022-02-27T06:00:00", "2022-02-27T07:00:00", "2022-02-27T08:00:00", "2022-02-27T09:00:00", "2022-02-27T10:00:00", "2022-02-27T11:00:00", "2022-02-27T12:00:00", "2022-02-27T13:00:00", "2022-02-27T14:00:00", "2022-02-27T15:00:00", "2022-02-27T16:00:00", "2022-02-27T17:00:00", "2022-02-27T18:00:00", "2022-02-27T19:00:00", "2022-02-27T20:00:00", "2022-02-27T21:00:00", "2022-02-27T22:00:00", "2022-02-27T23:00:00" ], "y": [ 125.0, 126.0, 127.0, 128.0, 129.0, 130.0, 131.0, 132.0, 133.0, 134.0, 135.0, 136.0, 137.0, 138.0, 139.0, 140.0, 140.0, 140.0, 140.0, 140.0, 140.0, 140.0, 140.0, 140.0 ] }, { "name": "Sum production busbar 2", "type": "scatter", "x": [ "2022-02-27T00:00:00", "2022-02-27T01:00:00", "2022-02-27T02:00:00", "2022-02-27T03:00:00", "2022-02-27T04:00:00", "2022-02-27T05:00:00", "2022-02-27T06:00:00", "2022-02-27T07:00:00", "2022-02-27T08:00:00", "2022-02-27T09:00:00", "2022-02-27T10:00:00", "2022-02-27T11:00:00", "2022-02-27T12:00:00", "2022-02-27T13:00:00", "2022-02-27T14:00:00", "2022-02-27T15:00:00", "2022-02-27T16:00:00", "2022-02-27T17:00:00", "2022-02-27T18:00:00", "2022-02-27T19:00:00", "2022-02-27T20:00:00", "2022-02-27T21:00:00", "2022-02-27T22:00:00", "2022-02-27T23:00:00" ], "y": [ 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.5, 11.0, 11.5, 11.999999999999993, 12.5, 13.0, 13.5, 14.0 ] }, { "name": "Sum production busbar 3", "type": "scatter", "x": [ "2022-02-27T00:00:00", "2022-02-27T01:00:00", "2022-02-27T02:00:00", "2022-02-27T03:00:00", "2022-02-27T04:00:00", "2022-02-27T05:00:00", "2022-02-27T06:00:00", "2022-02-27T07:00:00", "2022-02-27T08:00:00", "2022-02-27T09:00:00", "2022-02-27T10:00:00", "2022-02-27T11:00:00", "2022-02-27T12:00:00", "2022-02-27T13:00:00", "2022-02-27T14:00:00", "2022-02-27T15:00:00", "2022-02-27T16:00:00", "2022-02-27T17:00:00", "2022-02-27T18:00:00", "2022-02-27T19:00:00", "2022-02-27T20:00:00", "2022-02-27T21:00:00", "2022-02-27T22:00:00", "2022-02-27T23:00:00" ], "y": [ 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.0, 275.5, 276.0, 276.5, 277.0, 277.5, 278.0, 278.5, 279.0 ] } ], "layout": { "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "xaxis": { "title": { "text": "Time" } }, "yaxis": { "title": { "text": "Production [MW]" } } } }, "text/html": [ "