From d6af2b15cd6195198556ed4e8514faa343b4e0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Henr=C3=ADquez-Auba?= Date: Mon, 21 Oct 2024 16:36:17 -0700 Subject: [PATCH 1/8] Update README with docs link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 522103bd85..efaf6b7e94 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ The `PowerSystems.jl` package provides a rigorous data model using Julia structu - Dynamic Generators Models - Dynamic Inverter Models -For a more exhaustive list, check the [Documentation](https://nrel-sienna.github.io/PowerSystems.jl/stable). +For information on using the package and a more extensive list of device data enabled, see the [stable documentation](https://nrel-sienna.github.io/PowerSystems.jl/stable/). Use the [in-development documentation](https://nrel-sienna.github.io/PowerSystems.jl/dev/) for the version of the documentation which contains the unreleased features. ## Parsing capabilities in PowerSystems From c7fcef0fae162e5f3dfac0236ba8549acc346bf1 Mon Sep 17 00:00:00 2001 From: kdayday Date: Fri, 25 Oct 2024 11:12:47 -0600 Subject: [PATCH 2/8] Make filter func signature visible + get_available_components clarification --- docs/make.jl | 2 +- docs/src/api/type_tree.md | 2 +- src/base.jl | 50 ++++++++++++++++++++++++++++++--------- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 0bd7e8cbe9..22d9d288d6 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -45,7 +45,7 @@ pages = OrderedDict( "Reference" => Any["Public API" => "api/public.md", "Glossary and Acronyms" => "api/glossary.md", - "Type Hierarchy" => "api/type_tree.md", + "Type Tree" => "api/type_tree.md", "`ValueCurve` Options" => "api/valuecurve_options.md", "Specifying the category of..." => "api/enumerated_types.md", "Citation" => "api/citation.md", diff --git a/docs/src/api/type_tree.md b/docs/src/api/type_tree.md index 68fbbb183b..62b03c8562 100644 --- a/docs/src/api/type_tree.md +++ b/docs/src/api/type_tree.md @@ -1,4 +1,4 @@ -# Type Hierarchy +# Type Tree Here is the complete `PowerSystems.jl` type hierarchy: diff --git a/src/base.jl b/src/base.jl index 335f34a1ea..180fdc4c20 100644 --- a/src/base.jl +++ b/src/base.jl @@ -1080,22 +1080,25 @@ function get_component(::Type{T}, sys::System, name::AbstractString) where {T <: end """ -Returns an iterator of components. T can be concrete or abstract. +Return an iterator of components of a given `Type` from a [`System`](@ref). + +`T` can be a concrete or abstract [`Component`](@ref) type from the [Type Tree](@ref). Call collect on the result if an array is desired. # Examples ```julia -iter = PowerSystems.get_components(ThermalStandard, sys) -iter = PowerSystems.get_components(Generator, sys) -iter = PowerSystems.get_components(x -> PowerSystems.get_available(x), Generator, sys) -thermal_gens = get_components(ThermalStandard, sys) do gen - get_available(gen) -end -generators = collect(PowerSystems.get_components(Generator, sys)) - +iter = get_components(ThermalStandard, sys) +iter = get_components(Generator, sys) +generators = collect(get_components(Generator, sys)) ``` -See also: [`iterate_components`](@ref) +See also: [`iterate_components`](@ref), [`get_components` with a filter](@ref get_components( + filter_func::Function, + ::Type{T}, + sys::System; + subsystem_name = nothing, +) where {T <: Component}), +[`get_available_components`](@ref), [`get_buses`](@ref) """ function get_components( ::Type{T}, @@ -1105,6 +1108,27 @@ function get_components( return IS.get_components(T, sys.data; subsystem_name = subsystem_name) end +""" +Return an iterator of components of a given `Type` from a [`System`](@ref), using an +additional filter + +`T` can be a concrete or abstract [`Component`](@ref) type from the [Type Tree](@ref). +Call collect on the result if an array is desired. + +# Examples +```julia +iter_coal = get_components(x -> get_fuel(x) == ThermalFuels.COAL, Generator, sys) +pv_gens = + collect(get_components(x -> get_prime_mover_type(x) == PrimeMovers.PVe, Generator, sys)) +``` + +See also: [`get_components`](@ref get_components( + ::Type{T}, + sys::System; + subsystem_name = nothing, +) where {T <: Component}), [`get_available_components`](@ref), +[`get_buses`](@ref) +""" function get_components( filter_func::Function, ::Type{T}, @@ -1161,7 +1185,11 @@ function get_components_by_name( end """ -Gets components availability. Requires type T to have the method get_available implemented. +Returns iterator of available components in a [`System`](@ref). + +`T` can be a concrete or abstract [`Component`](@ref) type from the [Type Tree](@ref) +and must have the method `get_available` implemented. +Call collect on the result if an array is desired. """ function get_available_components(::Type{T}, sys::System) where {T <: Component} return get_components(get_available, T, sys) From f14ccb44a3a15d3b626e6956d8d4dc410a8f40c8 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Tue, 29 Oct 2024 11:46:16 -0600 Subject: [PATCH 3/8] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 51efba9335..a915a44253 100644 --- a/Project.toml +++ b/Project.toml @@ -27,7 +27,7 @@ DataFrames = "1" DataStructures = "~0.18" Dates = "1" DocStringExtensions = "0.8, 0.9.2" -InfrastructureSystems = "^2.2" +InfrastructureSystems = "^2.3" InteractiveUtils = "1" JSON3 = "1" LinearAlgebra = "1" From a603b756badd809fb77c6afaf0c4fb3c71f20e6e Mon Sep 17 00:00:00 2001 From: Daniel Thom Date: Tue, 29 Oct 2024 15:16:07 -0600 Subject: [PATCH 4/8] Fix get_buses when a bus does not have an Area The function get_buses would fail with an unhandled exception if any bus did have an AggregationTopology assigned. --- src/base.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base.jl b/src/base.jl index 180fdc4c20..31d38a9f77 100644 --- a/src/base.jl +++ b/src/base.jl @@ -73,7 +73,7 @@ System(; kwargs...) `"DEVICE_BASE"`, or `"NATURAL_UNITS"`) By default, time series data is stored in an HDF5 file in the tmp file system to prevent -large datasets from overwhelming system memory (see [Data Storage](@ref)). +large datasets from overwhelming system memory (see [Data Storage](@ref)). **If the system's time series data will be larger than the amount of tmp space available**, use the `time_series_directory` parameter to change its location. @@ -1325,7 +1325,7 @@ function _get_buses(data::IS.SystemData, aggregator::T) where {T <: AggregationT buses = Vector{ACBus}() for bus in IS.get_components(ACBus, data) _aggregator = accessor_func(bus) - if IS.get_uuid(_aggregator) == IS.get_uuid(aggregator) + if !isnothing(_aggregator) && IS.get_uuid(_aggregator) == IS.get_uuid(aggregator) push!(buses, bus) end end From 91bc0abc0bdfbb097459bf5f22b658453ef27643 Mon Sep 17 00:00:00 2001 From: GabrielKS <23368820+GabrielKS@users.noreply.github.com> Date: Fri, 22 Nov 2024 17:27:12 -0700 Subject: [PATCH 5/8] PERF: dispatch on `UnitSystem` value in `_get_multiplier` --- src/models/components.jl | 49 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/models/components.jl b/src/models/components.jl index 939e8e97d7..3ff5ac84ca 100644 --- a/src/models/components.jl +++ b/src/models/components.jl @@ -7,23 +7,38 @@ Default behavior of a component. If there is no base_power field, assume is in t """ get_base_power(c::Component) = get_system_base_power(c) -function _get_multiplier(c::T) where {T <: Component} - setting = get_internal(c).units_info - if isnothing(setting) - return 1.0 - elseif setting.unit_system == IS.UnitSystem.DEVICE_BASE - return 1.0 - elseif setting.unit_system == IS.UnitSystem.SYSTEM_BASE - numerator = get_base_power(c) - denominator = setting.base_value - elseif setting.unit_system == IS.UnitSystem.NATURAL_UNITS - numerator = get_base_power(c) - denominator = 1.0 - else - error("Undefined Conditional") - end - return numerator / denominator -end +_get_multiplier(c::T) where {T <: Component} = + _get_multiplier(c, get_internal(c).units_info) + +_get_multiplier(::T, ::Nothing) where {T <: Component} = + 1.0 +_get_multiplier(c::T, setting::IS.SystemUnitsSettings) where {T <: Component} = + _get_multiplier(c, setting, Val(setting.unit_system)) + +# PERF: dispatching on the UnitSystem values instead of comparing with if/else avoids the +# performance hit associated with consulting the dictionary that backs the @scoped_enum -- +# i.e., IS.UnitSystem.NATURAL_UNITS by itself isn't treated as a constant, it's a dictionary +# lookup each time. +_get_multiplier( + ::T, + ::IS.SystemUnitsSettings, + ::Val{IS.UnitSystem.DEVICE_BASE}, +) where {T <: Component} = + 1.0 +_get_multiplier( + c::T, + setting::IS.SystemUnitsSettings, + ::Val{IS.UnitSystem.SYSTEM_BASE}, +) where {T <: Component} = + get_base_power(c) / setting.base_value +_get_multiplier( + c::T, + ::IS.SystemUnitsSettings, + ::Val{IS.UnitSystem.NATURAL_UNITS}, +) where {T <: Component} = + get_base_power(c) +_get_multiplier(::T, ::IS.SystemUnitsSettings, ::Val) where {T <: Component} = + error("Undefined Conditional") function get_value(c::Component, value::Float64) return _get_multiplier(c) * value From 9dff0dbcbc2c9b4787893991814b1a3dd52c7f28 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Dec 2024 13:57:36 -0800 Subject: [PATCH 6/8] add ifelse for base power --- src/parsers/power_models_data.jl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/parsers/power_models_data.jl b/src/parsers/power_models_data.jl index ae3812993e..0ec1b7433d 100644 --- a/src/parsers/power_models_data.jl +++ b/src/parsers/power_models_data.jl @@ -555,7 +555,14 @@ function make_thermal_gen( ext["z_source"] = (r = d["r_source"], x = d["x_source"]) end - base_conversion = sys_mbase / d["mbase"] + if d["mbase"] != 0.0 + mbase = d["mbase"] + else + @warn "Generator $gen_name has base power equal to zero: $(d["mbase"]). Changing it to system base: $sys_mbase" + mbase = sys_mbase + end + + base_conversion = sys_mbase / mbase thermal_gen = ThermalStandard(; name = gen_name, status = Bool(d["gen_status"]), @@ -577,7 +584,7 @@ function make_thermal_gen( ramp_limits = (up = ramp_lim, down = ramp_lim), time_limits = nothing, operation_cost = operation_cost, - base_power = d["mbase"], + base_power = mbase, ext = ext, ) From 2d4b3365ed7f88a78baf4f9b4ac040fb0238dea6 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Dec 2024 14:03:07 -0800 Subject: [PATCH 7/8] update ifelse case for other type of gens --- src/parsers/power_models_data.jl | 40 +++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/parsers/power_models_data.jl b/src/parsers/power_models_data.jl index 0ec1b7433d..f95094ebf1 100644 --- a/src/parsers/power_models_data.jl +++ b/src/parsers/power_models_data.jl @@ -374,7 +374,14 @@ function make_hydro_gen( ramp_agc = get(d, "ramp_agc", get(d, "ramp_10", get(d, "ramp_30", abs(d["pmax"])))) curtailcost = HydroGenerationCost(zero(CostCurve), 0.0) - base_conversion = sys_mbase / d["mbase"] + if d["mbase"] != 0.0 + mbase = d["mbase"] + else + @warn "Generator $gen_name has base power equal to zero: $(d["mbase"]). Changing it to system base: $sys_mbase" + mbase = sys_mbase + end + + base_conversion = sys_mbase / mbase return HydroDispatch(; # No way to define storage parameters for gens in PM so can only make HydroDispatch name = gen_name, available = Bool(d["gen_status"]), @@ -394,7 +401,7 @@ function make_hydro_gen( ramp_limits = (up = ramp_agc, down = ramp_agc), time_limits = nothing, operation_cost = curtailcost, - base_power = d["mbase"], + base_power = mbase, ) end @@ -405,12 +412,20 @@ function make_renewable_dispatch( sys_mbase::Float64, ) cost = RenewableGenerationCost(zero(CostCurve)) - base_conversion = sys_mbase / d["mbase"] + + if d["mbase"] != 0.0 + mbase = d["mbase"] + else + @warn "Generator $gen_name has base power equal to zero: $(d["mbase"]). Changing it to system base: $sys_mbase" + mbase = sys_mbase + end + + base_conversion = sys_mbase / mbase rating = calculate_rating(d["pmax"], d["qmax"]) - if rating > d["mbase"] - @warn "rating is larger than base power for $gen_name, setting to $(d["mbase"])" - rating = d["mbase"] + if rating > mbase + @warn "rating is larger than base power for $gen_name, setting to $mbase" + rating = mbase end generator = RenewableDispatch(; @@ -427,7 +442,7 @@ function make_renewable_dispatch( ), power_factor = 1.0, operation_cost = cost, - base_power = d["mbase"], + base_power = mbase, ) return generator @@ -439,7 +454,14 @@ function make_renewable_fix( bus::ACBus, sys_mbase::Float64, ) - base_conversion = sys_mbase / d["mbase"] + if d["mbase"] != 0.0 + mbase = d["mbase"] + else + @warn "Generator $gen_name has base power equal to zero: $(d["mbase"]). Changing it to system base: $sys_mbase" + mbase = sys_mbase + end + + base_conversion = sys_mbase / mbase generator = RenewableNonDispatch(; name = gen_name, available = Bool(d["gen_status"]), @@ -449,7 +471,7 @@ function make_renewable_fix( rating = float(d["pmax"]) * base_conversion, prime_mover_type = parse_enum_mapping(PrimeMovers, d["type"]), power_factor = 1.0, - base_power = d["mbase"], + base_power = mbase, ) return generator From 774695e221fec676ccffc31f26cad9137d25a85b Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Wed, 11 Dec 2024 15:01:06 -0700 Subject: [PATCH 8/8] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a915a44253..898d0157af 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PowerSystems" uuid = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd" authors = ["Jose Daniel Lara", "Daniel Thom", "Clayton Barrows", "Sourabh Dalvi", "Dheepak Krishnamurthy"] -version = "4.4.0" +version = "4.4.1" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"