Optimal Power Flow
For further information on this topic, please see the AC Optimal Power Flow or DC Optimal Power Flow sections of the Manual. Below, we have provided a list of functions that can be utilized for optimal power flow analysis.
To load optimal power flow API functionalities into the current scope, one can employ the following command:
using JuliaGrid, Ipopt
AC Optimal Power Flow
DC Optimal Power Flow
Extended Formulation
Utility Functions
AC Optimal Power Flow
JuliaGrid.acOptimalPowerFlow
— FunctionacOptimalPowerFlow(system::PowerSystem, optimizer;
iteration, tolerance, bridge, interval, name,
magnitude, angle, active, reactive, actwise, reactwise, verbose)
The function sets up the optimization model for solving the AC optimal power flow problem.
Arguments
The function requires the PowerSystem
type to establish the framework. Next, the optimizer
argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the AC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.
Keywords
Users can configure the following parameters:
iteration
: Specifies the maximum number of iterations.tolerance
: Specifies the allowed deviation from the optimal solution.bridge
: Manage the bridging mechanism (default:false
).interval
: Uses interval form for two-sided constraints (default:true
).name
: Manage the creation of string names (default:true
).verbose
: Controls the output display, ranging from silent mode (0
) to detailed output (3
).
Additionally, users can modify the variable names used for printing and writing by setting the keywords for the variables magnitude
, angle
, active
, and reactive
, as well as the helper variables actwise
and reactwise
. For instance, users can choose magnitude = "V"
and angle = "θ"
to display equations in a more readable format.
Updates
If the AC model has not been created, the function automatically initiates an update within the ac
field of the PowerSystem
type.
Returns
The function returns an instance of the AcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
acModel!(system)
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer; iteration = 50, verbose = 1)
JuliaGrid.solve!
— Methodsolve!(analysis::AcOptimalPowerFlow)
The function solves the AC optimal power flow model, computing the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.
Updates
The calculated active and reactive powers, as well as voltage magnitudes and angles, are stored in the power.generator
and voltage
fields of the AcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
acModel!(system)
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
solve!(analysis)
JuliaGrid.setInitialPoint!
— MethodsetInitialPoint!(analysis::AcOptimalPowerFlow)
The function sets the initial point of the AC optimal power flow to the values from the PowerSystem
type.
Updates
The function modifies the voltage
and generator
fields of the AcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
acModel!(system)
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
powerFlow!(analysis)
updateBus!(analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)
setInitialPoint!(analysis)
powerFlow!(analysis)
JuliaGrid.setInitialPoint!
— MethodsetInitialPoint!(target::AcOptimalPowerFlow, source::Analysis)
The function initializes the AC optimal power flow based on results from the Analysis
type, whether from an AC or DC analysis.
The function assigns the active and reactive power outputs of the generators, along with the bus voltage magnitudes and angles in the target
argument, using data from the source
argument. This allows users to initialize primal values as needed. Additionally, if source
is of type AcOptimalPowerFlow
, the function also assigns initial dual values in the target
argument based on data from source
.
If source
comes from a DC analysis, only the active power outputs of the generators and bus voltage angles are assigned in the target
argument, while the reactive power outputs of the generators and bus voltage magnitudes remain unchanged. Additionally, if source
is of type DcOptimalPowerFlow
, the corresponding dual variable values are also assigned in the target
argument.
Updates
This function may modify the voltage
, generator
, and method.dual
fields of the AcOptimalPowerFlow
type.
Example
Use the AC power flow results to initialize the AC optimal power flow:
system = powerSystem("case14.h5")
acModel!(system)
source = newtonRaphson(system)
powerFlow!(source)
target = acOptimalPowerFlow(system, Ipopt.Optimizer)
setInitialPoint!(target, source)
powerFlow!(target)
JuliaGrid.powerFlow!
— MethodpowerFlow!(analysis::AcOptimalPowerFlow; iteration, tolerance, power, current, verbose)
The function serves as a wrapper for solving AC optimal power flow and includes the functions:
It computes the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles, with an option to compute the powers and currents related to buses and branches.
Keywords
Users can use the following keywords:
iteration
: Specifies the maximum number of iterations.tolerance
: Specifies the allowed deviation from the optimal solution.power
: Enables the computation of powers (default:false
).current
: Enables the computation of currents (default:false
).verbose
: Controls the output display, ranging from the default silent mode (0
) to detailed output (3
).
Example
system = powerSystem("case14.h5")
acModel!(system)
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
powerFlow!(analysis; power = true, verbose = 1)
DC Optimal Power Flow
JuliaGrid.dcOptimalPowerFlow
— FunctiondcOptimalPowerFlow(system::PowerSystem, optimizer;
iteration, tolerance, bridge, interval, name, angle, active, actwise, verbose)
The function sets up the optimization model for solving the DC optimal power flow problem.
Arguments
The function requires the PowerSystem
type to establish the framework. Next, the optimizer
argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the DC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.
Keywords
Users can configure the following parameters:
iteration
: Specifies the maximum number of iterations.tolerance
: Specifies the allowed deviation from the optimal solution.bridge
: Controls the bridging mechanism (default:false
).interval
: Uses interval form for two-sided expression constraints (default:true
).name
: Enables or disables the creation of string names (default:true
).verbose
: Controls the output display, ranging from the default silent mode (0
) to detailed output (3
).
Additionally, users can modify the variable names used for printing and writing by setting the keywords for the voltage variables angle
and active
, as well as the helper variable actwise
. For example, users may set angle = "θ"
, active = "P"
, and actwise = "H"
to display equations in a more readable format.
Updates
If the DC model has not been created, the function automatically initiates an update within the dc
field of the PowerSystem
type.
Returns
The function returns an instance of the DcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
dcModel!(system)
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
JuliaGrid.solve!
— Methodsolve!(analysis::DcOptimalPowerFlow)
The function solves the DC optimal power flow model, computing the active power outputs of the generators, as well as the bus voltage angles.
Updates
The calculated active powers, as well as voltage angles, are stored in the power.generator
and voltage
fields of the DcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
dcModel!(system)
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
solve!(analysis)
JuliaGrid.setInitialPoint!
— MethodsetInitialPoint!(analysis::DcOptimalPowerFlow)
The function sets the initial point of the DC optimal power flow to the values from the PowerSystem
type.
Updates
The function modifies the voltage
and generator
fields of the DcOptimalPowerFlow
type.
Example
system = powerSystem("case14.h5")
dcModel!(system)
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
powerFlow!(analysis)
updateBus!(analysis; label = 14, active = 0.1, angle = -0.17)
setInitialPoint!(analysis)
powerFlow!(analysis)
JuliaGrid.setInitialPoint!
— MethodsetInitialPoint!(target::DcOptimalPowerFlow, source::Analysis)
The function initializes the DC optimal power flow based on results from the Analysis
type, whether from an AC or DC analysis.
The function assigns the active power outputs of the generators, along with the bus voltage angles in the target
argument, using data from the source
argument. This allows users to initialize primal values as needed. Additionally, if source is of type AcOptimalPowerFlow
or DcOptimalPowerFlow
, the function also assigns initial dual values in the target
argument based on data from source
.
Updates
This function may modify the voltage
, generator
, and method.dual
fields of the DcOptimalPowerFlow
type.
Example
Use the DC power flow results to initialize the DC optimal power flow:
system = powerSystem("case14.h5")
dcModel!(system)
source = dcPowerFlow(system)
solve!(source)
target = dcOptimalPowerFlow(system, Ipopt.Optimizer)
setInitialPoint!(target, source)
solve!(target)
JuliaGrid.powerFlow!
— MethodpowerFlow!(analysis::DcOptimalPowerFlow; iteration, tolerance, power, verbose)
The function serves as a wrapper for solving DC optimal power flow and includes the functions:
It computes the active power outputs of the generators, as well as the bus voltage angles, with an option to compute the powers related to buses and branches.
Keywords
Users can use the following keywords:
iteration
: Specifies the maximum number of iterations.tolerance
: Specifies the allowed deviation from the optimal solution.power
: Enables the computation of powers (default:false
).verbose
: Controls the output display, ranging from the default silent mode (0
) to detailed output (3
).
Example
system = powerSystem("case14.h5")
dcModel!(system)
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
powerFlow!(analysis; power = true, verbose = 1)
Extended Formulation
JuliaGrid.@addVariable
— Macro@addVariable(analysis::OptimalPowerFlow, expr, primal, lower, upper, args..., kwargs...)
This macro wraps the JuMP @variable macro, adding an optimization variable defined by expr
to the model. In addition to creating the JuMP variable, it also registers the variable within the JuliaGrid framework and optionally sets initial values for both primal and dual variables.
The positional arguments args
and keyword arguments kwargs
are consistent with those accepted by the @variable macro in JuMP.
Additionally, the following keyword arguments can be used:
primal
: Sets the initial primal value.lower
: If a lower bound is defined, sets the initial dual value.upper
: If an upper bound is defined, sets the initial dual value.
Example
system = powerSystem("case14.h5")
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
@addVariable(analysis, 0.0 <= x <= 0.2, primal = 0.1, lower = 10.0, upper = 0.0)
@addVariable(analysis, y[i = 1:2] <= 0.2, primal = [0.1, 0.2], upper = [0.0; -2.5])
JuliaGrid.@addConstraint
— Macro@addConstraint(analysis::OptimalPowerFlow, expr, dual, args..., kwargs...)
This macro wraps the JuMP @constraint macro, adding an constraint defined by expr
to the model. In addition to creating the JuMP constraint, it also registers the constraint within the JuliaGrid framework and optionally sets initial dual value.
The positional arguments args
and keyword arguments kwargs
are consistent with those accepted by the @constraint macro in JuMP.
Additionally, the keyword dual
can be used to set the initial dual value.
Example
system = powerSystem("case14.h5")
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
@addVariable(analysis, 0.0 <= x[i = 1:2] <= 0.2)
@addConstraint(analysis, x[1] + 2 * x[2] <= 1.2, dual = 0.1)
Utility Functions
JuliaGrid.addDual!
— FunctionaddDual!(analysis::OptimalPowerFlow, field::Symbol, subfield::Symbol;
label, index, subindex, dual, lower, upper)
Assigns an initial dual value to a specific constraint in the optimal power flow model.
For DC optimal power flow, only field
is required to identify the constraint. For AC optimal power flow, both field
and subfield
must be provided to target the specific constraint type.
Arguments
field
: Specifies the primary constraint category.subfield
: Specifies the constraint subtype within the selectedfield
.
Initial dual values are assigned according to the selected constraint:
:slack
: Slack angle constraint.:capability
: Generator capability constraints::active
: Active power.:reactive
: Reactive power.:lower
: PQ capability curve.:upper
: PQ capability curve.
:balance
: Power balance constraints::active
: Active power balance.:reactive
: Reactive power balance.
:voltage
: Voltage constraints::magnitude
: Voltage magnitude.:angle
: Angle difference.
:flow
: Branch power flow constraints::from
: From-bus end.:to
: To-bus end.
:piecewise
: Piecewise linear cost constraints::active
: Active power.:reactive
: Reactive power.
:variable
: Constraint on external user-defined variable.:constraint
: External user-defined constraint.
Keywords
The following keyword arguments can be used:
label
: Identifies the constraint by the label of a bus, branch, or generator.index
: Identifies the constraint by numerical index.subindex
: Specify a subconstraint index for:piecewise
constraints only.dual
: Sets the dual value for equality or interval constraints.lower
: Sets the dual value associated with the lower bound.upper
: Sets the dual value associated with the upper bound.
Examples
AC optimal power flow:
system = powerSystem("case14.h5")
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
addDual!(analysis, :balance, :active; index = 2, dual = 258.23)
addDual!(analysis, :voltage, :magnitude; index = 2, lower = 0.0, upper = 587.23)
DC optimal power flow:
system = powerSystem("case14.h5")
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
addDual!(analysis, :balance; index = 2, dual = 258.23)
addDual!(analysis, :capability; index = 2, lower = 0.0, upper = 587.23)
JuliaGrid.remove!
— Functionremove!(analysis::OptimalPowerFlow, field::Symbol, subfield::Symbol; label, index)
Removes a specific constraint from the optimal power flow model.
For DC optimal power flow, only field
is required to identify the constraint. For AC optimal power flow, both field
and subfield
must be provided to target the specific constraint type.
Arguments
field
: Specifies the primary constraint category.subfield
: Specifies the constraint subtype within the selectedfield
.
The constraint to be removed can correspond to one of the following:
:slack
: Slack angle constraint.:capability
: Generator capability constraints::active
: Active power.:reactive
: Reactive power.:lower
: PQ capability curve.:upper
: PQ capability curve.
:balance
: Power balance constraints::active
: Active power balance.:reactive
: Reactive power balance.
:voltage
: Voltage constraints::magnitude
: Voltage magnitude.:angle
: Angle difference.
:flow
: Branch power flow constraints::from
: From-bus end.:to
: To-bus end.
:piecewise
: Piecewise linear cost constraints::active
: Active power.:reactive
: Reactive power.
:variable
: Constraint on external user-defined variable.:constraint
: External user-defined constraint.
Keywords
The following keyword arguments can be used:
label
: Identifies the constraint by the label of a bus, branch, or generator.index
: Identifies the constraint by numerical index.
Examples
AC optimal power flow:
system = powerSystem("case14.h5")
analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
remove!(analysis, :balance, :active; index = 2)
remove!(analysis, :voltage, :magnitude; index = 2)
DC optimal power flow:
system = powerSystem("case14.h5")
analysis = dcOptimalPowerFlow(system, Ipopt.Optimizer)
remove!(analysis, :balance; index = 2)
remove!(analysis, :capability; index = 2)