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