-
Notifications
You must be signed in to change notification settings - Fork 1
/
ITCStorage.jl
114 lines (87 loc) · 4.66 KB
/
ITCStorage.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""
struct ITCStorage <: Policy
Investment Tax Credit - A tax incentive that is a percentage of capital cost given to storage units that meet the qualifications.
# Keyword Arguments
* `name`: policy name
* `values`: the credit level, stored as an OrderedDict with year and value `(:y2020=>0.3)`. Credit level refers to the percentage of the capex that will be rebated to the investor
* `storage_filters`: filters for qualifying storage, stored as an OrderedDict with gen table columns and values
"""
Base.@kwdef struct ITCStorage <: Policy
name::Symbol
values::OrderedDict
storage_filters::OrderedDict = OrderedDict{Symbol, Any}()
end
export ITCStorage
"""
E4ST.modify_setup_data!(pol::ITCStorage, config, data)
Creates a column in the gen table with the ITCStorage value in each simulation year for the qualifying generators.
ITCStorage values are calculated based on `capex_obj` so ITCStorage values only apply in `year_on` for a generator.
"""
function E4ST.modify_setup_data!(pol::ITCStorage, config, data)
if ~haskey(data, :storage)
@warn "ITCStorage policy given, yet no storage defined. Consider adding a Storage modification."
return
end
storage = get_table(data, :storage)
stor_idxs = get_row_idxs(storage, parse_comparisons(pol.storage_filters))
@info "Applying ITCStorage $(pol.name) to $(length(stor_idxs)) storage units"
years = get_years(data)
#create column of annualized ITCStorage values
add_table_col!(data, :storage, pol.name, Container[ByNothing(0.0) for i in 1:nrow(storage)], DollarsPerMWBuiltCapacityPerHour,
"Investment tax credit value for $(pol.name)")
#update column for gen_idx
credit_yearly = [get(pol.values, Symbol(year), 0.0) for year in years] #values for the years in the sim
for stor_idx in stor_idxs
stor = storage[stor_idx, :]
# credit yearly * capex using the same filtering as capex_obj will
# only non-zero for new builds, in an after their year_on and until end of econ life
if stor.build_status == "unbuilt"
vals_tmp = vec([(years[i] >= stor.year_on && years[i] < add_to_year(stor.year_on, stor.econ_life)) ? credit_yearly[i]*stor.capex[i,:] : 0.0 for i in 1:length(years)])
else
vals_tmp = fill(0.0, length(years))
end
stor[pol.name] = ByYear(vals_tmp)
end
end
"""
function E4ST.modify_model!(pol::ITCStorage, config, data, model)
Subtracts the ITCStorage price * Capacity in that year from the objective function using [`add_obj_term!(data, model, PerMWCap(), pol.name, oper = -)`](@ref)
"""
function E4ST.modify_model!(pol::ITCStorage, config, data, model)
if ~haskey(data, :storage)
@warn "ITCStorage policy given, yet no storage defined. Consider adding a Storage modification."
return
end
nyr = get_num_years(data)
storage = get_table(data, :storage)
#name = Symbol("$(pol.name)_obj")
name = pol.name
pcap_stor_inv_sim = model[:pcap_stor_inv_sim]::Vector
model[name] = @expression(model,
[yr_idx in 1:nyr],
sum(
pcap_stor_inv_sim[stor_idx] * get_table_num(data, :storage, pol.name, stor_idx, yr_idx, :)
for stor_idx in axes(storage,1)
)
)
add_obj_exp!(data, model, PerMWCapInv(), name, oper = -)
# Add things to results here so it gets saved in the right places
total_result_name = "$(pol.name)_cost_obj"
total_result_sym = Symbol(total_result_name)
# calculate objective policy cost (based on capacity in each sim year)
add_results_formula!(data, :storage, total_result_sym, "SumYearly($(pol.name),ecap_inv_sim)", Dollars, "The cost of $(pol.name) as seen by the objective, not used for gov spending welfare")
#add_results_formula!(data, :gen, Symbol("$(pol.name)_cost_obj"), "SumHourly($(pol.name),ecap)", Dollars, "The cost of $(pol.name) as seen by the objective, not necessarily used for gov spending welfare")
# calculate welfare policy cost (obj policy cost spread over all years of investment represented by the sim years)
# if using pol_cost_obj, update the description provided in add_results_forumla above
add_to_results_formula!(data, :storage, :invest_subsidy, total_result_name)
end
"""
E4ST.modify_results!(pol::ITCStorage, config, data) ->
Calculates ITCStorage cost as seen by the objective (cost_obj) which is ITCStorage value * capacity (where ITCStorage value is credit level as a % multiplied by capital cost)
"""
function E4ST.modify_results!(pol::ITCStorage, config, data)
if ~haskey(data, :storage)
@warn "ITCStorage policy given, yet no storage defined. Consider adding a Storage modification."
return
end
end