{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# pandapower Interface" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example (1) shows how to convert an ANDES system (`ssa`) to a pandapower network (`ssp`), (2) benchmarks the powerflow results, (3) shows how to alter `ssa` active power setpoints according to `ssp` results.\n", "\n", "This interface is mainly developed by [Jinning Wang](https://www.linkedin.com/in/jinning-wang-846490199/)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import andes\n", "\n", "from andes.interop.pandapower import to_pandapower, \\\n", " make_link_table, runopp_map, add_gencost\n", "\n", "andes.config_logger(20)\n", "\n", "import pandapower as pp\n", "import numpy as np\n", "import pandas as pd\n", "\n", "from math import pi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load case" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we use the same ANDES system `ss0` to do the pandapower conversion, which leaves the `ssa` untouched.\n", "\n", "This will be useful if you need to modify the `ssa` parametes or setpoints." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Working directory: \"/Users/jinningwang/Documents/work/andes/docs/source/examples\"\n", "> Loaded generated Python code in \"/Users/jinningwang/.andes/pycode\".\n", "Parsing input file \"/Users/jinningwang/Documents/work/andes/andes/cases/ieee14/ieee14_ieeet1.xlsx\"...\n", "Input file parsed in 0.2310 seconds.\n", "System internal structure set up in 0.0481 seconds.\n", "Working directory: \"/Users/jinningwang/Documents/work/andes/docs/source/examples\"\n", "> Reloaded generated Python code of module \"pycode\".\n", "Parsing input file \"/Users/jinningwang/Documents/work/andes/andes/cases/ieee14/ieee14_ieeet1.xlsx\"...\n", "Input file parsed in 0.0895 seconds.\n", "System internal structure set up in 0.0383 seconds.\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssa = andes.load(andes.get_case('ieee14/ieee14_ieeet1.xlsx'),\n", " setup=False,\n", " no_output=True,\n", " default_config=True)\n", "ssa.Toggle.u.v = [0, 0]\n", "ssa.setup()\n", "\n", "ss0 = andes.load(andes.get_case('ieee14/ieee14_ieeet1.xlsx'),\n", " setup=False,\n", " no_output=True,\n", " default_config=True)\n", "ss0.Toggle.u.v = [0, 0]\n", "ss0.setup()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Convert to pandapower net" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convert ADNES system `ssa` to pandapower net `ssp`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "-> System connectivity check results:\n", " No islanded bus detected.\n", " System is interconnected.\n", " Each island has a slack bus correctly defined and enabled.\n", "\n", "-> Power flow calculation\n", " Sparse solver: KLU\n", " Solution method: NR method\n", "Power flow initialized in 0.0031 seconds.\n", "0: |F(x)| = 0.5605182134\n", "1: |F(x)| = 0.006202200332\n", "2: |F(x)| = 5.819382825e-06\n", "3: |F(x)| = 6.967745825e-12\n", "Converged in 4 iterations in 0.0071 seconds.\n", "Power flow results are consistent. Conversion is successful.\n" ] } ], "source": [ "ssp = to_pandapower(ss0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add generator cost data." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gen_cost = np.array([\n", " [2, 0, 0, 3, 0.0430293, 20, 0], \n", " [2, 0, 0, 3, 0.25, 20, 0], \n", " [2, 0, 0, 3, 0.01, 40, 0], \n", " [2, 0, 0, 3, 0.01, 40, 0], \n", " [2, 0, 0, 3, 0.01, 40, 0]\n", "])\n", "\n", "add_gencost(ssp, gen_cost)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inspect the pandapower net `ssp`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "This pandapower network includes the following parameter tables:\n", " - bus (14 elements)\n", " - load (11 elements)\n", " - gen (5 elements)\n", " - shunt (2 elements)\n", " - line (16 elements)\n", " - trafo (4 elements)\n", " - poly_cost (5 elements)\n", " and the following results tables:\n", " - res_bus (14 elements)\n", " - res_line (16 elements)\n", " - res_trafo (4 elements)\n", " - res_load (11 elements)\n", " - res_shunt (2 elements)\n", " - res_gen (5 elements)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comapre Power Flow Results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run power flow of `ssa`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "-> System connectivity check results:\n", " No islanded bus detected.\n", " System is interconnected.\n", " Each island has a slack bus correctly defined and enabled.\n", "\n", "-> Power flow calculation\n", " Sparse solver: KLU\n", " Solution method: NR method\n", "Power flow initialized in 0.0037 seconds.\n", "0: |F(x)| = 0.5605182134\n", "1: |F(x)| = 0.006202200332\n", "2: |F(x)| = 5.819382825e-06\n", "3: |F(x)| = 6.967745825e-12\n", "Converged in 4 iterations in 0.0071 seconds.\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssa.PFlow.run()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# ssa\n", "ssa_res_gen = pd.DataFrame(columns=['name', 'p_mw', 'q_mvar', 'va_degree', 'vm_pu'])\n", "ssa_res_gen['name'] = ssa.PV.as_df()['name']\n", "ssa_res_gen['p_mw'] = ssa.PV.p.v * ssa.config.mva\n", "ssa_res_gen['q_mvar'] = ssa.PV.q.v * ssa.config.mva\n", "ssa_res_gen['va_degree'] = ssa.PV.a.v * 180 / pi\n", "ssa_res_gen['vm_pu'] = ssa.PV.v.v\n", "ssa_res_slack = pd.DataFrame([[ssa.Slack.name.v[0], ssa.Slack.p.v[0] * ssa.config.mva,\n", " ssa.Slack.q.v[0] * ssa.config.mva, ssa.Slack.a.v[0] * 180 / pi,\n", " ssa.Slack.v.v[0]]],\n", " columns=ssa_res_gen.columns,\n", " )\n", "ssa_res_gen = pd.concat([ssa_res_gen, ssa_res_slack]).reset_index(drop=True)\n", "\n", "# ssp\n", "pp.runpp(ssp)\n", "ssp_res_gen = pd.concat([ssp.gen['name'], ssp.res_gen], axis=1)\n", "\n", "res_gen_concat = pd.concat([ssa_res_gen, ssp_res_gen], axis=1)\n", "\n", "# ssa\n", "ssa_pf_bus = ssa.Bus.as_df()[[\"name\"]].copy()\n", "ssa_pf_bus['v_andes'] = ssa.Bus.v.v\n", "ssa_pf_bus['a_andes'] = ssa.Bus.a.v * 180 / pi\n", "\n", "# ssp\n", "ssp_pf_bus = ssa.Bus.as_df()[[\"name\"]].copy()\n", "ssp_pf_bus['v_pp'] = ssp.res_bus['vm_pu']\n", "ssp_pf_bus['a_pp'] = ssp.res_bus['va_degree']\n", "\n", "pf_bus_concat = pd.concat([ssa_pf_bus, ssp_pf_bus], axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Generation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the table below, the left half are ANDES results, and the right half are from pandapower" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "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", "
namep_mwq_mvarva_degreevm_punamep_mwq_mvarva_degreevm_pu
0240.000030.4361-1.76411.03240.000030.4361-1.76411.03
1340.000012.5971-3.53711.01340.000012.5971-3.53711.01
2430.000020.9866-6.45271.03430.000020.9866-6.45271.03
3535.00007.3964-1.54001.03535.00007.3964-1.54001.03
4181.4272-21.61710.00001.03181.4272-21.61710.00001.03
\n", "
" ], "text/plain": [ " name p_mw q_mvar va_degree vm_pu name p_mw q_mvar va_degree \\\n", "0 2 40.0000 30.4361 -1.7641 1.03 2 40.0000 30.4361 -1.7641 \n", "1 3 40.0000 12.5971 -3.5371 1.01 3 40.0000 12.5971 -3.5371 \n", "2 4 30.0000 20.9866 -6.4527 1.03 4 30.0000 20.9866 -6.4527 \n", "3 5 35.0000 7.3964 -1.5400 1.03 5 35.0000 7.3964 -1.5400 \n", "4 1 81.4272 -21.6171 0.0000 1.03 1 81.4272 -21.6171 0.0000 \n", "\n", " vm_pu \n", "0 1.03 \n", "1 1.01 \n", "2 1.03 \n", "3 1.03 \n", "4 1.03 " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res_gen_concat.round(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bus voltage and angle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Likewise, the left half are ANDES results, and the right half are from pandapower" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "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", "
namev_andesa_andesnamev_ppa_pp
uid
0BUS11.03000.0000BUS11.03000.0000
1BUS21.0300-1.7641BUS21.0300-1.7641
2BUS31.0100-3.5371BUS31.0100-3.5371
3BUS41.0114-4.4098BUS41.0114-4.4098
4BUS51.0173-3.8430BUS51.0173-3.8430
5BUS61.0300-6.4527BUS61.0300-6.4527
6BUS71.0225-4.8852BUS71.0225-4.8852
7BUS81.0300-1.5400BUS81.0300-1.5400
8BUS91.0218-7.2459BUS91.0218-7.2459
9BUS101.0155-7.4155BUS101.0155-7.4155
10BUS111.0191-7.0797BUS111.0191-7.0797
11BUS121.0174-7.4730BUS121.0174-7.4730
12BUS131.0145-7.7208BUS131.0145-7.7208
13BUS141.0163-9.4811BUS141.0163-9.4811
\n", "
" ], "text/plain": [ " name v_andes a_andes name v_pp a_pp\n", "uid \n", "0 BUS1 1.0300 0.0000 BUS1 1.0300 0.0000\n", "1 BUS2 1.0300 -1.7641 BUS2 1.0300 -1.7641\n", "2 BUS3 1.0100 -3.5371 BUS3 1.0100 -3.5371\n", "3 BUS4 1.0114 -4.4098 BUS4 1.0114 -4.4098\n", "4 BUS5 1.0173 -3.8430 BUS5 1.0173 -3.8430\n", "5 BUS6 1.0300 -6.4527 BUS6 1.0300 -6.4527\n", "6 BUS7 1.0225 -4.8852 BUS7 1.0225 -4.8852\n", "7 BUS8 1.0300 -1.5400 BUS8 1.0300 -1.5400\n", "8 BUS9 1.0218 -7.2459 BUS9 1.0218 -7.2459\n", "9 BUS10 1.0155 -7.4155 BUS10 1.0155 -7.4155\n", "10 BUS11 1.0191 -7.0797 BUS11 1.0191 -7.0797\n", "11 BUS12 1.0174 -7.4730 BUS12 1.0174 -7.4730\n", "12 BUS13 1.0145 -7.7208 BUS13 1.0145 -7.7208\n", "13 BUS14 1.0163 -9.4811 BUS14 1.0163 -9.4811" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pf_bus_concat.round(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generator dispatch based on OPF from pandapower" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Prepare the link table." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# Asign the StaticGen with OPF, in this case, all the SynGen are GENROU\n", "link_table = make_link_table(ssa)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "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", "
stg_namestg_idxbus_idxsyn_idxexc_idxgov_idxbus_name
0222GENROU_2EXST1_1TGOV1_2BUS2
1333GENROU_3ESST3A_3TGOV1_3BUS3
2446GENROU_4ESST3A_4TGOV1_4BUS6
3558GENROU_51TGOV1_5BUS8
4111GENROU_1ESST3A_2TGOV1_1BUS1
\n", "
" ], "text/plain": [ " stg_name stg_idx bus_idx syn_idx exc_idx gov_idx bus_name\n", "0 2 2 2 GENROU_2 EXST1_1 TGOV1_2 BUS2\n", "1 3 3 3 GENROU_3 ESST3A_3 TGOV1_3 BUS3\n", "2 4 4 6 GENROU_4 ESST3A_4 TGOV1_4 BUS6\n", "3 5 5 8 GENROU_5 1 TGOV1_5 BUS8\n", "4 1 1 1 GENROU_1 ESST3A_2 TGOV1_1 BUS1" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "link_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the TDS in ADNES to 2s." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\n", "-> Time Domain Simulation Summary:\n", "Sparse Solver: KLU\n", "Simulation time: 0.0-2 s.\n", "Fixed step size: h=33.33 ms. Shrink if not converged.\n", "Initialization for dynamics completed in 0.0435 seconds.\n", "Initialization was successful.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "23a6233b6079469db993d06825b9e085", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/100 [00:00" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "(
, )" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssa.TDS.config.tf = 2\n", "ssa.TDS.run()\n", "\n", "ssa.TDS.plt.plot(ssa.GENROU.Pe)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get the OPF results from pandapower. The `ssp_res` has been converted to p.u.." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "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", "
namepqvm_pubus_namebus_idxcontrollablesyn_idxgov_idxexc_idxstg_idx
020.5000000.1292141.096908BUS22TrueGENROU_2TGOV1_2EXST1_12
130.4127280.1499991.082554BUS33TrueGENROU_3TGOV1_3ESST3A_33
240.3439620.0999991.086078BUS66TrueGENROU_4TGOV1_4ESST3A_44
350.4961960.0852311.099999BUS88TrueGENROU_5TGOV1_515
410.500000-0.0790921.100000BUS11TrueGENROU_1TGOV1_1ESST3A_21
\n", "
" ], "text/plain": [ " name p q vm_pu bus_name bus_idx controllable syn_idx \\\n", "0 2 0.500000 0.129214 1.096908 BUS2 2 True GENROU_2 \n", "1 3 0.412728 0.149999 1.082554 BUS3 3 True GENROU_3 \n", "2 4 0.343962 0.099999 1.086078 BUS6 6 True GENROU_4 \n", "3 5 0.496196 0.085231 1.099999 BUS8 8 True GENROU_5 \n", "4 1 0.500000 -0.079092 1.100000 BUS1 1 True GENROU_1 \n", "\n", " gov_idx exc_idx stg_idx \n", "0 TGOV1_2 EXST1_1 2 \n", "1 TGOV1_3 ESST3A_3 3 \n", "2 TGOV1_4 ESST3A_4 4 \n", "3 TGOV1_5 1 5 \n", "4 TGOV1_1 ESST3A_2 1 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssp_res = runopp_map(ssp, link_table)\n", "ssp_res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now dispatch the resutls into `ssa`, where the active power setpoitns are updated to `TurbinGov.pref0`." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.49999999, 0.41272757, 0.34396221, 0.49619557, 0.50000009])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssa_gov_idx = list(ssp_res['gov_idx'][~ssp_res['gov_idx'].isna()])\n", "ssa.TurbineGov.set(src='pref0', idx=ssa_gov_idx, attr='v', value=ssp_res['p'][~ssp_res['gov_idx'].isna()])\n", "ssa.TurbineGov.get(src='pref0', idx=ssa_gov_idx, attr='v')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now run the TDS to 50s." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b35d11c0cb8f466f8c888a83869ef149", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/100 [00:00" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "(
, )" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ssa.TDS.plt.plot(ssa.GENROU.Pe)" ] } ], "metadata": { "interpreter": { "hash": "9e82087c6c724a796d11bbbca032c2fea9f2a8500ea883496f2915648d5c9903" }, "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.7.10" } }, "nbformat": 4, "nbformat_minor": 2 }