Skip to content

Commit

Permalink
Separate new-buildability and ability to retire
Browse files Browse the repository at this point in the history
Previously this was one column "New_Build" which could be 0, 1, or -1.
Now, New_Build should be either 0 or 1 and
Can_Retire should be either 0 or 1.
  • Loading branch information
cfe316 committed Aug 25, 2023
1 parent b7d819a commit 79f6f92
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 39 deletions.
10 changes: 6 additions & 4 deletions docs/src/data_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,12 @@ This file contains cost and performance parameters for various generators and ot
|Resource | This column contains **unique** names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.|
|Zone | Integer representing zone number where the resource is located. |
|**Technology type flags**|
|New\_Build | {-1, 0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.|
||New\_Build = 1: eligible for capacity expansion and retirement. |
||New\_Build = 0: not eligible for capacity expansion, eligible for retirement.|
||New\_Build = -1: not eligible for capacity expansion or retirement.|
|New\_Build | { 0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.|
||New\_Build = 1: eligible for capacity expansion. |
||New\_Build = 0: not eligible for capacity expansion.|
|Can\_Retire | {0, 1}, Flag for resource (storage, generation) eligibility for retirement.|
||Can\_Retire = 1: eligible for retirement. |
||Can\_Retire = 0: not eligible for retirement.|
|THERM | {0, 1, 2}, Flag to indicate membership in set of thermal resources (e.g. nuclear, combined heat and power, natural gas combined cycle, coal power plant)|
||THERM = 0: Not part of set (default) |
||THERM = 1: If the power plant relies on thermal energy input and subject unit commitment constraints/decisions if `UCommit >= 1` (e.g. cycling decisions/costs/constraints). |
Expand Down
79 changes: 56 additions & 23 deletions src/load_inputs/load_generators_data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ function load_generators_data!(setup::Dict, path::AbstractString, inputs_gen::Di
# Set of storage resources with symmetric charge/discharge capacity
inputs_gen["STOR_SYMMETRIC"] = gen_in[gen_in.STOR.==1,:R_ID]
# Set of storage resources with asymmetric (separte) charge/discharge capacity components
inputs_gen["STOR_ASYMMETRIC"] = gen_in[gen_in.STOR.==2,:R_ID]
STOR_ASYMMETRIC = gen_in[gen_in.STOR.==2,:R_ID]
inputs_gen["STOR_ASYMMETRIC"] = STOR_ASYMMETRIC
# Set of all storage resources
inputs_gen["STOR_ALL"] = union(inputs_gen["STOR_SYMMETRIC"],inputs_gen["STOR_ASYMMETRIC"])
STOR_ALL = union(inputs_gen["STOR_SYMMETRIC"], STOR_ASYMMETRIC)
inputs_gen["STOR_ALL"] = STOR_ALL

# Set of storage resources with long duration storage capabilitites
inputs_gen["STOR_HYDRO_LONG_DURATION"] = gen_in[(gen_in.LDS.==1) .& (gen_in.HYDRO.==1),:R_ID]
Expand Down Expand Up @@ -95,20 +97,35 @@ function load_generators_data!(setup::Dict, path::AbstractString, inputs_gen::Di
inputs_gen["RSV"] = gen_in[(gen_in[!,:Rsv_Max].>0),:R_ID]
end

NEW_BUILD = gen_in[gen_in.New_Build.==1, :R_ID]
retirable_resources = get_resources_which_can_be_retired(gen_in)

# Set of all resources eligible for new capacity
inputs_gen["NEW_CAP"] = intersect(gen_in[gen_in.New_Build.==1,:R_ID], gen_in[gen_in.Max_Cap_MW.!=0,:R_ID])
inputs_gen["NEW_CAP"] = intersect(NEW_BUILD, gen_in[gen_in.Max_Cap_MW.!=0,:R_ID])
# Set of all resources eligible for capacity retirements
inputs_gen["RET_CAP"] = intersect(gen_in[gen_in.New_Build.!=-1,:R_ID], gen_in[gen_in.Existing_Cap_MW.>=0,:R_ID])

# Set of all storage resources eligible for new energy capacity
inputs_gen["NEW_CAP_ENERGY"] = intersect(gen_in[gen_in.New_Build.==1,:R_ID], gen_in[gen_in.Max_Cap_MWh.!=0,:R_ID], inputs_gen["STOR_ALL"])
# Set of all storage resources eligible for energy capacity retirements
inputs_gen["RET_CAP_ENERGY"] = intersect(gen_in[gen_in.New_Build.!=-1,:R_ID], gen_in[gen_in.Existing_Cap_MWh.>=0,:R_ID], inputs_gen["STOR_ALL"])
inputs_gen["RET_CAP"] = intersect(retirable_resources, gen_in[gen_in.Existing_Cap_MW.>=0,:R_ID])

# Set of asymmetric charge/discharge storage resources eligible for new charge capacity
inputs_gen["NEW_CAP_CHARGE"] = intersect(gen_in[gen_in.New_Build.==1,:R_ID], gen_in[gen_in.Max_Charge_Cap_MW.!=0,:R_ID], inputs_gen["STOR_ASYMMETRIC"])
# Set of asymmetric charge/discharge storage resources eligible for charge capacity retirements
inputs_gen["RET_CAP_CHARGE"] = intersect(gen_in[gen_in.New_Build.!=-1,:R_ID], gen_in[gen_in.Existing_Charge_Cap_MW.>=0,:R_ID], inputs_gen["STOR_ASYMMETRIC"])
NEW_CAP_ENERGY = Set{Int64}()
RET_CAP_ENERGY = Set{Int64}()
if !isempty(STOR_ALL)
# Set of all storage resources eligible for new energy capacity
NEW_CAP_ENERGY = intersect(NEW_BUILD, gen_in[gen_in.Max_Cap_MWh.!=0,:R_ID], STOR_ALL)
# Set of all storage resources eligible for energy capacity retirements
RET_CAP_ENERGY = intersect(retirable_resources, gen_in[gen_in.Existing_Cap_MWh.>=0,:R_ID], STOR_ALL)
end
inputs_gen["NEW_CAP_ENERGY"] = NEW_CAP_ENERGY
inputs_gen["RET_CAP_ENERGY"] = RET_CAP_ENERGY

NEW_CAP_CHARGE = Set{Int64}()
RET_CAP_CHARGE = Set{Int64}()
if !isempty(STOR_ASYMMETRIC)
# Set of asymmetric charge/discharge storage resources eligible for new charge capacity
NEW_CAP_CHARGE = intersect(NEW_BUILD, gen_in[gen_in.Max_Charge_Cap_MW.!=0,:R_ID], STOR_ASYMMETRIC)
# Set of asymmetric charge/discharge storage resources eligible for charge capacity retirements
RET_CAP_CHARGE = intersect(retirable_resources, gen_in[gen_in.Existing_Charge_Cap_MW.>=0,:R_ID], STOR_ASYMMETRIC)
end
inputs_gen["NEW_CAP_CHARGE"] = NEW_CAP_CHARGE
inputs_gen["RET_CAP_CHARGE"] = RET_CAP_CHARGE

# Names of resources
inputs_gen["RESOURCES"] = gen_in[!,:Resource]
Expand Down Expand Up @@ -372,7 +389,7 @@ function load_vre_stor_data!(inputs_gen::Dict, setup::Dict, path::AbstractString

# New build and retirement resources
new_build_resources = dfGen[dfGen.New_Build.==1,:R_ID]
retirement_resources = dfGen[dfGen.New_Build.!=-1,:R_ID]
retirable_resources = get_resources_which_can_be_retired(dfGen)

# Solar PV Resources
inputs_gen["VS_SOLAR"] = vre_stor_in[(vre_stor_in.SOLAR.!=0),:R_ID]
Expand All @@ -389,36 +406,36 @@ function load_vre_stor_data!(inputs_gen::Dict, setup::Dict, path::AbstractString
# Set of all VRE-STOR resources eligible for new solar capacity
inputs_gen["NEW_CAP_SOLAR"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.SOLAR.!=0,:R_ID], vre_stor_in[vre_stor_in.Max_Cap_Solar_MW.!=0,:R_ID])
# Set of all VRE_STOR resources eligible for solar capacity retirements
inputs_gen["RET_CAP_SOLAR"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.SOLAR.!=0,:R_ID], vre_stor_in[vre_stor_in.Existing_Cap_Solar_MW.>=0,:R_ID])
inputs_gen["RET_CAP_SOLAR"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.SOLAR.!=0,:R_ID], vre_stor_in[vre_stor_in.Existing_Cap_Solar_MW.>=0,:R_ID])
# Set of all VRE-STOR resources eligible for new wind capacity
inputs_gen["NEW_CAP_WIND"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.WIND.!=0,:R_ID], vre_stor_in[vre_stor_in.Max_Cap_Wind_MW.!=0,:R_ID])
# Set of all VRE_STOR resources eligible for wind capacity retirements
inputs_gen["RET_CAP_WIND"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.WIND.!=0,:R_ID], vre_stor_in[vre_stor_in.Existing_Cap_Wind_MW.>=0,:R_ID])
inputs_gen["RET_CAP_WIND"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.WIND.!=0,:R_ID], vre_stor_in[vre_stor_in.Existing_Cap_Wind_MW.>=0,:R_ID])
# Set of all VRE-STOR resources eligible for new inverter capacity
inputs_gen["NEW_CAP_DC"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.Max_Cap_Inverter_MW.!=0,:R_ID], inputs_gen["VS_DC"])
# Set of all VRE_STOR resources eligible for inverter capacity retirements
inputs_gen["RET_CAP_DC"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.Existing_Cap_Inverter_MW.>=0,:R_ID], inputs_gen["VS_DC"])
inputs_gen["RET_CAP_DC"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.Existing_Cap_Inverter_MW.>=0,:R_ID], inputs_gen["VS_DC"])
# Set of all storage resources eligible for new energy capacity
inputs_gen["NEW_CAP_STOR"] = intersect(new_build_resources, dfGen[dfGen.Max_Cap_MWh.!=0,:R_ID], inputs_gen["VS_STOR"])
# Set of all storage resources eligible for energy capacity retirements
inputs_gen["RET_CAP_STOR"] = intersect(retirement_resources, dfGen[dfGen.Existing_Cap_MWh.>=0,:R_ID], inputs_gen["VS_STOR"])
inputs_gen["RET_CAP_STOR"] = intersect(retirable_resources, dfGen[dfGen.Existing_Cap_MWh.>=0,:R_ID], inputs_gen["VS_STOR"])
if !isempty(inputs_gen["VS_ASYM"])
# Set of asymmetric charge DC storage resources eligible for new charge capacity
inputs_gen["NEW_CAP_CHARGE_DC"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.Max_Cap_Charge_DC_MW.!=0,:R_ID], inputs_gen["VS_ASYM_DC_CHARGE"])
# Set of asymmetric charge DC storage resources eligible for charge capacity retirements
inputs_gen["RET_CAP_CHARGE_DC"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.Existing_Cap_Charge_DC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_DC_CHARGE"])
inputs_gen["RET_CAP_CHARGE_DC"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.Existing_Cap_Charge_DC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_DC_CHARGE"])
# Set of asymmetric discharge DC storage resources eligible for new discharge capacity
inputs_gen["NEW_CAP_DISCHARGE_DC"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.Max_Cap_Discharge_DC_MW.!=0,:R_ID], inputs_gen["VS_ASYM_DC_DISCHARGE"])
# Set of asymmetric discharge DC storage resources eligible for discharge capacity retirements
inputs_gen["RET_CAP_DISCHARGE_DC"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.Existing_Cap_Discharge_DC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_DC_DISCHARGE"])
inputs_gen["RET_CAP_DISCHARGE_DC"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.Existing_Cap_Discharge_DC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_DC_DISCHARGE"])
# Set of asymmetric charge AC storage resources eligible for new charge capacity
inputs_gen["NEW_CAP_CHARGE_AC"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.Max_Cap_Charge_AC_MW.!=0,:R_ID], inputs_gen["VS_ASYM_AC_CHARGE"])
# Set of asymmetric charge AC storage resources eligible for charge capacity retirements
inputs_gen["RET_CAP_CHARGE_AC"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.Existing_Cap_Charge_AC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_AC_CHARGE"])
inputs_gen["RET_CAP_CHARGE_AC"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.Existing_Cap_Charge_AC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_AC_CHARGE"])
# Set of asymmetric discharge AC storage resources eligible for new discharge capacity
inputs_gen["NEW_CAP_DISCHARGE_AC"] = intersect(new_build_resources, vre_stor_in[vre_stor_in.Max_Cap_Discharge_AC_MW.!=0,:R_ID], inputs_gen["VS_ASYM_AC_DISCHARGE"])
# Set of asymmetric discharge AC storage resources eligible for discharge capacity retirements
inputs_gen["RET_CAP_DISCHARGE_AC"] = intersect(retirement_resources, vre_stor_in[vre_stor_in.Existing_Cap_Discharge_AC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_AC_DISCHARGE"])
inputs_gen["RET_CAP_DISCHARGE_AC"] = intersect(retirable_resources, vre_stor_in[vre_stor_in.Existing_Cap_Discharge_AC_MW.>=0,:R_ID], inputs_gen["VS_ASYM_AC_DISCHARGE"])
end

# Names for systemwide resources
Expand Down Expand Up @@ -501,4 +518,20 @@ function load_vre_stor_data!(inputs_gen::Dict, setup::Dict, path::AbstractString
inputs_gen["dfVRE_STOR"] = DataFrame()
end
summarize_errors(error_strings)
end
end

function get_resources_which_can_be_retired(df::DataFrame)::Set{Int64}
if string(:Can_Retire) in names(df)
retirable = df[df.Can_Retire.==1, :R_ID]
else
# Backward compatibility.
retirable = df[df.New_Build.==-1, :R_ID]
if !isempty(retirable)
@warn "The generators input file, 'New_Build' column, has some entries
which are -1 (indicating the ability to be retired). This input format is deprecated
and may be removed in a future version. Instead, use a column 'Can_Retire',
with entries of either 0 or 1."
end
end
return Set(retirable)
end
25 changes: 13 additions & 12 deletions src/multi_stage/configure_multi_stage_inputs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,23 +115,24 @@ function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkE
end
end

retirable_resources = get_generators_which_can_be_retired(dfGen)

# Set of all resources eligible for capacity retirements
can_retire_resources = dfGen[dfGen.New_Build.!=-1,:R_ID]
inputs_d["RET_CAP"] = intersect(can_retire_resources)
inputs_d["RET_CAP"] = retirable_resources
# Set of all storage resources eligible for energy capacity retirements
inputs_d["RET_CAP_ENERGY"] = intersect(can_retire_resources, inputs_d["STOR_ALL"])
inputs_d["RET_CAP_ENERGY"] = intersect(retirable_resources, inputs_d["STOR_ALL"])
# Set of asymmetric charge/discharge storage resources eligible for charge capacity retirements
inputs_d["RET_CAP_CHARGE"] = intersect(can_retire_resources, inputs_d["STOR_ASYMMETRIC"])
inputs_d["RET_CAP_CHARGE"] = intersect(retirable_resources, inputs_d["STOR_ASYMMETRIC"])
# Set of all co-located resources' components eligible for capacity retirements
if !isempty(inputs_d["VRE_STOR"])
inputs_d["RET_CAP_DC"] = intersect(can_retire_resources, inputs_d["VS_DC"])
inputs_d["RET_CAP_SOLAR"] = intersect(can_retire_resources, inputs_d["VS_SOLAR"])
inputs_d["RET_CAP_WIND"] = intersect(can_retire_resources, inputs_d["VS_WIND"])
inputs_d["RET_CAP_STOR"] = intersect(can_retire_resources, inputs_d["VS_STOR"])
inputs_d["RET_CAP_DISCHARGE_DC"] = intersect(can_retire_resources, inputs_d["VS_ASYM_DC_DISCHARGE"])
inputs_d["RET_CAP_CHARGE_DC"] = intersect(can_retire_resources, inputs_d["VS_ASYM_DC_CHARGE"])
inputs_d["RET_CAP_DISCHARGE_AC"] = intersect(can_retire_resources, inputs_d["VS_ASYM_AC_DISCHARGE"])
inputs_d["RET_CAP_CHARGE_AC"] = intersect(can_retire_resources, inputs_d["VS_ASYM_AC_CHARGE"])
inputs_d["RET_CAP_DC"] = intersect(retirable_resources, inputs_d["VS_DC"])
inputs_d["RET_CAP_SOLAR"] = intersect(retirable_resources, inputs_d["VS_SOLAR"])
inputs_d["RET_CAP_WIND"] = intersect(retirable_resources, inputs_d["VS_WIND"])
inputs_d["RET_CAP_STOR"] = intersect(retirable_resources, inputs_d["VS_STOR"])
inputs_d["RET_CAP_DISCHARGE_DC"] = intersect(retirable_resources, inputs_d["VS_ASYM_DC_DISCHARGE"])
inputs_d["RET_CAP_CHARGE_DC"] = intersect(retirable_resources, inputs_d["VS_ASYM_DC_CHARGE"])
inputs_d["RET_CAP_DISCHARGE_AC"] = intersect(retirable_resources, inputs_d["VS_ASYM_AC_DISCHARGE"])
inputs_d["RET_CAP_CHARGE_AC"] = intersect(retirable_resources, inputs_d["VS_ASYM_AC_CHARGE"])
end

# Transmission
Expand Down

0 comments on commit 79f6f92

Please sign in to comment.