def parse_branches_data(circuit: MultiCircuit, data, bus_idx_dict, logger: Logger): """ Parse Matpower / FUBM Matpower branch data into GridCal :param circuit: MultiCircuit instance :param data: data dictionary :param bus_idx_dict: bus index -> object dictionary :return: Nothing """ # Branches table = data['branch'] n = len(table) if table.shape[1] == 37: # FUBM model logger.add_info('It is a FUBM model') 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, matpower_branches.F_BUS])]] t = circuit.buses[bus_idx_dict[int(table[i, matpower_branches.T_BUS])]] if table.shape[1] == 37: # FUBM model # converter type (I, II, III) matpower_converter_mode = table[i, matpower_branches.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, matpower_branches.PF] Ptset = table[i, matpower_branches.PT] Vac_set = table[i, matpower_branches.VT_SET] Vdc_set = table[i, matpower_branches.VF_SET] Qfset = table[i, matpower_branches.QF] Qtset = table[i, matpower_branches.QT] m = table[i, matpower_branches. TAP] if table[i, matpower_branches.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 rate = max(table[i, [ matpower_branches.RATE_A, matpower_branches. RATE_B, matpower_branches.RATE_C ]]) branch = VSC( bus_from=f, bus_to=t, name='VSC' + str(len(circuit.vsc_devices) + 1), active=bool(table[i, matpower_branches.BR_STATUS]), r1=table[i, matpower_branches.BR_R], x1=table[i, matpower_branches.BR_X], m=m, m_max=table[i, matpower_branches.MA_MAX], m_min=table[i, matpower_branches.MA_MIN], theta=table[i, matpower_branches.SHIFT], theta_max=np.deg2rad(table[i, matpower_branches.ANGMAX]), theta_min=np.deg2rad(table[i, matpower_branches.ANGMIN]), G0=table[i, matpower_branches.GSW], Beq=table[i, matpower_branches.BEQ], Beq_max=table[i, matpower_branches.BEQ_MAX], Beq_min=table[i, matpower_branches.BEQ_MIN], rate=rate, kdp=table[i, matpower_branches.KDP], k=table[i, matpower_branches.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, matpower_branches.ALPHA1], alpha2=table[i, matpower_branches.ALPHA2], alpha3=table[i, matpower_branches.ALPHA3]) circuit.add_vsc(branch) logger.add_info('Branch as converter', 'Branch {}'.format(str(i + 1))) else: if f.Vnom != t.Vnom or ( table[i, matpower_branches.TAP] != 1.0 and table[i, matpower_branches.TAP] != 0 ) or table[i, matpower_branches.SHIFT] != 0.0: branch = Transformer2W( bus_from=f, bus_to=t, name=names[i], r=table[i, matpower_branches.BR_R], x=table[i, matpower_branches.BR_X], g=0, b=table[i, matpower_branches.BR_B], rate=table[i, matpower_branches.RATE_A], tap=table[i, matpower_branches.TAP], shift_angle=table[i, matpower_branches.SHIFT], active=bool(table[i, matpower_branches.BR_STATUS])) circuit.add_transformer2w(branch) logger.add_info('Branch as 2w transformer', 'Branch {}'.format(str(i + 1))) else: branch = Line(bus_from=f, bus_to=t, name=names[i], r=table[i, matpower_branches.BR_R], x=table[i, matpower_branches.BR_X], b=table[i, matpower_branches.BR_B], rate=table[i, matpower_branches.RATE_A], active=bool( table[i, matpower_branches.BR_STATUS])) circuit.add_line(branch) logger.add_info('Branch as line', 'Branch {}'.format(str(i + 1))) else: if f.Vnom != t.Vnom or (table[i, matpower_branches.TAP] != 1.0 and table[i, matpower_branches.TAP] != 0 ) or table[i, matpower_branches.SHIFT] != 0.0: branch = Transformer2W( bus_from=f, bus_to=t, name=names[i], r=table[i, matpower_branches.BR_R], x=table[i, matpower_branches.BR_X], g=0, b=table[i, matpower_branches.BR_B], rate=table[i, matpower_branches.RATE_A], tap=table[i, matpower_branches.TAP], shift_angle=table[i, matpower_branches.SHIFT], active=bool(table[i, matpower_branches.BR_STATUS])) circuit.add_transformer2w(branch) logger.add_info('Branch as 2w transformer', 'Branch {}'.format(str(i + 1))) else: branch = Line(bus_from=f, bus_to=t, name=names[i], r=table[i, matpower_branches.BR_R], x=table[i, matpower_branches.BR_X], b=table[i, matpower_branches.BR_B], rate=table[i, matpower_branches.RATE_A], active=bool(table[i, matpower_branches.BR_STATUS])) circuit.add_line(branch) logger.add_info('Branch as line', 'Branch {}'.format(str(i + 1))) # 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) logger.add_info('Converted to DC line', line.name)
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 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(i+1) for i in range(n)] # Buses bus_idx_dict = dict() for i in range(n): # Create bus bus = Bus(name=names[i], vnom=table[i, e.BASE_KV], vmax=table[i, e.VMAX], vmin=table[i, e.VMIN]) # 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 matpower_mode = table[i, e.CONV_A] if matpower_mode > 0: # it is a converter # 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 Pset = table[i, e.PF] Vac_set = table[i, e.VT_SET] Vdc_set = table[i, e.VF_SET] Qset = table[i, e.QF] m = table[i, e.TAP] if table[i, e.TAP] > 0 else 1.0 if matpower_mode == 1: if Pset != 0.0: control_mode = ConverterControlType.type_1_pf elif Qset != 0.0: control_mode = ConverterControlType.type_1_qf elif Vac_set != 0.0: control_mode = ConverterControlType.type_1_vac else: control_mode = ConverterControlType.type_1_free elif matpower_mode == 2: if Pset == 0.0: control_mode = ConverterControlType.type_2_vdc else: control_mode = ConverterControlType.type_2_vdc_pf elif matpower_mode == 3: control_mode = ConverterControlType.type_3 elif matpower_mode == 4: control_mode = ConverterControlType.type_4 else: control_mode = ConverterControlType.type_1_free branch = VSC(bus_from=f, bus_to=t, name='VSC' + str(len(circuit.vsc_converters) + 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=table[i, e.RATE_A], kdp=table[i, e.KDP], control_mode=control_mode, Pset=Pset, Qset=Qset, Vac_set=Vac_set, Vdc_set=Vdc_set, 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