-
Notifications
You must be signed in to change notification settings - Fork 1
/
Crediting.jl
188 lines (145 loc) · 6.24 KB
/
Crediting.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
abstract type Crediting
Crediting is used to set the credit levels of generators for policies. It is primarily used for [`GenerationStandard`](@ref)s and [`ReserveRequirement`](@ref)s (RPS, CES, carveouts, etc).
## Setup inside config yaml
Crediting is specified in the yaml file. A type key must be specified, along with the approriate keys for the credit type you specified. Two examples are shown in the config below.
```yaml
$(read(joinpath(@__DIR__,"../../test/config/config_3bus_rps.yml"), String))
```
## Standard Crediting subtypes include:
* [`CreditByBenchmark`](@ref)
* [`CreditByGentype`](@ref)
## Interfaces Implements
* [`get_credit(c::Crediting, data, gen_row::DataFrameRow)`](@ref) - gets the appropriate credit level for the generator row for the given Crediting subtype.
"""
abstract type Crediting end
"""
Crediting(d::OrderedDict) -> crediting
Constructs a Crediting structure from `d`, an OrderedDict read in from the config file inside of a mod. The Crediting structure is of type `d[:type]` with keyword arguments for all the other key value pairs in `d`.
"""
function Crediting(d::OrderedDict)
T = get_type(d[:type])
crediting = _discard_type(T; d...)
return crediting
end
function Crediting(c::Crediting)
c
end
export Crediting
"""
fieldnames_for_yaml(::Type{C}) where {C<:Crediting}
returns the fieldnames in a yaml, used for printing, modified for different types of crediting
"""
function fieldnames_for_yaml(::Type{C}) where {C<:Crediting}
return setdiff(fieldnames(C), (:name,))
end
export fieldnames_for_yaml
"""
function YAML._print(io::IO, c::C, level::Int=0, ignore_level::Bool=false) where {C<:Crediting}
Prints the field determined in fieldnames_for_yaml from the Crediting.
"""
function YAML._print(io::IO, c::C, level::Int=0, ignore_level::Bool=false) where {C<:Crediting}
println(io)
cdict = OrderedDict(:type => string(typeof(c)), (k=>getproperty(c, k) for k in fieldnames_for_yaml(C))...)
YAML._print(io::IO, cdict, level, ignore_level)
end
"""
get_credit(c::Crediting, data, gen_row::DataFrame) ->
Return the credit value for the given generator and crediting type.
"""
function get_credit(c::Crediting, data, gen_row::DataFrame)
error("No get_credit() defined for crediting type $(typeof(c)), no credits will be applied for this policy.")
end
export get_credit
"""
CreditByGentype(;credits::OrderedDict{String, Float64})
Crediting method where credit levels are specified by gentypes.
"""
struct CreditByGentype <: Crediting
credits::OrderedDict{String,Float64}
function CreditByGentype(credits)
if !(credits isa OrderedDict{String, Float64})
credits = OrderedDict{String, Float64}(string(k)=>v for (k,v) in credits)
end
return new(credits)
end
end
CreditByGentype(;credits) = CreditByGentype(credits)
export CreditByGentype
"""
get_credit(c::CreditByGentype, data, gen_row::DataFrameRow)
Returns the credit level specified for the gentype in c.credits. If no credit is specified for that gentype, it defaults to 0.
"""
function get_credit(c::CreditByGentype, data, gen_row::DataFrameRow)
credit = get(c.credits, gen_row.gentype, 0.0)
return ByNothing(credit)
end
"""
CreditByBenchmark(;gen_col, benchmark)
Awards credit of each generator based on how that generator's `gen_col` compares to `benchmark`, using the following formula.
max(1.0 - (gen_row[gen_col] / benchmark), 0.0)
* `gen_col::Symbol` - the column of the `gen` table to compare against
* `benchmark::Float64` - the benchmark rate to compare with, in the same units as the `gen_col`.
"""
Base.@kwdef struct CreditByBenchmark <: Crediting
gen_col::Symbol = :emis_co2e
benchmark::Float64
gen_filters::OrderedDict = OrderedDict()
# function CreditByBenchmark(gen_col, benchmark, gen_filters)
# return new(Symbol(gen_col), Float64(benchmark), gen_filters)
# end
end
export CreditByBenchmark
#CreditByBenchmark(;gen_col = :emis_co2e, benchmark) = CreditByBenchmark(gen_col, benchmark, gen_filters = OrderedDict())
"""
get_credit(c::CreditByBenchmark, data, gen_row::DataFrameRow) ->
Returns the credit level based on the formula `max(1.0 - (gen_row[gen_col] / c.benchmark), 0.0)`.
"""
function get_credit(c::CreditByBenchmark, data, gen_row::DataFrameRow)
gen_emis_rate = gen_row[c.gen_col]
if row_comparison(gen_row, parse_comparisons(c.gen_filters)) # meets gen filters
credit = min.(1.0, max.( 1.0 .- gen_emis_rate ./ c.benchmark, 0.0))
else
credit = 0.0 .* gen_emis_rate
end
return credit
end
"""
UnitCredit <: Crediting
Always gives credit value of 1.0
"""
struct UnitCredit <: Crediting end
export UnitCredit
function get_credit(::UnitCredit, data, gen_row)
return 1.0
end
"""
AvailabilityFactorCrediting <: Crediting
Returns the availability factor of the generator.
"""
struct AvailabilityFactorCrediting <: Crediting end
export AvailabilityFactorCrediting
function get_credit(::AvailabilityFactorCrediting, data, gen_row)
return gen_row.af
end
"""
struct StandardStorageReserveCrediting <: Crediting
Awards crediting to storage facilities based on their discharge duration and capacity. The values were retrieved from NYISO at the following website, page 31:
[`https://www.nyiso.com/documents/20142/23590734/20210805%20NYISO%20-%20Capacity%20Accreditation%20Current%20Rules%20Final.pdf`](https://www.nyiso.com/documents/20142/23590734/20210805%20NYISO%20-%20Capacity%20Accreditation%20Current%20Rules%20Final.pdf)
"""
struct StandardStorageReserveCrediting <: Crediting
itp1::LinearInterpolator{Float64, NoBoundaries}
itp2::LinearInterpolator{Float64, NoBoundaries}
function StandardStorageReserveCrediting()
itp1 = LinearInterpolator([2., 4., 6., 8.], [0.45, 0.90, 1.00, 1.00], NoBoundaries())
itp2 = LinearInterpolator([2., 4., 6., 8.], [0.375, 0.75, 0.90, 1.00], NoBoundaries())
return new(itp1, itp2)
end
end
export StandardStorageReserveCrediting
fieldnames_for_yaml(::Type{StandardStorageReserveCrediting}) = ()
function get_credit(c::StandardStorageReserveCrediting, data, stor_row)
itp = c.itp1 # TODO: decide which interpolator to use and when.
duration = stor_row.duration_discharge::Float64
return max(0.0, min(1.0, itp(duration)))
end