import os import numpy as np import pandas as pd import tempfile import random import pandapower as pp from pandapower.timeseries import DFData from pandapower.timeseries import OutputWriter from pandapower.timeseries.run_time_series import run_timeseries from pandapower.control import ConstControl from pandapower.control import controller import math import matplotlib.pyplot as plt from pandapower.plotting.plotly import simple_plotly import igraph from pandapower import control def timeseries(file_path, Blindleistungsfall): # 1. create Netz net = Windpark() # 2. get data n_timesteps = 101 profiles, ds = get_data(n_timesteps) gen_id = 0 max_q_mvar = -10 # 3. create controllers if Blindleistungsfall == "ind": create_controllers_neg(net, ds,gen_id, max_q_mvar) else: create_controllers_pos(net, ds,gen_id, max_q_mvar) # time steps to be calculated. time_steps= range(0, n_timesteps) # 4. Output wit OutputWriter ow = create_output_writer(net, time_steps,file_path) # 5. The main time series function run_timeseries(net, time_steps, continue_on_divergence=True) #print(net.res_line.loading_percent) def Windpark(): # Create an empty network net = pp.create_empty_network() # Create buses bus1 = pp.create_bus(net, name="Bus 1", vn_kv=220.0, type="b") bus2 = pp.create_bus(net, name="Bus 2", vn_kv=110.0, type="b") bus3 = pp.create_bus(net, name="Bus 3", vn_kv=110.0, type="b") bus4 = pp.create_bus(net, name="Bus 4", vn_kv=30.0, type="b") # Create a line between buses pp.create_line(net, from_bus=bus2, to_bus=bus3, length_km=70.0, std_type="N2XS(FL)2Y 1x120 RM/35 64/110 kV") # Create a load pp.create_load(net, bus=bus1, p_mw=50, q_mvar=10, name="load1") # Create a generator pp.create_gen(net,bus4, p_mw=62, q_mvar=1, vm_pu=1, ) pp.create_ext_grid(net, bus=bus1,vm_pu = 1, slack = True) # Create a transformer pp.create_transformer_from_parameters(net, hv_bus=bus3, lv_bus=bus4, name="Custom Transformer 1", sn_mva=63, vn_hv_kv=110, vn_lv_kv=30, vkr_percent=0.32, vk_percent=18.0, pfe_kw=22, i0_percent=0.04) pp.create_transformer(net, hv_bus=bus1, lv_bus=bus2, name="Transformer 2", std_type = "100 MVA 220/110 kV") return net def get_data(n_timesteps): profiles1 = pd.read_excel("C:/Users/ka29qewi/.vscode/BA_Beispiel/Windpark Daten/Wirkleistung_bearbeitet.xlsx", "PQ_Kurve", index_col=0) profiles = pd.DataFrame(profiles1) ds = DFData(profiles) return profiles, ds def create_controllers_pos(net, ds,gen_id, max_q_mvar): ConstControl(net,element='load', variable='p_mw', element_index=[0], data_source=ds, profile_name=["Wirkleistung"]) ConstControl(net,element='gen', variable='p_mw', element_index=[0], data_source=ds, profile_name=["Wirkleistung"]) ConstControl(net,element='load', variable='q_mvar', element_index=[0], data_source=ds, profile_name=["Blindleistung_pos"]) QLimitController(net,gen_id, max_q_mvar) def create_controllers_neg(net, ds,gen_id, max_q_mvar): ConstControl(net,element='load', variable='p_mw', element_index=[0], data_source=ds, profile_name=["Wirkleistung"]) ConstControl(net,element='gen', variable='p_mw', element_index=[0], data_source=ds, profile_name=["Wirkleistung"]) ConstControl(net,element='load', variable='q_mvar', element_index=[0], data_source=ds, profile_name=["Blindleistung_neg"]) QLimitController(net,gen_id, max_q_mvar) class QLimitController(control.basic_controller.Controller): def __init__(self,net,gen_id,max_q_mvar): super().__init__(net) # read generator atttriebutes from net self.gen_id = gen_id self.max_q_mvar = max_q_mvar self.q_mvar = net.gen.q_mvar.at[self.gen_id] self.applied=False # convergence check # Also remember that 'is_converged()' returns the boolean value of convergence: def is_converged(self, net): # check if controller already was applied return self.applied # In case the controller is not yet converged, the control step is executed. In the example it simply # adopts a new value according to the previously calculated target and writes back to the net. def control_step(self, net): # Call write_to_net and set the applied variable True self.write_to_net(net) self.applied = True # Also a first step we want our controller to be able to write its P and Q and state of charge values back to the # data structure net. def write_to_net(self, net): # write q and soc_percent to bus within the net net.gen.q_mvar.at[self.gen_id] = self.q_mvar def time_step(self,net, time): # Überprüfen die Blindleistung des Generators # print(self.gen_id) # print(self.q_mvar) # Wenn die Blindleistung das Maximum überschreitet, setzen sie auf das Maximum if self.q_mvar > self.max_q_mvar: self.q_mvar= self.max_q_mvar self.write_to_net(net) def create_output_writer(net, time_steps, file_path): ow = OutputWriter(net, time_steps, output_path=file_path, output_file_type=".xlsx", log_variables=list()) ow.log_variable('res_bus', 'vm_pu') ow.log_variable('res_bus', 'va_degree') ow.log_variable('res_bus', 'p_mw') ow.log_variable('res_bus', 'q_mvar') ow.log_variable('res_line', 'loading_percent') ow.log_variable('res_line', 'ql_mvar') ow.log_variable('res_line', 'pl_mw') ow.log_variable('res_line', 'p_from_mw') ow.log_variable('res_line', 'q_from_mvar') ow.log_variable('res_line', 'p_to_mw') #ow.log_variable('res_line', 'q_to_mw') ow.log_variable('res_gen', 'p_mw') ow.log_variable('res_gen', 'q_mvar') ow.log_variable('res_sgen', 'p_mw') ow.log_variable('res_sgen', 'q_mvar') ow.log_variable('res_ext_grid', 'p_mw') ow.log_variable('res_ext_grid', 'q_mvar') ow.log_variable('res_load', 'p_mw') ow.log_variable('res_load', 'q_mvar') ow.log_variable('res_trafo', 'loading_percent') ow.log_variable('res_trafo', 'p_hv_mw') ow.log_variable('res_trafo', 'p_lv_mw') ow.log_variable('res_trafo', 'q_hv_mvar') ow.log_variable('res_trafo', 'q_lv_mvar') #ow.log_variable('res_trafo', 'p_mw') #ow.log_variable('res_trafo', 'q_mvar') return ow data_sets = [ ("C:/Users/ka29qewi/.vscode/BA_Beispiel/Windpark Daten/PQ_Kurve/V_Einburch_ganz_netz/Blind_pos/gen", "kap"), ("C:/Users/ka29qewi/.vscode/BA_Beispiel/Windpark Daten/PQ_Kurve/V_Einburch_ganz_netz/Blind_neg/gen", "ind") ] for data_sets in data_sets: file_path, Blindleistungsfall = data_sets timeseries(file_path, Blindleistungsfall)