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

Add ComponentSelector feature: IS portion #342

Merged
merged 54 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
386f39b
Scaffold ComponentSelector move from PA, copy over implementation
GabrielKS Mar 18, 2024
2d7aa8c
Move `TopologyComponentSelector` from IS to PSY
GabrielKS Mar 19, 2024
ba4a935
Make code work - WIP
tengis-nrl Mar 22, 2024
05f41d7
implement component selector
tengis-nrl Mar 24, 2024
46757f9
make PA tests pass
tengis-nrl Mar 24, 2024
cf8b87d
run formatter
tengis-nrl Mar 25, 2024
dca1578
remove tmp files
tengis-nrl Mar 26, 2024
abe2ea5
Remove temp file
GabrielKS Jun 10, 2024
8e00776
`ComponentSelector`: Restore getters to IS, refurbish docs
GabrielKS Jun 10, 2024
4a9dc0b
`ComponentSelector`: begin adding IS tests
GabrielKS Jun 10, 2024
96fce13
`ComponentSelector`: fix get_subselectors, test ListComponentSelector
GabrielKS Jun 10, 2024
b80e65e
`ComponentSelector`: finish adding IS tests, everything passes
GabrielKS Jun 10, 2024
f208f48
`ComponentSelector`: add subtype specs
GabrielKS Jun 10, 2024
348a98f
Reinstate `component_to_qualified_string` method
GabrielKS Jun 10, 2024
866b2c7
`ComponentSelector`: remove TODO
GabrielKS Jun 10, 2024
47274e8
Add `filterby` kwarg option to `get_components` and `get_subselectors`
GabrielKS Jun 26, 2024
9be7b2e
`ComponentSelector`: Implement `in(component, selector)`
GabrielKS Jul 17, 2024
a131164
Prototype `ComponentSelector` grouping (tests not updated)
GabrielKS Sep 20, 2024
bbb5ee7
Rename `select_components` to `make_selector`
GabrielKS Sep 24, 2024
4c1a087
Standardize `groupby` interface
GabrielKS Sep 24, 2024
15bfb74
Remove `Base.in` for `ComponentSelector`
GabrielKS Sep 24, 2024
efc9dee
Implement `get_component` for `ComponentSelectorElement`
GabrielKS Sep 24, 2024
69291a8
Centralize definition of component name delimeter
GabrielKS Sep 25, 2024
b064785
Refine interface and run formatter (tests still not updated)
GabrielKS Sep 25, 2024
f25df44
Add `groupby` validation and conversion, remove `filter_fn` validation
GabrielKS Sep 25, 2024
8a084d1
Fine-tune docstrings
GabrielKS Sep 25, 2024
fe52784
Make tests pass!
GabrielKS Sep 25, 2024
dce74d7
Relax typing of `get_components`, `get_groups`
GabrielKS Sep 25, 2024
b3af8f0
Run formatter
GabrielKS Sep 25, 2024
67c98d0
Make minor docstring changes
GabrielKS Sep 25, 2024
fdc6b24
`ComponentSelector`: Change typing to accommodate PowerSystems
GabrielKS Sep 26, 2024
64d29cb
Address PR comments: rename `subtype` -> `type`, etc.
GabrielKS Sep 30, 2024
f378055
Address PR comments: add function-first interfaces
GabrielKS Sep 30, 2024
fcbeaf4
Address PR comments: rename `filterby` -> `scope_limiter`, etc.
GabrielKS Oct 2, 2024
af4753d
`ComponentSelector`: validate in constructors, eliminate `default_name`
GabrielKS Oct 3, 2024
57cdaf9
Make `get_components` always return `FlattenIteratorWrapper`
GabrielKS Oct 4, 2024
6cbd928
Implement `filter(..., ::IS.FlattenIteratorWrapper)`
GabrielKS Oct 25, 2024
ee78d4b
Revert "Implement `filter(..., ::IS.FlattenIteratorWrapper)`"
GabrielKS Oct 25, 2024
adc09a9
`ComponentSelector`: Eliminate `scope_limiter` from public interface
GabrielKS Oct 26, 2024
e6cc155
Require filter function as first argument in `make_selector`
GabrielKS Oct 29, 2024
33189da
Make `groupby` default to `:each` instead of `:all`
GabrielKS Oct 29, 2024
993206b
Implement `rebuild_selector`: easy cases
GabrielKS Oct 29, 2024
8b0ec63
Add `RegroupedComponentSelector` to regroup `ListComponentSelector`
GabrielKS Oct 30, 2024
984d6b2
Add `get_available...` methods in IS
GabrielKS Dec 4, 2024
abe3388
Add `SystemLike` abstract type
GabrielKS Dec 6, 2024
5f5e871
Rename `SystemData` to `ComponentContainer`
GabrielKS Dec 6, 2024
74445d4
Centralize implementations of 'availability' in IS
GabrielKS Dec 6, 2024
866a965
Implement `get_component(s)` for `IS.Results`
GabrielKS Dec 7, 2024
18fb728
Add `InfrastructureSystemsContainer` methods on `ComponentContainer`
GabrielKS Dec 7, 2024
924ef4e
`ComponentSelector`: Clean up default name code
GabrielKS Dec 12, 2024
1967b1f
Remove duplicate `get_component(s)` definitions
GabrielKS Dec 12, 2024
0df7915
Move `ComponentContainer` tests to their own file
GabrielKS Dec 12, 2024
701591e
`ComponentSelector`: make `scope_limiter` an optional first argument
GabrielKS Jan 17, 2025
5bfccd4
Fix typo, remove signatures from docstrings
GabrielKS Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/InfrastructureSystems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ include("forecasts.jl")
include("static_time_series.jl")
include("time_series_parameters.jl")
include("containers.jl")
include("component_container.jl")
include("component_uuids.jl")
include("geographic_supplemental_attribute.jl")
include("generated/includes.jl")
Expand All @@ -136,11 +137,12 @@ include("supplemental_attribute_manager.jl")
include("components.jl")
include("iterators.jl")
include("component.jl")
include("results.jl")
include("serialization.jl")
include("system_data.jl")
include("subsystems.jl")
include("validation.jl")
include("component_selector.jl")
include("results.jl")
include("utils/print.jl")
include("utils/test.jl")
include("units.jl")
Expand Down
11 changes: 10 additions & 1 deletion src/Optimization/Optimization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import ..InfrastructureSystems:
InfrastructureSystemsType,
InfrastructureSystemsComponent,
Results,
get_base_power,
get_variables,
get_parameters,
get_total_cost,
get_optimizer_stats,
get_timestamp,
write_results,
get_source_data,
TimeSeriesCacheKey,
TimeSeriesCache,
configure_logging,
Expand All @@ -26,7 +34,8 @@ import ..InfrastructureSystems:
get_uuid,
compute_file_hash,
convert_for_path,
InvalidValue
InvalidValue,
COMPONENT_NAME_DELIMITER

using DocStringExtensions

Expand Down
11 changes: 5 additions & 6 deletions src/Optimization/optimization_container_keys.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
abstract type OptimizationContainerKey end

const _DELIMITER = "__"
const CONTAINER_KEY_EMPTY_META = ""

function make_key(::Type{T}, args...) where {T <: OptimizationContainerKey}
Expand All @@ -19,15 +18,15 @@ function encode_symbol(
::Type{U},
meta::String = CONTAINER_KEY_EMPTY_META,
) where {T <: InfrastructureSystemsType, U}
meta_ = isempty(meta) ? meta : _DELIMITER * meta
T_ = replace(replace(strip_module_name(T), "{" => _DELIMITER), "}" => "")
return Symbol("$(strip_module_name(string(U)))$(_DELIMITER)$(T_)" * meta_)
meta_ = isempty(meta) ? meta : COMPONENT_NAME_DELIMITER * meta
T_ = replace(replace(strip_module_name(T), "{" => COMPONENT_NAME_DELIMITER), "}" => "")
return Symbol("$(strip_module_name(string(U)))$(COMPONENT_NAME_DELIMITER)$(T_)" * meta_)
end

function check_meta_chars(meta::String)
# Underscores in this field will prevent us from being able to decode keys.
if occursin(_DELIMITER, meta)
throw(InvalidValue("'$_DELIMITER' is not allowed in meta"))
if occursin(COMPONENT_NAME_DELIMITER, meta)
throw(InvalidValue("'$COMPONENT_NAME_DELIMITER' is not allowed in meta"))
end
end

Expand Down
3 changes: 3 additions & 0 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const CONSTANT = Float64
const LIM_TOL = 1e-6
const XY_COORDS = @NamedTuple{x::Float64, y::Float64}

"Delimiter to use when constructing qualified names like component_type__component_name."
const COMPONENT_NAME_DELIMITER = "__"

# See https://github.com/JuliaLang/julia/issues/18485
"An equality predicate that is `true` for `NaN, NaN` (unlike `==`) and for `-0.0, 0.0` (unlike `isequal`)"
isequivalent(x, y) = isequal(x, y) || (x == y)
71 changes: 71 additions & 0 deletions src/component_container.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"A data structure that acts like a container of components"
abstract type ComponentContainer <: InfrastructureSystemsContainer end

# For each of these functions, `ComponentContainer` concrete subtypes MUST either implement
# appropriate methods or accept the default if it exists.
# - `get_components`: no default, must at least implement the `(type, system)` and `(filter_func, type, system)` signatures.
# - `get_component`: no default, must at least implement the `(type, system, name)` signature, may also want `(system, UUID)`, etc.
# - `get_available(::ComponentContainer, ::InfrastructureSystemsComponent)`: defaults to true
# - `get_available_components`: defaults to calling `get_components` with a filter function from `get_available`
# - `get_available_component`: defaults to calling `get_component` and checking `get_available`
# The notion of availability used in `get_available` and `get_available_component(s)` is up
# to the subtype, but it must be consistent across the three functions.

"Get an iterator of components of a certain specification from the `ComponentContainer`."
function get_components end

"Get the single component that matches the given specification from the `ComponentContainer`, or `nothing` if there is no match."
function get_component end

"Get whether the given component of the given system is available for use (defaults to true)."
get_available(::ComponentContainer, ::InfrastructureSystemsComponent) = true

Check warning on line 21 in src/component_container.jl

View check run for this annotation

Codecov / codecov/patch

src/component_container.jl#L21

Added line #L21 was not covered by tests

"Like [`get_components`](@ref) but only on components that are available."
function get_available_components end

"Like [`get_component`](@ref) but only on components that are available."
function get_available_component end

get_available_components(sys::ComponentContainer, args...; kwargs...) =
get_components(c -> get_available(sys, c), sys, args...; kwargs...)

get_available_components(
::Type{T},
sys::ComponentContainer,
args...;
kwargs...,
) where {T <: InfrastructureSystemsComponent} =
get_components(c -> get_available(sys, c), T, sys, args...; kwargs...)

get_available_components(
filter_func::Function,
::Type{T},
sys::ComponentContainer,
args...;
kwargs...,
) where {T <: InfrastructureSystemsComponent} =
get_components(x -> get_available(sys, x) && filter_func(x), T, sys, args...; kwargs...)

# Helper function to most generically implement get_available_component
function _get_available_component(sys::ComponentContainer, args...; kwargs...)
the_component = get_component(args...; kwargs...)
return get_available(sys, the_component) ? the_component : nothing
end

get_available_component(
::Type{T},
sys::ComponentContainer,
name::AbstractString;
kwargs...,
) where {T <: InfrastructureSystemsComponent} =
_get_available_component(sys, T, sys, name; kwargs...)

get_available_component(sys::ComponentContainer, args...; kwargs...) =
_get_available_component(sys, sys, args...; kwargs...)

# Satisfy the InfrastructureSystemsContainer interface
iterate_container(sys::ComponentContainer) =
get_components(InfrastructureSystemsComponent, sys)

get_num_members(sys::ComponentContainer) =
length(get_components(InfrastructureSystemsComponent, sys))
Loading
Loading