-
Notifications
You must be signed in to change notification settings - Fork 4
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
Use formulations as an interface #59
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #59 +/- ##
==========================================
+ Coverage 48.73% 52.17% +3.44%
==========================================
Files 12 13 +1
Lines 788 851 +63
==========================================
+ Hits 384 444 +60
- Misses 404 407 +3
Flags with carried forward coverage won't be shown. Click here to find out more.
|
# Check if any GeometricDistributionForcedOutage objects exist in the System | ||
outages = PSY.get_supplemental_attributes(PSY.GeometricDistributionForcedOutage, sys) | ||
function add_default_data!(sys::PSY.System) | ||
@warn "No forced outage data available in the Sienna/Data PowerSystems System. Using generic outage data ..." |
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.
Can take this out of this function and make something more clean where we pass the CSV file? I don't really like that we rely on a CONST file definition for this.
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.
Are you saying we should let the user pass a CSV with default values? If that is the case, we might need to specify a set of necessary columns or something to map from custom column names to the columns the parser expects.
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.
Ok, I made it a parameter with a default value of the const value. Do we want to make this function public or exported? I didn't do that yet.
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.
It makes sense to make this function public. It is up to the user to format the CSV in a way we can ingest it. We might want to add column names and description of this CSV to documentation. Before we parse, we want to make sure the CSV has the necessary columns. Happy to discuss if you have any questions.
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.
I think we could probably handle this in a separate PR. #64
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.
lets not make CSV parser a default thing here. The data and models are separate. @scdhulipala if you want to make a data model to parse outages and put it in PSY that's what we need to do.
|
||
# FIXME | ||
for (idx, region) in enumerate(regions) | ||
reg_load_comps = | ||
get_available_components_in_aggregation_topology(PSY.StaticLoad, sys, region) |
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.
Be aware that a system can contain other load types. This should probably support all subtypes of ElectricLoad
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.
Agreed.
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.
I did not plan on messing with load or lines yet #61
src/PowerSystems2PRAS.jl
Outdated
@@ -396,33 +302,29 @@ function generate_pras_system( | |||
λ_gen = Matrix{Float64}(undef, n_gen, s2p_meta.N) | |||
μ_gen = Matrix{Float64}(undef, n_gen, s2p_meta.N) | |||
|
|||
#FIXME |
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.
@josephmckinsey is this pending? Do we need to add an issue or a comment to this?
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.
Yes. This needs to be fixed but this logic works for now. We will implement the component map solution we discussed for this.
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.
open an issue for this please
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.
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.
Tracked in #60
src/PowerSystems2PRAS.jl
Outdated
@@ -434,12 +336,12 @@ function generate_pras_system( | |||
PSY.get_time_series_multiple( | |||
g, | |||
s2p_meta.filter_func, | |||
name="max_active_power", | |||
name=component_to_formulation[g].max_active_power, |
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.
can use getter function for these fields?
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.
Done.
PSY.get_prime_mover_type(g) == PSY.PrimeMovers.PVe | ||
) | ||
) | ||
if haskey(PSY.get_ext(g), "region_gens") | ||
reg_gens_DA = PSY.get_ext(g)["region_gens"] | ||
gen_cap_array[idx, :] = | ||
round.( |
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 loop gives me a headache to follow what's up. We should abstract this into a function because it impossible to check if the logic is reasonable. @daniel-thom you might have some insight on the use of these functions for time series here.
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.
Same comment as above. We will not need this logic if we implement the component map solution for lumping.
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 is a mix of loop for the weird indexing PRAS needs and the lumped renewable generation. Later, I think we should spit the indexing into its own logic somehow later.
Apply HydroEnergyReservoir Formulation to fill in a row of a PRAS Matrix. | ||
Views should be passed in for all arrays. | ||
""" | ||
function assign_to_gen_stor_matrices!( |
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 logic here is also a bit unclear. Needs more comments to understand why some operations are happening
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.
I can add more comments.
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.
Yeah, I just pretty much copy pasted here.
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.
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.
Overall the design for the formulations looks ok to me. There are several methods that grab time series that definitely need to be put into separate methods.
There are some parts that also need more comments because I can't really review the logic without knowing what I am looking at.
src/SiennaPRASInterface.jl
Outdated
@@ -50,6 +50,15 @@ export add_csv_time_series! | |||
export add_csv_time_series_single_stage! | |||
export make_generator_outage_draws! | |||
|
|||
export GeneratorFormulation |
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.
General comment for all the formulation names, to follow PSI convention, can we call these GeneratorResourceAdequacy, etc. Do we need to call it PRASProblemTemplate? RATemplate?
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.
Changed to GeneratorPRAS but have a AbstractRAFormulation. The generator, generator storage, storage classification is very specific to PRAS.
src/formulation_definitions.jl
Outdated
|
||
Objects in Sienna that behave like storage are mapped to storage in PRAS. | ||
""" | ||
struct StorageFormulation <: AbstractPRASFormulation 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.
Do we want to add carry over efficiency to the formulation because currently we just assume it is 1.0?
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.
call this LossLess formulation
src/formulation_definitions.jl
Outdated
""" | ||
Check whether a DevicePRASModel applies to a given type | ||
""" | ||
function appliestodevice(::DevicePRASModel{D}, ::Type{T}) where {D, T} |
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.
I'm not sure I follow how this doesn't allow PSY.EnergyReservoirStorage to not have a GeneratorFormulation?
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 can totally do that in this framework. This only tells you about the PSY.Device
subtype D
and has nothing about the formulation type itself. Unless we specify some relation between the type parameters in DevicePRASModel, then it will error when it tries to actually apply a model.
for (idx, region) in enumerate(regions) | ||
reg_ren_comps = filter( | ||
x -> haskey(component_to_formulation, x), | ||
get_available_components_in_aggregation_topology(PSY.RenewableGen, sys, region), |
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.
Do we need to do this again get_available_components_in_aggregation_topology ? Or can we get all components from the Dict with this formulation and filter for this?
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.
I'm not sure we have a function to group by aggregation topology from a dictionary yet. It might be appropriate, but I didn't want to get into that here.
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.
Apply HydroEnergyReservoir Formulation to fill in a row of a PRAS Matrix. | ||
Views should be passed in for all arrays. | ||
""" | ||
function assign_to_gen_stor_matrices!( |
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.
I can add more comments.
Should solve #58 along with making everything more extensible.
This involved a lot of refactoring, some documentation, and more testing to make sure it works like the old version.
I also made some departures from how Sienna does it: