Add new resource type: CCS with solvent storage #854
Add new resource type: CCS with solvent storage #854qluo0320github wants to merge 25 commits intodevelopfrom
Conversation
|
Thanks @qluo0320github for reopening this PR! 🙌 |
This reverts commit 4a15eb5.
| "PoliciesFolder" => "policies", | ||
| "ObjScale" => 1) | ||
| "ObjScale" => 1, | ||
| "FlexibleCCS" => 1) |
There was a problem hiding this comment.
Just curious — what’s the reason for using a settings flag rather than a resource attribute?
lbonaldo
left a comment
There was a problem hiding this comment.
Hey @qluo0320github! Thanks so much for adding this new resource. I’ve added a few comments to the code and rebased the branch onto the current develop. Would you mind running the example case again and seeing if the results make sense to you? Thank you!
| end | ||
|
|
||
| if MultiStage == 1 | ||
| @expression(EP, eExistingCap_CCS_SS[y in CCS_SOLVENT_STORAGE, i = 1:7], vEXISTINGCAP_CCS_SS[y,i]) |
There was a problem hiding this comment.
Is multistage supported? I think we need to update the configure_ddp_dicts function in dual_dyanimic_programming.jl as well to make it run. For now, I added a check that throws an error if CCS_SOLVENT_STORAGE is used with both retrofit and multistage (as we did for allam cycle), but please let me if I'm wrong.
| @expression(EP, eCInv_CCS_SS[y in CCS_SOLVENT_STORAGE, i in 1:7], | ||
| if y in NEW_CAP_CCS_SS # Resources eligible for new capacity | ||
| if y in COMMIT_CCS_SS # Resource eligible for Unit commitment | ||
| solvent_storage_dict[y,"inv_cost"][i] * solvent_storage_dict[y,"cap_size"][i] * EP[:vCAP_CCS_SS][y, i] | ||
| else | ||
| solvent_storage_dict[y,"inv_cost"][i] * EP[:vCAP_CCS_SS][y, i] | ||
| end | ||
| else | ||
| 0 | ||
| end) | ||
|
|
||
| # Fixed O&M cost of each component in CCS_SOLVENT_STORAGE | ||
| @expression(EP, eCFom_CCS_SS[y in CCS_SOLVENT_STORAGE, i in 1:7], | ||
| solvent_storage_dict[y,"fom_cost"][i] * eTotalCap_CCS_SS[y,i]) | ||
|
|
||
| # Total fixed cost expression - combines investment and fixed O&M costs | ||
| @expression(EP, eCFix_CCS_SS[y in CCS_SOLVENT_STORAGE, i in 1:7], | ||
| if y in NEW_CAP_CCS_SS | ||
| # For resources with new capacity: investment cost + fixed O&M cost | ||
| EP[:eCInv_CCS_SS][y, i] + EP[:eCFom_CCS_SS][y, i] | ||
| else | ||
| # For existing resources: only fixed O&M cost | ||
| EP[:eCFom_CCS_SS][y, i] | ||
| end) | ||
|
|
||
| # connect eCFix_CCS_SS_Plant to eCFix | ||
| @expression(EP, eCFix_CCS_SS_Plant[y in CCS_SOLVENT_STORAGE], sum(EP[:eCFix_CCS_SS][y,i] for i in 1:7)) | ||
| @expression(EP, eTotalCFix_CCS_SS, sum(EP[:eCFix_CCS_SS_Plant][y] for y in CCS_SOLVENT_STORAGE)) | ||
|
|
||
| # connect eCInv_CCS_SS_Plant to eCInv | ||
| @expression(EP, eCInv_CCS_SS_Plant[y in CCS_SOLVENT_STORAGE], sum(EP[:eCInv_CCS_SS][y,i] for i in 1:7)) | ||
| @expression(EP, eTotalCInv_CCS_SS, sum(EP[:eCInv_CCS_SS_Plant][y] for y in CCS_SOLVENT_STORAGE)) |
There was a problem hiding this comment.
I've updated the file splitting eCFix = eCInv + eCFom. Could you please double check it makes sense to you?
| if MultiStage == 1 | ||
| # Existing capacity variable is equal to existing capacity specified in the input file | ||
| @constraint(EP, cExistingCap_CCS_SS[y in CCS_SOLVENT_STORAGE, i in 1:7], EP[:vEXISTINGCAP_CCS_SS][y,i]== solvent_storage_dict[y, "existing_cap"][i]) | ||
| end |
There was a problem hiding this comment.
I believe this constraint is repeated (see line 118)
| # sum to annual level | ||
| @expression(EP, eCVar_CCS_SS[y in CCS_SOLVENT_STORAGE], sum(EP[:eCVar_CCS_SS_unit][y,i,t] for i in 1:5 for t in 1:T)) | ||
| # sum to zonal-annual level | ||
| @expression(EP, eZonalCVar_CCS_SS[z = 1:Z], sum(EP[:eCVar_CCS_SS][y] for y in intersect(CCS_SOLVENT_STORAGE, resources_in_zone_by_rid(gen, z)))) |
There was a problem hiding this comment.
Pre-compute set outside @expression
| @expression(EP, eZonalCVar_CCS_SS[z = 1:Z], sum(EP[:eCVar_CCS_SS][y] for y in intersect(CCS_SOLVENT_STORAGE, resources_in_zone_by_rid(gen, z)))) | |
| CCS_SOLVENT_STORAGE_BY_ZONE = map(1:Z) do z | |
| return intersect(CCS_SOLVENT_STORAGE, resources_in_zone_by_rid(gen, z)) | |
| end | |
| @expression(EP, eZonalCVar_CCS_SS[z = 1:Z], | |
| sum(EP[:eCVar_CCS_SS][y] | |
| for y in CCS_SOLVENT_STORAGE_BY_ZONE[z])) |
| @constraint(EP, cP[y in CCS_SOLVENT_STORAGE, t = 1:T], eP_CCS_SS[y, t] == EP[:vP][y,t]) | ||
| @expression(EP, ePowerBalance_CCS_SS[t = 1:T, z = 1:Z], | ||
| sum(EP[:eP_CCS_SS][y, t] - EP[:vCHARGE_CCS_SS][y, t] | ||
| for y in intersect(CCS_SOLVENT_STORAGE, resources_in_zone_by_rid(gen, z)))) |
There was a problem hiding this comment.
similar to the previous comment:
| for y in intersect(CCS_SOLVENT_STORAGE, resources_in_zone_by_rid(gen, z)))) | |
| for y in CCS_SOLVENT_STORAGE_BY_ZONE[z])) |
| @constraint(EP,[y in COMMIT_CCS_SS, i in [gasturbine, absorber, compressor], t = 1:T], | ||
| EP[:vOutput_CCS_SS][y,i,t]-EP[:vOutput_CCS_SS][y,i,hoursbefore(p, t, 1)] <= solvent_storage_dict[y, "ramp_up"][i]*solvent_storage_dict[y, "cap_size"][i]*(vCOMMIT_CCS_SS[y,i,t]-vSTART_CCS_SS[y,i,t]) | ||
| + min(1,max(solvent_storage_dict[y, "min_power"][i],solvent_storage_dict[y, "ramp_up"][i]))*solvent_storage_dict[y, "cap_size"][i]*vSTART_CCS_SS[y,i,t] | ||
| -solvent_storage_dict[y, "min_power"][i]*solvent_storage_dict[y, "cap_size"][i]*vSHUT_CCS_SS[y,i,t]) |
There was a problem hiding this comment.
Two questions on this constraint:
- do we need to include regulation and reserves terms?
- can the max power output be different than 1 (e.g. inputs["pP_Max"])
| tempCVar += eCVar_CCS_SS_zone | ||
| tempCTotal += eCFix_CCS_SS_zone + eCVar_CCS_SS_zone | ||
| if setup["UCommit"] >= 1 && !isempty(Y_ZONE_CCS_SS) | ||
| eCStart_CCS_SS = sum(value.(EP[:eCStart_CCS_SS][Y_ZONE_CCS_SS, :])) + |
There was a problem hiding this comment.
Should we use the sum of (EP[:eCStart_CCS_SS][y,t] + EP[:eCStart_CCS_SS_steamturbine][y,t] + EP[:eCStart_CCS_SS_regenerator][y,t]) instead of EP[:eCStart_CCS_SS] only?
Description
What type of PR is this? (check all applicable)
Checklist
How this can be tested
An example case "11_three_zones_CCS_solvent_storage" is used in test.
Post-approval checklist for GenX core developers
After the PR is approved