def test_cost_piecewise_linear_sgen(): """ 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.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, "sgen", [[0, 150, 2]]) # run OPF pp.runopp(net) assert net["OPF_converged"] assert net.res_sgen.p_mw.values[0] - net.sgen.min_p_mw.values[0] < 1e-2 assert np.isclose(net.res_cost, 2 * net.res_sgen.p_mw.values[0])
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_mixed_p_q_pwl(): 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=.05, min_q_mvar=-.05) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False, max_q_mvar=.05, max_p_mw=0.1, min_p_mw=0.005, min_q_mvar=-.05) 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) # testing some combinations pp.create_pwl_cost(net, 0, "gen", [[-150, 150, 1]]) pp.create_pwl_cost(net, 0, "gen", [[-150, 150, 1]], power_type="q") pp.runopp(net) assert net["OPF_converged"] assert np.allclose(net.res_cost, net.res_gen.p_mw.values + net.res_gen.q_mvar.values)
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 test_contingency_sgen(base_net): net = base_net pp.create_sgen(net, 1, p_mw=0.1, q_mvar=0, controllable=True, min_p_mw=0.005, max_p_mw=0.150, max_q_mvar=0.05, min_q_mvar=-0.05) # pwl costs # maximize the sgen feed in by using a positive cost slope # using a slope of 1 # | / # | / # | / # |/ #------------------------------------------- # p_min_mw /| # / | # / | pwl = pp.create_pwl_cost(net, 0, "sgen", [[0, net.sgen.max_p_mw.at[0], 1]]) pp.runopp(net) assert isclose(net.res_cost, net.res_sgen.p_mw.at[0], atol=1e-3) # minimize the sgen feed in by using a positive cost slope # using a slope of 1 # \ | # \ | # \ | # \| #------------------------------------------- # p_min_mw |\ # | \ # | \ net.pwl_cost.points.loc[pwl] = [(0, net.sgen.max_p_mw.at[0], -1)] pp.runopp(net) assert isclose(net.res_cost, -net.res_sgen.p_mw.at[0], atol=1e-4) net.pwl_cost.drop(0, inplace=True) # first using a positive slope as in the case above pp.create_poly_cost(net, 0, "sgen", cp1_eur_per_mw=1.) pp.runopp(net) assert isclose(net.res_cost, net.res_sgen.p_mw.at[0], atol=1e-3) # negative slope as in the case above net.poly_cost.cp1_eur_per_mw.at[0] *= -1 pp.runopp(net) assert isclose(net.res_cost, -net.res_sgen.p_mw.at[0], atol=1e-4)
def test_compare_pwl_and_poly(net_3w_trafo_opf): net = net_3w_trafo_opf net.ext_grid.loc[:, "min_p_mw"] = -999. net.ext_grid.loc[:, "max_p_mw"] = 999. net.ext_grid.loc[:, "max_q_mvar"] = 999. net.ext_grid.loc[:, "min_q_mvar"] = -999. pp.create_pwl_cost(net, 0, 'ext_grid', [[0, 1, 1]]) pp.create_pwl_cost(net, 0, 'gen', [[0, 30, 3], [30, 80, 3]]) pp.create_pwl_cost(net, 1, 'gen', [[0, 80, 2]]) net.bus.loc[:, "max_vm_pu"] = 1.1 net.bus.loc[:, "min_vm_pu"] = .9 pp.runpm_ac_opf(net) consistency_checks(net) p_gen = net.res_gen.p_mw.values q_gen = net.res_gen.q_mvar.values vm_bus = net.res_bus.vm_pu.values va_bus = net.res_bus.va_degree.values net.pwl_cost.drop(net.pwl_cost.index, inplace=True) pp.create_poly_cost(net, 0, 'ext_grid', cp1_eur_per_mw=1) pp.create_poly_cost(net, 0, 'gen', cp1_eur_per_mw=3) pp.create_poly_cost(net, 1, 'gen', cp1_eur_per_mw=2) # pp.runopp(net) pp.runpm_ac_opf(net, correct_pm_network_data=False) consistency_checks(net) np.allclose(p_gen, net.res_gen.p_mw.values) np.allclose(q_gen, net.res_gen.q_mvar.values) np.allclose(vm_bus, net.res_bus.vm_pu.values) np.allclose(va_bus, net.res_bus.va_degree.values) # pp.rundcopp(net) pp.runpm_dc_opf(net, correct_pm_network_data=False) consistency_checks(net, test_q=False) np.allclose(p_gen, net.res_gen.p_mw.values) np.allclose(va_bus, net.res_bus.va_degree.values)
def test_cost_mixed(): """ Testing a very simple network for the resulting cost value constraints with OPF """ 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=.05, min_q_mvar=-.05) pp.create_ext_grid(net, 0) pp.create_load(net, 1, p_mw=0.02, controllable=False, max_q_mvar=.05, max_p_mw=0.1, min_p_mw=0.0050, min_q_mvar=-.05) 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) # testing some combinations pp.create_poly_cost(net, 0, "gen", cp1_eur_per_mw=1) pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_gen.p_mw.values[0]) net.poly_cost.cp1_eur_per_mw.at[0] = 0 net.poly_cost.cp2_eur_per_mw2.at[0] = 1 pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2) net.poly_cost.cp0_eur.at[0] = 1 pp.runopp(net) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2 + 1) net.load.controllable.at[0] = True pp.runopp(net) assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2 + 1) net.load.controllable.at[0] = False net.pwl_cost.drop(net.pwl_cost.index, inplace=True) pp.create_pwl_cost(net, 0, "ext_grid", [[-1000, 0, -2000], [0, 1000, 2000]], power_type="p") net.poly_cost.cp1_eur_per_mw.at[0] = 1000 net.poly_cost.cp2_eur_per_mw2.at[0] = 0 pp.runopp(net) assert np.isclose(net.res_ext_grid.p_mw.values[0], 0, atol=1e-4) assert np.isclose(net.res_cost, net.res_gen.p_mw.values[0] * 1000, atol=1e-3)
def test_pwl(): net = pp.create_empty_network() # create buses bus1 = pp.create_bus(net, vn_kv=110., min_vm_pu=0.9, max_vm_pu=1.1) bus2 = pp.create_bus(net, vn_kv=110., min_vm_pu=0.9, max_vm_pu=1.1) bus3 = pp.create_bus(net, vn_kv=110., min_vm_pu=0.9, max_vm_pu=1.1) # create 110 kV lines pp.create_line(net, bus1, bus2, length_km=50., std_type='149-AL1/24-ST1A 110.0') pp.create_line(net, bus2, bus3, length_km=50., std_type='149-AL1/24-ST1A 110.0') # create loads pp.create_load(net, bus2, p_mw=80, controllable=False) # create generators g1 = pp.create_gen(net, bus1, p_mw=80, min_p_mw=0, max_p_mw=80, vm_pu=1.01, slack=True) g2 = pp.create_gen(net, bus3, p_mw=80, min_p_mw=0, max_p_mw=80, vm_pu=1.01) # net.gen["controllable"] = False pp.create_pwl_cost(net, g1, 'gen', [[0, 2, 2], [2, 80, 5]]) pp.create_pwl_cost(net, g2, 'gen', [[0, 2, 2], [2, 80, 5]]) pp.runpm_ac_opf(net) consistency_checks(net, rtol=1e-3) assert np.isclose(net.res_gen.p_mw.iloc[0], net.res_gen.p_mw.iloc[1]) assert np.isclose(net.res_gen.q_mvar.iloc[0], net.res_gen.q_mvar.iloc[1]) net.pwl_cost.drop(net.pwl_cost.index, inplace=True) g3 = pp.create_gen(net, bus1, p_mw=80, min_p_mw=0, max_p_mw=80, vm_pu=1.01) pp.create_pwl_cost(net, g1, 'gen', [[0, 2, 1.], [2, 80, 8.]]) pp.create_pwl_cost(net, g2, 'gen', [[0, 3, 2.], [3, 80, 14]]) pp.create_pwl_cost(net, g3, 'gen', [[0, 1, 3.], [1, 80, 10.]]) net.load.p_mw = 1 pp.runpm_ac_opf(net) consistency_checks(net, rtol=1e-3) assert np.isclose(net.res_gen.p_mw.at[g2], 0) assert np.isclose(net.res_gen.p_mw.at[g3], 0) assert np.isclose(net.res_cost, net.res_gen.p_mw.at[g1], atol=1e-4) net.load.p_mw = 3 pp.runpm_ac_opf(net) consistency_checks(net, rtol=1e-3) assert np.isclose(net.res_gen.p_mw.at[g3], 0) assert np.isclose(net.res_gen.p_mw.at[g1], 2) assert np.isclose(net.res_cost, net.res_gen.p_mw.at[g1] + net.res_gen.p_mw.at[g2] * 2, atol=1e-4) net.load.p_mw = 5 pp.runpm_ac_opf(net) consistency_checks(net, rtol=1e-3) assert np.isclose(net.res_gen.p_mw.at[g1], 2) assert np.isclose(net.res_gen.p_mw.at[g2], 3) assert np.isclose(net.res_cost, net.res_gen.p_mw.at[g1] + net.res_gen.p_mw.at[g2] * 2 + net.res_gen.p_mw.at[g3] * 3, atol=1e-4)
net.poly_cost.cp1_eur_per_mw.at[0] = 0 net.poly_cost.cp2_eur_per_mw2.at[0] = 1 pp.runopp(net, ) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2) net.poly_cost.cp0_eur.at[0] = 1 pp.runopp(net, ) assert net["OPF_converged"] assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2 + 1) net.load.controllable.at[0] = True pp.runopp(net, ) assert np.isclose(net.res_cost, net.res_gen.p_mw.values**2 + 1) net.load.controllable.at[0] = False net.pwl_cost.drop(net.pwl_cost.index, inplace=True) pp.create_pwl_cost(net, 0, "ext_grid", [[-1000, 0, -2000], [0, 1000, 2000]], power_type="p") net.poly_cost.cp1_eur_per_mw.at[0] = 1000 net.poly_cost.cp2_eur_per_mw2.at[0] = 0 pp.runopp(net, ) assert np.isclose(net.res_ext_grid.p_mw.values[0], 0, atol=1e-4) assert np.isclose(net.res_cost, net.res_gen.p_mw.values[0] * 1000, atol=1e-3) # pytest.main([__file__, "-xs"])
def test_opf_task(): net = pp.create_empty_network() pp.create_buses(net, 6, [10, 10, 10, 0.4, 7, 7], min_vm_pu=[0.9, 0.9, 0.88, 0.9, np.nan, np.nan]) idx_ext_grid = 1 pp.create_ext_grid(net, 0, max_q_mvar=80, min_p_mw=0, index=idx_ext_grid) pp.create_gen(net, 1, 10, min_q_mvar=-50, max_q_mvar=-10, min_p_mw=0, max_p_mw=60) pp.create_gen(net, 2, 8) pp.create_gen(net, 3, 5) pp.create_load(net, 3, 120, max_p_mw=8) pp.create_sgen(net, 1, 8, min_q_mvar=-50, max_q_mvar=-10, controllable=False) pp.create_sgen(net, 2, 8) pp.create_storage(net, 3, 2, 100, min_q_mvar=-10, max_q_mvar=-50, min_p_mw=0, max_p_mw=60, controllable=True) pp.create_dcline(net, 4, 5, 0.3, 1e-4, 1e-2, 1.01, 1.02, min_q_from_mvar=-10, min_q_to_mvar=-10) pp.create_line(net, 3, 4, 5, "122-AL1/20-ST1A 10.0", max_loading_percent=50) pp.create_transformer(net, 2, 3, "0.25 MVA 10/0.4 kV") # --- run and check opf_task() out1 = pp.opf_task(net, keep=True) assert out1["flexibilities_without_costs"] == "all" assert sorted(out1["flexibilities"].keys()) == [i1 + i2 for i1 in ["P", "Q"] for i2 in [ "dcline", "ext_grid", "gen", "storage"]] for key, df in out1["flexibilities"].items(): assert df.shape[0] if "gen" in key: assert df.shape[0] > 1 assert out1["flexibilities"]["Pext_grid"].loc[0, "index"] == [1] assert np.isnan(out1["flexibilities"]["Pext_grid"].loc[0, "max"]) assert out1["flexibilities"]["Pext_grid"].loc[0, "min"] == 0 assert np.isnan(out1["flexibilities"]["Qext_grid"].loc[0, "min"]) assert out1["flexibilities"]["Qext_grid"].loc[0, "max"] == 80 assert sorted(out1["network_constraints"].keys()) == ["LOADINGline", "VMbus"] assert out1["network_constraints"]["VMbus"].shape[0] == 3 # check delta_pq net.gen.loc[0, "min_p_mw"] = net.gen.loc[0, "max_p_mw"] - 1e-5 out2 = pp.opf_task(net, delta_pq=1e-3, keep=True) assert out2["flexibilities"]["Pgen"].shape[0] == 1 net.gen.loc[0, "min_p_mw"] = net.gen.loc[0, "max_p_mw"] - 1e-1 out1["flexibilities"]["Pgen"].loc[0, "min"] = out1["flexibilities"]["Pgen"].loc[ 0, "max"] - 1e-1 out3 = pp.opf_task(net, delta_pq=1e-3, keep=True) for key in out3["flexibilities"]: assert pp.dataframes_equal(out3["flexibilities"][key], out1["flexibilities"][key]) # check costs pp.create_poly_cost(net, idx_ext_grid, "ext_grid", 2) pp.create_poly_cost(net, 1, "gen", 1.7) pp.create_poly_cost(net, 0, "dcline", 2) pp.create_pwl_cost(net, 2, "gen", [[-1e9, 1, 3.1], [1, 1e9, 0.5]], power_type="q") out4 = pp.opf_task(net) for dict_key in ["flexibilities", "network_constraints"]: for key in out4[dict_key]: assert pp.dataframes_equal(out4[dict_key][key], out1[dict_key][key]) assert isinstance(out4["flexibilities_without_costs"], dict) expected_elm_without_cost = ["gen", "storage"] assert sorted(out4["flexibilities_without_costs"].keys()) == expected_elm_without_cost for elm in expected_elm_without_cost: assert len(out4["flexibilities_without_costs"][elm]) == 1