diff --git a/CHANGELOG.md b/CHANGELOG.md index efedb06..e2c584e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added - Sub-hourly unit commitment -- Added function `UnitCommitment.write(filename, solution)` to simplify saving the solution to a file +- Added function `UnitCommitment.write(filename, solution)` - Added mathematical formulation to the documentation ### Changed @@ -18,7 +18,8 @@ - `model.isf` becomes `model[:isf]` - `model.lodf` becomes `model[:lodf]` - The function `UnitCommitment.get_solution` has been renamed to `UnitCommitment.solution` -- The function `UnitCommitment.fix!(instance)`, which attempts to repair an invalid instance, has been renamed to `UnitCommitment.repair!(instance)` +- All function that do not appear in the documentation have been renamed to `_something`. + These functions are not part of the public API and may change without notice. ## [0.1.1] - 2020-11-16 diff --git a/benchmark/run.jl b/benchmark/run.jl index 783dabe..2af77bf 100644 --- a/benchmark/run.jl +++ b/benchmark/run.jl @@ -10,6 +10,8 @@ using Logging using Printf using LinearAlgebra +UnitCommitment._setup_logger() + function main() basename, suffix = split(ARGS[1], ".") solution_filename = "results/$basename.$suffix.sol.json" @@ -18,7 +20,6 @@ function main() time_limit = 60 * 20 BLAS.set_num_threads(4) - global_logger(TimeLogger(initial_time = time())) total_time = @elapsed begin @info "Reading: $basename" diff --git a/src/convert.jl b/src/convert.jl index 6059e7e..b7b47fd 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -4,7 +4,7 @@ using DataStructures, JSON, GZip -function read_json(path::String)::OrderedDict +function _read_json(path::String)::OrderedDict if endswith(path, ".gz") file = GZip.gzopen(path) else @@ -13,16 +13,16 @@ function read_json(path::String)::OrderedDict return JSON.parse(file, dicttype=()->DefaultOrderedDict(nothing)) end -function read_egret_solution(path::String)::OrderedDict - egret = read_json(path) +function _read_egret_solution(path::String)::OrderedDict + egret = _read_json(path) T = length(egret["system"]["time_keys"]) - solution = OrderedDict() - is_on = solution["Is on"] = OrderedDict() + solution = OrderedDict() + is_on = solution["Is on"] = OrderedDict() production = solution["Production (MW)"] = OrderedDict() - reserve = solution["Reserve (MW)"] = OrderedDict() + reserve = solution["Reserve (MW)"] = OrderedDict() production_cost = solution["Production cost (\$)"] = OrderedDict() - startup_cost = solution["Startup cost (\$)"] = OrderedDict() + startup_cost = solution["Startup cost (\$)"] = OrderedDict() for (gen_name, gen_dict) in egret["elements"]["generator"] if endswith(gen_name, "_T") || endswith(gen_name, "_R") diff --git a/src/initcond.jl b/src/initcond.jl index 20deb45..b1be33a 100644 --- a/src/initcond.jl +++ b/src/initcond.jl @@ -11,8 +11,10 @@ Generates feasible initial conditions for the given instance, by constructing and solving a single-period mixed-integer optimization problem, using the given optimizer. The instance is modified in-place. """ -function generate_initial_conditions!(instance::UnitCommitmentInstance, - optimizer) +function generate_initial_conditions!( + instance::UnitCommitmentInstance, + optimizer, +)::Nothing G = instance.units B = instance.buses t = 1 @@ -73,4 +75,5 @@ function generate_initial_conditions!(instance::UnitCommitmentInstance, g.initial_status = -24 end end + return end diff --git a/src/instance.jl b/src/instance.jl index facd9a3..8cb9491 100644 --- a/src/instance.jl +++ b/src/instance.jl @@ -5,8 +5,8 @@ using Printf using JSON using DataStructures +using GZip import Base: getindex, time -import GZip mutable struct Bus @@ -116,18 +116,19 @@ end function read(path::AbstractString)::UnitCommitmentInstance if endswith(path, ".gz") - return read(GZip.gzopen(path)) + return _read(gzopen(path)) else - return read(open(path)) + return _read(open(path)) end end -function read(file::IO)::UnitCommitmentInstance - return from_json(JSON.parse(file, dicttype=()->DefaultOrderedDict(nothing))) +function _read(file::IO)::UnitCommitmentInstance + return _from_json(JSON.parse(file, dicttype=()->DefaultOrderedDict(nothing))) end -function from_json(json; repair=true) + +function _from_json(json; repair=true) units = Unit[] buses = Bus[] contingencies = Contingency[] @@ -160,16 +161,20 @@ function from_json(json; repair=true) end # Read parameters - power_balance_penalty = timeseries(json["Parameters"]["Power balance penalty (\$/MW)"], - default=[1000.0 for t in 1:T]) + power_balance_penalty = timeseries( + json["Parameters"]["Power balance penalty (\$/MW)"], + default=[1000.0 for t in 1:T], + ) # Read buses for (bus_name, dict) in json["Buses"] - bus = Bus(bus_name, - length(buses), - timeseries(dict["Load (MW)"]), - Unit[], - PriceSensitiveLoad[]) + bus = Bus( + bus_name, + length(buses), + timeseries(dict["Load (MW)"]), + Unit[], + PriceSensitiveLoad[], + ) name_to_bus[bus_name] = bus push!(buses, bus) end @@ -251,25 +256,35 @@ function from_json(json; repair=true) # Read reserves reserves = Reserves(zeros(T)) if "Reserves" in keys(json) - reserves.spinning = timeseries(json["Reserves"]["Spinning (MW)"], - default=zeros(T)) + reserves.spinning = timeseries( + json["Reserves"]["Spinning (MW)"], + default=zeros(T), + ) end # Read transmission lines if "Transmission lines" in keys(json) for (line_name, dict) in json["Transmission lines"] - line = TransmissionLine(line_name, - length(lines) + 1, - name_to_bus[dict["Source bus"]], - name_to_bus[dict["Target bus"]], - scalar(dict["Reactance (ohms)"]), - scalar(dict["Susceptance (S)"]), - timeseries(dict["Normal flow limit (MW)"], - default=[1e8 for t in 1:T]), - timeseries(dict["Emergency flow limit (MW)"], - default=[1e8 for t in 1:T]), - timeseries(dict["Flow limit penalty (\$/MW)"], - default=[5000.0 for t in 1:T])) + line = TransmissionLine( + line_name, + length(lines) + 1, + name_to_bus[dict["Source bus"]], + name_to_bus[dict["Target bus"]], + scalar(dict["Reactance (ohms)"]), + scalar(dict["Susceptance (S)"]), + timeseries( + dict["Normal flow limit (MW)"], + default=[1e8 for t in 1:T], + ), + timeseries( + dict["Emergency flow limit (MW)"], + default=[1e8 for t in 1:T], + ), + timeseries( + dict["Flow limit penalty (\$/MW)"], + default=[5000.0 for t in 1:T], + ), + ) name_to_line[line_name] = line push!(lines, line) end @@ -295,24 +310,27 @@ function from_json(json; repair=true) if "Price-sensitive loads" in keys(json) for (load_name, dict) in json["Price-sensitive loads"] bus = name_to_bus[dict["Bus"]] - load = PriceSensitiveLoad(load_name, - bus, - timeseries(dict["Demand (MW)"]), - timeseries(dict["Revenue (\$/MW)"]), - ) + load = PriceSensitiveLoad( + load_name, + bus, + timeseries(dict["Demand (MW)"]), + timeseries(dict["Revenue (\$/MW)"]), + ) push!(bus.price_sensitive_loads, load) push!(loads, load) end end - instance = UnitCommitmentInstance(T, - power_balance_penalty, - units, - buses, - lines, - reserves, - contingencies, - loads) + instance = UnitCommitmentInstance( + T, + power_balance_penalty, + units, + buses, + lines, + reserves, + contingencies, + loads, + ) if repair UnitCommitment.repair!(instance) end @@ -335,7 +353,10 @@ Example modified = UnitCommitment.slice(instance, 1:2) """ -function slice(instance::UnitCommitmentInstance, range::UnitRange{Int})::UnitCommitmentInstance +function slice( + instance::UnitCommitmentInstance, + range::UnitRange{Int}, +)::UnitCommitmentInstance modified = deepcopy(instance) modified.time = length(range) modified.power_balance_penalty = modified.power_balance_penalty[range] diff --git a/src/log.jl b/src/log.jl index d329c43..8d986ab 100644 --- a/src/log.jl +++ b/src/log.jl @@ -56,9 +56,7 @@ function handle_message(logger::TimeLogger, end end -function setup_logger() +function _setup_logger() initial_time = time() global_logger(TimeLogger(initial_time=initial_time)) end - -export TimeLogger \ No newline at end of file diff --git a/src/model.jl b/src/model.jl index ac69979..1e546c7 100644 --- a/src/model.jl +++ b/src/model.jl @@ -50,7 +50,7 @@ function build_model(; if isf === nothing @info "Computing injection shift factors..." time_isf = @elapsed begin - isf = UnitCommitment.injection_shift_factors( + isf = UnitCommitment._injection_shift_factors( lines=instance.lines, buses=instance.buses, ) @@ -59,7 +59,7 @@ function build_model(; @info "Computing line outage factors..." time_lodf = @elapsed begin - lodf = UnitCommitment.line_outage_factors( + lodf = UnitCommitment._line_outage_factors( lines=instance.lines, buses=instance.buses, isf=isf, @@ -439,7 +439,7 @@ function _build_reserve_eqs!(model::JuMP.Model) end -function enforce_transmission( +function _enforce_transmission( ; model::JuMP.Model, violation::Violation, @@ -667,7 +667,7 @@ function optimize!( has_transmission || break - violations = find_violations(model) + violations = _find_violations(model) if isempty(violations) @info "No violations found" if large_gap @@ -677,7 +677,7 @@ function optimize!( break end else - enforce_transmission(model, violations) + _enforce_transmission(model, violations) end end @@ -685,7 +685,7 @@ function optimize!( end -function find_violations(model::JuMP.Model) +function _find_violations(model::JuMP.Model) instance = model[:instance] net_injection = model[:net_injection] overflow = model[:overflow] @@ -702,7 +702,7 @@ function find_violations(model::JuMP.Model) value(overflow[lm.name, t]) for lm in instance.lines, t in 1:instance.time ] - violations = UnitCommitment.find_violations( + violations = UnitCommitment._find_violations( instance=instance, net_injections=net_injection_values, overflow=overflow_values, @@ -715,12 +715,12 @@ function find_violations(model::JuMP.Model) end -function enforce_transmission( +function _enforce_transmission( model::JuMP.Model, violations::Vector{Violation}, )::Nothing for v in violations - enforce_transmission( + _enforce_transmission( model=model, violation=v, isf=model[:isf], @@ -730,4 +730,4 @@ function enforce_transmission( return end -export build_model \ No newline at end of file +export build_model diff --git a/src/screening.jl b/src/screening.jl index 951962f..872f7b2 100644 --- a/src/screening.jl +++ b/src/screening.jl @@ -22,7 +22,7 @@ function Violation(; monitored_line::TransmissionLine, outage_line::Union{TransmissionLine, Nothing}, amount::Float64, - ) :: Violation + )::Violation return Violation(time, monitored_line, outage_line, amount) end @@ -42,7 +42,7 @@ function ViolationFilter(; end -function offer(filter::ViolationFilter, v::Violation)::Nothing +function _offer(filter::ViolationFilter, v::Violation)::Nothing if v.monitored_line.offset ∉ keys(filter.queues) filter.queues[v.monitored_line.offset] = PriorityQueue{Violation, Float64}() end @@ -59,7 +59,7 @@ function offer(filter::ViolationFilter, v::Violation)::Nothing end -function query(filter::ViolationFilter)::Array{Violation, 1} +function _query(filter::ViolationFilter)::Array{Violation, 1} violations = Array{Violation,1}() time_queue = PriorityQueue{Violation, Float64}() for l in keys(filter.queues) @@ -85,31 +85,35 @@ end """ - function find_violations(instance::UnitCommitmentInstance, - net_injections::Array{Float64, 2}; - isf::Array{Float64,2}, - lodf::Array{Float64,2}, - max_per_line::Int = 1, - max_per_period::Int = 5, - ) :: Array{Violation, 1} - -Find transmission constraint violations (both pre-contingency, as well as post-contingency). - -The argument `net_injection` should be a (B-1) x T matrix, where B is the number of buses -and T is the number of time periods. The arguments `isf` and `lodf` can be computed using -UnitCommitment.injection_shift_factors and UnitCommitment.line_outage_factors. -The argument `overflow` specifies how much flow above the transmission limits (in MW) is allowed. -It should be an L x T matrix, where L is the number of transmission lines. + function _find_violations( + instance::UnitCommitmentInstance, + net_injections::Array{Float64, 2}; + isf::Array{Float64,2}, + lodf::Array{Float64,2}, + max_per_line::Int = 1, + max_per_period::Int = 5, + )::Array{Violation, 1} + +Find transmission constraint violations (both pre-contingency, as well as +post-contingency). + +The argument `net_injection` should be a (B-1) x T matrix, where B is the +number of buses and T is the number of time periods. The arguments `isf` and +`lodf` can be computed using UnitCommitment.injection_shift_factors and +UnitCommitment.line_outage_factors. The argument `overflow` specifies how much +flow above the transmission limits (in MW) is allowed. It should be an L x T +matrix, where L is the number of transmission lines. """ -function find_violations(; - instance::UnitCommitmentInstance, - net_injections::Array{Float64, 2}, - overflow::Array{Float64, 2}, - isf::Array{Float64,2}, - lodf::Array{Float64,2}, - max_per_line::Int = 1, - max_per_period::Int = 5, - )::Array{Violation, 1} +function _find_violations( + ; + instance::UnitCommitmentInstance, + net_injections::Array{Float64, 2}, + overflow::Array{Float64, 2}, + isf::Array{Float64,2}, + lodf::Array{Float64,2}, + max_per_line::Int = 1, + max_per_period::Int = 5, +)::Array{Violation, 1} B = length(instance.buses) - 1 L = length(instance.lines) @@ -120,20 +124,28 @@ function find_violations(; size(isf) == (L, B) || error("isf has incorrect size") size(lodf) == (L, L) || error("lodf has incorrect size") - filters = Dict(t => ViolationFilter(max_total=max_per_period, - max_per_line=max_per_line) - for t in 1:T) + filters = Dict( + t => ViolationFilter( + max_total=max_per_period, + max_per_line=max_per_line, + ) + for t in 1:T + ) pre_flow::Array{Float64} = zeros(L, K) # pre_flow[lm, thread] post_flow::Array{Float64} = zeros(L, L, K) # post_flow[lm, lc, thread] pre_v::Array{Float64} = zeros(L, K) # pre_v[lm, thread] post_v::Array{Float64} = zeros(L, L, K) # post_v[lm, lc, thread] - normal_limits::Array{Float64,2} = [l.normal_flow_limit[t] + overflow[l.offset, t] - for l in instance.lines, t in 1:T] + normal_limits::Array{Float64,2} = [ + l.normal_flow_limit[t] + overflow[l.offset, t] + for l in instance.lines, t in 1:T + ] - emergency_limits::Array{Float64,2} = [l.emergency_flow_limit[t] + overflow[l.offset, t] - for l in instance.lines, t in 1:T] + emergency_limits::Array{Float64,2} = [ + l.emergency_flow_limit[t] + overflow[l.offset, t] + for l in instance.lines, t in 1:T + ] is_vulnerable::Array{Bool} = zeros(Bool, L) for c in instance.contingencies @@ -153,46 +165,57 @@ function find_violations(; # Pre-contingency violations for lm in 1:L - pre_v[lm, k] = max(0.0, - pre_flow[lm, k] - normal_limits[lm, t], - - pre_flow[lm, k] - normal_limits[lm, t]) + pre_v[lm, k] = max( + 0.0, + pre_flow[lm, k] - normal_limits[lm, t], + - pre_flow[lm, k] - normal_limits[lm, t], + ) end # Post-contingency violations for lc in 1:L, lm in 1:L - post_v[lm, lc, k] = max(0.0, - post_flow[lm, lc, k] - emergency_limits[lm, t], - - post_flow[lm, lc, k] - emergency_limits[lm, t]) + post_v[lm, lc, k] = max( + 0.0, + post_flow[lm, lc, k] - emergency_limits[lm, t], + - post_flow[lm, lc, k] - emergency_limits[lm, t], + ) end # Offer pre-contingency violations for lm in 1:L if pre_v[lm, k] > 1e-5 - offer(filters[t], Violation(time=t, - monitored_line=instance.lines[lm], - outage_line=nothing, - amount=pre_v[lm, k])) + _offer( + filters[t], + Violation( + time=t, + monitored_line=instance.lines[lm], + outage_line=nothing, + amount=pre_v[lm, k], + ), + ) end end # Offer post-contingency violations for lm in 1:L, lc in 1:L if post_v[lm, lc, k] > 1e-5 && is_vulnerable[lc] - offer(filters[t], Violation(time=t, - monitored_line=instance.lines[lm], - outage_line=instance.lines[lc], - amount=post_v[lm, lc, k])) + _offer( + filters[t], + Violation( + time=t, + monitored_line=instance.lines[lm], + outage_line=instance.lines[lc], + amount=post_v[lm, lc, k], + ), + ) end end end violations = Violation[] for t in 1:instance.time - append!(violations, query(filters[t])) + append!(violations, _query(filters[t])) end return violations end - - -export Violation, ViolationFilter, offer, query, find_violations \ No newline at end of file diff --git a/src/sensitivity.jl b/src/sensitivity.jl index 2c51407..48c559f 100644 --- a/src/sensitivity.jl +++ b/src/sensitivity.jl @@ -5,16 +5,17 @@ using SparseArrays, Base.Threads, LinearAlgebra, JuMP """ - injection_shift_factors(; buses, lines) + _injection_shift_factors(; buses, lines) -Returns a (B-1)xL matrix M, where B is the number of buses and L is the number of transmission -lines. For a given bus b and transmission line l, the entry M[l.offset, b.offset] indicates -the amount of power (in MW) that flows through transmission line l when 1 MW of power is -injected at the slack bus (the bus that has offset zero) and withdrawn from b. +Returns a (B-1)xL matrix M, where B is the number of buses and L is the number +of transmission lines. For a given bus b and transmission line l, the entry +M[l.offset, b.offset] indicates the amount of power (in MW) that flows through +transmission line l when 1 MW of power is injected at the slack bus (the bus +that has offset zero) and withdrawn from b. """ -function injection_shift_factors(; buses, lines) - susceptance = susceptance_matrix(lines) - incidence = reduced_incidence_matrix(lines = lines, buses = buses) +function _injection_shift_factors(; buses::Array{Bus}, lines::Array{TransmissionLine}) + susceptance = _susceptance_matrix(lines) + incidence = _reduced_incidence_matrix(lines=lines, buses=buses) laplacian = transpose(incidence) * susceptance * incidence isf = susceptance * incidence * inv(Array(laplacian)) return isf @@ -22,14 +23,15 @@ end """ - reduced_incidence_matrix(; buses::Array{Bus}, lines::Array{TransmissionLine}) + _reduced_incidence_matrix(; buses::Array{Bus}, lines::Array{TransmissionLine}) -Returns the incidence matrix for the network, with the column corresponding to the slack -bus is removed. More precisely, returns a (B-1) x L matrix, where B is the number of buses -and L is the number of lines. For each row, there is a 1 element and a -1 element, indicating -the source and target buses, respectively, for that line. +Returns the incidence matrix for the network, with the column corresponding to +the slack bus is removed. More precisely, returns a (B-1) x L matrix, where B +is the number of buses and L is the number of lines. For each row, there is a 1 +element and a -1 element, indicating the source and target buses, respectively, +for that line. """ -function reduced_incidence_matrix(; buses::Array{Bus}, lines::Array{TransmissionLine}) +function _reduced_incidence_matrix(; buses::Array{Bus}, lines::Array{TransmissionLine}) matrix = spzeros(Float64, length(lines), length(buses) - 1) for line in lines if line.source.offset > 0 @@ -43,33 +45,37 @@ function reduced_incidence_matrix(; buses::Array{Bus}, lines::Array{Transmission end """ - susceptance_matrix(lines::Array{TransmissionLine}) + _susceptance_matrix(lines::Array{TransmissionLine}) -Returns a LxL diagonal matrix, where each diagonal entry is the susceptance of the -corresponding transmission line. +Returns a LxL diagonal matrix, where each diagonal entry is the susceptance of +the corresponding transmission line. """ -function susceptance_matrix(lines::Array{TransmissionLine}) +function _susceptance_matrix(lines::Array{TransmissionLine}) return Diagonal([l.susceptance for l in lines]) end """ - line_outage_factors(; buses, lines, isf) + _line_outage_factors(; buses, lines, isf) -Returns a LxL matrix containing the Line Outage Distribution Factors (LODFs) for the -given network. This matrix how does the pre-contingency flow change when each individual -transmission line is removed. +Returns a LxL matrix containing the Line Outage Distribution Factors (LODFs) +for the given network. This matrix how does the pre-contingency flow change +when each individual transmission line is removed. """ -function line_outage_factors(; - buses::Array{Bus, 1}, - lines::Array{TransmissionLine, 1}, - isf::Array{Float64,2}, - ) :: Array{Float64,2} - +function _line_outage_factors( + ; + buses::Array{Bus, 1}, + lines::Array{TransmissionLine, 1}, + isf::Array{Float64,2}, +) :: Array{Float64,2} n_lines, n_buses = size(isf) - incidence = Array(reduced_incidence_matrix(lines=lines, - buses=buses)) + incidence = Array( + _reduced_incidence_matrix( + lines=lines, + buses=buses, + ), + ) lodf::Array{Float64,2} = isf * transpose(incidence) m, n = size(lodf) for i in 1:n diff --git a/src/sysimage.jl b/src/sysimage.jl index 79887d1..259b6fc 100644 --- a/src/sysimage.jl +++ b/src/sysimage.jl @@ -10,14 +10,17 @@ using JuMP using MathOptInterface using SparseArrays -pkg = [:DataStructures, - :JSON, - :JuMP, - :MathOptInterface, - :SparseArrays, - ] +pkg = [ + :DataStructures, + :JSON, + :JuMP, + :MathOptInterface, + :SparseArrays, +] @info "Building system image..." -create_sysimage(pkg, - precompile_statements_file="build/precompile.jl", - sysimage_path="build/sysimage.so") +create_sysimage( + pkg, + precompile_statements_file="build/precompile.jl", + sysimage_path="build/sysimage.so", +) diff --git a/src/validate.jl b/src/validate.jl index 19fdcf8..8574a7f 100644 --- a/src/validate.jl +++ b/src/validate.jl @@ -9,9 +9,10 @@ bin(x) = [xi > 0.5 for xi in x] """ repair!(instance) -Verifies that the given unit commitment instance is valid and automatically fixes -some validation errors if possible, issuing a warning for each error found. -If a validation error cannot be automatically fixed, issues an exception. +Verifies that the given unit commitment instance is valid and automatically +fixes some validation errors if possible, issuing a warning for each error +found. If a validation error cannot be automatically fixed, issues an +exception. Returns the number of validation errors found. """ @@ -86,16 +87,17 @@ Verifies that the given solution is feasible for the problem. If feasible, silently returns true. In infeasible, returns false and prints the validation errors to the screen. -This function is implemented independently from the optimization model in `model.jl`, and -therefore can be used to verify that the model is indeed producing valid solutions. It -can also be used to verify the solutions produced by other optimization packages. +This function is implemented independently from the optimization model in +`model.jl`, and therefore can be used to verify that the model is indeed +producing valid solutions. It can also be used to verify the solutions produced +by other optimization packages. """ function validate(instance::UnitCommitmentInstance, solution::Union{Dict,OrderedDict}; )::Bool err_count = 0 - err_count += validate_units(instance, solution) - err_count += validate_reserve_and_demand(instance, solution) + err_count += _validate_units(instance, solution) + err_count += _validate_reserve_and_demand(instance, solution) if err_count > 0 @error "Found $err_count validation errors" @@ -106,7 +108,7 @@ function validate(instance::UnitCommitmentInstance, end -function validate_units(instance, solution; tol=0.01) +function _validate_units(instance, solution; tol=0.01) err_count = 0 for unit in instance.units @@ -300,7 +302,7 @@ function validate_units(instance, solution; tol=0.01) end -function validate_reserve_and_demand(instance, solution, tol=0.01) +function _validate_reserve_and_demand(instance, solution, tol=0.01) err_count = 0 for t in 1:instance.time load_curtail = 0 diff --git a/test/convert_test.jl b/test/convert_test.jl index bc1496e..f6ee042 100644 --- a/test/convert_test.jl +++ b/test/convert_test.jl @@ -6,7 +6,7 @@ using UnitCommitment @testset "convert" begin @testset "EGRET solution" begin - solution = UnitCommitment.read_egret_solution("fixtures/egret_output.json.gz") + solution = UnitCommitment._read_egret_solution("fixtures/egret_output.json.gz") for attr in ["Is on", "Production (MW)", "Production cost (\$)"] @test attr in keys(solution) @test "115_STEAM_1" in keys(solution[attr]) @@ -16,4 +16,4 @@ using UnitCommitment @test solution["Startup cost (\$)"]["315_CT_6"][15:20] == [0., 0., 5665.23, 0., 0., 0.] @test length(keys(solution["Is on"])) == 154 end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 201452e..672860f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ using Test using UnitCommitment -UnitCommitment.setup_logger() +UnitCommitment._setup_logger() @testset "UnitCommitment" begin include("instance_test.jl") diff --git a/test/screening_test.jl b/test/screening_test.jl index 1670cf0..372f780 100644 --- a/test/screening_test.jl +++ b/test/screening_test.jl @@ -3,51 +3,83 @@ # Released under the modified BSD license. See COPYING.md for more details. using UnitCommitment, Test, LinearAlgebra +import UnitCommitment: Violation, _offer, _query @testset "Screening" begin @testset "Violation filter" begin instance = UnitCommitment.read_benchmark("test/case14") - filter = ViolationFilter(max_per_line=1, max_total=2) + filter = UnitCommitment.ViolationFilter(max_per_line=1, max_total=2) - offer(filter, Violation(time=1, - monitored_line=instance.lines[1], - outage_line=nothing, - amount=100.)) - - offer(filter, Violation(time=1, - monitored_line=instance.lines[1], - outage_line=instance.lines[1], - amount=300.)) - - offer(filter, Violation(time=1, - monitored_line=instance.lines[1], - outage_line=instance.lines[5], - amount=500.)) - - offer(filter, Violation(time=1, - monitored_line=instance.lines[1], - outage_line=instance.lines[4], - amount=400.)) - - offer(filter, Violation(time=1, - monitored_line=instance.lines[2], - outage_line=instance.lines[1], - amount=200.)) - - offer(filter, Violation(time=1, - monitored_line=instance.lines[2], - outage_line=instance.lines[8], - amount=100.)) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[1], + outage_line=nothing, + amount=100., + ), + ) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[1], + outage_line=instance.lines[1], + amount=300., + ), + ) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[1], + outage_line=instance.lines[5], + amount=500., + ), + ) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[1], + outage_line=instance.lines[4], + amount=400., + ), + ) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[2], + outage_line=instance.lines[1], + amount=200., + ), + ) + _offer( + filter, + Violation( + time=1, + monitored_line=instance.lines[2], + outage_line=instance.lines[8], + amount=100., + ) + ) - actual = query(filter) - expected = [Violation(time=1, - monitored_line=instance.lines[2], - outage_line=instance.lines[1], - amount=200.), - Violation(time=1, - monitored_line=instance.lines[1], - outage_line=instance.lines[5], - amount=500.)] + actual = _query(filter) + expected = [ + Violation( + time=1, + monitored_line=instance.lines[2], + outage_line=instance.lines[1], + amount=200., + ), + Violation( + time=1, + monitored_line=instance.lines[1], + outage_line=instance.lines[5], + amount=500., + ), + ] @test actual == expected end @@ -57,19 +89,24 @@ using UnitCommitment, Test, LinearAlgebra line.normal_flow_limit[t] = 1.0 line.emergency_flow_limit[t] = 1.0 end - isf = UnitCommitment.injection_shift_factors(lines=instance.lines, - buses=instance.buses) - lodf = UnitCommitment.line_outage_factors(lines=instance.lines, - buses=instance.buses, - isf=isf) + isf = UnitCommitment._injection_shift_factors( + lines=instance.lines, + buses=instance.buses, + ) + lodf = UnitCommitment._line_outage_factors( + lines=instance.lines, + buses=instance.buses, + isf=isf, + ) inj = [1000.0 for b in 1:13, t in 1:instance.time] overflow = [0.0 for l in instance.lines, t in 1:instance.time] - violations = UnitCommitment.find_violations(instance=instance, - net_injections=inj, - overflow=overflow, - isf=isf, - lodf=lodf) - + violations = UnitCommitment._find_violations( + instance=instance, + net_injections=inj, + overflow=overflow, + isf=isf, + lodf=lodf, + ) @test length(violations) == 20 end -end \ No newline at end of file +end diff --git a/test/sensitivity_test.jl b/test/sensitivity_test.jl index cfc97ee..0676a5a 100644 --- a/test/sensitivity_test.jl +++ b/test/sensitivity_test.jl @@ -7,7 +7,7 @@ using UnitCommitment, Test, LinearAlgebra @testset "Sensitivity" begin @testset "Susceptance matrix" begin instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment.susceptance_matrix(instance.lines) + actual = UnitCommitment._susceptance_matrix(instance.lines) @test size(actual) == (20, 20) expected = Diagonal([29.5, 7.83, 8.82, 9.9, 10.04, 10.2, 41.45, 8.35, 3.14, 6.93, @@ -18,8 +18,10 @@ using UnitCommitment, Test, LinearAlgebra @testset "Reduced incidence matrix" begin instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment.reduced_incidence_matrix(lines=instance.lines, - buses=instance.buses) + actual = UnitCommitment._reduced_incidence_matrix( + lines=instance.lines, + buses=instance.buses, + ) @test size(actual) == (20, 13) @test actual[1, 1] == -1.0 @test actual[3, 1] == 1.0 @@ -63,8 +65,10 @@ using UnitCommitment, Test, LinearAlgebra @testset "Injection Shift Factors (ISF)" begin instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment.injection_shift_factors(lines=instance.lines, - buses=instance.buses) + actual = UnitCommitment._injection_shift_factors( + lines=instance.lines, + buses=instance.buses, + ) @test size(actual) == (20, 13) @test round.(actual, digits=2) == [ -0.84 -0.75 -0.67 -0.61 -0.63 -0.66 -0.66 -0.65 -0.65 -0.64 -0.63 -0.63 -0.64; @@ -91,17 +95,23 @@ using UnitCommitment, Test, LinearAlgebra @testset "Line Outage Distribution Factors (LODF)" begin instance = UnitCommitment.read_benchmark("test/case14") - isf_before = UnitCommitment.injection_shift_factors(lines=instance.lines, - buses=instance.buses) - lodf = UnitCommitment.line_outage_factors(lines=instance.lines, - buses=instance.buses, - isf=isf_before) + isf_before = UnitCommitment._injection_shift_factors( + lines=instance.lines, + buses=instance.buses, + ) + lodf = UnitCommitment._line_outage_factors( + lines=instance.lines, + buses=instance.buses, + isf=isf_before, + ) for contingency in instance.contingencies for lc in contingency.lines prev_susceptance = lc.susceptance lc.susceptance = 0.0 - isf_after = UnitCommitment.injection_shift_factors(lines=instance.lines, - buses=instance.buses) + isf_after = UnitCommitment._injection_shift_factors( + lines=instance.lines, + buses=instance.buses, + ) lc.susceptance = prev_susceptance for lm in instance.lines expected = isf_after[lm.offset, :] diff --git a/test/validate_test.jl b/test/validate_test.jl index 3c46c24..9ca49c8 100644 --- a/test/validate_test.jl +++ b/test/validate_test.jl @@ -14,7 +14,7 @@ parse_case14() = JSON.parse(GZip.gzopen("../instances/test/case14.json.gz"), json = parse_case14() json["Generators"]["g1"]["Production cost curve (MW)"] = [100, 150, 200] json["Generators"]["g1"]["Production cost curve (\$)"] = [10, 25, 30] - instance = UnitCommitment.from_json(json, repair=false) + instance = UnitCommitment._from_json(json, repair=false) @test UnitCommitment.repair!(instance) == 4 end @@ -23,7 +23,7 @@ parse_case14() = JSON.parse(GZip.gzopen("../instances/test/case14.json.gz"), json["Generators"]["g1"]["Production cost curve (MW)"] = [100, 150] json["Generators"]["g1"]["Production cost curve (\$)"] = [100, 150] json["Generators"]["g1"]["Startup limit (MW)"] = 80 - instance = UnitCommitment.from_json(json, repair=false) + instance = UnitCommitment._from_json(json, repair=false) @test UnitCommitment.repair!(instance) == 1 end @@ -31,7 +31,7 @@ parse_case14() = JSON.parse(GZip.gzopen("../instances/test/case14.json.gz"), json = parse_case14() json["Generators"]["g1"]["Startup costs (\$)"] = [300, 200, 100] json["Generators"]["g1"]["Startup delays (h)"] = [8, 4, 2] - instance = UnitCommitment.from_json(json, repair=false) + instance = UnitCommitment._from_json(json, repair=false) @test UnitCommitment.repair!(instance) == 4 end