-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Frequently Used Policy Types #14
Comments
Frequently Used Policy Types
Currently represented as policies which will now be implemented differently
|
Clean Energy StandardsE4ST.m representation:
E4ST.jl possible representation: Mod inputs include:
Within mod:
|
Note: Ethan has already written a GenerationCap mod which can be applied as an emissions cap. We might want to just use that or create a an actual Policy |
@Ethan-Russell I'm thinking about how we want to store info for things like CESs and RPSs where we will have a cap level for each year. I think it would look clunky to have them all written out as key value pairs in the config file. We could specify a separate CSV but that's also going to mean a lot of CSVs. But I think that could be organized fairly easily so might not be a big deal. Any opinions? |
Production Tax CreditE4ST.m representation: The given $/MWh value is added to the general 'PTC' variable and then gencost is updated where 'PTC' is subtracted from the VOM and fuel cost (and other variable costs). Here the general 'PTC' doesn't just refer to actual PTC policies but just anything that is subtracted from gencost. E4ST.jl possible representation: Mod inputs include:
Within Mod:
|
Some thoughts on policy implementations, hopefully also addressing your comment above. Policy type that takes in a table of policies.That could look like: struct CSVPolicy
file::String
table::DataFrame
end
function CSVPolicy(;file)
table = E4ST.load_table(file)
return CSVPolicy(file, table)
end
E4ST.fieldnames_for_yaml(::Type{::CSVPolicy}) = (:file,)
function E4ST.modify_data!(mod::CSVPolicy, config, data)
for m in getmods(mod)
modify_data!(m, config, data)
end
end The above is very loose and unfinished. Just an idea we could expand upon. Policy ShortcutsThe idea here would be to create a fully-featured policy that requires a bunch of inputs, then make several convenience shortcut policy types that basically just use those policies. We could even do that with entire sets. Inside config YAML: mods:
ira:
type: InflationReductionAct
rps_il:
type: IllinoisRPS Julia implementation: struct IllinoisRPS <: Policy
pol::RPS
function IllinoisRPS() # This would be the function called when parsing the config file
pol = RPS(
gentypes=["wind", "solar"],
standard = Dict(
"y2020"=>500000,
"y2021"=>510000,
"y2022"=>520000,
# ...
),
)
return IllinoisRPS(pol)
end
end
E4ST.fieldnames_for_yaml(::Type{::IllinoisRPS}) = (,)
function E4ST.modify_data!(mod::IllinoisRPS, config, data)
modify_data!(mod.pol, config, data)
end
struct InflationReductionAct<: Policy
pols::Vector{<:Policy}
function InflationReductionAct()
pols = [
# insert policies here
]
return InflationReductionAct(pols)
end
end |
Investment Tax CreditE4ST.m representation: ITC value given as a percentage of CAP_COST. Credit level is multiplied by CAP_COST then added to the general 'ITC' and offer price is updated. The general 'ITC' is anything subtracted out from the offer price (the cost to add capacity) not just the policy ITC. E4ST.jl possible representation: Mod inputs include:
Within Mod:
|
Emissions PriceE4ST.jl possible representation: Mod inputs include:
Within Mod:
One option would be to create a general GenerationPrc mod like the GenerationCap mod where you specify a price and column name that it is multiplied by which is then multiplied by generation. This just makes things more modular and cleaner. |
Building on the above idea about policy shortcuts and policies from CSVs: There will be basic policy types (ie. PTC, ITC, CES, etc). When you write a new actual policy, it may contain multiple of these basic policy types (ie. The inflation reduction act has multiple ITCs and PTCs). All values, filters, and other info required for the basic policy type can be stored in a csv for that actual policy, or even multiple policies but best to not mix too much. The function for the actual policy is to:
Policy CSV example (work in progress)
|
From our discussion today about Emissions Cap: struct EmissionsCap
gen_cons::GenerationConstraint
other
fields
function EmissionsCap(other, fields)
gen_cons = GenerationConstraint(other, fields)
new(gen_cons, other, fields)
end
end
fieldnames_for_yaml(::EmissionsCap) = (:other, :fields)
"""
modify_model!(pol::EmissionsCap, config, data, model) ->
"""
function modify_model!(pol::EmissionsCap, config, data, model)
modify_model!(pol.gen_cons, config, data, model)
end
export modify_model! |
Questions about RPSs?
|
Generation/Portfolio Standards (RPS/CES)Matlab Representation:(done in applyPS.m)
E4ST.jl representationFor now we will only define it as a percent of demanded load (although we could define it as a percentage of served load, but this complicates formulation). For the quantity definition, we can use the GenerationConstraint type. Thinking of having a GenerationStandard or PortfolioStandard type which is created by the RPS/CES type Inputs for GenerationStandard:
Basic idea:
Simpler idea: Overlap challenge:Policies from different regions sometimes overlap in what generators qualify to supply the clean energy they need. We don't want to double count these generators for both policies. We need a way to indicate that only a portion of generation from an overlapped gen is going to each policy. (We, for the most part, define RPS regions so they don't overlap. This is most relevant to VGPs where some of the generation can come from anywhere in the nation.) There is an exception: Overlapping RPSs and CESs can have generators count for both (ie. generators in an RPS can get clean energy credits in a CES). Ideas:
Other notes:
|
I believe it should be a percentage of the served load in a region (which would be an expression). We could probably get away with using the demanded load. |
We should ask @DanShawhan about this. Another option is to do a percentage of energy served (which is closer to total generation). This complicates the constraint because it would include battery charging, DAC, and any other added loads, but is possibly more realistic. |
After talking with Dan about above question: We should apply the constraint to Should we include transmission and distribution losses? Could we have the option to apply it to retail sales? |
Thanks! The definitions below are good if the following conditions hold:
* We want "target load" to be load at the point of consumption, i.e. not counting T&D losses nor battery losses
* We want "target load" to not include load for DAC
* We want "retail sales" to include DAC but not include battery charging load (nether net nor gross battery charging load)
It seems to me that a possible imperfection of these definitions and terms, that we might be able to improve upon, is that the names "target load" and "retail sales" don't tell us what they include, that we will need to remember what they include, and that that will be difficult at least for me.
We could try to come up with more descriptive names. E.g. could use the term "target retail sales" so that we have two variables that are the same except that one is after taking into account prices.
It is possible that we use the word "load" in some other places in the code or results template to mean retail sales plus losses. In that case, we should probably not use the term "target load" to mean target load without losses.
However, if you think the current terms are fine and that you won't forget what one of them includes and doesn't include, and that they won't cause confusion for future team members, we could just include the definitions somewhere that is easy for all of us to find when we are working on code or results templates or looking at results, like in the results template or in a helper file in a place where I can find it. This actually goes for some other things in the results spreadsheets too. I don't know what is and is not included in some of the rows in the results spreadsheet, e.g. "fixed cost" or "fixed cost per MW" and that is a problem. We should either make the template more descriptive, or provide the needed additional description in a helper file.
Dan
|
Generation StandardsCurrent best idea:
*Not all policies that overlap will conflict. An RPS and CES can overlap and generators are allowed to count for both. A state carveout and an RPS can overlap without conflicting (the state carveout is almost a sub constraint of the RPS). But two overlapping RPSs will conflict and VGP will conflict with RPSs and CESs. |
Discussion 3/27/23:
|
mods:
illinois_rps:
type: RPS
crediting:
type: CreditByGentype
gentypes:
ngccccs: 0.5
solar: 1.0
geothermal: 0.9
california_rps:
type: GenerationStandard
crediting:
type: CreditByBenchmark
benchark: 0.6
texas_ces:
type: GenerationStandard
crediting:
type: CrazyTexasCrediting
util_rps:
type: GenerationStandard
crediting:
type: StandardRPSCrediting
# pseudocode
struct GenerationStandard{C} where {C<:Crediting} # Optional to parameterize
crediting::C
other
fields
end
function GenerationStandard(; crediting, other, fields)
c = Crediting(crediting)
return GenerationStandard(c, other, fields)
end
# Crediting interface
get_credits(c::Crediting, gen::DataFrame) -> credits::Vector{Float64}
# OR, probably better
get_credits(c::Crediting, gen_row::DataFrameRow) -> credit::Float64 |
|
|
In generating our existing state RPSs, I have come up against the issue of super constraints and overlapping generation regions. The main issue is that we specify different rps regions (midwest, ne, pjm, etc.) that different state RPSs can draw from. In matlab E4ST, we group all of the state policies in that region into one E4ST policy. The state targets are applied to the state load and then the constraint is applied on the total of those targets. To do this, we specify targets for each state. With the way that generation standards are current written in E4ST.jl, there is only one set of targets for each policy and it is applied to all the load in the filtered region. This means that each state policy is treated as a unique E4ST policy and we can't currently group them like we do in matlab E4ST. We could try to redesign GenerationStandard so that you could specify multiple sets of targets specific to a location in one policy. This might be useful for other policy representations beyond these state RPSs. Or we can write the script for creating superconstraints. This is something we wanted to do at some point in the future anyways but thought we didn't need yet. We haven't fully resolved how to deal with policies that only partially overlap but it would be pretty straightforward to write super constraints for policies like this where the entire gen area is the same for the grouped states and the rps regions don't overlap with each other. |
No description provided.
The text was updated successfully, but these errors were encountered: