def run_single_thread(self) -> TimeSeriesResults: """ Run single thread time series :return: TimeSeriesResults instance """ # initialize the grid time series results we will append the island results with another function n = len(self.grid.buses) m = len(self.grid.branches) nt = self.number_of_steps time_series_results = TimeSeriesResults( n, m, nt, start=0, end=self.number_of_steps, time_array=self.grid.time_profile[self.steps]) # compile the multi-circuit numerical_circuit = self.grid.compile( opf_time_series_results=self.opf_time_series_results) # do 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) time_series_results.bus_types = numerical_circuit.bus_types # 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, calculation_input in enumerate(calc_inputs): # Are we dispatching storage? if so, generate a dictionary of battery -> bus index # to be able to set the batteries values into the vector S batteries = list() batteries_bus_idx = list() if self.options.dispatch_storage: for k, bus in enumerate(self.grid.buses): for battery in bus.batteries: battery.reset() # reset the calculation values batteries.append(battery) batteries_bus_idx.append(k) self.progress_text.emit('Time series at circuit ' + str(island_index) + '...') # find the original indices bus_original_idx = calculation_input.original_bus_idx branch_original_idx = calculation_input.original_branch_idx # if there are valid profiles... if self.grid.time_profile is not None: # declare a results object for the partition # nt = calculation_input.ntime n = calculation_input.nbus m = calculation_input.nbr results = TimeSeriesResults(n, m, nt, 0, nt) last_voltage = calculation_input.Vbus self.progress_signal.emit(0.0) # default value in case of single-valued profile dt = 1.0 # traverse the time profiles of the partition and simulate each time step for it, t in enumerate(self.steps): # set the power values # if the storage dispatch option is active, the batteries power is not included # therefore, it shall be included after processing Ysh = calculation_input.Ysh_prof[:, t] I = calculation_input.Ibus_prof[:, t] S = calculation_input.Sbus_prof[:, t] branch_rates = calculation_input.branch_rates_prof[ t, :] # add the controlled storage power if we are controlling the storage devices if self.options.dispatch_storage: if (it + 1) < len( calculation_input.original_time_idx): # compute the time delta: the time values come in nanoseconds dt = (calculation_input.time_array[it + 1] - calculation_input.time_array[it] ).value * 1e-9 / 3600.0 for k, battery in enumerate(batteries): power = battery.get_processed_at( it, dt=dt, store_values=True) bus_idx = batteries_bus_idx[k] S[bus_idx] += power / calculation_input.Sbase else: pass # run power flow at the circuit res = single_island_pf(circuit=calculation_input, Vbus=last_voltage, Sbus=S, Ibus=I, branch_rates=branch_rates, options=self.options, logger=self.logger) # Recycle voltage solution # last_voltage = res.voltage # store circuit results at the time index 't' results.set_at(it, res) progress = ((it + 1) / self.number_of_steps) * 100 self.progress_signal.emit(progress) self.progress_text.emit('Simulating island ' + str(island_index) + ' at ' + str(self.grid.time_profile[t])) if self.__cancel__: # merge the circuit's results time_series_results.apply_from_island( results, bus_original_idx, branch_original_idx, np.array( range(self.number_of_steps) ), #np.array(calculation_input.original_time_idx)[self.steps], 'TS') # abort by returning at this point return time_series_results # merge the circuit's results time_series_results.apply_from_island( results, bus_original_idx, branch_original_idx, np.array(range(self.number_of_steps)), 'TS') else: print('There are no profiles') self.progress_text.emit('There are no profiles') return time_series_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 = split_time_circuit_into_islands( numeric_circuit=numerical_circuit, 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[0, :], 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.Sbranch 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 Sbranch, Ibranch, 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[0, :]) # apply the island averaged results avg_res.Sbus[bus_idx] = Sbus avg_res.voltage[bus_idx] = lhs_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 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: """ 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) 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, 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 # 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, 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.Sbr_points[t, numerical_island.original_branch_idx] = res.Sbranch 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))) # 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_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 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, 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) Sbase = numerical_circuit.Sbase 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 / Sbase, Ibus=I / Sbase, 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 n_minus_k_mt(self, k=1, indices=None, vmin=200, states_number_limit=None): """ Run N-K simulation in series :param k: Parameter level (1 for n-1, 2 for n-2, etc...) :param indices: time indices {np.array([0])} :param vmin: minimum nominal voltage to allow (filters out branches and buses below) :param states_number_limit: limit the amount of states :return: Nothing, saves a report """ self.progress_text.emit("Filtering elements by voltage") # filter branches branch_names = list() branch_index = list() branches = list() # list of filtered branches for i, branch in enumerate(self.grid.branches): if branch.bus_from.Vnom > vmin or branch.bus_to.Vnom > vmin: branch_names.append(branch.name) branch_index.append(i) branches.append(branch) branch_index = np.array(branch_index) # filter buses bus_names = list() bus_index = list() for i, bus in enumerate(self.grid.buses): if bus.Vnom > vmin: bus_names.append(bus.name) bus_index.append(i) bus_index = np.array(bus_index) # get N-k states self.progress_text.emit("Enumerating states") states, failed_indices = enumerate_states_n_k(m=len(branch_names), k=k) # limit states for memory reasons if states_number_limit is not None: states = states[:states_number_limit, :] failed_indices = failed_indices[:states_number_limit] # compile the multi-circuit self.progress_text.emit("Compiling assets...") self.progress_signal.emit(0) numerical_circuit = self.grid.compile(use_opf_vals=False, opf_time_series_results=None) # if no base profile time is given, pick the base values if indices is None: time_indices = np.array([0]) numerical_circuit.set_base_profile() else: time_indices = indices # re-index the profile (this is essential for time-compatibility) self.progress_signal.emit(100) # construct the profile indices profile_indices = np.tile(time_indices, len(states)) numerical_circuit.re_index_time(t_idx=profile_indices) # set the branch states numerical_circuit.branch_active_prof[:, branch_index] = np.tile( states, (len(time_indices), 1)) # initialize the power flow pf_options = PowerFlowOptions(solver_type=SolverType.LACPF) # initialize the grid time series results we will append the island results with another function n = len(self.grid.buses) m = len(self.grid.branches) nt = len(profile_indices) n_k_results = NMinusKResults(n, m, nt, time_array=numerical_circuit.time_array, states=states) # do the topological computation self.progress_text.emit("Compiling topology...") self.progress_signal.emit(0.0) calc_inputs_dict = numerical_circuit.compute_ts( ignore_single_node_islands=pf_options.ignore_single_node_islands) n_k_results.bus_types = numerical_circuit.bus_types # 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, calculation_input in enumerate(calc_inputs): # find the original indices bus_original_idx = calculation_input.original_bus_idx branch_original_idx = calculation_input.original_branch_idx # if there are valid profiles... if self.grid.time_profile is not None: # declare a results object for the partition # nt = calculation_input.ntime nt = len(calculation_input.original_time_idx) n = calculation_input.nbus m = calculation_input.nbr partial_results = NMinusKResults(n, m, nt) last_voltage = calculation_input.Vbus # traverse the time profiles of the partition and simulate each time step for it, t in enumerate( calculation_input.original_time_idx): self.progress_signal.emit(it / nt * 100.0) # set the power values # if the storage dispatch option is active, the batteries power is not included # therefore, it shall be included after processing Ysh = calculation_input.Ysh_prof[:, it] I = calculation_input.Ibus_prof[:, it] S = calculation_input.Sbus_prof[:, it] branch_rates = calculation_input.branch_rates_prof[ it, :] # run power flow at the circuit res = single_island_pf(circuit=calculation_input, Vbus=last_voltage, Sbus=S, Ibus=I, branch_rates=branch_rates, options=pf_options, logger=self.logger) # Recycle voltage solution last_voltage = res.voltage # store circuit results at the time index 't' partial_results.set_at(it, res) # merge the circuit's results n_k_results.apply_from_island( partial_results, bus_original_idx, branch_original_idx, calculation_input.original_time_idx, 'TS') else: self.progress_text.emit('There are no profiles') self.logger.append('There are no profiles') return n_k_results
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 run_single_thread(self, time_indices) -> TimeSeriesResults: """ Run single thread time series :param time_indices: array of time indices to consider :return: TimeSeriesResults instance """ # compile the multi-circuit time_circuit = compile_time_circuit( circuit=self.grid, apply_temperature=False, branch_tolerance_mode=BranchImpedanceMode.Specified, opf_results=self.opf_time_series_results) # do the topological computation time_islands = time_circuit.split_into_islands( ignore_single_node_islands=self.options.ignore_single_node_islands) # initialize the grid time series results we will append the island results with another function time_series_results = TimeSeriesResults( n=time_circuit.nbus, m=time_circuit.nbr, n_tr=time_circuit.ntr, n_hvdc=time_circuit.nhvdc, bus_names=time_circuit.bus_names, branch_names=time_circuit.branch_names, transformer_names=time_circuit.tr_names, hvdc_names=time_circuit.hvdc_names, bus_types=time_circuit.bus_types, time_array=self.grid.time_profile[time_indices]) time_series_results.bus_types = time_circuit.bus_types # For every island, run the time series for island_index, calculation_input in enumerate(time_islands): # fill in Vbus, Sbus Ibus # calculation_input.consolidate() # Are we dispatching storage? if so, generate a dictionary of battery -> bus index # to be able to set the batteries values into the vector S batteries = list() batteries_bus_idx = list() if self.options.dispatch_storage: for k, bus in enumerate(self.grid.buses): for battery in bus.batteries: battery.reset() # reset the calculation values batteries.append(battery) batteries_bus_idx.append(k) self.progress_text.emit('Time series at circuit ' + str(island_index) + '...') # find the original indices bus_original_idx = calculation_input.original_bus_idx branch_original_idx = calculation_input.original_branch_idx # declare a results object for the partition results = TimeSeriesResults( n=calculation_input.nbus, m=calculation_input.nbr, n_tr=calculation_input.ntr, n_hvdc=calculation_input.nhvdc, bus_names=calculation_input.bus_names, branch_names=calculation_input.branch_names, transformer_names=calculation_input.tr_names, hvdc_names=calculation_input.hvdc_names, bus_types=time_circuit.bus_types, time_array=self.grid.time_profile[time_indices]) self.progress_signal.emit(0.0) # default value in case of single-valued profile dt = 1.0 # traverse the time profiles of the partition and simulate each time step for it, t in enumerate(time_indices): # set the power values # if the storage dispatch option is active, the batteries power is not included # therefore, it shall be included after processing V = calculation_input.Vbus[:, it] # Ysh = calculation_input.Yshunt_from_devices[:, it] I = calculation_input.Ibus[:, it] S = calculation_input.Sbus[:, it] branch_rates = calculation_input.Rates[:, it] # add the controlled storage power if we are controlling the storage devices if self.options.dispatch_storage: if (it + 1) < len(calculation_input.original_time_idx): # compute the time delta: the time values come in nanoseconds dt = (calculation_input.time_array[it + 1] - calculation_input.time_array[it] ).value * 1e-9 / 3600.0 for k, battery in enumerate(batteries): power = battery.get_processed_at(it, dt=dt, store_values=True) bus_idx = batteries_bus_idx[k] S[bus_idx] += power / calculation_input.Sbase # run power flow at the circuit res = single_island_pf(circuit=calculation_input, Vbus=V, Sbus=S, Ibus=I, branch_rates=branch_rates, options=self.options, logger=self.logger) # Recycle voltage solution # last_voltage = res.voltage # store circuit results at the time index 'it' results.set_at(it, res) progress = ((t - self.start_ + 1) / (self.end_ - self.start_)) * 100 self.progress_signal.emit(progress) self.progress_text.emit('Simulating island ' + str(island_index) + ' at ' + str(self.grid.time_profile[t])) if self.__cancel__: # merge the circuit's results time_series_results.apply_from_island( results, bus_original_idx, branch_original_idx, time_indices, 'TS') # abort by returning at this point return time_series_results # merge the circuit's results time_series_results.apply_from_island(results, bus_original_idx, branch_original_idx, time_indices, 'TS') # set the HVDC results here since the HVDC is not a branch in this modality time_series_results.hvdc_Pf = -time_circuit.hvdc_Pf.T time_series_results.hvdc_Pt = -time_circuit.hvdc_Pt.T time_series_results.hvdc_loading = time_circuit.hvdc_loading.T time_series_results.hvdc_losses = time_circuit.hvdc_losses.T return time_series_results
def time_series_worker(n, m, time_profile, namespace, options: PowerFlowOptions, time_indices, logger: Logger) -> (TimeSeriesResults, np.array): """ :param n: :param m: :param time_profile: :param options: :param time_indices: array of time indices to consider :param logger: :return: TimeSeriesResults instance """ # initialize the grid time series results we will append the island results with another function time_series_results = TimeSeriesResults( n, m, time_array=time_profile[time_indices]) calc_inputs_dict = namespace.calc_inputs_dict time_series_results.bus_types = namespace.bus_types # 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, calculation_input in enumerate(calc_inputs): # find the original indices bus_original_idx = calculation_input.original_bus_idx branch_original_idx = calculation_input.original_branch_idx # if there are valid profiles... if time_profile is not None: # declare a results object for the partition results = TimeSeriesResults( n=calculation_input.nbus, m=calculation_input.nbr, time_array=time_profile[time_indices]) last_voltage = calculation_input.Vbus # default value in case of single-valued profile dt = 1.0 # traverse the time profiles of the partition and simulate each time step for it, t in enumerate(time_indices): # set the power values # if the storage dispatch option is active, the batteries power is not included # therefore, it shall be included after processing Ysh = calculation_input.Ysh_prof[:, it] I = calculation_input.Ibus_prof[:, it] S = calculation_input.Sbus_prof[:, it] branch_rates = calculation_input.branch_rates_prof[it, :] # add the controlled storage power if we are controlling the storage devices if options.dispatch_storage: if (it + 1) < len(calculation_input.original_time_idx): # compute the time delta: the time values come in nanoseconds dt = (calculation_input.time_array[it + 1] - calculation_input.time_array[it] ).value * 1e-9 / 3600.0 # run power flow at the circuit res = single_island_pf(circuit=calculation_input, Vbus=last_voltage, Sbus=S, Ibus=I, branch_rates=branch_rates, options=options, logger=logger) # store circuit results at the time index 'it' results.set_at(it, res) # merge the circuit's results time_series_results.apply_from_island(results, bus_original_idx, branch_original_idx, time_indices, 'TS') return time_series_results, time_indices