GridCal.Engine.Simulations.OPF package

GridCal.Engine.Simulations.OPF.maketrans()

Return a translation table usable for str.translate().

If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters to Unicode ordinals, strings or None. Character keys will be then converted to ordinals. If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.

Submodules

GridCal.Engine.Simulations.OPF.ac_opf module

This file implements a DC-OPF for time series That means that solves the OPF problem for a complete time series at once

class GridCal.Engine.Simulations.OPF.ac_opf.AcOpf(numerical_circuit: GridCal.Engine.Core.numerical_circuit.NumericalCircuit)

Bases: GridCal.Engine.Simulations.OPF.opf_templates.Opf

formulate()

Formulate the AC OPF time series in the non-sequential fashion (all to the solver at once) :return: PuLP Problem instance

get_voltage()

return the complex voltages (time, device) :return: 2D array

GridCal.Engine.Simulations.OPF.ac_opf.add_ac_nodal_power_balance(numerical_circuit, problem: GridCal.ThirdParty.pulp.pulp.LpProblem, dvm, dva, P, Q)

Add the nodal power balance :param numerical_circuit: NumericalCircuit instance :param problem: LpProblem instance :param dva: Voltage angles LpVars (n, nt) :param P: Power injection at the buses LpVars (n, nt) :return: Nothing, the restrictions are added to the problem

GridCal.Engine.Simulations.OPF.ac_opf.add_branch_loading_restriction(problem: GridCal.ThirdParty.pulp.pulp.LpProblem, theta_f, theta_t, Bseries, Fmax, FSlack1, FSlack2)

Add the branch loading restrictions :param problem: LpProblem instance :param theta_f: voltage angles at the “from” side of the branches (m, nt) :param theta_t: voltage angles at the “to” side of the branches (m, nt) :param Bseries: Array of branch susceptances (m) :param Fmax: Array of branch ratings (m, nt) :param FSlack1: Array of branch loading slack variables in the from-to sense :param FSlack2: Array of branch loading slack variables in the to-from sense :return: Nothing

GridCal.Engine.Simulations.OPF.ac_opf.get_objective_function(Pg, Pb, LSlack, FSlack1, FSlack2, cost_g, cost_b, cost_l, cost_br)

Add the objective function to the problem :param Pg: generator LpVars (ng, nt) :param Pb: batteries LpVars (nb, nt) :param LSlack: Load slack LpVars (nl, nt) :param FSlack1: Branch overload slack1 (m, nt) :param FSlack2: Branch overload slack2 (m, nt) :param cost_g: Cost of the generators (ng, nt) :param cost_b: Cost of the batteries (nb, nt) :param cost_l: Cost of the loss of load (nl, nt) :param cost_br: Cost of the overload (m, nt) :return: Nothing, just assign the objective function

GridCal.Engine.Simulations.OPF.ac_opf.get_power_injections(C_bus_gen, Pg, C_bus_bat, Pb, C_bus_load, PlSlack, QlSlack, Pl, Ql)

Create the power injections per bus :param C_bus_gen: Bus-Generators sparse connectivity matrix (n, ng) :param Pg: generator LpVars (ng, nt) :param C_bus_bat: Bus-Batteries sparse connectivity matrix (n, nb) :param Pb: Batteries LpVars (nb, nt) :param C_bus_load: Bus-Load sparse connectivity matrix (n, nl) :param PlSlack: Load (real) slack LpVars (nl, nt) :param QlSlack: Load (imag) slack LpVars (nl, nt) :param Pl: Load values (nl, nt) :return: Power injection at the buses (n, nt)

GridCal.Engine.Simulations.OPF.ac_opf.maketrans()

Return a translation table usable for str.translate().

If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters to Unicode ordinals, strings or None. Character keys will be then converted to ordinals. If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.

GridCal.Engine.Simulations.OPF.ac_opf.set_fix_generation(problem, Pg, P_fix, enabled_for_dispatch)

Set the generation fixed at the non dispatchable generators :param problem: LP problem instance :param Pg: Array of generation variables :param P_fix: Array of fixed generation values :param enabled_for_dispatch: array of “enables” for dispatching generators :return: Nothing

GridCal.Engine.Simulations.OPF.dc_opf module

This file implements a DC-OPF for time series That means that solves the OPF problem for a complete time series at once

class GridCal.Engine.Simulations.OPF.dc_opf.DcOpf(numerical_circuit: GridCal.Engine.Core.numerical_circuit.NumericalCircuit)

Bases: GridCal.Engine.Simulations.OPF.opf_templates.Opf

formulate()

Formulate the AC OPF time series in the non-sequential fashion (all to the solver at once) :return: PuLP Problem instance

GridCal.Engine.Simulations.OPF.dc_opf.add_branch_loading_restriction(problem: GridCal.ThirdParty.pulp.pulp.LpProblem, theta_f, theta_t, Bseries, rating, FSlack1, FSlack2)

Add the branch loading restrictions :param problem: LpProblem instance :param theta_f: voltage angles at the “from” side of the branches (m) :param theta_t: voltage angles at the “to” side of the branches (m) :param Bseries: Array of branch susceptances (m) :param rating: Array of branch ratings (m) :param FSlack1: Array of branch loading slack variables in the from-to sense :param FSlack2: Array of branch loading slack variables in the to-from sense :return: load_f and load_t arrays (LP+float)

GridCal.Engine.Simulations.OPF.dc_opf.add_dc_nodal_power_balance(numerical_circuit, problem: GridCal.ThirdParty.pulp.pulp.LpProblem, theta, P)

Add the nodal power balance :param numerical_circuit: NumericalCircuit instance :param problem: LpProblem instance :param theta: Voltage angles LpVars (n, nt) :param P: Power injection at the buses LpVars (n, nt) :return: Nothing, the restrictions are added to the problem

GridCal.Engine.Simulations.OPF.dc_opf.add_objective_function(Pg, Pb, LSlack, FSlack1, FSlack2, cost_g, cost_b, cost_l, cost_br)

Add the objective function to the problem :param Pg: generator LpVars (ng, nt) :param Pb: batteries LpVars (nb, nt) :param LSlack: Load slack LpVars (nl, nt) :param FSlack1: Branch overload slack1 (m, nt) :param FSlack2: Branch overload slack2 (m, nt) :param cost_g: Cost of the generators (ng, nt) :param cost_b: Cost of the batteries (nb, nt) :param cost_l: Cost of the loss of load (nl, nt) :param cost_br: Cost of the overload (m, nt) :return: Nothing, just assign the objective function

GridCal.Engine.Simulations.OPF.dc_opf.get_power_injections(C_bus_gen, Pg, C_bus_bat, Pb, C_bus_load, LSlack, Pl)

Create the power injections per bus :param C_bus_gen: Bus-Generators sparse connectivity matrix (n, ng) :param Pg: generator LpVars (ng, nt) :param C_bus_bat: Bus-Batteries sparse connectivity matrix (n, nb) :param Pb: Batteries LpVars (nb, nt) :param C_bus_load: Bus-Load sparse connectivity matrix (n, nl) :param LSlack: Load slack LpVars (nl, nt) :param Pl: Load values (nl, nt) :return: Power injection at the buses (n, nt)

GridCal.Engine.Simulations.OPF.dc_opf.maketrans()

Return a translation table usable for str.translate().

If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters to Unicode ordinals, strings or None. Character keys will be then converted to ordinals. If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.

GridCal.Engine.Simulations.OPF.dc_opf.set_fix_generation(problem, Pg, P_fix, enabled_for_dispatch)

Set the generation fixed at the non dispatchable generators :param problem: LP problem instance :param Pg: Array of generation variables :param P_fix: Array of fixed generation values :param enabled_for_dispatch: array of “enables” for dispatching generators :return: Nothing

GridCal.Engine.Simulations.OPF.nelder_mead_opf module

class GridCal.Engine.Simulations.OPF.nelder_mead_opf.AcOpfNelderMead(multi_circuit: GridCal.Engine.Core.multi_circuit.MultiCircuit, options: GridCal.Engine.Simulations.PowerFlow.power_flow_driver.PowerFlowOptions, verbose=False, break_at_value=True, good_enough_value=0)

Bases: object

build_solvers()
f_obj(x)
get_batteries_power()
get_branch_flows()
get_controlled_generation()
get_generation_shedding()
get_load_shedding()
get_loading()
get_overloads()
get_voltage()
set_default_state()

Set the default loading state

set_state(load_power, static_gen_power, controlled_gen_power, storage_power, Emin=None, Emax=None, E=None, dt=0, force_batteries_to_charge=False, bat_idx=None, battery_loading_pu=0.01)
set_state_at(t, force_batteries_to_charge=False, bat_idx=None, battery_loading_pu=0.01, Emin=None, Emax=None, E=None, dt=0)

Set the problem state at at time index Args:

t: force_batteries_to_charge: bat_idx: battery_loading_pu: Emin: Emax: E: dt:

Returns:

solve(verbose=False)
GridCal.Engine.Simulations.OPF.nelder_mead_opf.nelder_mead(objective_function, x_start, step=0.1, no_improve_thr=1e-05, no_improv_break=10, max_iter=0, alpha=1.0, gamma=2.0, rho=-0.5, sigma=0.5, break_at_value=False, good_enough_value=0.0, init_res=[], callback=None)
Args:
objective_function: function to optimize, must return a scalar score
and operate over a numpy array of the same dimensions as x_start

x_start: initial position LB: lower bounds (can be None) UB: upper bound (can be None) step: look-around radius in initial step no_improve_thr, no_improv_break: break after no_improv_break iterations with an improvement lower than no_improv_thr max_iter: always break after this number of iterations. Set it to 0 to loop indefinitely. alpha: gamma: rho: sigma:

Returns: xsol, fsol

GridCal.Engine.Simulations.OPF.nelder_mead_opf.nelder_mead_test()

GridCal.Engine.Simulations.OPF.opf_driver module

class GridCal.Engine.Simulations.OPF.opf_driver.OptimalPowerFlow(grid: GridCal.Engine.Core.multi_circuit.MultiCircuit, options: GridCal.Engine.Simulations.OPF.opf_driver.OptimalPowerFlowOptions)

Bases: PySide2.QtCore.QThread

cancel()
done_signal = <PySide2.QtCore.Signal object>
get_steps()

Get time steps list of strings

opf()

Run a power flow for every circuit @return: OptimalPowerFlowResults object

progress_signal = <PySide2.QtCore.Signal object>
progress_text = <PySide2.QtCore.Signal object>
run()
Returns:
staticMetaObject = <PySide2.QtCore.QMetaObject object>
class GridCal.Engine.Simulations.OPF.opf_driver.OptimalPowerFlowOptions(verbose=False, solver: GridCal.Engine.Simulations.PowerFlow.power_flow_driver.SolverType = <SolverType.DC_OPF: 'Linear DC OPF'>, grouping: GridCal.Engine.basic_structures.TimeGrouping = <TimeGrouping.NoGrouping: 'No grouping'>, mip_solver=<MIPSolvers.CBC: 'CBC'>, faster_less_accurate=False, power_flow_options=None, bus_types=None)

Bases: object

GridCal.Engine.Simulations.OPF.opf_results module

class GridCal.Engine.Simulations.OPF.opf_results.OptimalPowerFlowResults(Sbus=None, voltage=None, load_shedding=None, generation_shedding=None, battery_power=None, controlled_generation_power=None, Sbranch=None, overloads=None, loading=None, losses=None, converged=None, bus_types=None)

Bases: object

OPF results.

Arguments:

Sbus: bus power injections

voltage: bus voltages

load_shedding: load shedding values

Sbranch: branch power values

overloads: branch overloading values

loading: branch loading values

losses: branch losses

converged: converged?

copy()

Return a copy of this @return:

initialize(n, m)

Initialize the arrays @param n: number of buses @param m: number of branches @return:

plot(result_type, ax=None, indices=None, names=None)

Plot the results :param result_type: type of results (string) :param ax: matplotlib axis object :param indices: element indices :param names: element names :return: DataFrame of the results (or None if the result was not understood)

GridCal.Engine.Simulations.OPF.opf_time_series_driver module

class GridCal.Engine.Simulations.OPF.opf_time_series_driver.OptimalPowerFlowTimeSeries(grid: GridCal.Engine.Core.multi_circuit.MultiCircuit, options: GridCal.Engine.Simulations.OPF.opf_driver.OptimalPowerFlowOptions, start_=0, end_=None)

Bases: PySide2.QtCore.QThread

cancel()
done_signal = <PySide2.QtCore.Signal object>
get_steps()

Get time steps list of strings

opf(start_, end_, remote=False, batteries_energy_0=None)

Run a power flow for every circuit :param start_: start index :param end_: end index :param remote: is this function being called from the time series? :param batteries_energy_0: initial state of the batteries, if None the default values are taken :return: OptimalPowerFlowResults object

opf_by_groups()

Run the OPF by groups

progress_signal = <PySide2.QtCore.Signal object>
progress_text = <PySide2.QtCore.Signal object>
reset_results()

Clears the results

run()
Returns:
staticMetaObject = <PySide2.QtCore.QMetaObject object>
class GridCal.Engine.Simulations.OPF.opf_time_series_driver.OptimalPowerFlowTimeSeriesResults(n, m, nt, ngen=0, nbat=0, nload=0, time=None)

Bases: object

init_object_results(ngen, nbat)

declare the generator results. This is done separately since these results are known at the end of the simulation :param ngen: number of generators :param nbat: number of batteries

plot(result_type, ax=None, indices=None, names=None)

Plot the results :param result_type: :param ax: :param indices: :param names: :return:

set_at(t, res: GridCal.Engine.Simulations.OPF.opf_results.OptimalPowerFlowResults)

Set the results :param t: time index :param res: OptimalPowerFlowResults instance