예제 #1
0
    def get_raw_circuit(self, add_generation,
                        add_storage) -> CalculationInputs:
        """

        :param add_generation:
        :param add_storage:
        :return:
        """
        # Declare object to store the calculation inputs
        circuit = CalculationInputs(self.nbus, self.nbr, self.ntime,
                                    self.n_batt, self.n_ctrl_gen)

        # branches
        circuit.branch_rates = self.br_rates
        circuit.F = self.F
        circuit.T = self.T
        circuit.tap_f = self.tap_f
        circuit.tap_t = self.tap_t
        circuit.bus_names = self.bus_names
        circuit.branch_names = self.branch_names

        # connectivity matrices
        circuit.C_load_bus = self.C_load_bus
        circuit.C_batt_bus = self.C_batt_bus
        circuit.C_sta_gen_bus = self.C_sta_gen_bus
        circuit.C_ctrl_gen_bus = self.C_gen_bus
        circuit.C_shunt_bus = self.C_shunt_bus

        # needed for the tap changer
        circuit.is_bus_to_regulated = self.is_bus_to_regulated
        circuit.tap_position = self.tap_position
        circuit.min_tap = self.min_tap
        circuit.max_tap = self.max_tap
        circuit.tap_inc_reg_up = self.tap_inc_reg_up
        circuit.tap_inc_reg_down = self.tap_inc_reg_down
        circuit.vset = self.vset
        circuit.tap_ang = self.tap_ang
        circuit.tap_mod = self.tap_mod

        # active power control
        circuit.controlled_gen_pmin = self.generator_pmin
        circuit.controlled_gen_pmax = self.generator_pmax
        circuit.controlled_gen_enabled = self.generator_active
        circuit.controlled_gen_dispatchable = self.generator_dispatchable
        circuit.battery_pmin = self.battery_pmin
        circuit.battery_pmax = self.battery_pmax
        circuit.battery_Enom = self.battery_Enom
        circuit.battery_soc_0 = self.battery_soc_0
        circuit.battery_discharge_efficiency = self.battery_discharge_efficiency
        circuit.battery_charge_efficiency = self.battery_charge_efficiency
        circuit.battery_min_soc = self.battery_min_soc
        circuit.battery_max_soc = self.battery_max_soc
        circuit.battery_enabled = self.battery_active
        circuit.battery_dispatchable = self.battery_dispatchable

        ################################################################################################################
        # loads, generators, batteries, etc...
        ################################################################################################################

        # Shunts
        Ysh = self.C_shunt_bus.T * (self.shunt_admittance / self.Sbase)

        # Loads
        S = self.C_load_bus.T * (-self.load_power / self.Sbase *
                                 self.load_active)
        I = self.C_load_bus.T * (-self.load_current / self.Sbase *
                                 self.load_active)
        Ysh += self.C_load_bus.T * (self.load_admittance / self.Sbase *
                                    self.load_active)

        if add_generation:
            # static generators
            S += self.C_sta_gen_bus.T * (self.static_gen_power / self.Sbase *
                                         self.static_gen_active)

            # generators
            pf2 = np.power(self.generator_power_factor, 2.0)
            # compute the reactive power from the active power and the power factor
            pf_sign = (self.generator_power_factor +
                       1e-20) / np.abs(self.generator_power_factor + 1e-20)
            Q = pf_sign * self.generator_power * np.sqrt(
                (1.0 - pf2) / (pf2 + 1e-20))
            gen_S = self.generator_power + 1j * Q
            S += self.C_gen_bus.T * (gen_S / self.Sbase *
                                     self.generator_active)

        # batteries
        if add_storage:
            S += self.C_batt_bus.T * (self.battery_power / self.Sbase *
                                      self.battery_active)

        # Qmax
        q_max = self.C_gen_bus.T * (self.generator_qmax / self.Sbase)
        q_max += self.C_batt_bus.T * (self.battery_qmax / self.Sbase)

        # Qmin
        q_min = self.C_gen_bus.T * (self.generator_qmin / self.Sbase)
        q_min += self.C_batt_bus.T * (self.battery_qmin / self.Sbase)

        # assign the values
        circuit.Ysh = Ysh
        circuit.Sbus = S
        circuit.Ibus = I
        circuit.Vbus = self.V0
        circuit.Sbase = self.Sbase
        circuit.types = self.bus_types
        circuit.Qmax = q_max
        circuit.Qmin = q_min

        # if there are profiles...
        if self.ntime > 0:
            # Shunts
            Ysh_prof = self.C_shunt_bus.T * (self.shunt_admittance_profile /
                                             self.Sbase * self.shunt_active).T

            # Loads
            I_prof = self.C_load_bus.T * (-self.load_current_profile /
                                          self.Sbase * self.load_active).T
            Ysh_prof += self.C_load_bus.T * (self.load_admittance_profile /
                                             self.Sbase * self.load_active).T

            Sbus_prof = self.C_load_bus.T * (-self.load_power_profile /
                                             self.Sbase * self.load_active).T

            if add_generation:
                # static generators
                Sbus_prof += self.C_sta_gen_bus.T * (
                    self.static_gen_power_profile / self.Sbase *
                    self.static_gen_active).T

                # generators
                pf2 = np.power(self.generator_power_factor_profile, 2.0)
                # compute the reactive power from the active power and the power factor
                pf_sign = (self.generator_power_factor_profile + 1e-20
                           ) / np.abs(self.generator_power_factor_profile +
                                      1e-20)
                Q = pf_sign * self.generator_power_profile * np.sqrt(
                    (1.0 - pf2) / (pf2 + 1e-20))
                gen_S = self.generator_power_profile + 1j * Q
                Sbus_prof += self.C_gen_bus.T * (gen_S / self.Sbase *
                                                 self.generator_active).T

            # batteries
            if add_storage:
                Sbus_prof += self.C_batt_bus.T * (self.battery_power_profile /
                                                  self.Sbase *
                                                  self.battery_active).T

            circuit.Ysh_prof = Ysh_prof
            circuit.Sbus_prof = Sbus_prof
            circuit.Ibus_prof = I_prof
            circuit.time_array = self.time_array

        return circuit
예제 #2
0
def calc_islands(circuit: CalculationInputs,
                 C_bus_bus,
                 C_branch_bus,
                 C_gen_bus,
                 C_batt_bus,
                 nbus,
                 nbr,
                 time_idx=None) -> List[CalculationInputs]:
    """
    Partition the circuit in islands for the designated time intervals
    :param circuit: CalculationInputs instance with all the data regardless of the islands and the branch states
    :param C_bus_bus: bus-bus connectivity matrix
    :param C_branch_bus: branch-bus connectivity matrix
    :param C_gen_bus: gen-bus connectivity matrix
    :param C_batt_bus: battery-bus connectivity matrix
    :param nbus: number of buses
    :param nbr: number of branches
    :param time_idx: array with the time indices where this set of islands belongs to
                    (if None all the time series are kept)
    :return: list of CalculationInputs instances
    """
    # find the islands of the circuit
    islands = Graph(csc_matrix(C_bus_bus)).find_islands()

    # clear the list of circuits
    calculation_islands = list()

    # find the branches that belong to each island
    island_branches = list()

    if len(islands) > 1:

        # there are islands, pack the islands into sub circuits
        for island_bus_idx in islands:
            # get the branch indices of the island
            island_br_idx = get_branches_of_the_island(island_bus_idx,
                                                       C_branch_bus)
            island_br_idx = np.sort(island_br_idx)  # sort
            island_branches.append(island_br_idx)

            # indices of batteries and controlled generators that belong to this island
            gen_idx = np.where(C_gen_bus[:, island_bus_idx].sum(axis=0) > 0)[0]
            bat_idx = np.where(
                C_batt_bus[:, island_bus_idx].sum(axis=0) > 0)[0]

            # Get the island circuit (the bus types are computed automatically)
            # The island original indices are generated within the get_island function
            circuit_island = circuit.get_island(island_bus_idx, island_br_idx,
                                                gen_idx, bat_idx)

            if time_idx is not None:
                circuit_island.trim_profiles(time_idx=time_idx)

            # store the island
            calculation_islands.append(circuit_island)

    else:
        # Only one island

        # compile bus types
        circuit.consolidate()

        # only one island, no need to split anything
        calculation_islands.append(circuit)

        island_bus_idx = np.arange(start=0, stop=nbus, step=1, dtype=int)
        island_br_idx = np.arange(start=0, stop=nbr, step=1, dtype=int)

        # set the indices in the island too
        circuit.original_bus_idx = island_bus_idx
        circuit.original_branch_idx = island_br_idx

        if time_idx is not None:
            circuit.trim_profiles(time_idx=time_idx)

        # append a list with all the branch indices for completeness
        island_branches.append(island_br_idx)

    # return the list of islands
    return calculation_islands