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 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_contingency_sgen(base_net): net = base_net pp.create_sgen(net, 1, p_kw=-100, q_kvar=0, controllable=True, max_p_kw=-5, min_p_kw=-150, max_q_kvar=50, min_q_kvar=-50) # pwl costs # maximize the sgen feed in by using a positive cost slope # using a slope of 1 # | / # | / # | / # |/ #------------------------------------------- # p_min_kw /| # / | # / | pp.create_piecewise_linear_cost( net, 0, "sgen", array([[net.sgen.min_p_kw.at[0], net.sgen.min_p_kw.at[0]], [0, 0]])) pp.runopp(net) assert abs(net.res_cost - net.res_sgen.p_kw.at[0]) < 1e-5 # minimize the sgen feed in by using a positive cost slope # using a slope of 1 # \ | # \ | # \ | # \| #------------------------------------------- # p_min_kw |\ # | \ # | \ net.piecewise_linear_cost.f.at[0] *= -1 pp.runopp(net) assert abs(net.res_cost - net.res_sgen.p_kw.at[0] * -1) < 1e-5 try: net.piecewise_linear_cost = net.piecewise_linear_cost.drop(index=0) except: net.piecewise_linear_cost = net.piecewise_linear_cost.drop(0) # first using a positive slope as in the case above pp.create_polynomial_cost(net, 0, "sgen", array([1, 0])) pp.runopp(net) assert abs(net.res_cost - net.res_sgen.p_kw.at[0]) < 1e-5 # negative slope as in the case above net.polynomial_cost.c.at[0] *= -1 pp.runopp(net) assert abs(net.res_cost - net.res_sgen.p_kw.at[0] * -1) < 1e-5
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_dcopf_pwl(simple_opf_test_net): # create net net = simple_opf_test_net # pp.create_polynomial_cost(net, 0, "gen", np.array([-100, 0])) pp.create_piecewise_linear_cost( net, 0, "gen", np.array([[-200, -20000], [-100, -10000], [0, 0]])) # run OPF pp.rundcopp(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_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert abs(100 * net.res_gen.p_kw.values - net.res_cost) < 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_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, max_q_kvar=50, max_p_kw=100, min_p_kw=50, min_q_kvar=-50) 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_piecewise_linear_cost(net, 0, "gen", np.array([[-150, 150], [150, -150]])) pp.create_piecewise_linear_cost(net, 0, "gen", np.array([[-150, 150], [150, -150]]), type="q") pp.runopp(net, verbose=False) assert net["OPF_converged"] assert net.res_cost == -net.res_gen.p_kw.values + net.res_gen.q_kvar.values
def test_cost_mixed(): """ 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, max_q_kvar=50, max_p_kw=100, min_p_kw=50, min_q_kvar=-50) 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_polynomial_cost(net, 0, "gen", np.array([0, 1, 0])) pp.runopp(net, verbose=False) assert net["OPF_converged"] assert net.res_cost == - net.res_gen.p_kw.values net.polynomial_cost.c.at[0] = np.array([[1, 0, 0]]) pp.runopp(net, verbose=False) assert net["OPF_converged"] assert net.res_cost - net.res_gen.p_kw.values**2 < 1e-5 net.polynomial_cost.c.at[0] = np.array([[1, 0, 1]]) pp.runopp(net, verbose=False) assert net["OPF_converged"] assert net.res_cost - net.res_gen.p_kw.values**2 - 1 < 1e-5 net.load.controllable.at[0] = True pp.runopp(net, verbose=False) assert net.res_cost - net.res_gen.p_kw.values ** 2 - 1 < 1e-5 pp.create_piecewise_linear_cost(net, 0, "load", np.array([[0, 0], [100, 100]]), type="p") pp.runopp(net, verbose=False) assert net.res_cost - net.res_gen.p_kw.values ** 2 - 1 - net.res_load.p_kw.values < 1e-5
def _create_costs(net, ppc, gen_lookup, type, idx): if ppc['gencost'][idx, 0] == 1: if not len(ppc['gencost'][idx, 4:]) == 2*ppc['gencost'][idx, 3]: logger.error("In gencost line %s, the number n does not fit to the number of values" % idx) pp.create_piecewise_linear_cost(net, gen_lookup.element.at[idx], gen_lookup.element_type.at[idx], ppc['gencost'][idx, 4:], type) elif ppc['gencost'][idx, 0] == 2: if len(ppc['gencost'][idx, 4:]) == ppc['gencost'][idx, 3]: n = len(ppc['gencost'][idx, 4:]) values = ppc['gencost'][idx, 4:] / power(1e3, array(range(n))[::-1]) else: logger.error("In gencost line %s, the number n does not fit to the number of values" % idx) pp.create_polynomial_cost(net, gen_lookup.element.at[idx], gen_lookup.element_type.at[idx], values, type) else: logger.info("Cost mode of gencost line %s is unknown." % idx)
def test_cost_pwl_q_3point(): # We have a problem with the cost value after optimization of 3 point q cost functions! It returns the amount of q at the EG, but not the costs! # Also, the q result is not the optimum! 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_piecewise_linear_cost(net, 0, "sgen", np.array([[-50, 50], [0, 0], [50, 50]]), type="q") # run OPF pp.runopp(net, verbose=False) assert net["OPF_converged"]
def test_dcopf_pwl(): # create net net = pp.create_empty_network() pp.create_bus(net, vn_kv=10.) pp.create_bus(net, 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", array([-100, 0])) pp.create_piecewise_linear_cost( net, 0, "gen", array([[-200, 20000], [-100, 10000], [0, 0]])) # run OPF pp.rundcopp(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_ext_grid:\n%s" % net.res_ext_grid) logger.debug("res_bus.vm_pu: \n%s" % net.res_bus.vm_pu) assert abs(100 * net.res_gen.p_kw.values - net.res_cost) < 1e-3
def test_3point_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_sgen(net, 1, p_kw=-100, q_kvar=0, controllable=True, max_p_kw=-100, min_p_kw=-100.5, 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, "sgen", np.array([ [-100, 1], [0, 0], [100, 1], ]), type="q") # creating a pwl cost function that actually is realistic: The absolute value of the reactive power has costs. pp.runopp(net, verbose=False) # assert abs( net.res_sgen.q_kvar.values ) < 1e-5 # this is not the expected result. the reactive power should be at zero to minimze the costs. # checkout the dirty workaround: # the first sgen is only representing the positive segment of the function: net.piecewise_linear_cost.p.at[0] = np.array([[0, 1]]) net.piecewise_linear_cost.f.at[0] = np.array([[0, 1]]) net.sgen.min_q_kvar.at[0] = 0 # what we can do instead is modelling a second sgen on the same bus representing the negative segment of the function: pp.create_sgen(net, 1, p_kw=0, q_kvar=0, controllable=True, max_p_kw=0.01, min_p_kw=-0.01, max_q_kvar=0, min_q_kvar=-10) pp.create_piecewise_linear_cost(net, 1, "sgen", np.array([ [-100, 100], [0, 0], ]), type="q") # runOPF pp.runopp(net, verbose=False) assert abs(sum(net.res_sgen.q_kvar.values)) < 1e-5 # et voila, we have the q at zero. sure, we do have two seperate sgens now and this is very dirty. but it's working. # let's check if we can handle overvoltage net.bus.max_vm_pu = 1.041 pp.runopp(net, verbose=False) assert abs(max(net.res_bus.vm_pu.values) - 1.041) < 1e-5
def test_contingency_load(base_net): net = base_net pp.create_load(net, 1, p_kw=-100, q_kvar=0, controllable=True, max_p_kw=150, min_p_kw=5, max_q_kvar=50, min_q_kvar=-50) # pwl costs # minimze the load by using a positive cost slope # using a slope of 1 # | / # | / # | / # |/ # ------------------------------------------- # p_min_kw /| # / | # / | pp.create_piecewise_linear_cost( net, 1, "load", array([[0, 0], [net.load.max_p_kw.at[1], net.load.max_p_kw.at[1]]])) pp.runopp(net) assert abs(net.res_cost - net.res_load.p_kw.at[1]) < 1e-5 # maximize the load in by using a negative cost slope # using a slope of 1 # \ | # \ | # \ | # \| # ------------------------------------------- # p_min_kw |\ # | \ # | \ net.piecewise_linear_cost.f.at[0] *= -1 pp.runopp(net) assert abs(net.res_cost - net.res_load.p_kw.at[1] * -1) < 1e-5 # poly costs try: net.piecewise_linear_cost = net.piecewise_linear_cost.drop(index=0) except: # legacy fix net.piecewise_linear_cost = net.piecewise_linear_cost.drop(0) # first using a positive slope as in the case above pp.create_polynomial_cost(net, 1, "load", array([1, 0])) pp.runopp(net) assert abs(net.res_cost - net.res_load.p_kw.at[1]) < 1e-5 # negative slope as in the case above net.polynomial_cost.c.at[0] *= -1 pp.runopp(net) assert abs(net.res_cost - net.res_load.p_kw.at[1] * -1) < 1e-5