{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# pandapower Optimal Power Flow\n", "This is an introduction into the usage of the pandapower optimal power flow. It shows how to set the constraints and the cost factors into the pandapower element tables.\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", "import numpy as np\n", "net = pp.create_empty_network()\n", "\n", "#create buses\n", "bus1 = pp.create_bus(net, vn_kv=220.)\n", "bus2 = pp.create_bus(net, vn_kv=110.)\n", "bus3 = pp.create_bus(net, vn_kv=110.)\n", "bus4 = pp.create_bus(net, vn_kv=110.)\n", "\n", "#create 220/110 kV transformer\n", "pp.create_transformer(net, bus1, bus2, std_type=\"100 MVA 220/110 kV\")\n", "\n", "#create 110 kV lines\n", "pp.create_line(net, bus2, bus3, length_km=70., std_type='149-AL1/24-ST1A 110.0')\n", "pp.create_line(net, bus3, bus4, length_km=50., std_type='149-AL1/24-ST1A 110.0')\n", "pp.create_line(net, bus4, bus2, length_km=40., std_type='149-AL1/24-ST1A 110.0')\n", "\n", "#create loads\n", "pp.create_load(net, bus2, p_kw=60e3, controllable = False)\n", "pp.create_load(net, bus3, p_kw=70e3, controllable = False)\n", "pp.create_load(net, bus4, p_kw=10e3, controllable = False)\n", "\n", "#create generators\n", "eg = pp.create_ext_grid(net, bus1)\n", "g0 = pp.create_gen(net, bus3, p_kw=-80*1e3, min_p_kw=-80e3, max_p_kw=0,vm_pu=1.01, controllable=True)\n", "g1 = pp.create_gen(net, bus4, p_kw=-100*1e3, min_p_kw=-100e3, max_p_kw=0, vm_pu=1.01, controllable=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loss Minimization\n", "\n", "We specify the same costs for the power at the external grid and all generators to minimize the overall power feed in. This equals an overall loss minimization:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "costeg = pp.create_polynomial_cost(net, 0, 'ext_grid', np.array([1, 0]))\n", "costgen1 = pp.create_polynomial_cost(net, 0, 'gen', np.array([1, 0]))\n", "costgen2 = pp.create_polynomial_cost(net, 1, 'gen', np.array([1, 0]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We run an OPF:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PYPOWER Version 5.0.0, 29-May-2015 -- AC Optimal Power Flow\n", "Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011\n", "Numerically failed.\n", "Did not converge in 2 iterations.\n" ] }, { "ename": "OPFNotConverged", "evalue": "Optimal Power Flow did not converge!", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mOPFNotConverged\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrunopp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\run.py\u001b[0m in \u001b[0;36mrunopp\u001b[0;34m(net, verbose, calculate_voltage_angles, check_connectivity, suppress_warnings, r_switch, delta, **kwargs)\u001b[0m\n\u001b[1;32m 290\u001b[0m voltage_depend_loads=False, delta=delta)\n\u001b[1;32m 291\u001b[0m \u001b[0m_add_opf_options\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrafo_loading\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrafo_loading\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mac\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mac\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 292\u001b[0;31m \u001b[0m_optimal_powerflow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msuppress_warnings\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 293\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 294\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\optimal_powerflow.py\u001b[0m in \u001b[0;36m_optimal_powerflow\u001b[0;34m(net, verbose, suppress_warnings, **kwargs)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mresult\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"success\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[1;32mraise\u001b[0m \u001b[0mOPFNotConverged\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Optimal Power Flow did not converge!\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[1;31m# ppci doesn't contain out of service elements, but ppc does -> copy results accordingly\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;31mOPFNotConverged\u001b[0m: Optimal Power Flow did not converge!" ] } ], "source": [ "pp.runopp(net, verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Apparently the OPF did not converge. Sometimes the constraints are too broad or too narrow for the OPF to converge. So let's try setting the voltage constraints first:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.bus['max_vm_pu'] = 2\n", "pp.runopp(net, verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "let's check the results:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.res_ext_grid" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.res_gen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since all costs were specified the same, the OPF minimizes overall power generation, which is equal to a loss minimization in the network. The loads at buses 3 and 4 are supplied by generators at the same bus, the load at Bus 2 is provided by a combination of the other generators so that the power transmission leads to minimal losses." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Individual Generator Costs\n", "\n", "Let's now assign individual costs to each generator.\n", "\n", "We assign a cost of 10 ct/kW for the external grid, 15 ct/kw for the generator g0 and 12 ct/kw for generator g1:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "net.polynomial_cost.c.at[costeg] = np.array([[0.1, 0]])\n", "net.polynomial_cost.c.at[costgen1] = np.array([[0.15, 0]])\n", "net.polynomial_cost.c.at[costgen2] = np.array([[0.12, 0]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now run an OPF:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PYPOWER Version 5.0.0, 29-May-2015 -- AC Optimal Power Flow\n", "Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011\n", "Numerically failed.\n", "Did not converge in 32 iterations.\n" ] }, { "ename": "OPFNotConverged", "evalue": "Optimal Power Flow did not converge!", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mOPFNotConverged\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrunopp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\run.py\u001b[0m in \u001b[0;36mrunopp\u001b[0;34m(net, verbose, calculate_voltage_angles, check_connectivity, suppress_warnings, r_switch, delta, **kwargs)\u001b[0m\n\u001b[1;32m 290\u001b[0m voltage_depend_loads=False, delta=delta)\n\u001b[1;32m 291\u001b[0m \u001b[0m_add_opf_options\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrafo_loading\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtrafo_loading\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mac\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mac\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 292\u001b[0;31m \u001b[0m_optimal_powerflow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msuppress_warnings\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 293\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 294\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\optimal_powerflow.py\u001b[0m in \u001b[0;36m_optimal_powerflow\u001b[0;34m(net, verbose, suppress_warnings, **kwargs)\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mresult\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"success\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 54\u001b[0;31m \u001b[1;32mraise\u001b[0m \u001b[0mOPFNotConverged\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Optimal Power Flow did not converge!\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 55\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[1;31m# ppci doesn't contain out of service elements, but ppc does -> copy results accordingly\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;31mOPFNotConverged\u001b[0m: Optimal Power Flow did not converge!" ] } ], "source": [ "pp.runopp(net, verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that all active power is provided by the external grid. This makes sense, because the external grid has the lowest cost of all generators and we did not define any constraints.\n", "\n", "The dispatch costs are given in net.res_cost:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transformer Constraint\n", "\n", "Since all active power comes from the external grid and subsequently flows through the transformer, the transformer is overloaded with a loading of about 145%:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.res_trafo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now limit the transformer loading to 50%:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.trafo[\"max_loading_percent\"] = 50" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(the max_loading_percent parameter can also be specified directly when creating the transformer)\n", "and run the OPF:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the transformer complies with the maximum loading:" ] }, { "cell_type": "code", "execution_count": 8, "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_hv_kwq_hv_kvarp_lv_kwq_lv_kvarpl_kwql_kvari_hv_kai_lv_kaloading_percent
049953.861634-2147.313334-49833.8109655167.452594120.0506693020.139260.1312160.26215349.999992
\n", "
" ], "text/plain": [ " p_hv_kw q_hv_kvar p_lv_kw q_lv_kvar pl_kw \\\n", "0 49953.861634 -2147.313334 -49833.810965 5167.452594 120.050669 \n", "\n", " ql_kvar i_hv_ka i_lv_ka loading_percent \n", "0 3020.13926 0.131216 0.262153 49.999992 " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_trafo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And power generation is now split between the external grid and generator 1 (which is the second cheapest generation unit):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-49953.8616342147.313334
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -49953.861634 2147.313334" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "code", "execution_count": 10, "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", "
p_kwq_kvarva_degreevm_pu
0-0.009347-2993.145553-6.2328280.985230
1-93304.076626-3453.342439-1.2378841.025709
\n", "
" ], "text/plain": [ " p_kw q_kvar va_degree vm_pu\n", "0 -0.009347 -2993.145553 -6.232828 0.985230\n", "1 -93304.076626 -3453.342439 -1.237884 1.025709" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_gen" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "This comes of course with an increase in dispatch costs:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16191.876760535753" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Line Loading Constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wen now look at the line loadings:" ] }, { "cell_type": "code", "execution_count": 12, "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
019780.007620-2479.435263-19341.6934791104.392907438.314142-1375.0423560.1043090.1032070.10430922.193318
1-50658.2971751888.75264652783.695174921.0637402125.3980002809.8163860.2700610.2701400.27014057.476546
230520.3814522532.278698-29946.196656-2688.017331574.184796-155.7386330.1567120.1573230.15732333.472995
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 19780.007620 -2479.435263 -19341.693479 1104.392907 438.314142 \n", "1 -50658.297175 1888.752646 52783.695174 921.063740 2125.398000 \n", "2 30520.381452 2532.278698 -29946.196656 -2688.017331 574.184796 \n", "\n", " ql_kvar i_from_ka i_to_ka i_ka loading_percent \n", "0 -1375.042356 0.104309 0.103207 0.104309 22.193318 \n", "1 2809.816386 0.270061 0.270140 0.270140 57.476546 \n", "2 -155.738633 0.156712 0.157323 0.157323 33.472995 " ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and run the OPF with a 50% loading constraint:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PYPOWER Version 5.0.0, 29-May-2015 -- AC Optimal Power Flow\n", "Python Interior Point Solver - PIPS, Version 1.0, 07-Feb-2011\n", "Converged!\n" ] } ], "source": [ "net.line[\"max_loading_percent\"] = 50\n", "pp.runopp(net, verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the line loading constraint is complied with:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "scrolled": true }, "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
016727.532318-3194.198556-16412.7405831533.356250314.791735-1660.8423050.0888480.0871300.08884818.903796
1-44451.211099867.13790146059.955230832.5602231608.7441311699.6981240.2350000.2350000.23500049.999997
227533.0965634051.891931-27060.152701-4429.882352472.943862-377.9904220.1419650.1430580.14305830.437792
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw \\\n", "0 16727.532318 -3194.198556 -16412.740583 1533.356250 314.791735 \n", "1 -44451.211099 867.137901 46059.955230 832.560223 1608.744131 \n", "2 27533.096563 4051.891931 -27060.152701 -4429.882352 472.943862 \n", "\n", " ql_kvar i_from_ka i_to_ka i_ka loading_percent \n", "0 -1660.842305 0.088848 0.087130 0.088848 18.903796 \n", "1 1699.698124 0.235000 0.235000 0.235000 49.999997 \n", "2 -377.990422 0.141965 0.143058 0.143058 30.437792 " ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And all generators are involved in supplying the loads:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-49787.5942694603.789001
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -49787.594269 4603.789001" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "scrolled": true }, "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", "
p_kwq_kvarva_degreevm_pu
0-9136.048164-2400.493544-5.8149100.992992
1-83593.051621-4884.451800-1.5116861.028900
\n", "
" ], "text/plain": [ " p_kw q_kvar va_degree vm_pu\n", "0 -9136.048164 -2400.493544 -5.814910 0.992992\n", "1 -83593.051621 -4884.451800 -1.511686 1.028900" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_gen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This of course comes with a once again rising dispatch cost:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16380.332845968122" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Voltage Constraints\n", "\n", "Finally, we have a look at the bus voltage:" ] }, { "cell_type": "code", "execution_count": 18, "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", "
vm_puva_degreep_kwq_kvarlam_plam_q
01.0000000.000000-49787.5942694603.789001100.000000-1.673841e-21
11.006025-3.40883260000.0000000.000000130.952237-5.410368e-01
20.992992-5.81491060863.951836-2400.493544149.9999837.893715e-22
31.028900-1.511686-73593.051621-4884.451800120.0000091.859168e-21
\n", "
" ], "text/plain": [ " vm_pu va_degree p_kw q_kvar lam_p lam_q\n", "0 1.000000 0.000000 -49787.594269 4603.789001 100.000000 -1.673841e-21\n", "1 1.006025 -3.408832 60000.000000 0.000000 130.952237 -5.410368e-01\n", "2 0.992992 -5.814910 60863.951836 -2400.493544 149.999983 7.893715e-22\n", "3 1.028900 -1.511686 -73593.051621 -4884.451800 120.000009 1.859168e-21" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_bus" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and constrain it:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "net.bus[\"min_vm_pu\"] = 1.0\n", "net.bus[\"max_vm_pu\"] = 1.02\n", "pp.runopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that all voltages are within the voltage band:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "scrolled": true }, "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", "
vm_puva_degreep_kwq_kvarlam_plam_q
01.0000000.000000-49906.8478323050.617583100.000000-5.175965e-22
11.004168-3.42101560000.0000000.000000131.268594-2.133680e-01
21.000000-5.97609459278.207273-14858.927798149.9999932.520634e-21
31.020000-1.366892-71863.4934119172.685486120.000004-1.555865e-21
\n", "
" ], "text/plain": [ " vm_pu va_degree p_kw q_kvar lam_p lam_q\n", "0 1.000000 0.000000 -49906.847832 3050.617583 100.000000 -5.175965e-22\n", "1 1.004168 -3.421015 60000.000000 0.000000 131.268594 -2.133680e-01\n", "2 1.000000 -5.976094 59278.207273 -14858.927798 149.999993 2.520634e-21\n", "3 1.020000 -1.366892 -71863.493411 9172.685486 120.000004 -1.555865e-21" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_bus" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And all generators are once again involved in supplying the loads:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
p_kwq_kvar
0-49906.8478323050.617583
\n", "
" ], "text/plain": [ " p_kw q_kvar\n", "0 -49906.847832 3050.617583" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_ext_grid" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "scrolled": true }, "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", "
p_kwq_kvarva_degreevm_pu
0-10721.792727-14858.927798-5.9760941.00
1-81863.4934119172.685486-1.3668921.02
\n", "
" ], "text/plain": [ " p_kw q_kvar va_degree vm_pu\n", "0 -10721.792727 -14858.927798 -5.976094 1.00\n", "1 -81863.493411 9172.685486 -1.366892 1.02" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_gen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This of course comes once again with rising dispatch costs:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16422.572901622079" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## DC OPF\n", "\n", "pandapower also provides the possibility of running a DC Optimal Power Flow:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pp.rundcopp(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since voltage magnitudes are not included in the DC power flow formulation, voltage constraints canot be considered in the DC OPF:" ] }, { "cell_type": "code", "execution_count": 25, "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", "
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN0.000000-49999.999962NaN100.0000000.0
1NaN-3.43696760000.000000NaN130.9090910.0
2NaN-5.70856661488.746675NaN150.0000000.0
3NaN-1.362340-71488.746713NaN120.0000000.0
\n", "
" ], "text/plain": [ " vm_pu va_degree p_kw q_kvar lam_p lam_q\n", "0 NaN 0.000000 -49999.999962 NaN 100.000000 0.0\n", "1 NaN -3.436967 60000.000000 NaN 130.909091 0.0\n", "2 NaN -5.708566 61488.746675 NaN 150.000000 0.0\n", "3 NaN -1.362340 -71488.746713 NaN 120.000000 0.0" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_bus" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Line and transformer loading limits are however complied with:" ] }, { "cell_type": "code", "execution_count": 26, "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
016715.233326NaN-16715.233326NaNNaNNaN0.0877320.0877320.08773218.666430
1-44773.513348NaN44773.513348NaNNaNNaN0.2350000.2350000.23500050.000000
226715.233365NaN-26715.233365NaNNaNNaN0.1402190.1402190.14021929.833747
\n", "
" ], "text/plain": [ " p_from_kw q_from_kvar p_to_kw q_to_kvar pl_kw ql_kvar \\\n", "0 16715.233326 NaN -16715.233326 NaN NaN NaN \n", "1 -44773.513348 NaN 44773.513348 NaN NaN NaN \n", "2 26715.233365 NaN -26715.233365 NaN NaN NaN \n", "\n", " i_from_ka i_to_ka i_ka loading_percent \n", "0 0.087732 0.087732 0.087732 18.666430 \n", "1 0.235000 0.235000 0.235000 50.000000 \n", "2 0.140219 0.140219 0.140219 29.833747 " ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_line" ] }, { "cell_type": "code", "execution_count": 27, "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_hv_kwq_hv_kvarp_lv_kwq_lv_kvarpl_kwql_kvari_hv_kai_lv_kaloading_percent
049999.999962NaN-49999.999962NaNNaNNaN0.1312160.26243250.0
\n", "
" ], "text/plain": [ " p_hv_kw q_hv_kvar p_lv_kw q_lv_kvar pl_kw ql_kvar i_hv_ka \\\n", "0 49999.999962 NaN -49999.999962 NaN NaN NaN 0.131216 \n", "\n", " i_lv_ka loading_percent \n", "0 0.262432 50.0 " ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_trafo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As are generator limits:" ] }, { "cell_type": "code", "execution_count": 28, "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", "
namebusp_kwvm_pusn_kvamin_q_kvarmax_q_kvarscalingin_servicetypemin_p_kwmax_p_kwcontrollable
0None2-80000.01.01NaNNaNNaN1.0TrueNone-80000.00.0True
1None3-100000.01.01NaNNaNNaN1.0TrueNone-100000.00.0True
\n", "
" ], "text/plain": [ " name bus p_kw vm_pu sn_kva min_q_kvar max_q_kvar scaling \\\n", "0 None 2 -80000.0 1.01 NaN NaN NaN 1.0 \n", "1 None 3 -100000.0 1.01 NaN NaN NaN 1.0 \n", "\n", " in_service type min_p_kw max_p_kw controllable \n", "0 True None -80000.0 0.0 True \n", "1 True None -100000.0 0.0 True " ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.gen" ] }, { "cell_type": "code", "execution_count": 29, "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", "
p_kwq_kvarva_degreevm_pu
0-8511.253325NaN-5.7085661.0
1-81488.746713NaN-1.3623401.0
\n", "
" ], "text/plain": [ " p_kw q_kvar va_degree vm_pu\n", "0 -8511.253325 NaN -5.708566 1.0\n", "1 -81488.746713 NaN -1.362340 1.0" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_gen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The cost function is the same for the linearized OPF as for the non-linear one:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16055.337600528508" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "**Piecewise linear cost functions**\n", "The OPF also offers us piecewise linear cost functions. Let us first check the actual cost function setup:" ] }, { "cell_type": "code", "execution_count": 31, "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", "
typeelementelement_typec
0p0ext_grid[[0.1, 0.0]]
1p0gen[[0.15, 0.0]]
2p1gen[[0.12, 0.0]]
\n", "
" ], "text/plain": [ " type element element_type c\n", "0 p 0 ext_grid [[0.1, 0.0]]\n", "1 p 0 gen [[0.15, 0.0]]\n", "2 p 1 gen [[0.12, 0.0]]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.polynomial_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An element can either have polynomial costs or piecewise linear costs at the same time. So let us first delete the polynomial costs in order to avoid confusion and errors:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [], "source": [ "net.polynomial_cost= net.polynomial_cost.drop(net.polynomial_cost.index.values)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The results above have been produced with polynomial cost functions, that were linear. Let's try to reproduce the results using piecewise linear cost functions. Note: The cost functions need to have the same gradient!" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "ename": "ValueError", "evalue": "Cost function must be defined for whole power range of the generator", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreate_piecewise_linear_cost\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"gen\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m,\u001b[0m \u001b[1;36m0.15\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreate_piecewise_linear_cost\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"gen\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.12\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreate_piecewise_linear_cost\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"ext_grid\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\create.py\u001b[0m in \u001b[0;36mcreate_piecewise_linear_cost\u001b[0;34m(net, element, element_type, data_points, type, index)\u001b[0m\n\u001b[1;32m 2127\u001b[0m if not (net[element_type].max_p_kw.at[element] <= max(p) and\n\u001b[1;32m 2128\u001b[0m net[element_type].min_p_kw.at[element] >= min(p)):\n\u001b[0;32m-> 2129\u001b[0;31m raise ValueError(\"Cost function must be defined for whole power range of the \"\n\u001b[0m\u001b[1;32m 2130\u001b[0m \"generator\")\n\u001b[1;32m 2131\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mtype\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m\"q\"\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: Cost function must be defined for whole power range of the generator" ] } ], "source": [ "pp.create_piecewise_linear_cost(net, 0, \"gen\", np.array([[0, 0], [1 , 0.15]]))\n", "pp.create_piecewise_linear_cost(net, 1, \"gen\", np.array([[0, 0], [1, 0.12]]))\n", "pp.create_piecewise_linear_cost(net, 0, \"ext_grid\", np.array([[0, 0], [1, 0.1]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What we forgot is that the piecewise linear function should be defined for the whole range of the generator. The range is determined by p_max and p_min. Let's check:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0 0.0\n", "1 0.0\n", "Name: max_p_kw, dtype: float64" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.gen.max_p_kw" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0 -80000.0\n", "1 -100000.0\n", "Name: min_p_kw, dtype: float64" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.gen.min_p_kw" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We try again:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pp.create_piecewise_linear_cost(net, 0, \"gen\", np.array([[-80000* 1 , -80000*0.15], [0, 0]]))\n", "pp.create_piecewise_linear_cost(net, 1, \"gen\", np.array([[-100000*1, -100000*0.12], [0, 0]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An external grid usually has no operational limits, but this is a problem for the OPF:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "ename": "AttributeError", "evalue": "No operational constraints defined for controllable element!", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreate_piecewise_linear_cost\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"ext_grid\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32mC:\\Users\\fmeier\\pandapower\\pandapower\\create.py\u001b[0m in \u001b[0;36mcreate_piecewise_linear_cost\u001b[0;34m(net, element, element_type, data_points, type, index)\u001b[0m\n\u001b[1;32m 2124\u001b[0m if not (hasattr(net[element_type], \"max_p_kw\") and hasattr(net[element_type],\n\u001b[1;32m 2125\u001b[0m \"min_p_kw\")):\n\u001b[0;32m-> 2126\u001b[0;31m \u001b[1;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"No operational constraints defined for controllable element!\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2127\u001b[0m if not (net[element_type].max_p_kw.at[element] <= max(p) and\n\u001b[1;32m 2128\u001b[0m net[element_type].min_p_kw.at[element] >= min(p)):\n", "\u001b[0;31mAttributeError\u001b[0m: No operational constraints defined for controllable element!" ] } ], "source": [ "pp.create_piecewise_linear_cost(net, 0, \"ext_grid\", np.array([[0, 0], [1, 0.1]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we set imaginary constraints, that we can choose very broad:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": true }, "outputs": [], "source": [ "net.ext_grid[\"max_p_kw\"] = 1e9\n", "net.ext_grid[\"min_p_kw\"] = -1e9" ] }, { "cell_type": "code", "execution_count": 39, "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", "
namebusvm_puva_degreein_servicemax_p_kwmin_p_kw
0None01.00.0True1.000000e+09-1.000000e+09
\n", "
" ], "text/plain": [ " name bus vm_pu va_degree in_service max_p_kw min_p_kw\n", "0 None 0 1.0 0.0 True 1.000000e+09 -1.000000e+09" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.ext_grid" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pp.create_piecewise_linear_cost(net, 0, \"ext_grid\", np.array([[-1e9, -1e9*.1], [1e9, 1e9*0.1]]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us check the results from the previous OPF again!" ] }, { "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", " \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", "
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN0.000000-49999.999962NaN100.0000000.0
1NaN-3.43696760000.000000NaN130.9090910.0
2NaN-5.70856661488.746675NaN150.0000000.0
3NaN-1.362340-71488.746713NaN120.0000000.0
\n", "
" ], "text/plain": [ " vm_pu va_degree p_kw q_kvar lam_p lam_q\n", "0 NaN 0.000000 -49999.999962 NaN 100.000000 0.0\n", "1 NaN -3.436967 60000.000000 NaN 130.909091 0.0\n", "2 NaN -5.708566 61488.746675 NaN 150.000000 0.0\n", "3 NaN -1.362340 -71488.746713 NaN 120.000000 0.0" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_bus" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16055.337600528508" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We run the same OPF now with different cost function setup. We should get the exact same results:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pp.rundcopp(net)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16055.337600298368" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_cost" ] }, { "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
vm_puva_degreep_kwq_kvarlam_plam_q
0NaN-6.163691e-25-49999.999965NaN100.0000000.0
1NaN-3.436967e+0060000.000000NaN130.9090910.0
2NaN-5.708566e+0061488.746680NaN150.0000000.0
3NaN-1.362340e+00-71488.746715NaN120.0000000.0
\n", "
" ], "text/plain": [ " vm_pu va_degree p_kw q_kvar lam_p lam_q\n", "0 NaN -6.163691e-25 -49999.999965 NaN 100.000000 0.0\n", "1 NaN -3.436967e+00 60000.000000 NaN 130.909091 0.0\n", "2 NaN -5.708566e+00 61488.746680 NaN 150.000000 0.0\n", "3 NaN -1.362340e+00 -71488.746715 NaN 120.000000 0.0" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "net.res_bus" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "celltoolbar": "Raw Cell Format", "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 }