def run_events(nc: NumericalCircuit, events_list: list): for t, tpe, i, state in events_list: # Set the state of the event if tpe == DeviceType.BusDevice: pass elif tpe == DeviceType.BranchDevice: nc.branch_active[i] = state elif tpe == DeviceType.GeneratorDevice: nc.generator_active[i] = state elif tpe == DeviceType.StaticGeneratorDevice: nc.static_gen_active[i] = state elif tpe == DeviceType.BatteryDevice: nc.battery_active[i] = state elif tpe == DeviceType.ShuntDevice: nc.shunt_active[i] = state elif tpe == DeviceType.LoadDevice: nc.load_active[i] = state else: pass # compile the grid information calculation_islands = nc.compute()
def remove_probability_based(numerical_circuit: NumericalCircuit, results: MonteCarloResults, max_val, min_prob): """ Remove branches based on their chance of overload :param numerical_circuit: :param results: :param max_val: :param min_prob: :return: list of indices actually removed """ idx, val, prob, loading = results.get_index_loading_cdf( max_val=max_val) any_removed = False indices = list() criteria = 'None' for i, idx_val in enumerate(idx): if prob[i] >= min_prob: any_removed = True numerical_circuit.branch_active[idx_val] = False indices.append(idx_val) criteria = 'Overload probability > ' + str(min_prob) if not any_removed: if len(loading) > 0: if len(idx) > 0: # pick a random value idx_val = np.random.randint(0, len(idx)) criteria = 'Random with overloads' else: # pick the most loaded idx_val = int(np.where(loading == max(loading))[0][0]) criteria = 'Max loading, Overloads not seen' numerical_circuit.branch_active[idx_val] = False indices.append(idx_val) else: indices = [] criteria = 'No branches' return indices, criteria
def compile(self, use_opf_vals=False, opf_time_series_results=None, logger=Logger()) -> NumericalCircuit: """ Compile the circuit assets into an equivalent circuit that only contains matrices and vectors for calculation. This method returns the numerical circuit, but it also assigns it to **self.numerical_circuit**, which is used when the :ref:`MultiCircuit<multicircuit>` object is passed onto a :ref:`simulation driver<gridcal_engine_simulations>`, for example: .. code:: ipython3 from GridCal.Engine import * grid = MultiCircuit() grid.load_file("grid.xlsx") grid.compile() options = PowerFlowOptions() power_flow = PowerFlowMP(grid, options) power_flow.run() Arguments: **use_opf_vals** (bool, False): Use OPF results as inputs **opf_time_series_results** (list, None): OPF results to be used as inputs **logger** (list, []): Message log Returns: **self.numerical_circuit** (NumericalCircuit): Compiled numerical circuit of the grid """ n = len(self.buses) m = len(self.branches) if self.time_profile is not None: n_time = len(self.time_profile) else: n_time = 0 if use_opf_vals and opf_time_series_results is None: raise Exception('You want to use the OPF results but none is passed') self.bus_dictionary = dict() # Element count n_ld = 0 n_ctrl_gen = 0 n_sta_gen = 0 n_batt = 0 n_sh = 0 for bus in self.buses: n_ld += len(bus.loads) n_ctrl_gen += len(bus.controlled_generators) n_sta_gen += len(bus.static_generators) n_batt += len(bus.batteries) n_sh += len(bus.shunts) # declare the numerical circuit circuit = NumericalCircuit(n_bus=n, n_br=m, n_ld=n_ld, n_gen=n_ctrl_gen, n_sta_gen=n_sta_gen, n_batt=n_batt, n_sh=n_sh, n_time=n_time, Sbase=self.Sbase) # set hte time array profile if n_time > 0: circuit.time_array = self.time_profile # compile the buses and the shunt devices i_ld = 0 i_gen = 0 i_sta_gen = 0 i_batt = 0 i_sh = 0 self.bus_names = np.zeros(n, dtype=object) for i, bus in enumerate(self.buses): # bus parameters self.bus_names[i] = bus.name circuit.bus_names[i] = bus.name circuit.bus_active[i] = bus.active circuit.bus_vnom[i] = bus.Vnom # kV circuit.Vmax[i] = bus.Vmax circuit.Vmin[i] = bus.Vmin circuit.bus_types[i] = bus.determine_bus_type().value if n_time > 0: # active profile circuit.bus_active_prof[:, i] = bus.active_prof # Add buses dictionary entry self.bus_dictionary[bus] = i for elm in bus.loads: circuit.load_names[i_ld] = elm.name circuit.load_power[i_ld] = complex(elm.P, elm.Q) circuit.load_current[i_ld] = complex(elm.Ir, elm.Ii) circuit.load_admittance[i_ld] = complex(elm.G, elm.B) circuit.load_active[i_ld] = elm.active circuit.load_mttf[i_ld] = elm.mttf circuit.load_mttr[i_ld] = elm.mttr circuit.load_cost[i_ld] = elm.Cost if n_time > 0: circuit.load_power_profile[:, i_ld] = elm.P_prof + 1j * elm.Q_prof circuit.load_current_profile[:, i_ld] = elm.Ir_prof + 1j * elm.Ii_prof circuit.load_admittance_profile[:, i_ld] = elm.G_prof + 1j * elm.B_prof circuit.load_active_prof[:, i_ld] = elm.active_prof circuit.load_cost_prof[:, i_ld] = elm.Cost_prof if use_opf_vals: # subtract the load shedding from the generation circuit.load_power_profile[:, i_ld] -= opf_time_series_results.load_shedding[:, i_gen] circuit.C_load_bus[i_ld, i] = 1 i_ld += 1 for elm in bus.static_generators: circuit.static_gen_names[i_sta_gen] = elm.name circuit.static_gen_power[i_sta_gen] = complex(elm.P, elm.Q) circuit.static_gen_active[i_sta_gen] = elm.active circuit.static_gen_mttf[i_sta_gen] = elm.mttf circuit.static_gen_mttr[i_sta_gen] = elm.mttr if n_time > 0: circuit.static_gen_active_prof[:, i_sta_gen] = elm.active_prof circuit.static_gen_power_profile[:, i_sta_gen] = elm.P_prof + 1j * elm.Q_prof circuit.C_sta_gen_bus[i_sta_gen, i] = 1 i_sta_gen += 1 for elm in bus.controlled_generators: circuit.generator_names[i_gen] = elm.name circuit.generator_power[i_gen] = elm.P circuit.generator_power_factor[i_gen] = elm.Pf circuit.generator_voltage[i_gen] = elm.Vset circuit.generator_qmin[i_gen] = elm.Qmin circuit.generator_qmax[i_gen] = elm.Qmax circuit.generator_pmin[i_gen] = elm.Pmin circuit.generator_pmax[i_gen] = elm.Pmax circuit.generator_active[i_gen] = elm.active circuit.generator_dispatchable[i_gen] = elm.enabled_dispatch circuit.generator_mttf[i_gen] = elm.mttf circuit.generator_mttr[i_gen] = elm.mttr circuit.generator_cost[i_gen] = elm.Cost circuit.generator_nominal_power[i_gen] = elm.Snom if n_time > 0: # power profile if use_opf_vals: circuit.generator_power_profile[:, i_gen] = opf_time_series_results.controlled_generator_power[:, i_gen] else: circuit.generator_power_profile[:, i_gen] = elm.P_prof circuit.generator_active_prof[:, i_gen] = elm.active_prof # Power factor profile circuit.generator_power_factor_profile[:, i_gen] = elm.Pf_prof # Voltage profile circuit.generator_voltage_profile[:, i_gen] = elm.Vset_prof circuit.generator_cost_profile[:, i_gen] = elm.Cost_prof circuit.C_gen_bus[i_gen, i] = 1 if circuit.V0[i].real == 1.0: circuit.V0[i] = complex(elm.Vset, 0) elif elm.Vset != circuit.V0[i]: # circuit.V0[i] = elm.Vset logger.append('Different set points at ' + bus.name + ': ' + str(elm.Vset) + ' !=' + str(circuit.V0[i])) i_gen += 1 for elm in bus.batteries: # 'name', 'bus', 'active', 'P', 'Vset', 'Snom', 'Enom', # 'Qmin', 'Qmax', 'Pmin', 'Pmax', 'Cost', 'enabled_dispatch', 'mttf', 'mttr', # 'soc_0', 'max_soc', 'min_soc', 'charge_efficiency', 'discharge_efficiency' circuit.battery_names[i_batt] = elm.name circuit.battery_power[i_batt] = elm.P circuit.battery_voltage[i_batt] = elm.Vset circuit.battery_qmin[i_batt] = elm.Qmin circuit.battery_qmax[i_batt] = elm.Qmax circuit.battery_active[i_batt] = elm.active circuit.battery_dispatchable[i_batt] = elm.enabled_dispatch circuit.battery_mttf[i_batt] = elm.mttf circuit.battery_mttr[i_batt] = elm.mttr circuit.battery_cost[i_batt] = elm.Cost circuit.battery_pmin[i_batt] = elm.Pmin circuit.battery_pmax[i_batt] = elm.Pmax circuit.battery_Enom[i_batt] = elm.Enom circuit.battery_soc_0[i_batt] = elm.soc_0 circuit.battery_discharge_efficiency[i_batt] = elm.discharge_efficiency circuit.battery_charge_efficiency[i_batt] = elm.charge_efficiency circuit.battery_min_soc[i_batt] = elm.min_soc circuit.battery_max_soc[i_batt] = elm.max_soc if n_time > 0: # power profile if use_opf_vals: circuit.battery_power_profile[:, i_batt] = opf_time_series_results.battery_power[:, i_batt] else: circuit.battery_power_profile[:, i_batt] = elm.P_prof # Voltage profile circuit.battery_voltage_profile[:, i_batt] = elm.Vset_prof circuit.battery_active_prof[:, i_batt] = elm.active_prof circuit.battery_cost_profile[:, i_batt] = elm.Cost_prof circuit.C_batt_bus[i_batt, i] = 1 circuit.V0[i] *= elm.Vset i_batt += 1 for elm in bus.shunts: circuit.shunt_names[i_sh] = elm.name circuit.shunt_active[i_sh] = elm.active circuit.shunt_admittance[i_sh] = complex(elm.G, elm.B) circuit.shunt_mttf[i_sh] = elm.mttf circuit.shunt_mttr[i_sh] = elm.mttr if n_time > 0: circuit.shunt_active_prof[:, i_sh] = elm.active_prof circuit.shunt_admittance_profile[:, i_sh] = elm.G_prof + 1j * elm.B_prof circuit.C_shunt_bus[i_sh, i] = 1 i_sh += 1 # Compile the branches self.branch_names = np.zeros(m, dtype=object) for i, branch in enumerate(self.branches): self.branch_names[i] = branch.name f = self.bus_dictionary[branch.bus_from] t = self.bus_dictionary[branch.bus_to] # connectivity circuit.C_branch_bus_f[i, f] = 1 circuit.C_branch_bus_t[i, t] = 1 circuit.F[i] = f circuit.T[i] = t # name and state circuit.branch_names[i] = branch.name circuit.branch_active[i] = branch.active circuit.br_mttf[i] = branch.mttf circuit.br_mttr[i] = branch.mttr circuit.branch_cost[i] = branch.Cost # impedance and tap circuit.R[i] = branch.R circuit.X[i] = branch.X circuit.G[i] = branch.G circuit.B[i] = branch.B circuit.impedance_tolerance[i] = branch.tolerance circuit.br_rates[i] = branch.rate circuit.tap_mod[i] = branch.tap_module circuit.tap_ang[i] = branch.angle # Thermal correction circuit.temp_base[i] = branch.temp_base circuit.temp_oper[i] = branch.temp_oper circuit.alpha[i] = branch.alpha # tap changer circuit.is_bus_to_regulated[i] = branch.bus_to_regulated circuit.tap_position[i] = branch.tap_changer.tap circuit.min_tap[i] = branch.tap_changer.min_tap circuit.max_tap[i] = branch.tap_changer.max_tap circuit.tap_inc_reg_up[i] = branch.tap_changer.inc_reg_up circuit.tap_inc_reg_down[i] = branch.tap_changer.inc_reg_down circuit.vset[i] = branch.vset if n_time > 0: circuit.branch_active_prof[:, i] = branch.active_prof circuit.temp_oper_prof[:, i] = branch.temp_oper_prof circuit.branch_cost_profile[:, i] = branch.Cost_prof circuit.br_rate_profile[:, i] = branch.rate_prof # switches if branch.branch_type == BranchType.Switch: circuit.switch_indices.append(i) # virtual taps for transformers where the connection voltage is off elif branch.branch_type == BranchType.Transformer: circuit.tap_f[i], circuit.tap_t[i] = branch.get_virtual_taps() # Assign and return self.numerical_circuit = circuit return circuit