From a7ae6baf7ef440aebac43b9a81662ff9c1934475 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Thu, 16 Nov 2023 13:05:37 -0500 Subject: [PATCH 01/19] Separate reserves into creation and constraints (#580) Divide the core Reserves functionality into 1. variable and expression creation 2. constraint application This makes the module more like the CapacityReserveMargin or MinCapReq policies, allowing the expressions to be modified before constraints are applied. --- src/model/core/reserves.jl | 61 ++++++++++++++++++++++++------------- src/model/generate_model.jl | 10 ++++-- 2 files changed, 47 insertions(+), 24 deletions(-) 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/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 From 2ef54dcd2c484ffc83b4e74b7394be85ac13475f Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Sat, 18 Nov 2023 15:19:55 -0500 Subject: [PATCH 02/19] Refactor reserves (#562) This fixes #573, where Reserves + Num_VRE_Bins > 1 would lead to the VRE_NO_POWER_OUT resources being able to contribute an infinite amount to the reserves. This fixes #574, where VRE power output constraints were being applied length(VRE) times to all VRE resources, when Reserves = 1. This fixed #566, where some constraints in storage_symmetric were redundant. --------- Co-authored-by: Luca Bonaldo <39280783+lbonaldo@users.noreply.github.com> --- src/model/expression_manipulation.jl | 29 ++- .../curtailable_variable_renewable.jl | 131 ++++++------ src/model/resources/hydro/hydro_res.jl | 55 ++--- src/model/resources/storage/storage_all.jl | 190 ++++++------------ .../resources/storage/storage_asymmetric.jl | 38 ++-- .../resources/storage/storage_symmetric.jl | 136 +++---------- src/model/resources/thermal/thermal_commit.jl | 88 +++----- .../resources/thermal/thermal_no_commit.jl | 85 +++----- test/expression_manipulation_test.jl | 22 ++ 9 files changed, 282 insertions(+), 492 deletions(-) diff --git a/src/model/expression_manipulation.jl b/src/model/expression_manipulation.jl index 20b9474ceb..16cfc0cc65 100644 --- a/src/model/expression_manipulation.jl +++ b/src/model/expression_manipulation.jl @@ -47,6 +47,33 @@ function fill_with_const!(arr::Array{GenericAffExpr{C,T}, dims}, con::Real) wher 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 @@ -141,4 +168,4 @@ end function sum_expression(expr::AbstractArray{AbstractJuMPScalar, dims}) where {dims} return _sum_expression(expr) -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/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..47949bb557 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""" 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/test/expression_manipulation_test.jl b/test/expression_manipulation_test.jl index 1771f0d144..a83c234a7b 100644 --- a/test/expression_manipulation_test.jl +++ b/test/expression_manipulation_test.jl @@ -53,6 +53,28 @@ let @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 ###### ###### ###### ###### ###### ###### ###### From 861c714cd10a0f927bcc53dba123ba1a76642e58 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Mon, 20 Nov 2023 11:36:37 -0500 Subject: [PATCH 03/19] Allow ability to scale written timeseries outputs. (#581) --- src/write_outputs/write_maintenance.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 32b3836daa995af78f14c16c1e86d5ed7aa011b3 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Wed, 22 Nov 2023 12:15:29 -0500 Subject: [PATCH 04/19] Add method to calculate locational marginal prices (#582) --- src/write_outputs/write_charging_cost.jl | 16 +++++++++------- src/write_outputs/write_energy_revenue.jl | 9 +++++---- src/write_outputs/write_price.jl | 22 ++++++++++++++++++++-- 3 files changed, 34 insertions(+), 13 deletions(-) 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_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 From 9dcec7dc5eb92cc5027aa97df09298819d29656c Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Wed, 22 Nov 2023 14:20:44 -0500 Subject: [PATCH 05/19] Fix #567: apply min/max power for electrolyzers (#583) --- src/model/resources/hydrogen/electrolyzer.jl | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) 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 From 1033fff9a2db83f8317805ebf8c3baefc043d137 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 28 Nov 2023 10:46:43 -0500 Subject: [PATCH 06/19] Refactor write_capacity_value (#585) Co-authored-by: Luca Bonaldo <39280783+lbonaldo@users.noreply.github.com> --- .../write_capacity_value.jl | 132 ++++++++++++------ 1 file changed, 87 insertions(+), 45 deletions(-) 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..a8f6b2fc58 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,90 @@ 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] = crm_derate(i, 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 From d1c6fa0c13a571244be8bda8a48af281f8c127b0 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Wed, 29 Nov 2023 18:19:39 -0500 Subject: [PATCH 07/19] Fix DimensionMismatch error (#588) This is a followup to #585, to fix a previously un-tested bug. --- .../capacity_reserve_margin/write_capacity_value.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a8f6b2fc58..1acae4ee7f 100644 --- a/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl +++ b/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl @@ -48,7 +48,7 @@ function write_capacity_value(path::AbstractString, inputs::Dict, setup::Dict, E power(y::Vector{Int}) = value.(EP[:vP][y, riskyhour])' - capvalue[riskyhour, THERM_ALL_EX] = crm_derate(i, THERM_ALL_EX) + capvalue[riskyhour, THERM_ALL_EX] .= crm_derate(i, THERM_ALL_EX) capvalue[riskyhour, VRE_EX] = crm_derate(i, VRE_EX) .* max_power(riskyhour, VRE_EX) From 5727636eccad21d22a8dc5dda7e762f3b208caea Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Fri, 1 Dec 2023 10:24:28 -0500 Subject: [PATCH 08/19] Output correct CRM values for THERM plants with maintenance (#589) --- src/model/resources/thermal/thermal_commit.jl | 19 +++++-- .../effective_capacity.jl | 54 +++++++++++++++++++ .../write_capacity_value.jl | 3 +- .../write_reserve_margin_revenue.jl | 8 +-- 4 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 src/write_outputs/capacity_reserve_margin/effective_capacity.jl diff --git a/src/model/resources/thermal/thermal_commit.jl b/src/model/resources/thermal/thermal_commit.jl index 47949bb557..b654f098ca 100644 --- a/src/model/resources/thermal/thermal_commit.jl +++ b/src/model/resources/thermal/thermal_commit.jl @@ -361,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/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 1acae4ee7f..cbefad6c83 100644 --- a/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl +++ b/src/write_outputs/capacity_reserve_margin/write_capacity_value.jl @@ -48,7 +48,7 @@ function write_capacity_value(path::AbstractString, inputs::Dict, setup::Dict, E power(y::Vector{Int}) = value.(EP[:vP][y, riskyhour])' - capvalue[riskyhour, THERM_ALL_EX] .= crm_derate(i, THERM_ALL_EX) + 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) @@ -121,3 +121,4 @@ function capacity_reserve_margin_price(EP::Model, inputs::Dict, setup::Dict, cap 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..f40877ac78 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,9 +32,10 @@ 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"] / scale_factor 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[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, :] * (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, :]))) @@ -52,9 +54,7 @@ function write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup: 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 - end + tempresrev *= scale_factor^2 annual_sum .+= tempresrev dfResRevenue = hcat(dfResRevenue, DataFrame([tempresrev], [sym])) end From fa8aefc4f5065a714d44a9e9b85e5d46be15045f Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 10:54:18 -0500 Subject: [PATCH 09/19] use maxlog=1 (#592) --- src/configure_settings/configure_settings.jl | 2 +- src/load_inputs/load_generators_data.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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} From 54ef23ade17e029c279adf00c074cb09d1deb09c Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 10:57:52 -0500 Subject: [PATCH 10/19] Prefer columns-style network format to matrix format (#591) The matrix-style input in Network.csv is now deprecated. Instead, use `Start_Zone`, `End_Zone` columns with zone numbers of the two ends of each line. To translate: the column of the former `1` goes in Start_Zone, and the column of the former `-1` goes in End_Zone. --- .../ISONE_Trizone/Network.csv | 8 +++---- .../ISONE_Trizone_FullTimeseries/Network.csv | 8 +++---- .../Inputs/Inputs_p1/Network.csv | 8 +++---- .../Inputs/Inputs_p2/Network.csv | 8 +++---- .../Inputs/Inputs_p3/Network.csv | 8 +++---- .../Network.csv | 8 +++---- .../SmallNewEngland/ThreeZones/Network.csv | 8 +++---- .../Inputs/Inputs_p1/Network.csv | 8 +++---- .../Inputs/Inputs_p2/Network.csv | 8 +++---- .../Inputs/Inputs_p3/Network.csv | 8 +++---- .../Network.csv | 8 +++---- Example_Systems/VREStor_Example/Network.csv | 8 +++---- docs/src/data_documentation.md | 18 +++++++------- docs/src/model_notation.md | 2 +- src/load_inputs/load_network_data.jl | 24 ++++++++++++++----- test/ThreeZones/Network.csv | 8 +++---- test/VREStor/Network.csv | 8 +++---- 17 files changed, 84 insertions(+), 72 deletions(-) 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/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/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,,,,,,,,,,,,,,,, From dcb98a362029b80b49d2137117d2e81f4ba8bbe2 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 11:33:21 -0500 Subject: [PATCH 11/19] Minor refactor of write_esr_revenue (#593) * remove a defunct comment * add new column directly rather than use hcat and a rename! * 'price' as variable rather than multiple df accesses --- .../write_esr_revenue.jl | 36 ++++++++++--------- src/write_outputs/write_net_revenue.jl | 2 +- 2 files changed, 20 insertions(+), 18 deletions(-) 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/write_net_revenue.jl b/src/write_outputs/write_net_revenue.jl index fd1d473c45..a5c39b21aa 100644 --- a/src/write_outputs/write_net_revenue.jl +++ b/src/write_outputs/write_net_revenue.jl @@ -132,7 +132,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 From 0a35ba2f5579682abc4cee51f1bd476a4942b213 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 18:14:43 -0500 Subject: [PATCH 12/19] Update changelog for #591 (#595) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ab2ba877..7a6db097cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,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 From 090feccf70c55b75cc2e799b752ba3d1d8ab4ee8 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 18:18:20 -0500 Subject: [PATCH 13/19] Fix #559: report electrolyzer power per-zone (#596) Previously, electrolyzers reported their power as if they were in every zone. --- src/write_outputs/write_power_balance.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 From 68514b057f02c5dab4eaa7a4f7391248b7e63d9c Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 5 Dec 2023 18:21:03 -0500 Subject: [PATCH 14/19] Correctly write and scale unmet reserve output (#594) This also correctly scales the 'Total' column. --- CHANGELOG.md | 2 ++ src/write_outputs/reserves/write_rsv.jl | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a6db097cb..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). 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) From 838c5c5c4cd5860393814a85b0c336ea12c78c81 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Wed, 6 Dec 2023 14:18:14 -0500 Subject: [PATCH 15/19] use weighted_price in write_reserve_margin_revenue (#597) minor cleanup --- .../write_reserve_margin_revenue.jl | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) 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 f40877ac78..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 @@ -32,29 +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"] / scale_factor + weighted_price = capacity_reserve_margin_price(EP, inputs, setup, i) .* inputs["omega"] sym = Symbol("CapRes_$i") tempresrev = zeros(G) 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, :] * (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[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, :]))) + 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^2 + tempresrev *= scale_factor annual_sum .+= tempresrev dfResRevenue = hcat(dfResRevenue, DataFrame([tempresrev], [sym])) end From 783f7cd7b6fab53f3a0c4c56ea582b206ee88017 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Tue, 12 Dec 2023 15:44:43 -0500 Subject: [PATCH 16/19] Use scale_factor in write_min/max_capacity_requirement.jl (#599) Symmetrize the two functions and eliminate extra calls to setup["ParameterScale"] --- .../write_maximum_capacity_requirement.jl | 3 --- .../write_minimum_capacity_requirement.jl | 20 +++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) 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 From fa5f5b86d3818239b06c3e75059971437a2787d3 Mon Sep 17 00:00:00 2001 From: Jacob Schwartz Date: Fri, 22 Dec 2023 11:10:47 -0500 Subject: [PATCH 17/19] Fix 485, 571 asymmetric storage STOR=2 NetRevenue (#602) Add columns for Inv_Cost_Charge_MW and Fixed_OM_Cost_Charge_MW in NetRevenue.csv, and adds them to the total Costs. --- src/write_outputs/write_net_revenue.jl | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/write_outputs/write_net_revenue.jl b/src/write_outputs/write_net_revenue.jl index a5c39b21aa..5babd67e2d 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 @@ -169,7 +175,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) From a15e37f27d6bc377d62375ea5ae5106813f8ee49 Mon Sep 17 00:00:00 2001 From: Filippo Pecci Date: Mon, 8 Jan 2024 17:31:56 -0500 Subject: [PATCH 18/19] Fixed issue #605 (#609) * Fixed issue #605 by tracking capacity between stages for all generators with either New_Build=1 or Can_Retire=1. --- src/multi_stage/dual_dynamic_programming.jl | 6 +- src/multi_stage/endogenous_retirement.jl | 5 - .../Can_Retire/Inputs_p1/CO2_cap.csv | 2 + .../Inputs_p1/Capacity_reserve_margin.csv | 2 + .../Can_Retire/Inputs_p1/Demand_data.csv | 121 ++++++ .../Inputs_p1/Energy_share_requirement.csv | 2 + .../Can_Retire/Inputs_p1/Fuels_data.csv | 122 ++++++ .../Can_Retire/Inputs_p1/Generators_data.csv | 5 + .../Inputs_p1/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../Can_Retire/Inputs_p1/Period_map.csv | 366 ++++++++++++++++++ .../Can_Retire/Inputs_p1/Reserves.csv | 2 + .../Can_Retire/Inputs_p2/CO2_cap.csv | 2 + .../Inputs_p2/Capacity_reserve_margin.csv | 2 + .../Can_Retire/Inputs_p2/Demand_data.csv | 121 ++++++ .../Inputs_p2/Energy_share_requirement.csv | 2 + .../Can_Retire/Inputs_p2/Fuels_data.csv | 122 ++++++ .../Can_Retire/Inputs_p2/Generators_data.csv | 5 + .../Inputs_p2/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../Can_Retire/Inputs_p2/Period_map.csv | 366 ++++++++++++++++++ .../Can_Retire/Inputs_p2/Reserves.csv | 2 + .../Can_Retire/Inputs_p3/CO2_cap.csv | 2 + .../Inputs_p3/Capacity_reserve_margin.csv | 2 + .../Can_Retire/Inputs_p3/Demand_data.csv | 121 ++++++ .../Inputs_p3/Energy_share_requirement.csv | 2 + .../Can_Retire/Inputs_p3/Fuels_data.csv | 122 ++++++ .../Can_Retire/Inputs_p3/Generators_data.csv | 5 + .../Inputs_p3/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../Can_Retire/Inputs_p3/Period_map.csv | 366 ++++++++++++++++++ .../Can_Retire/Inputs_p3/Reserves.csv | 2 + test/MultiStage/Can_Retire/highs_settings.yml | 12 + .../New_Build/Inputs_p1/CO2_cap.csv | 2 + .../Inputs_p1/Capacity_reserve_margin.csv | 2 + .../New_Build/Inputs_p1/Demand_data.csv | 121 ++++++ .../Inputs_p1/Energy_share_requirement.csv | 2 + .../New_Build/Inputs_p1/Fuels_data.csv | 122 ++++++ .../New_Build/Inputs_p1/Generators_data.csv | 5 + .../Inputs_p1/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../New_Build/Inputs_p1/Period_map.csv | 366 ++++++++++++++++++ .../New_Build/Inputs_p1/Reserves.csv | 2 + .../New_Build/Inputs_p2/CO2_cap.csv | 2 + .../Inputs_p2/Capacity_reserve_margin.csv | 2 + .../New_Build/Inputs_p2/Demand_data.csv | 121 ++++++ .../Inputs_p2/Energy_share_requirement.csv | 2 + .../New_Build/Inputs_p2/Fuels_data.csv | 122 ++++++ .../New_Build/Inputs_p2/Generators_data.csv | 5 + .../Inputs_p2/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../New_Build/Inputs_p2/Period_map.csv | 366 ++++++++++++++++++ .../New_Build/Inputs_p2/Reserves.csv | 2 + .../New_Build/Inputs_p3/CO2_cap.csv | 2 + .../Inputs_p3/Capacity_reserve_margin.csv | 2 + .../New_Build/Inputs_p3/Demand_data.csv | 121 ++++++ .../Inputs_p3/Energy_share_requirement.csv | 2 + .../New_Build/Inputs_p3/Fuels_data.csv | 122 ++++++ .../New_Build/Inputs_p3/Generators_data.csv | 5 + .../Inputs_p3/Generators_variability.csv | 121 ++++++ .../Minimum_capacity_requirement.csv | 4 + .../New_Build/Inputs_p3/Period_map.csv | 366 ++++++++++++++++++ .../New_Build/Inputs_p3/Reserves.csv | 2 + test/MultiStage/New_Build/highs_settings.yml | 12 + test/test_multistage.jl | 53 ++- 65 files changed, 4561 insertions(+), 9 deletions(-) create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/CO2_cap.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Demand_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Energy_share_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Fuels_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Generators_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Generators_variability.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Period_map.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p1/Reserves.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/CO2_cap.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Demand_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Energy_share_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Fuels_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Generators_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Generators_variability.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Period_map.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p2/Reserves.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/CO2_cap.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Demand_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Energy_share_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Fuels_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Generators_data.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Generators_variability.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Period_map.csv create mode 100644 test/MultiStage/Can_Retire/Inputs_p3/Reserves.csv create mode 100644 test/MultiStage/Can_Retire/highs_settings.yml create mode 100644 test/MultiStage/New_Build/Inputs_p1/CO2_cap.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Demand_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Energy_share_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Fuels_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Generators_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Generators_variability.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Period_map.csv create mode 100644 test/MultiStage/New_Build/Inputs_p1/Reserves.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/CO2_cap.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Demand_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Energy_share_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Fuels_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Generators_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Generators_variability.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Period_map.csv create mode 100644 test/MultiStage/New_Build/Inputs_p2/Reserves.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/CO2_cap.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Capacity_reserve_margin.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Demand_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Energy_share_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Fuels_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Generators_data.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Generators_variability.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Minimum_capacity_requirement.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Period_map.csv create mode 100644 test/MultiStage/New_Build/Inputs_p3/Reserves.csv create mode 100644 test/MultiStage/New_Build/highs_settings.yml 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/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/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 From 66ba310b9ca38f1f19c55e07c0ad6c4b66a200cf Mon Sep 17 00:00:00 2001 From: "Chakrabarti, Sambuddha (Sam)" Date: Fri, 12 Jan 2024 20:34:05 -0500 Subject: [PATCH 19/19] =?UTF-8?q?Crunching=20the=20mass-based=20and=20dema?= =?UTF-8?q?nd-rate=20based=20into=20one=20expression=20in=E2=80=A6=20(#610?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Crunching the mass-based and demand-rate based into one expression in write_net_revenue.jl The expressions are exactly the same --- src/write_outputs/write_net_revenue.jl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/write_outputs/write_net_revenue.jl b/src/write_outputs/write_net_revenue.jl index 5babd67e2d..eb17cd001b 100644 --- a/src/write_outputs/write_net_revenue.jl +++ b/src/write_outputs/write_net_revenue.jl @@ -148,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