-
Notifications
You must be signed in to change notification settings - Fork 122
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
Output correct CRM values for THERM plants with maintenance #589
Output correct CRM values for THERM plants with maintenance #589
Conversation
eff_cap = thermal_plant_effective_capacity.(Ref(EP), Ref(inputs), resources, Ref(capres_zone), Ref(timesteps)) | ||
return reduce(hcat, eff_cap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref
is a part of Julia base which has not before been used in GenX. It allows vectorizing a function over arguments other than the Ref
'd ones.
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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function can be used for y::Int or y::Vector{Int}.
In the first case it outputs a Vector,{Float64} in the second case it outputs a Matrix{Float64}.
This a convenience function to automatically get the effective capacity over every time period.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is very neat.
if has_maintenance(inputs) && y in resources_with_maintenance(dfGen) | ||
resource_component = dfGen[y, :Resource] | ||
cap_size = dfGen[y, :Cap_Size] | ||
down_var = EP[Symbol(maintenance_down_name(resource_component))] | ||
vDOWN = value.(down_var[timesteps]) | ||
effective_capacity = effective_capacity .- capresfactor(y, capres_zone) * vDOWN * cap_size | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual accounting logic is all specified here, in a function that deals with one plant at a time.
Later, this will allow more detailed logic for FUSION plants, for example.
@@ -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, :]))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could similarly use weighted_price
to replace calls to dual.(EP[:cCapResMargin][i, :])
on other lines but I felt that would be better as a separate "refactor" PR.
The new Ideally all the mathematical logic would be also the same as gets put into the CRM expressions during model generation! But all the expressions for output need |
9676021
to
6a4f821
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR looks great, as always. Thanks @cfe316. Regarding the last comment, I think I had a similar idea while working on another part of the code. Let's talk about it.
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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is very neat.
capresfactor(y, capres) = dfGen[y, Symbol("CapRes_$capres")] | ||
eTotalCap = value.(EP[:eTotalCap][y]) | ||
|
||
effective_capacity = capresfactor(y, capres_zone) * eTotalCap * one.(timesteps) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could also use the fill method to create a vector of identical values.
e843554
to
f8fa6da
Compare
Account for the fact that THERM plants have provide no "capacity" while they are under maintenance.