Added Support for DCOPF Constrained Expansion - #915
Conversation
…ance for multistage
…d Integer_Build column
692a737 to
0e5e77b
Compare
lbonaldo
left a comment
There was a problem hiding this comment.
Hey @dlcole3, again, thank you so much for this additional PR! I added a few comments, most of them are probably related to the merge with the previous PR. Thank you for preparing them one next to the other. Let me know if you have any questions!
| using Gurobi | ||
|
|
||
| run_genx_case!(dirname(@__FILE__)) | ||
| run_genx_case!(dirname(@__FILE__), Gurobi.Optimizer) |
There was a problem hiding this comment.
I guess we can cleanup this file here, am I right?
| mysetup = merge(mysetup, mysetup_benders) | ||
|
|
||
| if mysetup["DC_OPF"] != 1 && mysetup[:RunTransportModel] | ||
| @warn "`RunTransportModel` only works with DC_OPF = 1 but DC_OPF is set to $(mysetup["DC_OPF"]). Turning off `RunTransportModel`" |
There was a problem hiding this comment.
do we need to turn off RunTransportModel?
| if get(mysetup, :Distributed, false) | ||
| target = get(mysetup, :NWorkers, 0) | ||
| if target > 1 | ||
| current = nworkers() | ||
| if current < target | ||
| n_to_add = target - current | ||
| @info "Benders: adding $n_to_add worker process(es) to reach $target total workers." | ||
| addprocs(n_to_add; exeflags=["--project=$(Base.active_project())"]) | ||
| Distributed.remotecall_eval(Main, workers(), :(using GenX)) | ||
| elseif current > target | ||
| @warn "Benders: $current workers are already running but NWorkers=$target was requested. Proceeding with $current workers." | ||
| else | ||
| @info "Benders: $current workers already running — no additional workers needed." | ||
| end | ||
| else | ||
| @warn "Benders: Distributed=true but NWorkers=$target (must be > 1 to enable parallel solving). Running sequentially." | ||
| end | ||
| end |
There was a problem hiding this comment.
isn't this part also in setup_benders_workers!?
| :ExpectFeasibleSubproblems => false, | ||
| :IntegerInvestment => false, | ||
| :Distributed => false, | ||
| :NWorkers => 0, |
There was a problem hiding this comment.
This default value changes from -1 to 0. Is that okay?
| @expression(EP, eChargeDischargeMaxAC[y in VS_SYM_AC, t = 1:T], | ||
| EP[:vP_AC_DISCHARGE][y, t]+EP[:vP_AC_CHARGE][y, t]) | ||
| end | ||
|
|
There was a problem hiding this comment.
Is this part related to this PR?
| vre_stor!(EP::Model, inputs::Dict, setup::Dict) | ||
|
|
||
| Operational-stage coordinator for the VRE-STOR module. | ||
|
|
||
| Builds and links component operational blocks (`inverter_vre_stor!`, `solar_vre_stor!`, | ||
| `wind_vre_stor!`, `stor_vre_stor!`, `elec_vre_stor!`) and enforces module-level | ||
| constraints using planning capacities from investment functions. | ||
|
|
||
| Core constraints include AC-balance dispatch and grid-interface limits: |
There was a problem hiding this comment.
are we removing the docstring for vre_stor here?
| @variable(EP, vNEW_TRANS_CAP[l in EXPANSION_LINES]>=0) | ||
| if DiscreteInvestments == 1 | ||
| @variable(EP, vNEW_TRANS_LINES[l in DISCRETE_BUILD_LINES], Bin) | ||
| end |
There was a problem hiding this comment.
Same as above. I think this part is also in capacity_decision.jl
| # Guard against unsupported Benders + VRE-STOR combination | ||
| if setup["Benders"] == 1 | ||
| if setup["LDSAdditionalConstraints"] == 1 | ||
| @warn "LDSAdditionalConstraints=1 applies to problems with non-representative periods and is not supported in the current Benders implementation. Benders will proceed as if LDSAdditionalConstraints=0" | ||
| end | ||
| end |
There was a problem hiding this comment.
are these lines from the Benders PR?
| else | ||
| hourly_matching!(EP, inputs) | ||
| end | ||
| hourly_matching!(EP, inputs) |
There was a problem hiding this comment.
We also need to double check the hourly matching for Benders.
| # (Benders case with VRE_STOR already errored at generate_model entry point) | ||
| if !isempty(inputs["VRE_STOR"]) | ||
| if setup["LDES_Feasible"] == 0 && ((setup["Benders"] == 1 && haskey(inputs, "SubPeriod_Index") && !isempty(inputs["VS_LDS"])) || ((inputs["REP_PERIOD"] > 1) && !isempty(inputs["VS_LDS"]))) | ||
| if (setup["Benders"] == 1 && haskey(inputs, "SubPeriod_Index") && !isempty(inputs["VS_LDS"])) || (inputs["REP_PERIOD"] > 1 && !isempty(inputs["VS_LDS"])) |
There was a problem hiding this comment.
Sorry, can you please remind me why we are removing this part here setup["LDES_Feasible"] == 0?
Description
This PR adds code to support expansion decisions of DCOPF constrained GenX models that can be solved both monolithically or using Benders Decomposition. This work was originally started by @sambuddhac. It includes updates to settings, inputs loading, model construction, and solution methods. Part of the motivation for this work is supporting nodal spatial resolution of CEMs. In these cases, you might solve with DCOPF constraints, and you might also want to have integer decisions on new transmisison or generation builds (e.g., CC might be built in 500 MW increments to avoid unrealistic modular CC construction in lots of different zones). This PR is intended as a second step after the Benders PR (#914) is merged.
DiscreteInvestmentsflag in the settings of GenX. This controls whether there can be integer variables in the model (not that I chose to call thisDiscreteInvestmentsoverIntegerInvestmentsbecause MacroEnergySolvers.jl already has anIntegerInvestmentssetting). This can be applied to both resources and transmission lines. IfDiscreteInvestmentsis set to 1, then GenX will look for a column headerDiscrete_Buildin the Network.csv, Thermal.csv, and Vre.CSV and throw a warning statement if none of these files have the column header. This header controls which resources or lines can have discrete builds. This also gives the user flexiblity in controlling which components should be treated as integer/binary build decisions.Discrete_Buildcolumn has a 1, then there can be at least one new line constructed on that corridor. GenX internally builds a new DataFrame with each line separated out with individual flow variables on them. This is important for handling DC-OPF constraints. In addition, it supports the case where there may be multiple discrete parallel lines on a corridor, and the user can pass these directly with only one line of the CSV. There is an additional constraint added which adds a solve order to identical lines to avoid degeneracy.Discrete_Buildto zero, but there is a nonzeroLine_Max_Reinforcement_MW, then that line will be treated as the traditional line expansion available in GenX (note that this can essentially be thought of as reconductoring). If the discrete build flag is set to 1, thenLine_Max_Reinforcement_MWis used to determine the size of the new lines (note: we can restructure this if you think new lines should have more columns to support this instead of using the existing), with theNew_Line_Cap_Size_MWcolumn name used to determine how may lines fit intoLine_Max_Reinforcement_MW.FIXED_LINESwhich are lines that can't be expanded,EXPANSION_LINES, which are lines that have continuous reinforcement on them,DISCRETE_BUILD_LINESwhich are lines that have a binary build decision associated with them, andPHANTOM_LINES, which are theDISCRETE_BUILD_LINESwhich are on new corridors (this is important for the line angle limit constraints, which you only want to have applied if the line is built).A couple of additional notes:
vFLOWvariable, and this will be zero for any line not constructed. @sambuddhac may have a better idea on whether this is the case.@gschivley and I had discussions on the above structuring, so tagging him in case he wants to give input on how it came together.
What type of PR is this? (check all applicable)
Related Tickets & Documents
This PR also address the feature request of #900
Checklist
How this can be tested
There is a new example case (12) and a new set of unit tests. The unit tests run a smaller time horizon version of example 12 with both monolithic and Benders. In addition, the unit test running the three zone case also runs it with
DiscreteInvestments=1to test integer build decisions on resources.Post-approval checklist for GenX core developers
After the PR is approved