Skip to content

Commit bd902e5

Browse files
committed
Prototype to evaluate method-forward paradigm
Uses the ReusePatterns.jl @forward macro to remove field duplication in structs that have common sets of fields.
1 parent 58a3c3d commit bd902e5

19 files changed

+128
-47
lines changed

Manifest.toml

+20-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ git-tree-sha1 = "70885e5e038cba1c4c17a84ad6c40756e10a4fb5"
2121
uuid = "19ecbf4d-ef7c-5e4b-b54a-0a0ff23c5aed"
2222
version = "0.5.0"
2323

24+
[[Combinatorics]]
25+
deps = ["LinearAlgebra", "Polynomials", "Test"]
26+
git-tree-sha1 = "50b3ae4d643dc27eaff69fb6be06ee094d5500c9"
27+
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
28+
version = "0.7.0"
29+
2430
[[Compat]]
2531
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
2632
git-tree-sha1 = "84aa74986c5b9b898b0d1acaf3258741ee64754f"
@@ -124,6 +130,12 @@ version = "0.2.22"
124130
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
125131
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
126132

133+
[[Polynomials]]
134+
deps = ["LinearAlgebra", "SparseArrays", "Test"]
135+
git-tree-sha1 = "62142bd65d3f8aeb2226ec64dd8493349147df94"
136+
uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
137+
version = "0.5.2"
138+
127139
[[PooledArrays]]
128140
deps = ["Test"]
129141
git-tree-sha1 = "6ea4cfb9136d3ff2b9d30d6696cd72166a3b837c"
@@ -164,6 +176,12 @@ git-tree-sha1 = "f6fbf4ba64d295e146e49e021207993b6b48c7d1"
164176
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
165177
version = "0.5.2"
166178

179+
[[ReusePatterns]]
180+
deps = ["Combinatorics", "InteractiveUtils", "Statistics", "Test"]
181+
git-tree-sha1 = "929cd6332efae7a2d7aa80d9a257c600b4617d0d"
182+
uuid = "a39b5e78-89b5-562b-97d8-70689129df0c"
183+
version = "0.1.2"
184+
167185
[[SHA]]
168186
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
169187

@@ -205,9 +223,9 @@ version = "1.0.0"
205223

206224
[[Tables]]
207225
deps = ["IteratorInterfaceExtensions", "LinearAlgebra", "Requires", "TableTraits", "Test"]
208-
git-tree-sha1 = "e2abd466ca2f00a1bb8cb80024d59745cc8f91a6"
226+
git-tree-sha1 = "9e748316f5aa7b7753c90de612ef98fe8b0ea297"
209227
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
210-
version = "0.2.0"
228+
version = "0.2.1"
211229

212230
[[Test]]
213231
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]

Project.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
1212
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
1313
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1414
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
15+
ReusePatterns = "a39b5e78-89b5-562b-97d8-70689129df0c"
1516
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1617
TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e"
1718
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

src/PowerSystems.jl

+13
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ export RenewableFix
4949
export RenewableCurtailment
5050
export RenewableFullDispatch
5151

52+
export available
53+
export bus
54+
export econ
55+
export internal
56+
export name
57+
export tech
58+
export uuid
59+
export uuids
60+
5261
export ThermalGen
5362
export TechThermal
5463
export EconThermal
@@ -98,6 +107,7 @@ import JSON2
98107
import CSV
99108
import YAML
100109
import UUIDs
110+
import ReusePatterns: forward, @forward
101111

102112
#################################################################################
103113
# Includes
@@ -167,4 +177,7 @@ include("models/serialization.jl")
167177
include("utils/data.jl")
168178
import .UtilsData: TestData
169179

180+
# TODO DT: temporay workaround
181+
name(value::T) where T <: Component = value.name
182+
170183
end # module

src/internal.jl

+10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ end
99
"""Creates PowerSystemInternal with a UUID."""
1010
PowerSystemInternal() = PowerSystemInternal(UUIDs.uuid4())
1111

12+
"""Gets the UUID for any PowerSystemType."""
13+
function uuid(value::PowerSystemInternal)::Base.UUID
14+
return value.uuid
15+
end
16+
17+
"""Gets the UUIDs for a vector of any PowerSystemType."""
18+
function uuids(objs::Vector{T})::Vector{Base.UUID} where T <: PowerSystemType
19+
return [uuid(x) for x in objs]
20+
end
21+
1222
"""Gets the UUID for any PowerSystemType."""
1323
function get_uuid(obj::T)::Base.UUID where T <: PowerSystemType
1424
return obj.internal.uuid

src/models/generation.jl

+6
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,9 @@ function genclassifier(gen::Array{T}) where T <: Generator
5151
return generators
5252
end
5353

54+
# TODO DT temporary functions to support changes in the current PR.
55+
# Can be removed when all Generators implement the method-forward paradigm.
56+
name(value::Generator) = value.name
57+
available(value::Generator) = value.available
58+
bus(value::Generator) = value.bus
59+
tech(value::Generator) = value.tech
+55-22
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,63 @@
1-
abstract type
2-
RenewableGen <: Generator
1+
abstract type RenewableGen <: Generator end
2+
3+
# TODO DT temporary workaround
4+
function get_uuid(obj::T)::Base.UUID where T <: RenewableGen
5+
return uuid(obj)
36
end
47

5-
struct RenewableFix <: RenewableGen
8+
struct RenewableGenBase
69
name::String
710
available::Bool
811
bus::Bus
912
tech::TechRenewable
1013
internal::PowerSystemInternal
1114
end
1215

16+
function RenewableGenBase(name, available, bus, tech)
17+
return RenewableGenBase(name, available, bus, tech, PowerSystemInternal())
18+
end
19+
20+
RenewableGenBase(; name="init",
21+
status=false,
22+
bus=Bus(),
23+
installedcapacity=0.0) = RenewableGenBase(name, status, bus,
24+
installedcapacity)
25+
26+
@forward((RenewableGenBase, :internal), PowerSystemInternal)
27+
28+
name(value::RenewableGenBase) = value.name
29+
available(value::RenewableGenBase) = value.available
30+
bus(value::RenewableGenBase) = value.bus
31+
tech(value::RenewableGenBase) = value.tech
32+
33+
struct RenewableFix <: RenewableGen
34+
base::RenewableGenBase
35+
end
36+
1337
function RenewableFix(name, available, bus, tech)
14-
return RenewableFix(name, available, bus, tech, PowerSystemInternal())
38+
return RenewableFix(RenewableGenBase(name, available, bus, tech))
1539
end
1640

1741
"""Accepts installedcapacity as a Float64 and then creates a TechRenewable."""
1842
function RenewableFix(name, status, bus, installedcapacity::Float64)
1943
tech = TechRenewable(installedcapacity, nothing, 1.0)
20-
RenewableFix(name, status, bus, tech)
44+
RenewableFix(RenewableGenBase(name, status, bus, tech))
2145
end
2246

2347
RenewableFix(; name="init",
2448
status = false,
2549
bus = Bus(),
2650
installedcapacity = 0.0) = RenewableFix(name, status, bus, installedcapacity)
2751

52+
@forward((RenewableFix, :base), RenewableGenBase)
53+
2854
struct RenewableCurtailment <: RenewableGen
29-
name::String
30-
available::Bool
31-
bus::Bus
32-
tech::TechRenewable
55+
base::RenewableGenBase
3356
econ::Union{EconRenewable,Nothing}
34-
internal::PowerSystemInternal
3557
end
3658

3759
function RenewableCurtailment(name, available, bus, tech, econ)
38-
return RenewableCurtailment(name, available, bus, tech, econ, PowerSystemInternal())
60+
return RenewableCurtailment(RenewableGenBase(name, available, bus, tech), econ)
3961
end
4062

4163
"""Accepts installedcapacity as a Float64 and then creates a TechRenewable."""
@@ -50,21 +72,32 @@ RenewableCurtailment(; name = "init",
5072
installedcapacity = 0.0,
5173
econ = EconRenewable()) = RenewableCurtailment(name, status, bus, installedcapacity, econ)
5274

75+
econ(value::RenewableCurtailment) = value.econ
76+
77+
@forward((RenewableCurtailment, :base), RenewableGenBase)
78+
5379
struct RenewableFullDispatch <: RenewableGen
54-
name::String
55-
available::Bool
56-
bus::Bus
57-
tech::TechRenewable
80+
base::RenewableGenBase
5881
econ::Union{EconRenewable,Nothing}
59-
internal::PowerSystemInternal
6082
end
6183

6284
function RenewableFullDispatch(name, available, bus, tech, econ)
63-
return RenewableFullDispatch(name, available, bus, tech, econ, PowerSystemInternal())
85+
return RenewableFullDispatch(RenewableGenBase(name, available, bus, tech), econ)
6486
end
6587

66-
RenewableFullDispatch(; name = "init",
67-
status = false,
68-
bus= Bus(),
69-
installedcapacity = 0.0,
70-
econ = EconRenewable()) = RenewableCurtailment(name, status, bus, installedcapacity, econ)
88+
function RenewableFullDispatch(; name = "init",
89+
status = false,
90+
bus= Bus(),
91+
installedcapacity = 0.0,
92+
econ = EconRenewable())
93+
rc = RenewableCurtailment(name, status, bus, installedcapacity, econ)
94+
return RenewableFullDispatch(PowerSystems.name(rc),
95+
PowerSystems.available(rc),
96+
PowerSystems.bus(rc),
97+
PowerSystems.tech(rc),
98+
PowerSystems.econ(rc))
99+
end
100+
101+
econ(value::RenewableFullDispatch) = value.econ
102+
103+
@forward((RenewableFullDispatch, :base), RenewableGenBase)

src/parsers/dict_to_struct.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ Takes a string or symbol "name" and returns a list of devices within a collectio
115115
function _get_device(name::Union{String,Symbol}, collection, devices = [])
116116
if isa(collection,Array) && !isempty(collection) && isassigned(collection)
117117
fn = fieldnames(typeof(collection[1]))
118-
if :name in fn
119-
[push!(devices,d) for d in collection if d.name == name]
118+
if :name in fn || :base in fn
119+
[push!(devices,d) for d in collection if PowerSystems.name(d) == name]
120120
end
121121
elseif isa(collection, Dict) && !isempty(collection)
122122
for (key, val) in collection

src/parsers/forecast_parser.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function make_forecast_array(sys::Union{System,Array{Component,1}},ts_dict::Dict
7171
if (typeof(ts)==DataFrames.DataFrame) & (size(ts,2) > 2)
7272
devices = reduce(vcat,[_get_device(c,sys) for c in string.(names(ts)) if c != "DateTime"]) #retrieve devices from system that are in the timeseries data
7373
for d in devices
74-
push!(fc,Deterministic(d,"scalingfactor",TimeSeries.TimeArray(ts.DateTime,ts[Symbol(d.name)]))) # TODO: unhardcode scalingfactor
74+
push!(fc,Deterministic(d,"scalingfactor",TimeSeries.TimeArray(ts.DateTime,ts[Symbol(name(d))]))) # TODO: unhardcode scalingfactor
7575
end
7676
else
7777
devices = _get_device(key,sys) #retrieve the device object
@@ -109,12 +109,12 @@ function make_forecast_array(sys::ConcreteSystem,ts_dict::Dict)
109109
for (key,val) in ts_map
110110
ts = _access(ts_dict,vcat(val,key)) #retrieve timeseries data
111111
if (typeof(ts)==DataFrames.DataFrame) & (size(ts,2) > 2)
112-
devices = [d for d in all_devices if d.name in string.(names(ts))]
112+
devices = [d for d in all_devices if name(d) in string.(names(ts))]
113113
for d in devices
114-
push!(fc,Deterministic(d,"scalingfactor",TimeSeries.TimeArray(ts.DateTime,ts[Symbol(d.name)]))) # TODO: unhardcode scalingfactor
114+
push!(fc,Deterministic(d,"scalingfactor",TimeSeries.TimeArray(ts.DateTime,ts[Symbol(name(d))]))) # TODO: unhardcode scalingfactor
115115
end
116116
else
117-
devices = [d for d in all_devices if d.name == key]
117+
devices = [d for d in all_devices if name(d) == key]
118118

119119
cn = isa(ts,DataFrames.DataFrame) ? names(ts) : TimeSeries.colnames(ts)
120120
cn = [c for c in cn if c != :DateTime]
@@ -165,4 +165,4 @@ function parse_json(filename,device_names)
165165
end
166166
return Devices
167167
end
168-
=#
168+
=#

src/utils/IO/branchdata_checks.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function checkanglelimits!(branches::Array{<:Branch,1})
3636

3737
if hist[1]
3838

39-
branches[ix] = Line(deepcopy(l.name),deepcopy(l.available),
39+
branches[ix] = Line(deepcopy(name(l)),deepcopy(l.available),
4040
deepcopy(l.connectionpoints),deepcopy(l.r),
4141
deepcopy(l.x),deepcopy(l.b),deepcopy(l.rate),
4242
hist[2])
@@ -92,7 +92,7 @@ function calculatethermallimits!(branches::Array{<:Branch,1},basemva::Float64)
9292
end
9393

9494
if flag
95-
branches[ix] = Line(deepcopy(l.name),deepcopy(l.available),
95+
branches[ix] = Line(deepcopy(name(l)),deepcopy(l.available),
9696
deepcopy(l.connectionpoints),deepcopy(l.r),
9797
deepcopy(l.x),deepcopy(l.b),
9898
rate,deepcopy(l.anglelimits))

src/utils/IO/system_checks.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ end
4343
function pvbuscheck(buses::Array{Bus}, generators::Array{T}) where {T<:Generator}
4444
pv_list = -1*ones(Int64, length(generators))
4545
for (ix,g) in enumerate(generators)
46-
g.bus.bustype == "PV" ? pv_list[ix] = g.bus.number : continue
46+
bus(g).bustype == "PV" ? pv_list[ix] = bus(g).number : continue
4747
end
4848

4949
for b in buses

src/utils/print.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ function printPST(pst::Union{Component, GenClasses}, short = false,
99
if short
1010
pst_summary = Base.summary(pst)
1111
# objects of type TechnicalParams do not have a 'name' field
12-
if in(:name, fieldnames(typeof(pst)))
13-
print(io, "$pst_summary(name=\"$(pst.name)\")")
12+
if in(:name, fieldnames(typeof(pst))) || in(:base, fieldnames(typeof(pst)))
13+
print(io, "$pst_summary(name=\"$(name(pst))\")")
1414
else
1515
print(io, "$pst_summary")
1616
end

src/utils/ptdf_calculations.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ end
9696
function PTDF(branches::Array{T}, nodes::Array{Bus}, dist_slack::Array{Float64}=[0.1]) where {T<:Branch}
9797

9898
#Get axis names
99-
line_ax = [branch.name for branch in branches]
99+
line_ax = [name(branch) for branch in branches]
100100
bus_ax = [bus.number for bus in nodes]
101101
S, A = _buildptdf(branches, nodes, dist_slack)
102102

src/utils/ybus_calculations.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function build_ybus(buscount::Int64, branches::Array{T}) where {T <: Branch}
128128

129129
for b in branches
130130

131-
if b.name == "init"
131+
if name(b) == "init"
132132
@error "The data in Branch is incomplete" # TODO: raise error here?
133133
end
134134

src/validation/branch.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
function validate(branch::Branch)::Bool
44
is_valid = true
55

6-
@debug "Branch validation" branch.name is_valid
6+
@debug "Branch validation" name(branch) is_valid
77
return is_valid
88
end

src/validation/bus.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
function validate(bus::Bus)::Bool
44
is_valid = true
55

6-
@debug "Bus validation" bus.name bus.number is_valid
6+
@debug "Bus validation" name(bus) bus.number is_valid
77
return is_valid
88
end

src/validation/generator.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ end
2020
function validate(generator::Generator)::Bool
2121
is_valid = true
2222

23-
@debug "Generator validation" generator.name is_valid
23+
@debug "Generator validation" name(generator) is_valid
2424
return is_valid
2525
end

src/validation/load.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
function validate(load::ElectricLoad)::Bool
55
is_valid = true
66

7-
@debug "Load validation" load.name is_valid
7+
@debug "Load validation" name(load) is_valid
88
return is_valid
99
end

src/validation/storage.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
function validate(storage::Storage)::Bool
44
is_valid = true
55

6-
@debug "Storage validation" storage.name is_valid
6+
@debug "Storage validation" name(storage) is_valid
77
return is_valid
88
end

test/cdmparse.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ end
102102
@test compare_values_without_uuids(cdmsys.generators.hydro[1].econ,
103103
mpsys.generators.hydro[1].econ)
104104

105-
@test compare_values_without_uuids(cdmsys.generators.renewable[1].tech,
106-
mpsys.generators.renewable[1].tech)
105+
@test compare_values_without_uuids(tech(cdmsys.generators.renewable[1]),
106+
tech(mpsys.generators.renewable[1]))
107107

108-
@test compare_values_without_uuids(cdmsys.generators.renewable[1].econ,
109-
mpsys.generators.renewable[1].econ)
108+
@test compare_values_without_uuids(econ(cdmsys.generators.renewable[1]),
109+
econ(mpsys.generators.renewable[1]))
110110

111111
@test cdmsys.branches[1].rate ==
112112
[b for b in mpsys.branches if

0 commit comments

Comments
 (0)