Skip to content
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

Merged

Conversation

cfe316
Copy link
Collaborator

@cfe316 cfe316 commented Nov 30, 2023

Account for the fact that THERM plants have provide no "capacity" while they are under maintenance.

@cfe316 cfe316 requested a review from lbonaldo November 30, 2023 20:06
Comment on lines 11 to 12
eff_cap = thermal_plant_effective_capacity.(Ref(EP), Ref(inputs), resources, Ref(capres_zone), Ref(timesteps))
return reduce(hcat, eff_cap)
Copy link
Collaborator Author

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.

Comment on lines 15 to 20
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

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

Comment on lines 29 to 35
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
Copy link
Collaborator Author

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, :])))
Copy link
Collaborator Author

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.

@cfe316
Copy link
Collaborator Author

cfe316 commented Nov 30, 2023

The new effective_capacity.jl file should contain functions where the (time-dependent) crm-policy-capacity can be found. This allows us to not repeat mathematical logic in both write_capacity_value.jl and reserve_margin_revenue.jl.

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 value.(x) where x is EP[....], so I'm not sure if this is possible.

@cfe316 cfe316 force-pushed the feature-output-correct-crm-for-maintenance branch from 9676021 to 6a4f821 Compare November 30, 2023 22:15
Copy link
Collaborator

@lbonaldo lbonaldo left a 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.

Comment on lines 15 to 20
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

Copy link
Collaborator

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)
Copy link
Collaborator

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.

@cfe316 cfe316 force-pushed the feature-output-correct-crm-for-maintenance branch from e843554 to f8fa6da Compare December 1, 2023 01:43
@cfe316 cfe316 merged commit 5727636 into GenXProject:develop Dec 1, 2023
7 checks passed
@cfe316 cfe316 deleted the feature-output-correct-crm-for-maintenance branch December 1, 2023 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants