def __init__(self,
              Sbus=None,
              voltage=None,
              Sbranch=None,
              Ibranch=None,
              loading=None,
              losses=None,
              error=None,
              converged=None,
              Qpv=None):
     """
     Constructor
     :param Sbus: Bus power injections
     :param voltage: Bus voltages
     :param Sbranch: Branch power flow
     :param Ibranch: Branch current flow
     :param loading: Branch loading
     :param losses: Branch losses
     :param error: error
     :param converged: converged?
     :param Qpv: Reactive power at the PV nodes
     """
     # initialize the
     PowerFlowResults.__init__(self,
                               Sbus=Sbus,
                               voltage=voltage,
                               Sbranch=Sbranch,
                               Ibranch=Ibranch,
                               loading=loading,
                               losses=losses,
                               error=error,
                               converged=converged,
                               Qpv=Qpv)
    def set_at(self, t, results: PowerFlowResults):
        """
        Set the results at the step t
        @param t: time index
        @param results: PowerFlowResults instance
        """

        self.voltage[t, :] = results.voltage

        self.S[t, :] = results.Sbus

        self.Sbranch[t, :] = results.Sbranch

        self.Ibranch[t, :] = results.Ibranch

        self.Vbranch[t, :] = results.Vbranch

        self.loading[t, :] = results.loading

        self.losses[t, :] = results.losses

        self.flow_direction[t, :] = results.flow_direction

        self.error[t] = results.error()

        self.converged[t] = results.converged()
Exemple #3
0
    def __init__(self,
                 grid: MultiCircuit,
                 options: PowerFlowOptions,
                 opf_results: OptimalPowerFlowResults = None):
        """
        PowerFlowDriver class constructor
        :param grid: MultiCircuit instance
        :param options: PowerFlowOptions instance
        :param opf_results: OptimalPowerFlowResults instance
        """

        QThread.__init__(self)

        # Grid to run a power flow in
        self.grid = grid

        # Options to use
        self.options = options

        self.opf_results = opf_results

        self.results = PowerFlowResults()

        self.logger = Logger()

        self.convergence_reports = list()

        self.__cancel__ = False
Exemple #4
0
def get_results_object_dictionary():
    """
    Get dictionary of recognizable result types in order to be able to load a driver from disk
    :return: dictionary[driver name: empty results object]
    """
    lst = [
        (AvailableTransferCapacityResults(0, 0, [], [], [], (), ()),
         SimulationTypes.NetTransferCapacity_run),
        (AvailableTransferCapacityTimeSeriesResults(0, 0, [], [], [], []),
         SimulationTypes.NetTransferCapacityTS_run),
        (ContingencyAnalysisResults(0, 0, [], [], []),
         SimulationTypes.ContingencyAnalysis_run),
        (ContingencyAnalysisTimeSeriesResults(0, 0, 0, [], [], [], []),
         SimulationTypes.ContingencyAnalysisTS_run),
        (ContinuationPowerFlowResults(0, 0, 0, [], [], []),
         SimulationTypes.ContinuationPowerFlow_run),
        (LinearAnalysisResults(0, 0, (), (),
                               ()), SimulationTypes.LinearAnalysis_run),
        (LinearAnalysisTimeSeriesResults(0, 0, (), (), (), ()),
         SimulationTypes.LinearAnalysis_TS_run),
        (OptimalPowerFlowResults((), (), (), (), ()), SimulationTypes.OPF_run),
        (OptimalPowerFlowTimeSeriesResults(
            (), (), (), (), (), 0, 0, 0), SimulationTypes.OPFTimeSeries_run),
        (PowerFlowResults(0, 0, 0, 0, (), (), (), (),
                          ()), SimulationTypes.PowerFlow_run),
        (TimeSeriesResults(0, 0, 0, 0, (), (), (), (), (),
                           ()), SimulationTypes.TimeSeries_run),
        (ShortCircuitResults(0, 0, 0, (), (), (),
                             ()), SimulationTypes.ShortCircuit_run),
        (StochasticPowerFlowResults(0, 0, 0, (), (),
                                    ()), SimulationTypes.StochasticPowerFlow)
    ]

    return {tpe.value: (elm, tpe) for elm, tpe in lst}
    def __init__(self, grid: MultiCircuit, options: PowerFlowOptions, opf_results: OptimalPowerFlowResults = None):
        """
        PowerFlowDriver class constructor
        :param grid: MultiCircuit instance
        :param options: PowerFlowOptions instance
        :param opf_results: OptimalPowerFlowResults instance
        """

        QThread.__init__(self)

        # Grid to run a power flow in
        self.grid = grid

        # Options to use
        self.options = options

        self.opf_results = opf_results

        self.results = PowerFlowResults(n=0, m=0, n_tr=0, n_hvdc=0,
                                        bus_names=(), branch_names=(), transformer_names=(),
                                        hvdc_names=(), bus_types=())

        self.logger = Logger()

        self.convergence_reports = list()

        self.__cancel__ = False
    def __init__(self,
                 Sbus=None,
                 voltage=None,
                 Sbranch=None,
                 Ibranch=None,
                 loading=None,
                 losses=None,
                 SCpower=None,
                 error=None,
                 converged=None,
                 Qpv=None):
        """

        Args:
            Sbus:
            voltage:
            Sbranch:
            Ibranch:
            loading:
            losses:
            SCpower:
            error:
            converged:
            Qpv:
        """
        PowerFlowResults.__init__(self,
                                  Sbus=Sbus,
                                  voltage=voltage,
                                  Sbranch=Sbranch,
                                  Ibranch=Ibranch,
                                  loading=loading,
                                  losses=losses,
                                  error=error,
                                  converged=converged,
                                  Qpv=Qpv)

        self.short_circuit_power = SCpower

        self.available_results = [
            ResultTypes.BusVoltage, ResultTypes.BranchPower,
            ResultTypes.BranchCurrent, ResultTypes.BranchLoading,
            ResultTypes.BranchLosses, ResultTypes.BusShortCircuitPower
        ]
Exemple #7
0
    def __init__(self, n, m, nt, start, end, time_array=None):
        """
        TimeSeriesResults constructor
        @param n: number of buses
        @param m: number of branches
        @param nt: number of time steps
        """
        PowerFlowResults.__init__(self)
        self.name = 'PTDF Time series'
        self.nt = nt
        self.m = m
        self.n = n
        self.start = start
        self.end = end

        self.time = time_array

        if nt > 0:

            self.voltage = np.zeros((nt, n), dtype=float)

            self.S = np.zeros((nt, n), dtype=float)

            self.Sbranch = np.zeros((nt, m), dtype=float)

            self.loading = np.zeros((nt, m), dtype=float)

        else:

            self.voltage = None

            self.S = None

            self.Sbranch = None

            self.loading = None

        self.available_results = [ResultTypes.BusVoltageModule,
                                  ResultTypes.BusActivePower,
                                  # ResultTypes.BusReactivePower,
                                  ResultTypes.BranchActivePower,
                                  ResultTypes.BranchLoading]
    def __init__(self, grid: MultiCircuit, options: PowerFlowOptions):
        """
        PowerFlowDriver class constructor
        **grid: MultiCircuit Object
        """
        QThread.__init__(self)

        # Grid to run a power flow in
        self.grid = grid

        # Options to use
        self.options = options

        self.results = PowerFlowResults()

        self.logger = Logger()

        self.convergence_reports = list()

        self.__cancel__ = False
Exemple #9
0
    def run_multi_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """
        # print('LHS run')
        self.__cancel__ = False

        # initialize vars
        batch_size = self.sampling_points
        n = len(self.circuit.buses)
        m = len(self.circuit.branches)
        n_cores = multiprocessing.cpu_count()

        self.progress_signal.emit(0.0)
        self.progress_text.emit(
            'Running Latin Hypercube Sampling in parallel using ' +
            str(n_cores) + ' cores ...')

        lhs_results = MonteCarloResults(n, m, batch_size)
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile
        # print('Compiling...', end='')
        numerical_circuit = self.circuit.compile()
        numerical_islands = numerical_circuit.compute(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode)

        lhs_results.bus_types = numerical_circuit.bus_types

        max_iter = batch_size * len(numerical_islands)
        Sbase = self.circuit.Sbase
        it = 0

        # For every circuit, run the time series
        for numerical_island in numerical_islands:

            # try:
            # set the time series as sampled in the circuit

            monte_carlo_input = make_monte_carlo_input(numerical_island)
            mc_time_series = monte_carlo_input(batch_size,
                                               use_latin_hypercube=True)
            Vbus = numerical_island.Vbus

            # short cut the indices
            b_idx = numerical_island.original_bus_idx
            br_idx = numerical_island.original_branch_idx

            manager = multiprocessing.Manager()
            return_dict = manager.dict()

            t = 0
            while t < batch_size and not self.__cancel__:

                k = 0
                jobs = list()

                # launch only n_cores jobs at the time
                while k < n_cores + 2 and (t + k) < batch_size:
                    # set the power values
                    Y, I, S = mc_time_series.get_at(t)

                    # run power flow at the circuit
                    p = multiprocessing.Process(
                        target=power_flow_worker,
                        args=(t, self.options, numerical_island, Vbus,
                              S / Sbase, I / Sbase, return_dict))
                    jobs.append(p)
                    p.start()
                    k += 1
                    t += 1

                # wait for all jobs to complete
                for proc in jobs:
                    proc.join()

                progress = ((t + 1) / batch_size) * 100
                self.progress_signal.emit(progress)

            # collect results
            self.progress_text.emit('Collecting results...')
            for t in return_dict.keys():
                # store circuit results at the time index 't'
                res = return_dict[t]

                lhs_results.S_points[
                    t, numerical_island.original_bus_idx] = res.Sbus
                lhs_results.V_points[
                    t, numerical_island.original_bus_idx] = res.voltage
                lhs_results.I_points[
                    t, numerical_island.original_branch_idx] = res.Ibranch
                lhs_results.loading_points[
                    t, numerical_island.original_branch_idx] = res.loading
                lhs_results.losses_points[
                    t, numerical_island.original_branch_idx] = res.losses

            # except Exception as ex:
            #     print(c.name, ex)

            if self.__cancel__:
                break

            # compile MC results
            self.progress_text.emit('Compiling results...')
            lhs_results.compile()

            # compute the island branch results
            island_avg_res = numerical_island.compute_branch_results(
                lhs_results.voltage[b_idx])

            # apply the island averaged results
            avg_res.apply_from_island(island_avg_res,
                                      b_idx=b_idx,
                                      br_idx=br_idx)

        # lhs_results the averaged branch magnitudes
        lhs_results.sbranch = avg_res.Sbranch
        lhs_results.losses = avg_res.losses
        self.results = lhs_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return lhs_results
Exemple #10
0
def multi_island_pf(multi_circuit: MultiCircuit, options: PowerFlowOptions, opf_results=None,
                    logger=bs.Logger()) -> "PowerFlowResults":
    """
    Multiple islands power flow (this is the most generic power flow function)
    :param multi_circuit: MultiCircuit instance
    :param options: PowerFlowOptions instance
    :param opf_results: OPF results, to be used if not None
    :param logger: list of events to add to
    :return: PowerFlowResults instance
    """

    nc = compile_snapshot_circuit(circuit=multi_circuit,
                                  apply_temperature=options.apply_temperature_correction,
                                  branch_tolerance_mode=options.branch_impedance_tolerance_mode,
                                  opf_results=opf_results)

    calculation_inputs = nc.split_into_islands(ignore_single_node_islands=options.ignore_single_node_islands)

    results = PowerFlowResults(n=nc.nbus,
                               m=nc.nbr,
                               n_tr=nc.ntr,
                               n_hvdc=nc.nhvdc,
                               bus_names=nc.bus_data.bus_names,
                               branch_names=nc.branch_data.branch_names,
                               transformer_names=nc.transformer_data.tr_names,
                               hvdc_names=nc.hvdc_data.names,
                               bus_types=nc.bus_data.bus_types)

    if len(calculation_inputs) > 1:

        # simulate each island and merge the results
        for i, calculation_input in enumerate(calculation_inputs):

            if len(calculation_input.vd) > 0:

                # run circuit power flow
                res = single_island_pf(circuit=calculation_input,
                                       Vbus=calculation_input.Vbus,
                                       Sbus=calculation_input.Sbus,
                                       Ibus=calculation_input.Ibus,
                                       branch_rates=calculation_input.Rates,
                                       options=options,
                                       logger=logger)

                bus_original_idx = calculation_input.original_bus_idx
                branch_original_idx = calculation_input.original_branch_idx
                tr_original_idx = calculation_input.original_tr_idx

                # merge the results from this island
                results.apply_from_island(res, bus_original_idx, branch_original_idx, tr_original_idx)

            else:
                logger.add_info('No slack nodes in the island', str(i))
    else:

        if len(calculation_inputs[0].vd) > 0:
            # only one island
            # run circuit power flow
            res = single_island_pf(circuit=calculation_inputs[0],
                                   Vbus=calculation_inputs[0].Vbus,
                                   Sbus=calculation_inputs[0].Sbus,
                                   Ibus=calculation_inputs[0].Ibus,
                                   branch_rates=calculation_inputs[0].Rates,
                                   options=options,
                                   logger=logger)

            if calculation_inputs[0].nbus == nc.nbus:
                # we can confidently say that the island is the only one
                results = res
            else:
                # the island is the only valid subset, but does not contain all the buses
                bus_original_idx = calculation_inputs[0].original_bus_idx
                branch_original_idx = calculation_inputs[0].original_branch_idx
                tr_original_idx = calculation_inputs[0].original_tr_idx

                # merge the results from this island
                results.apply_from_island(res, bus_original_idx, branch_original_idx, tr_original_idx)

        else:
            logger.add_error('There are no slack nodes')

    # compile HVDC results (available for the complete grid since HVDC line as formulated are split objects
    # Pt is the "generation" at the sending point
    results.hvdc_Pf = -nc.hvdc_Pf
    results.hvdc_Pt = -nc.hvdc_Pt
    results.hvdc_loading = nc.hvdc_loading
    results.hvdc_losses = nc.hvdc_losses

    return results
Exemple #11
0
    def run_multi_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """
        # print('LHS run')
        self.__cancel__ = False

        # initialize vars
        batch_size = self.sampling_points
        n = len(self.circuit.buses)
        m = self.circuit.get_branch_number()
        n_cores = multiprocessing.cpu_count()
        self.pool = multiprocessing.Pool()

        self.progress_signal.emit(0.0)
        self.progress_text.emit(
            'Running Latin Hypercube Sampling in parallel using ' +
            str(n_cores) + ' cores ...')

        lhs_results = MonteCarloResults(n,
                                        m,
                                        batch_size,
                                        name='Latin Hypercube')
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile the multi-circuit
        numerical_circuit = self.circuit.compile_time_series()

        # perform the topological computation
        calc_inputs_dict = numerical_circuit.compute(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode,
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        # for each partition of the profiles...
        for t_key, calc_inputs in calc_inputs_dict.items():

            # For every island, run the time series
            for island_index, numerical_island in enumerate(calc_inputs):

                lhs_results.bus_types = numerical_circuit.bus_types

                monte_carlo_input = make_monte_carlo_input(numerical_island)
                mc_time_series = monte_carlo_input(batch_size,
                                                   use_latin_hypercube=True)
                Vbus = numerical_island.Vbus
                branch_rates = numerical_island.branch_rates

                # short cut the indices
                b_idx = numerical_island.original_bus_idx
                br_idx = numerical_island.original_branch_idx

                # Start jobs
                self.returned_results = list()

                t = 0
                while t < batch_size and not self.__cancel__:

                    Ysh, Ibus, Sbus = mc_time_series.get_at(t)

                    args = (t, self.options, numerical_island, Vbus, Sbus,
                            Ibus, branch_rates)

                    self.pool.apply_async(power_flow_worker_args, (args, ),
                                          callback=self.update_progress_mt)

                # wait for all jobs to complete
                self.pool.close()
                self.pool.join()

                # collect results
                self.progress_text.emit('Collecting results...')
                for t, res in self.returned_results:
                    # store circuit results at the time index 't'
                    lhs_results.S_points[
                        t, numerical_island.original_bus_idx] = res.Sbus
                    lhs_results.V_points[
                        t, numerical_island.original_bus_idx] = res.voltage
                    lhs_results.Sbr_points[
                        t, numerical_island.original_branch_idx] = res.Sf
                    lhs_results.loading_points[
                        t, numerical_island.original_branch_idx] = res.loading
                    lhs_results.losses_points[
                        t, numerical_island.original_branch_idx] = res.losses

                # compile MC results
                self.progress_text.emit('Compiling results...')
                lhs_results.compile()

                # compute the island branch results
                island_avg_res = numerical_island.compute_branch_results(
                    lhs_results.voltage[b_idx])

                # apply the island averaged results
                avg_res.apply_from_island(island_avg_res,
                                          b_idx=b_idx,
                                          br_idx=br_idx)

        # lhs_results the averaged branch magnitudes
        lhs_results.sbranch = avg_res.Sf
        lhs_results.losses = avg_res.losses
        self.results = lhs_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return lhs_results
Exemple #12
0
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """
        # print('LHS run')
        self.__cancel__ = False

        # initialize the power flow
        power_flow = PowerFlowMP(self.circuit, self.options)

        # initialize the grid time series results
        # we will append the island results with another function
        self.circuit.time_series_results = TimeSeriesResults(0, 0, 0, 0, 0)

        batch_size = self.sampling_points
        n = len(self.circuit.buses)
        m = len(self.circuit.branches)

        self.progress_signal.emit(0.0)
        self.progress_text.emit('Running Latin Hypercube Sampling...')

        lhs_results = MonteCarloResults(n, m, batch_size)
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile the numerical circuit
        numerical_circuit = self.circuit.compile()
        numerical_input_islands = numerical_circuit.compute(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode)

        max_iter = batch_size * len(numerical_input_islands)
        Sbase = numerical_circuit.Sbase
        it = 0

        # For every circuit, run the time series
        for numerical_island in numerical_input_islands:

            # try:
            # set the time series as sampled in the circuit
            # build the inputs
            monte_carlo_input = make_monte_carlo_input(numerical_island)
            mc_time_series = monte_carlo_input(batch_size,
                                               use_latin_hypercube=True)
            Vbus = numerical_island.Vbus

            # short cut the indices
            b_idx = numerical_island.original_bus_idx
            br_idx = numerical_island.original_branch_idx

            # run the time series
            for t in range(batch_size):

                # set the power values from a Monte carlo point at 't'
                Y, I, S = mc_time_series.get_at(t)

                # Run the set monte carlo point at 't'
                res = power_flow.run_pf(circuit=numerical_island,
                                        Vbus=Vbus,
                                        Sbus=S / Sbase,
                                        Ibus=I / Sbase)

                # Gather the results
                lhs_results.S_points[
                    t, numerical_island.original_bus_idx] = res.Sbus
                lhs_results.V_points[
                    t, numerical_island.original_bus_idx] = res.voltage
                lhs_results.I_points[
                    t, numerical_island.original_branch_idx] = res.Ibranch
                lhs_results.loading_points[
                    t, numerical_island.original_branch_idx] = res.loading
                lhs_results.losses_points[
                    t, numerical_island.original_branch_idx] = res.losses

                it += 1
                self.progress_signal.emit(it / max_iter * 100)

                if self.__cancel__:
                    break

            if self.__cancel__:
                break

            # compile MC results
            self.progress_text.emit('Compiling results...')
            lhs_results.compile()

            # compute the island branch results
            island_avg_res = numerical_island.compute_branch_results(
                lhs_results.voltage[b_idx])

            # apply the island averaged results
            avg_res.apply_from_island(island_avg_res,
                                      b_idx=b_idx,
                                      br_idx=br_idx)

        # lhs_results the averaged branch magnitudes
        lhs_results.sbranch = avg_res.Sbranch

        lhs_results.bus_types = numerical_circuit.bus_types
        # Ibranch = avg_res.Ibranch
        # loading = avg_res.loading
        # lhs_results.losses = avg_res.losses
        # flow_direction = avg_res.flow_direction
        # Sbus = avg_res.Sbus

        self.results = lhs_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return lhs_results
Exemple #13
0
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """
        # print('LHS run')
        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function

        batch_size = self.sampling_points
        n = len(self.circuit.buses)
        m = len(self.circuit.branches)

        self.progress_signal.emit(0.0)
        self.progress_text.emit('Running Latin Hypercube Sampling...')

        lhs_results = MonteCarloResults(n,
                                        m,
                                        batch_size,
                                        name='Latin Hypercube')
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile the multi-circuit
        numerical_circuit = self.circuit.compile()

        # perform the topological computation
        calc_inputs_dict = numerical_circuit.compute_ts(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode,
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        it = 0
        # for each partition of the profiles...
        for t_key, calc_inputs in calc_inputs_dict.items():

            # For every island, run the time series
            for island_index, numerical_island in enumerate(calc_inputs):

                # try:
                # set the time series as sampled in the circuit
                # build the inputs
                monte_carlo_input = make_monte_carlo_input(numerical_island)
                mc_time_series = monte_carlo_input(batch_size,
                                                   use_latin_hypercube=True)
                Vbus = numerical_island.Vbus

                # short cut the indices
                b_idx = numerical_island.original_bus_idx
                br_idx = numerical_island.original_branch_idx

                # run the time series
                for t in range(batch_size):

                    # set the power values from a Monte carlo point at 't'
                    Y, I, S = mc_time_series.get_at(t)

                    # Run the set monte carlo point at 't'
                    res = single_island_pf(
                        circuit=numerical_island,
                        Vbus=Vbus,
                        Sbus=S,
                        Ibus=I,
                        branch_rates=numerical_island.branch_rates,
                        options=self.options,
                        logger=self.logger)

                    # Gather the results
                    lhs_results.S_points[
                        t, numerical_island.original_bus_idx] = res.Sbus
                    lhs_results.V_points[
                        t, numerical_island.original_bus_idx] = res.voltage
                    lhs_results.I_points[
                        t, numerical_island.original_branch_idx] = res.Ibranch
                    lhs_results.loading_points[
                        t, numerical_island.original_branch_idx] = res.loading
                    lhs_results.losses_points[
                        t, numerical_island.original_branch_idx] = res.losses

                    it += 1
                    self.progress_signal.emit(it / batch_size * 100)

                    if self.__cancel__:
                        break

                if self.__cancel__:
                    break

                # compile MC results
                self.progress_text.emit('Compiling results...')
                lhs_results.compile()

                # compute the island branch results
                island_avg_res = numerical_island.compute_branch_results(
                    lhs_results.voltage[b_idx])

                # apply the island averaged results
                avg_res.apply_from_island(island_avg_res,
                                          b_idx=b_idx,
                                          br_idx=br_idx)

        # lhs_results the averaged branch magnitudes
        lhs_results.sbranch = avg_res.Sbranch

        lhs_results.bus_types = numerical_circuit.bus_types

        self.results = lhs_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return lhs_results
Exemple #14
0
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """
        # print('LHS run')
        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function

        # batch_size = self.sampling_points

        self.progress_signal.emit(0.0)
        self.progress_text.emit('Running Latin Hypercube Sampling...')

        # compile the multi-circuit
        numerical_circuit = compile_time_circuit(
            circuit=self.circuit,
            apply_temperature=False,
            branch_tolerance_mode=BranchImpedanceMode.Specified,
            opf_results=self.opf_time_series_results)

        # do the topological computation
        calculation_inputs = numerical_circuit.split_into_islands(
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        lhs_results = MonteCarloResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            p=self.sampling_points,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            bus_types=numerical_circuit.bus_types,
            name='Latin Hypercube')

        avg_res = PowerFlowResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            n_tr=numerical_circuit.ntr,
            n_hvdc=numerical_circuit.nhvdc,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            transformer_names=numerical_circuit.tr_names,
            hvdc_names=numerical_circuit.hvdc_names,
            bus_types=numerical_circuit.bus_types)

        it = 0

        # For every island, run the time series
        for island_index, numerical_island in enumerate(calculation_inputs):

            # try:
            # set the time series as sampled in the circuit
            # build the inputs
            monte_carlo_input = make_monte_carlo_input(numerical_island)
            mc_time_series = monte_carlo_input(self.sampling_points,
                                               use_latin_hypercube=True)
            Vbus = numerical_island.Vbus[:, 0]

            # short cut the indices
            bus_idx = numerical_island.original_bus_idx
            br_idx = numerical_island.original_branch_idx

            # run the time series
            for t in range(self.sampling_points):

                # set the power values from a Monte carlo point at 't'
                Y, I, S = mc_time_series.get_at(t)

                # Run the set monte carlo point at 't'
                res = single_island_pf(
                    circuit=numerical_island,
                    Vbus=Vbus,
                    Sbus=S,
                    Ibus=I,
                    branch_rates=numerical_island.branch_rates,
                    options=self.options,
                    logger=self.logger)

                # Gather the results
                lhs_results.S_points[t, bus_idx] = S
                lhs_results.V_points[t, bus_idx] = res.voltage
                lhs_results.Sbr_points[t, br_idx] = res.Sf
                lhs_results.loading_points[t, br_idx] = res.loading
                lhs_results.losses_points[t, br_idx] = res.losses

                it += 1
                self.progress_signal.emit(it / self.sampling_points * 100)

                if self.__cancel__:
                    break

            if self.__cancel__:
                break

            # compile MC results
            self.progress_text.emit('Compiling results...')
            lhs_results.compile()

            # compute the island branch results
            Sfb, Stb, If, It, Vbranch, loading, \
            losses, flow_direction, Sbus = power_flow_post_process(numerical_island,
                                                                   Sbus=lhs_results.S_points.mean(axis=0)[bus_idx],
                                                                   V=lhs_results.V_points.mean(axis=0)[bus_idx],
                                                                   branch_rates=numerical_island.branch_rates)

            # apply the island averaged results
            avg_res.Sbus[bus_idx] = Sbus
            avg_res.voltage[bus_idx] = lhs_results.voltage[bus_idx]
            avg_res.Sf[br_idx] = Sfb
            avg_res.St[br_idx] = Stb
            avg_res.If[br_idx] = If
            avg_res.It[br_idx] = It
            avg_res.Vbranch[br_idx] = Vbranch
            avg_res.loading[br_idx] = loading
            avg_res.losses[br_idx] = losses
            avg_res.flow_direction[br_idx] = flow_direction

        self.results = lhs_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return lhs_results
    def __init__(self, n, m, n_tr, n_hvdc, bus_names, branch_names, transformer_names, hvdc_names,
                 time_array, bus_types):
        """
        TimeSeriesResults constructor
        :param n: number of buses
        :param m: number of branches
        :param n_tr:
        :param n_hvdc:
        :param bus_names:
        :param branch_names:
        :param transformer_names:
        :param hvdc_names:
        :param time_array:
        :param bus_types:
        """
        PowerFlowResults.__init__(self,
                                  n=n,
                                  m=m,
                                  n_tr=n_tr,
                                  n_hvdc=n_hvdc,
                                  bus_names=bus_names,
                                  branch_names=branch_names,
                                  transformer_names=transformer_names,
                                  hvdc_names=hvdc_names,
                                  bus_types=bus_types)

        self.name = 'Time series'
        self.nt = len(time_array)
        self.m = m
        self.n = n

        self.time = time_array

        self.bus_types = np.zeros(n, dtype=int)

        self.voltage = np.zeros((self.nt, n), dtype=complex)

        self.S = np.zeros((self.nt, n), dtype=complex)

        self.Sf = np.zeros((self.nt, m), dtype=complex)

        self.St = np.zeros((self.nt, m), dtype=complex)

        self.Ibranch = np.zeros((self.nt, m), dtype=complex)

        self.Vbranch = np.zeros((self.nt, m), dtype=complex)

        self.loading = np.zeros((self.nt, m), dtype=complex)

        self.losses = np.zeros((self.nt, m), dtype=complex)

        self.hvdc_losses = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_Pf = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_Pt = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_loading = np.zeros((self.nt, self.n_hvdc))

        self.flow_direction = np.zeros((self.nt, m), dtype=float)

        self.error_values = np.zeros(self.nt)

        self.converged_values = np.ones(self.nt, dtype=bool)  # guilty assumption

        self.overloads = [None] * self.nt

        self.overvoltage = [None] * self.nt

        self.undervoltage = [None] * self.nt

        self.overloads_idx = [None] * self.nt

        self.overvoltage_idx = [None] * self.nt

        self.undervoltage_idx = [None] * self.nt

        self.buses_useful_for_storage = [None] * self.nt

        # results available
        self.available_results = [ResultTypes.BusVoltageModule,
                                  ResultTypes.BusVoltageAngle,
                                  ResultTypes.BusActivePower,
                                  ResultTypes.BusReactivePower,

                                  ResultTypes.BranchActivePowerFrom,
                                  ResultTypes.BranchReactivePowerFrom,
                                  ResultTypes.BranchActiveCurrentFrom,
                                  ResultTypes.BranchReactiveCurrentFrom,
                                  ResultTypes.BranchLoading,
                                  ResultTypes.BranchActiveLosses,
                                  ResultTypes.BranchReactiveLosses,
                                  ResultTypes.BranchVoltage,
                                  ResultTypes.BranchAngles,
                                  ResultTypes.SimulationError,

                                  ResultTypes.HvdcLosses,
                                  ResultTypes.HvdcPowerFrom,
                                  ResultTypes.HvdcPowerTo]
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """

        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function
        # self.circuit.time_series_results = TimeSeriesResults(0, 0, [])
        # Sbase = self.circuit.Sbase

        it = 0
        variance_sum = 0.0
        std_dev_progress = 0
        v_variance = 0

        # n = len(self.circuit.buses)
        # m = self.circuit.get_branch_number()
        #
        # # compile circuits
        # numerical_circuit = self.circuit.compile_time_series()
        #
        # # perform the topological computation
        # calc_inputs_dict = numerical_circuit.compute(branch_tolerance_mode=self.options.branch_impedance_tolerance_mode,
        #                                              ignore_single_node_islands=self.options.ignore_single_node_islands)
        #
        # mc_results = MonteCarloResults(n, m, name='Monte Carlo')
        # avg_res = PowerFlowResults()
        # avg_res.initialize(n, m)

        # compile the multi-circuit
        numerical_circuit = compile_time_circuit(
            circuit=self.circuit,
            apply_temperature=False,
            branch_tolerance_mode=BranchImpedanceMode.Specified,
            opf_results=self.opf_time_series_results)

        # do the topological computation
        calculation_inputs = split_time_circuit_into_islands(
            numeric_circuit=numerical_circuit,
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        mc_results_master = MonteCarloResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            p=self.max_mc_iter,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            bus_types=numerical_circuit.bus_types,
            name='Monte Carlo')

        avg_res = PowerFlowResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            n_tr=numerical_circuit.ntr,
            n_hvdc=numerical_circuit.nhvdc,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            transformer_names=numerical_circuit.tr_names,
            hvdc_names=numerical_circuit.hvdc_names,
            bus_types=numerical_circuit.bus_types)

        n = numerical_circuit.nbus
        m = numerical_circuit.nbr
        v_sum = zeros(n, dtype=complex)

        self.progress_signal.emit(0.0)

        while (std_dev_progress <
               100.0) and (it < self.max_mc_iter) and not self.__cancel__:

            self.progress_text.emit('Running Monte Carlo: Variance: ' +
                                    str(v_variance))

            batch_results = MonteCarloResults(
                n=numerical_circuit.nbus,
                m=numerical_circuit.nbr,
                p=self.max_mc_iter,
                bus_names=numerical_circuit.bus_names,
                branch_names=numerical_circuit.branch_names,
                bus_types=numerical_circuit.bus_types,
                name='Monte Carlo')

            # For every island, run the time series
            for island_index, numerical_island in enumerate(
                    calculation_inputs):

                # short cut the indices
                bus_idx = numerical_island.original_bus_idx
                br_idx = numerical_island.original_branch_idx

                # set the time series as sampled
                monte_carlo_input = make_monte_carlo_input(numerical_island)
                mc_time_series = monte_carlo_input(self.batch_size,
                                                   use_latin_hypercube=False)
                Vbus = numerical_island.Vbus[0, :]

                # run the time series
                for t in range(self.batch_size):
                    # set the power values
                    Y, I, S = mc_time_series.get_at(t)

                    res = single_island_pf(
                        circuit=numerical_island,
                        Vbus=Vbus,
                        Sbus=S,
                        Ibus=I,
                        branch_rates=numerical_island.branch_rates[0, :],
                        options=self.options,
                        logger=self.logger)

                    batch_results.S_points[t, bus_idx] = res.Sbus
                    batch_results.V_points[t, bus_idx] = res.voltage
                    batch_results.Sbr_points[t, br_idx] = res.Sbranch
                    batch_results.loading_points[t, br_idx] = res.loading
                    batch_results.losses_points[t, br_idx] = res.losses

                self.progress_text.emit('Compiling results...')
                batch_results.compile()

                # compute the island branch results
                Sbranch, Ibranch, Vbranch, loading, \
                losses, flow_direction, Sbus = power_flow_post_process(numerical_island,
                                                                       Sbus=batch_results.S_points.mean(axis=0)[bus_idx],
                                                                       V=batch_results.V_points.mean(axis=0)[bus_idx],
                                                                       branch_rates=numerical_island.branch_rates[0, :])

                # apply the island averaged results
                avg_res.Sbus[bus_idx] = Sbus
                avg_res.voltage[bus_idx] = batch_results.voltage[bus_idx]
                avg_res.Sbranch[br_idx] = Sbranch
                avg_res.Ibranch[br_idx] = Ibranch
                avg_res.Vbranch[br_idx] = Vbranch
                avg_res.loading[br_idx] = loading
                avg_res.losses[br_idx] = losses
                avg_res.flow_direction[br_idx] = flow_direction

            # Compute the Monte Carlo values
            it += self.batch_size
            mc_results_master.append_batch(batch_results)
            v_sum += mc_results_master.get_voltage_sum()
            v_avg = v_sum / it
            v_variance = abs((power(mc_results_master.V_points - v_avg, 2.0) /
                              (it - 1)).min())

            # progress
            variance_sum += v_variance
            err = variance_sum / it
            if err == 0:
                err = 1e-200  # to avoid division by zeros
            mc_results_master.error_series.append(err)

            # emmit the progress signal
            std_dev_progress = 100 * self.mc_tol / err
            if std_dev_progress > 100:
                std_dev_progress = 100
            self.progress_signal.emit(
                max((std_dev_progress, it / self.max_mc_iter * 100)))

        # compile results
        mc_results_master.bus_types = numerical_circuit.bus_types

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return mc_results_master
Exemple #17
0
    def __init__(self, n, m, n_tr, n_hvdc, bus_names, branch_names,
                 transformer_names, hvdc_names, time_array, bus_types):
        """
        TimeSeriesResults constructor
        :param n: number of buses
        :param m: number of branches
        :param n_tr:
        :param n_hvdc:
        :param bus_names:
        :param branch_names:
        :param transformer_names:
        :param hvdc_names:
        :param time_array:
        :param bus_types:
        """
        PowerFlowResults.__init__(self,
                                  n=n,
                                  m=m,
                                  n_tr=n_tr,
                                  n_hvdc=n_hvdc,
                                  bus_names=bus_names,
                                  branch_names=branch_names,
                                  transformer_names=transformer_names,
                                  hvdc_names=hvdc_names,
                                  bus_types=bus_types)

        self.data_variables.append(
            'time')  # this is missing from the base class

        # results available (different from the base class)
        self.available_results = [
            ResultTypes.BusVoltageModule, ResultTypes.BusVoltageAngle,
            ResultTypes.BusActivePower, ResultTypes.BusReactivePower,
            ResultTypes.BranchActivePowerFrom,
            ResultTypes.BranchReactivePowerFrom, ResultTypes.BranchLoading,
            ResultTypes.BranchActiveLosses, ResultTypes.BranchReactiveLosses,
            ResultTypes.BranchVoltage, ResultTypes.BranchAngles,
            ResultTypes.SimulationError, ResultTypes.HvdcLosses,
            ResultTypes.HvdcPowerFrom, ResultTypes.HvdcPowerTo
        ]

        self.name = 'Time series'
        self.nt = len(time_array)
        self.m = m
        self.n = n

        self.time = time_array

        self.bus_types = np.zeros(n, dtype=int)

        self.voltage = np.zeros((self.nt, n), dtype=complex)

        self.S = np.zeros((self.nt, n), dtype=complex)

        self.Sf = np.zeros((self.nt, m), dtype=complex)

        self.St = np.zeros((self.nt, m), dtype=complex)

        self.Vbranch = np.zeros((self.nt, m), dtype=complex)

        self.loading = np.zeros((self.nt, m), dtype=complex)

        self.losses = np.zeros((self.nt, m), dtype=complex)

        self.hvdc_losses = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_Pf = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_Pt = np.zeros((self.nt, self.n_hvdc))

        self.hvdc_loading = np.zeros((self.nt, self.n_hvdc))

        self.error_values = np.zeros(self.nt)

        self.converged_values = np.ones(self.nt,
                                        dtype=bool)  # guilty assumption
Exemple #18
0
    def run_multi_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """

        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function
        self.circuit.time_series_results = TimeSeriesResults(0, 0, 0, 0, 0)
        Sbase = self.circuit.Sbase
        n_cores = multiprocessing.cpu_count()

        it = 0
        variance_sum = 0.0
        std_dev_progress = 0
        v_variance = 0

        n = len(self.circuit.buses)
        m = len(self.circuit.branches)

        mc_results = MonteCarloResults(n, m)
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile circuits
        numerical_circuit = self.circuit.compile()
        numerical_input_islands = numerical_circuit.compute(branch_tolerance_mode=self.options.branch_impedance_tolerance_mode)

        mc_results.bus_types = numerical_circuit.bus_types

        v_sum = zeros(n, dtype=complex)

        self.progress_signal.emit(0.0)

        while (std_dev_progress < 100.0) and (it < self.max_mc_iter) and not self.__cancel__:

            self.progress_text.emit('Running Monte Carlo: Variance: ' + str(v_variance))

            mc_results = MonteCarloResults(n, m, self.batch_size)

            # For every circuit, run the time series
            for numerical_island in numerical_input_islands:

                # set the time series as sampled
                monte_carlo_input = make_monte_carlo_input(numerical_island)
                mc_time_series = monte_carlo_input(self.batch_size, use_latin_hypercube=False)
                Vbus = numerical_island.Vbus

                manager = multiprocessing.Manager()
                return_dict = manager.dict()

                # short cut the indices
                b_idx = numerical_island.original_bus_idx
                br_idx = numerical_island.original_branch_idx

                t = 0
                while t < self.batch_size and not self.__cancel__:

                    k = 0
                    jobs = list()

                    # launch only n_cores jobs at the time
                    while k < n_cores + 2 and (t + k) < self.batch_size:
                        # set the power values
                        Y, I, S = mc_time_series.get_at(t)

                        # run power flow at the circuit
                        p = multiprocessing.Process(target=power_flow_worker,
                                                    args=(t, self.options, numerical_island, Vbus, S / Sbase, I / Sbase, return_dict))
                        jobs.append(p)
                        p.start()
                        k += 1
                        t += 1

                    # wait for all jobs to complete
                    for proc in jobs:
                        proc.join()

                    # progress = ((t + 1) / self.batch_size) * 100
                    # self.progress_signal.emit(progress)

                # collect results
                self.progress_text.emit('Collecting batch results...')
                for t in return_dict.keys():
                    # store circuit results at the time index 't'
                    res = return_dict[t]

                    mc_results.S_points[t, numerical_island.original_bus_idx] = res.Sbus
                    mc_results.V_points[t, numerical_island.original_bus_idx] = res.voltage
                    mc_results.I_points[t, numerical_island.original_branch_idx] = res.Ibranch
                    mc_results.loading_points[t, numerical_island.original_branch_idx] = res.loading
                    mc_results.losses_points[t, numerical_island.original_branch_idx] = res.losses

                # compile MC results
                self.progress_text.emit('Compiling results...')
                mc_results.compile()

                # compute the island branch results
                island_avg_res = numerical_island.compute_branch_results(mc_results.voltage[b_idx])

                # apply the island averaged results
                avg_res.apply_from_island(island_avg_res, b_idx=b_idx, br_idx=br_idx)

            # Compute the Monte Carlo values
            it += self.batch_size
            mc_results.append_batch(mc_results)
            v_sum += mc_results.get_voltage_sum()
            v_avg = v_sum / it
            v_variance = abs((power(mc_results.V_points - v_avg, 2.0) / (it - 1)).min())

            # progress
            variance_sum += v_variance
            err = variance_sum / it
            if err == 0:
                err = 1e-200  # to avoid division by zeros
            mc_results.error_series.append(err)

            # emmit the progress signal
            std_dev_progress = 100 * self.mc_tol / err
            if std_dev_progress > 100:
                std_dev_progress = 100
            self.progress_signal.emit(max((std_dev_progress, it / self.max_mc_iter * 100)))

            # print(iter, '/', max_mc_iter)
            # print('Vmc:', Vavg)
            # print('Vstd:', Vvariance, ' -> ', std_dev_progress, ' %')

        # compute the averaged branch magnitudes
        mc_results.sbranch = avg_res.Sbranch
        mc_results.losses = avg_res.losses

        # print('V mc: ', mc_results.voltage)

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return mc_results
    def compute_branch_results(self, V):
        """
        Compute the branch magnitudes from the voltages
        :param V: Voltage vector solution in p.u.
        :return: CalculationResults instance with all the grid magnitudes
        """

        # declare circuit results
        data = PowerFlowResults(self.nbus, self.nbr)

        # copy the voltage
        data.V = V

        # power at the slack nodes
        data.Sbus = self.Sbus.copy()
        data.Sbus[self.ref] = V[self.ref] * np.conj(self.Ybus[self.ref, :].dot(V))

        # Reactive power at the pv nodes: keep the original P injection and set the calculated reactive power
        Q = (V[self.pv] * np.conj(self.Ybus[self.pv, :].dot(V))).imag

        data.Sbus[self.pv] = self.Sbus[self.pv].real + 1j * Q

        # Branches current, loading, etc
        data.If = self.Yf * V
        data.It = self.Yt * V
        data.Sf = self.C_branch_bus_f * V * np.conj(data.If)
        data.St = self.C_branch_bus_t * V * np.conj(data.It)

        # Branch losses in MVA
        data.losses = (data.Sf + data.St)

        # Branch current in p.u.
        data.Ibranch = np.maximum(data.If, data.It)

        # Branch power in MVA
        data.Sbranch = np.maximum(data.Sf, data.St)

        # Branch loading in p.u.
        data.loading = data.Sbranch / (self.branch_rates + 1e-9)

        return data
Exemple #20
0
def outer_loop_power_flow(circuit: SnapshotData, options: PowerFlowOptions,
                          voltage_solution, Sbus, Ibus, branch_rates, t=0,
                          logger=bs.Logger()) -> "PowerFlowResults":
    """
    Run a power flow simulation for a single circuit using the selected outer loop
    controls. This method shouldn't be called directly.
    :param circuit: CalculationInputs instance
    :param options:
    :param voltage_solution: vector of initial voltages
    :param Sbus: vector of power injections
    :param Ibus: vector of current injections
    :param branch_rates:
    :param t: time step
    :param logger:
    :return: PowerFlowResults instance
    """

    # get the original types and compile this class' own lists of node types for thread independence
    bus_types = circuit.bus_types.copy()

    # vd = circuit.vd.copy()
    # pq = circuit.pq.copy()
    # pv = circuit.pv.copy()
    # pqpv = circuit.pqpv.copy()

    report = ConvergenceReport()
    solution = NumericPowerFlowResults(V=voltage_solution,
                                       converged=False,
                                       norm_f=1e200,
                                       Scalc=Sbus,
                                       ma=circuit.branch_data.m[:, 0],
                                       theta=circuit.branch_data.theta[:, 0],
                                       Beq=circuit.branch_data.Beq[:, 0],
                                       iterations=0,
                                       elapsed=0)

    # this the "outer-loop"
    if len(circuit.vd) == 0:
        voltage_solution = np.zeros(len(Sbus), dtype=complex)
        normF = 0
        Scalc = Sbus.copy()
        any_q_control_issue = False
        converged = True
        logger.add_error('Not solving power flow because there is no slack bus')
    else:

        # run the power flow method that shall be run
        solution = solve(circuit=circuit,
                         options=options,
                         report=report,  # is modified here
                         V0=voltage_solution,
                         Sbus=Sbus,
                         Ibus=Ibus,
                         pq=circuit.pq,
                         pv=circuit.pv,
                         ref=circuit.vd,
                         pqpv=circuit.pqpv,
                         logger=logger)

        if options.distributed_slack:
            # Distribute the slack power
            slack_power = Sbus[circuit.vd].real.sum()
            total_installed_power = circuit.bus_installed_power.sum()

            if total_installed_power > 0.0:
                delta = slack_power * circuit.bus_installed_power / total_installed_power

                # repeat power flow with the redistributed power
                solution = solve(circuit=circuit,
                                 options=options,
                                 report=report,  # is modified here
                                 V0=solution.V,
                                 Sbus=Sbus + delta,
                                 Ibus=Ibus,
                                 pq=circuit.pq,
                                 pv=circuit.pv,
                                 ref=circuit.vd,
                                 pqpv=circuit.pqpv,
                                 logger=logger)

    # Compute the branches power and the slack buses power
    Sfb, Stb, If, It, Vbranch, loading, losses, \
     flow_direction, Sbus = power_flow_post_process(calculation_inputs=circuit,
                                                    Sbus=solution.Scalc,
                                                    V=solution.V,
                                                    branch_rates=branch_rates)

    # voltage, Sf, loading, losses, error, converged, Qpv
    results = PowerFlowResults(n=circuit.nbus,
                               m=circuit.nbr,
                               n_tr=circuit.ntr,
                               n_hvdc=circuit.nhvdc,
                               bus_names=circuit.bus_names,
                               branch_names=circuit.branch_names,
                               transformer_names=circuit.tr_names,
                               hvdc_names=circuit.hvdc_names,
                               bus_types=bus_types)

    results.Sbus = solution.Scalc * circuit.Sbase  # MVA
    results.voltage = solution.V
    results.Sf = Sfb  # in MVA already
    results.St = Stb  # in MVA already
    results.If = If  # in p.u.
    results.It = It  # in p.u.
    results.ma = solution.ma
    results.theta = solution.theta
    results.Beq = solution.Beq
    results.Vbranch = Vbranch
    results.loading = loading
    results.losses = losses
    results.flow_direction = flow_direction
    results.transformer_tap_module = solution.ma[circuit.transformer_idx]
    results.convergence_reports.append(report)
    results.Qpv = Sbus.imag[circuit.pv]

    # HVDC results are gathered in the multi island power flow function due to their nature

    return results
Exemple #21
0
    def __init__(self,
                 n,
                 m,
                 nt,
                 n_tr,
                 n_hvdc,
                 bus_names,
                 branch_names,
                 transformer_names,
                 hvdc_names,
                 bus_types,
                 time_array=None,
                 states=None):
        """
        TimeSeriesResults constructor
        @param n: number of buses
        @param m: number of branches
        @param nt: number of time steps
        """
        PowerFlowResults.__init__(self,
                                  n=n,
                                  m=m,
                                  n_tr=n_tr,
                                  n_hvdc=n_hvdc,
                                  bus_names=bus_names,
                                  branch_names=branch_names,
                                  transformer_names=transformer_names,
                                  hvdc_names=hvdc_names,
                                  bus_types=bus_types)

        self.name = 'N-1'

        self.nt = nt

        self.time = time_array

        self.states = states

        self.bus_types = np.zeros(n, dtype=int)

        self.branch_names = None

        if nt > 0:
            self.voltage = np.zeros((nt, n), dtype=complex)

            self.S = np.zeros((nt, n), dtype=complex)

            self.Sbranch = np.zeros((nt, m), dtype=complex)

            self.Ibranch = np.zeros((nt, m), dtype=complex)

            self.Vbranch = np.zeros((nt, m), dtype=complex)

            self.loading = np.zeros((nt, m), dtype=complex)

            self.losses = np.zeros((nt, m), dtype=complex)

            self.flow_direction = np.zeros((nt, m), dtype=float)

            self.error = np.zeros(nt)

            self.converged = np.ones(nt, dtype=bool)  # guilty assumption

            self.overloads = [None] * nt

            self.overvoltage = [None] * nt

            self.undervoltage = [None] * nt

            self.overloads_idx = [None] * nt

            self.overvoltage_idx = [None] * nt

            self.undervoltage_idx = [None] * nt

            self.buses_useful_for_storage = [None] * nt

        else:
            self.voltage = None

            self.S = None

            self.Sbranch = None

            self.Ibranch = None

            self.Vbranch = None

            self.loading = None

            self.losses = None

            self.flow_direction = None

            self.error = None

            self.converged = None

            self.overloads = None

            self.overvoltage = None

            self.undervoltage = None

            self.overloads_idx = None

            self.overvoltage_idx = None

            self.undervoltage_idx = None

            self.buses_useful_for_storage = None

        self.otdf = np.zeros((m, m))

        self.available_results = [
            ResultTypes.OTDF, ResultTypes.BusVoltageModule,
            ResultTypes.BusVoltageAngle, ResultTypes.BusActivePower,
            ResultTypes.BusReactivePower, ResultTypes.BranchPower,
            ResultTypes.BranchCurrent, ResultTypes.BranchLoading,
            ResultTypes.BranchLosses, ResultTypes.BranchVoltage,
            ResultTypes.BranchAngles, ResultTypes.OTDFSimulationError
        ]
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """

        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function
        self.circuit.time_series_results = TimeSeriesResults(0, 0, 0, 0, 0)
        Sbase = self.circuit.Sbase

        it = 0
        variance_sum = 0.0
        std_dev_progress = 0
        v_variance = 0

        n = len(self.circuit.buses)
        m = len(self.circuit.branches)

        # compile circuits
        numerical_circuit = self.circuit.compile()

        # perform the topological computation
        calc_inputs_dict = numerical_circuit.compute_ts(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode,
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        mc_results = MonteCarloResults(n, m)
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        v_sum = zeros(n, dtype=complex)

        self.progress_signal.emit(0.0)

        while (std_dev_progress <
               100.0) and (it < self.max_mc_iter) and not self.__cancel__:

            self.progress_text.emit('Running Monte Carlo: Variance: ' +
                                    str(v_variance))

            mc_results = MonteCarloResults(n, m, self.batch_size)

            # for each partition of the profiles...
            for t_key, calc_inputs in calc_inputs_dict.items():

                # For every island, run the time series
                for island_index, numerical_island in enumerate(calc_inputs):

                    # set the time series as sampled
                    monte_carlo_input = make_monte_carlo_input(
                        numerical_island)
                    mc_time_series = monte_carlo_input(
                        self.batch_size, use_latin_hypercube=False)
                    Vbus = numerical_island.Vbus

                    # run the time series
                    for t in range(self.batch_size):
                        # set the power values
                        Y, I, S = mc_time_series.get_at(t)

                        res = single_island_pf(
                            circuit=numerical_island,
                            Vbus=Vbus,
                            Sbus=S / Sbase,
                            Ibus=I / Sbase,
                            branch_rates=numerical_island.branch_rates,
                            options=self.options,
                            logger=self.logger)

                        mc_results.S_points[
                            t, numerical_island.original_bus_idx] = res.Sbus
                        mc_results.V_points[
                            t, numerical_island.original_bus_idx] = res.voltage
                        mc_results.I_points[
                            t,
                            numerical_island.original_branch_idx] = res.Ibranch
                        mc_results.loading_points[
                            t,
                            numerical_island.original_branch_idx] = res.loading
                        mc_results.losses_points[
                            t,
                            numerical_island.original_branch_idx] = res.losses

                    # short cut the indices
                    b_idx = numerical_island.original_bus_idx
                    br_idx = numerical_island.original_branch_idx

                self.progress_text.emit('Compiling results...')
                mc_results.compile()

                # compute the island branch results
                island_avg_res = numerical_island.compute_branch_results(
                    mc_results.voltage[b_idx])

                # apply the island averaged results
                avg_res.apply_from_island(island_avg_res,
                                          b_idx=b_idx,
                                          br_idx=br_idx)

            # Compute the Monte Carlo values
            it += self.batch_size
            mc_results.append_batch(mc_results)
            v_sum += mc_results.get_voltage_sum()
            v_avg = v_sum / it
            v_variance = abs(
                (power(mc_results.V_points - v_avg, 2.0) / (it - 1)).min())

            # progress
            variance_sum += v_variance
            err = variance_sum / it
            if err == 0:
                err = 1e-200  # to avoid division by zeros
            mc_results.error_series.append(err)

            # emmit the progress signal
            std_dev_progress = 100 * self.mc_tol / err
            if std_dev_progress > 100:
                std_dev_progress = 100
            self.progress_signal.emit(
                max((std_dev_progress, it / self.max_mc_iter * 100)))

            # print(iter, '/', max_mc_iter)
            # print('Vmc:', Vavg)
            # print('Vstd:', Vvariance, ' -> ', std_dev_progress, ' %')

        # compile results
        mc_results.sbranch = avg_res.Sbranch
        # mc_results.losses = avg_res.losses
        mc_results.bus_types = numerical_circuit.bus_types

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return mc_results
Exemple #23
0
    def run_multi_thread(self):
        """
        Run the monte carlo simulation
        @return: StochasticPowerFlowResults instance
        """

        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function
        # self.circuit.time_series_results = TimeSeriesResults(0, 0, [])
        self.pool = multiprocessing.Pool()
        it = 0
        variance_sum = 0.0
        std_dev_progress = 0
        v_variance = 0

        n = len(self.circuit.buses)
        m = self.circuit.get_branch_number()

        mc_results = StochasticPowerFlowResults(n, m, name='Monte Carlo')
        avg_res = PowerFlowResults()
        avg_res.initialize(n, m)

        # compile circuits
        numerical_circuit = self.circuit.compile_time_series()

        # perform the topological computation
        calc_inputs_dict = numerical_circuit.compute(
            branch_tolerance_mode=self.options.branch_impedance_tolerance_mode,
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        mc_results.bus_types = numerical_circuit.bus_types

        v_sum = np.zeros(n, dtype=complex)

        self.progress_signal.emit(0.0)

        while (std_dev_progress <
               100.0) and (it < self.sampling_points) and not self.__cancel__:

            self.progress_text.emit('Running Monte Carlo: Variance: ' +
                                    str(v_variance))

            mc_results = StochasticPowerFlowResults(n,
                                                    m,
                                                    self.batch_size,
                                                    name='Monte Carlo')

            # for each partition of the profiles...
            for t_key, calc_inputs in calc_inputs_dict.items():

                # For every island, run the time series
                for island_index, numerical_island in enumerate(calc_inputs):

                    # set the time series as sampled
                    monte_carlo_input = make_monte_carlo_input(
                        numerical_island)
                    mc_time_series = monte_carlo_input(
                        self.batch_size, use_latin_hypercube=False)
                    Vbus = numerical_island.Vbus
                    branch_rates = numerical_island.branch_rates

                    # short cut the indices
                    b_idx = numerical_island.original_bus_idx
                    br_idx = numerical_island.original_branch_idx

                    self.returned_results = list()

                    t = 0
                    while t < self.batch_size and not self.__cancel__:

                        Ysh, Ibus, Sbus = mc_time_series.get_at(t)

                        args = (t, self.options, numerical_island, Vbus, Sbus,
                                Ibus, branch_rates)

                        self.pool.apply_async(power_flow_worker_args, (args, ),
                                              callback=self.update_progress_mt)

                    # wait for all jobs to complete
                    self.pool.close()
                    self.pool.join()

                    # collect results
                    self.progress_text.emit('Collecting batch results...')
                    for t, res in self.returned_results:
                        # store circuit results at the time index 't'
                        mc_results.S_points[
                            t, numerical_island.original_bus_idx] = res.Sbus
                        mc_results.V_points[
                            t, numerical_island.original_bus_idx] = res.voltage
                        mc_results.Sbr_points[
                            t, numerical_island.original_branch_idx] = res.Sf
                        mc_results.loading_points[
                            t,
                            numerical_island.original_branch_idx] = res.loading
                        mc_results.losses_points[
                            t,
                            numerical_island.original_branch_idx] = res.losses

                    # compile MC results
                    self.progress_text.emit('Compiling results...')
                    mc_results.compile()

                    # compute the island branch results
                    island_avg_res = numerical_island.compute_branch_results(
                        mc_results.voltage[b_idx])

                    # apply the island averaged results
                    avg_res.apply_from_island(island_avg_res,
                                              b_idx=b_idx,
                                              br_idx=br_idx)

            # Compute the Monte Carlo values
            it += self.batch_size
            mc_results.append_batch(mc_results)
            v_sum += mc_results.get_voltage_sum()
            v_avg = v_sum / it
            v_variance = np.abs(
                (np.power(mc_results.V_points - v_avg, 2.0) / (it - 1)).min())

            # progress
            variance_sum += v_variance
            err = variance_sum / it
            if err == 0:
                err = 1e-200  # to avoid division by zeros
            mc_results.error_series.append(err)

            # emmit the progress signal
            std_dev_progress = 100 * self.mc_tol / err
            if std_dev_progress > 100:
                std_dev_progress = 100
            self.progress_signal.emit(
                max((std_dev_progress, it / self.sampling_points * 100)))

        # compute the averaged branch magnitudes
        mc_results.sbranch = avg_res.Sf
        mc_results.losses = avg_res.losses

        # print('V mc: ', mc_results.voltage)

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return mc_results
Exemple #24
0
    def __init__(self, n, m, nt, start, end, time=None):
        """
        TimeSeriesResults constructor
        @param n: number of buses
        @param m: number of branches
        @param nt: number of time steps
        """
        PowerFlowResults.__init__(self)

        self.nt = nt
        self.m = m
        self.n = n
        self.start = start
        self.end = end

        self.time = time

        self.bus_types = zeros(n, dtype=int)

        if nt > 0:
            self.voltage = zeros((nt, n), dtype=complex)

            self.S = zeros((nt, n), dtype=complex)

            self.Sbranch = zeros((nt, m), dtype=complex)

            self.Ibranch = zeros((nt, m), dtype=complex)

            self.Vbranch = zeros((nt, m), dtype=complex)

            self.loading = zeros((nt, m), dtype=complex)

            self.losses = zeros((nt, m), dtype=complex)

            self.flow_direction = zeros((nt, m), dtype=float)

            self.error = zeros(nt)

            self.converged = ones(nt, dtype=bool)  # guilty assumption

            self.overloads = [None] * nt

            self.overvoltage = [None] * nt

            self.undervoltage = [None] * nt

            self.overloads_idx = [None] * nt

            self.overvoltage_idx = [None] * nt

            self.undervoltage_idx = [None] * nt

            self.buses_useful_for_storage = [None] * nt

        else:
            self.voltage = None

            self.S = None

            self.Sbranch = None

            self.Ibranch = None

            self.Vbranch = None

            self.loading = None

            self.losses = None

            self.flow_direction = None

            self.error = None

            self.converged = None

            self.overloads = None

            self.overvoltage = None

            self.undervoltage = None

            self.overloads_idx = None

            self.overvoltage_idx = None

            self.undervoltage_idx = None

            self.buses_useful_for_storage = None

        self.available_results = [ResultTypes.BusVoltageModule,
                                  ResultTypes.BusVoltageAngle,
                                  ResultTypes.BusActivePower,
                                  ResultTypes.BusReactivePower,
                                  ResultTypes.BranchPower,
                                  ResultTypes.BranchCurrent,
                                  ResultTypes.BranchLoading,
                                  ResultTypes.BranchLosses,
                                  ResultTypes.BranchVoltage,
                                  ResultTypes.BranchAngles,
                                  ResultTypes.SimulationError]
Exemple #25
0
    def run_single_thread_mc(self):

        self.__cancel__ = False

        # initialize the grid time series results
        # we will append the island results with another function

        # batch_size = self.sampling_points

        self.progress_signal.emit(0.0)
        self.progress_text.emit('Running Monte Carlo Sampling...')

        # compile the multi-circuit
        numerical_circuit = compile_time_circuit(
            circuit=self.circuit,
            apply_temperature=False,
            branch_tolerance_mode=BranchImpedanceMode.Specified,
            opf_results=self.opf_time_series_results)

        # do the topological computation
        calculation_inputs = numerical_circuit.split_into_islands(
            ignore_single_node_islands=self.options.ignore_single_node_islands)

        mc_results = StochasticPowerFlowResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            p=self.sampling_points,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            bus_types=numerical_circuit.bus_types,
            name='Monte Carlo')

        avg_res = PowerFlowResults(
            n=numerical_circuit.nbus,
            m=numerical_circuit.nbr,
            n_tr=numerical_circuit.ntr,
            n_hvdc=numerical_circuit.nhvdc,
            bus_names=numerical_circuit.bus_names,
            branch_names=numerical_circuit.branch_names,
            transformer_names=numerical_circuit.tr_names,
            hvdc_names=numerical_circuit.hvdc_names,
            bus_types=numerical_circuit.bus_types)

        variance_sum = 0.0
        v_sum = np.zeros(numerical_circuit.nbus, dtype=complex)

        # For every island, run the time series
        for island_index, numerical_island in enumerate(calculation_inputs):

            # try:
            # set the time series as sampled in the circuit
            # build the inputs
            monte_carlo_input = make_monte_carlo_input(numerical_island)
            mc_time_series = monte_carlo_input(self.sampling_points,
                                               use_latin_hypercube=False)
            Vbus = numerical_island.Vbus[:, 0]

            # short cut the indices
            bus_idx = numerical_island.original_bus_idx
            br_idx = numerical_island.original_branch_idx

            # run the time series
            for t in range(self.sampling_points):

                # set the power values from a Monte carlo point at 't'
                Y, I, S = mc_time_series.get_at(t)

                # Run the set monte carlo point at 't'
                res = single_island_pf(
                    circuit=numerical_island,
                    Vbus=Vbus,
                    Sbus=S,
                    Ibus=I,
                    branch_rates=numerical_island.branch_rates,
                    options=self.options,
                    logger=self.logger)

                # Gather the results
                mc_results.S_points[t, bus_idx] = S
                mc_results.V_points[t, bus_idx] = res.voltage
                mc_results.Sbr_points[t, br_idx] = res.Sf
                mc_results.loading_points[t, br_idx] = res.loading
                mc_results.losses_points[t, br_idx] = res.losses

                # determine when to stop
                if t > 1:
                    v_sum += mc_results.get_voltage_sum()
                    v_avg = v_sum / t
                    v_variance = np.abs(
                        (np.power(mc_results.V_points - v_avg, 2.0) /
                         (t - 1)).min())

                    # progress
                    variance_sum += v_variance
                    err = variance_sum / t
                    if err == 0:
                        err = 1e-200  # to avoid division by zeros
                    mc_results.error_series.append(err)

                    # emmit the progress signal
                    std_dev_progress = 100 * self.mc_tol / err
                    if std_dev_progress > 100:
                        std_dev_progress = 100
                    self.progress_signal.emit(
                        max((std_dev_progress,
                             t / self.sampling_points * 100)))

                if self.__cancel__:
                    break

            if self.__cancel__:
                break

            # compile MC results
            self.progress_text.emit('Compiling results...')
            mc_results.compile()

            # compute the island branch results
            Sfb, Stb, If, It, Vbranch, loading, \
            losses, flow_direction, Sbus = power_flow_post_process(numerical_island,
                                                                   Sbus=mc_results.S_points.mean(axis=0)[bus_idx],
                                                                   V=mc_results.V_points.mean(axis=0)[bus_idx],
                                                                   branch_rates=numerical_island.branch_rates)

            # apply the island averaged results
            avg_res.Sbus[bus_idx] = Sbus
            avg_res.voltage[bus_idx] = mc_results.voltage[bus_idx]
            avg_res.Sf[br_idx] = Sfb
            avg_res.St[br_idx] = Stb
            avg_res.If[br_idx] = If
            avg_res.It[br_idx] = It
            avg_res.Vbranch[br_idx] = Vbranch
            avg_res.loading[br_idx] = loading
            avg_res.losses[br_idx] = losses
            avg_res.flow_direction[br_idx] = flow_direction

        self.results = mc_results

        # send the finnish signal
        self.progress_signal.emit(0.0)
        self.progress_text.emit('Done!')
        self.done_signal.emit()

        return mc_results