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()
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
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 ]
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
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
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
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
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
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
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
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
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
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
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
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
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]
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