diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ab2ba877..0abde2ecb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 for anyone running non-myopic multistage GenX with asymmetric storage. - Fix computation of cumulative minimum capacity retirements in multistage GenX (#514) - Fix access of eELOSSByZone expr before initialization (#541) +- Correctly write unmet reserves (in reg_dn.csv) (#575) +- Correctly scale total reserves column (in reg_dn.csv) (#594) ### Changed - Use add_to_expression! instead of the += and -= operators for memory performance improvements (#498). @@ -61,6 +63,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 "Load" now typically refers only to the transferrence of data from files to memory, except for a few places such as the common term "value of lost load" which refers to non-served demand (#397). - `New_Build = -1` in `Generators_data.csv`: instead, use `New_Build = 0` and `Can_Retire = 0`. +- The matrix-style input of the grid for Network.csv is deprecated in favor a column-style input. + Instead of columns z1, z2, ... with entries -1, 0, 1, use two columns: Start_Zone, End_Zone (#591). ## [0.3.6] - 2023-08-01 diff --git a/Example_Systems/RealSystemExample/ISONE_Trizone/Network.csv b/Example_Systems/RealSystemExample/ISONE_Trizone/Network.csv index a26c95a6be..7afea3db0f 100644 --- a/Example_Systems/RealSystemExample/ISONE_Trizone/Network.csv +++ b/Example_Systems/RealSystemExample/ISONE_Trizone/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -NENG_ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +NENG_ME,z3,,,,,,,,,,,, diff --git a/Example_Systems/RealSystemExample/ISONE_Trizone_FullTimeseries/Network.csv b/Example_Systems/RealSystemExample/ISONE_Trizone_FullTimeseries/Network.csv index a26c95a6be..7afea3db0f 100644 --- a/Example_Systems/RealSystemExample/ISONE_Trizone_FullTimeseries/Network.csv +++ b/Example_Systems/RealSystemExample/ISONE_Trizone_FullTimeseries/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -NENG_ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +NENG_ME,z3,,,,,,,,,,,, diff --git a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p1/Network.csv b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p1/Network.csv index 13317c8d9f..76bb6f5c34 100644 --- a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p1/Network.csv +++ b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p1/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 -NENG_ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 +NENG_ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p2/Network.csv b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p2/Network.csv index 13317c8d9f..76bb6f5c34 100644 --- a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p2/Network.csv +++ b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p2/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 -NENG_ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 +NENG_ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p3/Network.csv b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p3/Network.csv index 13317c8d9f..76bb6f5c34 100644 --- a/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p3/Network.csv +++ b/Example_Systems/RealSystemExample/ISONE_Trizone_MultiStage/Inputs/Inputs_p3/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 -NENG_ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0,5900,0.062,30 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0,4000,0.062,30 +NENG_ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/RealSystemExample/MGA_ISONE_Trizone_FullTimeseries/Network.csv b/Example_Systems/RealSystemExample/MGA_ISONE_Trizone_FullTimeseries/Network.csv index a26c95a6be..7afea3db0f 100644 --- a/Example_Systems/RealSystemExample/MGA_ISONE_Trizone_FullTimeseries/Network.csv +++ b/Example_Systems/RealSystemExample/MGA_ISONE_Trizone_FullTimeseries/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -NENGREST,z1,1,1,-1,0,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -NENG_CT,z2,2,1,0,-1,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -NENG_ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +NENGREST,z1,1,1,2,2950,NENGREST_to_NENG_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +NENG_CT,z2,2,1,3,2000,NENGREST_to_NENG_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +NENG_ME,z3,,,,,,,,,,,, diff --git a/Example_Systems/SmallNewEngland/ThreeZones/Network.csv b/Example_Systems/SmallNewEngland/ThreeZones/Network.csv index 5cca655c66..c6413479ff 100644 --- a/Example_Systems/SmallNewEngland/ThreeZones/Network.csv +++ b/Example_Systems/SmallNewEngland/ThreeZones/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +ME,z3,,,,,,,,,,,, diff --git a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p1/Network.csv b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p1/Network.csv index a67a2667e5..e233912403 100644 --- a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p1/Network.csv +++ b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p1/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 -ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 +ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p2/Network.csv b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p2/Network.csv index a67a2667e5..e233912403 100644 --- a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p2/Network.csv +++ b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p2/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 -ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 +ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p3/Network.csv b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p3/Network.csv index a67a2667e5..e233912403 100644 --- a/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p3/Network.csv +++ b/Example_Systems/SmallNewEngland/ThreeZones_MultiStage/Inputs/Inputs_p3/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 -ME,z3,,,,,,,,,,,,,,,, +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1,Line_Max_Flow_Possible_MW,WACC,Capital_Recovery_Period +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0,7000,0.062,30 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0,5000,0.062,30 +ME,z3,,,,,,,,,,,,,,, diff --git a/Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example/Network.csv b/Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example/Network.csv index 5cca655c66..c6413479ff 100644 --- a/Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example/Network.csv +++ b/Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +ME,z3,,,,,,,,,,,, diff --git a/Example_Systems/VREStor_Example/Network.csv b/Example_Systems/VREStor_Example/Network.csv index c286cebd00..1a7000a3b6 100644 --- a/Example_Systems/VREStor_Example/Network.csv +++ b/Example_Systems/VREStor_Example/Network.csv @@ -1,4 +1,4 @@ -Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,Line_Min_Flow_MW,transmission_path_name,Line_Reinforcement_Cost_per_MWyr,Line_Reinforcement_Cost_per_MW,Line_Loss_Percentage,Line_Max_Reinforcement_MW,DerateCapRes_1,CapRes_Excl_1,DerateCapRes_2,CapRes_Excl_2,DerateCapRes_3,CapRes_Excl_3 -z1,1.0,1.0,-1.0,0.0,820.0,820.0,EIC_to_TRE,45958.0,948772.0,0.0649,410.0,0.95,0.0,0.95,0.0,0.95,0.0 -z2,2.0,1.0,0.0,-1.0,1830.0,1830.0,EIC_to_WECC,71600.0,1478140.0,0.1001,915.0,0.95,0.0,0.95,0.0,0.95,0.0 -z3,,,,,,,,,,,,,,,,, +Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,Line_Min_Flow_MW,transmission_path_name,Line_Reinforcement_Cost_per_MWyr,Line_Reinforcement_Cost_per_MW,Line_Loss_Percentage,Line_Max_Reinforcement_MW,DerateCapRes_1,CapRes_Excl_1,DerateCapRes_2,CapRes_Excl_2,DerateCapRes_3,CapRes_Excl_3 +z1,1.0,1,2,820.0,820.0,EIC_to_TRE,45958.0,948772.0,0.0649,410.0,0.95,0.0,0.95,0.0,0.95,0.0 +z2,2.0,1,3,1830.0,1830.0,EIC_to_WECC,71600.0,1478140.0,0.1001,915.0,0.95,0.0,0.95,0.0,0.95,0.0 +z3,,,,,,,,,,,,,,,, diff --git a/docs/src/data_documentation.md b/docs/src/data_documentation.md index 1931325814..5505831700 100644 --- a/docs/src/data_documentation.md +++ b/docs/src/data_documentation.md @@ -188,7 +188,7 @@ This input file contains input parameters related to: 1) definition of model zon |**Settings-specific Columns**| |**Multiple zone model**|| |Network\_Lines | Numerical index for each network line. The length of this column is counted but the actual values are not used.| -| z* (Network map) **OR** Origin_Zone, Destination_Zone | See below | +| z* (Network map) **OR** Start_Zone, End_Zone | See below | |Line\_Max\_Flow\_MW | Existing capacity of the inter-regional transmission line.| |**NetworkExpansion = 1**|| |Line\_Max\_Reinforcement\_MW |Maximum allowable capacity addition to the existing transmission line.| @@ -211,17 +211,17 @@ This input file contains input parameters related to: 1) definition of model zon There are two interfaces implemented for specifying the network topology itself: a matrix interface and a list interface. Only one choice is permitted in a given file. -The list interface consists of a column for the lines origin zone and one for the line's destination zone. +The list interface consists of a column for the lines start zone and one for the line's end zone. Here is a snippet of the Network.csv file for a map with three zones and two lines: ``` -Network_Lines, Origin_Zone, Destination_Zone, - 1, 1, 2, - 2, 1, 3, +Network_Lines, Start_Zone, End_Zone, + 1, 1, 2, + 2, 1, 3, ``` The matrix interface requires N columns labeled `z1, z2, z3 ... zN`, -and L rows, one for each network line (or interregional path), with a `1` in the column corresponding to the 'origin' zone -and a `-1` in the column corresponding to the 'destination' zone for each line. +and L rows, one for each network line (or interregional path), with a `1` in the column corresponding to the 'start' zone +and a `-1` in the column corresponding to the 'end' zone for each line. Here is the same network map implemented as a matrix: ``` Network_Lines, z1, z2, z3, @@ -229,8 +229,8 @@ Network_Lines, z1, z2, z3, 2, 1, 0, -1, ``` -Note that in either case, positive flows indicate flow from origin to destination zone; -negative flows indicate flow from destination to origin zone. +Note that in either case, positive flows indicate flow from start to end zone; +negative flows indicate flow from end to start zone. #### 2.1.3 Demand\_data.csv (Load\_data.csv) diff --git a/docs/src/model_notation.md b/docs/src/model_notation.md index defffad6fc..aa8d39df27 100644 --- a/docs/src/model_notation.md +++ b/docs/src/model_notation.md @@ -238,7 +238,7 @@ $\mathcal{W} \subseteq \mathcal{G}$ | where $\mathcal{W}$ set of hydroelectric g |$\rho_{y,z,t}^{max,pv}$ | Maximum available generation per unit of installed capacity for the solar PV component of a co-located VRE and storage resource during time step t for technology y in zone z [%]| |$\rho_{y,z,t}^{max,wind}$ | Maximum available generation per unit of installed capacity for the wind component of a co-located VRE and storage resource during time step t for technology y in zone z [%]| |$VREIndex_{y,z}$ | Resource bin index for VRE technology $y$ in zone $z$. $VREIndex_{y,z}=1$ for the first bin, and $VREIndex_{y,z}=0$ for remaining bins. Only defined for $y\in \mathcal{VRE}$ | -|$\varphi^{map}_{l,z}$ | Topology of the network, for line l: $\varphi^{map}_{l,z}=1$ for zone $z$ of origin, - 1 for zone $z$ of destination, 0 otherwise. | +|$\varphi^{map}_{l,z}$ | Topology of the network, for line l: $\varphi^{map}_{l,z}=1$ for start zone $z$, - 1 for end zone $z$, 0 otherwise. | |$\eta_{y,z}^{loss}$ | Self discharge rate per time step per unit of installed capacity for storage technology $y$ in zone $z$ [%]| |$\eta_{y,z}^{charge}$ | Single-trip efficiency of storage charging/demand deferral for technology $y$ in zone $z$ [%]| |$\eta_{y,z}^{discharge}$ | Single-trip efficiency of storage (and hydro reservoir) discharging/demand satisfaction for technology $y$ in zone $z$ [%]| diff --git a/src/configure_settings/configure_settings.jl b/src/configure_settings/configure_settings.jl index a7b943416e..7864d47383 100644 --- a/src/configure_settings/configure_settings.jl +++ b/src/configure_settings/configure_settings.jl @@ -46,7 +46,7 @@ function validate_settings!(settings::Dict{Any,Any}) @warn """The behavior of the TimeDomainReduction and OperationWrapping settings have changed recently. OperationWrapping has been removed, and is ignored. The relevant behavior is now controlled by TimeDomainReduction. - Please see the Methods page in the documentation.""" + Please see the Methods page in the documentation.""" maxlog=1 end end diff --git a/src/load_inputs/load_generators_data.jl b/src/load_inputs/load_generators_data.jl index 7aa6947570..71386808a7 100644 --- a/src/load_inputs/load_generators_data.jl +++ b/src/load_inputs/load_generators_data.jl @@ -645,7 +645,7 @@ While for now, New_Build entries of {1, 0, -1} are still supported, this format is being deprecated. Now and going forward, New_Build and Can_Retire should be separate columns, each with values {0, 1}. -Please see the documentation for additional details." +Please see the documentation for additional details." maxlog=1 end function resources_which_can_be_retired(df::DataFrame)::Set{Int64} diff --git a/src/load_inputs/load_network_data.jl b/src/load_inputs/load_network_data.jl index 558699aea5..dc3acfbea3 100644 --- a/src/load_inputs/load_network_data.jl +++ b/src/load_inputs/load_network_data.jl @@ -90,9 +90,9 @@ end Loads the network map from a list-style interface ``` -..., Network_Lines, Origin_Zone, Destination_Zone, ... - 1, 1, 2, - 2, 1, 3, +..., Network_Lines, Start_Zone, End_Zone, ... + 1, 1, 2, + 2, 1, 3, ``` """ function load_network_map_from_list(network_var::DataFrame, Z, L, list_columns) @@ -117,10 +117,11 @@ Loads the network map from a matrix-style interface 2, 1, 0, -1, ``` This is equivalent to the list-style interface where the zone zN with entry +1 is the -starting node of the line and the zone with entry -1 is the ending node of the line. +starting zone of the line and the zone with entry -1 is the ending zone of the line. """ function load_network_map_from_matrix(network_var::DataFrame, Z, L) # Topology of the network source-sink matrix + network_map_matrix_format_deprecation_warning() col = findall(s -> s == "z1", names(network_var))[1] mat = Matrix{Float64}(network_var[1:L, col:col+Z-1]) end @@ -128,14 +129,14 @@ end function load_network_map(network_var::DataFrame, Z, L) columns = names(network_var) - list_columns = ["Origin_Zone", "Destination_Zone"] + list_columns = ["Start_Zone", "End_Zone"] has_network_list = all([c in columns for c in list_columns]) zones_as_strings = ["z" * string(i) for i in 1:Z] has_network_matrix = all([c in columns for c in zones_as_strings]) instructions = """The transmission network should be specified in the form of a matrix - (with columns z1, z2, ... zN) or in the form of lists (with Start_Node, End_Node), + (with columns z1, z2, ... zN) or in the form of lists (with Start_Zone, End_Zone), but not both. See the documentation for examples.""" if has_network_list && has_network_matrix @@ -148,3 +149,14 @@ function load_network_map(network_var::DataFrame, Z, L) load_network_map_from_matrix(network_var, Z, L) end end + +function network_map_matrix_format_deprecation_warning() + @warn """Specifying the network map as a matrix is deprecated as of v0.4 +and will be removed in v0.5. Instead, use the more compact list-style format. + +..., Network_Lines, Start_Zone, End_Zone, ... + 1, 1, 2, + 2, 1, 3, + 3, 2, 3, +""" maxlog=1 +end diff --git a/src/model/core/reserves.jl b/src/model/core/reserves.jl index bf503acf5e..a850ff05e5 100644 --- a/src/model/core/reserves.jl +++ b/src/model/core/reserves.jl @@ -217,6 +217,13 @@ function reserves_core!(EP::Model, inputs::Dict, setup::Dict) REG = inputs["REG"] RSV = inputs["RSV"] + STOR_ALL = inputs["STOR_ALL"] + + pDemand = inputs["pD"] + pP_Max(y, t) = inputs["pP_Max"][y, t] + + systemwide_hourly_demand = sum(pDemand, dims=2) + must_run_vre_generation(t) = sum(pP_Max(y, t) * EP[:eTotalCap][y] for y in intersect(inputs["VRE"], inputs["MUST_RUN"]); init=0) ### Variables ### @@ -228,10 +235,10 @@ function reserves_core!(EP::Model, inputs::Dict, setup::Dict) # Storage techs have two pairs of auxilary variables to reflect contributions to regulation and reserves # when charging and discharging (primary variable becomes equal to sum of these auxilary variables) - @variable(EP, vREG_discharge[y in intersect(inputs["STOR_ALL"], REG), t=1:T] >= 0) # Contribution to regulation (primary reserves) (mirrored variable used for storage devices) - @variable(EP, vRSV_discharge[y in intersect(inputs["STOR_ALL"], RSV), t=1:T] >= 0) # Contribution to operating reserves (secondary reserves) (mirrored variable used for storage devices) - @variable(EP, vREG_charge[y in intersect(inputs["STOR_ALL"], REG), t=1:T] >= 0) # Contribution to regulation (primary reserves) (mirrored variable used for storage devices) - @variable(EP, vRSV_charge[y in intersect(inputs["STOR_ALL"], RSV), t=1:T] >= 0) # Contribution to operating reserves (secondary reserves) (mirrored variable used for storage devices) + @variable(EP, vREG_discharge[y in intersect(STOR_ALL, REG), t=1:T] >= 0) # Contribution to regulation (primary reserves) (mirrored variable used for storage devices) + @variable(EP, vRSV_discharge[y in intersect(STOR_ALL, RSV), t=1:T] >= 0) # Contribution to operating reserves (secondary reserves) (mirrored variable used for storage devices) + @variable(EP, vREG_charge[y in intersect(STOR_ALL, REG), t=1:T] >= 0) # Contribution to regulation (primary reserves) (mirrored variable used for storage devices) + @variable(EP, vRSV_charge[y in intersect(STOR_ALL, RSV), t=1:T] >= 0) # Contribution to operating reserves (secondary reserves) (mirrored variable used for storage devices) @variable(EP, vUNMET_RSV[t=1:T] >= 0) # Unmet operating reserves penalty/cost @@ -239,16 +246,16 @@ function reserves_core!(EP::Model, inputs::Dict, setup::Dict) ## Total system reserve expressions # Regulation requirements as a percentage of demand and scheduled variable renewable energy production in each hour # Reg up and down requirements are symmetric - @expression(EP, eRegReq[t=1:T], inputs["pReg_Req_Demand"]*sum(inputs["pD"][t,z] for z=1:Z) + - inputs["pReg_Req_VRE"]*sum(inputs["pP_Max"][y,t]*EP[:eTotalCap][y] for y in intersect(inputs["VRE"], inputs["MUST_RUN"]))) + @expression(EP, eRegReq[t=1:T], inputs["pReg_Req_Demand"] * systemwide_hourly_demand[t] + + inputs["pReg_Req_VRE"] * must_run_vre_generation(t)) # Operating reserve up / contingency reserve requirements as ˚a percentage of demand and scheduled variable renewable energy production in each hour # and the largest single contingency (generator or transmission line outage) - @expression(EP, eRsvReq[t=1:T], inputs["pRsv_Req_Demand"]*sum(inputs["pD"][t,z] for z=1:Z) + - inputs["pRsv_Req_VRE"]*sum(inputs["pP_Max"][y,t]*EP[:eTotalCap][y] for y in intersect(inputs["VRE"], inputs["MUST_RUN"]))) + @expression(EP, eRsvReq[t=1:T], inputs["pRsv_Req_Demand"] * systemwide_hourly_demand[t] + + inputs["pRsv_Req_VRE"] * must_run_vre_generation(t)) # N-1 contingency requirement is considered only if Unit Commitment is being modeled if UCommit >= 1 && (inputs["pDynamic_Contingency"] >= 1 || inputs["pStatic_Contingency"] > 0) - EP[:eRsvReq] = EP[:eRsvReq] + EP[:eContingencyReq] + add_to_expression!(EP[:eRsvReq], EP[:eContingencyReq]) end ## Objective Function Expressions ## @@ -259,17 +266,29 @@ function reserves_core!(EP::Model, inputs::Dict, setup::Dict) sum(dfGen[y,:Reg_Cost]*vRSV[y,t] for y in RSV, t=1:T) + sum(dfGen[y,:Rsv_Cost]*vREG[y,t] for y in REG, t=1:T) ) add_to_expression!(EP[:eObj], eTotalCRsvPen) +end - ### Constraints ### - - ## Total system reserve constraints - # Regulation requirements as a percentage of demand and scheduled variable renewable energy production in each hour - # Note: frequencty regulation up and down requirements are symmetric and all resources contributing to regulation are assumed to contribute equal capacity to both up and down directions - if !isempty(REG) - @constraint(EP, cReg[t=1:T], sum(vREG[y,t] for y in REG) >= EP[:eRegReq][t]) - end - if !isempty(RSV) - @constraint(EP, cRsvReq[t=1:T], sum(vRSV[y,t] for y in RSV) + vUNMET_RSV[t] >= EP[:eRsvReq][t]) - end - +function reserves_constraints!(EP, inputs) + T = inputs["T"] # Number of time steps (hours) + + REG = inputs["REG"] + RSV = inputs["RSV"] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + vUNMET_RSV = EP[:vUNMET_RSV] + eRegulationRequirement = EP[:eRegReq] + eReserveRequirement = EP[:eRsvReq] + + ## Total system reserve constraints + # Regulation requirements as a percentage of demand and scheduled + # variable renewable energy production in each hour. + # Note: frequency regulation up and down requirements are symmetric and all resources + # contributing to regulation are assumed to contribute equal capacity to both up + # and down directions + if !isempty(REG) + @constraint(EP, cReg[t=1:T], sum(vREG[y,t] for y in REG) >= eRegulationRequirement[t]) + end + if !isempty(RSV) + @constraint(EP, cRsvReq[t=1:T], sum(vRSV[y,t] for y in RSV) + vUNMET_RSV[t] >= eReserveRequirement[t]) + end end diff --git a/src/model/expression_manipulation.jl b/src/model/expression_manipulation.jl index dd2cd86a36..1a2c75eb9b 100644 --- a/src/model/expression_manipulation.jl +++ b/src/model/expression_manipulation.jl @@ -71,6 +71,33 @@ function fill_with_const!(arr::AbstractArray{GenericAffExpr{C,T}, dims}, con::Re return nothing end +###### ###### ###### ###### ###### ###### +# Create an expression from some first-dimension indices of a 2D variable array, +# where all of the 2nd-dimension indices are kept +###### ###### ###### ###### ###### ###### +# +function extract_time_series_to_expression(var::Matrix{VariableRef}, + set::AbstractVector{Int}) + TIME_DIM = 2 + time_range = 1:size(var)[TIME_DIM] + + aff_exprs_data = AffExpr.(0, var[set, :] .=> 1) + new_axes = (set, time_range) + expr = JuMP.Containers.DenseAxisArray(aff_exprs_data, new_axes...) + return expr +end + +function extract_time_series_to_expression(var::JuMP.Containers.DenseAxisArray{VariableRef, 2, Tuple{X, Base.OneTo{Int64}}, Y}, + set::AbstractVector{Int}) where {X, Y} + TIME_DIM = 2 + time_range = var.axes[TIME_DIM] + + aff_exprs = AffExpr.(0, var[set, :] .=> 1) + new_axes = (set, time_range) + expr = JuMP.Containers.DenseAxisArray(aff_exprs.data, new_axes...) + return expr +end + ###### ###### ###### ###### ###### ###### # Element-wise addition of one expression into another # Both arrays must have the same dimensions diff --git a/src/model/generate_model.jl b/src/model/generate_model.jl index 45c964c776..07fbc40a6f 100644 --- a/src/model/generate_model.jl +++ b/src/model/generate_model.jl @@ -94,10 +94,10 @@ function generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAtt EP[:eObj] = AffExpr(0.0) create_empty_expression!(EP, :eGenerationByZone, (Z, T)) - + # Energy losses related to technologies create_empty_expression!(EP, :eELOSSByZone, Z) - + # Initialize Capacity Reserve Margin Expression if setup["CapacityReserveMargin"] > 0 create_empty_expression!(EP, :eCapResMarBalance, (inputs["NCapacityReserveMargin"], T)) @@ -191,6 +191,10 @@ function generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAtt # Policies + if setup["Reserves"] > 0 + reserves_constraints!(EP, inputs) + end + # CO2 emissions limits if setup["CO2Cap"] > 0 co2_cap!(EP, inputs, setup) @@ -236,4 +240,4 @@ function generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAtt end return EP -end \ No newline at end of file +end diff --git a/src/model/resources/curtailable_variable_renewable/curtailable_variable_renewable.jl b/src/model/resources/curtailable_variable_renewable/curtailable_variable_renewable.jl index 5555e3f699..cdd43f1a33 100644 --- a/src/model/resources/curtailable_variable_renewable/curtailable_variable_renewable.jl +++ b/src/model/resources/curtailable_variable_renewable/curtailable_variable_renewable.jl @@ -47,24 +47,24 @@ function curtailable_variable_renewable!(EP::Model, inputs::Dict, setup::Dict) add_similar_to_expression!(EP[:eCapResMarBalance], eCapResMarBalanceVRE) end - ### Constratints ### - # For resource for which we are modeling hourly power output - for y in VRE_POWER_OUT - # Define the set of generator indices corresponding to the different sites (or bins) of a particular VRE technology (E.g. wind or solar) in a particular zone. - # For example the wind resource in a particular region could be include three types of bins corresponding to different sites with unique interconnection, hourly capacity factor and maximim available capacity limits. - VRE_BINS = intersect(dfGen[dfGen[!,:R_ID].>=y,:R_ID], dfGen[dfGen[!,:R_ID].<=y+dfGen[y,:Num_VRE_Bins]-1,:R_ID]) - - # Constraints on contribution to regulation and reserves - if Reserves == 1 - curtailable_variable_renewable_reserves!(EP, inputs) - else - # Maximum power generated per hour by renewable generators must be less than - # sum of product of hourly capacity factor for each bin times its the bin installed capacity - # Note: inequality constraint allows curtailment of output below maximum level. - @constraint(EP, [t=1:T], EP[:vP][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS)) - end - - end + ### Constraints ### + if Reserves == 1 + # Constraints on power output and contribution to regulation and reserves + curtailable_variable_renewable_reserves!(EP, inputs) + remove_reserves_for_binned_vre_resources!(EP, inputs) + else + # For resource for which we are modeling hourly power output + for y in VRE_POWER_OUT + # Define the set of generator indices corresponding to the different sites (or bins) of a particular VRE technology (E.g. wind or solar) in a particular zone. + # For example the wind resource in a particular region could be include three types of bins corresponding to different sites with unique interconnection, hourly capacity factor and maximim available capacity limits. + VRE_BINS = intersect(dfGen[dfGen[!,:R_ID].>=y,:R_ID], dfGen[dfGen[!,:R_ID].<=y+dfGen[y,:Num_VRE_Bins]-1,:R_ID]) + + # Maximum power generated per hour by renewable generators must be less than + # sum of product of hourly capacity factor for each bin times its the bin installed capacity + # Note: inequality constraint allows curtailment of output below maximum level. + @constraint(EP, [t=1:T], EP[:vP][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS)) + end + end # Set power variables for all bins that are not being modeled for hourly output to be zero for y in VRE_NO_POWER_OUT @@ -102,60 +102,53 @@ The amount of frequency regulation and operating reserves procured in each time ``` """ function curtailable_variable_renewable_reserves!(EP::Model, inputs::Dict) - dfGen = inputs["dfGen"] T = inputs["T"] - VRE_POWER_OUT = intersect(dfGen[dfGen.Num_VRE_Bins.>=1,:R_ID], inputs["VRE"]) - - for y in VRE_POWER_OUT - # Define the set of generator indices corresponding to the different sites (or bins) of a particular VRE technology (E.g. wind or solar) in a particular zone. - # For example the wind resource in a particular region could be include three types of bins corresponding to different sites with unique interconnection, hourly capacity factor and maximim available capacity limits. - VRE_BINS = intersect(dfGen[dfGen[!,:R_ID].>=y,:R_ID], dfGen[dfGen[!,:R_ID].<=y+dfGen[y,:Num_VRE_Bins]-1,:R_ID]) - - if y in inputs["REG"] && y in inputs["RSV"] # Resource eligible for regulation and spinning reserves - @constraints(EP, begin - # For VRE, reserve contributions must be less than the specified percentage of the capacity factor for the hour - [t=1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - [t=1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - - # Power generated and regulation reserve contributions down per hour must be greater than zero - [t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= 0 - - # Power generated and reserve contributions up per hour by renewable generators must be less than - # hourly capacity factor. Note: inequality constraint allows curtailment of output below maximum level. - [t=1:T], EP[:vP][y,t]+EP[:vREG][y,t]+EP[:vRSV][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - end) - elseif y in inputs["REG"] # Resource only eligible for regulation reserves - @constraints(EP, begin - # For VRE, reserve contributions must be less than the specified percentage of the capacity factor for the hour - [t=1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - - # Power generated and regulation reserve contributions down per hour must be greater than zero - [t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= 0 - - # Power generated and reserve contributions up per hour by renewable generators must be less than - # hourly capacity factor. Note: inequality constraint allows curtailment of output below maximum level. - [t=1:T], EP[:vP][y,t]+EP[:vREG][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - end) - - elseif y in inputs["RSV"] # Resource only eligible for spinning reserves - only available in up, no down spinning reserves - - @constraints(EP, begin - # For VRE, reserve contributions must be less than the specified percentage of the capacity factor for the hour - [t=1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - - # Power generated and reserve contributions up per hour by renewable generators must be less than - # hourly capacity factor. Note: inequality constraint allows curtailment of output below maximum level. - [t=1:T], EP[:vP][y,t]+EP[:vRSV][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS) - end) - else # Resource not eligible for reserves - # Maximum power generated per hour by renewable generators must be less than - # sum of product of hourly capacity factor for each bin times its the bin installed capacity - # Note: inequality constraint allows curtailment of output below maximum level. - @constraint(EP, [t=1:T], EP[:vP][y,t] <= sum(inputs["pP_Max"][yy,t]*EP[:eTotalCap][yy] for yy in VRE_BINS)) - end - end + VRE = inputs["VRE"] + VRE_POWER_OUT = intersect(dfGen[dfGen.Num_VRE_Bins.>=1,:R_ID], VRE) + REG = intersect(VRE_POWER_OUT, inputs["REG"]) + RSV = intersect(VRE_POWER_OUT, inputs["RSV"]) + + eTotalCap = EP[:eTotalCap] + vP = EP[:vP] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + hourly_capacity_factor(y, t) = inputs["pP_Max"][y, t] + reg_max(y) = dfGen[y, :Reg_Max] + rsv_max(y) = dfGen[y, :Rsv_Max] + + hourly_capacity(y, t) = hourly_capacity_factor(y, t) * eTotalCap[y] + resources_in_bin(y) = UnitRange(y, y + dfGen[y, :Num_VRE_Bins] - 1) + hourly_bin_capacity(y, t) = sum(hourly_capacity(yy, t) for yy in resources_in_bin(y)) + + @constraint(EP, [y in REG, t in 1:T], vREG[y, t] <= reg_max(y) * hourly_bin_capacity(y, t)) + @constraint(EP, [y in RSV, t in 1:T], vRSV[y, t] <= rsv_max(y) * hourly_bin_capacity(y, t)) + + expr = extract_time_series_to_expression(vP, VRE_POWER_OUT) + add_similar_to_expression!(expr[REG, :], -vREG[REG, :]) + @constraint(EP, [y in VRE_POWER_OUT, t in 1:T], expr[y, t] >= 0) + + expr = extract_time_series_to_expression(vP, VRE_POWER_OUT) + add_similar_to_expression!(expr[REG, :], +vREG[REG, :]) + add_similar_to_expression!(expr[RSV, :], +vRSV[RSV, :]) + @constraint(EP, [y in VRE_POWER_OUT, t in 1:T], expr[y, t] <= hourly_bin_capacity(y, t)) +end + +function remove_reserves_for_binned_vre_resources!(EP::Model, inputs::Dict) + dfGen = inputs["dfGen"] + + VRE = inputs["VRE"] + VRE_POWER_OUT = intersect(dfGen[dfGen.Num_VRE_Bins.>=1,:R_ID], VRE) + REG = inputs["REG"] + RSV = inputs["RSV"] + VRE_NO_POWER_OUT = setdiff(VRE, VRE_POWER_OUT) + for y in intersect(VRE_NO_POWER_OUT, REG) + fix.(EP[:vREG][y,:], 0.0, force=true) + end + for y in intersect(VRE_NO_POWER_OUT, RSV) + fix.(EP[:vRSV][y,:], 0.0, force=true) + end end diff --git a/src/model/resources/hydro/hydro_res.jl b/src/model/resources/hydro/hydro_res.jl index 8b86e5517a..37eddce2ee 100644 --- a/src/model/resources/hydro/hydro_res.jl +++ b/src/model/resources/hydro/hydro_res.jl @@ -185,45 +185,32 @@ function hydro_res_reserves!(EP::Model, inputs::Dict) T = inputs["T"] # Number of time steps (hours) HYDRO_RES = inputs["HYDRO_RES"] + REG = inputs["REG"] + RSV = inputs["RSV"] - HYDRO_RES_REG_RSV = intersect(HYDRO_RES, inputs["REG"], inputs["RSV"]) # Set of reservoir hydro resources with both regulation and spinning reserves + HYDRO_RES_REG = intersect(HYDRO_RES, REG) # Set of reservoir hydro resources with regulation reserves + HYDRO_RES_RSV = intersect(HYDRO_RES, RSV) # Set of reservoir hydro resources with spinning reserves - HYDRO_RES_REG = intersect(HYDRO_RES, inputs["REG"]) # Set of reservoir hydro resources with regulation reserves - HYDRO_RES_RSV = intersect(HYDRO_RES, inputs["RSV"]) # Set of reservoir hydro resources with spinning reserves + vP = EP[:vP] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + eTotalCap = EP[:eTotalCap] + reg_max(y) = dfGen[y, :Reg_Max] + rsv_max(y) = dfGen[y, :Rsv_Max] - HYDRO_RES_REG_ONLY = setdiff(HYDRO_RES_REG, HYDRO_RES_RSV) # Set of reservoir hydro resources only with regulation reserves - HYDRO_RES_RSV_ONLY = setdiff(HYDRO_RES_RSV, HYDRO_RES_REG) # Set of reservoir hydro resources only with spinning reserves + max_up_reserves_lhs = extract_time_series_to_expression(vP, HYDRO_RES) + max_dn_reserves_lhs = extract_time_series_to_expression(vP, HYDRO_RES) - if !isempty(HYDRO_RES_REG_RSV) - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed capacity - cRegulation[y in HYDRO_RES_REG_RSV, t in 1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - cReserve[y in HYDRO_RES_REG_RSV, t in 1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] - # Maximum discharging rate and contribution to reserves up must be less than power rating - cMaxReservesUp[y in HYDRO_RES_REG_RSV, t in 1:T], EP[:vP][y,t]+EP[:vREG][y,t]+EP[:vRSV][y,t] <= EP[:eTotalCap][y] - # Maximum discharging rate and contribution to regulation down must be greater than zero - cMaxReservesDown[y in HYDRO_RES_REG_RSV, t in 1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= 0 - end) - end + S = HYDRO_RES_REG + add_similar_to_expression!(max_up_reserves_lhs[S, :], vREG[S, :]) + add_similar_to_expression!(max_dn_reserves_lhs[S, :], -vREG[S, :]) - if !isempty(HYDRO_RES_REG_ONLY) - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed capacity - cRegulation[y in HYDRO_RES_REG_ONLY, t in 1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - # Maximum discharging rate and contribution to reserves up must be less than power rating - cMaxReservesUp[y in HYDRO_RES_REG_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vREG][y,t] <= EP[:eTotalCap][y] - # Maximum discharging rate and contribution to regulation down must be greater than zero - cMaxReservesDown[y in HYDRO_RES_REG_ONLY, t in 1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= 0 - end) - end + S = HYDRO_RES_RSV + add_similar_to_expression!(max_up_reserves_lhs[S, :], vRSV[S, :]) - if !isempty(HYDRO_RES_RSV_ONLY) - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed capacity - cReserve[y in HYDRO_RES_RSV_ONLY, t in 1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] - # Maximum discharging rate and contribution to reserves up must be less than power rating - cMaxReservesUp[y in HYDRO_RES_RSV_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vRSV][y,t] <= EP[:eTotalCap][y] - end) - end + @constraint(EP, [y in HYDRO_RES, t in 1:T], max_up_reserves_lhs[y, t] <= eTotalCap[y]) + @constraint(EP, [y in HYDRO_RES, t in 1:T], max_dn_reserves_lhs[y, t] >= 0) + @constraint(EP, [y in HYDRO_RES_REG, t in 1:T], vREG[y, t] <= reg_max(y) * eTotalCap[y]) + @constraint(EP, [y in HYDRO_RES_RSV, t in 1:T], vRSV[y, t] <= rsv_max(y) * eTotalCap[y]) end diff --git a/src/model/resources/hydrogen/electrolyzer.jl b/src/model/resources/hydrogen/electrolyzer.jl index 300ef34e51..64463fbf47 100644 --- a/src/model/resources/hydrogen/electrolyzer.jl +++ b/src/model/resources/hydrogen/electrolyzer.jl @@ -122,18 +122,16 @@ function electrolyzer!(EP::Model, inputs::Dict, setup::Dict) end) ### Minimum and maximum power output constraints (Constraints #3-4) - if setup["Reserves"] == 1 - ## Electrolyzers currently do not contribute to operating reserves. Could allow them to contribute as a curtailable demand in future. - else - @constraints(EP, begin - # Minimum stable power generated per technology "y" at hour "t" Min_Power - [y in ELECTROLYZERS, t in 1:T], EP[:vUSE][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] - - # Maximum power generated per technology "y" at hour "t" - [y in ELECTROLYZERS, t in 1:T], EP[:vUSE][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] - end) - - end + # Electrolyzers currently do not contribute to operating reserves, so there is not + # special case (for Reserves == 1) here. + # Could allow them to contribute as a curtailable demand in future. + @constraints(EP, begin + # Minimum stable power generated per technology "y" at hour "t" Min_Power + [y in ELECTROLYZERS, t in 1:T], EP[:vUSE][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] + + # Maximum power generated per technology "y" at hour "t" + [y in ELECTROLYZERS, t in 1:T], EP[:vUSE][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] + end) ### Minimum hydrogen production constraint (if any) (Constraint #5) kt_to_t = 10^3 diff --git a/src/model/resources/storage/storage_all.jl b/src/model/resources/storage/storage_all.jl index c9d69da1d1..d0ff71ce1a 100644 --- a/src/model/resources/storage/storage_all.jl +++ b/src/model/resources/storage/storage_all.jl @@ -156,140 +156,64 @@ function storage_all_reserves!(EP::Model, inputs::Dict, setup::Dict) dfGen = inputs["dfGen"] T = inputs["T"] p = inputs["hours_per_subperiod"] - CapacityReserveMargin = setup["CapacityReserveMargin"] + CapacityReserveMargin = setup["CapacityReserveMargin"] > 1 STOR_ALL = inputs["STOR_ALL"] - STOR_REG_RSV = intersect(STOR_ALL, inputs["REG"], inputs["RSV"]) # Set of storage resources with both REG and RSV reserves - - STOR_REG = intersect(STOR_ALL, inputs["REG"]) # Set of storage resources with REG reserves - STOR_RSV = intersect(STOR_ALL, inputs["RSV"]) # Set of storage resources with RSV reserves - - STOR_NO_RES = setdiff(STOR_ALL, STOR_REG, STOR_RSV) # Set of storage resources with no reserves - - STOR_REG_ONLY = setdiff(STOR_REG, STOR_RSV) # Set of storage resources only with REG reserves - STOR_RSV_ONLY = setdiff(STOR_RSV, STOR_REG) # Set of storage resources only with RSV reserves - - if !isempty(STOR_REG_RSV) - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed discharge power capacity - [y in STOR_REG_RSV, t=1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - [y in STOR_REG_RSV, t=1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] - - # Actual contribution to regulation and reserves is sum of auxilary variables for portions contributed during charging and discharging - [y in STOR_REG_RSV, t=1:T], EP[:vREG][y,t] == EP[:vREG_charge][y,t]+EP[:vREG_discharge][y,t] - [y in STOR_REG_RSV, t=1:T], EP[:vRSV][y,t] == EP[:vRSV_charge][y,t]+EP[:vRSV_discharge][y,t] - - # Maximum charging rate plus contribution to reserves up must be greater than zero - # Note: when charging, reducing charge rate is contributing to upwards reserve & regulation as it drops net demand - [y in STOR_REG_RSV, t=1:T], EP[:vCHARGE][y,t]-EP[:vREG_charge][y,t]-EP[:vRSV_charge][y,t] >= 0 - - # Maximum discharging rate and contribution to reserves down must be greater than zero - # Note: when discharging, reducing discharge rate is contributing to downwards regulation as it drops net supply - [y in STOR_REG_RSV, t=1:T], EP[:vP][y,t]-EP[:vREG_discharge][y,t] >= 0 - - # Maximum charging rate plus contribution to regulation down must be less than available storage capacity - [y in STOR_REG_RSV, t=1:T], dfGen[y,:Eff_Up]*(EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]) <= EP[:eTotalCapEnergy][y]-EP[:vS][y, hoursbefore(p,t,1)] - # Note: maximum charge rate is also constrained by maximum charge power capacity, but as this differs by storage type, - # this constraint is set in functions below for each storage type - end) - # Maximum discharging rate and contribution to reserves up must be less than power rating OR available stored energy in prior period, whichever is less - # wrapping from end of sample period to start of sample period for energy capacity constraint - if CapacityReserveMargin > 0 - @constraints(EP, begin - [y in STOR_REG_RSV, t=1:T], EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_REG_RSV, t=1:T], (EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - else - @constraints(EP, begin - [y in STOR_REG_RSV, t=1:T], EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_REG_RSV, t=1:T], (EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - end - - end - if !isempty(STOR_REG_ONLY) - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed capacity - [y in STOR_REG_ONLY, t=1:T], EP[:vREG][y,t] <= dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - - # Actual contribution to regulation and reserves is sum of auxilary variables for portions contributed during charging and discharging - [y in STOR_REG_ONLY, t=1:T], EP[:vREG][y,t] == EP[:vREG_charge][y,t]+EP[:vREG_discharge][y,t] - - # Maximum charging rate plus contribution to reserves up must be greater than zero - # Note: when charging, reducing charge rate is contributing to upwards reserve & regulation as it drops net demand - [y in STOR_REG_ONLY, t=1:T], EP[:vCHARGE][y,t]-EP[:vREG_charge][y,t] >= 0 - - # Maximum discharging rate and contribution to reserves down must be greater than zero - # Note: when discharging, reducing discharge rate is contributing to downwards regulation as it drops net supply - [y in STOR_REG_ONLY, t=1:T], EP[:vP][y,t] - EP[:vREG_discharge][y,t] >= 0 - - # Maximum charging rate plus contribution to regulation down must be less than available storage capacity - [y in STOR_REG_ONLY, t=1:T], dfGen[y,:Eff_Up]*(EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]) <= EP[:eTotalCapEnergy][y]-EP[:vS][y, hoursbefore(p,t,1)] - # Note: maximum charge rate is also constrained by maximum charge power capacity, but as this differs by storage type, - # this constraint is set in functions below for each storage type - end) - # Maximum discharging rate and contribution to reserves up must be less than power rating OR available stored energy in prior period, whichever is less - # wrapping from end of sample period to start of sample period for energy capacity constraint - if CapacityReserveMargin > 0 - @constraints(EP, begin - [y in STOR_REG_ONLY, t=1:T], EP[:vP][y,t] + EP[:vCAPRES_discharge][y,t] + EP[:vREG_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_REG_ONLY, t=1:T], (EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vREG_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - else - @constraints(EP, begin - [y in STOR_REG_ONLY, t=1:T], EP[:vP][y,t] + EP[:vREG_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_REG_ONLY, t=1:T], (EP[:vP][y,t]+EP[:vREG_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - end - - end - if !isempty(STOR_RSV_ONLY) - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum storage contribution to reserves is a specified fraction of installed capacity - [y in STOR_RSV_ONLY, t=1:T], EP[:vRSV][y,t] <= dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] - - # Actual contribution to regulation and reserves is sum of auxilary variables for portions contributed during charging and discharging - [y in STOR_RSV_ONLY, t=1:T], EP[:vRSV][y,t] == EP[:vRSV_charge][y,t]+EP[:vRSV_discharge][y,t] - - # Maximum charging rate plus contribution to reserves up must be greater than zero - # Note: when charging, reducing charge rate is contributing to upwards reserve & regulation as it drops net demand - [y in STOR_RSV_ONLY, t=1:T], EP[:vCHARGE][y,t]-EP[:vRSV_charge][y,t] >= 0 - end) - - # Note: maximum charge rate is also constrained by maximum charge power capacity, but as this differs by storage type, - # this constraint is set in functions below for each storage type - - # Maximum discharging rate and contribution to reserves up must be less than power rating OR available stored energy in prior period, whichever is less - # wrapping from end of sample period to start of sample period for energy capacity constraint - if CapacityReserveMargin > 0 - @constraints(EP, begin - [y in STOR_RSV_ONLY, t=1:T], EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vRSV_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_RSV_ONLY, t=1:T], (EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vRSV_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - else - @constraints(EP, begin - [y in STOR_RSV_ONLY, t=1:T], EP[:vP][y,t]+EP[:vRSV_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_RSV_ONLY, t=1:T], (EP[:vP][y,t]+EP[:vRSV_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - end - end - if !isempty(STOR_NO_RES) - # Maximum discharging rate must be less than power rating OR available stored energy in prior period, whichever is less - # wrapping from end of sample period to start of sample period for energy capacity constraint - if CapacityReserveMargin > 0 - @constraints(EP, begin - [y in STOR_NO_RES, t=1:T], EP[:vP][y,t] + EP[:vCAPRES_discharge][y,t] <= EP[:eTotalCap][y] - [y in STOR_NO_RES, t=1:T], (EP[:vP][y,t]+EP[:vCAPRES_discharge][y,t])/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - else - @constraints(EP, begin - [y in STOR_NO_RES, t=1:T], EP[:vP][y,t] <= EP[:eTotalCap][y] - [y in STOR_NO_RES, t=1:T], EP[:vP][y,t]/dfGen[y,:Eff_Down] <= EP[:vS][y, hoursbefore(p,t,1)] - end) - end - end + STOR_REG = intersect(STOR_ALL, inputs["REG"]) # Set of storage resources with REG reserves + STOR_RSV = intersect(STOR_ALL, inputs["RSV"]) # Set of storage resources with RSV reserves + + vP = EP[:vP] + vS = EP[:vS] + vCHARGE = EP[:vCHARGE] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + vREG_charge = EP[:vREG_charge] + vRSV_charge = EP[:vRSV_charge] + vREG_discharge = EP[:vREG_discharge] + vRSV_discharge = EP[:vRSV_discharge] + + eTotalCap = EP[:eTotalCap] + eTotalCapEnergy = EP[:eTotalCapEnergy] + + eff_up(y) = dfGen[y, :Eff_Up] + eff_down(y) = dfGen[y, :Eff_Down] + reg_max(y) = dfGen[y, :Reg_Max] + rsv_max(y) = dfGen[y, :Rsv_Max] + + # Maximum storage contribution to reserves is a specified fraction of installed capacity + @constraint(EP, [y in STOR_REG, t in 1:T], vREG[y, t] <= reg_max(y) * eTotalCap[y]) + @constraint(EP, [y in STOR_RSV, t in 1:T], vRSV[y, t] <= rsv_max(y) * eTotalCap[y]) + + # Actual contribution to regulation and reserves is sum of auxilary variables for portions contributed during charging and discharging + @constraint(EP, [y in STOR_REG, t in 1:T], vREG[y, t] == vREG_charge[y, t] + vREG_discharge[y, t]) + @constraint(EP, [y in STOR_RSV, t in 1:T], vRSV[y, t] == vRSV_charge[y, t] + vRSV_discharge[y, t]) + + # Maximum charging rate plus contribution to reserves up must be greater than zero + # Note: when charging, reducing charge rate is contributing to upwards reserve & regulation as it drops net demand + expr = extract_time_series_to_expression(vCHARGE, STOR_ALL) + add_similar_to_expression!(expr[STOR_REG, :], -vREG_charge[STOR_REG, :]) + add_similar_to_expression!(expr[STOR_RSV, :], -vRSV_charge[STOR_RSV, :]) + @constraint(EP, [y in STOR_ALL, t in 1:T], expr[y, t] >= 0) + + # Maximum discharging rate and contribution to reserves down must be greater than zero + # Note: when discharging, reducing discharge rate is contributing to downwards regulation as it drops net supply + @constraint(EP, [y in STOR_REG, t in 1:T], vP[y, t] - vREG_discharge[y, t] >= 0) + + # Maximum charging rate plus contribution to regulation down must be less than available storage capacity + @constraint(EP, [y in STOR_REG, t in 1:T], eff_up(y)*(vCHARGE[y, t]+vREG_charge[y, t]) <= eTotalCapEnergy[y]-vS[y, hoursbefore(p,t,1)]) + # Note: maximum charge rate is also constrained by maximum charge power capacity, but as this differs by storage type, + # this constraint is set in functions below for each storage type + + expr = extract_time_series_to_expression(vP, STOR_ALL) + add_similar_to_expression!(expr[STOR_REG, :], vREG_discharge[STOR_REG, :]) + add_similar_to_expression!(expr[STOR_RSV, :], vRSV_discharge[STOR_RSV, :]) + if CapacityReserveMargin + vCAPRES_discharge = EP[:vCAPRES_discharge] + add_similar_to_expression!(expr[STOR_ALL, :], vCAPRES_discharge[STOR_ALL, :]) + end + # Maximum discharging rate and contribution to reserves up must be less than power rating + @constraint(EP, [y in STOR_ALL, t in 1:T], expr[y, t] <= eTotalCap[y]) + # Maximum discharging rate and contribution to reserves up must be less than available stored energy in prior period + @constraint(EP, [y in STOR_ALL, t in 1:T], expr[y, t] <= vS[y, hoursbefore(p,t,1)] * eff_down(y)) end diff --git a/src/model/resources/storage/storage_asymmetric.jl b/src/model/resources/storage/storage_asymmetric.jl index 3f4a4e6c3a..93e74ad025 100644 --- a/src/model/resources/storage/storage_asymmetric.jl +++ b/src/model/resources/storage/storage_asymmetric.jl @@ -42,35 +42,21 @@ Sets up variables and constraints specific to storage resources with asymmetric """ function storage_asymmetric_reserves!(EP::Model, inputs::Dict, setup::Dict) - dfGen = inputs["dfGen"] T = inputs["T"] - CapacityReserveMargin = setup["CapacityReserveMargin"] + CapacityReserveMargin = setup["CapacityReserveMargin"] > 0 STOR_ASYMMETRIC = inputs["STOR_ASYMMETRIC"] - STOR_ASYM_REG = intersect(STOR_ASYMMETRIC, inputs["REG"]) # Set of asymmetric storage resources with REG reserves - STOR_ASYM_NO_REG = setdiff(STOR_ASYMMETRIC, STOR_ASYM_REG) # Set of asymmetric storage resources without REG reserves - - if !isempty(STOR_ASYM_REG) - if CapacityReserveMargin > 0 - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - # Maximum charging rate plus contribution to regulation down must be less than charge power rating - @constraint(EP, [y in STOR_ASYM_REG, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCapCharge][y]) - else - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - # Maximum charging rate plus contribution to regulation down must be less than charge power rating - @constraint(EP, [y in STOR_ASYM_REG, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]<= EP[:eTotalCapCharge][y]) - end - else - if CapacityReserveMargin > 0 - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - # Maximum charging rate plus contribution to regulation down must be less than charge power rating - @constraint(EP, [y in STOR_ASYM_NO_REG, t in 1:T], EP[:vCHARGE][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCapCharge][y]) - else - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - # Maximum charging rate plus contribution to regulation down must be less than charge power rating - @constraint(EP, [y in STOR_ASYM_NO_REG, t in 1:T], EP[:vCHARGE][y,t]<= EP[:eTotalCapCharge][y]) - end - end + vCHARGE = EP[:vCHARGE] + vREG_charge = EP[:vREG_charge] + eTotalCapCharge = EP[:eTotalCapCharge] + + expr = extract_time_series_to_expression(vCHARGE, STOR_ASYMMETRIC) + add_similar_to_expression!(expr[STOR_ASYM_REG, :], vREG_charge[STOR_ASYM_REG, :]) + if CapacityReserveMargin + vCAPRES_charge = EP[:vCAPRES_charge] + add_similar_to_expression!(expr[STOR_ASYMMETRIC, :], vCAPRES_charge[STOR_ASYMMETRIC, :]) + end + @constraint(EP, [y in STOR_ASYMMETRIC, t in 1:T], expr[y, t] <= eTotalCapCharge[y]) end diff --git a/src/model/resources/storage/storage_symmetric.jl b/src/model/resources/storage/storage_symmetric.jl index 446e9891f7..569ff59498 100644 --- a/src/model/resources/storage/storage_symmetric.jl +++ b/src/model/resources/storage/storage_symmetric.jl @@ -10,7 +10,6 @@ function storage_symmetric!(EP::Model, inputs::Dict, setup::Dict) println("Storage Resources with Symmetric Charge/Discharge Capacity Module") - dfGen = inputs["dfGen"] Reserves = setup["Reserves"] CapacityReserveMargin = setup["CapacityReserveMargin"] @@ -27,16 +26,12 @@ function storage_symmetric!(EP::Model, inputs::Dict, setup::Dict) if CapacityReserveMargin > 0 @constraints(EP, begin # Maximum charging rate (including virtual charging to move energy held in reserve back to available storage) must be less than symmetric power rating - [y in STOR_SYMMETRIC, t in 1:T], EP[:vCHARGE][y,t] + EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - # Max simultaneous charge and discharge cannot be greater than capacity [y in STOR_SYMMETRIC, t in 1:T], EP[:vP][y,t]+EP[:vCHARGE][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] end) else @constraints(EP, begin # Maximum charging rate (including virtual charging to move energy held in reserve back to available storage) must be less than symmetric power rating - [y in STOR_SYMMETRIC, t in 1:T], EP[:vCHARGE][y,t] <= EP[:eTotalCap][y] - # Max simultaneous charge and discharge cannot be greater than capacity [y in STOR_SYMMETRIC, t in 1:T], EP[:vP][y,t]+EP[:vCHARGE][y,t] <= EP[:eTotalCap][y] end) @@ -52,106 +47,33 @@ Sets up variables and constraints specific to storage resources with symmetric c """ function storage_symmetric_reserves!(EP::Model, inputs::Dict, setup::Dict) - dfGen = inputs["dfGen"] T = inputs["T"] - CapacityReserveMargin = setup["CapacityReserveMargin"] - - STOR_SYMMETRIC = inputs["STOR_SYMMETRIC"] - - STOR_SYM_REG_RSV = intersect(STOR_SYMMETRIC, inputs["REG"], inputs["RSV"]) # Set of symmetric storage resources with both REG and RSV reserves - - STOR_SYM_REG = intersect(STOR_SYMMETRIC, inputs["REG"]) # Set of symmetric storage resources with REG reserves - STOR_SYM_RSV = intersect(STOR_SYMMETRIC, inputs["RSV"]) # Set of symmetric storage resources with RSV reserves - - STOR_SYM_NO_RES = setdiff(STOR_SYMMETRIC, STOR_SYM_REG, STOR_SYM_RSV) # Set of symmetric storage resources with no reserves - - STOR_SYM_REG_ONLY = setdiff(STOR_SYM_REG, STOR_SYM_RSV) # Set of symmetric storage resources only with REG reserves - STOR_SYM_RSV_ONLY = setdiff(STOR_SYM_RSV, STOR_SYM_REG) # Set of symmetric storage resources only with RSV reserves - - if !isempty(STOR_SYM_REG_RSV) - if CapacityReserveMargin > 0 - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate plus contribution to regulation down must be less than symmetric power rating - [y in STOR_SYM_REG_RSV, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_REG_RSV, t in 1:T], EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t]+EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - end) - else - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate plus contribution to regulation down must be less than symmetric power rating - [y in STOR_SYM_REG_RSV, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]<= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_REG_RSV, t in 1:T], EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vRSV_discharge][y,t]+EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]<= EP[:eTotalCap][y] - end) - end - end - - if !isempty(STOR_SYM_REG_ONLY) - if CapacityReserveMargin > 0 - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate plus contribution to regulation down must be less than symmetric power rating - [y in STOR_SYM_REG_ONLY, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_REG_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - end) - else - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate plus contribution to regulation down must be less than symmetric power rating - [y in STOR_SYM_REG_ONLY, t in 1:T], EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]<= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_REG_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vREG_discharge][y,t]+EP[:vCHARGE][y,t]+EP[:vREG_charge][y,t]<= EP[:eTotalCap][y] - end) - end - end - - if !isempty(STOR_SYM_RSV_ONLY) - if CapacityReserveMargin > 0 - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate must be less than symmetric power rating - [y in STOR_SYM_RSV_ONLY, t in 1:T], EP[:vCHARGE][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_RSV_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vRSV_discharge][y,t]+EP[:vCHARGE][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - end) - else - # Storage units charging can charge faster to provide reserves down and charge slower to provide reserves up - @constraints(EP, begin - # Maximum charging rate must be less than symmetric power rating - [y in STOR_SYM_RSV_ONLY, t in 1:T], EP[:vCHARGE][y,t]<= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity - [y in STOR_SYM_RSV_ONLY, t in 1:T], EP[:vP][y,t]+EP[:vRSV_discharge][y,t]+EP[:vCHARGE][y,t]<= EP[:eTotalCap][y] - end) - end - end - - if !isempty(STOR_SYM_NO_RES) - if CapacityReserveMargin > 0 - @constraints(EP, begin - # Maximum charging rate must be less than symmetric power rating - [y in STOR_SYM_NO_RES, t in 1:T], EP[:vCHARGE][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge cannot be greater than capacity - [y in STOR_SYM_NO_RES, t in 1:T], EP[:vP][y,t]+EP[:vCHARGE][y,t]+EP[:vCAPRES_discharge][y,t]+EP[:vCAPRES_charge][y,t] <= EP[:eTotalCap][y] - end) - else - @constraints(EP, begin - # Maximum charging rate must be less than symmetric power rating - [y in STOR_SYM_NO_RES, t in 1:T], EP[:vCHARGE][y,t]<= EP[:eTotalCap][y] - - # Max simultaneous charge and discharge cannot be greater than capacity - [y in STOR_SYM_NO_RES, t in 1:T], EP[:vP][y,t]+EP[:vCHARGE][y,t]<= EP[:eTotalCap][y] - end) - end - end - -end \ No newline at end of file + CapacityReserveMargin = setup["CapacityReserveMargin"] > 0 + + SYMMETRIC = inputs["STOR_SYMMETRIC"] + + REG = intersect(SYMMETRIC, inputs["REG"]) + RSV = intersect(SYMMETRIC, inputs["RSV"]) + + vP = EP[:vP] + vCHARGE = EP[:vCHARGE] + vREG_charge = EP[:vREG_charge] + vRSV_charge = EP[:vRSV_charge] + vREG_discharge = EP[:vREG_discharge] + vRSV_discharge = EP[:vRSV_discharge] + eTotalCap = EP[:eTotalCap] + + # Maximum charging rate plus contribution to regulation down must be less than symmetric power rating + # Max simultaneous charge and discharge rates cannot be greater than symmetric charge/discharge capacity + expr = @expression(EP, [y in SYMMETRIC, t in 1:T], vP[y, t] + vCHARGE[y, t]) + add_similar_to_expression!(expr[REG, :], vREG_charge[REG, :]) + add_similar_to_expression!(expr[REG, :], vREG_discharge[REG, :]) + add_similar_to_expression!(expr[RSV, :], vRSV_discharge[RSV, :]) + if CapacityReserveMargin + vCAPRES_charge = EP[:vCAPRES_charge] + vCAPRES_discharge = EP[:vCAPRES_discharge] + add_similar_to_expression!(expr[SYMMETRIC, :], vCAPRES_charge[SYMMETRIC, :]) + add_similar_to_expression!(expr[SYMMETRIC, :], vCAPRES_discharge[SYMMETRIC, :]) + end + @constraint(EP, [y in SYMMETRIC, t in 1:T], expr[y, t] <= eTotalCap[y]) +end diff --git a/src/model/resources/thermal/thermal_commit.jl b/src/model/resources/thermal/thermal_commit.jl index dce4c29aa2..b654f098ca 100644 --- a/src/model/resources/thermal/thermal_commit.jl +++ b/src/model/resources/thermal/thermal_commit.jl @@ -264,7 +264,6 @@ When modeling frequency regulation and spinning reserves contributions, thermal \end{aligned} ``` -Note there are multiple versions of these constraints in the code in order to avoid creation of unecessary constraints and decision variables for thermal units unable to provide regulation and/or reserves contributions due to input parameters (e.g. ```Reg_Max=0``` and/or ```RSV_Max=0```). """ function thermal_commit_reserves!(EP::Model, inputs::Dict) @@ -276,66 +275,33 @@ function thermal_commit_reserves!(EP::Model, inputs::Dict) THERM_COMMIT = inputs["THERM_COMMIT"] - THERM_COMMIT_REG_RSV = intersect(THERM_COMMIT, inputs["REG"], inputs["RSV"]) # Set of thermal resources with both regulation and spinning reserves - - THERM_COMMIT_REG = intersect(THERM_COMMIT, inputs["REG"]) # Set of thermal resources with regulation reserves - THERM_COMMIT_RSV = intersect(THERM_COMMIT, inputs["RSV"]) # Set of thermal resources with spinning reserves - - THERM_COMMIT_NO_RES = setdiff(THERM_COMMIT, THERM_COMMIT_REG, THERM_COMMIT_RSV) # Set of thermal resources with no reserves - - THERM_COMMIT_REG_ONLY = setdiff(THERM_COMMIT_REG, THERM_COMMIT_RSV) # Set of thermal resources only with regulation reserves - THERM_COMMIT_RSV_ONLY = setdiff(THERM_COMMIT_RSV, THERM_COMMIT_REG) # Set of thermal resources only with spinning reserves - - if !isempty(THERM_COMMIT_REG_RSV) - @constraints(EP, begin - # Maximum regulation and reserve contributions - [y in THERM_COMMIT_REG_RSV, t=1:T], EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Reg_Max]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - [y in THERM_COMMIT_REG_RSV, t=1:T], EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Rsv_Max]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation must be > min power - [y in THERM_COMMIT_REG_RSV, t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= dfGen[y,:Min_Power]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves up must be < max power - [y in THERM_COMMIT_REG_RSV, t=1:T], EP[:vP][y,t]+EP[:vREG][y,t]+EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - end) - end - - if !isempty(THERM_COMMIT_REG) - @constraints(EP, begin - # Maximum regulation and reserve contributions - [y in THERM_COMMIT_REG, t=1:T], EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Reg_Max]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation must be > min power - [y in THERM_COMMIT_REG, t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= dfGen[y,:Min_Power]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Maximum power generated per technology "y" at hour "t" and contribution to regulation must be < max power - [y in THERM_COMMIT_REG, t=1:T], EP[:vP][y,t]+EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - end) - end - - if !isempty(THERM_COMMIT_RSV) - @constraints(EP, begin - # Maximum regulation and reserve contributions - [y in THERM_COMMIT_RSV, t=1:T], EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Rsv_Max]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Minimum stable power generated per technology "y" at hour "t" must be > min power - [y in THERM_COMMIT_RSV, t=1:T], EP[:vP][y,t] >= dfGen[y,:Min_Power]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Maximum power generated per technology "y" at hour "t" and contribution to reserves up must be < max power - [y in THERM_COMMIT_RSV, t=1:T], EP[:vP][y,t]+EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - end) - end - - if !isempty(THERM_COMMIT_NO_RES) - @constraints(EP, begin - # Minimum stable power generated per technology "y" at hour "t" > Min power - [y in THERM_COMMIT_NO_RES, t=1:T], EP[:vP][y,t] >= dfGen[y,:Min_Power]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - - # Maximum power generated per technology "y" at hour "t" < Max power - [y in THERM_COMMIT_NO_RES, t=1:T], EP[:vP][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Cap_Size]*EP[:vCOMMIT][y,t] - end) - end - + REG = intersect(THERM_COMMIT, inputs["REG"]) # Set of thermal resources with regulation reserves + RSV = intersect(THERM_COMMIT, inputs["RSV"]) # Set of thermal resources with spinning reserves + + vP = EP[:vP] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + + commit(y,t) = dfGen[y, :Cap_Size] * EP[:vCOMMIT][y,t] + min_power(y) = dfGen[y, :Min_Power] + max_power(y,t) = inputs["pP_Max"][y,t] + reg_max(y) = dfGen[y, :Reg_Max] + rsv_max(y) = dfGen[y, :Rsv_Max] + + # Maximum regulation and reserve contributions + @constraint(EP, [y in REG, t in 1:T], vREG[y, t] <= max_power(y, t) * reg_max(y) * commit(y, t)) + @constraint(EP, [y in RSV, t in 1:T], vRSV[y, t] <= max_power(y, t) * rsv_max(y) * commit(y, t)) + + # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation must be > min power + expr = extract_time_series_to_expression(vP, THERM_COMMIT) + add_similar_to_expression!(expr[REG, :], -vREG[REG, :]) + @constraint(EP, [y in THERM_COMMIT, t in 1:T], expr[y, t] >= min_power(y) * commit(y, t)) + + # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves up must be < max power + expr = extract_time_series_to_expression(vP, THERM_COMMIT) + add_similar_to_expression!(expr[REG, :], vREG[REG, :]) + add_similar_to_expression!(expr[RSV, :], vRSV[RSV, :]) + @constraint(EP, [y in THERM_COMMIT, t in 1:T], expr[y, t] <= max_power(y, t) * commit(y, t)) end @doc raw""" @@ -395,11 +361,20 @@ function thermal_maintenance_capacity_reserve_margin_adjustment!(EP::Model, MAINT = resources_with_maintenance(dfGen) applicable_resources = intersect(MAINT, THERM_COMMIT) - resource_component(y) = dfGen[y, :Resource] - capresfactor(y, capres) = dfGen[y, Symbol("CapRes_$capres")] - cap_size(y) = dfGen[y, :Cap_Size] - down_var(y) = EP[Symbol(maintenance_down_name(resource_component(y)))] maint_adj = @expression(EP, [capres in 1:ncapres, t in 1:T], - -sum(capresfactor(y, capres) * down_var(y)[t] * cap_size(y) for y in applicable_resources)) + sum(thermal_maintenance_capacity_reserve_margin_adjustment(EP, inputs, y, capres, t) for y in applicable_resources)) add_similar_to_expression!(EP[:eCapResMarBalance], maint_adj) end + +function thermal_maintenance_capacity_reserve_margin_adjustment(EP::Model, + inputs::Dict, + y::Int, + capres::Int, + t) + dfGen = inputs["dfGen"] + resource_component = dfGen[y, :Resource] + capresfactor = dfGen[y, Symbol("CapRes_$capres")] + cap_size = dfGen[y, :Cap_Size] + down_var = EP[Symbol(maintenance_down_name(resource_component))] + return -capresfactor * down_var[t] * cap_size +end diff --git a/src/model/resources/thermal/thermal_no_commit.jl b/src/model/resources/thermal/thermal_no_commit.jl index 480e6e2380..91fc176dd7 100644 --- a/src/model/resources/thermal/thermal_no_commit.jl +++ b/src/model/resources/thermal/thermal_no_commit.jl @@ -140,72 +140,35 @@ function thermal_no_commit_reserves!(EP::Model, inputs::Dict) dfGen = inputs["dfGen"] - T = inputs["T"] # Number of time steps (hours) - - THERM_NO_COMMIT = setdiff(inputs["THERM_ALL"], inputs["COMMIT"]) - - # Constraints on contribution to regulation and reserves - # Thermal units without commitment constraints assumed to be quick-start units, so can contribute a specified fraction of their - # total installed capacity to reserves - - THERM_NO_COMMIT_REG_RSV = intersect(THERM_NO_COMMIT, inputs["REG"], inputs["RSV"]) # Set of thermal resources with both regulation and spinning reserves + T = inputs["T"] # Number of time steps (hours) - THERM_NO_COMMIT_REG = intersect(THERM_NO_COMMIT, inputs["REG"]) # Set of thermal resources with regulation reserves - THERM_NO_COMMIT_RSV = intersect(THERM_NO_COMMIT, inputs["RSV"]) # Set of thermal resources with spinning reserves + THERM_NO_COMMIT = setdiff(inputs["THERM_ALL"], inputs["COMMIT"]) - THERM_NO_COMMIT_NO_RES = setdiff(THERM_NO_COMMIT, THERM_NO_COMMIT_REG, THERM_NO_COMMIT_RSV) # Set of thermal resources with no reserves + REG = intersect(THERM_NO_COMMIT, inputs["REG"]) # Set of thermal resources with regulation reserves + RSV = intersect(THERM_NO_COMMIT, inputs["RSV"]) # Set of thermal resources with spinning reserves - THERM_NO_COMMIT_REG_ONLY = setdiff(THERM_NO_COMMIT_REG, THERM_NO_COMMIT_RSV) # Set of thermal resources only with regulation reserves - THERM_NO_COMMIT_RSV_ONLY = setdiff(THERM_NO_COMMIT_RSV, THERM_NO_COMMIT_REG) # Set of thermal resources only with spinning reserves + vP = EP[:vP] + vREG = EP[:vREG] + vRSV = EP[:vRSV] + eTotalCap = EP[:eTotalCap] - if !isempty(THERM_NO_COMMIT_REG_RSV) - @constraints(EP, begin - - [y in THERM_NO_COMMIT_REG_RSV, t=1:T], EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - [y in THERM_NO_COMMIT_REG_RSV, t=1:T], EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] + min_power(y) = dfGen[y, :Min_Power] + max_power(y,t) = inputs["pP_Max"][y,t] + reg_max(y) = dfGen[y, :Reg_Max] + rsv_max(y) = dfGen[y, :Rsv_Max] - # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation down must be > min power - [y in THERM_NO_COMMIT_REG_RSV, t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] + # Maximum regulation and reserve contributions + @constraint(EP, [y in REG, t in 1:T], vREG[y, t] <= max_power(y, t) * reg_max(y) * eTotalCap[y]) + @constraint(EP, [y in RSV, t in 1:T], vRSV[y, t] <= max_power(y, t) * rsv_max(y) * eTotalCap[y]) - # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves must be < max power - [y in THERM_NO_COMMIT_REG_RSV, t=1:T], EP[:vP][y,t]+EP[:vREG][y,t]+EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] - end) - end - - if !isempty(THERM_NO_COMMIT_REG) - @constraints(EP, begin - - [y in THERM_NO_COMMIT_REG, t=1:T], EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Reg_Max]*EP[:eTotalCap][y] - - # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation down must be > min power - [y in THERM_NO_COMMIT_REG, t=1:T], EP[:vP][y,t]-EP[:vREG][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] - - # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves must be < max power - [y in THERM_NO_COMMIT_REG, t=1:T], EP[:vP][y,t]+EP[:vREG][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] - end) - end - - if !isempty(THERM_NO_COMMIT_RSV) - @constraints(EP, begin - - [y in THERM_NO_COMMIT_RSV, t=1:T], EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*dfGen[y,:Rsv_Max]*EP[:eTotalCap][y] - - # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation down must be > min power - [y in THERM_NO_COMMIT_RSV, t=1:T], EP[:vP][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] - - # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves must be < max power - [y in THERM_NO_COMMIT_RSV, t=1:T], EP[:vP][y,t]+EP[:vRSV][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] - end) - end - - if !isempty(THERM_NO_COMMIT_NO_RES) - @constraints(EP, begin - # Minimum stable power generated per technology "y" at hour "t" Min_Power - [y in THERM_NO_COMMIT_NO_RES, t=1:T], EP[:vP][y,t] >= dfGen[y,:Min_Power]*EP[:eTotalCap][y] - - # Maximum power generated per technology "y" at hour "t" - [y in THERM_NO_COMMIT_NO_RES, t=1:T], EP[:vP][y,t] <= inputs["pP_Max"][y,t]*EP[:eTotalCap][y] - end) - end + # Minimum stable power generated per technology "y" at hour "t" and contribution to regulation must be > min power + expr = extract_time_series_to_expression(vP, THERM_NO_COMMIT) + add_similar_to_expression!(expr[REG, :], -vREG[REG, :]) + @constraint(EP, [y in THERM_NO_COMMIT, t in 1:T], expr[y, t] >= min_power(y) * eTotalCap[y]) + # Maximum power generated per technology "y" at hour "t" and contribution to regulation and reserves up must be < max power + expr = extract_time_series_to_expression(vP, THERM_NO_COMMIT) + add_similar_to_expression!(expr[REG, :], vREG[REG, :]) + add_similar_to_expression!(expr[RSV, :], vRSV[RSV, :]) + @constraint(EP, [y in THERM_NO_COMMIT, t in 1:T], expr[y, t] <= max_power(y, t) * eTotalCap[y]) end diff --git a/src/multi_stage/dual_dynamic_programming.jl b/src/multi_stage/dual_dynamic_programming.jl index 1b5aa3e489..92f9791eb3 100644 --- a/src/multi_stage/dual_dynamic_programming.jl +++ b/src/multi_stage/dual_dynamic_programming.jl @@ -356,13 +356,13 @@ returns: JuMP model with updated linking constraints. """ function fix_initial_investments(EP_prev::Model, EP_cur::Model, start_cap_d::Dict, inputs_d::Dict) - RET_CAP = inputs_d["RET_CAP"] # Set of all resources subject to inter-stage capacity tracking - + ALL_CAP = union(inputs_d["RET_CAP"],inputs_d["NEW_CAP"]) # Set of all resources subject to inter-stage capacity tracking + # start_cap_d dictionary contains the starting capacity expression name (e) as a key, # and the associated linking constraint name (c) as a value for (e, c) in start_cap_d for y in keys(EP_cur[c]) - if y[1] in RET_CAP # extract resource integer index value from key + if y[1] in ALL_CAP # extract resource integer index value from key # Set the right hand side value of the linking initial capacity constraint in the current # stage to the value of the available capacity variable solved for in the previous stages set_normalized_rhs(EP_cur[c][y], value(EP_prev[e][y])) diff --git a/src/multi_stage/endogenous_retirement.jl b/src/multi_stage/endogenous_retirement.jl index fa165a9df1..3371476c17 100644 --- a/src/multi_stage/endogenous_retirement.jl +++ b/src/multi_stage/endogenous_retirement.jl @@ -124,8 +124,6 @@ function endogenous_retirement_discharge!(EP::Model, inputs::Dict, num_stages::I dfGen = inputs["dfGen"] - G = inputs["G"] # Number of resources (generators, storage, DR, and DERs) - NEW_CAP = inputs["NEW_CAP"] # Set of all resources eligible for new capacity RET_CAP = inputs["RET_CAP"] # Set of all resources eligible for capacity retirements COMMIT = inputs["COMMIT"] # Set of all resources eligible for unit commitment @@ -181,8 +179,6 @@ function endogenous_retirement_charge!(EP::Model, inputs::Dict, num_stages::Int, dfGen = inputs["dfGen"] - STOR_ASYMMETRIC = inputs["STOR_ASYMMETRIC"] # Set of storage resources with asymmetric (separte) charge/discharge capacity components - NEW_CAP_CHARGE = inputs["NEW_CAP_CHARGE"] # Set of asymmetric charge/discharge storage resources eligible for new charge capacity RET_CAP_CHARGE = inputs["RET_CAP_CHARGE"] # Set of asymmetric charge/discharge storage resources eligible for charge capacity retirements @@ -231,7 +227,6 @@ function endogenous_retirement_energy!(EP::Model, inputs::Dict, num_stages::Int, dfGen = inputs["dfGen"] - STOR_ALL = inputs["STOR_ALL"] # Set of all storage resources NEW_CAP_ENERGY = inputs["NEW_CAP_ENERGY"] # Set of all storage resources eligible for new energy capacity RET_CAP_ENERGY = inputs["RET_CAP_ENERGY"] # Set of all storage resources eligible for energy capacity retirements diff --git a/src/write_outputs/capacity_reserve_margin/effective_capacity.jl b/src/write_outputs/capacity_reserve_margin/effective_capacity.jl new file mode 100644 index 0000000000..5d6d47246c --- /dev/null +++ b/src/write_outputs/capacity_reserve_margin/effective_capacity.jl @@ -0,0 +1,54 @@ +@doc raw""" + thermal_plant_effective_capacity(EP::Model, + inputs::Dict, + resources::Vector{Int}, + capres_zone::Int, + timesteps::Vector{Int})::Matrix{Float64} + + Effective capacity in a capacity reserve margin zone for certain resources in the given timesteps. +""" +function thermal_plant_effective_capacity( + EP, + inputs, + resources::Vector{Int}, + capres_zone::Int, + timesteps::Vector{Int}, +)::Matrix{Float64} + eff_cap = + thermal_plant_effective_capacity.( + Ref(EP), + Ref(inputs), + resources, + Ref(capres_zone), + Ref(timesteps), + ) + return reduce(hcat, eff_cap) +end + +function thermal_plant_effective_capacity(EP::Model, inputs::Dict, y, capres_zone::Int) + T = inputs["T"] + timesteps = collect(1:T) + return thermal_plant_effective_capacity(EP, inputs, y, capres_zone, timesteps) +end + +function thermal_plant_effective_capacity( + EP::Model, + inputs::Dict, + r_id::Int, + capres_zone::Int, + timesteps::Vector{Int}, +)::Vector{Float64} + y = r_id + dfGen = inputs["dfGen"] + capresfactor = dfGen[y, Symbol("CapRes_$capres_zone")] + eTotalCap = value.(EP[:eTotalCap][y]) + + effective_capacity = fill(capresfactor * eTotalCap, length(timesteps)) + + if has_maintenance(inputs) && y in resources_with_maintenance(dfGen) + adjustment = thermal_maintenance_capacity_reserve_margin_adjustment(EP, inputs, y, capres_zone, timesteps) + effective_capacity = effective_capacity .+ value.(adjustment) + end + + return effective_capacity +end diff --git a/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl b/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl index ec1968ca4b..cbefad6c83 100644 --- a/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl +++ b/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl @@ -2,8 +2,6 @@ function write_capacity_value(path::AbstractString, inputs::Dict, setup::Dict, E dfGen = inputs["dfGen"] G = inputs["G"] # Number of resources (generators, storage, DR, and DERs) T = inputs["T"] # Number of time steps (hours) - SEG = inputs["SEG"] # Number of lines - L = inputs["L"] # Number of lines THERM_ALL = inputs["THERM_ALL"] VRE = inputs["VRE"] HYDRO_RES = inputs["HYDRO_RES"] @@ -11,19 +9,21 @@ function write_capacity_value(path::AbstractString, inputs::Dict, setup::Dict, E FLEX = inputs["FLEX"] MUST_RUN = inputs["MUST_RUN"] VRE_STOR = inputs["VRE_STOR"] - if setup["ParameterScale"] == 1 - existingplant_position = findall(x -> x >= 1, (value.(EP[:eTotalCap])) * ModelScalingFactor) - else - existingplant_position = findall(x -> x >= 1, (value.(EP[:eTotalCap]))) - end - THERM_ALL_EX = intersect(THERM_ALL, existingplant_position) - VRE_EX = intersect(VRE, existingplant_position) - HYDRO_RES_EX = intersect(HYDRO_RES, existingplant_position) - STOR_ALL_EX = intersect(STOR_ALL, existingplant_position) - FLEX_EX = intersect(FLEX, existingplant_position) - MUST_RUN_EX = intersect(MUST_RUN, existingplant_position) + + scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 + eTotalCap = value.(EP[:eTotalCap]) + + minimum_plant_size = 1 # MW + large_plants = findall(>=(minimum_plant_size), eTotalCap * scale_factor) + + THERM_ALL_EX = intersect(THERM_ALL, large_plants) + VRE_EX = intersect(VRE, large_plants) + HYDRO_RES_EX = intersect(HYDRO_RES, large_plants) + STOR_ALL_EX = intersect(STOR_ALL, large_plants) + FLEX_EX = intersect(FLEX, large_plants) + MUST_RUN_EX = intersect(MUST_RUN, large_plants) # Will only be activated if grid connection capacity exists (because may build standalone storage/VRE, which will only be telling by grid connection capacity) - VRE_STOR_EX = intersect(VRE_STOR, existingplant_position) + VRE_STOR_EX = intersect(VRE_STOR, large_plants) if !isempty(VRE_STOR_EX) DC_DISCHARGE = inputs["VS_STOR_DC_DISCHARGE"] DC_CHARGE = inputs["VS_STOR_DC_CHARGE"] @@ -34,48 +34,91 @@ function write_capacity_value(path::AbstractString, inputs::Dict, setup::Dict, E AC_CHARGE_EX = intersect(inputs["VS_STOR_AC_CHARGE"], VRE_STOR_EX) dfVRE_STOR = inputs["dfVRE_STOR"] end - - totalcap = repeat((value.(EP[:eTotalCap])), 1, T) + + crm_derate(i, y::Vector{Int}) = dfGen[y, Symbol("CapRes_$i")]' + max_power(t::Vector{Int}, y::Vector{Int}) = inputs["pP_Max"][y, t]' + total_cap(y::Vector{Int}) = eTotalCap[y]' + dfCapValue = DataFrame() for i in 1:inputs["NCapacityReserveMargin"] - temp_dfCapValue = DataFrame(Resource = inputs["RESOURCES"], Zone = dfGen[!, :Zone], Reserve = fill(Symbol("CapRes_$i"), G)) - temp_capvalue = zeros(G, T) - temp_riskyhour = zeros(G, T) - temp_cap_derate = zeros(G, T) - if setup["ParameterScale"] == 1 - riskyhour_position = findall(x -> x >= 1, ((dual.(EP[:cCapacityResMargin][i, :])) ./ inputs["omega"] * ModelScalingFactor)) - else - riskyhour_position = findall(x -> x >= 1, ((dual.(EP[:cCapacityResMargin][i, :])) ./ inputs["omega"])) - end - temp_riskyhour[:, riskyhour_position] = ones(Int, G, length(riskyhour_position)) - temp_cap_derate[existingplant_position, :] = repeat(dfGen[existingplant_position, Symbol("CapRes_$i")], 1, T) + capvalue = zeros(T, G) + + minimum_crm_price = 1 # $/MW + riskyhour = findall(>=(minimum_crm_price), capacity_reserve_margin_price(EP, inputs, setup, i)) + + power(y::Vector{Int}) = value.(EP[:vP][y, riskyhour])' + + capvalue[riskyhour, THERM_ALL_EX] = thermal_plant_effective_capacity(EP, inputs, THERM_ALL_EX, i, riskyhour) ./ total_cap(THERM_ALL_EX) + + capvalue[riskyhour, VRE_EX] = crm_derate(i, VRE_EX) .* max_power(riskyhour, VRE_EX) + + capvalue[riskyhour, MUST_RUN_EX] = crm_derate(i, MUST_RUN_EX) .* max_power(riskyhour, MUST_RUN_EX) + + capvalue[riskyhour, HYDRO_RES_EX] = crm_derate(i, HYDRO_RES_EX) .* power(HYDRO_RES_EX) ./ total_cap(HYDRO_RES_EX) - temp_capvalue[THERM_ALL_EX, :] = temp_cap_derate[THERM_ALL_EX, :] .* temp_riskyhour[THERM_ALL_EX, :] - temp_capvalue[VRE_EX, :] = temp_cap_derate[VRE_EX, :] .* (inputs["pP_Max"][VRE_EX, :]) .* temp_riskyhour[VRE_EX, :] - temp_capvalue[MUST_RUN_EX, :] = temp_cap_derate[MUST_RUN_EX, :] .* (inputs["pP_Max"][MUST_RUN_EX, :]) .* temp_riskyhour[MUST_RUN_EX, :] - temp_capvalue[HYDRO_RES_EX, :] = temp_cap_derate[HYDRO_RES_EX, :] .* (value.(EP[:vP][HYDRO_RES_EX, :])) .* temp_riskyhour[HYDRO_RES_EX, :] ./ totalcap[HYDRO_RES_EX, :] if !isempty(STOR_ALL_EX) - temp_capvalue[STOR_ALL_EX, :] = temp_cap_derate[STOR_ALL_EX, :] .* ((value.(EP[:vP][STOR_ALL_EX, :]) - value.(EP[:vCHARGE][STOR_ALL_EX, :]).data + value.(EP[:vCAPRES_discharge][STOR_ALL_EX, :]).data - value.(EP[:vCAPRES_charge][STOR_ALL_EX, :]).data)) .* temp_riskyhour[STOR_ALL_EX, :] ./ totalcap[STOR_ALL_EX, :] + charge = value.(EP[:vCHARGE][STOR_ALL_EX, riskyhour].data)' + capres_discharge = value.(EP[:vCAPRES_discharge][STOR_ALL_EX, riskyhour].data)' + capres_charge = value.(EP[:vCAPRES_charge][STOR_ALL_EX, riskyhour].data)' + + capvalue[riskyhour, STOR_ALL_EX] = crm_derate(i, STOR_ALL_EX) .* (power(STOR_ALL_EX) - charge + capres_discharge - capres_charge) ./ total_cap(STOR_ALL_EX) end + if !isempty(FLEX_EX) - temp_capvalue[FLEX_EX, :] = temp_cap_derate[FLEX_EX, :] .* ((value.(EP[:vCHARGE_FLEX][FLEX_EX, :]).data - value.(EP[:vP][FLEX_EX, :]))) .* temp_riskyhour[FLEX_EX, :] ./ totalcap[FLEX_EX, :] + charge = value.(EP[:vCHARGE_FLEX][FLEX_EX, riskyhour].data)' + capvalue[riskyhour, FLEX_EX] = crm_derate(i, FLEX_EX) .* (charge - power(FLEX_EX)) ./ total_cap(FLEX_EX) end if !isempty(VRE_STOR_EX) - temp_capvalue_dc_discharge = zeros(G, T) - temp_capvalue_dc_discharge[DC_DISCHARGE, :] = value.(EP[:vCAPRES_DC_DISCHARGE][DC_DISCHARGE, :].data) .* dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0), :EtaInverter] - temp_capvalue_dc_charge = zeros(G, T) - temp_capvalue_dc_charge[DC_CHARGE, :] = value.(EP[:vCAPRES_DC_CHARGE][DC_CHARGE, :].data) ./ dfVRE_STOR[(dfVRE_STOR.STOR_DC_CHARGE.!=0), :EtaInverter] - temp_capvalue[VRE_STOR_EX, :] = temp_cap_derate[VRE_STOR_EX, :] .* (value.(EP[:vP][VRE_STOR_EX, :])) .* temp_riskyhour[VRE_STOR_EX, :] ./ totalcap[VRE_STOR_EX, :] - temp_capvalue[VRE_STOR_STOR_EX, :] .-= temp_cap_derate[VRE_STOR_STOR_EX, :] .* (value.(EP[:vCHARGE_VRE_STOR][VRE_STOR_STOR_EX, :].data)) .* temp_riskyhour[VRE_STOR_STOR_EX, :] ./ totalcap[VRE_STOR_STOR_EX, :] - temp_capvalue[DC_DISCHARGE_EX, :] .+= temp_cap_derate[DC_DISCHARGE_EX, :] .* temp_capvalue_dc_discharge[DC_DISCHARGE_EX, :] .* temp_riskyhour[DC_DISCHARGE_EX, :] ./ totalcap[DC_DISCHARGE_EX, :] - temp_capvalue[AC_DISCHARGE_EX, :] .+= temp_cap_derate[AC_DISCHARGE_EX, :] .* (value.(EP[:vCAPRES_AC_DISCHARGE][AC_DISCHARGE_EX, :]).data) .* temp_riskyhour[AC_DISCHARGE_EX, :] ./ totalcap[AC_DISCHARGE_EX, :] - temp_capvalue[DC_CHARGE_EX, :] .-= temp_cap_derate[DC_CHARGE_EX, :] .* temp_capvalue_dc_charge[DC_CHARGE_EX, :] .* temp_riskyhour[DC_CHARGE_EX, :] ./ totalcap[DC_CHARGE_EX, :] - temp_capvalue[AC_CHARGE_EX, :] .-= temp_cap_derate[AC_CHARGE_EX, :] .* (value.(EP[:vCAPRES_AC_CHARGE][AC_CHARGE_EX, :]).data) .* temp_riskyhour[AC_CHARGE_EX, :] ./ totalcap[AC_CHARGE_EX, :] + capres_dc_discharge = value.(EP[:vCAPRES_DC_DISCHARGE][DC_DISCHARGE, riskyhour].data)' + discharge_eff = dfVRE_STOR[dfVRE_STOR.STOR_DC_DISCHARGE .!= 0, :EtaInverter]' + capvalue_dc_discharge = zeros(T, G) + capvalue_dc_discharge[riskyhour, DC_DISCHARGE] = capres_dc_discharge .* discharge_eff + + capres_dc_charge = value.(EP[:vCAPRES_DC_CHARGE][DC_CHARGE, riskyhour].data)' + charge_eff = dfVRE_STOR[dfVRE_STOR.STOR_DC_CHARGE .!= 0, :EtaInverter]' + capvalue_dc_charge = zeros(T, G) + capvalue_dc_charge[riskyhour, DC_CHARGE] = capres_dc_charge ./ charge_eff + + capvalue[riskyhour, VRE_STOR_EX] = crm_derate(i, VRE_STOR_EX) .* power(VRE_STOR_EX) ./ total_cap(VRE_STOR_EX) + + charge_vre_stor = value.(EP[:vCHARGE_VRE_STOR][VRE_STOR_STOR_EX, riskyhour].data)' + capvalue[riskyhour, VRE_STOR_STOR_EX] -= crm_derate(i, VRE_STOR_STOR_EX) .* charge_vre_stor ./ total_cap(VRE_STOR_STOR_EX) + + capvalue[riskyhour, DC_DISCHARGE_EX] += crm_derate(i, DC_DISCHARGE_EX) .* capvalue_dc_discharge[riskyhour, DC_DISCHARGE_EX] ./ total_cap(DC_DISCHARGE_EX) + capres_ac_discharge = value.(EP[:vCAPRES_AC_DISCHARGE][AC_DISCHARGE_EX, riskyhour].data)' + capvalue[riskyhour, AC_DISCHARGE_EX] += crm_derate(i, AC_DISCHARGE_EX) .* capres_ac_discharge ./ total_cap(AC_DISCHARGE_EX) + + capvalue[riskyhour, DC_CHARGE_EX] -= crm_derate(i, DC_CHARGE_EX) .* capvalue_dc_charge[riskyhour, DC_CHARGE_EX] ./ total_cap(DC_CHARGE_EX) + capres_ac_charge = value.(EP[:vCAPRES_AC_CHARGE][AC_CHARGE_EX, riskyhour].data)' + capvalue[riskyhour, AC_CHARGE_EX] -= crm_derate(i, AC_CHARGE_EX) .* capres_ac_charge ./ total_cap(AC_CHARGE_EX) end - temp_dfCapValue = hcat(temp_dfCapValue, DataFrame(temp_capvalue, :auto)) + capvalue = collect(transpose(capvalue)) + temp_dfCapValue = DataFrame(Resource = inputs["RESOURCES"], Zone = dfGen.Zone, Reserve = fill(Symbol("CapRes_$i"), G)) + temp_dfCapValue = hcat(temp_dfCapValue, DataFrame(capvalue, :auto)) auxNew_Names = [Symbol("Resource"); Symbol("Zone"); Symbol("Reserve"); [Symbol("t$t") for t in 1:T]] rename!(temp_dfCapValue, auxNew_Names) append!(dfCapValue, temp_dfCapValue) end - CSV.write(joinpath(path, "CapacityValue.csv"), dfCapValue) + write_simple_csv(joinpath(path, "CapacityValue.csv"), dfCapValue) +end + +@doc raw""" + capacity_reserve_margin_price(EP::Model, + inputs::Dict, + setup::Dict, + capres_zone::Int)::Vector{Float64} + +Marginal electricity price for each model zone and time step. +This is equal to the dual variable of the power balance constraint. +When solving a linear program (i.e. linearized unit commitment or economic dispatch) +this output is always available; when solving a mixed integer linear program, this can +be calculated only if `WriteShadowPrices` is activated. + + Returns a vector, with units of $/MW +""" +function capacity_reserve_margin_price(EP::Model, inputs::Dict, setup::Dict, capres_zone::Int)::Vector{Float64} + ω = inputs["omega"] + scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 + return dual.(EP[:cCapacityResMargin][capres_zone, :]) ./ ω * scale_factor end + diff --git a/src/write_outputs/capacity_reserve_margin/write_reserve_margin_revenue.jl b/src/write_outputs/capacity_reserve_margin/write_reserve_margin_revenue.jl index e2bfc70153..0311dc0143 100644 --- a/src/write_outputs/capacity_reserve_margin/write_reserve_margin_revenue.jl +++ b/src/write_outputs/capacity_reserve_margin/write_reserve_margin_revenue.jl @@ -9,6 +9,7 @@ Function for reporting the capacity revenue earned by each generator listed in t As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint. """ function write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model) + scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 dfGen = inputs["dfGen"] G = inputs["G"] # Number of resources (generators, storage, DR, and DERs) T = inputs["T"] # Number of time steps (hours) @@ -31,30 +32,29 @@ function write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup: dfResRevenue = DataFrame(Region = dfGen.region, Resource = inputs["RESOURCES"], Zone = dfGen.Zone, Cluster = dfGen.cluster) annual_sum = zeros(G) for i in 1:inputs["NCapacityReserveMargin"] + weighted_price = capacity_reserve_margin_price(EP, inputs, setup, i) .* inputs["omega"] sym = Symbol("CapRes_$i") tempresrev = zeros(G) - tempresrev[THERM_ALL] = dfGen[THERM_ALL, sym] .* (value.(EP[:eTotalCap][THERM_ALL])) * sum(dual.(EP[:cCapacityResMargin][i, :])) - tempresrev[VRE] = dfGen[VRE, sym] .* (value.(EP[:eTotalCap][VRE])) .* (inputs["pP_Max"][VRE, :] * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[MUST_RUN] = dfGen[MUST_RUN, sym] .* (value.(EP[:eTotalCap][MUST_RUN])) .* (inputs["pP_Max"][MUST_RUN, :] * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[HYDRO_RES] = dfGen[HYDRO_RES, sym] .* (value.(EP[:vP][HYDRO_RES, :]) * (dual.(EP[:cCapacityResMargin][i, :]))) + tempresrev[THERM_ALL] = thermal_plant_effective_capacity(EP, inputs, THERM_ALL, i)' * weighted_price + tempresrev[VRE] = dfGen[VRE, sym] .* (value.(EP[:eTotalCap][VRE])) .* (inputs["pP_Max"][VRE, :] * weighted_price) + tempresrev[MUST_RUN] = dfGen[MUST_RUN, sym] .* (value.(EP[:eTotalCap][MUST_RUN])) .* (inputs["pP_Max"][MUST_RUN, :] * weighted_price) + tempresrev[HYDRO_RES] = dfGen[HYDRO_RES, sym] .* (value.(EP[:vP][HYDRO_RES, :]) * weighted_price) if !isempty(STOR_ALL) - tempresrev[STOR_ALL] = dfGen[STOR_ALL, sym] .* ((value.(EP[:vP][STOR_ALL, :]) - value.(EP[:vCHARGE][STOR_ALL, :]).data + value.(EP[:vCAPRES_discharge][STOR_ALL, :]).data - value.(EP[:vCAPRES_charge][STOR_ALL, :]).data) * (dual.(EP[:cCapacityResMargin][i, :]))) + tempresrev[STOR_ALL] = dfGen[STOR_ALL, sym] .* ((value.(EP[:vP][STOR_ALL, :]) - value.(EP[:vCHARGE][STOR_ALL, :]).data + value.(EP[:vCAPRES_discharge][STOR_ALL, :]).data - value.(EP[:vCAPRES_charge][STOR_ALL, :]).data) * weighted_price) end if !isempty(FLEX) - tempresrev[FLEX] = dfGen[FLEX, sym] .* ((value.(EP[:vCHARGE_FLEX][FLEX, :]).data - value.(EP[:vP][FLEX, :])) * (dual.(EP[:cCapacityResMargin][i, :]))) + tempresrev[FLEX] = dfGen[FLEX, sym] .* ((value.(EP[:vCHARGE_FLEX][FLEX, :]).data - value.(EP[:vP][FLEX, :])) * weighted_price) end if !isempty(VRE_STOR) sym_vs = Symbol("CapResVreStor_$i") - tempresrev[VRE_STOR] = dfVRE_STOR[!, sym_vs] .* ((value.(EP[:vP][VRE_STOR, :])) * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[VRE_STOR_STOR] .-= dfVRE_STOR[((dfVRE_STOR.STOR_DC_DISCHARGE.!=0) .| (dfVRE_STOR.STOR_DC_CHARGE.!=0) .| (dfVRE_STOR.STOR_AC_DISCHARGE.!=0) .|(dfVRE_STOR.STOR_AC_CHARGE.!=0)), sym_vs] .* (value.(EP[:vCHARGE_VRE_STOR][VRE_STOR_STOR, :]).data * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[DC_DISCHARGE] .+= dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_DC_DISCHARGE][DC_DISCHARGE, :]).data .* dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0), :EtaInverter]) * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[AC_DISCHARGE] .+= dfVRE_STOR[(dfVRE_STOR.STOR_AC_DISCHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_AC_DISCHARGE][AC_DISCHARGE, :]).data) * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[DC_CHARGE] .-= dfVRE_STOR[(dfVRE_STOR.STOR_DC_CHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_DC_CHARGE][DC_CHARGE, :]).data ./ dfVRE_STOR[(dfVRE_STOR.STOR_DC_CHARGE.!=0), :EtaInverter]) * (dual.(EP[:cCapacityResMargin][i, :]))) - tempresrev[AC_CHARGE] .-= dfVRE_STOR[(dfVRE_STOR.STOR_AC_CHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_AC_CHARGE][AC_CHARGE, :]).data) * (dual.(EP[:cCapacityResMargin][i, :]))) - end - if setup["ParameterScale"] == 1 - tempresrev *= ModelScalingFactor^2 + tempresrev[VRE_STOR] = dfVRE_STOR[!, sym_vs] .* ((value.(EP[:vP][VRE_STOR, :])) * weighted_price) + tempresrev[VRE_STOR_STOR] .-= dfVRE_STOR[((dfVRE_STOR.STOR_DC_DISCHARGE.!=0) .| (dfVRE_STOR.STOR_DC_CHARGE.!=0) .| (dfVRE_STOR.STOR_AC_DISCHARGE.!=0) .|(dfVRE_STOR.STOR_AC_CHARGE.!=0)), sym_vs] .* (value.(EP[:vCHARGE_VRE_STOR][VRE_STOR_STOR, :]).data * weighted_price) + tempresrev[DC_DISCHARGE] .+= dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_DC_DISCHARGE][DC_DISCHARGE, :]).data .* dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0), :EtaInverter]) * weighted_price) + tempresrev[AC_DISCHARGE] .+= dfVRE_STOR[(dfVRE_STOR.STOR_AC_DISCHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_AC_DISCHARGE][AC_DISCHARGE, :]).data) * weighted_price) + tempresrev[DC_CHARGE] .-= dfVRE_STOR[(dfVRE_STOR.STOR_DC_CHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_DC_CHARGE][DC_CHARGE, :]).data ./ dfVRE_STOR[(dfVRE_STOR.STOR_DC_CHARGE.!=0), :EtaInverter]) * weighted_price) + tempresrev[AC_CHARGE] .-= dfVRE_STOR[(dfVRE_STOR.STOR_AC_CHARGE.!=0), sym_vs] .* ((value.(EP[:vCAPRES_AC_CHARGE][AC_CHARGE, :]).data) * weighted_price) end + tempresrev *= scale_factor annual_sum .+= tempresrev dfResRevenue = hcat(dfResRevenue, DataFrame([tempresrev], [sym])) end diff --git a/src/write_outputs/energy_share_requirement/write_esr_revenue.jl b/src/write_outputs/energy_share_requirement/write_esr_revenue.jl index fc945e218a..9f74ed5baa 100644 --- a/src/write_outputs/energy_share_requirement/write_esr_revenue.jl +++ b/src/write_outputs/energy_share_requirement/write_esr_revenue.jl @@ -7,6 +7,8 @@ function write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPo dfGen = inputs["dfGen"] dfESRRev = DataFrame(region = dfGen[!,:region], Resource = inputs["RESOURCES"], zone = dfGen[!,:Zone], Cluster = dfGen[!,:cluster], R_ID = dfGen[!,:R_ID]) G = inputs["G"] + nESR = inputs["nESR"] + weight = inputs["omega"] VRE_STOR = inputs["VRE_STOR"] dfVRE_STOR = inputs["dfVRE_STOR"] if !isempty(VRE_STOR) @@ -16,48 +18,48 @@ function write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPo WIND_ONLY = setdiff(WIND, SOLAR) SOLAR_WIND = intersect(SOLAR, WIND) end + by_rid(rid, sym) = by_rid_df(rid, sym, dfVRE_STOR) - for i in 1:inputs["nESR"] + for i in 1:nESR esr_col = Symbol("ESR_$i") - dfESRRev = hcat(dfESRRev, dfPower[1:G,:AnnualSum] .* dfGen[!,esr_col] * dfESR[i,:ESR_Price]) - # dfpower is in MWh already, price is in $/MWh already, no need to scale - # if setup["ParameterScale"] == 1 - # #dfESRRev[!,:x1] = dfESRRev[!,:x1] * (1e+3) # MillionUS$ to US$ - # dfESRRev[!,:x1] = dfESRRev[!,:x1] * ModelScalingFactor # MillionUS$ to US$ # Is this right? -Jack 4/29/2021 - # end - rename!(dfESRRev, Dict(:x1 => esr_col)) + price = dfESR[i, :ESR_Price] + derated_annual_net_generation = dfPower[1:G,:AnnualSum] .* dfGen[!,esr_col] + revenue = derated_annual_net_generation * price + dfESRRev[!, esr_col] = revenue + if !isempty(VRE_STOR) esr_vrestor_col = Symbol("ESRVreStor_$i") if !isempty(SOLAR_ONLY) solar_resources = ((dfVRE_STOR.WIND.==0) .& (dfVRE_STOR.SOLAR.!=0)) dfESRRev[SOLAR, esr_col] = ( value.(EP[:vP_SOLAR][SOLAR, :]).data - .* dfVRE_STOR[solar_resources, :EtaInverter] * inputs["omega"] - ) .* dfVRE_STOR[solar_resources,esr_vrestor_col] * dfESR[i,:ESR_Price] + .* dfVRE_STOR[solar_resources, :EtaInverter] * weight + ) .* dfVRE_STOR[solar_resources,esr_vrestor_col] * price end if !isempty(WIND_ONLY) wind_resources = ((dfVRE_STOR.WIND.!=0) .& (dfVRE_STOR.SOLAR.==0)) dfESRRev[WIND, esr_col] = ( value.(EP[:vP_WIND][WIND, :]).data - * inputs["omega"] - ) .* dfVRE_STOR[wind_resources,esr_vrestor_col] * dfESR[i,:ESR_Price] + * weight + ) .* dfVRE_STOR[wind_resources,esr_vrestor_col] * price end if !isempty(SOLAR_WIND) solar_and_wind_resources = ((dfVRE_STOR.WIND.!=0) .& (dfVRE_STOR.SOLAR.!=0)) dfESRRev[SOLAR_WIND, esr_col] = ( ( - (value.(EP[:vP_WIND][SOLAR_WIND, :]).data * inputs["omega"]) - .* dfVRE_STOR[solar_and_wind_resources,esr_vrestor_col] * dfESR[i,:ESR_Price] + (value.(EP[:vP_WIND][SOLAR_WIND, :]).data * weight) + .* dfVRE_STOR[solar_and_wind_resources,esr_vrestor_col] * price ) + ( value.(EP[:vP_SOLAR][SOLAR_WIND, :]).data .* dfVRE_STOR[solar_and_wind_resources, :EtaInverter] - * inputs["omega"] - ) .* dfVRE_STOR[solar_and_wind_resources,esr_vrestor_col] * dfESR[i,:ESR_Price] + * weight + ) .* dfVRE_STOR[solar_and_wind_resources,esr_vrestor_col] * price ) end end end - dfESRRev.AnnualSum = sum(eachcol(dfESRRev[:,6:inputs["nESR"]+5])) + dfESRRev.Total = sum(eachcol(dfESRRev[:, 6:nESR + 5])) CSV.write(joinpath(path, "ESR_Revenue.csv"), dfESRRev) return dfESRRev end + diff --git a/src/write_outputs/min_max_capacity_requirement/write_maximum_capacity_requirement.jl b/src/write_outputs/min_max_capacity_requirement/write_maximum_capacity_requirement.jl index 5e3f44bfdd..24e3a7f4e6 100644 --- a/src/write_outputs/min_max_capacity_requirement/write_maximum_capacity_requirement.jl +++ b/src/write_outputs/min_max_capacity_requirement/write_maximum_capacity_requirement.jl @@ -3,9 +3,6 @@ function write_maximum_capacity_requirement(path::AbstractString, inputs::Dict, dfMaxCapPrice = DataFrame(Constraint = [Symbol("MaxCapReq_$maxcap") for maxcap = 1:NumberOfMaxCapReqs], Price=-dual.(EP[:cZoneMaxCapReq])) - # Generally the scale_factor is used to convert - # GW (in the model) back to MW (for output) - # and likewise for $M to $. scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 dfMaxCapPrice.Price *= scale_factor diff --git a/src/write_outputs/min_max_capacity_requirement/write_minimum_capacity_requirement.jl b/src/write_outputs/min_max_capacity_requirement/write_minimum_capacity_requirement.jl index a1fb39e3aa..a1bfe1d28d 100644 --- a/src/write_outputs/min_max_capacity_requirement/write_minimum_capacity_requirement.jl +++ b/src/write_outputs/min_max_capacity_requirement/write_minimum_capacity_requirement.jl @@ -2,16 +2,16 @@ function write_minimum_capacity_requirement(path::AbstractString, inputs::Dict, NumberOfMinCapReqs = inputs["NumberOfMinCapReqs"] dfMinCapPrice = DataFrame(Constraint = [Symbol("MinCapReq_$mincap") for mincap = 1:NumberOfMinCapReqs], Price= dual.(EP[:cZoneMinCapReq])) - if setup["ParameterScale"] == 1 - dfMinCapPrice.Price *= ModelScalingFactor # Convert Million $/GW to $/MW - end + + scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 + + dfMinCapPrice.Price *= scale_factor # Convert Million $/GW to $/MW + if haskey(inputs, "MinCapPriceCap") - dfMinCapPrice[!,:Slack] = convert(Array{Float64}, value.(EP[:vMinCap_slack])) - dfMinCapPrice[!,:Penalty] = convert(Array{Float64}, value.(EP[:eCMinCap_slack])) - if setup["ParameterScale"] == 1 - dfMinCapPrice.Slack *= ModelScalingFactor # Convert GW to MW - dfMinCapPrice.Penalty *= ModelScalingFactor^2 # Convert Million $ to $ - end - end + dfMinCapPrice[!,:Slack] = convert(Array{Float64}, value.(EP[:vMinCap_slack])) + dfMinCapPrice[!,:Penalty] = convert(Array{Float64}, value.(EP[:eCMinCap_slack])) + dfMinCapPrice.Slack *= scale_factor # Convert GW to MW + dfMinCapPrice.Penalty *= scale_factor^2 # Convert Million $ to $ + end CSV.write(joinpath(path, "MinCapReq_prices_and_penalties.csv"), dfMinCapPrice) end diff --git a/src/write_outputs/reserves/write_rsv.jl b/src/write_outputs/reserves/write_rsv.jl index c5cd942966..53f81d0817 100644 --- a/src/write_outputs/reserves/write_rsv.jl +++ b/src/write_outputs/reserves/write_rsv.jl @@ -8,11 +8,11 @@ function write_rsv(path::AbstractString, inputs::Dict, setup::Dict, EP::Model) dfRsv = DataFrame(Resource = inputs["RESOURCES"], Zone = dfGen[!, :Zone]) rsv = zeros(G,T) unmet_vec = zeros(T) - rsv[RSV, :] = value.(EP[:vRSV][RSV, :]) - unmet_vec[RSV] = value.(EP[:vUNMET_RSV][RSV]) - total_unmet = (sum(unmet_vec)*scale_factor) - dfRsv.AnnualSum = (rsv*scale_factor) * inputs["omega"] - dfRsv = hcat(dfRsv, DataFrame((rsv*scale_factor), :auto)) + rsv[RSV, :] = value.(EP[:vRSV][RSV, :]) * scale_factor + unmet_vec = value.(EP[:vUNMET_RSV]) * scale_factor + total_unmet = sum(unmet_vec) + dfRsv.AnnualSum = rsv * inputs["omega"] + dfRsv = hcat(dfRsv, DataFrame(rsv, :auto)) auxNew_Names=[Symbol("Resource");Symbol("Zone");Symbol("AnnualSum");[Symbol("t$t") for t in 1:T]] rename!(dfRsv,auxNew_Names) diff --git a/src/write_outputs/write_charging_cost.jl b/src/write_outputs/write_charging_cost.jl index 46c79f7969..3f87f64549 100644 --- a/src/write_outputs/write_charging_cost.jl +++ b/src/write_outputs/write_charging_cost.jl @@ -7,25 +7,27 @@ function write_charging_cost(path::AbstractString, inputs::Dict, setup::Dict, EP ELECTROLYZER = inputs["ELECTROLYZER"] VRE_STOR = inputs["VRE_STOR"] VS_STOR = !isempty(VRE_STOR) ? inputs["VS_STOR"] : [] - + + price = locational_marginal_price(EP, inputs, setup) + dfChargingcost = DataFrame(Region = dfGen[!, :region], Resource = inputs["RESOURCES"], Zone = dfGen[!, :Zone], Cluster = dfGen[!, :cluster], AnnualSum = Array{Float64}(undef, G),) chargecost = zeros(G, T) if !isempty(STOR_ALL) - chargecost[STOR_ALL, :] .= (value.(EP[:vCHARGE][STOR_ALL, :]).data) .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[STOR_ALL, :Zone], :] + chargecost[STOR_ALL, :] .= (value.(EP[:vCHARGE][STOR_ALL, :]).data) .* transpose(price)[dfGen[STOR_ALL, :Zone], :] end if !isempty(FLEX) - chargecost[FLEX, :] .= value.(EP[:vP][FLEX, :]) .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[FLEX, :Zone], :] + chargecost[FLEX, :] .= value.(EP[:vP][FLEX, :]) .* transpose(price)[dfGen[FLEX, :Zone], :] end if !isempty(ELECTROLYZER) - chargecost[ELECTROLYZER, :] .= (value.(EP[:vUSE][ELECTROLYZER, :]).data) .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[ELECTROLYZER, :Zone], :] + chargecost[ELECTROLYZER, :] .= (value.(EP[:vUSE][ELECTROLYZER, :]).data) .* transpose(price)[dfGen[ELECTROLYZER, :Zone], :] end if !isempty(VS_STOR) - chargecost[VS_STOR, :] .= value.(EP[:vCHARGE_VRE_STOR][VS_STOR, :].data) .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[VS_STOR, :Zone], :] + chargecost[VS_STOR, :] .= value.(EP[:vCHARGE_VRE_STOR][VS_STOR, :].data) .* transpose(price)[dfGen[VS_STOR, :Zone], :] end if setup["ParameterScale"] == 1 - chargecost *= ModelScalingFactor^2 + chargecost *= ModelScalingFactor end dfChargingcost.AnnualSum .= chargecost * inputs["omega"] - CSV.write(joinpath(path, "ChargingCost.csv"), dfChargingcost) + write_simple_csv(joinpath(path, "ChargingCost.csv"), dfChargingcost) return dfChargingcost end diff --git a/src/write_outputs/write_energy_revenue.jl b/src/write_outputs/write_energy_revenue.jl index d566d3c79c..f53abbaa5b 100644 --- a/src/write_outputs/write_energy_revenue.jl +++ b/src/write_outputs/write_energy_revenue.jl @@ -11,14 +11,15 @@ function write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, E NONFLEX = setdiff(collect(1:G), FLEX) dfEnergyRevenue = DataFrame(Region = dfGen.region, Resource = inputs["RESOURCES"], Zone = dfGen.Zone, Cluster = dfGen.cluster, AnnualSum = Array{Float64}(undef, G),) energyrevenue = zeros(G, T) - energyrevenue[NONFLEX, :] = value.(EP[:vP][NONFLEX, :]) .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[NONFLEX, :Zone], :] + price = locational_marginal_price(EP, inputs, setup) + energyrevenue[NONFLEX, :] = value.(EP[:vP][NONFLEX, :]) .* transpose(price)[dfGen[NONFLEX, :Zone], :] if !isempty(FLEX) - energyrevenue[FLEX, :] = value.(EP[:vCHARGE_FLEX][FLEX, :]).data .* transpose(dual.(EP[:cPowerBalance]) ./ inputs["omega"])[dfGen[FLEX, :Zone], :] + energyrevenue[FLEX, :] = value.(EP[:vCHARGE_FLEX][FLEX, :]).data .* transpose(price)[dfGen[FLEX, :Zone], :] end if setup["ParameterScale"] == 1 - energyrevenue *= ModelScalingFactor^2 + energyrevenue *= ModelScalingFactor end dfEnergyRevenue.AnnualSum .= energyrevenue * inputs["omega"] - CSV.write(joinpath(path, "EnergyRevenue.csv"), dfEnergyRevenue) + write_simple_csv(joinpath(path, "EnergyRevenue.csv"), dfEnergyRevenue) return dfEnergyRevenue end diff --git a/src/write_outputs/write_maintenance.jl b/src/write_outputs/write_maintenance.jl index 741abdcfa8..d00af7b696 100644 --- a/src/write_outputs/write_maintenance.jl +++ b/src/write_outputs/write_maintenance.jl @@ -7,9 +7,9 @@ function write_simple_csv(filename::AbstractString, header::Vector, matrix) write_simple_csv(filename, df) end -function prepare_timeseries_variables(EP::Model, set::Set{Symbol}) +function prepare_timeseries_variables(EP::Model, set::Set{Symbol}, scale::Float64=1.0) # function to extract data from DenseAxisArray - data(var) = value.(EP[var]).data + data(var) = scale * value.(EP[var]).data return DataFrame(set .=> data.(set)) end diff --git a/src/write_outputs/write_net_revenue.jl b/src/write_outputs/write_net_revenue.jl index fd1d473c45..eb17cd001b 100644 --- a/src/write_outputs/write_net_revenue.jl +++ b/src/write_outputs/write_net_revenue.jl @@ -30,6 +30,8 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: # Add investment cost to the dataframe dfNetRevenue.Inv_cost_MW = dfGen[!,:Inv_Cost_per_MWyr] .* dfCap[1:G,:NewCap] dfNetRevenue.Inv_cost_MWh = dfGen[!,:Inv_Cost_per_MWhyr] .* dfCap[1:G,:NewEnergyCap] + dfNetRevenue.Inv_cost_charge_MW = dfGen[!,:Inv_Cost_Charge_per_MWyr] .* dfCap[1:G,:NewChargeCap] + if !isempty(VRE_STOR) # Doesn't include charge capacities if !isempty(SOLAR) @@ -37,7 +39,7 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: end if !isempty(DC) dfNetRevenue.Inv_cost_MW[VRE_STOR] += dfVRE_STOR[!,:Inv_Cost_Inverter_per_MWyr] .* dfVreStor[1:VRE_STOR_LENGTH,:NewCapDC] - end + end if !isempty(WIND) dfNetRevenue.Inv_cost_MW[VRE_STOR] += dfVRE_STOR[!,:Inv_Cost_Wind_per_MWyr] .* dfVreStor[1:VRE_STOR_LENGTH,:NewCapWind] end @@ -45,11 +47,14 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: if setup["ParameterScale"] == 1 dfNetRevenue.Inv_cost_MWh *= ModelScalingFactor # converting Million US$ to US$ dfNetRevenue.Inv_cost_MW *= ModelScalingFactor # converting Million US$ to US$ + dfNetRevenue.Inv_cost_charge_MW *= ModelScalingFactor # converting Million US$ to US$ end # Add operations and maintenance cost to the dataframe dfNetRevenue.Fixed_OM_cost_MW = dfGen[!,:Fixed_OM_Cost_per_MWyr] .* dfCap[1:G,:EndCap] dfNetRevenue.Fixed_OM_cost_MWh = dfGen[!,:Fixed_OM_Cost_per_MWhyr] .* dfCap[1:G,:EndEnergyCap] + dfNetRevenue.Fixed_OM_cost_charge_MW = dfGen[!, :Fixed_OM_Cost_Charge_per_MWyr] .* dfCap[1:G, :EndChargeCap] + dfNetRevenue.Var_OM_cost_out = (dfGen[!,:Var_OM_Cost_per_MWh]) .* dfPower[1:G,:AnnualSum] if !isempty(VRE_STOR) if !isempty(SOLAR) @@ -59,10 +64,10 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: if !isempty(WIND) dfNetRevenue.Fixed_OM_cost_MW[VRE_STOR] += dfVRE_STOR[!,:Fixed_OM_Wind_Cost_per_MWyr] .* dfVreStor[1:VRE_STOR_LENGTH, :EndCapWind] dfNetRevenue.Var_OM_cost_out[WIND] += dfVRE_STOR[(dfVRE_STOR.WIND.!=0),:Var_OM_Cost_per_MWh_Wind] .* (value.(EP[:vP_WIND][WIND, :]).data * inputs["omega"]) - end + end if !isempty(DC) dfNetRevenue.Fixed_OM_cost_MW[VRE_STOR] += dfVRE_STOR[!,:Fixed_OM_Inverter_Cost_per_MWyr] .* dfVreStor[1:VRE_STOR_LENGTH, :EndCapDC] - end + end if !isempty(DC_DISCHARGE) dfNetRevenue.Var_OM_cost_out[DC_DISCHARGE] += dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0),:Var_OM_Cost_per_MWh_Discharge_DC] .* (value.(EP[:vP_DC_DISCHARGE][DC_DISCHARGE, :]).data .* dfVRE_STOR[(dfVRE_STOR.STOR_DC_DISCHARGE.!=0),:EtaInverter] * inputs["omega"]) end @@ -73,6 +78,7 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: if setup["ParameterScale"] == 1 dfNetRevenue.Fixed_OM_cost_MW *= ModelScalingFactor # converting Million US$ to US$ dfNetRevenue.Fixed_OM_cost_MWh *= ModelScalingFactor # converting Million US$ to US$ + dfNetRevenue.Fixed_OM_cost_charge_MW *= ModelScalingFactor # converting Million US$ to US$ dfNetRevenue.Var_OM_cost_out *= ModelScalingFactor # converting Million US$ to US$ end @@ -132,7 +138,7 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: # Add RPS/CES revenue to the dataframe dfNetRevenue.ESRRevenue = zeros(nrow(dfNetRevenue)) if setup["EnergyShareRequirement"] > 0 && has_duals(EP) == 1 # The unit is confirmed to be $ - dfNetRevenue.ESRRevenue = dfESRRev[1:G,:AnnualSum] + dfNetRevenue.ESRRevenue = dfESRRev[1:G,:Total] end # Calculate emissions cost @@ -142,11 +148,7 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: co2_cap_dual = dual(EP[:cCO2Emissions_systemwide][cap]) CO2ZONES = findall(x->x==1, inputs["dfCO2CapZones"][:,cap]) GEN_IN_ZONE = dfGen[[y in CO2ZONES for y in dfGen[:, :Zone]], :R_ID] - if setup["CO2Cap"]==1 # Mass-based - # Cost = sum(sum(emissions of gen y * dual(CO2 constraint[cap]) for z in Z) for cap in setup["NCO2"]) - temp_vec = value.(EP[:eEmissionsByPlant][GEN_IN_ZONE, :]) * inputs["omega"] - dfNetRevenue.EmissionsCost[GEN_IN_ZONE] += - co2_cap_dual * temp_vec - elseif setup["CO2Cap"]==2 # Demand + Rate-based + if setup["CO2Cap"]==1 || setup["CO2Cap"]==2 # Mass-based or Demand + Rate-based # Cost = sum(sum(emissions for zone z * dual(CO2 constraint[cap]) for z in Z) for cap in setup["NCO2"]) temp_vec = value.(EP[:eEmissionsByPlant][GEN_IN_ZONE, :]) * inputs["omega"] dfNetRevenue.EmissionsCost[GEN_IN_ZONE] += - co2_cap_dual * temp_vec @@ -169,7 +171,18 @@ function write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP:: end dfNetRevenue.Revenue = dfNetRevenue.EnergyRevenue .+ dfNetRevenue.SubsidyRevenue .+ dfNetRevenue.ReserveMarginRevenue .+ dfNetRevenue.ESRRevenue .+ dfNetRevenue.RegSubsidyRevenue - dfNetRevenue.Cost = dfNetRevenue.Inv_cost_MW .+ dfNetRevenue.Inv_cost_MWh .+ dfNetRevenue.Fixed_OM_cost_MW .+ dfNetRevenue.Fixed_OM_cost_MWh .+ dfNetRevenue.Var_OM_cost_out .+ dfNetRevenue.Var_OM_cost_in .+ dfNetRevenue.Fuel_cost .+ dfNetRevenue.Charge_cost .+ dfNetRevenue.EmissionsCost .+ dfNetRevenue.StartCost + dfNetRevenue.Cost = (dfNetRevenue.Inv_cost_MW + .+ dfNetRevenue.Inv_cost_MWh + .+ dfNetRevenue.Inv_cost_charge_MW + .+ dfNetRevenue.Fixed_OM_cost_MW + .+ dfNetRevenue.Fixed_OM_cost_MWh + .+ dfNetRevenue.Fixed_OM_cost_charge_MW + .+ dfNetRevenue.Var_OM_cost_out + .+ dfNetRevenue.Var_OM_cost_in + .+ dfNetRevenue.Fuel_cost + .+ dfNetRevenue.Charge_cost + .+ dfNetRevenue.EmissionsCost + .+ dfNetRevenue.StartCost) dfNetRevenue.Profit = dfNetRevenue.Revenue .- dfNetRevenue.Cost CSV.write(joinpath(path, "NetRevenue.csv"), dfNetRevenue) diff --git a/src/write_outputs/write_power_balance.jl b/src/write_outputs/write_power_balance.jl index 8db0b72a4c..ae45be8aed 100644 --- a/src/write_outputs/write_power_balance.jl +++ b/src/write_outputs/write_power_balance.jl @@ -49,8 +49,9 @@ function write_power_balance(path::AbstractString, inputs::Dict, setup::Dict, EP powerbalance[(z-1)*L+9, :] = -(value.(EP[:eLosses_By_Zone][z, :])) end powerbalance[(z-1)*L+10, :] = (((-1) * inputs["pD"][:, z]))' # Transpose - if (!isempty(ELECTROLYZER)) - powerbalance[(z-1)*L+11, :] = (-1) * sum(value.(EP[:vUSE][ELECTROLYZER, :].data), dims = 1) + if !isempty(ELECTROLYZER) + ELECTROLYZER_ZONE = intersect(dfGen[dfGen.Zone.==z, :R_ID], ELECTROLYZER) + powerbalance[(z-1)*L+11, :] = (-1) * sum(value.(EP[:vUSE][ELECTROLYZER_ZONE, :].data), dims = 1) end end if setup["ParameterScale"] == 1 diff --git a/src/write_outputs/write_price.jl b/src/write_outputs/write_price.jl index 1228744918..0a2f743ff9 100644 --- a/src/write_outputs/write_price.jl +++ b/src/write_outputs/write_price.jl @@ -10,9 +10,9 @@ function write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model) ## Extract dual variables of constraints # Electricity price: Dual variable of hourly power balance constraint = hourly price dfPrice = DataFrame(Zone = 1:Z) # The unit is $/MWh - scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 # Dividing dual variable for each hour with corresponding hourly weight to retrieve marginal cost of generation - dfPrice = hcat(dfPrice, DataFrame(transpose(dual.(EP[:cPowerBalance])./inputs["omega"]*scale_factor), :auto)) + price = locational_marginal_price(EP, inputs, setup) + dfPrice = hcat(dfPrice, DataFrame(transpose(price), :auto)) auxNew_Names=[Symbol("Zone");[Symbol("t$t") for t in 1:T]] rename!(dfPrice,auxNew_Names) @@ -21,3 +21,21 @@ function write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model) CSV.write(joinpath(path, "prices.csv"), dftranspose(dfPrice, false), writeheader=false) return dfPrice end + +@doc raw""" + locational_marginal_price(EP::Model, inputs::Dict, setup::Dict) + +Marginal electricity price for each model zone and time step. +This is equal to the dual variable of the power balance constraint. +When solving a linear program (i.e. linearized unit commitment or economic dispatch) +this output is always available; when solving a mixed integer linear program, this can +be calculated only if `WriteShadowPrices` is activated. + + Returns a matrix of size (T, Z). + Values have units of $/MWh +""" +function locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)::Matrix{Float64} + ω = inputs["omega"] + scale_factor = setup["ParameterScale"] == 1 ? ModelScalingFactor : 1 + return dual.(EP[:cPowerBalance]) ./ ω * scale_factor +end diff --git a/test/MultiStage/Can_Retire/Inputs_p1/CO2_cap.csv b/test/MultiStage/Can_Retire/Inputs_p1/CO2_cap.csv new file mode 100644 index 0000000000..f1f3ff4165 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,1,1 \ No newline at end of file diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Capacity_reserve_margin.csv b/test/MultiStage/Can_Retire/Inputs_p1/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Demand_data.csv b/test/MultiStage/Can_Retire/Inputs_p1/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Energy_share_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p1/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Fuels_data.csv b/test/MultiStage/Can_Retire/Inputs_p1/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Generators_data.csv b/test/MultiStage/Can_Retire/Inputs_p1/Generators_data.csv new file mode 100644 index 0000000000..7a759104c9 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,1,0,10000,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,500,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,1000,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Generators_variability.csv b/test/MultiStage/Can_Retire/Inputs_p1/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Minimum_capacity_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p1/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Period_map.csv b/test/MultiStage/Can_Retire/Inputs_p1/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/Can_Retire/Inputs_p1/Reserves.csv b/test/MultiStage/Can_Retire/Inputs_p1/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p1/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/CO2_cap.csv b/test/MultiStage/Can_Retire/Inputs_p2/CO2_cap.csv new file mode 100644 index 0000000000..e8a5ff9305 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,0.5,0.5 \ No newline at end of file diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Capacity_reserve_margin.csv b/test/MultiStage/Can_Retire/Inputs_p2/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Demand_data.csv b/test/MultiStage/Can_Retire/Inputs_p2/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Energy_share_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p2/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Fuels_data.csv b/test/MultiStage/Can_Retire/Inputs_p2/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Generators_data.csv b/test/MultiStage/Can_Retire/Inputs_p2/Generators_data.csv new file mode 100644 index 0000000000..574127a24d --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,1,0,0,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Generators_variability.csv b/test/MultiStage/Can_Retire/Inputs_p2/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Minimum_capacity_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p2/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Period_map.csv b/test/MultiStage/Can_Retire/Inputs_p2/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/Can_Retire/Inputs_p2/Reserves.csv b/test/MultiStage/Can_Retire/Inputs_p2/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p2/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/CO2_cap.csv b/test/MultiStage/Can_Retire/Inputs_p3/CO2_cap.csv new file mode 100644 index 0000000000..cfb18ecf62 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,0.05,0.05 \ No newline at end of file diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Capacity_reserve_margin.csv b/test/MultiStage/Can_Retire/Inputs_p3/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Demand_data.csv b/test/MultiStage/Can_Retire/Inputs_p3/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Energy_share_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p3/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Fuels_data.csv b/test/MultiStage/Can_Retire/Inputs_p3/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Generators_data.csv b/test/MultiStage/Can_Retire/Inputs_p3/Generators_data.csv new file mode 100644 index 0000000000..574127a24d --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,1,0,0,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Generators_variability.csv b/test/MultiStage/Can_Retire/Inputs_p3/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Minimum_capacity_requirement.csv b/test/MultiStage/Can_Retire/Inputs_p3/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Period_map.csv b/test/MultiStage/Can_Retire/Inputs_p3/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/Can_Retire/Inputs_p3/Reserves.csv b/test/MultiStage/Can_Retire/Inputs_p3/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/Can_Retire/Inputs_p3/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/Can_Retire/highs_settings.yml b/test/MultiStage/Can_Retire/highs_settings.yml new file mode 100644 index 0000000000..e520dfbef7 --- /dev/null +++ b/test/MultiStage/Can_Retire/highs_settings.yml @@ -0,0 +1,12 @@ +# HiGHS Solver Parameters +# Common solver settings +Feasib_Tol: 1.0e-05 # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07] +Optimal_Tol: 1.0e-05 # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07] +TimeLimit: 1.0e23 # Time limit # [type: double, advanced: false, range: [0, inf], default: inf] +Pre_Solve: on # Presolve option: "off", "choose" or "on" # [type: string, advanced: false, default: "choose"] +Method: ipm # HiGHS-specific solver settings # Solver option: "simplex", "choose" or "ipm" # [type: string, advanced: false, default: "choose"] +ipm_optimality_tolerance: 1e-04 + +# run the crossover routine for ipx +# [type: string, advanced: "on", range: {"off", "on"}, default: "off"] +run_crossover: "on" diff --git a/test/MultiStage/New_Build/Inputs_p1/CO2_cap.csv b/test/MultiStage/New_Build/Inputs_p1/CO2_cap.csv new file mode 100644 index 0000000000..f1f3ff4165 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,1,1 \ No newline at end of file diff --git a/test/MultiStage/New_Build/Inputs_p1/Capacity_reserve_margin.csv b/test/MultiStage/New_Build/Inputs_p1/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/New_Build/Inputs_p1/Demand_data.csv b/test/MultiStage/New_Build/Inputs_p1/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/New_Build/Inputs_p1/Energy_share_requirement.csv b/test/MultiStage/New_Build/Inputs_p1/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/New_Build/Inputs_p1/Fuels_data.csv b/test/MultiStage/New_Build/Inputs_p1/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/New_Build/Inputs_p1/Generators_data.csv b/test/MultiStage/New_Build/Inputs_p1/Generators_data.csv new file mode 100644 index 0000000000..f891203315 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,0,1,10000,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,500,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,1000,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/New_Build/Inputs_p1/Generators_variability.csv b/test/MultiStage/New_Build/Inputs_p1/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/New_Build/Inputs_p1/Minimum_capacity_requirement.csv b/test/MultiStage/New_Build/Inputs_p1/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/New_Build/Inputs_p1/Period_map.csv b/test/MultiStage/New_Build/Inputs_p1/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/New_Build/Inputs_p1/Reserves.csv b/test/MultiStage/New_Build/Inputs_p1/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p1/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/New_Build/Inputs_p2/CO2_cap.csv b/test/MultiStage/New_Build/Inputs_p2/CO2_cap.csv new file mode 100644 index 0000000000..e8a5ff9305 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,0.5,0.5 \ No newline at end of file diff --git a/test/MultiStage/New_Build/Inputs_p2/Capacity_reserve_margin.csv b/test/MultiStage/New_Build/Inputs_p2/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/New_Build/Inputs_p2/Demand_data.csv b/test/MultiStage/New_Build/Inputs_p2/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/New_Build/Inputs_p2/Energy_share_requirement.csv b/test/MultiStage/New_Build/Inputs_p2/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/New_Build/Inputs_p2/Fuels_data.csv b/test/MultiStage/New_Build/Inputs_p2/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/New_Build/Inputs_p2/Generators_data.csv b/test/MultiStage/New_Build/Inputs_p2/Generators_data.csv new file mode 100644 index 0000000000..d8e0ca4e9b --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,0,1,0,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/New_Build/Inputs_p2/Generators_variability.csv b/test/MultiStage/New_Build/Inputs_p2/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/New_Build/Inputs_p2/Minimum_capacity_requirement.csv b/test/MultiStage/New_Build/Inputs_p2/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/New_Build/Inputs_p2/Period_map.csv b/test/MultiStage/New_Build/Inputs_p2/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/New_Build/Inputs_p2/Reserves.csv b/test/MultiStage/New_Build/Inputs_p2/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p2/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/New_Build/Inputs_p3/CO2_cap.csv b/test/MultiStage/New_Build/Inputs_p3/CO2_cap.csv new file mode 100644 index 0000000000..cfb18ecf62 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/CO2_cap.csv @@ -0,0 +1,2 @@ +,Network_zones,CO_2_Cap_Zone_1,CO_2_Max_tons_MWh_1,CO_2_Max_Mtons_1 +NE,z1,1,0.05,0.05 \ No newline at end of file diff --git a/test/MultiStage/New_Build/Inputs_p3/Capacity_reserve_margin.csv b/test/MultiStage/New_Build/Inputs_p3/Capacity_reserve_margin.csv new file mode 100644 index 0000000000..1cda938c80 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Capacity_reserve_margin.csv @@ -0,0 +1,2 @@ +,Network_zones,CapRes_1 +NE,z1,0.156 diff --git a/test/MultiStage/New_Build/Inputs_p3/Demand_data.csv b/test/MultiStage/New_Build/Inputs_p3/Demand_data.csv new file mode 100644 index 0000000000..473c675be1 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Demand_data.csv @@ -0,0 +1,121 @@ +Voll,Demand_Segment,Cost_of_Demand_Curtailment_per_MW,Max_Demand_Curtailment,Rep_Periods,Timesteps_per_Rep_Period,Sub_Weights,Time_Index,Demand_MW_z1 +50000,1,1,1,5,24,24.0,1,11122.0 +,,,,,,3672.0,2,10655.0 +,,,,,,5016.0,3,10441.0 +,,,,,,24.0,4,10365.0 +,,,,,,24.0,5,10639.0 +,,,,,,,6,11577.0 +,,,,,,,7,13349.0 +,,,,,,,8,14550.0 +,,,,,,,9,14922.0 +,,,,,,,10,15165.0 +,,,,,,,11,15328.0 +,,,,,,,12,15380.0 +,,,,,,,13,15275.0 +,,,,,,,14,15154.0 +,,,,,,,15,14953.0 +,,,,,,,16,14885.0 +,,,,,,,17,15340.0 +,,,,,,,18,16003.0 +,,,,,,,19,15767.0 +,,,,,,,20,15236.0 +,,,,,,,21,14663.0 +,,,,,,,22,13889.0 +,,,,,,,23,12855.0 +,,,,,,,24,11809.0 +,,,,,,,25,9702.0 +,,,,,,,26,9229.0 +,,,,,,,27,9004.0 +,,,,,,,28,8951.0 +,,,,,,,29,9188.0 +,,,,,,,30,10087.0 +,,,,,,,31,11929.0 +,,,,,,,32,13166.0 +,,,,,,,33,13504.0 +,,,,,,,34,13632.0 +,,,,,,,35,13724.0 +,,,,,,,36,13742.0 +,,,,,,,37,13665.0 +,,,,,,,38,13641.0 +,,,,,,,39,13501.0 +,,,,,,,40,13366.0 +,,,,,,,41,13376.0 +,,,,,,,42,13524.0 +,,,,,,,43,13736.0 +,,,,,,,44,14401.0 +,,,,,,,45,14006.0 +,,,,,,,46,13006.0 +,,,,,,,47,11658.0 +,,,,,,,48,10416.0 +,,,,,,,49,10219.0 +,,,,,,,50,9671.0 +,,,,,,,51,9383.0 +,,,,,,,52,9269.0 +,,,,,,,53,9483.0 +,,,,,,,54,10103.0 +,,,,,,,55,11573.0 +,,,,,,,56,13059.0 +,,,,,,,57,13905.0 +,,,,,,,58,14430.0 +,,,,,,,59,14873.0 +,,,,,,,60,15179.0 +,,,,,,,61,15323.0 +,,,,,,,62,15515.0 +,,,,,,,63,15537.0 +,,,,,,,64,15481.0 +,,,,,,,65,15485.0 +,,,,,,,66,15440.0 +,,,,,,,67,15208.0 +,,,,,,,68,15028.0 +,,,,,,,69,15221.0 +,,,,,,,70,14913.0 +,,,,,,,71,13573.0 +,,,,,,,72,12159.0 +,,,,,,,73,14935.0 +,,,,,,,74,14062.0 +,,,,,,,75,13498.0 +,,,,,,,76,13146.0 +,,,,,,,77,13178.0 +,,,,,,,78,13712.0 +,,,,,,,79,15192.0 +,,,,,,,80,17114.0 +,,,,,,,81,18656.0 +,,,,,,,82,20020.0 +,,,,,,,83,21201.0 +,,,,,,,84,22009.0 +,,,,,,,85,22567.0 +,,,,,,,86,23070.0 +,,,,,,,87,23388.0 +,,,,,,,88,23629.0 +,,,,,,,89,23770.0 +,,,,,,,90,23575.0 +,,,,,,,91,23034.0 +,,,,,,,92,22325.0 +,,,,,,,93,21921.0 +,,,,,,,94,21122.0 +,,,,,,,95,19311.0 +,,,,,,,96,17514.0 +,,,,,,,97,11232.0 +,,,,,,,98,10825.0 +,,,,,,,99,10632.0 +,,,,,,,100,10622.0 +,,,,,,,101,10948.0 +,,,,,,,102,11984.0 +,,,,,,,103,13879.0 +,,,,,,,104,14890.0 +,,,,,,,105,15134.0 +,,,,,,,106,15241.0 +,,,,,,,107,15360.0 +,,,,,,,108,15407.0 +,,,,,,,109,15385.0 +,,,,,,,110,15372.0 +,,,,,,,111,15285.0 +,,,,,,,112,15482.0 +,,,,,,,113,16544.0 +,,,,,,,114,17247.0 +,,,,,,,115,17114.0 +,,,,,,,116,16657.0 +,,,,,,,117,15936.0 +,,,,,,,118,14783.0 +,,,,,,,119,13342.0 +,,,,,,,120,12052.0 diff --git a/test/MultiStage/New_Build/Inputs_p3/Energy_share_requirement.csv b/test/MultiStage/New_Build/Inputs_p3/Energy_share_requirement.csv new file mode 100644 index 0000000000..50c97b4b39 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Energy_share_requirement.csv @@ -0,0 +1,2 @@ +,Network_zones,ESR_1,ESR_2 +NE,z1,0.259,0.348 diff --git a/test/MultiStage/New_Build/Inputs_p3/Fuels_data.csv b/test/MultiStage/New_Build/Inputs_p3/Fuels_data.csv new file mode 100644 index 0000000000..4c5f7bc799 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Fuels_data.csv @@ -0,0 +1,122 @@ +Time_Index,NG,None +0,0.05306,0.0 +1,5.28,0.0 +2,5.28,0.0 +3,5.28,0.0 +4,5.28,0.0 +5,5.28,0.0 +6,5.28,0.0 +7,5.28,0.0 +8,5.28,0.0 +9,5.28,0.0 +10,5.28,0.0 +11,5.28,0.0 +12,5.28,0.0 +13,5.28,0.0 +14,5.28,0.0 +15,5.28,0.0 +16,5.28,0.0 +17,5.28,0.0 +18,5.28,0.0 +19,5.28,0.0 +20,5.28,0.0 +21,5.28,0.0 +22,5.28,0.0 +23,5.28,0.0 +24,5.28,0.0 +25,3.69,0.0 +26,3.69,0.0 +27,3.69,0.0 +28,3.69,0.0 +29,3.69,0.0 +30,3.69,0.0 +31,3.69,0.0 +32,3.69,0.0 +33,3.69,0.0 +34,3.69,0.0 +35,3.69,0.0 +36,3.69,0.0 +37,3.69,0.0 +38,3.69,0.0 +39,3.69,0.0 +40,3.69,0.0 +41,3.69,0.0 +42,3.69,0.0 +43,3.69,0.0 +44,3.69,0.0 +45,3.69,0.0 +46,3.69,0.0 +47,3.69,0.0 +48,3.69,0.0 +49,2.23,0.0 +50,2.23,0.0 +51,2.23,0.0 +52,2.23,0.0 +53,2.23,0.0 +54,2.23,0.0 +55,2.23,0.0 +56,2.23,0.0 +57,2.23,0.0 +58,2.23,0.0 +59,2.23,0.0 +60,2.23,0.0 +61,2.23,0.0 +62,2.23,0.0 +63,2.23,0.0 +64,2.23,0.0 +65,2.23,0.0 +66,2.23,0.0 +67,2.23,0.0 +68,2.23,0.0 +69,2.23,0.0 +70,2.23,0.0 +71,2.23,0.0 +72,2.23,0.0 +73,2.34,0.0 +74,2.34,0.0 +75,2.34,0.0 +76,2.34,0.0 +77,2.34,0.0 +78,2.34,0.0 +79,2.34,0.0 +80,2.34,0.0 +81,2.34,0.0 +82,2.34,0.0 +83,2.34,0.0 +84,2.34,0.0 +85,2.34,0.0 +86,2.34,0.0 +87,2.34,0.0 +88,2.34,0.0 +89,2.34,0.0 +90,2.34,0.0 +91,2.34,0.0 +92,2.34,0.0 +93,2.34,0.0 +94,2.34,0.0 +95,2.34,0.0 +96,2.34,0.0 +97,2.74,0.0 +98,2.74,0.0 +99,2.74,0.0 +100,2.74,0.0 +101,2.74,0.0 +102,2.74,0.0 +103,2.74,0.0 +104,2.74,0.0 +105,2.74,0.0 +106,2.74,0.0 +107,2.74,0.0 +108,2.74,0.0 +109,2.74,0.0 +110,2.74,0.0 +111,2.74,0.0 +112,2.74,0.0 +113,2.74,0.0 +114,2.74,0.0 +115,2.74,0.0 +116,2.74,0.0 +117,2.74,0.0 +118,2.74,0.0 +119,2.74,0.0 +120,2.74,0.0 diff --git a/test/MultiStage/New_Build/Inputs_p3/Generators_data.csv b/test/MultiStage/New_Build/Inputs_p3/Generators_data.csv new file mode 100644 index 0000000000..d8e0ca4e9b --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Generators_data.csv @@ -0,0 +1,5 @@ +Resource,Zone,THERM,MUST_RUN,STOR,FLEX,HYDRO,VRE,Num_VRE_Bins,New_Build,Can_Retire,Existing_Cap_MW,Existing_Cap_MWh,Existing_Charge_Cap_MW,Max_Cap_MW,Max_Cap_MWh,Max_Charge_Cap_MW,Min_Cap_MW,Min_Cap_MWh,Min_Charge_Cap_MW,Inv_Cost_per_MWyr,Inv_Cost_per_MWhyr,Inv_Cost_Charge_per_MWyr,Fixed_OM_Cost_per_MWyr,Fixed_OM_Cost_per_MWhyr,Fixed_OM_Cost_Charge_per_MWyr,Var_OM_Cost_per_MWh,Var_OM_Cost_per_MWh_In,Heat_Rate_MMBTU_per_MWh,Fuel,Cap_Size,Start_Cost_per_MW,Start_Fuel_MMBTU_per_MW,Up_Time,Down_Time,Ramp_Up_Percentage,Ramp_Dn_Percentage,Hydro_Energy_to_Power_Ratio,Min_Power,Self_Disch,Eff_Up,Eff_Down,Min_Duration,Max_Duration,Max_Flexible_Demand_Advance,Max_Flexible_Demand_Delay,Flexible_Demand_Energy_Eff,Reg_Max,Rsv_Max,Reg_Cost,Rsv_Cost,MinCapTag,MinCapTag_1,MinCapTag_2,MinCapTag_3,MGA,Resource_Type,CapRes_1,ESR_1,ESR_2,region,cluster,WACC,Capital_Recovery_Period,Lifetime,Min_Retired_Cap_MW,Min_Retired_Energy_Cap_MW,Min_Retired_Charge_Cap_MW,LDS +natural_gas_combined_cycle,1,1,0,0,0,0,0,0,0,1,0,0,0,-1,-1,-1,0,0,0,65400,0,0,10287,0,0,3.55,0,7.43,NG,250,91,2,6,6,0.64,0.64,0,0.468,0,1,1,0,0,0,0,1,0.25,0.5,0,0,2,0,0,0,1,natural_gas_fired_combined_cycle,0.93,0,0,NE,1,0.039,20,20,0,0,0,0 +solar_pv,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,85300,0,0,18760,0,0,0,0,9.13,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,7,1,0,0,1,solar_photovoltaic,0.8,1,1,NE,1,0.017,20,20,0,0,0,0 +onshore_wind,1,0,0,0,0,0,1,1,1,1,0,0,0,-1,-1,-1,0,0,0,97200,0,0,43205,0,0,0.1,0,9.12,None,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,6,0,1,0,1,onshore_wind_turbine,0.8,1,1,NE,1,0.024,20,20,0,0,0,0 +battery,1,0,0,1,0,0,0,0,1,1,0,0,0,-1,-1,-1,0,0,0,19584,22494,0,4895,5622,5622,0.15,0.15,0,None,0,0,0,0,0,1,1,0,0,0,0.92,0.92,1,10,0,0,1,0,0,0,0,12,0,0,1,0,battery_mid,0.95,0,0,NE,0,0.027,20,20,0,0,0,0 diff --git a/test/MultiStage/New_Build/Inputs_p3/Generators_variability.csv b/test/MultiStage/New_Build/Inputs_p3/Generators_variability.csv new file mode 100644 index 0000000000..509dadf457 --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Generators_variability.csv @@ -0,0 +1,121 @@ +Time_Index,natural_gas_combined_cycle,solar_pv,onshore_wind,battery +1,1.0,0.0,0.523972332,1.0 +2,1.0,0.0,0.657110274,1.0 +3,1.0,0.0,0.757477045,1.0 +4,1.0,0.0,0.644009769,1.0 +5,1.0,0.0,0.467615873,1.0 +6,1.0,0.0,0.553678334,1.0 +7,1.0,0.0,0.77921623,1.0 +8,1.0,0.0,0.725531518,1.0 +9,1.0,0.0,0.786552846,1.0 +10,1.0,0.003,0.589495063,1.0 +11,1.0,0.0852,0.436854541,1.0 +12,1.0,0.1324,0.533977807,1.0 +13,1.0,0.1041,0.54939425,1.0 +14,1.0,0.1276,0.297182679,1.0 +15,1.0,0.1108,0.108885378,1.0 +16,1.0,0.0825,0.097908288,1.0 +17,1.0,0.0043,0.092191279,1.0 +18,1.0,0.0,0.112537816,1.0 +19,1.0,0.0,0.366680771,1.0 +20,1.0,0.0,0.794670165,1.0 +21,1.0,0.0,0.931621909,1.0 +22,1.0,0.0,1.0,1.0 +23,1.0,0.0,1.0,1.0 +24,1.0,0.0,1.0,1.0 +25,1.0,0.0,0.676885605,1.0 +26,1.0,0.0,0.738456726,1.0 +27,1.0,0.0,0.703836918,1.0 +28,1.0,0.0,0.697715104,1.0 +29,1.0,0.0,0.578294039,1.0 +30,1.0,0.0,0.478842616,1.0 +31,1.0,0.0,0.57159102,1.0 +32,1.0,0.0216,0.389114857,1.0 +33,1.0,0.1372,0.520889282,1.0 +34,1.0,0.3468,0.376534432,1.0 +35,1.0,0.3952,0.327963144,1.0 +36,1.0,0.4551,0.407575041,1.0 +37,1.0,0.5095,0.536571622,1.0 +38,1.0,0.5567,0.576452434,1.0 +39,1.0,0.5691,0.562025309,1.0 +40,1.0,0.4904,0.422575682,1.0 +41,1.0,0.3087,0.521396458,1.0 +42,1.0,0.1034,0.710955501,1.0 +43,1.0,0.0,0.683217525,1.0 +44,1.0,0.0,0.635520697,1.0 +45,1.0,0.0,0.5644238,1.0 +46,1.0,0.0,0.61978668,1.0 +47,1.0,0.0,0.516743779,1.0 +48,1.0,0.0,0.470443606,1.0 +49,1.0,0.0,0.500380576,1.0 +50,1.0,0.0,0.512022793,1.0 +51,1.0,0.0,0.404206336,1.0 +52,1.0,0.0,0.142279267,1.0 +53,1.0,0.0,0.133046106,1.0 +54,1.0,0.1356,0.133957967,1.0 +55,1.0,0.1041,0.041104347,1.0 +56,1.0,0.2399,0.029715812,1.0 +57,1.0,0.3785,0.064291924,1.0 +58,1.0,0.4837,0.043738909,1.0 +59,1.0,0.5323,0.056054953,1.0 +60,1.0,0.5114,0.101633437,1.0 +61,1.0,0.5175,0.238559932,1.0 +62,1.0,0.5099,0.194997847,1.0 +63,1.0,0.502,0.190832943,1.0 +64,1.0,0.4113,0.26438266,1.0 +65,1.0,0.3017,0.273810387,1.0 +66,1.0,0.1773,0.195969075,1.0 +67,1.0,0.0811,0.235671312,1.0 +68,1.0,0.0006,0.188544422,1.0 +69,1.0,0.0,0.179863051,1.0 +70,1.0,0.0,0.223087296,1.0 +71,1.0,0.0,0.457369655,1.0 +72,1.0,0.0,0.715852976,1.0 +73,1.0,0.0,0.280310601,1.0 +74,1.0,0.0,0.603805244,1.0 +75,1.0,0.0,0.741859972,1.0 +76,1.0,0.0,0.44207269,1.0 +77,1.0,0.0,0.534612,1.0 +78,1.0,0.0259,0.587511122,1.0 +79,1.0,0.096,0.48241505,1.0 +80,1.0,0.2133,0.226682097,1.0 +81,1.0,0.3624,0.376575917,1.0 +82,1.0,0.4795,0.272142261,1.0 +83,1.0,0.5633,0.132447034,1.0 +84,1.0,0.5708,0.091180928,1.0 +85,1.0,0.534,0.420845181,1.0 +86,1.0,0.5641,0.543866694,1.0 +87,1.0,0.5537,0.943579316,1.0 +88,1.0,0.457,0.83001256,1.0 +89,1.0,0.3439,0.698711514,1.0 +90,1.0,0.1642,0.536995411,1.0 +91,1.0,0.0638,0.770702124,1.0 +92,1.0,0.0,0.569594324,1.0 +93,1.0,0.0,0.668922722,1.0 +94,1.0,0.0,0.759383678,1.0 +95,1.0,0.0,0.672967851,1.0 +96,1.0,0.0,0.861851215,1.0 +97,1.0,0.0,0.000154842,1.0 +98,1.0,0.0,5.75e-5,1.0 +99,1.0,0.0,7.18e-5,1.0 +100,1.0,0.0,3.65e-5,1.0 +101,1.0,0.0,3.0e-5,1.0 +102,1.0,0.0,0.0,1.0 +103,1.0,0.0,0.000772537,1.0 +104,1.0,0.0,0.000930232,1.0 +105,1.0,0.1029,0.000778525,1.0 +106,1.0,0.2427,0.000131503,1.0 +107,1.0,0.3353,0.005792293,1.0 +108,1.0,0.3693,0.00257458,1.0 +109,1.0,0.321,1.01e-5,1.0 +110,1.0,0.2798,0.000134685,1.0 +111,1.0,0.2887,0.000516413,1.0 +112,1.0,0.1717,0.001232307,1.0 +113,1.0,0.0,0.002655152,1.0 +114,1.0,0.0,0.003173271,1.0 +115,1.0,0.0,0.003878384,1.0 +116,1.0,0.0,0.005781263,1.0 +117,1.0,0.0,0.006259252,1.0 +118,1.0,0.0,0.008088858,1.0 +119,1.0,0.0,0.008165604,1.0 +120,1.0,0.0,0.007110484,1.0 diff --git a/test/MultiStage/New_Build/Inputs_p3/Minimum_capacity_requirement.csv b/test/MultiStage/New_Build/Inputs_p3/Minimum_capacity_requirement.csv new file mode 100644 index 0000000000..8593a5abcc --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Minimum_capacity_requirement.csv @@ -0,0 +1,4 @@ +MinCapReqConstraint,ConstraintDescription,Min_MW +1,PV,5000 +2,Wind,10000 +3,Batteries,6000 diff --git a/test/MultiStage/New_Build/Inputs_p3/Period_map.csv b/test/MultiStage/New_Build/Inputs_p3/Period_map.csv new file mode 100644 index 0000000000..72f49e820b --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Period_map.csv @@ -0,0 +1,366 @@ +Period_Index,Rep_Period,Rep_Period_Index +1,72,2 +2,72,2 +3,72,2 +4,72,2 +5,72,2 +6,72,2 +7,72,2 +8,72,2 +9,72,2 +10,72,2 +11,72,2 +12,72,2 +13,72,2 +14,72,2 +15,72,2 +16,72,2 +17,72,2 +18,72,2 +19,72,2 +20,72,2 +21,72,2 +22,72,2 +23,72,2 +24,72,2 +25,72,2 +26,72,2 +27,27,1 +28,72,2 +29,72,2 +30,72,2 +31,72,2 +32,72,2 +33,72,2 +34,72,2 +35,72,2 +36,72,2 +37,72,2 +38,72,2 +39,72,2 +40,72,2 +41,72,2 +42,72,2 +43,72,2 +44,72,2 +45,72,2 +46,72,2 +47,72,2 +48,72,2 +49,72,2 +50,72,2 +51,72,2 +52,72,2 +53,72,2 +54,72,2 +55,72,2 +56,72,2 +57,72,2 +58,72,2 +59,72,2 +60,72,2 +61,72,2 +62,72,2 +63,72,2 +64,72,2 +65,72,2 +66,72,2 +67,72,2 +68,72,2 +69,72,2 +70,72,2 +71,72,2 +72,72,2 +73,72,2 +74,72,2 +75,72,2 +76,72,2 +77,72,2 +78,72,2 +79,72,2 +80,72,2 +81,72,2 +82,72,2 +83,72,2 +84,72,2 +85,72,2 +86,72,2 +87,72,2 +88,72,2 +89,72,2 +90,72,2 +91,72,2 +92,72,2 +93,72,2 +94,72,2 +95,72,2 +96,72,2 +97,72,2 +98,72,2 +99,72,2 +100,72,2 +101,72,2 +102,72,2 +103,72,2 +104,72,2 +105,72,2 +106,72,2 +107,72,2 +108,72,2 +109,170,3 +110,72,2 +111,72,2 +112,72,2 +113,72,2 +114,72,2 +115,72,2 +116,72,2 +117,72,2 +118,72,2 +119,72,2 +120,72,2 +121,72,2 +122,170,3 +123,170,3 +124,170,3 +125,170,3 +126,170,3 +127,170,3 +128,170,3 +129,170,3 +130,170,3 +131,170,3 +132,170,3 +133,170,3 +134,170,3 +135,170,3 +136,170,3 +137,170,3 +138,170,3 +139,170,3 +140,170,3 +141,170,3 +142,170,3 +143,170,3 +144,170,3 +145,170,3 +146,170,3 +147,170,3 +148,170,3 +149,170,3 +150,170,3 +151,170,3 +152,170,3 +153,170,3 +154,170,3 +155,170,3 +156,170,3 +157,170,3 +158,170,3 +159,170,3 +160,170,3 +161,170,3 +162,170,3 +163,170,3 +164,170,3 +165,170,3 +166,170,3 +167,170,3 +168,170,3 +169,170,3 +170,170,3 +171,170,3 +172,170,3 +173,170,3 +174,170,3 +175,170,3 +176,170,3 +177,170,3 +178,170,3 +179,170,3 +180,170,3 +181,170,3 +182,170,3 +183,170,3 +184,170,3 +185,170,3 +186,170,3 +187,170,3 +188,170,3 +189,170,3 +190,170,3 +191,170,3 +192,170,3 +193,170,3 +194,170,3 +195,170,3 +196,170,3 +197,170,3 +198,198,4 +199,170,3 +200,170,3 +201,170,3 +202,170,3 +203,170,3 +204,170,3 +205,170,3 +206,170,3 +207,170,3 +208,170,3 +209,170,3 +210,170,3 +211,170,3 +212,170,3 +213,170,3 +214,170,3 +215,170,3 +216,170,3 +217,170,3 +218,170,3 +219,170,3 +220,170,3 +221,170,3 +222,170,3 +223,170,3 +224,170,3 +225,170,3 +226,170,3 +227,170,3 +228,170,3 +229,170,3 +230,170,3 +231,170,3 +232,170,3 +233,170,3 +234,170,3 +235,170,3 +236,170,3 +237,170,3 +238,170,3 +239,170,3 +240,170,3 +241,170,3 +242,170,3 +243,170,3 +244,170,3 +245,170,3 +246,170,3 +247,170,3 +248,170,3 +249,170,3 +250,170,3 +251,170,3 +252,170,3 +253,170,3 +254,170,3 +255,170,3 +256,170,3 +257,170,3 +258,170,3 +259,170,3 +260,170,3 +261,170,3 +262,170,3 +263,170,3 +264,170,3 +265,170,3 +266,170,3 +267,170,3 +268,170,3 +269,170,3 +270,170,3 +271,170,3 +272,170,3 +273,170,3 +274,170,3 +275,170,3 +276,170,3 +277,170,3 +278,170,3 +279,170,3 +280,170,3 +281,170,3 +282,170,3 +283,170,3 +284,170,3 +285,170,3 +286,170,3 +287,170,3 +288,170,3 +289,170,3 +290,170,3 +291,170,3 +292,170,3 +293,170,3 +294,170,3 +295,170,3 +296,170,3 +297,170,3 +298,170,3 +299,170,3 +300,170,3 +301,170,3 +302,170,3 +303,170,3 +304,170,3 +305,170,3 +306,170,3 +307,72,2 +308,72,2 +309,170,3 +310,170,3 +311,170,3 +312,72,2 +313,170,3 +314,170,3 +315,170,3 +316,170,3 +317,170,3 +318,170,3 +319,170,3 +320,170,3 +321,170,3 +322,170,3 +323,170,3 +324,170,3 +325,170,3 +326,170,3 +327,170,3 +328,72,2 +329,170,3 +330,170,3 +331,331,5 +332,170,3 +333,170,3 +334,170,3 +335,170,3 +336,72,2 +337,72,2 +338,72,2 +339,72,2 +340,72,2 +341,72,2 +342,72,2 +343,72,2 +344,72,2 +345,72,2 +346,72,2 +347,72,2 +348,72,2 +349,72,2 +350,72,2 +351,72,2 +352,72,2 +353,72,2 +354,72,2 +355,72,2 +356,72,2 +357,72,2 +358,72,2 +359,72,2 +360,72,2 +361,72,2 +362,72,2 +363,72,2 +364,72,2 +365,72,2 diff --git a/test/MultiStage/New_Build/Inputs_p3/Reserves.csv b/test/MultiStage/New_Build/Inputs_p3/Reserves.csv new file mode 100644 index 0000000000..b495df0dea --- /dev/null +++ b/test/MultiStage/New_Build/Inputs_p3/Reserves.csv @@ -0,0 +1,2 @@ +Reg_Req_Percent_Demand,Reg_Req_Percent_VRE,Rsv_Req_Percent_Demand,Rsv_Req_Percent_VRE,Unmet_Rsv_Penalty_Dollar_per_MW,Dynamic_Contingency,Static_Contingency_MW +0.01,0.0032,0.033,0.0795,1000,0,0 diff --git a/test/MultiStage/New_Build/highs_settings.yml b/test/MultiStage/New_Build/highs_settings.yml new file mode 100644 index 0000000000..e520dfbef7 --- /dev/null +++ b/test/MultiStage/New_Build/highs_settings.yml @@ -0,0 +1,12 @@ +# HiGHS Solver Parameters +# Common solver settings +Feasib_Tol: 1.0e-05 # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07] +Optimal_Tol: 1.0e-05 # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07] +TimeLimit: 1.0e23 # Time limit # [type: double, advanced: false, range: [0, inf], default: inf] +Pre_Solve: on # Presolve option: "off", "choose" or "on" # [type: string, advanced: false, default: "choose"] +Method: ipm # HiGHS-specific solver settings # Solver option: "simplex", "choose" or "ipm" # [type: string, advanced: false, default: "choose"] +ipm_optimality_tolerance: 1e-04 + +# run the crossover routine for ipx +# [type: string, advanced: "on", range: {"off", "on"}, default: "off"] +run_crossover: "on" diff --git a/test/ThreeZones/Network.csv b/test/ThreeZones/Network.csv index 5cca655c66..c6413479ff 100644 --- a/test/ThreeZones/Network.csv +++ b/test/ThreeZones/Network.csv @@ -1,4 +1,4 @@ -,Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 -MA,z1,1,1,-1,0,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 -CT,z2,2,1,0,-1,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 -ME,z3,,,,,,,,,,,,, \ No newline at end of file +,Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,transmission_path_name,distance_mile,Line_Loss_Percentage,Line_Max_Reinforcement_MW,Line_Reinforcement_Cost_per_MWyr,DerateCapRes_1,CapRes_1,CapRes_Excl_1 +MA,z1,1,1,2,2950,MA_to_CT,123.0584,0.012305837,2950,12060,0.95,0,0 +CT,z2,2,1,3,2000,MA_to_ME,196.5385,0.019653847,2000,19261,0.95,0,0 +ME,z3,,,,,,,,,,,, diff --git a/test/VREStor/Network.csv b/test/VREStor/Network.csv index c286cebd00..1a7000a3b6 100644 --- a/test/VREStor/Network.csv +++ b/test/VREStor/Network.csv @@ -1,4 +1,4 @@ -Network_zones,Network_Lines,z1,z2,z3,Line_Max_Flow_MW,Line_Min_Flow_MW,transmission_path_name,Line_Reinforcement_Cost_per_MWyr,Line_Reinforcement_Cost_per_MW,Line_Loss_Percentage,Line_Max_Reinforcement_MW,DerateCapRes_1,CapRes_Excl_1,DerateCapRes_2,CapRes_Excl_2,DerateCapRes_3,CapRes_Excl_3 -z1,1.0,1.0,-1.0,0.0,820.0,820.0,EIC_to_TRE,45958.0,948772.0,0.0649,410.0,0.95,0.0,0.95,0.0,0.95,0.0 -z2,2.0,1.0,0.0,-1.0,1830.0,1830.0,EIC_to_WECC,71600.0,1478140.0,0.1001,915.0,0.95,0.0,0.95,0.0,0.95,0.0 -z3,,,,,,,,,,,,,,,,, +Network_zones,Network_Lines,Start_Zone,End_Zone,Line_Max_Flow_MW,Line_Min_Flow_MW,transmission_path_name,Line_Reinforcement_Cost_per_MWyr,Line_Reinforcement_Cost_per_MW,Line_Loss_Percentage,Line_Max_Reinforcement_MW,DerateCapRes_1,CapRes_Excl_1,DerateCapRes_2,CapRes_Excl_2,DerateCapRes_3,CapRes_Excl_3 +z1,1.0,1,2,820.0,820.0,EIC_to_TRE,45958.0,948772.0,0.0649,410.0,0.95,0.0,0.95,0.0,0.95,0.0 +z2,2.0,1,3,1830.0,1830.0,EIC_to_WECC,71600.0,1478140.0,0.1001,915.0,0.95,0.0,0.95,0.0,0.95,0.0 +z3,,,,,,,,,,,,,,,, diff --git a/test/expression_manipulation_test.jl b/test/expression_manipulation_test.jl index c0a3fb8d39..aae5d442ec 100644 --- a/test/expression_manipulation_test.jl +++ b/test/expression_manipulation_test.jl @@ -116,6 +116,32 @@ let @test sum_disjoint_expr() == true @test sum_combo_expr() == true + # Test add_term_to_expression! for variable + @variable(EP, single_var >= 0) + GenX.add_term_to_expression!(EP[:large_expr], single_var) + @test EP[:large_expr][100] == test_var[100] + 22.0 + single_var + + # Test extracting some rows from a 2D matrix variable + columns = 10 + @variable(EP, var_matrix[row in 1:4, col in 1:columns]) + rows_to_extract = [3, 4] + expr = GenX.extract_time_series_to_expression(var_matrix, rows_to_extract) + @test size(expr) == (length(rows_to_extract), columns) + @test expr isa JuMP.Containers.DenseAxisArray + @test eltype(expr.data) == AffExpr + @test expr.axes[1] == rows_to_extract + @test expr.axes[2] == 1:columns + unregister(EP, :var_matrix) + + # Test extracting some rows from a 2D dense axis array variable + @variable(EP, var_denseaxisarray[row in [1, 3, 5, 11], col in 1:columns]) + rows_to_extract = [3, 5] + expr = GenX.extract_time_series_to_expression(var_denseaxisarray, rows_to_extract) + @test size(expr) == (length(rows_to_extract), columns) + @test expr isa JuMP.Containers.DenseAxisArray + @test expr.axes[1] == rows_to_extract + @test expr.axes[2] == 1:columns + unregister(EP, :var_denseaxisarray) end ###### ###### ###### ###### ###### ###### ###### diff --git a/test/test_multistage.jl b/test/test_multistage.jl index 4c6a8d4600..8624251e19 100644 --- a/test/test_multistage.jl +++ b/test/test_multistage.jl @@ -5,7 +5,7 @@ using Test include(joinpath(@__DIR__, "utilities.jl")) obj_true = [79734.80032, 41630.03494, 27855.20631] -test_path = "MultiStage" +test_path = joinpath(@__DIR__,"MultiStage"); # Define test inputs multistage_setup = Dict( @@ -58,4 +58,55 @@ obj_test = round_from_tol!.(obj_test, optimal_tol) optimal_tol = round_from_tol!.(optimal_tol, optimal_tol) write_testlog(test_path, obj_test, optimal_tol, test_result) +function test_new_build(EP::Dict,inputs::Dict) + ### Test that the resource with New_Build = 0 did not expand capacity + a = true; + + for t in keys(EP) + if t==1 + a = value(EP[t][:eTotalCap][1]) <= inputs[1]["dfGen"][1,:Existing_Cap_MW][1] + else + a = value(EP[t][:eTotalCap][1]) <= value(EP[t-1][:eTotalCap][1]) + end + if a==false + break + end + end + + return a +end + +function test_can_retire(EP::Dict,inputs::Dict) + ### Test that the resource with Can_Retire = 0 did not retire capacity + a = true; + + for t in keys(EP) + if t==1 + a = value(EP[t][:eTotalCap][1]) >= inputs[1]["dfGen"][1,:Existing_Cap_MW][1] + else + a = value(EP[t][:eTotalCap][1]) >= value(EP[t-1][:eTotalCap][1]) + end + if a==false + break + end + end + + return a +end + +test_path_new_build = joinpath(@__DIR__,"MultiStage","New_Build"); +EP, inputs, _ = redirect_stdout(devnull) do + run_genx_case_testing(test_path_new_build, genx_setup); +end + +new_build_test_result = @test test_new_build(EP,inputs) +write_testlog(test_path_new_build,"Testing that the resource with New_Build = 0 did not expand capacity",new_build_test_result) + +test_path_can_retire = joinpath(@__DIR__,"MultiStage","Can_Retire"); +EP, inputs, _ = redirect_stdout(devnull) do + run_genx_case_testing(test_path_can_retire, genx_setup); +end +can_retire_test_result = @test test_can_retire(EP,inputs) +write_testlog(test_path_can_retire,"Testing that the resource with Can_Retire = 0 did not expand capacity",can_retire_test_result) + end # module TestMultiStage