{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Reactive Power Optimization with PandaModels.jl\n", "\n", "This tutorial describes how to solve some optimization problems regarding reactive power redispatch using **PandaModels**. The reactive power provision of generators, e.g., net.sgen, can be optimized for \n", "\n", "1) maintaining voltage setpoints \n", "2) maintaining reactive power setpoints \n", "3) (active) power loss reduction \\\n", "4) branch loading reduction\n", "\n", "\n", "For more details on the corresponding models, see:\n", "* [maintaining voltage setpoints](https://github.com/e2nIEE/PandaModels.jl/blob/develop/src/models/vstab.jl)\n", "* [maintaining reactive power setpoints](https://github.com/e2nIEE/PandaModels.jl/blob/develop/src/models/qflex.jl)\n", "* [power loss reduction](https://github.com/e2nIEE/PandaModels.jl/blob/develop/src/models/ploss.jl)\n", "\n", "**Note**:\n", "\n", "- **PandaModels** is still in the development stage, and the developed models for reactive power optimizations are tested with limited grids. It is possible that errors may arise when facing different grids.\n", "- It is suggested to use **net.sn_mva=1.0** to start the optimization. Using other sn_mva values may introduce not converged OPF \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1) Maintaining Voltage Setpoints\n", "\n", "Grid operators want to maintain a constant voltage profile across all or a part of the system buses. Reactive power optimization, in this case, helps them identify the preferable provision of reactive power from generators. The objective is to minimize the deviation of the voltages of certain buses (here, buses of DER) from a setpoint, e.g.,$V_{\\rm setpoint}\n", "= 1.03 p.u.$ As a result, the reactive power setpoint for each generator is calculated. The mathematical formulation of this objective function can have the following forms:\n", "\n", "\\begin{align}\n", "& \\underset{\\mathcal{X} = [q, ...]}{\\text{minimize}}\n", "& & \\sum_{i\\in \\mathcal{BI}} (V_i-V_{\\rm setpoint})^2 \\\\\n", "& \\text{subject to}\n", "& & g(\\mathcal{X})=0 \\\\\n", "& & & h(\\mathcal{X}) \\leq 0\n", "\\end{align}\n", "\n", "where $V_{i}$ is the voltage variable of bus $i$ in $\\mathcal{BI}$ which denotes the set of buses of DER. The $g(\\mathcal{X})$ and $h(\\mathcal{X})$, denote equality and inequality constraints, respectively. The $\\mathcal{X}$ denotes the set of variables decisions, such as reactive power $q$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-1: Create test grid\n", "\n", "How does it work? Let's first create a cigre grid with DERs(distribution energy resource) from the pandapower's network database. After running the power flow calculation, we can see that there are nine DERs (net.sgen) in the grid, and they don't provide reactive power for normal operation." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", "
p_mwq_mvar
00.020.0
10.020.0
20.030.0
30.030.0
40.030.0
50.030.0
60.040.0
70.010.0
81.500.0
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.0\n", "1 0.02 0.0\n", "2 0.03 0.0\n", "3 0.03 0.0\n", "4 0.03 0.0\n", "5 0.03 0.0\n", "6 0.04 0.0\n", "7 0.01 0.0\n", "8 1.50 0.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import pandapower as pp\n", "import pandapower.networks as nw\n", "from copy import deepcopy\n", "\n", "net = nw.create_cigre_network_mv(with_der=\"pv_wind\")\n", "pp.runpp(net) # run power flow calculation\n", "net_org = deepcopy(net) # copy of the grid for further comparison\n", "display(net.res_sgen) # show power flow results for DER" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(You can use the pandapower plotting module to visualize the grid model.)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandapower.plotting as plot\n", "%matplotlib inline\n", "plot.simple_plot(net)" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "### 1-2: Parametrization for optimization\n", "Before starting the optimization, we need to configure some parameters. \n", "In PandaModels, the uncontrollable loads and DER (net.sgen) are converted to load, and the controllable power elements are converted to generators. Accordingly, we neet to set loads as uncontrollable and set DER (net.sgen) as controllable elements. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "net_opt = deepcopy(net) # copy of the grid for further comparison \n", "net_opt.load['controllable'] = False\n", "net_opt.sgen['controllable'] = True" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Now, let's set the constraints." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "# lower and upper bounds for buses\n", "net_opt.bus[\"max_vm_pu\"] = 1.1\n", "net_opt.bus[\"min_vm_pu\"] = 0.9\n", "\n", "# lower and upper bounds for external grid\n", "net_opt.ext_grid[\"max_q_mvar\"] = 10000.0\n", "net_opt.ext_grid[\"min_q_mvar\"] = -10000.0\n", "net_opt.ext_grid[\"max_p_mw\"] = 10000.0\n", "net_opt.ext_grid[\"min_p_mw\"] = -10000.0" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "We keep the active power for DER constant to the calculated value from the power flow and define a constraint for the reactive power. (In this grid, there is no generator (net.gen))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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_mwq_mvarsn_mvascalingin_servicetypecurrent_sourcecontrollablemax_p_mwmin_p_mwmax_q_mvarmin_q_mvar
0PV 330.020.00.021.0TruePVTrueTrue0.020.020.00656-0.00656
1PV 440.020.00.021.0TruePVTrueTrue0.020.020.00656-0.00656
2PV 550.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
3PV 660.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
4PV 880.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
5PV 990.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
6PV 10100.040.00.041.0TruePVTrueTrue0.040.040.01312-0.01312
7PV 11110.010.00.011.0TruePVTrueTrue0.010.010.00328-0.00328
8WKA 771.500.01.501.0TrueWPTrueTrue1.501.500.49200-0.49200
\n", "
" ], "text/plain": [ " name bus p_mw q_mvar sn_mva scaling in_service type current_source \\\n", "0 PV 3 3 0.02 0.0 0.02 1.0 True PV True \n", "1 PV 4 4 0.02 0.0 0.02 1.0 True PV True \n", "2 PV 5 5 0.03 0.0 0.03 1.0 True PV True \n", "3 PV 6 6 0.03 0.0 0.03 1.0 True PV True \n", "4 PV 8 8 0.03 0.0 0.03 1.0 True PV True \n", "5 PV 9 9 0.03 0.0 0.03 1.0 True PV True \n", "6 PV 10 10 0.04 0.0 0.04 1.0 True PV True \n", "7 PV 11 11 0.01 0.0 0.01 1.0 True PV True \n", "8 WKA 7 7 1.50 0.0 1.50 1.0 True WP True \n", "\n", " controllable max_p_mw min_p_mw max_q_mvar min_q_mvar \n", "0 True 0.02 0.02 0.00656 -0.00656 \n", "1 True 0.02 0.02 0.00656 -0.00656 \n", "2 True 0.03 0.03 0.00984 -0.00984 \n", "3 True 0.03 0.03 0.00984 -0.00984 \n", "4 True 0.03 0.03 0.00984 -0.00984 \n", "5 True 0.03 0.03 0.00984 -0.00984 \n", "6 True 0.04 0.04 0.01312 -0.01312 \n", "7 True 0.01 0.01 0.00328 -0.00328 \n", "8 True 1.50 1.50 0.49200 -0.49200 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# lower and upper bounds for DERs\n", "net_opt.sgen[\"max_p_mw\"] = net_opt.sgen.p_mw.values\n", "net_opt.sgen[\"min_p_mw\"] = net_opt.sgen.p_mw.values\n", "net_opt.sgen[\"max_q_mvar\"] = net_opt.sgen.p_mw.values * 0.328\n", "net_opt.sgen[\"min_q_mvar\"] = -net_opt.sgen.p_mw.values * 0.328\n", "display(net_opt.sgen)" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Subsequently, let's set a high upper bound for lines and transformers to avoid congestion issues." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "# lower and upper bounds for lines\n", "net_opt.trafo[\"max_loading_percent\"] = 100.0\n", "net_opt.line[\"max_loading_percent\"] = 100.0" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Finally, we need to let PandaModels know which buses are of interest and what is user-defined voltage setpoint. To do this, we can add extra column called **\"pm_param/setpoint_v\"** in net.bus and set values for buses connecting DER (net.sgen)." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "net_opt.bus[\"pm_param/setpoint_v\"] = None # add extra column\n", "net_opt.bus[\"pm_param/setpoint_v\"].loc[net_opt.sgen.bus] = 0.96 # voltage setpoints for theses buses are 0.96" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-3: Start optimization\n", "Now let's call the function ***pandapower.runpm_vstab()*** to start the optimizaiton for maintaining voltage setpoints. \n", "(Note that the first time the function is called, Julia is started in the background, which may take some time.)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "pycharm": { "name": "#%%\n" }, "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 2.05 seconds:\n" ] } ], "source": [ "try:\n", " pp.runpm_vstab(net_opt)\n", "except Exception as err:\n", " print(err) " ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Also, the following parameters and options can be modified as inputs while calling the optimization from PandaModles. For this case, we can keep the default values.\n", "\n", "| parameter | description | type | default |\n", "| :--- | :--- | :---: | :--- |\n", "| correct_pm_network_data | checks if network data is correct. If not tries to correct it | bool | True |\n", "| silence | Suppresses information and warning messages output by PowerModels | bool | True |\n", "| pm_model | PowerModels.jl model to use | str | \"ACPPowerModel\" |\n", "| pm_solver | \"main\" solver| str | \"ipopt\" |\n", "| pm_mip_solver | mixed integer solver| str | \"cbc\" |\n", "| pm_nl_solver | nonlinear solver| str | \"ipopt\" |\n", "| pm_tol | default desired convergence tolerance for solver to use | float | 1e-8 |\n", "| pm_log_level | solver log level in power models | int | 0 |\n", "| delete_buffer_file | If True, the .json file used by PandaModels will be deleted after optimization. | bool | True |\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-4: Results comparison\n", "Let's check the results for voltage and reactive power at buses connecting DER before and after the optimization." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/plain": [ "3 0.951848\n", "4 0.950094\n", "5 0.948893\n", "6 0.947488\n", "8 0.949187\n", "9 0.948264\n", "10 0.947100\n", "11 0.946916\n", "7 0.952199\n", "Name: vm_pu, dtype: float64" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "--- deviation from setpionts v=0.96 ---\n" ] }, { "data": { "text/plain": [ "0.0010976683852842502" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# results from power flow\n", "display(net_org.res_bus.vm_pu[net_org.sgen.bus])\n", "v_org = net_org.res_bus.vm_pu[net_org.sgen.bus].values\n", "print(\"--- deviation from setpionts v=0.96 ---\")\n", "display(sum((v_org-0.96)**2)) " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3 0.961792\n", "4 0.960087\n", "5 0.958920\n", "6 0.957559\n", "8 0.960321\n", "9 0.959425\n", "10 0.958299\n", "11 0.958119\n", "7 0.964668\n", "Name: vm_pu, dtype: float64" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "--- deviation from setpionts v=0.96 ---\n" ] }, { "data": { "text/plain": [ "3.900054027594424e-05" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# results from optimization\n", "display(net_opt.res_bus.vm_pu[net.sgen.bus])\n", "v_opt = net_opt.res_bus.vm_pu[net_opt.sgen.bus].values\n", "print(\"--- deviation from setpionts v=0.96 ---\")\n", "display(sum((v_opt-0.96)**2)) # devition from setpoints v=0.96 p.u." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As exected, the bus voltages after optimization are close to the defined setpoints. It is caused by the provision of reactive power of DER." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", "
p_mwq_mvar
00.020.0
10.020.0
20.030.0
30.030.0
40.030.0
50.030.0
60.040.0
70.010.0
81.500.0
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.0\n", "1 0.02 0.0\n", "2 0.03 0.0\n", "3 0.03 0.0\n", "4 0.03 0.0\n", "5 0.03 0.0\n", "6 0.04 0.0\n", "7 0.01 0.0\n", "8 1.50 0.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# results from power flow\n", "display(net_org.res_sgen)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", "
p_mwq_mvar
00.020.006482
10.020.006497
20.030.009787
30.030.009799
40.030.009752
50.030.009765
60.040.013063
70.010.003228
81.500.441400
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.006482\n", "1 0.02 0.006497\n", "2 0.03 0.009787\n", "3 0.03 0.009799\n", "4 0.03 0.009752\n", "5 0.03 0.009765\n", "6 0.04 0.013063\n", "7 0.01 0.003228\n", "8 1.50 0.441400" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# results from optimization\n", "display(net_opt.res_sgen)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-5: Saving reactive power with multi-objectives\n", "In some situations, users want to improve the voltage profiles with limited reactive power provisions. For this, the objective function is modified by minimizing the reactive power provision. As the formulation below shows, the two sub-objectives for **maintaining voltage setpoints** and **saving reactive power provisions** are connected through coefficients $c_{\\rm v}$ and $c_{\\rm q}$. \n", "\n", "\\begin{align}\n", "& \\underset{\\mathcal{X} = [q, ...]}{\\text{minimize}}\n", "& & \\sum_{i\\in \\mathcal{BI}} c_{\\rm v}*(V_i-V_{\\rm setpoint})^2 + c_{\\rm q}*(q_i-0)^2 \\\\\n", "\\end{align}\n", "\n", "We can call the objective function with different coefficient combinations, e.g., $c_{\\rm v}=0.99$ and $c_{\\rm q}=0.01$.\n", "(In default, $c_{\\rm v}=1.0$ and $c_{\\rm q}=0.0$)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n" ] } ], "source": [ "net_optlim = deepcopy(net_opt)\n", "net_optlim[\"obj_factors\"] = [0.99, 0.01] # set coefficients for the multi-objective function\n", "try:\n", " pp.runpm_vstab(net_optlim)\n", "except:\n", " print(\"[WinError 3] The system cannot find the path specified to the python39.dll\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As the results below show, with $c_{\\rm v}=0.99$ and $c_{\\rm q}=0.01$, the provided reactive powers are reduced, and the corresponding voltages are increased." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "pycharm": { "name": "#%%\n" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "--- optimized reactive power without limitation Cv = 1.0, Cq = 0. ----\n" ] }, { "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", "
p_mwq_mvar
00.020.006482
10.020.006497
20.030.009787
30.030.009799
40.030.009752
50.030.009765
60.040.013063
70.010.003228
81.500.441400
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.006482\n", "1 0.02 0.006497\n", "2 0.03 0.009787\n", "3 0.03 0.009799\n", "4 0.03 0.009752\n", "5 0.03 0.009765\n", "6 0.04 0.013063\n", "7 0.01 0.003228\n", "8 1.50 0.441400" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "--- optimized reactive power with limitation Cv = 0.99, Cq = 0.01 ----\n" ] }, { "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", "
p_mwq_mvar
00.020.006559
10.020.006559
20.030.009839
30.030.009839
40.030.009839
50.030.009839
60.040.013119
70.010.003279
81.500.127064
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.006559\n", "1 0.02 0.006559\n", "2 0.03 0.009839\n", "3 0.03 0.009839\n", "4 0.03 0.009839\n", "5 0.03 0.009839\n", "6 0.04 0.013119\n", "7 0.01 0.003279\n", "8 1.50 0.127064" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "--- deviation from setpoints without limitation Cv = 1.0, Cq = 0. ----\n" ] }, { "data": { "text/plain": [ "3.900054027594424e-05" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "--- deviation from setpoints with limitation Cv = 0.99, Cq = 0.01 ----\n" ] }, { "data": { "text/plain": [ "0.00043781176800306845" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "print (\"--- optimized reactive power without limitation Cv = 1.0, Cq = 0. ----\")\n", "display(net_opt.res_sgen) # show optimized reactive power without limitation\n", "print (\"--- optimized reactive power with limitation Cv = 0.99, Cq = 0.01 ----\")\n", "display(net_optlim.res_sgen) # show optimized reactive power with limitation\n", "\n", "print (\"--- deviation from setpoints without limitation Cv = 1.0, Cq = 0. ----\")\n", "display(sum((v_opt - 0.96) ** 2)) # show optimized reactive power without limitation\n", "print (\"--- deviation from setpoints with limitation Cv = 0.99, Cq = 0.01 ----\")\n", "v_optlim = net_optlim.res_bus.vm_pu[net_optlim.sgen.bus].values\n", "display(sum((v_optlim - 0.96) ** 2)) # show optimized bus voltages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The coefficient combination is grid-dependent. For example, the picture below shows the result for one of our case studies with a realistic grid. The user can find the most suitable combination setting through several attempts.\n", "\"ALT\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-6: Time series optimizations\n", "There are two ways to perform time series optimizations. \n", "The first one is optimization in a loop, i.e., updating the grid condition for each time step and repeatedly calling optimization. The second one uses the \"multi-timestep\" optimization. PowerModels can solve the multi-grid optimization problem. This feature is used in PandaModels to deal with time series optimization for on specific grid by replacing the \"multi-grid\" with \"multi-timestep\" of the grid. \n", "\n", "Next, you will see an example." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, let's load the time series data." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timesteppvwindresidential
000.0061430.6226000.256022
110.0058770.6235850.248835
220.0055050.6250560.211973
330.0052930.6258970.201825
440.0049210.6273690.209164
...............
91910.0058350.9213880.435660
92920.0054230.9184470.410870
93930.0047040.8868370.344715
94940.0041430.8583390.304026
95950.0036670.8383700.286328
\n", "

96 rows × 4 columns

\n", "
" ], "text/plain": [ " timestep pv wind residential\n", "0 0 0.006143 0.622600 0.256022\n", "1 1 0.005877 0.623585 0.248835\n", "2 2 0.005505 0.625056 0.211973\n", "3 3 0.005293 0.625897 0.201825\n", "4 4 0.004921 0.627369 0.209164\n", ".. ... ... ... ...\n", "91 91 0.005835 0.921388 0.435660\n", "92 92 0.005423 0.918447 0.410870\n", "93 93 0.004704 0.886837 0.344715\n", "94 94 0.004143 0.858339 0.304026\n", "95 95 0.003667 0.838370 0.286328\n", "\n", "[96 rows x 4 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import pandas as pd\n", "\n", "# load time series data for 96 time steps\n", "time_series = pd.read_json(\"cigre_timeseries_15min.json\")\n", "time_series.sort_index(inplace=True)\n", "\n", "# show time series\n", "display(time_series) \n", "\n", "# set load type and sgen type in the cigre grid\n", "net[\"load\"].loc[:, \"type\"] = \"residential\"\n", "net.sgen.loc[:, \"type\"] = \"pv\"\n", "net.sgen.loc[8, \"type\"] = \"wind\"\n", "\n", "# get rated power\n", "load_p = net[\"load\"].loc[:, \"p_mw\"].values\n", "sgen_p = net[\"sgen\"].loc[:7, \"p_mw\"].values\n", "wind_p = net[\"sgen\"].loc[8, \"p_mw\"]\n", "\n", "# create dataframe for loads and sgens\n", "load_ts = pd.DataFrame(index=time_series.index.tolist(), columns=net.load.index.tolist())\n", "sgen_ts = pd.DataFrame(index=time_series.index.tolist(), columns=net.sgen.index.tolist())\n", "for t in range(96):\n", " load_ts.loc[t] = load_p * time_series.at[t, \"residential\"]\n", " sgen_ts.loc[t][:8] = sgen_p * time_series.at[t, \"pv\"]\n", " sgen_ts.loc[t][8] = wind_p * time_series.at[t, \"wind\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we perform the time series optimizations in a loop." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.02 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.06 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.07 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.05 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.04 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.02 seconds:\n", "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_vstab') is finished in 0.03 seconds:\n" ] } ], "source": [ "########################################################################\n", "####################### Optimization in a loop #########################\n", "########################################################################\n", "\n", "y_loop = []\n", "for t in range(96):\n", " \n", " # Update operating points for each time step\n", " net_opt.load.p_mw = load_ts.loc[t]\n", " net_opt.sgen.p_mw = sgen_ts.loc[t]\n", " \n", " # If required, we also need to update the constraints, e.g., Qmax- and Qmin-value, for each time step. \n", " net_opt.sgen.max_p_mw = sgen_ts.loc[t] # for load: max_p_mw == min_p_mw, because they are not controllable.\n", " net_opt.sgen.min_p_mw = sgen_ts.loc[t]\n", " net_opt.sgen.max_q_mvar = net_opt.sgen.max_q_mvar\n", " net_opt.sgen.min_q_mvar = net_opt.sgen.min_q_mvar\n", " \n", " # run optimization for time step t\n", " try:\n", " pp.runpm_vstab(net_opt)\n", " except:\n", " print(\"[WinError 3] The system cannot find the path specified to the python39.dll\")\n", " \n", " # save the mean voltage value for each time step\n", " y_loop.append(net_opt.res_bus.vm_pu[net_opt.sgen.bus].values.mean())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we can do it using multi-timestep optimization." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_multi_vstab') is finished in 5.88 seconds:\n" ] } ], "source": [ "########################################################################\n", "####################### multi-timestep optimization ####################\n", "########################################################################\n", "\n", "from pandapower.control import ConstControl\n", "from pandapower.timeseries import DFData\n", "\n", "# For this method, we need to add the time series data into the pandapower.controller.\n", "net_opt.controller.drop(net.controller.index, inplace=True) # remove the existing controllers\n", "\n", "# Add time series for load and sgen.\n", "ConstControl(net_opt, element=\"load\", variable=\"p_mw\",\n", " element_index=net.load.index.tolist(), profile_name=net.load.index.tolist(),\n", " data_source=DFData(load_ts))\n", "ConstControl(net_opt, element=\"sgen\", variable=\"p_mw\",\n", " element_index=net.sgen.index.tolist(), profile_name=net.sgen.index.tolist(),\n", " data_source=DFData(sgen_ts))\n", "\n", "# If required, we also need to creat a time series for the constraints, e.g., Qmax- and Qmin-value, for each time step. \n", "df_qmax, df_qmin = sgen_ts.copy(), sgen_ts.copy()\n", "df_qmax[df_qmax.columns] = net_opt.sgen.max_q_mvar\n", "df_qmin[df_qmin.columns] = net_opt.sgen.min_q_mvar\n", "\n", "# Then create controllers for them.\n", "ConstControl(net_opt, element=\"sgen\", variable=\"max_p_mw\",\n", " element_index=net.sgen.index.tolist(), profile_name=net.sgen.index.tolist(),\n", " data_source=DFData(sgen_ts))\n", "ConstControl(net_opt, element=\"sgen\", variable=\"min_p_mw\",\n", " element_index=net.sgen.index.tolist(), profile_name=net.sgen.index.tolist(),\n", " data_source=DFData(sgen_ts))\n", "ConstControl(net_opt, element=\"sgen\", variable=\"max_q_mvar\",\n", " element_index=net.sgen.index.tolist(), profile_name=net.sgen.index.tolist(),\n", " data_source=DFData(df_qmax))\n", "ConstControl(net_opt, element=\"sgen\", variable=\"min_q_mvar\",\n", " element_index=net.sgen.index.tolist(), profile_name=net.sgen.index.tolist(),\n", " data_source=DFData(df_qmin))\n", "\n", "# For the multi-timestep optimization, we need to call another PandaModels-function.\n", "try:\n", " pp.runpm_multi_vstab(net_opt, from_time_step=0, to_time_step=96)\n", "except:\n", " print(\"[WinError 3] The system cannot find the path specified to the python39.dll\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note that**, currently, the function ***pp.runpm_multi_vstab()*** doesn't support using of the multi-objective function for saving reactive power.\n", "\n", "The results for each time step are saved in **net.res_ts_opt**. Let's get them." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "y_multi = []\n", "for t in range(96):\n", " y_multi.append(net_opt.res_ts_opt[str(t)].res_bus.vm_pu[net_opt.sgen.bus].values.mean())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And then plot them." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, 'mean voltage value for DER-buses [p.u.]')" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)\n", "ax1.plot(range(96), y_loop)\n", "ax1.set_title(\"results for \\n optimization in a loop\")\n", "ax2.plot(range(96), y_multi)\n", "ax2.set_title(\"results for \\n multi-timestep optimization\")\n", "\n", "for ax in ax1, ax2:\n", " ax.grid(True)\n", " ax.label_outer()\n", " ax.set_xlabel(\"time step [15min]\")\n", "ax1.set_ylabel(\"mean voltage value for DER-buses [p.u.]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As the plot above shows, both methods have the same results.\n", "\n", "**For a long-term time series optimization (>500 timesteps), we suggest using the first method, optimization in a loop.**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2) Maintaining Reactive Power Setpoints\n", "\n", "The motivation for this objective is to minimize the deviations of reactive power injection at the TSO-DSO interface from a target value, e.g., $Q_{\\rm setpoint}= 2 \\rm MVar$. It is formulated by the following equation:\n", "\n", "\\begin{align}\n", "& \\underset{\\mathcal{X} = [q, ...]}{\\text{minimize}}\n", "& & \\sum_{i\\in \\mathcal{interfaces}} (Q_i-Q_{\\rm setpoint})^2 \\\\\n", "\\end{align}\n", "\n", "We use the same grid model to introduce the example. As the picture low shows, the marked bus (or interface) is observed.\n", "\n", "\n", "\"ALT\"\n", "\n", "First, let's create the grid and check the reactive power injection at this interface." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/plain": [ "-5.941540318632734" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import pandapower as pp\n", "import pandapower.networks as nw\n", "from copy import deepcopy\n", "\n", "net = nw.create_cigre_network_mv(with_der=\"pv_wind\")\n", "pp.runpp(net)\n", "net_org = deepcopy(net)\n", "\n", "display(net.res_trafo.q_lv_mvar[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Without optimization, the reactive power injection at this interface is -5.942 MVAr.\n", "\n", "Let's configure optimization parameters and define a target value for this interface, $Q_{\\rm setpoint}= -5 \\rm MVAr$, i.e., we optimize the reactive power provision of DER to achieve this target." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "pycharm": { "name": "#%%\n" } }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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_mwq_mvarsn_mvascalingin_servicetypecurrent_sourcecontrollablemax_p_mwmin_p_mwmax_q_mvarmin_q_mvar
0PV 330.020.00.021.0TruePVTrueTrue0.020.020.00656-0.00656
1PV 440.020.00.021.0TruePVTrueTrue0.020.020.00656-0.00656
2PV 550.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
3PV 660.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
4PV 880.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
5PV 990.030.00.031.0TruePVTrueTrue0.030.030.00984-0.00984
6PV 10100.040.00.041.0TruePVTrueTrue0.040.040.01312-0.01312
7PV 11110.010.00.011.0TruePVTrueTrue0.010.010.00328-0.00328
8WKA 771.500.01.501.0TrueWPTrueTrue1.501.500.49200-0.49200
\n", "
" ], "text/plain": [ " name bus p_mw q_mvar sn_mva scaling in_service type current_source \\\n", "0 PV 3 3 0.02 0.0 0.02 1.0 True PV True \n", "1 PV 4 4 0.02 0.0 0.02 1.0 True PV True \n", "2 PV 5 5 0.03 0.0 0.03 1.0 True PV True \n", "3 PV 6 6 0.03 0.0 0.03 1.0 True PV True \n", "4 PV 8 8 0.03 0.0 0.03 1.0 True PV True \n", "5 PV 9 9 0.03 0.0 0.03 1.0 True PV True \n", "6 PV 10 10 0.04 0.0 0.04 1.0 True PV True \n", "7 PV 11 11 0.01 0.0 0.01 1.0 True PV True \n", "8 WKA 7 7 1.50 0.0 1.50 1.0 True WP True \n", "\n", " controllable max_p_mw min_p_mw max_q_mvar min_q_mvar \n", "0 True 0.02 0.02 0.00656 -0.00656 \n", "1 True 0.02 0.02 0.00656 -0.00656 \n", "2 True 0.03 0.03 0.00984 -0.00984 \n", "3 True 0.03 0.03 0.00984 -0.00984 \n", "4 True 0.03 0.03 0.00984 -0.00984 \n", "5 True 0.03 0.03 0.00984 -0.00984 \n", "6 True 0.04 0.04 0.01312 -0.01312 \n", "7 True 0.01 0.01 0.00328 -0.00328 \n", "8 True 1.50 1.50 0.49200 -0.49200 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "net_opt = deepcopy(net) # copy of the grid for further comparison \n", "net_opt.load['controllable'] = False\n", "net_opt.sgen['controllable'] = True\n", "\n", "# lower and upper bounds for buses\n", "net_opt.bus[\"max_vm_pu\"] = 1.1\n", "net_opt.bus[\"min_vm_pu\"] = 0.9\n", "\n", "# lower and upper bounds for external grid\n", "net_opt.ext_grid[\"max_q_mvar\"] = 10000.0\n", "net_opt.ext_grid[\"min_q_mvar\"] = -10000.0\n", "net_opt.ext_grid[\"max_p_mw\"] = 10000.0\n", "net_opt.ext_grid[\"min_p_mw\"] = -10000.0\n", "\n", "# lower and upper bounds for DERs\n", "net_opt.sgen[\"max_p_mw\"] = net_opt.sgen.p_mw.values\n", "net_opt.sgen[\"min_p_mw\"] = net_opt.sgen.p_mw.values\n", "net_opt.sgen[\"max_q_mvar\"] = net_opt.sgen.p_mw.values * 0.328\n", "net_opt.sgen[\"min_q_mvar\"] = -net_opt.sgen.p_mw.values * 0.328\n", "display(net_opt.sgen)\n", "\n", "# lower and upper bounds for lines\n", "net_opt.trafo[\"max_loading_percent\"] = 100.0\n", "net_opt.line[\"max_loading_percent\"] = 100.0\n", "\n", "######################################################\n", "####################### Attention ####################\n", "######################################################\n", "\n", "# We need to let PandaModels know which interface is of interest and what is user-defined setpoint. \n", "# So, we need to add extra column called **\"pm_param/setpoint_q\"** in net.trafo and set target value. \n", "\n", "net_opt.trafo[\"pm_param/setpoint_q\"] = None # add extra column\n", "net_opt.trafo[\"pm_param/setpoint_q\"][0] = -5 # reactive power setpoint for trafo 0 is -5 MVAR\n", "\n", "# Also, we need to tell PandaModels which side is observed.\n", "net_opt.trafo[\"pm_param/side\"] = None\n", "net_opt.trafo[\"pm_param/side\"][0] = \"lv\" # the observed side is the low-voltage side\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After parametrization, we can start the optimization using ***pp.runpm_qflex()***." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "pycharm": { "name": "#%%\n" }, "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_qflex') is finished in 0.03 seconds:\n" ] } ], "source": [ "try:\n", " pp.runpm_qflex(net_opt)\n", "except:\n", " print(\"[WinError 3] The system cannot find the path specified to the python39.dll\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check the optimization results." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/plain": [ "-5.356245826038442" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
p_mwq_mvar
00.020.00656
10.020.00656
20.030.00984
30.030.00984
40.030.00984
50.030.00984
60.040.01312
70.010.00328
81.500.49200
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.00656\n", "1 0.02 0.00656\n", "2 0.03 0.00984\n", "3 0.03 0.00984\n", "4 0.03 0.00984\n", "5 0.03 0.00984\n", "6 0.04 0.01312\n", "7 0.01 0.00328\n", "8 1.50 0.49200" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(net_opt.res_trafo.q_lv_mvar[0]) # show Q-injection at the interface after optimization\n", "display(net_opt.res_sgen) # show optimized reactiv power provision of DER" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From the results above, we can see that the Q-injection at the interface is closer to the setpoint after the optimization but not achieved. The reason is that the Q-maximum is limited. We can modify the Q-maximum and try again." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "hp.pandapower.opf.make_objective - WARNING: no costs are given - overall generated power is minimized\n", "hp.pandapower.opf.run_powermodels - INFO: Optimization ('run_pandamodels_qflex') is finished in 0.02 seconds:\n" ] }, { "data": { "text/plain": [ "-5.0000000238509115" ] }, "metadata": {}, "output_type": "display_data" }, { "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", "
p_mwq_mvar
00.020.001931
10.020.001945
20.030.004184
30.030.004198
40.030.004140
50.030.004168
60.040.006959
70.010.000483
81.500.881054
\n", "
" ], "text/plain": [ " p_mw q_mvar\n", "0 0.02 0.001931\n", "1 0.02 0.001945\n", "2 0.03 0.004184\n", "3 0.03 0.004198\n", "4 0.03 0.004140\n", "5 0.03 0.004168\n", "6 0.04 0.006959\n", "7 0.01 0.000483\n", "8 1.50 0.881054" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "net_opt.sgen[\"max_q_mvar\"] = net_opt.sgen.p_mw.values * 0.628\n", "net_opt.sgen[\"min_q_mvar\"] = -net_opt.sgen.p_mw.values * 0.628\n", "try:\n", " pp.runpm_qflex(net_opt)\n", "except:\n", " print(\"[WinError 3] The system cannot find the path specified to the python39.dll\")\n", "display(net_opt.res_trafo.q_lv_mvar[0]) # show Q-injection at the interface after optimization\n", "display(net_opt.res_sgen)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, the Q-injection at the interface is optimized to -5 MVAr. \n", "\n", "Similar to the **maintaining voltage setpoints**, if you are interested in time series optimizations, you can do it through a loop or use ***pp.runpm_multi_qflex()***." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3) Power Loss Reduction and Branch Loading Reduction\n", "\n", "The corresponding objective functions are formulated as follows: \n", "\n", "- loss reduction\n", "\\begin{align}\n", "& \\underset{\\mathcal{X} = [q, ...]}{\\text{minimize}}\n", "& & \\sum_{(i, j)\\in \\mathcal{N}} (S_{ij}+S_{ji})^2 \\\\\n", "\\end{align}\n", "\n", "\n", "- loading reduction\n", "\\begin{align}\n", "& \\underset{\\mathcal{X} = [q, ...]}{\\text{minimize}}\n", "& & \\sum_{(i, j)\\in \\mathcal{N}} (i_{i->j, target}-0)^2 \\\\\n", "\\end{align}\n", "\n", "We still use the cigre medium voltage grid to introduce the case studies. First, let's create the grid, add constraints, and define the observed branches." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import pandapower as pp\n", "import pandapower.networks as nw\n", "from copy import deepcopy\n", "\n", "net = nw.create_cigre_network_mv(with_der=\"pv_wind\")\n", "net.load['controllable'] = False\n", "net.sgen['controllable'] = True\n", "net.sgen[\"max_p_mw\"] = net.sgen.p_mw.values\n", "net.sgen[\"min_p_mw\"] = net.sgen.p_mw.values\n", "net.sgen[\"max_q_mvar\"] = net.sgen.p_mw.values * 0.328\n", "net.sgen[\"min_q_mvar\"] = -net.sgen.p_mw.values * 0.328\n", "net.bus[\"max_vm_pu\"] = 1.1\n", "net.bus[\"min_vm_pu\"] = 0.9\n", "net.ext_grid[\"max_q_mvar\"] = 10000.0\n", "net.ext_grid[\"min_q_mvar\"] = -10000.0\n", "net.ext_grid[\"max_p_mw\"] = 10000.0\n", "net.ext_grid[\"min_p_mw\"] = -10000.0\n", "net.trafo[\"max_loading_percent\"] = 100.0\n", "net.line[\"max_loading_percent\"] = 100.0\n", "\n", "# add an additional column named \"pm_param/target_branch\" to let PandaModels know the observed branches.\n", "net.line[\"pm_param/target_branch\"] = True \n", "net.switch.loc[:, \"closed\"] = True\n", "\n", "# run power flow calculation\n", "pp.runpp(net)\n", "net_loss = deepcopy(net)\n", "net_loading = deepcopy(net)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you see, the power flow results without optimization are stored in the grid ***net***, and the grids ***net_loss*** and ***net_loading*** are going to used for optimization. Now we call the functions ***pp.runpm_ploss*** and ***pp.runpm_loading*** to reduce the power loss and line loading percent." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "no costs are given - overall generated power is minimized\n", "no costs are given - overall generated power is minimized\n" ] } ], "source": [ "pp.runpm_ploss(net_loss)\n", "pp.runpm_loading(net_loading)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's compare the results." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "loss without optimization: 0.070711475427468\n", "loss with optimization: 0.06241656797117738\n", "++++++++++++++++++++++++++++++++++++++++++++++\n", "loading without optimization: 260.54100720602156\n", "loading with optimization: 247.549588132589\n" ] } ], "source": [ "print(\"loss without optimization:\", net.res_line.pl_mw.values.sum())\n", "print(\"loss with optimization:\", net_loss.res_line.pl_mw.values.sum())\n", "print(\"++++++++++++++++++++++++++++++++++++++++++++++\")\n", "print(\"loading without optimization:\", net.res_line.loading_percent.values.sum())\n", "print(\"loading with optimization:\", net_loading.res_line.loading_percent.values.sum())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Also, we can reduce loss or loading percent of transformers:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "no costs are given - overall generated power is minimized\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "loss without optimization: 0.06354567913302844\n", "loss with optimization: 0.0629529981193997\n" ] } ], "source": [ "net_loss.line.drop(columns=[\"pm_param/target_branch\"], inplace=True)\n", "net_loss.trafo[\"pm_param/target_branch\"] = True\n", "pp.runpm_ploss(net_loss)\n", "print(\"loss without optimization:\", net.res_trafo.pl_mw.values.sum())\n", "print(\"loss with optimization:\", net_loss.res_trafo.pl_mw.values.sum())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "execution": { "allow_errors": true, "timeout": 300 }, "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.10.6" } }, "nbformat": 4, "nbformat_minor": 2 }