Exemple #1
0
    def run_multi_island(self, numerical_circuit, calculation_inputs, Vbus, Sbus, Ibus):
        """
        Power flow execution for optimization purposes
        Args:
            numerical_circuit:
            calculation_inputs:
            Vbus:
            Sbus:
            Ibus:

        Returns: PowerFlowResults instance

        """
        n = len(self.grid.buses)
        m = len(self.grid.branches)
        results = PowerFlowResults()
        results.initialize(n, m)

        if len(numerical_circuit.islands) > 1:

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

                if len(calculation_input.ref) > 0:

                    bus_original_idx = numerical_circuit.islands[i]
                    branch_original_idx = numerical_circuit.island_branches[i]

                    # run circuit power flow
                    res = self.run_pf(calculation_input,
                                      Vbus[bus_original_idx],
                                      Sbus[bus_original_idx],
                                      Ibus[bus_original_idx])

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

                else:
                    warn('There are no slack nodes in the island ' + str(i))
                    self.logger.append('There are no slack nodes in the island ' + str(i))
        else:

            # run circuit power flow
            results = self.run_pf(calculation_inputs[0], Vbus, Sbus, Ibus)

        return results
Exemple #2
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()

        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
Exemple #3
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()

        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
        # 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 #4
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()

        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 #5
0
    def run_single_thread(self):
        """
        Run the monte carlo simulation
        @return:
        """

        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)
        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()
        numerical_input_islands = numerical_circuit.compute()

        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 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

                # 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 = powerflow.run_at(t, mc=True)
                    res = power_flow.run_pf(circuit=numerical_island,
                                            Vbus=Vbus,
                                            Sbus=S / Sbase,
                                            Ibus=I / Sbase)

                    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

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

        return mc_results
Exemple #6
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

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

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

            self.Ibranch = 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.Qpv = Qpv

            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.Sbranch = None

            self.Ibranch = None

            self.loading = None

            self.losses = None

            self.flow_direction = None

            self.error = None

            self.converged = None

            # self.Qpv = Qpv

            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 = [
                'Bus voltage', 'Branch power', 'Branch current',
                'Branch_loading', 'Branch losses'
            ]
    def run(self, store_in_island=False):
        """
        Pack run_pf for the QThread
        :return:
        """
        # print('PowerFlow at ', self.grid.name)
        n = len(self.grid.buses)
        m = len(self.grid.branches)
        results = PowerFlowResults()
        results.initialize(n, m)
        # self.progress_signal.emit(0.0)
        Sbase = self.grid.Sbase

        # columns of the report
        col = ['Method', 'Converged?', 'Error', 'Elapsed (s)', 'Iterations']
        self.convergence_reports.clear()

        print('Compiling...', end='')
        numerical_circuit = self.grid.compile()
        calculation_inputs = numerical_circuit.compute()

        if len(numerical_circuit.islands) > 1:

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

                if len(calculation_input.ref) > 0:
                    Vbus = calculation_input.Vbus
                    Sbus = calculation_input.Sbus
                    Ibus = calculation_input.Ibus

                    # run circuit power flow
                    res = self.run_pf(calculation_input, Vbus, Sbus, Ibus)

                    bus_original_idx = numerical_circuit.islands[i]
                    branch_original_idx = numerical_circuit.island_branches[i]

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

                    # build the report
                    data = np.c_[results.methods[i],
                                 results.converged[i],
                                 results.error[i],
                                 results.elapsed[i],
                                 results.inner_iterations[i]]
                    df = pd.DataFrame(data, columns=col)
                    self.convergence_reports.append(df)
                else:
                    warn('There are no slack nodes in the island ' + str(i))
                    self.logger.append('There are no slack nodes in the island ' + str(i))
        else:
            # only one island
            Vbus = calculation_inputs[0].Vbus
            Sbus = calculation_inputs[0].Sbus
            Ibus = calculation_inputs[0].Ibus

            # run circuit power flow
            results = self.run_pf(calculation_inputs[0], Vbus, Sbus, Ibus)

            # build the report
            data = np.c_[results.methods[0],
                         results.converged[0],
                         results.error[0],
                         results.elapsed[0],
                         results.inner_iterations[0]]
            df = pd.DataFrame(data, columns=col)
            self.convergence_reports.append(df)

        self.last_V = results.voltage  # done inside single_power_flow

        # check the limits
        sum_dev = results.check_limits(F=numerical_circuit.F, T=numerical_circuit.T,
                                       Vmax=numerical_circuit.Vmax, Vmin=numerical_circuit.Vmin,
                                       wo=1, wv1=1, wv2=1)

        self.results = results

        return self.results
    def single_power_flow(self, circuit: CalculationInputs, solver_type: SolverType, voltage_solution, Sbus, Ibus):
        """
        Run a power flow simulation for a single circuit
        @param circuit:
        @param solver_type
        @param voltage_solution
        @return:
        """

        original_types = circuit.types.copy()
        ref, pq, pv, pqpv = self.compile_types(Sbus, original_types)

        any_control_issue = True  # guilty assumption...

        control_max_iter = 10

        inner_it = list()
        outer_it = 0
        elapsed = list()
        methods = list()
        converged_lst = list()
        errors = list()
        it = list()
        el = list()

        while any_control_issue and outer_it < control_max_iter:

            if len(circuit.ref) == 0:
                voltage_solution = zeros(len(Sbus), dtype=complex)
                normF = 0
                Scalc = Sbus.copy()
                any_control_issue = False
                converged = True
                warn('Not solving power flow because there is no slack bus')
                self.logger.append('Not solving power flow because there is no slack bus')
            else:
                # type HELM
                if solver_type == SolverType.HELM:
                    methods.append(SolverType.HELM)
                    voltage_solution, converged, normF, Scalc, it, el = helm(Vbus=voltage_solution,
                                                                             Sbus=Sbus,
                                                                             Ybus=circuit.Ybus,
                                                                             pq=pq,
                                                                             pv=pv,
                                                                             ref=ref,
                                                                             pqpv=pqpv,
                                                                             tol=self.options.tolerance,
                                                                             max_coefficient_count=self.options.max_iter)

                # type DC
                elif solver_type == SolverType.DC:
                    methods.append(SolverType.DC)
                    voltage_solution, converged, normF, Scalc, it, el = dcpf(Ybus=circuit.Ybus,
                                                                             Sbus=Sbus,
                                                                             Ibus=Ibus,
                                                                             V0=voltage_solution,
                                                                             ref=ref,
                                                                             pvpq=pqpv,
                                                                             pq=pq,
                                                                             pv=pv)

                # LAC PF
                elif solver_type == SolverType.LACPF:
                    methods.append(SolverType.LACPF)

                    voltage_solution, converged, normF, Scalc, it, el = lacpf(Y=circuit.Ybus,
                                                                              Ys=circuit.Yseries,
                                                                              S=Sbus,
                                                                              I=Ibus,
                                                                              Vset=voltage_solution,
                                                                              pq=pq,
                                                                              pv=pv)

                # Levenberg-Marquardt
                elif solver_type == SolverType.LM:
                    methods.append(SolverType.LM)
                    voltage_solution, converged, normF, Scalc, it, el = LevenbergMarquardtPF(
                        Ybus=circuit.Ybus,
                        Sbus=Sbus,
                        V0=voltage_solution,
                        Ibus=Ibus,
                        pv=pv,
                        pq=pq,
                        tol=self.options.tolerance,
                        max_it=self.options.max_iter)

                # Fast decoupled
                elif solver_type == SolverType.FASTDECOUPLED:
                    methods.append(SolverType.FASTDECOUPLED)
                    voltage_solution, converged, normF, Scalc, it, el = FDPF(Vbus=voltage_solution,
                                                                             Sbus=Sbus,
                                                                             Ibus=Ibus,
                                                                             Ybus=circuit.Ybus,
                                                                             B1=circuit.B1,
                                                                             B2=circuit.B2,
                                                                             pq=pq,
                                                                             pv=pv,
                                                                             pqpv=pqpv,
                                                                             tol=self.options.tolerance,
                                                                             max_it=self.options.max_iter)

                # Newton-Raphson
                elif solver_type == SolverType.NR:
                    methods.append(SolverType.NR)

                    # Solve NR with the linear AC solution
                    voltage_solution, converged, normF, Scalc, it, el = NR_LS(Ybus=circuit.Ybus,
                                                                              Sbus=Sbus,
                                                                              V0=voltage_solution,
                                                                              Ibus=Ibus,
                                                                              pv=pv,
                                                                              pq=pq,
                                                                              tol=self.options.tolerance,
                                                                              max_it=self.options.max_iter)

                # Newton-Raphson-Iwamoto
                elif solver_type == SolverType.IWAMOTO:
                    methods.append(SolverType.IWAMOTO)
                    voltage_solution, converged, normF, Scalc, it, el = IwamotoNR(Ybus=circuit.Ybus,
                                                                                  Sbus=Sbus,
                                                                                  V0=voltage_solution,
                                                                                  Ibus=Ibus,
                                                                                  pv=pv,
                                                                                  pq=pq,
                                                                                  tol=self.options.tolerance,
                                                                                  max_it=self.options.max_iter,
                                                                                  robust=True)

                # Newton-Raphson in current equations
                elif solver_type == SolverType.NRI:
                    methods.append(SolverType.NRI)
                    # NR_I_LS(Ybus, Sbus_sp, V0, Ibus_sp, pv, pq, tol, max_it
                    voltage_solution, converged, normF, Scalc, it, el = NR_I_LS(Ybus=circuit.Ybus,
                                                                                Sbus_sp=Sbus,
                                                                                V0=voltage_solution,
                                                                                Ibus_sp=Ibus,
                                                                                pv=pv,
                                                                                pq=pq,
                                                                                tol=self.options.tolerance,
                                                                                max_it=self.options.max_iter)

                # for any other method, for now, do a LM
                else:
                    methods.append(SolverType.LM)
                    voltage_solution, converged, \
                    normF, Scalc, it, el = LevenbergMarquardtPF(Ybus=circuit.Ybus,
                                                                Sbus=Sbus,
                                                                V0=voltage_solution,
                                                                Ibus=Ibus,
                                                                pv=pv,
                                                                pq=pq,
                                                                tol=self.options.tolerance,
                                                                max_it=self.options.max_iter)

                if converged:
                    # Check controls
                    if self.options.control_Q:
                        voltage_solution, \
                        Qnew, \
                        types_new, \
                        any_control_issue = self.switch_logic(V=voltage_solution,
                                                              Vset=abs(voltage_solution),
                                                              Q=Scalc.imag,
                                                              Qmax=circuit.Qmax,
                                                              Qmin=circuit.Qmin,
                                                              types=circuit.types,
                                                              original_types=original_types,
                                                              verbose=self.options.verbose)
                        if any_control_issue:
                            # voltage_solution = Vnew
                            Sbus = Sbus.real + 1j * Qnew
                            ref, pq, pv, pqpv = self.compile_types(Sbus, types_new)
                        else:
                            if self.options.verbose:
                                print('Controls Ok')

                    else:
                        # did not check Q limits
                        any_control_issue = False
                else:
                    any_control_issue = False

            # increment the inner iterations counter
            inner_it.append(it)

            # increment the outer control iterations counter
            outer_it += 1

            # add the time taken by the solver in this iteration
            elapsed.append(el)

            # append loop error
            errors.append(normF)

            # append converged
            converged_lst.append(bool(converged))

        # revert the types to the original
        # ref, pq, pv, pqpv = self.compile_types(original_types)

        # Compute the branches power and the slack buses power
        Sbranch, Ibranch, loading, losses, \
        flow_direction, Sbus = self.power_flow_post_process(calculation_inputs=circuit, V=voltage_solution)

        # voltage, Sbranch, loading, losses, error, converged, Qpv
        results = PowerFlowResults(Sbus=Sbus,
                                   voltage=voltage_solution,
                                   Sbranch=Sbranch,
                                   Ibranch=Ibranch,
                                   loading=loading,
                                   losses=losses,
                                   flow_direction=flow_direction,
                                   error=errors,
                                   converged=converged_lst,
                                   Qpv=None,
                                   inner_it=inner_it,
                                   outer_it=outer_it,
                                   elapsed=elapsed,
                                   methods=methods)

        return results
Exemple #9
0
    def run_pf(self, circuit: CalculationInputs, Vbus, Sbus, Ibus):
        """
        Run a power flow for a circuit
        Args:
            circuit:
            Vbus:
            Sbus:
            Ibus:
            battery_energy:

        Returns:

        """

        # Retry with another solver

        if self.options.auxiliary_solver_type is not None:
            solvers = [self.options.solver_type,
                       SolverType.IWAMOTO,
                       SolverType.FASTDECOUPLED,
                       SolverType.LM,
                       SolverType.LACPF]
        else:
            # No retry selected
            solvers = [self.options.solver_type]

        # set worked to false to enter in the loop
        worked = False
        k = 0
        methods = list()
        inner_it = list()
        elapsed = list()
        errors = list()
        converged_lst = list()
        outer_it = 0

        if not worked:

            while k < len(solvers) and not worked:

                # get the solver
                solver = solvers[k]

                # print('Trying', solver)

                # set the initial voltage
                V0 = Vbus.copy()

                results = self.single_power_flow(circuit=circuit,
                                                 solver_type=solver,
                                                 voltage_solution=V0,
                                                 Sbus=Sbus,
                                                 Ibus=Ibus)

                # did it worked?
                worked = np.all(results.converged)

                # record the solver steps
                methods += results.methods
                inner_it += results.inner_iterations
                outer_it += results.outer_iterations
                elapsed += results.elapsed
                errors += results.error
                converged_lst += results.converged

                k += 1

            if not worked:
                print('Did not converge, even after retry!, Error:', results.error)
                return None

            else:
                # set the total process variables:
                results.methods = methods
                results.inner_iterations = inner_it
                results.outer_iterations = outer_it
                results.elapsed = elapsed
                results.error = errors
                results.converged = converged_lst

                # check the power flow limits
                results.check_limits(F=circuit.F, T=circuit.T,
                                     Vmax=circuit.Vmax, Vmin=circuit.Vmin,
                                     wo=1, wv1=1, wv2=1)

                return results
        else:
            # the original solver worked
            pass

            return PowerFlowResults()
Exemple #10
0
    def single_power_flow(self, circuit: CalculationInputs, solver_type: SolverType, voltage_solution, Sbus, Ibus):
        """
        Run a power flow simulation for a single circuit using the selected outer loop controls
        :param circuit: CalculationInputs instance
        :param solver_type: type of power flow to use first
        :param voltage_solution: vector of initial voltages
        :param Sbus: vector of power injections
        :param Ibus: vector of current injections
        :return: PowerFlowResults instance
        """

        # get the original types and compile this class' own lists of node types for thread independence
        original_types = circuit.types.copy()
        ref, pq, pv, pqpv = self.compile_types(Sbus, original_types)

        # copy the tap positions
        tap_positions = circuit.tap_position.copy()

        tap_module = circuit.tap_mod.copy()

        any_q_control_issue = True  # guilty assumption...
        any_tap_control_issue = True

        # The control iterations are either the number of tap_regulated transformers or 10, the larger of the two
        control_max_iter = 10
        for k in circuit.bus_to_regulated_idx:   # indices of the branches that are regulated at the bus "to"
            control_max_iter = max(control_max_iter, circuit.max_tap[k] + circuit.min_tap[k])
        # control_max_iter = max(len(circuit.bus_to_regulated_idx), 10)

        inner_it = list()
        outer_it = 0
        elapsed = list()
        methods = list()
        converged_lst = list()
        errors = list()
        it = list()
        el = list()

        # this the "outer-loop"
        while (any_q_control_issue or any_tap_control_issue) and outer_it < control_max_iter:

            if len(circuit.ref) == 0:
                voltage_solution = zeros(len(Sbus), dtype=complex)
                normF = 0
                Scalc = Sbus.copy()
                any_q_control_issue = False
                converged = True
                warn('Not solving power flow because there is no slack bus')
                self.logger.append('Not solving power flow because there is no slack bus')
            else:

                # run the power flow method that shall be run
                voltage_solution, converged, normF, Scalc, it, el = self.solve(solver_type=solver_type,
                                                                               V0=voltage_solution,
                                                                               Sbus=Sbus,
                                                                               Ibus=Ibus,
                                                                               Ybus=circuit.Ybus,
                                                                               Yseries=circuit.Yseries,
                                                                               B1=circuit.B1,
                                                                               B2=circuit.B2,
                                                                               pq=pq,
                                                                               pv=pv,
                                                                               ref=ref,
                                                                               pqpv=pqpv,
                                                                               tolerance=self.options.tolerance,
                                                                               max_iter=self.options.max_iter)
                # record the method used
                methods.append(solver_type)

                if converged:
                    # Check controls
                    if self.options.control_Q:
                        voltage_solution, \
                            Qnew, \
                            types_new, \
                            any_q_control_issue = self.switch_logic(V=voltage_solution,
                                                                    Vset=np.abs(voltage_solution),
                                                                    Q=Scalc.imag,
                                                                    Qmax=circuit.Qmax,
                                                                    Qmin=circuit.Qmin,
                                                                    types=circuit.types,
                                                                    original_types=original_types,
                                                                    verbose=self.options.verbose)
                        if any_q_control_issue:
                            Sbus = Sbus.real + 1j * Qnew
                            ref, pq, pv, pqpv = self.compile_types(Sbus, types_new)
                        else:
                            if self.options.verbose:
                                print('Controls Ok')

                    else:
                        # did not check Q limits
                        any_q_control_issue = False

                    # control the transformer taps
                    if self.options.control_taps and any_tap_control_issue:

                        stable, tap_module, \
                            tap_positions = self.adjust_tap_changers(voltage=voltage_solution,
                                                                     T=circuit.T,
                                                                     bus_to_regulated_idx=circuit.bus_to_regulated_idx,
                                                                     tap_position=tap_positions,
                                                                     tap_module=tap_module,
                                                                     min_tap=circuit.min_tap,
                                                                     max_tap=circuit.max_tap,
                                                                     tap_inc_reg_up=circuit.tap_inc_reg_up,
                                                                     tap_inc_reg_down=circuit.tap_inc_reg_down,
                                                                     vset=circuit.vset,
                                                                     verbose=self.options.verbose)
                        # print('Recompiling Ybus due to tap changes')
                        # recompute the admittance matrices based on the tap changes
                        circuit.re_calc_admittance_matrices(tap_module)

                        any_tap_control_issue = not stable

                    else:
                        any_tap_control_issue = False

                else:
                    any_q_control_issue = False
                    any_tap_control_issue = False

            # increment the inner iterations counter
            inner_it.append(it)

            # increment the outer control iterations counter
            outer_it += 1

            # add the time taken by the solver in this iteration
            elapsed.append(el)

            # append loop error
            errors.append(normF)

            # append converged
            converged_lst.append(bool(converged))

        # Compute the branches power and the slack buses power
        Sbranch, Ibranch, loading, losses, \
        flow_direction, Sbus = self.power_flow_post_process(calculation_inputs=circuit, V=voltage_solution)

        # voltage, Sbranch, loading, losses, error, converged, Qpv
        results = PowerFlowResults(Sbus=Sbus,
                                   voltage=voltage_solution,
                                   Sbranch=Sbranch,
                                   Ibranch=Ibranch,
                                   loading=loading,
                                   losses=losses,
                                   flow_direction=flow_direction,
                                   tap_module=tap_module,
                                   error=errors,
                                   converged=converged_lst,
                                   Qpv=Sbus.imag[pv],
                                   inner_it=inner_it,
                                   outer_it=outer_it,
                                   elapsed=elapsed,
                                   methods=methods)

        return results