예제 #1
0
    def ptdf(self,
             circuit: MultiCircuit,
             options: PowerFlowOptions,
             group_mode: PtdfGroupMode,
             power_amount,
             text_func=None,
             prog_func=None):
        """
        Power Transfer Distribution Factors analysis
        :param circuit: MultiCircuit instance
        :param options: power flow options
        :param group_mode: group mode
        :param power_amount: amount o power to vary in MW
        :param text_func: text function to display progress
        :param prog_func: progress function to display progress [0~100]
        :return:
        """

        if text_func is not None:
            text_func('Compiling...')

        # compile to arrays
        numerical_circuit = compile_snapshot_circuit(
            circuit=circuit,
            apply_temperature=options.apply_temperature_correction,
            branch_tolerance_mode=options.branch_impedance_tolerance_mode,
            opf_results=self.opf_results)

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

        # compute the variations
        delta_of_power_variations = get_ptdf_variations(
            circuit=circuit,
            numerical_circuit=numerical_circuit,
            group_mode=group_mode,
            power_amount=power_amount)

        # declare the PTDF results
        results = PTDFResults(n_variations=len(delta_of_power_variations) - 1,
                              n_br=numerical_circuit.nbr,
                              n_bus=numerical_circuit.nbus,
                              br_names=numerical_circuit.branch_names,
                              bus_names=numerical_circuit.bus_names,
                              bus_types=numerical_circuit.bus_types)

        if text_func is not None:
            text_func('Running PTDF...')

        nvar = len(delta_of_power_variations)
        for v, variation in enumerate(delta_of_power_variations):

            # this super strange way of calling a function is done to maintain the same
            # call format as the multi-threading function
            returns = dict()
            power_flow_worker(variation=0,
                              nbus=numerical_circuit.nbus,
                              nbr=numerical_circuit.nbr,
                              n_tr=numerical_circuit.ntr,
                              bus_names=numerical_circuit.bus_names,
                              branch_names=numerical_circuit.branch_names,
                              transformer_names=numerical_circuit.tr_names,
                              bus_types=numerical_circuit.bus_types,
                              calculation_inputs=calculation_inputs,
                              options=options,
                              dP=variation.dP,
                              return_dict=returns)

            pf_results, log = returns[0]
            results.logger += log

            # add the power flow results
            if v == 0:
                results.default_pf_results = pf_results
            else:
                results.add_results_at(v - 1, pf_results, variation)

            if prog_func is not None:
                p = (v + 1) / nvar * 100.0
                prog_func(p)

            if self.__cancel__:
                break

        return results
예제 #2
0
    def ptdf_multi_treading(self,
                            circuit: MultiCircuit,
                            options: PowerFlowOptions,
                            group_mode: PtdfGroupMode,
                            power_amount,
                            text_func=None,
                            prog_func=None):
        """
        Power Transfer Distribution Factors analysis
        :param circuit: MultiCircuit instance
        :param options: power flow options
        :param group_mode: ptdf grouping mode
        :param power_amount: amount o power to vary in MW
        :param text_func:
        :param prog_func
        :return:
        """

        if text_func is not None:
            text_func('Compiling...')

        # compile to arrays
        # numerical_circuit = circuit.compile_snapshot()
        # calculation_inputs = numerical_circuit.compute(apply_temperature=options.apply_temperature_correction,
        #                                                branch_tolerance_mode=options.branch_impedance_tolerance_mode,
        #                                                ignore_single_node_islands=options.ignore_single_node_islands)

        numerical_circuit = compile_snapshot_circuit(
            circuit=circuit,
            apply_temperature=options.apply_temperature_correction,
            branch_tolerance_mode=options.branch_impedance_tolerance_mode,
            opf_results=self.opf_results)

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

        # compute the variations
        delta_of_power_variations = get_ptdf_variations(
            circuit=circuit,
            numerical_circuit=numerical_circuit,
            group_mode=group_mode,
            power_amount=power_amount)

        # declare the PTDF results
        results = PTDFResults(n_variations=len(delta_of_power_variations) - 1,
                              n_br=numerical_circuit.nbr,
                              n_bus=numerical_circuit.nbus,
                              br_names=numerical_circuit.branch_names,
                              bus_names=numerical_circuit.bus_names,
                              bus_types=numerical_circuit.bus_types)

        if text_func is not None:
            text_func('Running PTDF...')

        jobs = list()
        n_cores = multiprocessing.cpu_count()
        manager = multiprocessing.Manager()
        return_dict = manager.dict()

        # for v, variation in enumerate(delta_of_power_variations):
        v = 0
        nvar = len(delta_of_power_variations)
        while v < nvar:

            k = 0

            # launch only n_cores jobs at the time
            while k < n_cores + 2 and (v + k) < nvar:
                # run power flow at the circuit
                p = multiprocessing.Process(
                    target=power_flow_worker,
                    args=(v, numerical_circuit.nbus, numerical_circuit.nbr,
                          numerical_circuit.ntr, numerical_circuit.bus_names,
                          numerical_circuit.branch_names,
                          numerical_circuit.tr_names,
                          numerical_circuit.bus_types, calculation_inputs,
                          options, delta_of_power_variations[v].dP,
                          return_dict))
                jobs.append(p)
                p.start()
                v += 1
                k += 1

                if self.__cancel__:
                    break

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

            # emit the progress
            if prog_func is not None:
                p = (v + 1) / nvar * 100.0
                prog_func(p)

            if self.__cancel__:
                break

        if text_func is not None:
            text_func('Collecting results...')

        # gather the results
        if not self.__cancel__:
            for v in range(nvar):
                pf_results, log = return_dict[v]
                results.logger += log
                if v == 0:
                    results.default_pf_results = pf_results
                else:
                    results.add_results_at(v - 1, pf_results,
                                           delta_of_power_variations[v])

        return results