Example #1
0
def test_demo_5_node(root_path=ROOT_PATH):
    np.core.arrayprint.set_printoptions(precision=4)

    grid = MultiCircuit()

    # Add buses
    bus1 = Bus('Bus 1', vnom=20)
    grid.add_bus(bus1)
    gen1 = Generator('Slack Generator', voltage_module=1.0)
    grid.add_generator(bus1, gen1)

    bus2 = Bus('Bus 2', vnom=20)
    grid.add_bus(bus2)
    grid.add_load(bus2, Load('load 2', P=40, Q=20))

    bus3 = Bus('Bus 3', vnom=20)
    grid.add_bus(bus3)
    grid.add_load(bus3, Load('load 3', P=25, Q=15))

    bus4 = Bus('Bus 4', vnom=20)
    grid.add_bus(bus4)
    grid.add_load(bus4, Load('load 4', P=40, Q=20))

    bus5 = Bus('Bus 5', vnom=20)
    grid.add_bus(bus5)
    grid.add_load(bus5, Load('load 5', P=50, Q=20))

    # add branches (Lines in this case)
    grid.add_line(Line(bus1, bus2, 'line 1-2', r=0.05, x=0.11, b=0.02))
    grid.add_line(Line(bus1, bus3, 'line 1-3', r=0.05, x=0.11, b=0.02))
    grid.add_line(Line(bus1, bus5, 'line 1-5', r=0.03, x=0.08, b=0.02))
    grid.add_line(Line(bus2, bus3, 'line 2-3', r=0.04, x=0.09, b=0.02))
    grid.add_line(Line(bus2, bus5, 'line 2-5', r=0.04, x=0.09, b=0.02))
    grid.add_line(Line(bus3, bus4, 'line 3-4', r=0.06, x=0.13, b=0.03))
    grid.add_line(Line(bus4, bus5, 'line 4-5', r=0.04, x=0.09, b=0.02))
    # grid.plot_graph()
    print('\n\n', grid.name)

    FileSave(grid, 'demo_5_node.json').save()

    options = PowerFlowOptions(SolverType.NR, verbose=False)

    power_flow = PowerFlowDriver(grid, options)
    power_flow.run()

    print_power_flow_results(power_flow=power_flow)
    v = np.array([1., 0.9553, 0.9548, 0.9334, 0.9534])
    all_ok = np.isclose(np.abs(power_flow.results.voltage), v, atol=1e-3)
    return all_ok
Example #2
0
    def parse_ac_line_segment(self, cim: CIMCircuit, circuit: MultiCircuit,
                              busbar_dict):
        """

        :param cim:
        :param circuit:
        :param busbar_dict:
        :return:
        """

        if 'ACLineSegment' in cim.elements_by_type.keys():
            for elm in cim.elements_by_type['ACLineSegment']:

                b1, b2 = elm.get_buses()

                B1, B2 = try_buses(b1, b2, busbar_dict)

                if B1 is not None and B2 is not None:
                    R, X, G, B = elm.get_pu_values()
                    rate = elm.get_rate()

                    # create AcLineSegment (Line)
                    line = gcdev.Line(idtag=elm.uuid,
                                      bus_from=B1,
                                      bus_to=B2,
                                      name=str(elm.name),
                                      r=R,
                                      x=X,
                                      b=B,
                                      rate=rate,
                                      active=True,
                                      mttf=0,
                                      mttr=0)

                    circuit.add_line(line)
                else:
                    self.logger.add_error('Bus not found', elm.rfid)
Example #3
0
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)
Example #4
0
def parse_json_data_v2(data: dict, logger: Logger):
    """
    New Json parser
    :param data:
    :param logger:
    :return:
    """
    devices = data['devices']
    profiles = data['profiles']

    if DeviceType.CircuitDevice.value in devices.keys():

        dta = devices[DeviceType.CircuitDevice.value]
        circuit = MultiCircuit(name=str(dta['name']),
                               Sbase=float(dta['sbase']),
                               fbase=float(dta['fbase']),
                               idtag=str(dta['id']))

        jcircuit = devices["Circuit"]
        circuit.Sbase = jcircuit["sbase"]

        # Countries
        country_dict = dict()
        if 'Country' in devices.keys():
            elms = devices["Country"]
            for jentry in elms:
                elm = Country(idtag=str(jentry['id']),
                              code=str(jentry['code']),
                              name=str(jentry['name']))
                circuit.countries.append(elm)
                country_dict[elm.idtag] = elm
        else:
            elm = Country(idtag=None, code='Default', name='Default')
            circuit.countries.append(elm)

        # Areas
        areas_dict = dict()
        if 'Area' in devices.keys():
            elms = devices["Area"]
            for jentry in elms:
                elm = Area(idtag=str(jentry['id']),
                           code=str(jentry['code']),
                           name=str(jentry['name']))
                circuit.areas.append(elm)
                areas_dict[elm.idtag] = elm
        else:
            elm = Area(idtag=None, code='Default', name='Default')
            circuit.areas.append(elm)

        # Zones
        zones_dict = dict()
        if 'Zone' in devices.keys():
            elms = devices["Zone"]
            for jentry in elms:
                elm = Zone(idtag=str(jentry['id']),
                           code=str(jentry['code']),
                           name=str(jentry['name']))
                circuit.zones.append(elm)
                zones_dict[elm.idtag] = elm
        else:
            elm = Zone(idtag=None, code='Default', name='Default')
            circuit.zones.append(elm)

        # Substations
        substations_dict = dict()
        if 'Substation' in devices.keys():
            elms = devices["Substation"]
            for jentry in elms:
                elm = Substation(idtag=str(jentry['id']),
                                 code=str(jentry['code']),
                                 name=str(jentry['name']))
                circuit.substations.append(elm)
                substations_dict[elm.idtag] = elm
        else:
            elm = Substation(idtag=None, code='Default', name='Default')
            circuit.substations.append(elm)

        # buses
        bus_dict = dict()
        if 'Bus' in devices.keys():
            buses = devices["Bus"]
            for jentry in buses:

                area_id = str(jentry['area']) if 'area' in jentry.keys() else ''
                zone_id = str(jentry['zone']) if 'zone' in jentry.keys() else ''
                substation_id = str(jentry['substation']) if 'substation' in jentry.keys() else ''
                country_id = str(jentry['country']) if 'country' in jentry.keys() else ''

                if area_id in areas_dict.keys():
                    area = areas_dict[area_id]
                else:
                    area = circuit.areas[0]

                if zone_id in zones_dict.keys():
                    zone = zones_dict[zone_id]
                else:
                    zone = circuit.zones[0]

                if substation_id in substations_dict.keys():
                    substation = substations_dict[substation_id]
                else:
                    substation = circuit.substations[0]

                if country_id in country_dict.keys():
                    country = country_dict[country_id]
                else:
                    country = circuit.countries[0]

                bus = Bus(name=str(jentry['name']),
                          idtag=str(jentry['id']),
                          vnom=float(jentry['vnom']),
                          vmin=float(jentry['vmin']),
                          vmax=float(jentry['vmax']),
                          r_fault=float(jentry['rf']),
                          x_fault=float(jentry['xf']),
                          xpos=float(jentry['x']),
                          ypos=float(jentry['y']),
                          height=float(jentry['h']),
                          width=float(jentry['w']),
                          active=bool(jentry['active']),
                          is_slack=bool(jentry['is_slack']),
                          area=area,
                          zone=zone,
                          substation=substation,
                          country=country,
                          longitude=float(jentry['lon']),
                          latitude=float(jentry['lat']))

                bus_dict[jentry['id']] = bus
                circuit.add_bus(bus)

        if 'Generator' in devices.keys():
            generators = devices["Generator"]
            for jentry in generators:
                gen = Generator(name=str(jentry['name']),
                                idtag=str(jentry['id']),
                                active_power=float(jentry['p']),
                                power_factor=float(jentry['pf']),
                                voltage_module=float(jentry['vset']),
                                is_controlled=bool(jentry['is_controlled']),
                                Qmin=float(jentry['qmin']),
                                Qmax=float(jentry['qmax']),
                                Snom=float(jentry['snom']),
                                active=bool(jentry['active']),
                                p_min=float(jentry['pmin']),
                                p_max=float(jentry['pmax']),
                                op_cost=float(jentry['cost']),
                                )
                gen.bus = bus_dict[jentry['bus']]
                circuit.add_generator(gen.bus, gen)

        if 'Battery' in devices.keys():
            batteries = devices["Battery"]
            for jentry in batteries:
                gen = Battery(name=str(jentry['name']),
                              idtag=str(jentry['id']),
                              active_power=float(jentry['p']),
                              power_factor=float(jentry['pf']),
                              voltage_module=float(jentry['vset']),
                              is_controlled=bool(jentry['is_controlled']),
                              Qmin=float(jentry['qmin']),
                              Qmax=float(jentry['qmax']),
                              Snom=float(jentry['snom']),
                              active=bool(jentry['active']),
                              p_min=float(jentry['pmin']),
                              p_max=float(jentry['pmax']),
                              op_cost=float(jentry['cost']),
                              )
                gen.bus = bus_dict[jentry['bus']]
                circuit.add_battery(gen.bus, gen)

        if 'Load' in devices.keys():
            loads = devices["Load"]
            for jentry in loads:
                elm = Load(name=str(jentry['name']),
                           idtag=str(jentry['id']),
                           P=float(jentry['p']),
                           Q=float(jentry['q']),
                           active=bool(jentry['active']))
                elm.bus = bus_dict[jentry['bus']]
                circuit.add_load(elm.bus, elm)

        if "Shunt" in devices.keys():
            shunts = devices["Shunt"]
            for jentry in shunts:
                elm = Shunt(name=str(jentry['name']),
                            idtag=str(jentry['id']),
                            G=float(jentry['g']),
                            B=float(jentry['b']),
                            active=bool(jentry['active']))
                elm.bus = bus_dict[jentry['bus']]
                circuit.add_shunt(elm.bus, elm)

        if "Line" in devices.keys():
            lines = devices["Line"]
            for entry in lines:
                elm = Line(bus_from=bus_dict[entry['bus_from']],
                           bus_to=bus_dict[entry['bus_to']],
                           name=str(entry['name']),
                           idtag=str(entry['id']),
                           r=float(entry['r']),
                           x=float(entry['x']),
                           b=float(entry['b']),
                           rate=float(entry['rate']),
                           active=entry['active'],
                           length=float(entry['length']),
                           )
                circuit.add_line(elm)

        if "Transformer" in devices.keys() or "Transformer2w" in devices.keys():

            if "Transformer" in devices.keys():
                transformers = devices["Transformer"]
            elif "Transformer2w" in devices.keys():
                transformers = devices["Transformer2w"]
            else:
                raise Exception('Transformer key not found')

            for entry in transformers:
                elm = Transformer2W(bus_from=bus_dict[entry['bus_from']],
                                    bus_to=bus_dict[entry['bus_to']],
                                    name=str(entry['name']),
                                    idtag=str(entry['id']),
                                    r=float(entry['r']),
                                    x=float(entry['x']),
                                    g=float(entry['g']),
                                    b=float(entry['b']),
                                    rate=float(entry['rate']),
                                    active=bool(entry['active']),
                                    tap=float(entry['tap_module']),
                                    shift_angle=float(entry['tap_angle']),
                                    )
                circuit.add_transformer2w(elm)

        if "VSC" in devices.keys():
            vsc = devices["VSC"]

            # TODO: call correct_buses_connection()

        if "HVDC Line" in devices.keys():
            hvdc = devices["HVDC Line"]

        return circuit

    else:
        logger.add('The Json structure does not have a Circuit inside the devices!')
        return MultiCircuit()
Example #5
0
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
def test_tolerance_lf_higher():
    test_name = "test_tolerance_lf_higher"
    grid = MultiCircuit(name=test_name)
    grid.Sbase = Sbase
    grid.time_profile = None
    grid.logger = Logger()

    # Create buses
    Bus0 = Bus(name="Bus0", vnom=25, is_slack=True)
    Bus1 = Bus(name="Bus1", vnom=25)

    grid.add_bus(Bus0)
    grid.add_bus(Bus1)

    # Create load
    grid.add_load(Bus1, Load(name="Load0", P=1.0, Q=0.4))

    # Create slack bus
    grid.add_generator(Bus0, Generator(name="Utility"))

    # Create cable (r and x should be in pu)
    grid.add_line(Line(bus_from=Bus0,
                       bus_to=Bus1,
                       name="Cable1",
                       r=0.01,
                       x=0.05,
                       tolerance=10))

    # Run non-linear power flow
    options = PowerFlowOptions(verbose=True,
                               branch_impedance_tolerance_mode=BranchImpedanceMode.Upper)

    power_flow = PowerFlowDriver(grid, options)
    power_flow.run()

    # Check solution
    approx_losses = round(1000 * power_flow.results.losses[0], 3)
    solution = complex(0.128, 0.58)  # Expected solution from GridCal
    # Tested on ETAP 16.1.0 and pandapower

    print("\n=================================================================")
    print(f"Test: {test_name}")
    print("=================================================================\n")
    print(f"Results:  {approx_losses}")
    print(f"Solution: {solution}")
    print()

    print("Buses:")
    for i, b in enumerate(grid.buses):
        print(f" - bus[{i}]: {b}")
    print()

    print("Branches:")
    branches = grid.get_branches()
    for b in branches:
        print(f" - {b}:")
        print(f"   R = {round(b.R, 4)} pu")
        print(f"   X = {round(b.X, 4)} pu")
        print(f"   X/R = {round(b.X/b.R, 2)}")
    print()

    print("Voltages:")
    for i in range(len(grid.buses)):
        print(
            f" - {grid.buses[i]}: voltage={round(power_flow.results.voltage[i], 3)} pu"
        )
    print()

    print("Losses:")
    for i in range(len(branches)):
        print(
            f" - {branches[i]}: losses={round(power_flow.results.losses[i], 3)} MVA"
        )
    print()

    print("Loadings (power):")
    for i in range(len(branches)):
        print(
            f" - {branches[i]}: loading={round(power_flow.results.Sf[i], 3)} MVA"
        )
    print()

    print("Loadings (current):")
    for i in range(len(branches)):
        print(
            f" - {branches[i]}: loading={round(power_flow.results.If[i], 3)} pu"
        )
    print()

    assert approx_losses == solution
Example #7
0
class GridGeneratorGUI(QDialog):
    def __init__(
        self,
        parent=None,
    ):
        """

        :param parent:
        """
        QDialog.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle('Grid Generator')

        self.g = RpgAlgorithm()
        self.circuit = MultiCircuit()
        self.applied = False

        self.ui.applyButton.clicked.connect(self.apply)
        self.ui.previewButton.clicked.connect(self.preview)

    def msg(self, text, title="Warning"):
        """
        Message box
        :param text: Text to display
        :param title: Name of the window
        """
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(text)
        # msg.setInformativeText("This is additional information")
        msg.setWindowTitle(title)
        # msg.setDetailedText("The details are as follows:")
        msg.setStandardButtons(QMessageBox.Ok)
        retval = msg.exec_()

    def fill_graph(self):
        """
        # set desired parameters and perform algorithm
        :return:
        """
        self.g = RpgAlgorithm()

        n = self.ui.nodes_spinBox.value()
        n0 = 10
        r = self.ui.ratio_SpinBox.value()
        if n0 >= n:
            n0 = n - 1

        self.g.set_params(n=n, n0=n0, r=r)
        self.g.initialise()
        self.g.grow()

    def preview(self):
        """

        :return:
        """
        self.fill_graph()
        G = nx.Graph(self.g.edges)
        pos = {
            i: (self.g.lat[i], self.g.lon[i])
            for i in range(self.g.added_nodes)
        }

        self.ui.plotwidget.clear()
        nx.draw(G,
                ax=self.ui.plotwidget.get_axis(),
                pos=pos,
                with_labels=True,
                node_color='lightblue')
        self.ui.plotwidget.redraw()

    def apply(self):
        """
        Create graph, then the circuit and close
        :return: Nothing
        """
        self.fill_graph()

        self.circuit = MultiCircuit()

        explosion_factor = 10000.0

        # number of nodes
        n = self.g.added_nodes

        # assign the load and generation buses
        genbus = self.ui.generation_nodes_SpinBox.value()
        loadbus = self.ui.load_nodes_SpinBox.value()

        if (genbus + loadbus) > 100:
            s = genbus + loadbus
            genbus /= s
            loadbus /= s

        gen_buses_num = int(np.floor(n * genbus / 100))
        load_buses_num = int(np.floor(n * loadbus / 100))

        rng = default_rng()
        numbers = rng.choice(n,
                             size=gen_buses_num + load_buses_num,
                             replace=False)

        gen_buses = numbers[:gen_buses_num]
        load_buses = numbers[gen_buses_num:]

        pmax = self.ui.power_SpinBox.value()

        # generate buses
        bus_dict = dict()
        for i in range(n):

            bus = Bus(name='Bus ' + str(i + 1),
                      xpos=self.g.lat[i] * explosion_factor,
                      ypos=-self.g.lon[i] * explosion_factor)

            bus_dict[i] = bus

            self.circuit.add_bus(bus)

        # generate loads
        factor = np.random.random(load_buses_num)
        factor /= factor.sum()
        pf = self.ui.power_factor_SpinBox.value()
        for k, i in enumerate(load_buses):
            bus = bus_dict[i]
            p = pmax * factor[k]
            q = p * pf
            load = Load(name='Load@bus' + str(i + 1), P=p, Q=q)
            self.circuit.add_load(bus, load)

        # generate generators
        factor = np.random.random(gen_buses_num)
        factor /= factor.sum()
        for k, i in enumerate(gen_buses):
            bus = bus_dict[i]
            gen = Generator(name='Generator@bus' + str(i + 1),
                            active_power=pmax * factor[k])
            self.circuit.add_generator(bus, gen)

        # generate lines
        r = self.ui.r_SpinBox.value()
        x = self.ui.x_SpinBox.value()
        b = self.ui.b_SpinBox.value()

        for f, t in self.g.edges:
            dx = (self.g.lat[f] - self.g.lat[t]) * explosion_factor
            dy = (self.g.lon[f] - self.g.lon[t]) * explosion_factor
            m = np.sqrt(
                dx * dx +
                dy * dy) / 10.0  # divided by 10 to have more meaningful values

            b1 = bus_dict[f]
            b2 = bus_dict[t]
            lne = Line(bus_from=b1,
                       bus_to=b2,
                       name='Line ' + str(f) + '-' + str(t),
                       r=r * m,
                       x=x * m,
                       b=b * m,
                       length=m)
            self.circuit.add_line(lne)

        # quit
        self.applied = True
        self.close()
Example #8
0
def parse_json_data_v2(data: dict, logger: Logger):
    """
    New Json parser
    :param data:
    :param logger:
    :return:
    """
    devices = data['devices']
    profiles = data['profiles']

    if DeviceType.CircuitDevice.value in devices.keys():

        dta = devices[DeviceType.CircuitDevice.value]
        circuit = MultiCircuit(name=str(dta['name']),
                               Sbase=float(dta['sbase']),
                               fbase=float(dta['fbase']),
                               idtag=str(dta['id']))

        jcircuit = devices["Circuit"]
        circuit.Sbase = jcircuit["sbase"]

        bus_dict = dict()

        if 'Bus' in devices.keys():
            buses = devices["Bus"]
            for jentry in buses:
                bus = Bus(name=str(jentry['name']),
                          idtag=str(jentry['id']),
                          vnom=float(jentry['vnom']),
                          vmin=float(jentry['vmin']),
                          vmax=float(jentry['vmax']),
                          r_fault=float(jentry['rf']),
                          x_fault=float(jentry['xf']),
                          xpos=float(jentry['x']),
                          ypos=float(jentry['y']),
                          height=float(jentry['h']),
                          width=float(jentry['w']),
                          active=bool(jentry['active']),
                          is_slack=bool(jentry['is_slack']),
                          # is_dc=jbus['id'],
                          area=jentry['area'],
                          zone=jentry['zone'],
                          substation=jentry['substation'],
                          # country=jbus['id'],
                          longitude=float(jentry['lon']),
                          latitude=float(jentry['lat']) )

                bus_dict[jentry['id']] = bus
                circuit.add_bus(bus)

        if 'Generator' in devices.keys():
            generators = devices["Generator"]
            for jentry in generators:
                gen = Generator(name=str(jentry['name']),
                                idtag=str(jentry['id']),
                                active_power=float(jentry['p']),
                                power_factor=float(jentry['pf']),
                                voltage_module=float(jentry['vset']),
                                is_controlled=bool(jentry['is_controlled']),
                                Qmin=float(jentry['qmin']),
                                Qmax=float(jentry['qmax']),
                                Snom=float(jentry['snom']),
                                # power_prof=jgen['name'],
                                # power_factor_prof=jgen['name'],
                                # vset_prof=jgen['name'],
                                # Cost_prof=jgen['name'],
                                active=bool(jentry['active']),
                                p_min=float(jentry['pmin']),
                                p_max=float(jentry['pmax']),
                                op_cost=float(jentry['cost']),
                                # Sbase=jgen['name'],
                                # enabled_dispatch=jgen['name'],
                                # mttf=jgen['name'],
                                # mttr=jgen['name']
                                )
                gen.bus = bus_dict[jentry['bus']]
                circuit.add_generator(gen.bus, gen)

        if 'Battery' in devices.keys():
            batteries = devices["Battery"]
            for jentry in batteries:
                gen = Battery(name=str(jentry['name']),
                              idtag=str(jentry['id']),
                              active_power=float(jentry['p']),
                              power_factor=float(jentry['pf']),
                              voltage_module=float(jentry['vset']),
                              is_controlled=bool(jentry['is_controlled']),
                              Qmin=float(jentry['qmin']),
                              Qmax=float(jentry['qmax']),
                              Snom=float(jentry['snom']),
                              # power_prof=jgen['name'],
                              # power_factor_prof=jgen['name'],
                              # vset_prof=jgen['name'],
                              # Cost_prof=jgen['name'],
                              active=bool(jentry['active']),
                              p_min=float(jentry['pmin']),
                              p_max=float(jentry['pmax']),
                              op_cost=float(jentry['cost']),
                              # Sbase=jgen['name'],
                              # enabled_dispatch=jgen['name'],
                              # mttf=jgen['name'],
                              # mttr=jgen['name']
                              )
                gen.bus = bus_dict[jentry['bus']]
                circuit.add_battery(gen.bus, gen)

        if 'Load' in devices.keys():
            loads = devices["Load"]
            for jentry in loads:
                elm = Load(name=str(jentry['name']),
                           idtag=str(jentry['id']),
                           # G: float = 0.0,
                           # B: float = 0.0,
                           # Ir: float = 0.0,
                           # Ii: float = 0.0,
                           P=float(jentry['p']),
                           Q=float(jentry['q']),
                           # cost=jentry['cost'],
                           # G_prof: Any = None,
                           # B_prof: Any = None,
                           # Ir_prof: Any = None,
                           # Ii_prof: Any = None,
                           # P_prof: Any = None,
                           # Q_prof: Any = None,
                           active=bool(jentry['active']))
                elm.bus = bus_dict[jentry['bus']]
                circuit.add_load(elm.bus, elm)

        if "Shunt" in devices.keys():
            shunts = devices["Shunt"]
            for jentry in shunts:
                elm = Shunt(name=str(jentry['name']),
                            idtag=str(jentry['id']),
                            G=float(jentry['g']),
                            B=float(jentry['b']),
                            # G_prof: Any = None,
                            # B_prof: Any = None,
                            active=bool(jentry['active']))
                elm.bus = bus_dict[jentry['bus']]
                circuit.add_shunt(elm.bus, elm)

        if "Line" in devices.keys():
            lines = devices["Line"]
            for entry in lines:
                elm = Line(bus_from=bus_dict[entry['bus_from']],
                           bus_to=bus_dict[entry['bus_to']],
                           name=str(entry['name']),
                           idtag=str(entry['id']),
                           r=float(entry['r']),
                           x=float(entry['x']),
                           b=float(entry['b']),
                           rate=float(entry['rate']),
                           active=entry['active'],
                           # tolerance: int = 0,
                           # cost: float = 0.0,
                           # mttf: int = 0,
                           # mttr: int = 0,
                           # r_fault: float = 0.0,
                           # x_fault: float = 0.0,
                           # fault_pos: float = 0.5,
                           length=float(entry['length']),
                           # temp_base: int = 20,
                           # temp_oper: int = 20,
                           # alpha: float = 0.00330,
                           # template: LineTemplate = LineTemplate(),
                           # rate_prof: Any = None,
                           # Cost_prof: Any = None,
                           # active_prof: Any = None,
                           # temp_oper_prof: Any = None
                           )
                circuit.add_line(elm)

        if "Transformer" in devices.keys():
            transformers = devices["Transformer"]
            for entry in transformers:
                elm = Transformer2W(bus_from=bus_dict[entry['bus_from']],
                                    bus_to=bus_dict[entry['bus_to']],
                                    name=str(entry['name']),
                                    idtag=str(entry['id']),
                                    r=float(entry['r']),
                                    x=float(entry['x']),
                                    g=float(entry['g']),
                                    b=float(entry['b']),
                                    rate=float(entry['rate']),
                                    active=bool(entry['active']),
                                    tap=float(entry['tap_module']),
                                    shift_angle=float(entry['tap_angle']),
                                    # tolerance: int = 0,
                                    # cost: float = 0.0,
                                    # mttf: int = 0,
                                    # mttr: int = 0,
                                    # r_fault: float = 0.0,
                                    # x_fault: float = 0.0,
                                    # fault_pos: float = 0.5,
                                    # temp_base: int = 20,
                                    # temp_oper: int = 20,
                                    # alpha: float = 0.00330,
                                    # template: LineTemplate = LineTemplate(),
                                    # rate_prof: Any = None,
                                    # Cost_prof: Any = None,
                                    # active_prof: Any = None,
                                    # temp_oper_prof: Any = None
                                    )
                circuit.add_transformer2w(elm)

        if "VSC" in devices.keys():
            vsc = devices["VSC"]

        if "HVDC Line" in devices.keys():
            hvdc = devices["HVDC Line"]

        return circuit

    else:
        logger.add('The Json structure does not have a Circuit inside the devices!')
        return MultiCircuit()
Example #9
0
def test_corr_line_losses():
    test_name = "test_corr_line_losses"

    grid = MultiCircuit(name=test_name)
    grid.Sbase = Sbase
    grid.time_profile = None
    grid.logger = Logger()

    # Create buses
    Bus0 = Bus(name="Bus0", vnom=10, is_slack=True)
    Bus1 = Bus(name="Bus1", vnom=10)

    grid.add_bus(Bus0)
    grid.add_bus(Bus1)

    # Create load
    grid.add_load(Bus1, Load(name="Load0", P=1.0, Q=0.4))

    # Create slack bus
    grid.add_generator(Bus0, Generator(name="Utility"))

    # Create cable
    cable = Line(
        bus_from=Bus0,
        bus_to=Bus1,
        name="Cable0",
        r=0.784,
        x=0.174,
        temp_base=20,  # °C
        temp_oper=90,  # °C
        alpha=0.00323)  # Copper

    grid.add_line(cable)

    options = PowerFlowOptions(verbose=True, apply_temperature_correction=True)

    power_flow = PowerFlowDriver(grid, options)
    power_flow.run()

    # Check solution
    approx_losses = round(power_flow.results.losses[0], 3)
    solution = complex(0.011, 0.002)  # Expected solution from GridCal
    # Tested on ETAP 16.1.0

    print(
        "\n=================================================================")
    print(f"Test: {test_name}")
    print(
        "=================================================================\n")
    print(f"Results:  {approx_losses}")
    print(f"Solution: {solution}")
    print()

    print("Buses:")
    for i, b in enumerate(grid.buses):
        print(f" - bus[{i}]: {b}")
    print()

    print("Branches:")
    for b in grid.lines:
        print(f" - {b}:")
        print(f"   R = {round(b.R, 4)} pu")
        print(f"   X = {round(b.X, 4)} pu")
        print(f"   X/R = {round(b.X/b.R, 2)}")
    print()

    print("Voltages:")
    for i in range(len(grid.buses)):
        print(
            f" - {grid.buses[i]}: voltage={round(power_flow.results.voltage[i], 3)} pu"
        )
    print()

    print("Losses:")
    for i in range(len(grid.lines)):
        print(
            f" - {grid.lines[i]}: losses={round(power_flow.results.losses[i], 3)} MVA"
        )
    print()

    print("Loadings (power):")
    for i in range(len(grid.lines)):
        print(
            f" - {grid.lines[i]}: loading={round(power_flow.results.Sf[i], 3)} MVA"
        )
    print()

    print("Loadings (current):")
    for i in range(len(grid.lines)):
        print(
            f" - {grid.lines[i]}: loading={round(power_flow.results.If[i], 3)} pu"
        )
    print()

    assert approx_losses == solution
Example #10
0
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']
    buses_dict = dict()
    n = len(table)

    # 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) 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 f.Vnom != t.Vnom or table[i, e.TAP] != 1.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)

    # add the profiles
    if master_time_array is not None:

        circuit.format_profiles(master_time_array)
    print('Interpreted.')
    return circuit