def test_cost_piecewise_linear_sgen_very_unsteady_slopes(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.5 vm_min = 0.5 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_sgen(net, 1, p_mw=0.10, controllable=True, min_p_mw=0, max_p_mw=1.50, max_q_mvar=0.05, min_q_mvar=-0.05) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_pwl_cost(net, 0, "sgen", [[0, 0.75, -1], [0.75, 1500, 2]]) # run OPF pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_sgen.p_mw.values[0], .75, rtol=1e-2) assert np.isclose(net.res_sgen.p_mw.values[0], -net.res_cost, rtol=1e-2)
def test_cost_piecewise_linear_eg(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10) pp.create_ext_grid(net, 0, min_p_mw=0, max_p_mw=0.050) pp.create_gen(net, 1, p_mw=0.01, min_p_mw=0, max_p_mw=0.050, controllable=True) # pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_pwl_cost(net, 0, "ext_grid", [[0, 50, -10]]) # run OPF pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, -10*net.res_ext_grid.p_mw.values)
def test_cost_piecewise_linear_load(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_load(net, 1, p_mw=0.1, controllable=True, max_p_mw=0.15, min_p_mw=0.050, max_q_mvar=0, min_q_mvar=0) pp.create_ext_grid(net, 0) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_pwl_cost(net, 0, "load", [[0, 75, 1.5], [75, 150, 1.5]]) pp.runopp(net) assert net["OPF_converged"] assert abs(net.res_cost - net.res_load.p_mw.values * 1.5) < 1e-3
def test_cost_piecewise_linear_load_uneven_slopes(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_load(net, 1, p_mw=0.050) pp.create_ext_grid(net, 0) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_pwl_cost(net, 0, "ext_grid", [(0, 0.075, 1), (0.075, 150, 2)]) pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_ext_grid.p_mw.values[0]) net.load.p_mw = 0.1 pp.runopp(net) assert np.isclose(net.res_cost, (0.075 + 2*(net.res_ext_grid.p_mw.values[0] - 0.075)), rtol=1e-2)
def run_opf(grid: pp.pandapowerNet, min_loss_reduction_mwt: float, acceptable_loading: float, opf_type: str, asset: str = "", logger=logging.getLogger()): loss_before = calc_losses(grid) line_loading_before = grid.res_line.loading_percent.max() trafo_loading_before = (grid.res_trafo.i_hv_ka / grid.trafo.max_i_ka * 100.).max() try: if opf_type == "pypower": pp.runopp(grid) # pypower OPF elif opf_type == "powermodels": grid.line["in_service"] = True grid.trafo["in_service"] = True pp.runpm_ots(grid, pm_nl_solver="ipopt", pm_model="ACPPowerModel") # PowerModels.jl OPF grid.line.loc[:, "in_service"] = grid.res_line.loc[:, "in_service"].values.astype( bool) grid.trafo.loc[:, "in_service"] = grid.res_trafo.loc[:, "in_service"].values.astype( bool) if len(grid.ext_grid) > 0: generation = np.array(grid.res_gen.p_mw.tolist() + grid.res_ext_grid.p_mw.tolist()) else: generation = grid.res_gen.p_mw.values losses_avoided = loss_before - calc_losses(grid) line_loading_after = grid.res_line.loading_percent.max() trafo_loading_after = (grid.res_trafo.i_hv_ka / grid.trafo.max_i_ka * 100.).max() use_opf_results = False # three conditions for using the OPF results: # 1. transformer was overloaded before and is now less overloaded # 2. line was overloaded before and is now less overloaded # 3. losses are minimized at least by "min_loss_reduction_mwt" while all loadings are acceptably low if trafo_loading_before > acceptable_loading and trafo_loading_after < trafo_loading_before: use_opf_results = True if line_loading_before > acceptable_loading and line_loading_after < line_loading_before: use_opf_results = True if losses_avoided > min_loss_reduction_mwt and line_loading_after < acceptable_loading and trafo_loading_after < acceptable_loading: use_opf_results = True if use_opf_results: logger.info( f"Losses avoided: {losses_avoided:.3f} MW (max. loading: {line_loading_after:.1f}% [{line_loading_after - line_loading_before:.1f}%] " f"/ Trafo: {trafo_loading_after:.1f}% [{trafo_loading_after - trafo_loading_before:.1f}%])" ) return generation, grid.line.in_service, grid.trafo.in_service, True return np.zeros(len( grid.gen)), grid.line.in_service, grid.trafo.in_service, False except pp.optimal_powerflow.OPFNotConverged: asset_str = f"if asset #{asset} is out of service" if len( asset) else "" logger.info(f"OPF failed {asset_str}") return np.zeros(len( grid.gen)), grid.line.in_service, grid.trafo.in_service, False
def test_some_sgens_not_controllable(): """ Testing a simple network with transformer for loading constraints with OPF using a generator """ # create net net = nw.create_cigre_network_mv(with_der="pv_wind") net.bus["max_vm_pu"] = 1.1 net.bus["min_vm_pu"] = 0.9 net.line["max_loading_percent"] = 200 net.trafo["max_loading_percent"] = 100 net.sgen["max_p_mw"] = net.sgen.sn_mva net.sgen["min_p_mw"] = 0 net.sgen["max_q_mvar"] = 0.01 net.sgen["min_q_mvar"] = -0.01 net.sgen["controllable"] = True net.load["controllable"] = False net.sgen.controllable[net.sgen.bus == 4] = False net.sgen.controllable[net.sgen.bus == 6] = False net.sgen.controllable[net.sgen.bus == 8] = False net.sgen.controllable[net.sgen.bus == 9] = False for sgen_idx, row in net["sgen"].iterrows(): cost_sgen = pp.create_poly_cost(net, sgen_idx, 'sgen', cp1_eur_per_mw=1.) net.poly_cost.cp1_eur_per_mw.at[cost_sgen] = 100 # run OPF pp.runopp(net, calculate_voltage_angles=False) assert net["OPF_converged"] # check if p_mw of non conrollable sgens are unchanged assert np.allclose(net.res_sgen.p_mw[net.sgen.controllable == False], net.sgen.p_mw[net.sgen.controllable == False]) assert not np.allclose(net.res_sgen.p_mw[net.sgen.controllable == True], net.sgen.p_mw[net.sgen.controllable == True])
def test_cost_piecewise_linear_load_uneven_slopes(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_load(net, 1, p_kw=100, controllable=True, max_p_kw=150, min_p_kw=50, max_q_kvar=0, min_q_kvar=0) pp.create_ext_grid(net, 0) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_piecewise_linear_cost(net, 0, "load", np.array([[0, 0], [75, 51], [150, 101]])) # run OPF with pytest.raises(OPFNotConverged): pp.runopp(net, verbose=False) assert net["OPF_converged"] assert abs(net.res_cost - net.res_load.p_kw.values / 1.5) < 1e-3
def test_get_costs(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_gen(net, 1, p_kw=-100, controllable=True, max_p_kw=-5, min_p_kw=-150, max_q_kvar=50, min_q_kvar=-50) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_kw=20, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_piecewise_linear_cost(net, 0, "gen", np.array([[-150, 300], [0, 0]])) # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"] assert net.res_cost == 2 * net.res_gen.p_kw.values
def test_trafo3w_loading(): net = pp.create_empty_network() b1, b2, l1 = add_grid_connection(net, vn_kv=110.) b3 = pp.create_bus(net, vn_kv=20.) b4 = pp.create_bus(net, vn_kv=10.) tidx = pp.create_transformer3w(net, b2, b3, b4, std_type='63/25/38 MVA 110/20/10 kV', max_loading_percent=120) pp.create_load(net, b3, 5e3, controllable=False) id = pp.create_load(net, b4, 5e3, controllable=True, max_p_kw=5e4, min_p_kw=0) pp.create_polynomial_cost(net, id, "load", array([-1, 0])) #pp.create_xward(net, b4, 1000, 1000, 1000, 1000, 0.1, 0.1, 1.0) net.trafo3w.shift_lv_degree.at[tidx] = 120 net.trafo3w.shift_mv_degree.at[tidx] = 80 # pp.runopp(net, calculate_voltage_angles = True) >> Doesn't converge pp.runopp(net, calculate_voltage_angles=False) assert abs(net.res_trafo3w.loading_percent.values - 120) < 1e-3
def test_some_sgens_not_controllable(): """ Testing a simple network with transformer for loading constraints with OPF using a generator """ # create net net = nw.create_cigre_network_mv(with_der="pv_wind") net.bus["max_vm_pu"] = 1.1 net.bus["min_vm_pu"] = 0.9 net.line["max_loading_percent"] = 200 net.trafo["max_loading_percent"] = 100 net.sgen["min_p_kw"] = -net.sgen.sn_kva net.sgen["max_p_kw"] = 0 net.sgen["max_q_kvar"] = 10 net.sgen["min_q_kvar"] = -10 net.sgen["controllable"] = 1 net.load["controllable"] = 0 net.sgen.controllable[net.sgen.bus == 4] = False net.sgen.controllable[net.sgen.bus == 6] = False net.sgen.controllable[net.sgen.bus == 8] = False net.sgen.controllable[net.sgen.bus == 9] = False for sgen_idx, row in net["sgen"].iterrows(): cost_sgen = pp.create_polynomial_cost(net, sgen_idx, 'sgen', np.array([1, 0])) net.polynomial_cost.c.at[cost_sgen] = np.array([[0.1, 0]]) # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"] # check if p_kw of non conrollable sgens are unchanged assert np.allclose(net.res_sgen.p_kw[net.sgen.controllable == False], net.sgen.p_kw[net.sgen.controllable == False]) assert not np.allclose(net.res_sgen.p_kw[net.sgen.controllable == True], net.sgen.p_kw[net.sgen.controllable == True])
def test_cost_pol_q(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_sgen(net, 1, p_mw=0.1, controllable=True, min_p_mw=0.005, max_p_mw=0.15, max_q_mvar=0.05, min_q_mvar=-0.05) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_poly_cost(net, 0, "sgen", cp1_eur_per_mw=0, cq1_eur_per_mvar=-1) # run OPF pp.runopp(net) assert net["OPF_converged"] assert abs(net.res_cost + (net.res_sgen.q_mvar.values)) < 1e-2 net.poly_cost.cq1_eur_per_mvar.at[0] = 0 net.poly_cost.cq2_eur_per_mvar2.at[0] = 1 # net.poly_cost.c.at[0] = np.array([[1, 0, 0]]) # run OPF pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_sgen.q_mvar.values**2)
def test_get_costs(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_gen(net, 1, p_mw=0.1, controllable=True, min_p_mw=0.05, max_p_mw=0.15, max_q_mvar=0.05, min_q_mvar=-0.05) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_pwl_cost(net, 0, "gen", [[0, 150, 2]]) # run OPF pp.runopp(net) assert net["OPF_converged"] assert net.res_gen.p_mw.values[0] - net.gen.min_p_mw.values[0] < 1e-2 assert np.isclose(net.res_cost, 2 * net.res_gen.p_mw.values[0])
def test_simplest_voltage(): """ Testing a very simple network without transformer for voltage constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 net = simplest_grid() # run OPF for init in ["pf", "flat"]: pp.runopp(net, init=init) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert min(net.res_bus.vm_pu) > vm_min pp.runopp(net, check_connectivity=True) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert min(net.res_bus.vm_pu) > vm_min
def test_cost_pol_q(): """ Testing a very simple network for the resulting cost value constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_sgen(net, 1, p_kw=-100, controllable=True, max_p_kw=-5, min_p_kw=-150, max_q_kvar=50, min_q_kvar=-50) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_kw=20, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) pp.create_polynomial_cost(net, 0, "sgen", np.array([0, -1, 0]), type="q") # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"] assert abs(net.res_cost + (net.res_sgen.q_kvar.values)) < 1e-2 net.polynomial_cost.c.at[0] = np.array([[1, 0, 0]]) # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"] assert abs(net.res_cost - net.res_sgen.q_kvar.values**2) < 1e-5
def test_dcline_dispatch2(dcline_net): net = dcline_net pp.create_polynomial_cost(net, 0, "ext_grid", array([.08, 0])) pp.create_polynomial_cost(net, 1, "ext_grid", array([.1, 0])) net.bus["max_vm_pu"] = 2 net.bus["min_vm_pu"] = 0 # needs to be constrained more than default net.line[ "max_loading_percent"] = 1000 # does not converge if unconstrained pp.runopp(net) consistency_checks(net, rtol=1e-3) consistency_checks(net, rtol=1e-3) rel_loss_expect = (net.res_dcline.pl_kw - net.dcline.loss_kw) / \ (net.res_dcline.p_from_kw - net.res_dcline.pl_kw) * 100 assert allclose(rel_loss_expect.values, net.dcline.loss_percent.values) p_eg_expect = array([-8.21525358e+05, -5.43498903e-02]) q_eg_expect = array([7787.55852923, 21048.59213887]) assert allclose(net.res_ext_grid.p_kw.values, p_eg_expect) assert allclose(net.res_ext_grid.q_kvar.values, q_eg_expect) p_from_expect = array([813573.88366999]) q_from_expect = array([-26446.0473644]) assert allclose(net.res_dcline.p_from_kw.values, p_from_expect) assert allclose(net.res_dcline.q_from_kvar.values, q_from_expect) p_to_expect = array([-805023.64719801]) q_to_expect = array([-21736.31196315]) assert allclose(net.res_dcline.p_to_kw.values, p_to_expect) assert allclose(net.res_dcline.q_to_kvar.values, q_to_expect)
def test_convert_format(): """ Testing a very simple network without transformer for voltage constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_gen(net, 1, p_mw=0.1, controllable=True, min_p_mw=0.005, max_p_mw=0.15, max_q_mvar=0.05, min_q_mvar=-0.005) net.gen["cost_per_mw"] = 100 pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100 * 690) # run OPF convert_format(net) for init in ["pf", "flat"]: pp.runopp(net, init=init) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert min(net.res_bus.vm_pu) > vm_min
def test_simplest_dispatch(): """ Testing a very simple network without transformer for voltage constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_gen(net, 1, p_kw=-100, controllable=True, max_p_kw=-150, min_p_kw=-5, max_q_kvar=50, min_q_kvar=-50, cost_per_kw=100) pp.create_ext_grid(net, 0, cost_per_kw=101) pp.create_load(net, 1, p_kw=20) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, imax_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100*690) # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_est_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert net.OPF_converged
def test_dispatch1(dcline_net): net = dcline_net pp.create_piecewise_linear_cost( net, 0, "ext_grid", array([[-1e12, -0.1 * 1e12], [1e12, .1 * 1e12]])) pp.create_piecewise_linear_cost( net, 1, "ext_grid", array([[-1e12, -0.08 * 1e12], [1e12, .08 * 1e12]])) net.bus["max_vm_pu"] = 2 net.bus["min_vm_pu"] = 0 # needs to be constrained more than default net.line[ "max_loading_percent"] = 1000 # does not converge if unconstrained pp.runopp(net) consistency_checks(net, rtol=1e-3) rel_loss_expect = (net.res_dcline.pl_kw - net.dcline.loss_kw) / \ (net.res_dcline.p_from_kw - net.res_dcline.pl_kw) * 100 assert allclose(rel_loss_expect.values, net.dcline.loss_percent.values) p_eg_expect = array([-5.00078353e+02, -8.05091476e+05]) q_eg_expect = array([7787.55773243, -628.30727889]) assert allclose(net.res_ext_grid.p_kw.values, p_eg_expect) assert allclose(net.res_ext_grid.q_kvar.values, q_eg_expect) p_from_expect = array([500.0754071]) q_from_expect = array([7787.45600524]) assert allclose(net.res_dcline.p_from_kw.values, p_from_expect) assert allclose(net.res_dcline.q_from_kvar.values, q_from_expect) p_to_expect = array([-0.0746605]) q_to_expect = array([-627.12636707]) assert allclose(net.res_dcline.p_to_kw.values, p_to_expect) assert allclose(net.res_dcline.q_to_kvar.values, q_to_expect)
def evalsipsbattery(net, t, s, PGEN, DEM, XSOL, GENDATA, print_results=False): print('PGEN:', PGEN[:, 0, t]) print('DEM:', DEM[:, t]) net = confignet(net, t, s, PGEN, DEM, XSOL, GENDATA) numGen = 3 INF = 1e32 # geninservice = False for i in range(numGen): if (net.gen['in_service'][i]): # geninservice=True net.gen['slack'][i] = True break # #Define slack bus # if not geninservice: # net.storage['slack'][0]=True #Run Optimal Power Flow try: pp.runopp(net) if print_results: print('Results Storage') print(net.res_storage) print('Results Generators') print(net.res_gen) print('Line Loading') print(net.res_line['loading_percent'][:]) return net.res_cost, net.res_storage.values except: print('OPF not converges') print('Pgen:', PGEN[:, 0, t]) print('Dem:', DEM[:, t]) return INF, np.ndarray((3, 2))
def test_opf_create_ext_grid_controllable(): # load net net = case5_pm_matfile_I() # run pd2ppc with ext_grid controllable = False pp.create_ext_grid(net, bus=1, controllable=True) pp.runopp(net) assert np.isclose(net.res_bus.vm_pu[net.ext_grid.bus[0]], 1.0641399999827315)
def test_trafo3w_loading(): net = pp.create_empty_network() b1, b2, l1 = add_grid_connection(net, vn_kv=110.) b3 = pp.create_bus(net, vn_kv=20.) b4 = pp.create_bus(net, vn_kv=10.) tidx = pp.create_transformer3w(net, b2, b3, b4, std_type='63/25/38 MVA 110/20/10 kV', max_loading_percent=120) pp.create_load(net, b3, p_mw=5, controllable=False) load_id = pp.create_load(net, b4, p_mw=5, controllable=True, max_p_mw=50, min_p_mw=0, min_q_mvar=-1e6, max_q_mvar=1e6) pp.create_poly_cost(net, load_id, "load", cp1_eur_per_mw=-1000) # pp.create_xward(net, b4, 1000, 1000, 1000, 1000, 0.1, 0.1, 1.0) net.trafo3w.shift_lv_degree.at[tidx] = 120 net.trafo3w.shift_mv_degree.at[tidx] = 80 # pp.runopp(net, calculate_voltage_angles = True) >> Doesn't converge for init in ["pf", "flat"]: pp.runopp(net, calculate_voltage_angles=False, init=init) assert net["OPF_converged"] assert abs(net.res_trafo3w.loading_percent.values - 120) < 1e-3
def test_dcline_dispatch2(dcline_net): net = dcline_net pp.create_poly_cost(net, 0, "ext_grid", cp1_eur_per_mw=80) pp.create_poly_cost(net, 1, "ext_grid", cp1_eur_per_mw=100) # pp.create_poly_cost(net, 0, "ext_grid", array([.08, 0])) # pp.create_poly_cost(net, 1, "ext_grid", array([.1, 0])) net.bus["max_vm_pu"] = 2 net.bus["min_vm_pu"] = 0 # needs to be constrained more than default net.line[ "max_loading_percent"] = 1000 # does not converge if unconstrained # pp.runopp(net, delta=get_delta_try_except(net)) pp.runopp(net) consistency_checks(net, rtol=1e-3) rel_loss_expect = (net.res_dcline.pl_mw - net.dcline.loss_mw) / \ (net.res_dcline.p_from_mw - net.res_dcline.pl_mw) * 100 assert allclose(rel_loss_expect.values, net.dcline.loss_percent.values) p_eg_expect = array([8.21525358e+02, 5.43498903e-05]) q_eg_expect = array([-7787.55852923e-3, -21048.59213887e-3]) assert allclose(net.res_ext_grid.p_mw.values, p_eg_expect) assert allclose(net.res_ext_grid.q_mvar.values, q_eg_expect) p_from_expect = array([813573.88366999e-3]) q_from_expect = array([-26446.0473644e-3]) assert allclose(net.res_dcline.p_from_mw.values, p_from_expect) assert allclose(net.res_dcline.q_from_mvar.values, q_from_expect) p_to_expect = array([-805023.64719801e-3]) q_to_expect = array([-21736.31196315e-3]) assert allclose(net.res_dcline.p_to_mw.values, p_to_expect) assert allclose(net.res_dcline.q_to_mvar.values, q_to_expect)
def test_gen_violated_p_vm_limits(four_bus_net): # tests if gen max_vm_pu and min_vm_pu are correctly enforced net = four_bus_net min_vm_pu, max_vm_pu = .98, 1.007 # gen limits are out of bus limits net.bus.loc[:, "min_vm_pu"] = min_vm_pu net.bus.loc[:, "max_vm_pu"] = max_vm_pu min_p_mw, max_p_mw = 0., 1. bus = 1 # controllable == False -> limits are ignored and p_mw / vm_pu values are enforced g = pp.create_gen(net, bus, p_mw=0.02, vm_pu=1.01, controllable=True, min_vm_pu=.9, max_vm_pu=1.1, min_p_mw=min_p_mw, max_p_mw=max_p_mw) pp.runopp(net, calculate_voltage_angles=False) assert not np.allclose(net.res_bus.at[bus, "vm_pu"], 1.01) assert not np.allclose(net.res_bus.at[bus, "p_mw"], 0.02) assert min_vm_pu < net.res_bus.at[bus, "vm_pu"] < max_vm_pu assert min_p_mw <= -net.res_bus.at[bus, "p_mw"] < max_p_mw net.gen.at[g, "vm_pu"] = 0.9 # lower bus vm_pu limit violation pp.runopp(net, calculate_voltage_angles=False) assert min_vm_pu < net.res_bus.at[bus, "vm_pu"] < max_vm_pu
def test_dispatch1(dcline_net): net = dcline_net pp.create_pwl_cost(net, 0, "ext_grid", [[-1e12, 1e9, 100]]) pp.create_pwl_cost(net, 1, "ext_grid", [[-1e12, 1e9, 80]]) net.bus["max_vm_pu"] = 2 net.bus["min_vm_pu"] = 0 # needs to be constrained more than default net.line[ "max_loading_percent"] = 1000 # does not converge if unconstrained pp.runopp(net, delta=1e-8) consistency_checks(net) rel_loss_expect = (net.res_dcline.pl_mw - net.dcline.loss_mw) / \ (net.res_dcline.p_from_mw - net.res_dcline.pl_mw) * 100 assert allclose(rel_loss_expect.values, net.dcline.loss_percent.values, rtol=1e-2) assert allclose(net.res_ext_grid.p_mw.values, [0.5, 805], atol=0.1) assert allclose(net.res_ext_grid.q_mvar.values, [-7.78755773243, 0.62830727889], atol=1e-3) assert allclose(net.res_dcline.p_from_mw.values, [0.500754071], atol=1e-3) assert allclose(net.res_dcline.q_from_mvar.values, [7.78745600524]) assert allclose(net.res_dcline.p_to_mw.values, array([-5.48553789e-05])) assert allclose(net.res_dcline.q_to_mvar.values, array([-.62712636707]))
def get_delta_try_except(net): for delta in [1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, 1e-11, 1e-12]: try: pp.runopp(net, delta=delta) return delta except pp.OPFNotConverged: continue return 1e-10
def init(self): if self.pf == 'pf': pp.runpp(self.network) elif self.pf == 'dcpf': pp.rundcpp(self.network) elif self.pf == 'opf': pp.runopp(self.network) else: pp.rundcopp(self.network)
def test_simplest_voltage(): """ Testing a very simple network without transformer for voltage constraints with OPF """ # boundaries: vm_max = 1.05 vm_min = 0.95 # create net net = pp.create_empty_network() pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=10.) pp.create_bus(net, max_vm_pu=vm_max, min_vm_pu=vm_min, vn_kv=.4) pp.create_gen(net, 1, p_kw=-100, controllable=True, max_p_kw=-5, min_p_kw=-150, max_q_kvar=50, min_q_kvar=-50) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_kw=20, controllable=False) pp.create_line_from_parameters(net, 0, 1, 50, name="line2", r_ohm_per_km=0.876, c_nf_per_km=260.0, max_i_ka=0.123, x_ohm_per_km=0.1159876, max_loading_percent=100) pp.create_polynomial_cost(net, 0, "gen", np.array([100, 0])) # run OPF for init in ["pf", "flat"]: pp.runopp(net, verbose=False, init=init) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert min(net.res_bus.vm_pu) > vm_min pp.runopp(net, verbose=False, check_connectivity=True) assert net["OPF_converged"] # check and assert result logger.debug("test_simplest_voltage") logger.debug("res_gen:\n%s" % net.res_gen) logger.debug("res_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert max(net.res_bus.vm_pu) < vm_max assert min(net.res_bus.vm_pu) > vm_min
def scenario1ref(): """ pandapower-OPF as reference for scenario 1. """ net = create_net1() pp.create_poly_cost(net, 0, 'ext_grid', cp1_eur_per_mw=10) pp.create_poly_cost(net, 0, 'gen', cp1_eur_per_mw=10) pp.create_poly_cost(net, 1, 'gen', cp1_eur_per_mw=10) pp.runopp(net) print(f'Costs for pandapower-OPF: {net.res_cost} \n') return net, net.res_cost
def evalsipsbatteryloadshedding(net, t, s, PGEN, DEM, XSOL, GENDATA, DEMDATA, print_results=False, verbose=False): # print('PGEN:',PGEN[:,0,t]) # print('DEM:',DEM[:,t ]) net = confignet(net, t, s, PGEN, DEM, XSOL, GENDATA) numGen = 3 numBar = 3 INF = 1e32 for i in range(numBar): net.load['p_mw'][i] = DEM[i, t] net.load['min_p_mw'][i] = max(DEM[i, t] - DEMDATA[i][4], 0) net.load['max_p_mw'][i] = DEM[i, t] geninservice = False for i in range(numGen): if (net.gen['in_service'][i]): geninservice = True net.gen['slack'][i] = True break #Define slack bus if not geninservice: net.gen['slack'][0] = True net.gen['p_mw'][0] = PGEN[0, 0, t] net.gen['max_p_mw'] = PGEN[0, 0, t] net.gen['min_p_mw'] = PGEN[0, 0, t] #Run Optimal Power Flow try: pp.runopp(net) if print_results: print('Results Loads:') print(net.res_load) print('Results Storage') print(net.res_storage) print('Results Generators') print(net.res_gen) print('Line Loading') print(net.res_line['loading_percent'][:]) return net.res_cost, net.res_load.values, net.res_storage.values, net.res_line.values, net.res_gen.values, net.res_bus.values except: print('OPF not converges') print('Pgen:', PGEN[:, 0, t]) print('Dem:', DEM[:, t]) return INF, np.ndarray((3, 2))
def test_opf_no_controllables_vs_pf(): """ Comparing the calculation results of PF and OPF in a simple network with non-controllable elements """ # boundaries vm_max = 1.3 vm_min = 0.9 max_line_loading_percent = 100 # create network net = pp.create_empty_network() b1 = pp.create_bus(net, vn_kv=0.4, max_vm_pu=vm_max, min_vm_pu=vm_min) b2 = pp.create_bus(net, vn_kv=0.4, max_vm_pu=vm_max, min_vm_pu=vm_min) pp.create_line(net, b1, b2, length_km=5, std_type="NAYY 4x50 SE", max_loading_percent=max_line_loading_percent) # test elements static pp.create_ext_grid(net, b2) pp.create_load(net, b1, p_mw=.0075, controllable=False) pp.create_sgen(net, b1, p_mw=0.025, controllable=False, min_p_mw=0.01, max_p_mw=0.025, max_q_mvar=0.025, min_q_mvar=-0.025) # testing cost assignment (for non-controllable elements - see Gitlab Issue #27) pp.create_poly_cost(net, 0, "ext_grid", cp1_eur_per_mw=3) pp.create_poly_cost(net, 0, "load", cp1_eur_per_mw=-3) pp.create_poly_cost(net, 0, "sgen", cp1_eur_per_mw=2) # do calculations pp.runopp(net) assert net["OPF_converged"] res_opf_line_loading = net.res_line.loading_percent res_opf_bus_voltages = net.res_bus.vm_pu pp.runpp(net) assert net["converged"] res_pf_line_loading = net.res_line.loading_percent res_pf_bus_voltages = net.res_bus.vm_pu # assert calculation behaviour assert np.isclose(res_opf_line_loading, res_pf_line_loading).all() assert np.isclose(res_opf_bus_voltages, res_pf_bus_voltages).all()