-
Notifications
You must be signed in to change notification settings - Fork 141
Add new resource type: CCS with solvent storage #854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious — what’s the reason for using a settings flag rather than a resource attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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