def parse_areas_data(circuit: MultiCircuit, data, logger: Logger): """ Parse Matpower / FUBM Matpower area data into GridCal :param circuit: MultiCircuit instance :param data: data dictionary :return: area index -> object dictionary """ area_idx_dict = dict() if 'areas' in data.keys(): table = data['areas'] if table.shape[0] > 0: # if there are areas declared, clean the default areas circuit.areas = list() for i in range(table.shape[0]): area_idx = int(table[i, 0]) area_ref_bus_idx = table[i, 1] a = Area(name='Area ' + str(area_idx), code=str(area_idx)) area_idx_dict[area_idx] = (a, area_ref_bus_idx) circuit.add_area(a) if i == 0: # set the default area circuit.default_area = circuit.areas[0] return area_idx_dict
def interpret_data_v1(circuit: MultiCircuit, data) -> MultiCircuit: """ Pass the loaded table-like data to the structures :param circuit: :param data: Data dictionary :return: """ circuit.clear() # time profile if 'master_time' in data.keys(): master_time_array = data['master_time'] else: master_time_array = None # areas area_idx_dict = dict() if 'areas' in data.keys(): table = data['areas'] if table.shape[0] > 0: # if there are areas declared, clean the default areas circuit.areas = list() for i in range(table.shape[0]): area_idx = int(table[i, 0]) area_ref_bus_idx = table[i, 1] a = Area(name='Area ' + str(area_idx), code=str(area_idx)) area_idx_dict[area_idx] = (a, area_ref_bus_idx) circuit.add_area(a) if i == 0: # set the default area circuit.default_area = circuit.areas[0] import GridCal.Engine.IO.matpower_bus_definitions as e # Buses table = data['bus'] n = table.shape[0] # load profiles if 'Lprof' in data.keys(): Pprof = data['Lprof'] Qprof = data['LprofQ'] are_load_prfiles = True print('There are load profiles') else: are_load_prfiles = False if 'bus_names' in data.keys(): names = data['bus_names'] else: names = ['bus ' + str(int(table[i, e.BUS_I])) for i in range(n)] # Buses bus_idx_dict = dict() for i in range(n): # Create bus area_idx = int(table[i, e.BUS_AREA]) bus_idx = int(table[i, e.BUS_I]) is_slack = False if area_idx in area_idx_dict.keys(): area, ref_idx = area_idx_dict[area_idx] if ref_idx == bus_idx: is_slack = True else: area = circuit.default_area code = str(bus_idx) bus = Bus(name=names[i], code=code, vnom=table[i, e.BASE_KV], vmax=table[i, e.VMAX], vmin=table[i, e.VMIN], area=area, is_slack=is_slack) # store the given bus index in relation to its real index in the table for later bus_idx_dict[table[i, e.BUS_I]] = i # determine if the bus is set as slack manually tpe = table[i, e.BUS_TYPE] if tpe == e.REF: bus.is_slack = True else: bus.is_slack = False # Add the load if table[i, e.PD] != 0 or table[i, e.QD] != 0: load = Load(P=table[i, e.PD], Q=table[i, e.QD]) load.bus = bus bus.loads.append(load) # Add the shunt if table[i, e.GS] != 0 or table[i, e.BS] != 0: shunt = Shunt(G=table[i, e.GS], B=table[i, e.BS]) shunt.bus = bus bus.shunts.append(shunt) # Add the bus to the circuit buses circuit.add_bus(bus) import GridCal.Engine.IO.matpower_gen_definitions as e # Generators table = data['gen'] n = len(table) # load profiles if 'Gprof' in data.keys(): Gprof = data['Gprof'] are_gen_prfiles = True print('There are gen profiles') else: are_gen_prfiles = False if 'gen_names' in data.keys(): names = data['gen_names'] else: names = ['gen ' + str(i) for i in range(n)] for i in range(len(table)): bus_idx = bus_idx_dict[int(table[i, e.GEN_BUS])] gen = Generator(name=names[i], active_power=table[i, e.PG], voltage_module=table[i, e.VG], Qmax=table[i, e.QMAX], Qmin=table[i, e.QMIN]) # Add the generator to the bus gen.bus = circuit.buses[bus_idx] circuit.buses[bus_idx].controlled_generators.append(gen) import GridCal.Engine.IO.matpower_branch_definitions as e # Branches table = data['branch'] n = len(table) if 'branch_names' in data.keys(): names = data['branch_names'] else: names = ['branch ' + str(i) for i in range(n)] for i in range(len(table)): f = circuit.buses[bus_idx_dict[int(table[i, e.F_BUS])]] t = circuit.buses[bus_idx_dict[int(table[i, e.T_BUS])]] if table.shape[1] == 37: # FUBM model # converter type (I, II, III) matpower_converter_mode = table[i, e.CONV_A] if matpower_converter_mode > 0: # it is a converter # set the from bus as a DC bus # this is by design of the matpower FUBM model, # if it is a converter, # the DC bus is always the "from" bus f.is_dc = True # determine the converter control mode Pfset = table[i, e.PF] Ptset = table[i, e.PT] Vac_set = table[i, e.VT_SET] Vdc_set = table[i, e.VF_SET] Qfset = table[i, e.QF] Qtset = table[i, e.QT] m = table[i, e.TAP] if table[i, e.TAP] > 0 else 1.0 if matpower_converter_mode == 1: if Pfset != 0.0: if Qtset != 0.0: control_mode = ConverterControlType.type_I_2 elif Vac_set != 0.0: control_mode = ConverterControlType.type_I_3 else: control_mode = ConverterControlType.type_I_1 else: control_mode = ConverterControlType.type_0_free elif matpower_converter_mode == 2: if Vac_set == 0.0: control_mode = ConverterControlType.type_II_4 else: control_mode = ConverterControlType.type_II_5 elif matpower_converter_mode == 3: control_mode = ConverterControlType.type_III_6 elif matpower_converter_mode == 4: control_mode = ConverterControlType.type_III_7 else: control_mode = ConverterControlType.type_0_free branch = VSC(bus_from=f, bus_to=t, name='VSC' + str(len(circuit.vsc_devices) + 1), active=bool(table[i, e.BR_STATUS]), r1=table[i, e.BR_R], x1=table[i, e.BR_X], m=m, m_max=table[i, e.MA_MAX], m_min=table[i, e.MA_MIN], theta=table[i, e.SHIFT], theta_max=np.deg2rad(table[i, e.ANGMAX]), theta_min=np.deg2rad(table[i, e.ANGMIN]), G0=table[i, e.GSW], Beq=table[i, e.BEQ], Beq_max=table[i, e.BEQ_MAX], Beq_min=table[i, e.BEQ_MIN], rate=max(table[i, [e.RATE_A, e.RATE_B, e.RATE_C]]), kdp=table[i, e.KDP], k=table[i, e.K2], control_mode=control_mode, Pfset=Pfset, Qfset=Qfset, Vac_set=Vac_set if Vac_set > 0 else 1.0, Vdc_set=Vdc_set if Vdc_set > 0 else 1.0, alpha1=table[i, e.ALPHA1], alpha2=table[i, e.ALPHA2], alpha3=table[i, e.ALPHA3]) circuit.add_vsc(branch) else: if f.Vnom != t.Vnom or (table[i, e.TAP] != 1.0 and table[i, e.TAP] != 0) or table[i, e.SHIFT] != 0.0: branch = Transformer2W(bus_from=f, bus_to=t, name=names[i], r=table[i, e.BR_R], x=table[i, e.BR_X], g=0, b=table[i, e.BR_B], rate=table[i, e.RATE_A], tap=table[i, e.TAP], shift_angle=table[i, e.SHIFT], active=bool(table[i, e.BR_STATUS])) circuit.add_transformer2w(branch) else: branch = Line(bus_from=f, bus_to=t, name=names[i], r=table[i, e.BR_R], x=table[i, e.BR_X], b=table[i, e.BR_B], rate=table[i, e.RATE_A], active=bool(table[i, e.BR_STATUS])) circuit.add_line(branch) else: if f.Vnom != t.Vnom or (table[i, e.TAP] != 1.0 and table[i, e.TAP] != 0) or table[i, e.SHIFT] != 0.0: branch = Transformer2W(bus_from=f, bus_to=t, name=names[i], r=table[i, e.BR_R], x=table[i, e.BR_X], g=0, b=table[i, e.BR_B], rate=table[i, e.RATE_A], tap=table[i, e.TAP], shift_angle=table[i, e.SHIFT], active=bool(table[i, e.BR_STATUS])) circuit.add_transformer2w(branch) else: branch = Line(bus_from=f, bus_to=t, name=names[i], r=table[i, e.BR_R], x=table[i, e.BR_X], b=table[i, e.BR_B], rate=table[i, e.RATE_A], active=bool(table[i, e.BR_STATUS])) circuit.add_line(branch) # convert normal lines into DC-lines if needed for line in circuit.lines: if line.bus_to.is_dc and line.bus_from.is_dc: dc_line = DcLine(bus_from=line.bus_from, bus_to=line.bus_to, name=line.name, active=line.active, rate=line.rate, r=line.R, active_prof=line.active_prof, rate_prof=line.rate_prof) # add device to the circuit circuit.add_dc_line(dc_line) # delete the line from the circuit circuit.delete_line(line) # add the profiles if master_time_array is not None: circuit.format_profiles(master_time_array) return circuit