-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Division of AMPL code in functional blocks (#71)
* Divide AMPL code in OpenReac resources. * Update README. * Add last modifications in main branch * Add licence identifier in ampl resources * Fix typos in README --------- Signed-off-by: p-arvy <[email protected]>
- Loading branch information
Showing
17 changed files
with
2,764 additions
and
2,715 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
############################################################################### | ||
# | ||
# Copyright (c) 2022 2023 2024, RTE (http://www.rte-france.com) | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
# SPDX-License-Identifier: MPL-2.0 | ||
# | ||
############################################################################### | ||
|
||
############################################################################### | ||
# Reactive OPF | ||
# Author: Jean Maeght 2022 2023 | ||
# Author: Manuel Ruiz 2023 2024 | ||
############################################################################### | ||
|
||
|
||
set PROBLEM_ACOPF default { }; | ||
|
||
############################################################################### | ||
# | ||
# Variables and contraints for ACOPF | ||
# | ||
############################################################################### | ||
# Notice that some variables and constraints for DCOPF are also used for ACOPF | ||
|
||
# | ||
# Phase and modulus of voltage | ||
# | ||
# Complex voltage = V*exp(i*teta). (with i**2=-1) | ||
|
||
# Phase of voltage | ||
var teta{BUSCC} <= teta_max, >= teta_min; | ||
subject to ctr_null_phase_bus{PROBLEM_ACOPF}: teta[null_phase_bus] = 0; | ||
|
||
# Modulus of voltage | ||
var V{n in BUSCC} | ||
<= | ||
if substation_Vnomi[1,bus_substation[1,n]] <= ignore_voltage_bounds then max_plausible_high_voltage_limit else | ||
voltage_upper_bound[1,bus_substation[1,n]], | ||
>= | ||
if substation_Vnomi[1,bus_substation[1,n]] <= ignore_voltage_bounds then min_plausible_low_voltage_limit else | ||
voltage_lower_bound[1,bus_substation[1,n]]; | ||
|
||
|
||
# | ||
# Generation | ||
# | ||
# General idea: generation is an input data, but as voltage may vary, generation may vary a little. | ||
# Variations of generation is totally controlled by unique scalar variable alpha | ||
# Before and after optimization, there is no waranty that P is within | ||
# its "bounds" [corrected_unit_Pmin;corrected_unit_Pmax] | ||
# | ||
|
||
# Active generation | ||
var alpha <=1, >=-1; # If alpha==1 then all units are at Pmax | ||
var P_bounded{(g,n) in UNITON} <= max(unit_Pc[1,g,n],corrected_unit_Pmax[g,n]), >= min(unit_Pc[1,g,n],corrected_unit_Pmin[g,n]); | ||
# If coeff_alpha == 1 then all P are defined by the single variable alpha | ||
# If coeff_alpha == 0 then all P are free within their respective bounds | ||
# todo faire des tests avec les valeurs de coeff_alpha | ||
var P{(g,n) in UNITON} = | ||
if ( unit_Pc[1,g,n] < (corrected_unit_Pmax[g,n] - Pnull) and unit_Pc[1,g,n] > Pnull ) | ||
then ( coeff_alpha * ( unit_Pc[1,g,n] + alpha*(corrected_unit_Pmax[g,n]- unit_Pc[1,g,n]) ) | ||
+ (1-coeff_alpha) * P_bounded[g,n] ) | ||
else unit_Pc[1,g,n] ; | ||
|
||
|
||
# | ||
# Reactive generation | ||
# | ||
# todo: add trapeze or hexagone constraints for reactive power | ||
var Q{(g,n) in UNITON} <= corrected_unit_Qmax[g,n], >= corrected_unit_Qmin[g,n]; | ||
|
||
|
||
# | ||
# Variable shunts | ||
# | ||
var shunt_var{(shunt,n) in SHUNT_VAR} | ||
>= min{(1,shunt,k) in SHUNT} shunt_valmin[1,shunt,k], | ||
<= max{(1,shunt,k) in SHUNT} shunt_valmax[1,shunt,k]; | ||
|
||
|
||
# | ||
# SVC reactive generation | ||
# | ||
var svc_qvar{(svc,n) in SVCON} >= svc_bmin[1,svc,n], <= svc_bmax[1,svc,n]; | ||
|
||
|
||
# | ||
# VSCCONV reactive generation | ||
# | ||
var vscconv_qvar{(v,n) in VSCCONVON} | ||
>= min(vscconv_qP[1,v,n],vscconv_qp0[1,v,n],vscconv_qp[1,v,n]), | ||
<= max(vscconv_QP[1,v,n],vscconv_Qp0[1,v,n],vscconv_Qp[1,v,n]); | ||
# todo: add trapeze or hexagone constraints for reactive power | ||
|
||
|
||
# | ||
# Ratios of transformers | ||
# | ||
var branch_Ror_var{(qq,m,n) in BRANCHCC_REGL_VAR} | ||
>= regl_ratio_min[1,branch_ptrRegl[1,qq,m,n]], | ||
<= regl_ratio_max[1,branch_ptrRegl[1,qq,m,n]]; | ||
|
||
# | ||
# Flows | ||
# | ||
|
||
var Red_Tran_Act_Dir{(qq,m,n) in BRANCHCC } = | ||
V[n] * branch_admi[qq,m,n] * sin(teta[m]-teta[n]+branch_dephor[qq,m,n]-branch_angper[qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n]) | ||
+ V[m] * (branch_admi[qq,m,n]*sin(branch_angper[qq,m,n])+branch_Gor[1,qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n])**2 | ||
; | ||
|
||
var Red_Tran_Rea_Dir{(qq,m,n) in BRANCHCC } = | ||
- V[n] * branch_admi[qq,m,n] * cos(teta[m]-teta[n]+branch_dephor[qq,m,n]-branch_angper[qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n]) | ||
+ V[m] * (branch_admi[qq,m,n]*cos(branch_angper[qq,m,n])-branch_Bor[1,qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n])^2 | ||
; | ||
|
||
var Red_Tran_Act_Inv{(qq,m,n) in BRANCHCC } = | ||
V[m] * branch_admi[qq,m,n] * sin(teta[n]-teta[m]-branch_dephor[qq,m,n]-branch_angper[qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n]) | ||
+ V[n] * (branch_admi[qq,m,n]*sin(branch_angper[qq,m,n])+branch_Gex[1,qq,m,n]) | ||
; | ||
|
||
var Red_Tran_Rea_Inv{(qq,m,n) in BRANCHCC } = | ||
- V[m] * branch_admi[qq,m,n] * cos(teta[n]-teta[m]-branch_dephor[qq,m,n]-branch_angper[qq,m,n]) | ||
* (if (qq,m,n) in BRANCHCC_REGL_VAR then branch_Ror_var[qq,m,n]*branch_cstratio[1,qq,m,n] else branch_Ror[qq,m,n]) | ||
+ V[n] * (branch_admi[qq,m,n]*cos(branch_angper[qq,m,n])-branch_Bex[1,qq,m,n]) | ||
; | ||
|
||
|
||
# | ||
# Active Balance | ||
# | ||
|
||
subject to ctr_balance_P{PROBLEM_ACOPF,k in BUSCC}: | ||
# Flows | ||
sum{(qq,k,n) in BRANCHCC} base100MVA * V[k] * Red_Tran_Act_Dir[qq,k,n] | ||
+ sum{(qq,m,k) in BRANCHCC} base100MVA * V[k] * Red_Tran_Act_Inv[qq,m,k] | ||
# Generating units | ||
- sum{(g,k) in UNITON} P[g,k] | ||
# Batteries | ||
- sum{(b,k) in BATTERYCC} battery_p0[1,b,k] | ||
# Loads | ||
+ sum{(c,k) in LOADCC} load_PFix[1,c,k] # Fixed value | ||
# VSC converters | ||
+ sum{(v,k) in VSCCONVON} vscconv_P0[1,v,k] # Fixed value | ||
# LCC converters | ||
+ sum{(l,k) in LCCCONVON} lccconv_P0[1,l,k] # Fixed value | ||
= 0; # No slack variables for active power. If data are really too bad, may not converge. | ||
|
||
|
||
# | ||
# Reactive Balance | ||
# | ||
|
||
# Reactive balance slack variables at configured nodes | ||
set BUSCC_SLACK := if buses_with_reactive_slacks == "ALL" then BUSCC | ||
else if buses_with_reactive_slacks == "NO_GENERATION" then {n in BUSCC: (card{(g,n) in UNITON: (g,n) not in UNIT_FIXQ}==0 and card{(svc,n) in SVCON}==0 and card{(vscconv,n) in VSCCONVON}==0)} | ||
else BUSCC inter PARAM_BUSES_WITH_REACTIVE_SLACK; # if = "CONFIGURED", buses given as parameter but in connex component | ||
var slack1_shunt_B{BUSCC_SLACK} >= 0; | ||
var slack2_shunt_B{BUSCC_SLACK} >= 0; | ||
#subject to ctr_compl_slack_Q{PROBLEM_ACOPF,k in BUSCC_SLACK}: slack1_balance_Q[k] >= 0 complements slack2_balance_Q[k] >= 0; | ||
|
||
subject to ctr_balance_Q{PROBLEM_ACOPF,k in BUSCC}: | ||
# Flows | ||
sum{(qq,k,n) in BRANCHCC} base100MVA * V[k] * Red_Tran_Rea_Dir[qq,k,n] | ||
+ sum{(qq,m,k) in BRANCHCC} base100MVA * V[k] * Red_Tran_Rea_Inv[qq,m,k] | ||
# Generating units | ||
- sum{(g,k) in UNITON: (g,k) not in UNIT_FIXQ } Q[g,k] | ||
- sum{(g,k) in UNIT_FIXQ} unit_Qc[1,g,k] | ||
# Batteries | ||
- sum{(b,k) in BATTERYCC} battery_q0[1,b,k] | ||
# Loads | ||
+ sum{(c,k) in LOADCC} load_QFix[1,c,k] | ||
# Shunts | ||
- sum{(shunt,k) in SHUNT_FIX} base100MVA * shunt_valnom[1,shunt,k] * V[k]^2 | ||
- sum{(shunt,k) in SHUNT_VAR} base100MVA * shunt_var[shunt,k] * V[k]^2 | ||
# SVC | ||
- sum{(svc,k) in SVCON} base100MVA * svc_qvar[svc,k] * V[k]^2 | ||
# VSC converters | ||
- sum{(v,k) in VSCCONVON} vscconv_qvar[v,k] | ||
# LCC converters | ||
+ sum{(l,k) in LCCCONVON} lccconv_Q0[1,l,k] # Fixed value | ||
# Slack variables | ||
+ if k in BUSCC_SLACK then | ||
(- base100MVA * V[k]^2 * slack1_shunt_B[k] # Homogeneous to a generation of reactive power (condensator) | ||
+ base100MVA * V[k]^2 * slack2_shunt_B[k]) # homogeneous to a reactive load (self) | ||
= 0; | ||
|
||
|
||
# | ||
# Definitions for objective function | ||
# | ||
|
||
# Voltage target : ratio between Vmin and Vmax | ||
var target_voltage_ratio = sum{n in BUSCC: substation_Vnomi[1,bus_substation[1,n]] > ignore_voltage_bounds} | ||
( V[n] - (1-ratio_voltage_target)*voltage_lower_bound[1,bus_substation[1,n]] + ratio_voltage_target*voltage_upper_bound[1,bus_substation[1,n]] )**2; | ||
|
||
# Voltage target : value V0 in input data | ||
var target_voltage_data = sum{n in BUSVV} (V[n] - bus_V0[1,n])**2; | ||
|
||
|
||
# | ||
# Objective function and penalties | ||
# | ||
param penalty_invest_rea_pos := 10; | ||
param penalty_invest_rea_neg := 10; | ||
param penalty_units_reactive := 0.1; | ||
param penalty_transfo_ratio := 0.1; | ||
|
||
param penalty_active_power_high := 1; | ||
param penalty_active_power_low := 0.01; | ||
|
||
param penalty_voltage_target_high := 1; | ||
param penalty_voltage_target_low := 0.01; | ||
|
||
minimize problem_acopf_objective: | ||
sum{n in BUSCC_SLACK} ( | ||
penalty_invest_rea_pos * base100MVA * slack1_shunt_B[n] | ||
+ penalty_invest_rea_neg * base100MVA * slack2_shunt_B[n] | ||
) | ||
|
||
# coeff_alpha == 1 : minimize sum of generation, all generating units vary with 1 unique variable alpha | ||
# coeff_alpha == 0 : minimize sum of squared difference between target and value | ||
+ (if objective_choice==1 or objective_choice==2 then penalty_active_power_low else penalty_active_power_high) | ||
* sum{(g,n) in UNITON} (coeff_alpha * P[g,n] + (1-coeff_alpha)*( (P[g,n]-unit_Pc[1,g,n])/max(1,abs(unit_Pc[1,g,n])) )**2 ) | ||
|
||
# Voltage for busses, ratio between Vmin and Vmax | ||
+ (if objective_choice==1 then penalty_voltage_target_high else penalty_voltage_target_low) | ||
* target_voltage_ratio | ||
|
||
# Voltage target : value V0 in input data | ||
+ (if objective_choice==2 then penalty_voltage_target_high else penalty_voltage_target_low) | ||
* target_voltage_data | ||
|
||
# Reactive power of units | ||
+ penalty_units_reactive * sum{(g,n) in UNITON} (Q[g,n]/max(1,abs(corrected_unit_Qmin[g,n]),abs(corrected_unit_Qmax[g,n])))**2 | ||
|
||
# Ratio of transformers | ||
+ penalty_transfo_ratio * sum{(qq,m,n) in BRANCHCC_REGL_VAR} (branch_Ror[qq,m,n]-branch_Ror_var[qq,m,n])**2 | ||
; | ||
|
||
|
||
# | ||
param solve_result_num_limit := 200; | ||
param output_results binary default 0; |
Oops, something went wrong.