{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# DC Line dispatch with pandapower OPF\n", "This is an introduction into the usage of the pandapower optimal power flow with dc lines.\n", "\n", "## Example Network\n", "\n", "We use the following four bus example network for this tutorial:\n", "\n", "\n", "\n", "We first create this network in pandapower:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pandapower as pp\n", "from numpy import array\n", "net = pp.create_empty_network()\n", "\n", "b1 = pp.create_bus(net, 380)\n", "b2 = pp.create_bus(net, 380)\n", "b3 = pp.create_bus(net, 380)\n", "b4 = pp.create_bus(net, 380)\n", "b5 = pp.create_bus(net, 380)\n", "\n", "l1 = pp.create_line(net, b1, b2, 30, \"490-AL1/64-ST1A 380.0\")\n", "l2 = pp.create_line(net, b3, b4, 20, \"490-AL1/64-ST1A 380.0\")\n", "l3 = pp.create_line(net, b4, b5, 20, \"490-AL1/64-ST1A 380.0\")\n", "\n", "dcl1 = pp.create_dcline(net, name=\"dc line\", from_bus=b2, to_bus=b3, p_kw=0.2e6, loss_percent=1.0, \n", " loss_kw=500, vm_from_pu=1.01, vm_to_pu=1.012, max_p_kw=1e6,\n", " in_service=True)\n", "\n", "eg1 = pp.create_ext_grid(net, b1, 1.02, max_p_kw=0.)\n", "eg2 = pp.create_ext_grid(net, b5, 1.02, max_p_kw=0.)\n", "\n", "l1 = pp.create_load(net, bus=b4, p_kw=800e3, controllable = False)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "We now run a regular load flow to check out the DC line model:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pp.runpp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The transmission power of the DC line is defined in the loadflow as given by the p_kw parameter, which was set to 0.2 GW:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0200000.0152443.185449-197500.074491.7589432500.01.01-0.485951.012-0.725627
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw vm_from_pu \\\n", "0 200000.0 152443.185449 -197500.0 74491.758943 2500.0 1.01 \n", "\n", " va_from_degree vm_to_pu va_to_degree \n", "0 -0.48595 1.012 -0.725627 " ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The losses amount to 2500 kW, which are made up of 500 kW conversion loss and 200 MW * 0.01 = 2 MW transmission losses. The voltage setpoints defined at from and to bus are complied with. \n", "\n", "Now lets define costs for the external grids to run an OPF:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": true }, "outputs": [], "source": [ "costeg0 = pp.create_polynomial_cost(net, 0, 'ext_grid', array([.1, 0]))\n", "costeg1 = pp.create_polynomial_cost(net, 1, 'ext_grid', array([.08, 0]))\n", "net.bus['max_vm_pu'] = 1.5\n", "net.line['max_loading_percent'] = 1000\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since we defined lower costs for Ext Grid 2, it fully services the load:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-500.0783537787.557732
1-805091.476316-628.307279
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -500.078353 7787.557732\n", "1 -805091.476316 -628.307279" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While the DC line does not transmit any power:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0500.0754077787.456005-0.07466-627.126367500.0007471.019994-0.0014481.013925-1.563437
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw vm_from_pu \\\n", "0 500.075407 7787.456005 -0.07466 -627.126367 500.000747 1.019994 \n", "\n", " va_from_degree vm_to_pu va_to_degree \n", "0 -0.001448 1.013925 -1.563437 " ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we set the costs of the left grid to a lower value than the right grid and run the loadflow again:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": true }, "outputs": [], "source": [ "net.polynomial_cost.c.at[costeg0]= array([[0.08, 0]])\n", "net.polynomial_cost.c.at[costeg1]= array([[0.1, 0]])\n", "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the power now comes from the left ext_grid:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-821525.3582817787.558529
1-0.05435021048.592139
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -821525.358281 7787.558529\n", "1 -0.054350 21048.592139" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And is transmitted over the DC line:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0813573.88367-26446.047364-805023.647198-21736.3119638550.2364721.011014-2.399871.0275041.522333
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 813573.88367 -26446.047364 -805023.647198 -21736.311963 8550.236472 \n", "\n", " vm_from_pu va_from_degree vm_to_pu va_to_degree \n", "0 1.011014 -2.39987 1.027504 1.522333 " ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can however see that the lines on the left hand side are now overloaded:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
0821525.358281-7787.558529-813573.88367026446.0473647951.47461118658.4888351.2237601.2232771.223760127.474952
1805023.64719821736.311963-800001.920574-10668.1017305021.72662411068.2102331.1908001.1911141.191114124.074383
21.92057410668.1017300.054350-21048.5921391.974924-10380.4904090.0158820.0313530.0313533.265934
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 821525.358281 -7787.558529 -813573.883670 26446.047364 7951.474611 \n", "1 805023.647198 21736.311963 -800001.920574 -10668.101730 5021.726624 \n", "2 1.920574 10668.101730 0.054350 -21048.592139 1.974924 \n", "\n", " ql_kvar i_from_ka i_to_ka i_ka loading_percent \n", "0 18658.488835 1.223760 1.223277 1.223760 127.474952 \n", "1 11068.210233 1.190800 1.191114 1.191114 124.074383 \n", "2 -10380.490409 0.015882 0.031353 0.031353 3.265934 " ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we set the maximum line loading to 100% and run the OPF again:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": true }, "outputs": [], "source": [ "net.line[\"max_loading_percent\"] = 100\n", "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the lines are no longer overloaded:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
0644488.858958-642.506854-639594.5663196169.9591584894.2926395527.4523030.9600000.9598780.960000100.000000
1632766.89737810098.568594-629647.068718-7138.7026733119.8286602959.8659210.9386240.9388360.93883697.795376
2-170352.9312827138.702673170582.491792-16527.962212229.560511-9389.2595390.2542110.2552810.25528126.591809
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 644488.858958 -642.506854 -639594.566319 6169.959158 4894.292639 \n", "1 632766.897378 10098.568594 -629647.068718 -7138.702673 3119.828660 \n", "2 -170352.931282 7138.702673 170582.491792 -16527.962212 229.560511 \n", "\n", " ql_kvar i_from_ka i_to_ka i_ka loading_percent \n", "0 5527.452303 0.960000 0.959878 0.960000 100.000000 \n", "1 2959.865921 0.938624 0.938836 0.938836 97.795376 \n", "2 -9389.259539 0.254211 0.255281 0.255281 26.591809 " ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the load is serviced from both grids:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-644488.858782642.506837
1-170582.49179216527.962212
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -644488.858782 642.506837\n", "1 -170582.491792 16527.962212" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And the DC line transmits only part of the power needed to service the load:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0639594.566352-6169.958242-632766.897378-10098.5685946827.6689741.012429-1.8751.0243850.875621
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 639594.566352 -6169.958242 -632766.897378 -10098.568594 6827.668974 \n", "\n", " vm_from_pu va_from_degree vm_to_pu va_to_degree \n", "0 1.012429 -1.875 1.024385 0.875621 " ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can also define transmission costs for the DC line:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": true }, "outputs": [], "source": [ "costeg1 = pp.create_polynomial_cost(net, 0, 'dcline', array([.03, 0]))\n", "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the sum of the costs for generating power on the left hand side (0.08) and transmitting it to the right side (0.03) is now larger than for generating on the right side (0.1), the OPF draws as much power from the right side as is possible without violating line loading constraints:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwql_kvari_from_kai_to_kai_kaloading_percent
0161370.351241-7787.557137-161063.552750-6442.901692306.798490-14230.4588290.2406490.2405540.24064925.067628
1158973.810254-4896.498618-158773.820749-4539.248232199.989505-9435.7468500.2377980.2377810.23779824.770574
2-641226.1703494539.247144644488.776263-880.6726923262.6059143658.5744510.9599360.9600000.960000100.000031
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 161370.351241 -7787.557137 -161063.552750 -6442.901692 306.798490 \n", "1 158973.810254 -4896.498618 -158773.820749 -4539.248232 199.989505 \n", "2 -641226.170349 4539.247144 644488.776263 -880.672692 3262.605914 \n", "\n", " ql_kvar i_from_ka i_to_ka i_ka loading_percent \n", "0 -14230.458829 0.240649 0.240554 0.240649 25.067628 \n", "1 -9435.746850 0.237798 0.237781 0.237798 24.770574 \n", "2 3658.574451 0.959936 0.960000 0.960000 100.000031 " ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0161063.552756442.901692-158973.8146044896.5349632089.7381461.018095-0.4679911.016202-0.938725
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 161063.55275 6442.901692 -158973.814604 4896.534963 2089.738146 \n", "\n", " vm_from_pu va_from_degree vm_to_pu va_to_degree \n", "0 1.018095 -0.467991 1.016202 -0.938725 " ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we broaden the line loading constraint and run the OPF again:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.line[\"max_loading_percent\"] = 1000\n", "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The load is once again fully serviced by the grid on the right hand side:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-500.3009427787.555581
1-805091.253109-628.302293
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -500.300942 7787.555581\n", "1 -805091.253109 -628.302293" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And the DC line is in open loop operation:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\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", " \n", " \n", " \n", " \n", "
p_from_kwq_from_kvarp_to_kwq_to_kvarpl_kwvm_from_puva_from_degreevm_to_puva_to_degree
0500.2979937787.458105-0.295043-627.119172500.002951.019994-0.0014481.013925-1.563436
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw vm_from_pu \\\n", "0 500.297993 7787.458105 -0.295043 -627.119172 500.00295 1.019994 \n", "\n", " va_from_degree vm_to_pu va_to_degree \n", "0 -0.001448 1.013925 -1.563436 " ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_dcline" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [default]", "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.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }