def test_cigre_mv(): net = pn.create_cigre_network_mv() # with_der=False pp.runpp(net) all_vn_kv = pd.Series([110, 20]) assert net.bus.vn_kv.isin(all_vn_kv).all() assert len(net.bus) == 15 assert len(net.line) == 15 assert len(net.gen) == 0 assert len(net.sgen) == 0 assert len(net.shunt) == 0 assert len(net.trafo) == 2 assert len(net.load) == 18 assert len(net.ext_grid) == 1 assert len(net.switch) == 8 assert net.converged is True net = pn.create_cigre_network_mv(with_der=True) pp.runpp(net) all_vn_kv = pd.Series([110, 20]) assert net.bus.vn_kv.isin(all_vn_kv).all() assert len(net.bus) == 15 assert len(net.line) == 15 assert len(net.gen) == 0 assert len(net.sgen) == 9 assert len(net.shunt) == 0 assert len(net.trafo) == 2 assert len(net.load) == 18 assert len(net.ext_grid) == 1 assert len(net.switch) == 8 assert net.converged is True
def peak_network(peak='demand', scale_nominal_value=40): """ Creates 15 bus cigre network with 8 solar units and 1 wind park. The network is scaled so that there is a lot of solar power production :param with_der: :return: """ net = pn.create_cigre_network_mv(with_der="pv_wind") pq_ratio = net.load['q_mvar'] / net.load['p_mw'] net.sgen['sn_mva'] *= scale_nominal_value net.sgen.loc[ 8, 'sn_mva'] /= scale_nominal_value # undo scaling for wind park if peak == 'solar': net.sgen['p_mw'] = net.sgen[ 'sn_mva'].values * 0.794747 # max solar at 12 am net.load['p_mw'] = net.load['sn_mva'] * 0.444 # mean demand at 12 am net.load['q_mvar'] = net.load['p_mw'] * pq_ratio elif peak == 'demand': net.sgen['p_mw'] = net.sgen['sn_mva'] * 0.039228 # mean solar at 7 pm net.load['p_mw'] = net.load['sn_mva'] * 0.926647 # max demand at 7 pm net.load['q_mvar'] = net.load['p_mw'] * pq_ratio pp.runpp(net) return net
def test_connectivity_check_island_without_pv_bus(): # Network with islands without pv bus -> all buses in island should be set out of service net = create_cigre_network_mv(with_der=False) iso_buses, iso_p, iso_q = get_isolated(net) assert len(iso_buses) == 0 assert np.isclose(iso_p, 0) assert np.isclose(iso_q, 0) isolated_bus1 = pp.create_bus(net, vn_kv=20., name="isolated Bus1") isolated_bus2 = pp.create_bus(net, vn_kv=20., name="isolated Bus2") pp.create_line(net, isolated_bus2, isolated_bus1, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLine") iso_buses, iso_p, iso_q = get_isolated(net) assert len(iso_buses) == 2 assert np.isclose(iso_p, 0) assert np.isclose(iso_q, 0) pp.create_load(net, isolated_bus1, p_kw=200., q_kvar=20) pp.create_sgen(net, isolated_bus2, p_kw=-150., q_kvar=-10) # with pytest.warns(UserWarning): iso_buses, iso_p, iso_q = get_isolated(net) assert len(iso_buses) == 2 assert np.isclose(iso_p, 350) assert np.isclose(iso_q, 30) # with pytest.warns(UserWarning): runpp_with_consistency_checks(net, check_connectivity=True)
def inicializa_rede(barras_gd, p_pv_kw, p_eolica_kw): """Metodo de inicializacao da rede.""" # seleciona a rede cigre media tensao net = pn.create_cigre_network_mv(with_der=False) if barras_gd != []: load = net.load.query('bus==' + str(barras_gd[0])) net.load.p_kw[load.index[0]] -= p_pv_kw net.load.q_kvar[load.index[0]] -= p_pv_kw/0.9 * np.sin(np.arccos(0.9)) load = net.load.query('bus==' + str(barras_gd[1])) net.load.p_kw[load.index[0]] -= p_eolica_kw net.load.q_kvar[load.index[0]] -= p_eolica_kw / 0.9 * np.sin(np.arccos(0.9)) # roda o fluxo de carga pp.runpp(net) # ------------------------------- # # insere a impedancia de sq. zero # # ------------------------------- # r0_ohm_per_km = 3.0 * 0.501 x0_ohm_per_km = 3.0 * 0.716 net.line['r0_ohm_per_km'] = r0_ohm_per_km * np.ones(len(net.line)) net.line['x0_ohm_per_km'] = x0_ohm_per_km * np.ones(len(net.line)) # ------------------------------- # # insere a impedancia equivalente # # ------------------------------- # fat = 0.25 net.bus['zeq_ohms'] = np.zeros(len(net.bus)) net.bus.zeq_ohms[1] = fat * (0.488 + 5.832j) net.bus.zeq_ohms[12] = fat * (0.488 + 5.832j) net.bus['z0_eq_ohms'] = np.zeros(len(net.bus)) net.bus.z0_eq_ohms[1] = fat * (0.444 + 5.34j) net.bus.z0_eq_ohms[12] = fat * (0.444 + 5.34j) # ------------------------------------- # # insere a impedancia do trafo # # ------------------------------------- # net.trafo['z_ohms'] = np.zeros(len(net.trafo)) net.trafo.z_ohms[0] = 0.5 + 3.2j net.trafo.z_ohms[1] = 0.5 + 3.2j # ------------------------------------- # # insere a corrente defalta dos trafos # # ------------------------------------- # net.trafo['i_cc'] = np.zeros(len(net.trafo)) # ------------------------------------- # # insere a corrente de falta nas linhas # # ------------------------------------- # net.line['i_cc'] = np.zeros(len(net.line)) return net
def test_connectivity_check_island_with_multiple_pv_buses(): # Network with islands an multiple PV buses in the island -> Error should be thrown since it # would be random to choose just some PV bus as the reference bus net = create_cigre_network_mv(with_der=False) iso_buses, iso_p, iso_q = get_isolated(net) assert len(iso_buses) == 0 assert np.isclose(iso_p, 0) assert np.isclose(iso_q, 0) isolated_bus1 = pp.create_bus(net, vn_kv=20., name="isolated Bus1") isolated_bus2 = pp.create_bus(net, vn_kv=20., name="isolated Bus2") isolated_pv_bus1 = pp.create_bus(net, vn_kv=20., name="isolated PV bus1") isolated_pv_bus2 = pp.create_bus(net, vn_kv=20., name="isolated PV bus2") pp.create_gen(net, isolated_pv_bus1, p_mw=0.3, vm_pu=1.0, name="isolated PV bus1") pp.create_gen(net, isolated_pv_bus2, p_mw=0.05, vm_pu=1.0, name="isolated PV bus2") pp.create_line(net, isolated_pv_bus1, isolated_bus1, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLineToGen1") pp.create_line(net, isolated_pv_bus2, isolated_bus2, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLineToGen2") pp.create_line(net, isolated_bus2, isolated_bus1, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLine") # ToDo with pytest.warns(UserWarning): iso_buses, iso_p, iso_q = get_isolated(net)
def test_add_column_from_element_to_elements(): net = nw.create_cigre_network_mv() pp.create_measurement(net, "i", "trafo", 5, 3, 0, side="hv") pp.create_measurement(net, "i", "line", 5, 3, 0, side="to") pp.create_measurement(net, "p", "bus", 5, 3, 2) assert net.measurement.name.isnull().all() assert ~net.switch.name.isnull().all() orig_switch_names = copy.deepcopy(net.switch.name.values) expected_measurement_names = np.array( [net.trafo.name.loc[0], net.line.name.loc[0], net.bus.name.loc[2]]) expected_switch_names = np.append( net.line.name.loc[net.switch.element.loc[net.switch.et == "l"]].values, net.trafo.name.loc[net.switch.element.loc[net.switch.et == "t"]].values) pp.add_column_from_element_to_elements(net, "name", False) assert all( pp.compare_arrays(net.measurement.name.values, expected_measurement_names)) assert all(pp.compare_arrays(net.switch.name.values, orig_switch_names)) del net.measurement["name"] pp.add_column_from_element_to_elements(net, "name", True) assert all( pp.compare_arrays(net.measurement.name.values, expected_measurement_names)) assert all(pp.compare_arrays(net.switch.name.values, expected_switch_names))
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 _testnet_with_profiles(): # get and manipulate net net = pn.create_cigre_network_mv(with_der="all") in_net_profiles = pd.DataFrame([[0.1, 0.2, np.nan], [0.3, 0.2, 0.6]], columns=["in_net1", "in_net2", "input1"]) net["profiles"] = { "load": deepcopy(in_net_profiles), "powerplants": in_net_profiles, "renewables": in_net_profiles, "storage": in_net_profiles } net["profiles"]["load"].columns += "_pload" in_net_profiles_qload = deepcopy(in_net_profiles) in_net_profiles_qload.columns += "_qload" net["profiles"]["load"] = pd.concat( [net["profiles"]["load"], in_net_profiles_qload], axis=1) np.random.seed(1) for elm, high in zip(["load", "sgen", "storage"], [2, 3, 3]): net[elm]["profile"] = np.array(["in_net1", "in_net2", "input1"])[np.random.randint( 0, high, net[elm].shape[0])] net["loadcases"] = pd.DataFrame( [["hL", 1.0, 1., 0., 0., 0, 1.035], ["n1", 1.0, 1., 0., 0., 0, 1.035], ["hW", 1.0, 1., 1.00, 0.80, 1, 1.035], ["hPV", 1.0, 1., 0.85, 0.95, 1, 1.035], ["lW", 0.1, 0.122543, 1.00, 0.80, 1, 1.015], ["lPV", 0.1, 0.122543, 0.85, 0.95, 1, 1.015]], columns=[ "Study Case", "pload", "qload", "Wind_p", "PV_p", "RES_p", "Slack_vm" ]) net["loadcases"].set_index("Study Case", inplace=True) return net, deepcopy(in_net_profiles)
def test_connectivity_check_island_with_one_pv_bus(): # Network with islands with one PV bus -> PV bus should be converted to the reference bus net = create_cigre_network_mv(with_der=False) iso_buses, iso_p, iso_q = get_isolated(net) assert len(iso_buses) == 0 assert np.isclose(iso_p, 0) assert np.isclose(iso_q, 0) isolated_bus1 = pp.create_bus(net, vn_kv=20., name="isolated Bus1") isolated_bus2 = pp.create_bus(net, vn_kv=20., name="isolated Bus2") isolated_gen = pp.create_bus(net, vn_kv=20., name="isolated Gen") isolated_pv_bus = pp.create_gen(net, isolated_gen, p_mw=0.35, vm_pu=1.0, name="isolated PV bus") pp.create_line(net, isolated_bus2, isolated_bus1, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLine") pp.create_line(net, isolated_gen, isolated_bus1, length_km=1, std_type="N2XS(FL)2Y 1x300 RM/35 64/110 kV", name="IsolatedLineToGen") # with pytest.warns(UserWarning): iso_buses, iso_p, iso_q = get_isolated(net) # assert len(iso_buses) == 0 # assert np.isclose(iso_p, 0) # assert np.isclose(iso_q, 0) # # pp.create_load(net, isolated_bus1, p_mw=0.200., q_mvar=0.020) # pp.create_sgen(net, isolated_bus2, p_mw=0.0150., q_mvar=-0.010) # # iso_buses, iso_p, iso_q = get_isolated(net) # assert len(iso_buses) == 0 # assert np.isclose(iso_p, 0) # assert np.isclose(iso_q, 0) # with pytest.warns(UserWarning): runpp_with_consistency_checks(net, check_connectivity=True)
def test_add_column_from_node_to_elements(): net = nw.create_cigre_network_mv("pv_wind") net.bus["subnet"] = ["subnet_%i" % i for i in range(net.bus.shape[0])] net.sgen["subnet"] = "already_given" net.switch["subnet"] = None net_orig = copy.deepcopy(net) branch_bus = ["from_bus", "lv_bus"] pp.add_column_from_node_to_elements(net, "subnet", False, branch_bus=branch_bus) def check_subnet_correctness(net, elements, branch_bus): for elm in elements: if "bus" in net[elm].columns: assert all(pp.compare_arrays(net[elm]["subnet"].values, np.array(["subnet_%i" % bus for bus in net[elm].bus]))) elif branch_bus[0] in net[elm].columns: assert all(pp.compare_arrays(net[elm]["subnet"].values, np.array([ "subnet_%i" % bus for bus in net[elm][branch_bus[0]]]))) elif branch_bus[1] in net[elm].columns: assert all(pp.compare_arrays(net[elm]["subnet"].values, np.array([ "subnet_%i" % bus for bus in net[elm][branch_bus[1]]]))) check_subnet_correctness(net, pp.pp_elements(bus=False)-{"sgen"}, branch_bus) pp.add_column_from_node_to_elements(net_orig, "subnet", True, branch_bus=branch_bus) check_subnet_correctness(net_orig, pp.pp_elements(bus=False), branch_bus)
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_cigre_network(init='flat'): # 1. create network # test the mv ring network with all available voltage measurements and bus powers # test if switches and transformer will work correctly with the state estimation np.random.seed(123456) net = nw.create_cigre_network_mv(with_der=False) pp.runpp(net) for bus, row in net.res_bus.iterrows(): pp.create_measurement(net, "v", "bus", row.vm_pu * r(0.01), 0.01, bus) # if np.random.randint(0, 4) == 0: # continue pp.create_measurement(net, "p", "bus", -row.p_mw * r(), max(0.001, abs(0.03 * row.p_mw)), bus) pp.create_measurement(net, "q", "bus", -row.q_mvar * r(), max(0.001, abs(0.03 * row.q_mvar)), bus) # 2. Do state estimation success = estimate(net, init="flat", calculate_voltage_angles=False) v_result = net.res_bus_est.vm_pu.values delta_result = net.res_bus_est.va_degree.values target_v = net.res_bus.vm_pu.values diff_v = target_v - v_result target_delta = net.res_bus.va_degree.values diff_delta = target_delta - delta_result assert success assert (np.nanmax(abs(diff_v)) < 0.0043) assert (np.nanmax(abs(diff_delta)) < 0.17)
def cigre_grid(): net = nw.create_cigre_network_mv() net["bus"].loc[:, "min_vm_pu"] = 0.95 net["bus"].loc[:, "max_vm_pu"] = 1.05 net["line"].loc[:, "max_loading_percent"] = 60. return net
def calc_pq_ratio(self): """ Power factor for loads are assumed constant. This method finds the PQ-ratio for all loads (same as for default cigre network) """ net = create_cigre_network_mv(with_der="pv_wind") pq_ratio = net.load['q_mvar'] / net.load['p_mw'] return pq_ratio
def test_add_zones_to_elements(): net = nw.create_cigre_network_mv() # add zones to lines and switchs tb.add_zones_to_elements(net, elements=["line", "switch"]) # create 2 arrays which include "zone" in lines and switchs zone_line = net["line"]["zone"].values zone_switch = net["switch"]["zone"].values assert "CIGRE_MV" in net["line"]["zone"].values assert "CIGRE_MV" in net["switch"]["zone"].values
def voltage_effect(net=None, buses=[1,12], scale_factor=2): if net is None: net = pn.create_cigre_network_mv(with_der="pv_wind") net.load[['p_mw','q_mvar']] = net.load[['p_mw','q_mvar']]*0.748772 #mean demand at 20 pm pp.runpp(net) v1 = net.res_bus['vm_pu'] idx = net.load['bus'].isin(buses) net.load.loc[idx,['p_mw','q_mvar']] *= scale_factor pp.runpp(net) v2 = net.res_bus['vm_pu'] df = pd.DataFrame(data={'A':v1,'B':v2}) return df, net
def cigre_network(with_der='pv_wind', scale_nominal_value=40): """ Creates 15 bus cigre network with 8 solar units and 1 wind park. The network is scaled so that there is a lot of solar power production :param with_der: :return: """ net = pn.create_cigre_network_mv(with_der="pv_wind") net.sgen['sn_mva'] *= scale_nominal_value net.sgen.loc[8, 'sn_mva'] /= scale_nominal_value # undo scaling for wind park return net
def current_effect(net=None, buses=[1,12], scale_factor=2): """ Effect of scaling consumption at buses """ if net is None: net = pn.create_cigre_network_mv(with_der="pv_wind") net.load[['p_mw','q_mvar']] = net.load[['p_mw','q_mvar']]*0.748772 #mean demand in hour 8 pp.runpp(net) loading1 = net.res_line['loading_percent'] idx = net.load['bus'].isin(buses) net.load.loc[idx,['p_mw','q_mvar']] *= scale_factor pp.runpp(net) loading2 = net.res_line['loading_percent'] df = pd.DataFrame(data={'A':loading1,'B':loading2}) return df, net
def _evaluate(self, x, out, *args, **kwargs): # print(x) net = pn.create_cigre_network_mv(with_der="pv_wind") net.bus = net.bus.sort_index() net.line = net.line.sort_index() net.trafo = net.trafo.sort_index() net.load = net.load.sort_index() net.sgen = net.sgen.sort_index() # net.sgen.p_mw=np.random.randint(50, size=len(net.sgen))/1000 net.sgen.sn_mva = net.sgen.p_mw # net.shunt=net.shunt.sort_index() net.switch.closed = [True] * 2 + [True] * 2 + [True] * 2 + [True] * 2 pp.runpp(net) zero_inject_bus = list( set(net.bus.index).difference( set(np.where(net.sgen.p_mw != 0)[0]).union(set( net.load.bus)).union(net.ext_grid.bus).union( net.shunt.bus))) list_bus_meas = list(set(net.bus.index)) list_line_meas = list(set(net.line.index)) list_transfo_meas = list(set(net.trafo.index)) df_measurement = pd.DataFrame() df_measurement['meas_type'] = ['v'] * len(list_bus_meas) + [ 'p', 'q', 'i', 'p', 'q', 'i' ] * len(list_line_meas) + ['p', 'q', 'i', 'p', 'q', 'i' ] * len(list_transfo_meas) df_measurement['element_type'] = ['bus'] * len(list_bus_meas) + [ 'line', 'line', 'line', 'line', 'line', 'line' ] * len(list_line_meas) + [ 'trafo', 'trafo', 'trafo', 'trafo', 'trafo', 'trafo' ] * len(list_transfo_meas) df_measurement['element'] = [item for item in list_bus_meas] + [ item for item in list_line_meas for x in range(6) ] + [item for item in list_transfo_meas for x in range(6)] df_measurement['side'] = ['None'] * len(list_bus_meas) + [ 'from', 'from', 'from', 'to', 'to', 'to' ] * len(list_line_meas) + ['from', 'from', 'from', 'to', 'to', 'to' ] * len(list_transfo_meas) df_measurement, net = create_measurement_unit(df_measurement, net) print(len(net.measurement)) f1, f2 = get_f_g(x) print(f1) print(f2) out["F"] = anp.column_stack([f1, f2])
def test_merge_and_split_nets(): net1 = nw.mv_oberrhein() # TODO there are some geodata values in oberrhein without corresponding lines net1.line_geodata.drop(set(net1.line_geodata.index) - set(net1.line.index), inplace=True) n1 = len(net1.bus) pp.runpp(net1) net2 = nw.create_cigre_network_mv() pp.runpp(net2) net = pp.merge_nets(net1, net2) pp.runpp(net) assert np.allclose(net.res_bus.vm_pu.iloc[:n1].values, net1.res_bus.vm_pu.values) assert np.allclose(net.res_bus.vm_pu.iloc[n1:].values, net2.res_bus.vm_pu.values) net3 = pp.select_subnet(net, net.bus.index[:n1], include_results=True) assert pp.dataframes_equal(net3.res_bus[["vm_pu"]], net1.res_bus[["vm_pu"]]) net4 = pp.select_subnet(net, net.bus.index[n1:], include_results=True) assert np.allclose(net4.res_bus.vm_pu.values, net2.res_bus.vm_pu.values)
def test_select_subnet(): # This network has switches of type 'l' and 't' net = nw.create_cigre_network_mv() # Do nothing same_net = pp.select_subnet(net, net.bus.index) assert pp.dataframes_equal(net.bus, same_net.bus) assert pp.dataframes_equal(net.switch, same_net.switch) assert pp.dataframes_equal(net.trafo, same_net.trafo) assert pp.dataframes_equal(net.line, same_net.line) assert pp.dataframes_equal(net.load, same_net.load) assert pp.dataframes_equal(net.ext_grid, same_net.ext_grid) # Remove everything empty = pp.select_subnet(net, set()) assert len(empty.bus) == 0 assert len(empty.line) == 0 assert len(empty.load) == 0 assert len(empty.trafo) == 0 assert len(empty.switch) == 0 assert len(empty.ext_grid) == 0 # Should keep all trafo ('t') switches when buses are included hv_buses = set(net.trafo.hv_bus) lv_buses = set(net.trafo.lv_bus) trafo_switch_buses = set(net.switch[net.switch.et == 't'].bus) subnet = pp.select_subnet(net, hv_buses | lv_buses | trafo_switch_buses) assert net.switch[net.switch.et == 't'].index.isin(subnet.switch.index).all() # Should keep all line ('l') switches when buses are included from_bus = set(net.line.from_bus) to_bus = set(net.line.to_bus) line_switch_buses = set(net.switch[net.switch.et == 'l'].bus) subnet = pp.select_subnet(net, from_bus | to_bus | line_switch_buses) assert net.switch[net.switch.et == 'l'].index.isin(subnet.switch.index).all() # This network has switches of type 'b' net2 = nw.create_cigre_network_lv() # Should keep all bus-to-bus ('b') switches when buses are included buses = set(net2.switch[net2.switch.et == 'b'].bus) elements = set(net2.switch[net2.switch.et == 'b'].element) subnet = pp.select_subnet(net2, buses | elements) assert net2.switch[net2.switch.et == 'b'].index.isin(subnet.switch.index).all()
def create_net2(): """ Cigre MV: Net + constraints for optimal reactive power flow. """ net = pn.create_cigre_network_mv(with_der='pv_wind') net = settings_orpf(net) # Make trafo tap-changable with tap-range [-2, +2] net.trafo.tap_pos = pd.Series([0, 0], index=net.trafo.index) net.trafo.tap_neutral = pd.Series([0, 0], index=net.trafo.index) net.trafo.tap_min = pd.Series([-2, -2], index=net.trafo.index) net.trafo.tap_max = pd.Series([+2, +2], index=net.trafo.index) net.trafo.tap_step_percent = pd.Series([2.5, 2.5], index=net.trafo.index) net.trafo.tap_step_degree = pd.Series([0, 0], index=net.trafo.index) net.trafo.tap_side = pd.Series(['hv', 'hv'], index=net.trafo.index) # Make trafo controllable net.trafo['controllable'] = pd.Series([True for _ in net.trafo.index], index=net.trafo.index) return net
def decisive_bus(buses, base_net=None, kind='voltage', scale_factor=2): buses = range(1, 15) mean_diff = [] if base_net is None: base_net = pn.create_cigre_network_mv(with_der="pv_wind") pp.runpp(base_net) for bus in buses: net = copy.deepcopy(base_net) if kind == 'voltage': df, net = voltage_effect(net=net, buses=[bus], scale_factor=scale_factor) elif kind == 'current': df, net = current_effect(net=net, buses=[bus], scale_factor=scale_factor) diff = df['A'] - df['B'] mean_diff.append(diff.sum()) diffs = pd.DataFrame(data=mean_diff, index=buses, columns=[kind]) flex = '{:d} %'.format(int((scale_factor - 1) * 100)) diffs['Flexibility'] = flex return diffs
def test_runpm_vd(): net = nw.create_cigre_network_mv(with_der="pv_wind") net.sgen.p_mw = net.sgen.p_mw * 8 net.sgen.sn_mva = net.sgen.sn_mva * 8 pp.runpp(net) net_org = deepcopy(net) net.load['controllable'] = False net.sgen['controllable'] = True net.sgen["max_p_mw"] = net.sgen.p_mw.values net.sgen["min_p_mw"] = net.sgen.p_mw.values net.sgen["max_q_mvar"] = net.sgen.p_mw.values * 0.328 net.sgen["min_q_mvar"] = -net.sgen.p_mw.values * 0.328 net.bus["max_vm_pu"] = 1.1 net.bus["min_vm_pu"] = 0.9 net.ext_grid["max_q_mvar"] = 10000.0 net.ext_grid["min_q_mvar"] = -10000.0 net.ext_grid["max_p_mw"] = 10000.0 net.ext_grid["min_p_mw"] = -10000.0 net.gen["max_p_mw"] = net.gen.p_mw.values net.gen["min_p_mw"] = net.gen.p_mw.values net.gen["max_q_mvar"] = 10000.0 net.gen["min_q_mvar"] = -10000.0 net.trafo["max_loading_percent"] = 500.0 net.line["max_loading_percent"] = 500.0 for idx in net.sgen.index: pp.create_poly_cost(net, idx, "sgen", 1.0) for idx in net.gen.index: pp.create_poly_cost(net, idx, "gen", 1.0) for idx in net.ext_grid.index: pp.create_poly_cost(net, idx, "ext_grid", 1.0) net.bus["pm_param/setpoint_v"] = None net.bus["pm_param/setpoint_v"].loc[net.sgen.bus] = 0.99 pp.runpm_vd(net) assert np.allclose(net.res_bus.vm_pu[net.sgen.bus], 0.99, atol=1e-2, rtol=1e-2) assert np.not_equal(net_org.res_sgen.q_mvar.values.all(), net.res_sgen.q_mvar.values.all())
def test_cigre_with_bad_data(): np.random.seed(123456) net = nw.create_cigre_network_mv(with_der=False) net.load.q_mvar = net.load["p_mw"].apply(lambda p: p * np.tan(np.arccos(np.random.choice([0.95, 0.9, 0.97])))) pp.runpp(net) for bus, row in net.res_bus.iterrows(): if bus == 2: continue if bus != 6: pp.create_measurement(net, "v", "bus", row.vm_pu * r(0.01), 0.01, bus) # skip our bad data measurement pp.create_measurement(net, "p", "bus", -row.p_mw * r(), max(0.001, abs(0.03 * row.p_mw)), bus) pp.create_measurement(net, "q", "bus", -row.q_mvar * r(), max(0.001, abs(0.03 * row.q_mvar)), bus) # 2. Do state estimation success_SE = estimate(net, init='slack') v_est_SE = net.res_bus_est.vm_pu.values delta_SE = net.res_bus_est.va_degree.values # 3. Create false measurement (very close to useful values) pp.create_measurement(net, "v", "bus", 0.85, 0.01, element=6) # 4. Do chi2-test bad_data_detected = chi2_analysis(net, init='slack') # 5. Perform rn_max_test success_rn_max = remove_bad_data(net, init='slack') v_est_rn_max = net.res_bus_est.vm_pu.values delta_est_rn_max = net.res_bus_est.va_degree.values diff_v = v_est_SE - v_est_rn_max diff_delta = delta_SE - delta_est_rn_max assert success_SE assert bad_data_detected assert success_rn_max assert (np.nanmax(abs(diff_v)) < 1e-8) assert (np.nanmax(abs(diff_delta)) < 1e-8)
def test_opf_cigre(): """ 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.in_service[net.sgen.bus == 4] = False net.sgen.in_service[net.sgen.bus == 6] = False net.sgen.in_service[net.sgen.bus == 8] = False net.sgen.in_service[net.sgen.bus == 9] = False # run OPF pp.runopp(net, ) assert net["OPF_converged"]
def test_pf_algorithms(): alg_to_test = ['bfsw', 'fdbx', 'fdxb', 'gs'] for alg in alg_to_test: net = create_cigre_network_mv(with_der=False) pp.runpp(net, algorithm='nr') vm_nr = net.res_bus.vm_pu va_nr = net.res_bus.va_degree pp.runpp(net, algorithm=alg) vm_alg = net.res_bus.vm_pu va_alg = net.res_bus.va_degree assert np.allclose(vm_nr, vm_alg) assert np.allclose(va_nr, va_alg) # testing with a network which contains DERs net = create_cigre_network_mv() pp.runpp(net) vm_nr = net.res_bus.vm_pu va_nr = net.res_bus.va_degree pp.runpp(net, algorithm=alg) vm_alg = net.res_bus.vm_pu va_alg = net.res_bus.va_degree assert np.allclose(vm_nr, vm_alg) assert np.allclose(va_nr, va_alg) # testing a weakly meshed network and consideration of phase-shifting transformer using calculate_voltage_angles net = four_loads_with_branches_out() # adding a line in order to create a loop pp.create_line(net, from_bus=8, to_bus=9, length_km=0.05, name='line9', std_type='NAYY 4x120 SE') pp.runpp(net, calculate_voltage_angles=True) vm_nr = net.res_bus.vm_pu va_nr = net.res_bus.va_degree pp.runpp(net, algorithm=alg, calculate_voltage_angles=True) vm_alg = net.res_bus.vm_pu va_alg = net.res_bus.va_degree assert np.allclose(vm_nr, vm_alg) assert np.allclose(va_nr, va_alg) # testing a network with PV buses net = example_simple() pp.runpp(net) vm_nr = net.res_bus.vm_pu va_nr = net.res_bus.va_degree pp.runpp(net, algorithm='bfsw') vm_alg = net.res_bus.vm_pu va_alg = net.res_bus.va_degree assert np.allclose(vm_nr, vm_alg) assert np.allclose(va_nr, va_alg)
# Youtube Tutorial: https://www.youtube.com/watch?v=O74yw1FmmsM import pandapower.toolbox as tb import pandapower.networks as nw import pandapower as pp net = nw.create_cigre_network_mv() pp.runpp(net) # print some power flow information tb.lf_info(net) net2 = nw.create_cigre_network_mv() net2.load.drop(index=0, inplace=True) # check if two nets are identical. You can also only check the results tb.nets_equal(net, net2) # merge two power systems net3 = tb.merge_nets(net, net2) # drop some buses tb.drop_buses(net, buses=[5]) # creates a continuous index in net.bus starting at 10 tb.create_continuous_bus_index(net, start=10) # get all line elements connected to buses els = tb.get_connected_elements(net, "line", buses=[11]) print(els) print(net.line.loc[els])
def __init__(self, train): # simulation timestep self.dt = 1 # timestep counter self.t = 0 # running mode: train or test self.train = train # simulation data: load, solar power, wind pwoer, price self.data = read_pickle_data()['train'] if train else read_pickle_data( )['test'] # time steps self.total_timesteps = self.data['solar'].size # days self.days = self.data['solar'].size // 24 # network architecture self.net = pn.create_cigre_network_mv(with_der="all") # how much history to store self.past_t = 24 # seed self.seed() # list of agents RFC_1 = DG('Residential fuel cell 1', bus='5', min_p_mw=0, max_p_mw=0.33, sn_mva=0.33, control_q=True, cost_curve_coefs=[100, 51.6, 0.5011]) RFC_2 = DG('Residential fuel cell 2', bus='10', min_p_mw=0, max_p_mw=0.14, sn_mva=0.14, control_q=True, cost_curve_coefs=[100, 72.4, 0.4615]) FC_1 = DG('Fuel cell 1', bus='9', min_p_mw=0, max_p_mw=0.212, sn_mva=0.212, control_q=True, cost_curve_coefs=[100, 40.7, 1.1532]) CHP_DG_1 = DG('CHP diesel 1', bus='9', min_p_mw=0, max_p_mw=0.310, sn_mva=0.310, control_q=True, cost_curve_coefs=[100, 35.8, 1.3156]) CL_1 = DG('CL1', type='CL', bus='5', min_p_mw=-0.05, max_p_mw=0, sn_mva=0.05, leading=False, control_q=False, cost_curve_coefs=[3000, 0, 0]) CL_2 = DG('CL2', type='CL', bus='9', min_p_mw=-0.1, max_p_mw=0, sn_mva=0.1, leading=False, control_q=False, cost_curve_coefs=[4000, 0, 0]) PV_3 = RES('PV 3', source='SOLAR', bus='3', sn_mva=0.02, control_q=False) PV_4 = RES('PV 4', source='SOLAR', bus='4', sn_mva=0.02, control_q=False) PV_5 = RES('PV 5', source='SOLAR', bus='5', sn_mva=0.03, control_q=False) PV_6 = RES('PV 6', source='SOLAR', bus='6', sn_mva=0.03, control_q=False) PV_8 = RES('PV 8', source='SOLAR', bus='8', sn_mva=0.03, control_q=False) PV_9 = RES('PV 9', source='SOLAR', bus='9', sn_mva=0.03, control_q=False) PV_10 = RES('PV 10', source='SOLAR', bus='10', sn_mva=0.04, control_q=False) PV_11 = RES('PV 11', source='SOLAR', bus='11', sn_mva=0.01, control_q=False) WKA_7 = RES('WKA 7', source='WIND', bus='7', sn_mva=1.5, control_q=False) BAT_1 = ESS('Battery 1', bus='5', min_p_mw=-0.8, max_p_mw=0.8, max_e_mwh=4, min_e_mwh=0.2) BAT_2 = ESS('Battery 2', bus='10', min_p_mw=-1.5, max_p_mw=1.5, max_e_mwh=6, min_e_mwh=0.3) GRID = Grid('GRID', bus='0', sn_mva=10) self.agents = [ RFC_1, RFC_2, FC_1, CHP_DG_1, CL_1, CL_2, PV_3, PV_4, PV_5, PV_6, PV_8, PV_9, PV_10, PV_11, WKA_7, BAT_1, BAT_2, GRID ] # reset ob = self.reset() # configure spaces action_space, action_shape = [], 0 for agent in self.policy_agents: total_action_space = [] # continuous action space if agent.action.range is not None: low, high = agent.action.range u_action_space = spaces.Box(low=low, high=high, dtype=np.float32) total_action_space.append(u_action_space) action_shape += u_action_space.shape[-1] action_space.extend(total_action_space) low = np.concatenate([ac.low for ac in action_space]) high = np.concatenate([ac.high for ac in action_space]) self.action_space = spaces.Box(low=low, high=high, dtype=np.float32) # observation space self.observation_space = spaces.Box(low=-np.inf, high=+np.inf, shape=(ob.shape[0], ), dtype=np.float32) # reward self.reward_range = (-200.0, 200.0)
std_dev=row['std_dev'], element=row['element'], side=row['side']) return df_measurement, net global upper_bus_accuracy, lower_bus_accuracy, upper_line_accuracy, lower_line_accuracy, upper_trafo_accuracy, lower_trafo_accuracy upper_bus_accuracy = 1.01 lower_bus_accuracy = 0.99 upper_line_accuracy = 1.03 lower_line_accuracy = 0.97 upper_trafo_accuracy = 1.03 lower_trafo_accuracy = 0.97 # net = pn.simple_four_bus_system() net = pn.create_cigre_network_mv(with_der="pv_wind") net.bus = net.bus.sort_index() net.line = net.line.sort_index() net.trafo = net.trafo.sort_index() net.load = net.load.sort_index() net.sgen = net.sgen.sort_index() # net.sgen.p_mw=np.random.randint(50, size=len(net.sgen))/1000 net.sgen.sn_mva = net.sgen.p_mw # net.shunt=net.shunt.sort_index() net.switch.closed = [True] * 2 + [True] * 2 + [True] * 2 + [True] * 2 pp.runpp(net) zero_inject_bus = list( set(net.bus.index).difference( set(np.where(net.sgen.p_mw != 0)[0]).union(set(net.load.bus)).union( net.ext_grid.bus).union(net.shunt.bus)))