openreac.connected_component.run Maven / Gradle / Ivy
The newest version!
###############################################################################
#
# 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
###############################################################################
###############################################################################
#
# Computation of "slack bus" or reference bus
#
###############################################################################
# This is not really a slack bus since this reactive OPF will change values
# of generation proportionally, to ensure global balance generation=losses+load
# So this "slack node" is used only for zero phase constraint
# This reference bus is also used to choose on which connect component computation si performed
printf{LOG_INFO} "\nComputation of bus with largest number of branches connected, in order to fix phase to 0 and to choose on which connex component reacive OPF will run\n";
let temp1 := min(300,max{n in BUS2} substation_Vnomi[1,bus_substation[1,n]]);
let null_phase_bus := min{n in BUS2} n;
let tempo := 0;
for {n in BUS2 : substation_Vnomi[1,bus_substation[1,n]] >= temp1 * 0.9}
let tempo := max (tempo, card({(qq,mm,n) in BRANCH2} union {(qq,n,nn) in BRANCH2}));
for {n in BUS2 : substation_Vnomi[1,bus_substation[1,n]] >= temp1 * 0.9 && card({(qq,mm,n) in BRANCH2} union {(qq,n,nn) in BRANCH2}) == tempo}
let null_phase_bus := n;
if ( tempo > 0 ) then
printf{LOG_INFO} "Bus %QkV with most branches: %Q in substation %s/%s with %Q connected branches\n",
substation_Vnomi[1,bus_substation[1,null_phase_bus]],
null_phase_bus,
substation_id[1,bus_substation[1,null_phase_bus]],
substation_description[1,bus_substation[1,null_phase_bus]],
tempo;
if ( tempo == 0 ) then
printf{LOG_WARNING} "Bus with most branches: not found. Take first bus (=%Q) for phase=0 constraint\n",null_phase_bus;
###############################################################################
# Solve PROBLEM_CCOMP
###############################################################################
let PROBLEM_CCOMP := {1};
let tempstr := ctime();
printf{LOG_KNITRO} "\n######################################################################\n";
printf{LOG_KNITRO} "** CCcomp solve: start (%s)\n\n",tempstr;
option presolve 0;
option knitro_options ("outlev=3");;
# TODO : remove suffix printing
if (log_level_knitro <= 1) then {
solve cccomputation_objective > (nullDevice);
} else {
solve cccomputation_objective;
}
printf{LOG_KNITRO} "\n** CCcomp solve: end (%s -> %s)\n",tempstr,ctime();
printf{LOG_KNITRO} "######################################################################\n\n";
###############################################################################
# Analysis of solve_result_num
###############################################################################
if solve_result_num > 103 or card({n in BUS2: teta_ccomputation[n].val > 0.01 and teta_ccomputation[n].val < 0.99})>0
then {
# First return codes of knitro :
# See https://www.artelys.com/docs/knitro/3_referenceManual/knitroamplReference.html#return-codes
# 0 Locally optimal or satisfactory solution.
let errorMessage := "Optimization for connex component computation failed";
let final_status := "NOK";
include reactiveopfexit.run;
}
option presolve 10;
###############################################################################
# Definition of BUSCC below was the purpose of this optimization
###############################################################################
printf{LOG_INFO} "\n######################################################################\n";
printf{LOG_INFO} "** CCcomp results\n";
let BUSCC := {n in BUS2: teta_ccomputation[n].val <= 0.01};
for{n in BUS2 diff BUSCC}
printf{LOG_WARNING} "Bus %Q in substation %Q (Vnomi=%.2fkV, country=%Q) is out of main AC CC\n",
bus_id[1,n], substation_id[1,bus_substation[1,n]],
substation_Vnomi[1,bus_substation[1,n]], substation_country[1,bus_substation[1,n]];
printf{LOG_INFO} "Nb of busses in AC+DC CC: %i\n",card(BUS2);
printf{LOG_INFO} "Nb of busses in CC %Q: %i\n",bus_id[1,null_phase_bus],card(BUSCC);
printf{LOG_INFO} "Nb of busses in other CCs: %Q\n",card(BUS2)-card(BUSCC);
printf "\n";
###############################################################################
# A few information
###############################################################################
if 1 in LOG_INFO then {
display
maximal_voltage_upper_bound, minimal_voltage_lower_bound,
card(SUBSTATIONS),card(BUS),card(BUS2),card(BUSCC),card(BUS2 diff BUSCC),card(BUSVV),
card(BRANCH),card(BRANCHCC),card(BRANCHZNULL),card(BRANCHCC diff BRANCHZNULL),
card(UNIT),card(UNITCC),card(UNITON),card(UNITON diff UNIT_FIXQ),card(UNIT_FIXQ),
card(LOAD),card(LOADCC),
card(SHUNTCC),card(SHUNT_FIX),card(SHUNT_VAR),
card(SVC),card(SVCCC),card(SVCON),
card(VSCCONV),card(VSCCONVON),
card(LCCCONV),card(LCCCONVON)
;
}
# Is the case power globally power balanced?
let temp1 := sum{(c,n) in LOADCC} load_PFix[1,c,n];
let temp2 := sum{(g,n) in UNITON} unit_Pc[1,g,n];
let temp2 := temp2 + sum{(b,n) in BATTERYCC} battery_p0[1,b,n];
let temp3 := (sum{(vscconv,n) in VSCCONVON} vscconv_P0[1,vscconv,n])+(sum{(l,k) in LCCCONVON} lccconv_P0[1,l,k]);
let global_initial_losses_ratio := (temp2-temp1-temp3)/(temp1+temp3);
printf{LOG_INFO} "HVDC injections (homogeneous to loads):\n";
for {(v,n) in VSCCONVON}
printf{LOG_INFO} "VSC converter %Q in %Q: P0=%.1fMW is fixed, Q is variable\n",
vscconv_id[1,v,n],substation_id[1,bus_substation[1,n]],vscconv_P0[1,v,n];
for {(l,n) in LCCCONVON}
printf{LOG_INFO} "LCC converter %Q in %Q: P0=%.1fMW is fixed, Q0=%.1fMvar is fixed\n",
lccconv_id[1,l,n],substation_id[1,bus_substation[1,n]],lccconv_P0[1,l,n],lccconv_Q0[1,l,n];
printf{LOG_INFO} "Sum of HVDC conv. H: %.0f MW\n", temp3;
printf{LOG_INFO} "Sum of loads C: %.0f MW\n", temp1;
printf{LOG_INFO} "Sum of generations P: %.0f MW\n", temp2;
printf{LOG_INFO} " (including batteries for %.1f MW\n", sum{(b,n) in BATTERYCC} battery_p0[1,b,n];
printf{LOG_INFO} "Balance (P-C-H)/C: %.2f %% (global_initial_losses_ratio=%f)\n\n", (temp2-temp1-temp3)/temp1*100,global_initial_losses_ratio;
# Branches with low current limits (but keep in mind they are not used; this is just for information)
let temp1 := min{(qq,m,n) in BRANCHCC} Fmax[qq,m,n];
for {(qq,m,n) in BRANCHCC : Fmax[qq,m,n] <= temp1 * 1.5}
printf{LOG_INFO} "Branch %Q Fmax=%.2fMW is small ; Vnom1=%ikV Vnom2=%ikV patl1=%iA patl2=%iA (Fmax not used, this is just for information)\n",
branch_id[1,qq,m,n],Fmax[qq,m,n],substation_Vnomi[1,bus_substation[1,m]],substation_Vnomi[1,bus_substation[1,n]],branch_patl1[1,qq,m,n],branch_patl1[1,qq,m,n];
# Abnormally low nominal voltages
for {(t,n) in BUS: substation_Vnomi[1,bus_substation[1,n]] < epsilon_nominal_voltage}
printf{LOG_WARNING} "Warning: bus %Q in substation %Q has nominal voltage %.2fkV < %QkV -> bus is ignored\n",
bus_id[1,n], substation_id[1,bus_substation[1,n]], substation_Vnomi[1,bus_substation[1,n]], epsilon_nominal_voltage;
# desactivate optimization problem
let PROBLEM_CCOMP := { };