├── test ├── data │ ├── pti │ │ ├── parser_test_d.raw │ │ ├── parser_test_c.raw │ │ ├── parser_test_i.raw │ │ ├── parser_test_g.raw │ │ ├── parser_test_h.raw │ │ ├── parser_test_a.raw │ │ ├── parser_test_f.raw │ │ ├── parser_test_e.raw │ │ ├── parser_test_b.raw │ │ ├── case0.raw │ │ ├── two_winding_mag_test.raw │ │ ├── three_winding_test.raw │ │ ├── three_winding_test_2.raw │ │ ├── three_winding_mag_test.raw │ │ ├── frankenstein_00.raw │ │ ├── frankenstein_00_2.raw │ │ ├── case3.raw │ │ ├── frankenstein_20.raw │ │ ├── case5.raw │ │ ├── case7_tplgy.raw │ │ └── frankenstein_70.raw │ └── matpower │ │ ├── case2.m │ │ ├── case3_tnep.m │ │ ├── frankenstein_00.m │ │ ├── case6.m │ │ ├── case5_asym.m │ │ ├── case3.m │ │ ├── case5_pwlc.m │ │ ├── case5.m │ │ ├── case7_tplgy.m │ │ ├── case5_dc.m │ │ ├── case5_tnep.m │ │ ├── case14.m │ │ └── case30.m ├── REQUIRE ├── common.jl ├── runtests.jl ├── docs.jl ├── modify.jl ├── tnep.jl ├── ots.jl ├── output.jl ├── pti.jl └── matpower.jl ├── .gitignore ├── REQUIRE ├── docs ├── src │ ├── objective.md │ ├── relaxations.md │ ├── model.md │ ├── variables.md │ ├── index.md │ ├── formulations.md │ ├── parser.md │ ├── result-data.md │ ├── constraints.md │ ├── quickguide.md │ ├── developer.md │ └── specifications.md ├── README.md └── make.jl ├── .codecov.yml ├── .travis.yml ├── src ├── prob │ ├── opf_bf.jl │ ├── opf.jl │ ├── ots.jl │ ├── tnep.jl │ ├── pf_bf.jl │ └── pf.jl ├── PowerModels.jl ├── io │ └── common.jl ├── form │ ├── act.jl │ ├── wrm.jl │ ├── acr.jl │ ├── shared.jl │ └── df.jl └── core │ └── constraint.jl ├── CONTRIBUTING.md ├── LICENCE.md ├── README.md └── CHANGELOG.md /test/data/pti/parser_test_d.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00 2 | Q -------------------------------------------------------------------------------- /test/data/pti/parser_test_c.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 32, 0, 1, 60.00 2 | 3 | 4 | Q -------------------------------------------------------------------------------- /test/REQUIRE: -------------------------------------------------------------------------------- 1 | julia 0.6 2 | 3 | Cbc 4 | Ipopt 5 | SCS 6 | Juniper 0.2.0 7 | Pajarito 0.4.0 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.jl.cov 3 | *.jl.*.cov 4 | *.jl.mem 5 | deps/deps.jl 6 | docs/build/ 7 | docs/site/ 8 | docs/.documenter 9 | -------------------------------------------------------------------------------- /REQUIRE: -------------------------------------------------------------------------------- 1 | julia 0.6 2 | JSON 0.6.0 3 | InfrastructureModels 0.0.2 0.2- 4 | MathProgBase 0.5.4 5 | JuMP 0.17 0.19- 6 | Compat 0.26.0 7 | Memento 0.5.0 8 | -------------------------------------------------------------------------------- /docs/src/objective.md: -------------------------------------------------------------------------------- 1 | # Objective 2 | 3 | ```@autodocs 4 | Modules = [PowerModels] 5 | Pages = ["core/objective.jl"] 6 | Order = [:function] 7 | Private = true 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/src/relaxations.md: -------------------------------------------------------------------------------- 1 | # Relaxation Schemes 2 | 3 | ```@autodocs 4 | Modules = [PowerModels] 5 | Pages = ["core/relaxation_scheme.jl"] 6 | Order = [:function] 7 | Private = true 8 | ``` 9 | -------------------------------------------------------------------------------- /test/data/pti/parser_test_i.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 1002,, 345.0000, 2, 101, 201, 301,1.00000000, 0.000000 5 | 1005,'', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000 6 | Q -------------------------------------------------------------------------------- /test/data/pti/parser_test_g.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 'MTDC Ln 1', 0, 0, 0, 0, 0, 0.00, 0 15 | Q -------------------------------------------------------------------------------- /test/data/pti/parser_test_h.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 0 15 | 0 16 | 0 17 | 0 18 | 0 19 | 0 20 | 0 21 | something 22 | 0 23 | Q 24 | -------------------------------------------------------------------------------- /test/data/pti/parser_test_a.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 1002,, 345.0000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 1005,'', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | Q -------------------------------------------------------------------------------- /test/data/pti/parser_test_f.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 'MTDC Ln 1', 0, 0, 3, 0, 0, 0.00, 0 15 | 1, 2,'1',1, 0.0007, 0.00 16 | 1, 3,'1',1, 0.0006, 0.00 17 | 2, 3,'1',1, 0.0005, 0.00 18 | Q -------------------------------------------------------------------------------- /docs/src/model.md: -------------------------------------------------------------------------------- 1 | # Power Model 2 | 3 | ```@meta 4 | CurrentModule = PowerModels 5 | ``` 6 | 7 | All methods for constructing powermodels should be defined on the following type: 8 | 9 | ```@docs 10 | GenericPowerModel 11 | ``` 12 | 13 | which utilizes the following (internal) functions: 14 | 15 | ```@docs 16 | build_ref 17 | buspair_parameters 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/src/variables.md: -------------------------------------------------------------------------------- 1 | # Variables 2 | 3 | We provide the following methods to provide a compositional approach for defining common variables used in power flow models. These methods should always be defined over "GenericPowerModel". 4 | 5 | ```@autodocs 6 | Modules = [PowerModels] 7 | Pages = ["core/variable.jl"] 8 | Order = [:type, :function] 9 | Private = true 10 | ``` 11 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | status: 2 | project: # measuring the overall project coverage 3 | default: # context, you can create multiple ones with custom titles 4 | enabled: yes # must be yes|true to enable this status 5 | target: 80% 6 | threshold: 5% # allowed to drop X% and still result in a "success" PR status 7 | branches: 8 | threshold: 5% # allowed to drop X% and still result in a "success" commit status 9 | -------------------------------------------------------------------------------- /test/data/pti/parser_test_e.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 'MTDC Ln 1', 0, 3, 3, 0, 0, 0.00, 0 15 | 1,1001, 101, 201,'1 ', 0,9999.0000, 301 16 | 2,1002, 101, 201,'2 ', 0,9999.0000, 301 17 | 3,1003, 101, 201,'2 ', 0,9999.0000, 301 18 | 1, 2,'1',1, 0.0007, 0.00 19 | 1, 3,'1',1, 0.0006, 0.00 20 | 2, 3,'1',1, 0.0005, 0.00 21 | Q 22 | -------------------------------------------------------------------------------- /test/data/pti/parser_test_b.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | 3 | 4 | 0 / END OF BUS DATA, BEGIN LOAD DATA 5 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 6 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 7 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 8 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 9 | 1005,1002, 0,'1 ',1,1,1,0.00000E0,0.00000E0,2,'T2 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 10 | 5.21000E-3,1.77370E-1, 100.00, 1 11 | 1.025000, 115.000, 0.000, 84.00, 84.00, 84.00,0, 0,1.500000,0.500000,1.500000,0.500000,9999, 0, 0.00000, 0.00000, 0.000 12 | 1.000000, 13.800 13 | Q -------------------------------------------------------------------------------- /test/data/pti/case0.raw: -------------------------------------------------------------------------------- 1 | Header 1 2 | Header 2 3 | Header 3 4 | 1 'Line 1 ' 1.1000 -.1 1.1e-2 '1' '1.1' A,, 'A' /, "comment 1" 5 | 2,'Line, "2"', 2.2000 , -0.2 , 0.022, '2 ' ,' 2.2',B , , 'B' / comment, '2' 6 | 3 "Line, '3'" 3.3000 -0.3 33E-3 ' 3 ' ' 3.3' C , , 'C' / 'comment 3' 7 | 4 'Line 4' 44e-1 -0.4 0.44E-1 '4' '4.4' D , , 'D' ///comment,4 8 | 0 / END OF TEST1 DATA, BEGIN TEST2 DATA 9 | 1 'Line 1 ' 1.1000 -.1 1.1e-2 '1' '1.1' A,, 'A' /, "comment 1" 10 | 2,'Line, "2"', 2.2000 , -0.2 , 0.022, '2 ' ,' 2.2',B , , 'B' / comment, '2' 11 | Q 12 | 3 "Line, '3'" 3.3000 -0.3 33E-3 ' 3 ' ' 3.3' C , , 'C' / 'comment 3' 13 | 4 'Line 4' 44e-1 -0.4 0.44E-1 '4' '4.4' D , , 'D' ///comment,4 14 | 0 / END OF TEST2 DATA 15 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Building the Documentation for PowerModels.jl 2 | 3 | ## Installation 4 | We rely on [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl). To install it, run the following command in a julia session: 5 | 6 | ```julia 7 | Pkg.add("Documenter") 8 | ``` 9 | 10 | ## Building the Docs 11 | To preview the html output of the documents, run the following command: 12 | 13 | ```julia 14 | julia --color=yes make.jl 15 | ``` 16 | 17 | You can then view the documents in `build/index.html`. 18 | 19 | **Warning**: Do not `git commit` the contents of build (or any other content generated by Documenter) to your repository's master branch. This helps to avoid including unnessesary changes for anyone reviewing commits that happen to include documentation changes. 20 | 21 | For further details, please read the [documentation for Documenter.jl](https://juliadocs.github.io/Documenter.jl/stable/). -------------------------------------------------------------------------------- /test/data/matpower/case2.m: -------------------------------------------------------------------------------- 1 | % Case to test space based matlab matrix 2 | % And other hard to parse cases 3 | % also test data without a generator cost model 4 | 5 | function mpc = case2 6 | mpc.version = '2'; 7 | mpc.baseMVA = 100.00; 8 | 9 | mpc.bus = [ 10 | 1 3 0.00 0.00 0.00 0.00 1 1.0000 0.00000 20.00 1 1.100 0.900 0.00 0.00 0 0 11 | % comment in a matrix 12 | 144 1 184.31 52.53 0.00 0.00 1 1.0000 0.00000 100.00 1 1.100 0.900 0.00 0.00 0 0]; 13 | 14 | mpc.gen = [1 1098.17 140.74 952.77 -186.22 1.0400 2246.86 1 2042.60 0 612.78 2042.60 -186.22 952.77 -186.22 952.77 0 0 0 0 20.4260 0 0 0 0]; 15 | 16 | mpc.branch = [ 17 | 144 1 0.00122 0.04896 0.00000 2042.60 9999.00 9999.00 1.02000 0.000 1 0.00 0.00 -1096.78 -85.26 1098.17 140.74 0 0 0 0 % line comment 18 | ]; 19 | 20 | mpc.bus_name = { 21 | 'Bus 1 LV'; 22 | 'Bus 144 HV'; 23 | }; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: julia 2 | os: 3 | - linux 4 | - osx 5 | julia: 6 | - 0.6 7 | - nightly 8 | matrix: 9 | allow_failures: 10 | - julia: nightly 11 | cache: 12 | directories: 13 | - /home/travis/.julia 14 | addons: 15 | apt_packages: 16 | - gfortran 17 | 18 | before_install: 19 | # don't keep an old version of the code in the cache 20 | - julia -e 'if "PowerModels" in keys(Pkg.installed()) Pkg.rm("PowerModels"); Pkg.rm("PowerModels") end' 21 | - julia -e 'Pkg.update()' #make sure we get the latest version of METADATA 22 | - julia -e 'if !("Coverage" in keys(Pkg.installed())) Pkg.add("Coverage") end' 23 | - julia -e 'if !("Documenter" in keys(Pkg.installed())) Pkg.add("Documenter") end' 24 | 25 | script: 26 | - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi 27 | - julia -e 'Pkg.clone(pwd())' 28 | - julia -e 'Pkg.test("PowerModels", coverage=true)' 29 | 30 | after_success: 31 | - julia -e 'using Coverage; cd(Pkg.dir("PowerModels")); LCOV.writefile("lcov.info", process_folder(".")); run(pipeline(`curl -s https://codecov.io/bash`, `bash`))' 32 | - julia -e 'cd(Pkg.dir("PowerModels")); include(joinpath("docs", "make.jl"))' 33 | -------------------------------------------------------------------------------- /test/common.jl: -------------------------------------------------------------------------------- 1 | 2 | # TODO replace with the version from InfrastructureModels 3 | # used by data.jl and multinetwork.jl 4 | function compare_dict(d1, d2) 5 | for (k1,v1) in d1 6 | if !haskey(d2, k1) 7 | #println(k1) 8 | return false 9 | end 10 | v2 = d2[k1] 11 | 12 | if isa(v1, Number) 13 | if isnan(v1) 14 | #println("1.1") 15 | if !isnan(v2) 16 | #println(v1, " ", v2) 17 | return false 18 | end 19 | else 20 | #println("1.2") 21 | if !isapprox(v1, v2) 22 | #println(v1, " ", v2) 23 | return false 24 | end 25 | end 26 | elseif isa(v1, Dict) 27 | if !compare_dict(v1, v2) 28 | #println(v1, " ", v2) 29 | return false 30 | end 31 | else 32 | #println("2") 33 | if v1 != v2 34 | #println(v1, " ", v2) 35 | return false 36 | end 37 | end 38 | end 39 | return true 40 | end 41 | 42 | -------------------------------------------------------------------------------- /test/runtests.jl: -------------------------------------------------------------------------------- 1 | using PowerModels 2 | using InfrastructureModels 3 | using Memento 4 | 5 | # Suppress warnings during testing. 6 | setlevel!(getlogger(InfrastructureModels), "error") 7 | setlevel!(getlogger(PowerModels), "error") 8 | 9 | using Cbc 10 | using Ipopt 11 | using SCS 12 | using Pajarito 13 | using Juniper 14 | 15 | using Base.Test 16 | 17 | # default setup for solvers 18 | ipopt_solver = IpoptSolver(tol=1e-6, print_level=0) 19 | cbc_solver = CbcSolver() 20 | juniper_solver = JuniperSolver(IpoptSolver(tol=1e-4, print_level=0), mip_solver=cbc_solver, log_levels=[]) 21 | #juniper_solver = JuniperSolver(IpoptSolver(tol=1e-4, print_level=0), mip_solver=cbc_solver) 22 | pajarito_solver = PajaritoSolver(mip_solver=cbc_solver, cont_solver=ipopt_solver, log_level=0) 23 | scs_solver = SCSSolver(max_iters=1000000, verbose=0) 24 | 25 | 26 | @testset "PowerModels" begin 27 | 28 | include("common.jl") 29 | 30 | include("matpower.jl") 31 | 32 | include("pti.jl") 33 | 34 | include("psse.jl") 35 | 36 | include("output.jl") 37 | 38 | include("modify.jl") 39 | 40 | include("data.jl") 41 | 42 | include("pf.jl") 43 | 44 | include("opf.jl") 45 | 46 | include("ots.jl") 47 | 48 | include("tnep.jl") 49 | 50 | include("multinetwork.jl") 51 | 52 | include("docs.jl") 53 | 54 | end 55 | -------------------------------------------------------------------------------- /src/prob/opf_bf.jl: -------------------------------------------------------------------------------- 1 | export run_opf_bf, run_ac_opf_bf, run_dc_opf_bf 2 | 3 | "" 4 | function run_opf_bf(file, model_constructor, solver; kwargs...) 5 | if model_constructor != SOCDFPowerModel 6 | error(LOGGER, "The problem type opf_bf at the moment only supports the SOCDFForm formulation") 7 | end 8 | return run_generic_model(file, model_constructor, solver, post_opf_bf; kwargs...) 9 | end 10 | 11 | "" 12 | function post_opf_bf(pm::GenericPowerModel) 13 | variable_voltage(pm) 14 | variable_generation(pm) 15 | variable_branch_flow(pm) 16 | variable_branch_current(pm) 17 | variable_dcline_flow(pm) 18 | 19 | objective_min_fuel_cost(pm) 20 | 21 | for i in ids(pm, :ref_buses) 22 | constraint_theta_ref(pm, i) 23 | end 24 | 25 | for i in ids(pm, :bus) 26 | constraint_kcl_shunt(pm, i) 27 | end 28 | 29 | for i in ids(pm, :branch) 30 | constraint_flow_losses(pm, i) 31 | constraint_voltage_magnitude_difference(pm, i) 32 | constraint_branch_current(pm, i) 33 | 34 | constraint_voltage_angle_difference(pm, i) 35 | 36 | constraint_thermal_limit_from(pm, i) 37 | constraint_thermal_limit_to(pm, i) 38 | end 39 | 40 | for i in ids(pm, :dcline) 41 | constraint_dcline(pm, i) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /src/prob/opf.jl: -------------------------------------------------------------------------------- 1 | export run_opf, run_ac_opf, run_dc_opf 2 | 3 | "" 4 | function run_ac_opf(file, solver; kwargs...) 5 | return run_opf(file, ACPPowerModel, solver; kwargs...) 6 | end 7 | 8 | "" 9 | function run_dc_opf(file, solver; kwargs...) 10 | return run_opf(file, DCPPowerModel, solver; kwargs...) 11 | end 12 | 13 | "" 14 | function run_opf(file, model_constructor, solver; kwargs...) 15 | return run_generic_model(file, model_constructor, solver, post_opf; kwargs...) 16 | end 17 | 18 | "" 19 | function post_opf(pm::GenericPowerModel) 20 | variable_voltage(pm) 21 | variable_generation(pm) 22 | variable_branch_flow(pm) 23 | variable_dcline_flow(pm) 24 | 25 | objective_min_fuel_cost(pm) 26 | 27 | constraint_voltage(pm) 28 | 29 | for i in ids(pm, :ref_buses) 30 | constraint_theta_ref(pm, i) 31 | end 32 | 33 | for i in ids(pm, :bus) 34 | constraint_kcl_shunt(pm, i) 35 | end 36 | 37 | for i in ids(pm, :branch) 38 | constraint_ohms_yt_from(pm, i) 39 | constraint_ohms_yt_to(pm, i) 40 | 41 | constraint_voltage_angle_difference(pm, i) 42 | 43 | constraint_thermal_limit_from(pm, i) 44 | constraint_thermal_limit_to(pm, i) 45 | end 46 | 47 | for i in ids(pm, :dcline) 48 | constraint_dcline(pm, i) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /docs/make.jl: -------------------------------------------------------------------------------- 1 | using Documenter, PowerModels 2 | 3 | makedocs( 4 | modules = [PowerModels], 5 | format = :html, 6 | sitename = "PowerModels", 7 | authors = "Carleton Coffrin, Russell Bent, and contributors.", 8 | analytics = "UA-367975-10", 9 | pages = [ 10 | "Home" => "index.md", 11 | "Manual" => [ 12 | "Getting Started" => "quickguide.md", 13 | "Network Data Format" => "network-data.md", 14 | "Result Data Format" => "result-data.md" 15 | ], 16 | "Library" => [ 17 | "Network Formulations" => "formulations.md", 18 | "Problem Specifications" => "specifications.md", 19 | "Modeling Components" => [ 20 | "PowerModel" => "model.md", 21 | "Objective" => "objective.md", 22 | "Variables" => "variables.md", 23 | "Constraints" => "constraints.md" 24 | ], 25 | "Relaxation Schemes" => "relaxations.md", 26 | "File IO" => "parser.md" 27 | ], 28 | "Developer" => "developer.md", 29 | "Experiment Results" => "experiment-results.md" 30 | ] 31 | ) 32 | 33 | deploydocs( 34 | deps = nothing, 35 | make = nothing, 36 | target = "build", 37 | repo = "github.com/lanl-ansi/PowerModels.jl.git", 38 | julia = "0.6" 39 | ) 40 | -------------------------------------------------------------------------------- /src/PowerModels.jl: -------------------------------------------------------------------------------- 1 | isdefined(Base, :__precompile__) && __precompile__() 2 | 3 | module PowerModels 4 | 5 | using JSON 6 | using InfrastructureModels 7 | using MathProgBase 8 | using JuMP 9 | using Compat 10 | using Memento 11 | 12 | import Compat: @__MODULE__ 13 | 14 | # Create our module level logger (this will get precompiled) 15 | const LOGGER = getlogger(@__MODULE__) 16 | setlevel!(LOGGER, "info") 17 | 18 | # Register the module level logger at runtime so that folks can access the logger via `getlogger(PowerModels)` 19 | # NOTE: If this line is not included then the precompiled `PowerModels.LOGGER` won't be registered at runtime. 20 | __init__() = Memento.register(LOGGER) 21 | 22 | include("io/matpower.jl") 23 | include("io/common.jl") 24 | include("io/pti.jl") 25 | include("io/psse.jl") 26 | 27 | include("core/data.jl") 28 | include("core/base.jl") 29 | include("core/variable.jl") 30 | include("core/constraint_template.jl") 31 | include("core/constraint.jl") 32 | include("core/relaxation_scheme.jl") 33 | include("core/objective.jl") 34 | include("core/solution.jl") 35 | 36 | include("form/acp.jl") 37 | include("form/acr.jl") 38 | include("form/act.jl") 39 | include("form/dcp.jl") 40 | include("form/df.jl") 41 | include("form/wr.jl") 42 | include("form/wrm.jl") 43 | include("form/shared.jl") 44 | 45 | include("prob/pf.jl") 46 | include("prob/pf_bf.jl") 47 | include("prob/opf.jl") 48 | include("prob/opf_bf.jl") 49 | include("prob/ots.jl") 50 | include("prob/tnep.jl") 51 | 52 | end 53 | -------------------------------------------------------------------------------- /test/data/matpower/case3_tnep.m: -------------------------------------------------------------------------------- 1 | % based on NESTA v0.6.0 2 | function mpc = case3_lmbd_tnep 3 | mpc.version = '2'; 4 | mpc.baseMVA = 100.0; 5 | 6 | mpc.bus = [ 7 | 1 3 110.0 40.0 0.0 0.0 1 1.10000 -0.00000 240.0 1 1.10000 0.90000; 8 | 2 2 110.0 40.0 0.0 0.0 1 0.92617 7.25883 240.0 1 1.10000 0.90000; 9 | 3 2 95.0 50.0 0.0 0.0 1 0.90000 -17.26710 240.0 2 1.10000 0.90000; 10 | ]; 11 | 12 | mpc.gen = [ 13 | 1 148.067 54.697 1000.0 -1000.0 1.1 100.0 1 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 14 | 2 170.006 -8.791 1000.0 -1000.0 0.92617 100.0 1 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 15 | 3 0.0 -4.843 1000.0 -1000.0 0.9 100.0 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 16 | ]; 17 | 18 | mpc.gencost = [ 19 | 2 0.0 0.0 3 0.110000 5.000000 0.000000; 20 | 2 0.0 0.0 3 0.085000 1.200000 0.000000; 21 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; 22 | ]; 23 | 24 | mpc.branch = [ 25 | 1 2 0.042 0.9 0.3 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 26 | ]; 27 | 28 | %column_names% f_bus t_bus br_r br_x br_b rate_a rate_b rate_c tap shift br_status angmin angmax construction_cost 29 | mpc.ne_branch = [ 30 | 1 3 0.065 0.62 0.45 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0 1; 31 | 3 2 0.025 0.75 0.7 50.0 0.0 0.0 0.0 0.0 1 -30.0 30.0 1; 32 | 3 2 0.025 0.75 0.7 0.0 0.0 0.0 0.0 0.0 1 -30.0 30.0 1; 33 | ]; 34 | -------------------------------------------------------------------------------- /src/io/common.jl: -------------------------------------------------------------------------------- 1 | """ 2 | parse_file(file) 3 | 4 | Parses a Matpower .m `file` or PTI (PSS(R)E-v33) .raw `file` into a 5 | PowerModels data structure. 6 | """ 7 | function parse_file(file::String) 8 | if endswith(file, ".m") 9 | pm_data = PowerModels.parse_matpower(file) 10 | elseif endswith(lowercase(file), ".raw") 11 | warn(LOGGER, "The PSS(R)E parser is partially implimented, and currently only supports buses, loads, shunts, generators, branches, and transformers") 12 | pm_data = PowerModels.parse_psse(file) 13 | else 14 | pm_data = parse_json(file) 15 | end 16 | 17 | check_network_data(pm_data) 18 | 19 | return pm_data 20 | end 21 | 22 | 23 | "Adds PowerModels version to native data structure" 24 | function add_powermodels_version(data::Dict{String,Any}) 25 | data["version"] = Pkg.installed("PowerModels") 26 | end 27 | 28 | 29 | "" 30 | function parse_json(file_string::String) 31 | data_string = readstring(open(file_string)) 32 | return JSON.parse(data_string) 33 | end 34 | 35 | "" 36 | function check_network_data(data::Dict{String,Any}) 37 | add_powermodels_version(data) 38 | make_per_unit(data) 39 | check_connectivity(data) 40 | check_transformer_parameters(data) 41 | check_voltage_angle_differences(data) 42 | check_thermal_limits(data) 43 | check_branch_directions(data) 44 | check_branch_loops(data) 45 | check_bus_types(data) 46 | check_dcline_limits(data) 47 | check_voltage_setpoints(data) 48 | check_cost_functions(data) 49 | end 50 | -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | # PowerModels.jl Documentation 2 | 3 | ```@meta 4 | CurrentModule = PowerModels 5 | ``` 6 | 7 | ## Overview 8 | 9 | PowerModels.jl is a Julia/JuMP package for Steady-State Power Network Optimization. It provides utilities for parsing and modifying network data (see [PowerModels Network Data Format](@ref) for details), and is designed to enable computational evaluation of emerging power network formulations and algorithms in a common platform. 10 | 11 | The code is engineered to decouple [Problem Specifications](@ref) (e.g. Power Flow, Optimal Power Flow, ...) from [Network Formulations](@ref) (e.g. AC, DC-approximation, SOC-relaxation, ...). This enables the definition of a wide variety of power network formulations and their comparison on common problem specifications. 12 | 13 | ## Installation 14 | 15 | The latest stable release of PowerModels can be installed using the Julia package manager with 16 | 17 | ```julia 18 | Pkg.add("PowerModels") 19 | ``` 20 | 21 | For the current development version, "checkout" this package with 22 | 23 | ```julia 24 | Pkg.checkout("PowerModels") 25 | ``` 26 | 27 | At least one solver is required for running PowerModels. The open-source solver Ipopt is recommended, as it is extremely fast, and can be used to solve a wide variety of the problems and network formulations provided in PowerModels. The Ipopt solver can be installed via the package manager with 28 | 29 | ```julia 30 | Pkg.add("Ipopt") 31 | ``` 32 | 33 | Test that the package works by running 34 | 35 | ```julia 36 | Pkg.test("PowerModels") 37 | ``` 38 | -------------------------------------------------------------------------------- /src/prob/ots.jl: -------------------------------------------------------------------------------- 1 | #### General Assumptions of these OTS Models #### 2 | # 3 | # - if the branch status is 0 in the input, it is out of service and forced to 0 in OTS 4 | # - the network will be maintained as one connected component (i.e. at least n-1 edges) 5 | # 6 | 7 | export run_ots 8 | 9 | "" 10 | function run_ots(file, model_constructor, solver; kwargs...) 11 | return run_generic_model(file, model_constructor, solver, post_ots; solution_builder = get_ots_solution, kwargs...) 12 | end 13 | 14 | "" 15 | function post_ots(pm::GenericPowerModel) 16 | variable_branch_indicator(pm) 17 | variable_voltage_on_off(pm) 18 | variable_generation(pm) 19 | variable_branch_flow(pm) 20 | variable_dcline_flow(pm) 21 | 22 | objective_min_fuel_cost(pm) 23 | 24 | constraint_voltage_on_off(pm) 25 | 26 | for i in ids(pm, :ref_buses) 27 | constraint_theta_ref(pm, i) 28 | end 29 | 30 | for i in ids(pm, :bus) 31 | constraint_kcl_shunt(pm, i) 32 | end 33 | 34 | for i in ids(pm, :branch) 35 | constraint_ohms_yt_from_on_off(pm, i) 36 | constraint_ohms_yt_to_on_off(pm, i) 37 | 38 | constraint_voltage_angle_difference_on_off(pm, i) 39 | 40 | constraint_thermal_limit_from_on_off(pm, i) 41 | constraint_thermal_limit_to_on_off(pm, i) 42 | end 43 | 44 | for i in ids(pm, :dcline) 45 | constraint_dcline(pm, i) 46 | end 47 | end 48 | 49 | "" 50 | function get_ots_solution(pm::GenericPowerModel, sol::Dict{String,Any}) 51 | add_bus_voltage_setpoint(sol, pm) 52 | add_generator_power_setpoint(sol, pm) 53 | add_branch_flow_setpoint(sol, pm) 54 | add_branch_status_setpoint(sol, pm) 55 | end 56 | -------------------------------------------------------------------------------- /test/docs.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | @testset "code snippets from docs" begin 4 | @testset "DATA.md - The Network Data Dictionary" begin 5 | network_data = PowerModels.parse_file("../test/data/matpower/case14.m") 6 | 7 | @test length(network_data["bus"]) == 14 8 | @test length(network_data["branch"]) == 20 9 | end 10 | 11 | @testset "README.md - Modifying Network Data" begin 12 | network_data = PowerModels.parse_file("../test/data/matpower/case3.m") 13 | 14 | result = run_opf(network_data, ACPPowerModel, IpoptSolver(print_level=0)) 15 | 16 | @test result["status"] == :LocalOptimal 17 | @test isapprox(result["objective"], 5906.88; atol = 1e0) 18 | 19 | network_data["load"]["3"]["pd"] = 0.0 20 | network_data["load"]["3"]["qd"] = 0.0 21 | 22 | result = run_opf(network_data, ACPPowerModel, IpoptSolver(print_level=0)) 23 | 24 | @test result["status"] == :LocalOptimal 25 | @test isapprox(result["objective"], 2937.16; atol = 1e0) 26 | end 27 | 28 | @testset "README.md - JuMP Model Inspection" begin 29 | pm = build_generic_model("../test/data/matpower/case3.m", ACPPowerModel, PowerModels.post_opf) 30 | 31 | #pretty print the model to the terminal 32 | #print(pm.model) 33 | 34 | @test MathProgBase.numlinconstr(pm.model) == 8 35 | @test MathProgBase.numquadconstr(pm.model) == 12 36 | @test MathProgBase.numconstr(pm.model) - MathProgBase.numlinconstr(pm.model) - MathProgBase.numquadconstr(pm.model) == 12 37 | @test MathProgBase.numvar(pm.model) == 28 38 | 39 | result = solve_generic_model(pm, IpoptSolver(print_level=0)) 40 | 41 | @test result["status"] == :LocalOptimal 42 | @test isapprox(result["objective"], 5906.88; atol = 1e0) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Comments, Questions, Feature Requests, Bug Reports 2 | 3 | At this time, any kind of comment, question, feature request or bug report is welcome in the issue tracker. If you are asking a question, please search the issues for an answer before making a post. 4 | 5 | ## Code Contributions 6 | 7 | Community-driven development and enhancement of PowerModels is welcomed and encouraged. Please fell free to fork this repository and share your contributions to the master with a pull requests. 8 | 9 | That said it is important to keep in mind the code-quality requirements and scope of PowerModels in mind, before preparing a contribution. 10 | 11 | ### PowerModels Scope 12 | The primary motivation for PowerModels is to help researchers quickly and easily replicate _established_ results in power system optimization. 13 | More preliminary research and development efforts are best left to other packages, which extend PowerModels. 14 | That said, the PowerModels package should have a software design that makes building such extensions as easy as possible. 15 | 16 | ### Code Quality Requirements 17 | PowerModels strives to be a user-friendly, highly-reliable, and well-maintained package. 18 | To that end, the following code quality controls are necessary for all contributions, 19 | - all features must have unit tests 20 | - naming conventions must be consistent 21 | - core features must have documentation 22 | - code style must be consistent (e.g. 4 spaces for indetnation) 23 | 24 | Due to these quality control requirements, pull request to PowerModels may require lengthy discussion and code review (e.g. see [#111](https://github.com/lanl-ansi/PowerModels.jl/pull/111)). 25 | 26 | PowerModels contributions that do not meet these scope or quality requirements are always welcome in [PowerModelsAnnex.jl](https://github.com/lanl-ansi/PowerModelsAnnex.jl) 27 | -------------------------------------------------------------------------------- /docs/src/formulations.md: -------------------------------------------------------------------------------- 1 | # Network Formulations 2 | 3 | ## Type Hierarchy 4 | We begin with the top of the hierarchy, where we can distinguish between AC and DC power flow models. 5 | ```julia 6 | AbstractACPForm <: AbstractPowerFormulation 7 | AbstractDCPForm <: AbstractPowerFormulation 8 | AbstractWRForm <: AbstractPowerFormulation 9 | AbstractWForm <: AbstractPowerFormulation 10 | ``` 11 | 12 | From there, different forms for ACP and DCP are possible: 13 | ```julia 14 | StandardACPForm <: AbstractACPForm 15 | APIACPForm <: AbstractACPForm 16 | 17 | StandardDCPForm <: AbstractDCPForm 18 | 19 | SOCWRForm <: AbstractWRForm 20 | QCWRForm <: AbstractWRForm 21 | 22 | SOCDFForm <: AbstractWForm 23 | ``` 24 | 25 | ## Power Models 26 | Each of these forms can be used as the type parameter for a PowerModel: 27 | ```julia 28 | ACPPowerModel = GenericPowerModel{StandardACPForm} 29 | APIACPPowerModel = GenericPowerModel{APIACPForm} 30 | 31 | DCPPowerModel = GenericPowerModel{StandardDCPForm} 32 | 33 | SOCWRPowerModel = GenericPowerModel{SOCWRForm} 34 | QCWRPowerModel = GenericPowerModel{QCWRForm} 35 | 36 | SOCDFPowerModel = GenericPowerModel{SOCDFForm} 37 | ``` 38 | 39 | For details on `GenericPowerModel`, see the section on [Power Model](@ref). 40 | 41 | ## User-Defined Abstractions 42 | 43 | Consider the class of conic formulations for power flow models. One way of modelling them in this package is through the following type hierarchy: 44 | ```julia 45 | AbstractConicPowerFormulation <: AbstractPowerFormulation 46 | AbstractWRMForm <: AbstractConicPowerFormulation 47 | 48 | SDPWRMForm <: AbstractWRMForm 49 | SDPWRMPowerModel = GenericPowerModel{SDPWRMForm} 50 | ``` 51 | 52 | The user-defined abstractions do not have to begin from the root `AbstractPowerFormulation` abstract type, and can begin from an intermediate abstract type. For example, in the following snippet: 53 | ```julia 54 | AbstractDCPLLForm <: AbstractDCPForm 55 | 56 | StandardDCPLLForm <: AbstractDCPLLForm 57 | DCPLLPowerModel = GenericPowerModel{StandardDCPLLForm} 58 | ``` 59 | -------------------------------------------------------------------------------- /src/prob/tnep.jl: -------------------------------------------------------------------------------- 1 | #### General Assumptions of these TNEP Models #### 2 | # 3 | # 4 | 5 | export run_tnep 6 | 7 | "" 8 | function run_tnep(file, model_constructor, solver; kwargs...) 9 | return run_generic_model(file, model_constructor, solver, post_tnep; solution_builder = get_tnep_solution, kwargs...) 10 | end 11 | 12 | "the general form of the tnep optimization model" 13 | function post_tnep(pm::GenericPowerModel) 14 | variable_branch_ne(pm) 15 | variable_voltage(pm) 16 | variable_voltage_ne(pm) 17 | variable_generation(pm) 18 | variable_branch_flow(pm) 19 | variable_dcline_flow(pm) 20 | variable_branch_flow_ne(pm) 21 | 22 | objective_tnep_cost(pm) 23 | 24 | constraint_voltage(pm) 25 | constraint_voltage_ne(pm) 26 | 27 | for i in ids(pm, :ref_buses) 28 | constraint_theta_ref(pm, i) 29 | end 30 | 31 | for i in ids(pm, :bus) 32 | constraint_kcl_shunt_ne(pm, i) 33 | end 34 | 35 | for i in ids(pm, :branch) 36 | constraint_ohms_yt_from(pm, i) 37 | constraint_ohms_yt_to(pm, i) 38 | 39 | constraint_voltage_angle_difference(pm, i) 40 | 41 | constraint_thermal_limit_from(pm, i) 42 | constraint_thermal_limit_to(pm, i) 43 | end 44 | 45 | for i in ids(pm, :ne_branch) 46 | constraint_ohms_yt_from_ne(pm, i) 47 | constraint_ohms_yt_to_ne(pm, i) 48 | 49 | constraint_voltage_angle_difference_ne(pm, i) 50 | 51 | constraint_thermal_limit_from_ne(pm, i) 52 | constraint_thermal_limit_to_ne(pm, i) 53 | end 54 | 55 | for i in ids(pm, :dcline) 56 | constraint_dcline(pm, i) 57 | end 58 | end 59 | 60 | "" 61 | function get_tnep_solution(pm::GenericPowerModel, sol::Dict{String,Any}) 62 | add_bus_voltage_setpoint(sol, pm) 63 | add_generator_power_setpoint(sol, pm) 64 | add_branch_flow_setpoint(sol, pm) 65 | add_branch_flow_setpoint_ne(sol, pm) 66 | add_branch_ne_setpoint(sol, pm) 67 | end 68 | -------------------------------------------------------------------------------- /docs/src/parser.md: -------------------------------------------------------------------------------- 1 | # File IO 2 | 3 | ```@meta 4 | CurrentModule = PowerModels 5 | ``` 6 | 7 | ## General Data Formats 8 | 9 | ```@docs 10 | parse_file 11 | parse_json 12 | ``` 13 | 14 | ## Matpower Data Files 15 | 16 | The following two methods are the main exported methods for parsing matpower data files: 17 | 18 | ```@docs 19 | parse_matpower 20 | parse_matpower_data 21 | ``` 22 | 23 | We also provide the following (internal) helper methods: 24 | 25 | ```@docs 26 | standardize_cost_order 27 | update_branch_transformer_settings 28 | merge_generator_cost_data 29 | merge_bus_name_data 30 | parse_cell 31 | parse_matrix 32 | parse_matlab_data 33 | split_line 34 | add_line_delimiter 35 | extract_assignment 36 | extract_mpc_assignment 37 | type_value 38 | type_array 39 | build_typed_dict 40 | extend_case_data 41 | mp_data_to_pm_data 42 | split_loads_shunts 43 | ``` 44 | 45 | ## PTI Data Files (PSS/E) 46 | 47 | **Note: This feature is currently in development, and only partial parsing of 48 | and conversion of PTI files into a PowerModels format is supported. The 49 | following power network components are currently supported: buses, loads, 50 | shunts (fixed and approximation of switched), branches, two-winding and 51 | three-winding transformers (incl. magnetizing admittance), and generators. 52 | There is early support for two-terminal dc lines, but this feature should not 53 | be relied upon.** 54 | 55 | The following method is the main exported method for parsing PTI data files: 56 | 57 | ```@docs 58 | parse_pti 59 | parse_psse 60 | ``` 61 | 62 | The following internal helper methods are also provided: 63 | 64 | ```@docs 65 | get_pti_sections 66 | get_pti_dtypes 67 | parse_line_element! 68 | add_section_data! 69 | get_line_elements 70 | parse_pti_data 71 | convert_vsc_to_dcline 72 | wye_delta_transform 73 | psse2pm_branch! 74 | psse2pm_generator! 75 | psse2pm_bus! 76 | psse2pm_load! 77 | psse2pm_shunt! 78 | psse2pm_transformer! 79 | psse2pm_dclines 80 | calc_2term_reactive_power 81 | get_bus_values 82 | find_max_bus_id 83 | create_starbus_from_transformer 84 | ``` -------------------------------------------------------------------------------- /test/modify.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | @testset "data modification tests" begin 4 | @testset "30-bus case file incremental" begin 5 | data = PowerModels.parse_file("../test/data/matpower/case30.m") 6 | 7 | result = run_opf(data, ACPPowerModel, ipopt_solver) 8 | @test result["status"] == :LocalOptimal 9 | @test isapprox(result["objective"], 204.96; atol = 1e-1) 10 | 11 | data["branch"]["6"]["br_status"] = 0 12 | 13 | result = run_opf(data, ACPPowerModel, ipopt_solver) 14 | @test result["status"] == :LocalOptimal 15 | @test isapprox(result["objective"], 195.25; atol = 1e-1) 16 | 17 | data["gen"]["6"]["gen_status"] = 0 18 | 19 | result = run_opf(data, ACPPowerModel, ipopt_solver) 20 | @test result["status"] == :LocalOptimal 21 | @test isapprox(result["objective"], 195.896; atol = 1e-1) 22 | 23 | data["load"]["4"]["pd"] = 0 24 | data["load"]["4"]["qd"] = 0 25 | 26 | result = run_opf(data, ACPPowerModel, ipopt_solver) 27 | @test result["status"] == :LocalOptimal 28 | @test isapprox(result["objective"], 104.428; atol = 1e-1) 29 | end 30 | 31 | @testset "30-bus case file batch" begin 32 | data = PowerModels.parse_file("../test/data/matpower/case30.m") 33 | 34 | data_delta = JSON.parse(" 35 | { 36 | \"branch\":{ 37 | \"6\":{ 38 | \"br_status\":0 39 | } 40 | }, 41 | \"gen\":{ 42 | \"6\":{ 43 | \"gen_status\":0 44 | } 45 | }, 46 | \"load\":{ 47 | \"4\":{ 48 | \"pd\":0, 49 | \"qd\":0 50 | } 51 | } 52 | }") 53 | 54 | PowerModels.update_data(data, data_delta) 55 | 56 | result = run_opf(data, ACPPowerModel, ipopt_solver) 57 | @test result["status"] == :LocalOptimal 58 | @test isapprox(result["objective"], 104.428; atol = 1e-1) 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /src/form/act.jl: -------------------------------------------------------------------------------- 1 | ### w-theta form of the non-convex AC equations 2 | 3 | export 4 | ACTPowerModel, StandardACTForm 5 | 6 | "" 7 | abstract type AbstractACTForm <: AbstractPowerFormulation end 8 | 9 | "" 10 | abstract type StandardACTForm <: AbstractACTForm end 11 | 12 | "" 13 | const ACTPowerModel = GenericPowerModel{StandardACTForm} 14 | 15 | "default AC constructor" 16 | ACTPowerModel(data::Dict{String,Any}; kwargs...) = 17 | GenericPowerModel(data, StandardACTForm; kwargs...) 18 | 19 | "`t[ref_bus] == 0`" 20 | function constraint_theta_ref(pm::GenericPowerModel{T}, n::Int, i::Int) where T <: AbstractACTForm 21 | @constraint(pm.model, pm.var[:nw][n][:va][i] == 0) 22 | end 23 | 24 | "" 25 | function variable_voltage(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractACTForm 26 | variable_voltage_angle(pm, n; kwargs...) 27 | variable_voltage_magnitude_sqr(pm, n; kwargs...) 28 | variable_voltage_product(pm, n; kwargs...) 29 | end 30 | 31 | function constraint_voltage(pm::GenericPowerModel{T}, n::Int) where T <: StandardACTForm 32 | t = pm.var[:nw][n][:va] 33 | w = pm.var[:nw][n][:w] 34 | wr = pm.var[:nw][n][:wr] 35 | wi = pm.var[:nw][n][:wi] 36 | 37 | for (i,j) in keys(pm.ref[:nw][n][:buspairs]) 38 | @constraint(pm.model, wr[(i,j)]^2 + wi[(i,j)]^2 == w[i]*w[j]) 39 | @NLconstraint(pm.model, wi[(i,j)] == tan(t[i] - t[j])*wr[(i,j)]) 40 | end 41 | end 42 | 43 | 44 | """ 45 | ``` 46 | t[f_bus] - t[t_bus] <= angmax 47 | t[f_bus] - t[t_bus] >= angmin 48 | ``` 49 | """ 50 | function constraint_voltage_angle_difference(pm::GenericPowerModel{T}, n::Int, f_idx, angmin, angmax) where T <: StandardACTForm 51 | i, f_bus, t_bus = f_idx 52 | 53 | va_fr = pm.var[:nw][n][:va][f_bus] 54 | va_to = pm.var[:nw][n][:va][t_bus] 55 | 56 | @constraint(pm.model, va_fr - va_to <= angmax) 57 | @constraint(pm.model, va_fr - va_to >= angmin) 58 | end 59 | 60 | 61 | "" 62 | function add_bus_voltage_setpoint(sol, pm::GenericPowerModel{T}) where T <: AbstractACTForm 63 | add_setpoint(sol, pm, "bus", "vm", :w; scale = (x,item) -> sqrt(x)) 64 | add_setpoint(sol, pm, "bus", "va", :va) 65 | end 66 | -------------------------------------------------------------------------------- /test/data/matpower/frankenstein_00.m: -------------------------------------------------------------------------------- 1 | % Case saved by PowerWorld Simulator, version 19, build date January 17, 2017 2 | % Case Information Header = 2 lines 3 | % A Frankenstein network for testing all of the core features of v33 data files 4 | % developed by Carleton Coffrin (cjc@lanl.gov) June 2017 5 | function mpc = frankenstein_00 6 | mpc.version = '2'; 7 | mpc.baseMVA = 100.00; 8 | 9 | %% bus data 10 | mpc.bus = [ 11 | 1002 2 0.00 0.00 0.00 0.00 101 0.9989281 2.93603 345.00 201 1.100 0.900 12 | 1005 2 0.00 0.00 0.00 0.00 101 1.0199983 0.12982 87.00 201 1.100 0.900 13 | 1008 2 18.90 6.90 0.00 0.00 101 1.0203628 -0.00217 87.00 201 1.100 0.900 14 | 1009 3 10.50 2.30 0.00 105.30 101 1.0300000 0.00000 87.00 201 1.100 0.900 15 | ]; 16 | 17 | %% generator data 18 | mpc.gen = [ 19 | 1002 27.50 2.00 2.00 2.00 1.0200 31.30 1 27.50 16.00 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 0 27.5000 20 | 1005 20.00 -242.52 250.00 -250.00 1.0200 320.00 1 200.00 -200.00 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 0 200.0000 21 | 1009 -17.73 109.28 250.00 -250.00 1.0300 100.00 1 250.00 -250.00 0.00 0.00 0.00 0.00 0.00 0.00 0 0 0 0 250.0000 22 | ]; 23 | 24 | %% generator cost data 25 | mpc.gencost = [ 26 | 2 0 0 4 0 0 1 0 27 | 2 0 0 4 0 0 1 0 28 | 2 0 0 4 0 0 1 0 29 | ]; 30 | 31 | %% branch data 32 | mpc.branch = [ 33 | 1005 1002 0.005210 0.177370 0.00000 84.00 84.00 84.00 1.02500 0.000 1 0.00 0.00 -27.46 -0.66 27.50 2.01 34 | 1008 1005 0.001278 0.012294 0.22708 1086.00 1195.00 1086.00 0.00000 0.000 1 0.00 0.00 -18.98 -6.80 18.98 -16.79 35 | 1005 1009 0.000475 0.004680 0.08200 1044.00 1170.00 1044.00 0.00000 0.000 1 0.00 0.00 28.45 -225.08 -28.23 218.69 36 | ]; 37 | 38 | %% bus names 39 | mpc.bus_name = { 40 | 'FAV SPOT 02'; 41 | 'FAV PLACE 05'; 42 | 'FAV PLC 08'; 43 | 'FAV PLACE 09'; 44 | }; 45 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Los Alamos National Security, LLC 2 | All rights reserved. 3 | Copyright 2016. Los Alamos National Security, LLC. This software was produced under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National Laboratory (LANL), which is operated by Los Alamos National Security, LLC for the U.S. Department of Energy. The U.S. Government has rights to use, reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to produce derivative works, such modified software should be clearly marked, so as not to confuse it with the version available from LANL. 4 | 5 | Additionally, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 3. Neither the name of Los Alamos National Security, LLC, Los Alamos National Laboratory, LANL, the U.S. Government, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | THIS SOFTWARE IS PROVIDED BY LOS ALAMOS NATIONAL SECURITY, LLC AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /src/prob/pf_bf.jl: -------------------------------------------------------------------------------- 1 | export run_pf_bf, run_ac_pf_bf, run_dc_pf_bf 2 | 3 | "" 4 | function run_pf_bf(file, model_constructor, solver; kwargs...) 5 | if model_constructor != SOCDFPowerModel 6 | error(LOGGER, "The problem type pf_bf at the moment only supports the SOCDFForm formulation") 7 | end 8 | return run_generic_model(file, model_constructor, solver, post_pf_bf; kwargs...) 9 | end 10 | 11 | "" 12 | function post_pf_bf(pm::GenericPowerModel) 13 | variable_voltage(pm, bounded = false) 14 | variable_generation(pm, bounded = false) 15 | variable_branch_flow(pm, bounded = false) 16 | variable_branch_current(pm, bounded = false) 17 | variable_dcline_flow(pm, bounded = false) 18 | 19 | for (i,bus) in ref(pm, :ref_buses) 20 | @assert bus["bus_type"] == 3 21 | constraint_theta_ref(pm, i) 22 | constraint_voltage_magnitude_setpoint(pm, i) 23 | end 24 | 25 | for (i,bus) in ref(pm, :bus) 26 | constraint_kcl_shunt(pm, i) 27 | 28 | # PV Bus Constraints 29 | if length(ref(pm, :bus_gens, i)) > 0 && !(i in ids(pm,:ref_buses)) 30 | # this assumes inactive generators are filtered out of bus_gens 31 | @assert bus["bus_type"] == 2 32 | 33 | constraint_voltage_magnitude_setpoint(pm, i) 34 | for j in ref(pm, :bus_gens, i) 35 | constraint_active_gen_setpoint(pm, j) 36 | end 37 | end 38 | end 39 | 40 | for i in ids(pm, :branch) 41 | constraint_flow_losses(pm, i) 42 | constraint_voltage_magnitude_difference(pm, i) 43 | constraint_branch_current(pm, i) 44 | end 45 | 46 | for (i,dcline) in ref(pm, :dcline) 47 | #constraint_dcline(pm, i) not needed, active power flow fully defined by dc line setpoints 48 | constraint_active_dcline_setpoint(pm, i) 49 | 50 | f_bus = ref(pm, :bus)[dcline["f_bus"]] 51 | if f_bus["bus_type"] == 1 52 | constraint_voltage_magnitude_setpoint(pm, f_bus["index"]) 53 | end 54 | 55 | t_bus = ref(pm, :bus)[dcline["t_bus"]] 56 | if t_bus["bus_type"] == 1 57 | constraint_voltage_magnitude_setpoint(pm, t_bus["index"]) 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /src/prob/pf.jl: -------------------------------------------------------------------------------- 1 | export run_pf, run_ac_pf, run_dc_pf 2 | 3 | "" 4 | function run_ac_pf(file, solver; kwargs...) 5 | return run_pf(file, ACPPowerModel, solver; kwargs...) 6 | end 7 | 8 | "" 9 | function run_dc_pf(file, solver; kwargs...) 10 | return run_pf(file, DCPPowerModel, solver; kwargs...) 11 | end 12 | 13 | "" 14 | function run_pf(file, model_constructor, solver; kwargs...) 15 | return run_generic_model(file, model_constructor, solver, post_pf; kwargs...) 16 | end 17 | 18 | "" 19 | function post_pf(pm::GenericPowerModel) 20 | variable_voltage(pm, bounded = false) 21 | variable_generation(pm, bounded = false) 22 | variable_branch_flow(pm, bounded = false) 23 | variable_dcline_flow(pm, bounded = false) 24 | 25 | constraint_voltage(pm) 26 | 27 | for (i,bus) in ref(pm, :ref_buses) 28 | @assert bus["bus_type"] == 3 29 | constraint_theta_ref(pm, i) 30 | constraint_voltage_magnitude_setpoint(pm, i) 31 | end 32 | 33 | for (i,bus) in ref(pm, :bus) 34 | constraint_kcl_shunt(pm, i) 35 | 36 | # PV Bus Constraints 37 | if length(ref(pm, :bus_gens, i)) > 0 && !(i in ids(pm,:ref_buses)) 38 | # this assumes inactive generators are filtered out of bus_gens 39 | @assert bus["bus_type"] == 2 40 | 41 | constraint_voltage_magnitude_setpoint(pm, i) 42 | for j in ref(pm, :bus_gens, i) 43 | constraint_active_gen_setpoint(pm, j) 44 | end 45 | end 46 | end 47 | 48 | for i in ids(pm, :branch) 49 | constraint_ohms_yt_from(pm, i) 50 | constraint_ohms_yt_to(pm, i) 51 | end 52 | 53 | for (i,dcline) in ref(pm, :dcline) 54 | #constraint_dcline(pm, i) not needed, active power flow fully defined by dc line setpoints 55 | constraint_active_dcline_setpoint(pm, i) 56 | 57 | f_bus = ref(pm, :bus)[dcline["f_bus"]] 58 | if f_bus["bus_type"] == 1 59 | constraint_voltage_magnitude_setpoint(pm, f_bus["index"]) 60 | end 61 | 62 | t_bus = ref(pm, :bus)[dcline["t_bus"]] 63 | if t_bus["bus_type"] == 1 64 | constraint_voltage_magnitude_setpoint(pm, t_bus["index"]) 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /test/data/matpower/case6.m: -------------------------------------------------------------------------------- 1 | % Case to test two connected components in the network data 2 | % the case is two replicates of the nesta_case3_lmbd network 3 | 4 | function mpc = nesta_case3_lmbd_2x 5 | mpc.version = '2'; 6 | mpc.baseMVA = 100.0; 7 | 8 | mpc.bus = [ 9 | 1 3 110.0 40.0 0.0 0.0 1 1.10000 -0.00000 240.0 1 1.10000 0.90000; 10 | 2 2 110.0 40.0 0.0 0.0 1 0.92617 7.25883 240.0 1 1.10000 0.90000; 11 | 3 2 95.0 50.0 0.0 0.0 1 0.90000 -17.26710 240.0 2 1.10000 0.90000; 12 | 4 3 110.0 40.0 0.0 0.0 1 1.10000 -0.00000 240.0 1 1.10000 0.90000; 13 | 5 2 110.0 40.0 0.0 0.0 1 0.92617 7.25883 240.0 1 1.10000 0.90000; 14 | 6 2 95.0 50.0 0.0 0.0 1 0.90000 -17.26710 240.0 2 1.10000 0.90000; 15 | ]; 16 | 17 | mpc.gen = [ 18 | 1 148.067 54.697 1000.0 -1000.0 1.1 100.0 1 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 19 | 2 170.006 -8.791 1000.0 -1000.0 0.92617 100.0 1 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 20 | 3 0.0 -4.843 1000.0 -1000.0 0.9 100.0 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 21 | 4 148.067 54.697 1000.0 -1000.0 1.1 100.0 1 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 22 | 5 170.006 -8.791 1000.0 -1000.0 0.92617 100.0 1 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 23 | 6 0.0 -4.843 1000.0 -1000.0 0.9 100.0 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 24 | ]; 25 | 26 | mpc.gencost = [ 27 | 2 0.0 0.0 3 0.110000 5.000000 0.000000; 28 | 2 0.0 0.0 3 0.085000 1.200000 0.000000; 29 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; 30 | 2 0.0 0.0 3 0.110000 5.000000 0.000000; 31 | 2 0.0 0.0 3 0.085000 1.200000 0.000000; 32 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; 33 | ]; 34 | 35 | mpc.branch = [ 36 | 1 3 0.065 0.62 0.45 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 37 | 3 2 0.025 0.75 0.7 50.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 38 | 1 2 0.042 0.9 0.3 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 39 | 4 6 0.065 0.62 0.45 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 40 | 6 5 0.025 0.75 0.7 50.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 41 | 3 5 0.042 0.9 0.3 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 42 | ]; 43 | -------------------------------------------------------------------------------- /test/data/pti/two_winding_mag_test.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 0, 60.00 2 | A Frankenstein network for testing two-winding transformers with magnetizing admittance 3 | developed by Carleton Coffrin (cjc@lanl.gov) and David Fobes (dfobes@lanl.gov) April 2018 4 | 1,'FAV SPOT 01', 230.0000,2, 1, 1, 1,1.00000000, -0.559720, 1.10000, 0.90000, 1.10000, 0.90000 5 | 2,'FAV SPOT 02', 230.0000,3, 1, 1, 1,1.06413996, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 0 / END OF BUS DATA, BEGIN LOAD DATA 7 | 1,'1 ',1, 1, 1, 300.000, 98.610, 0.000, 0.000, 0.000, 0.000, 1,1 8 | 2,'1 ',1, 1, 1, 400.000, 131.470, 0.000, 0.000, 0.000, 0.000, 1,1 9 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 10 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 11 | 1,'1 ', 324.498, 390.000, 390.000, -390.000,1.10000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 520.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 12 | 2,'1 ', 0.000, -10.802, 150.000, -150.000,1.06414, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 13 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 14 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 15 | 2, 1, 0,'1 ',1,1,1,5.0000E-3,6.74000E-3,2,' ',1, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 16 | 2.97000E-3,2.97000E-2, 100.00 17 | 1.050000,230.000, -1.000, 426.00, 426.00, 426.00,-3, 0, 30.00, -30.00, 150.00, 51.00,9601, 0, 0.00000, 0.00000, 0.000 18 | 1.000000,230.000 19 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 20 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 21 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 22 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 23 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 24 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 25 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 26 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 27 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 28 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 29 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 30 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 31 | 0 /END OF GNE DEVICE DATA 32 | Q 33 | -------------------------------------------------------------------------------- /test/data/matpower/case5_asym.m: -------------------------------------------------------------------------------- 1 | % NESTA v0.6.0 2 | function mpc = case5_asym 3 | mpc.version = '2'; 4 | mpc.baseMVA = 100.0; 5 | 6 | %% bus data 7 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 8 | mpc.bus = [ 9 | 1 2 0.0 0.0 0.0 0.0 1 1.07762 2.80377 230.0 1 1.10000 0.90000; 10 | 2 1 300.0 98.61 0.0 0.0 1 1.08407 -0.73465 230.0 1 1.09071 0.90000; 11 | 3 2 300.0 98.61 0.0 0.0 1 1.10000 -0.55972 230.0 1 1.10000 0.90000; 12 | 4 3 400.0 131.47 0.0 0.0 1 1.06414 0.00000 230.0 1 1.09981 0.90000; 13 | 5 2 0.0 0.0 0.0 0.0 1 1.06907 3.59033 230.0 1 1.10000 0.90000; 14 | ]; 15 | 16 | %% generator data 17 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 18 | mpc.gen = [ 19 | 1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 20 | 1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 21 | 3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 22 | 4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 23 | 5 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 24 | ]; 25 | 26 | %% generator cost data 27 | % 2 startup shutdown n c(n-1) ... c0 28 | mpc.gencost = [ 29 | 2 0.0 0.0 3 0.000000 14.000000 0.000000; 30 | 2 0.0 0.0 3 0.000000 15.000000 0.000000; 31 | 2 0.0 0.0 3 0.000000 30.000000 0.000000; 32 | 2 0.0 0.0 3 0.000000 40.000000 0.000000; 33 | 2 0.0 0.0 3 0.000000 10.000000 0.000000; 34 | ]; 35 | 36 | %% branch data 37 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 38 | mpc.branch = [ 39 | 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 1.13502939215 7.37625865451; 40 | 1 4 0.00304 0.0304 0.00658 426.0 426.0 426.0 0.0 0.0 1 0.658328506605 4.09149161503; 41 | 1 5 0.00064 0.0064 0.03126 426.0 426.0 426.0 0.0 0.0 1 -1.85752917181 0.214859173174; 42 | 2 3 0.00108 0.0108 0.01852 426.0 426.0 426.0 0.0 0.0 1 -1.6352215473 0.67895498723; 43 | 3 4 0.00297 0.0297 0.00674 426.0 426.0 426.0 0.0 0.0 1 -4.41979643164 2.02540580579; 44 | 4 5 0.00297 0.0297 0.00674 240.0 240.0 240.0 0.0 0.0 1 -5.06895761352 -0.827924013964; 45 | ]; 46 | -------------------------------------------------------------------------------- /test/data/matpower/case3.m: -------------------------------------------------------------------------------- 1 | % Case to test adding data to matpower file 2 | % also tests basic ac and hvdc modeling 3 | % tests when gencost is present but not dclinecost 4 | % based on nesta_case3_lmbd from NESTA v0.6.0 5 | function mpc = case3 6 | mpc.version = '2'; 7 | mpc.baseMVA = 100.0; 8 | mpc.bus = [ 9 | 1 3 110.0 40.0 0.0 0.0 1 1.10000 -0.00000 240.0 1 1.10000 0.90000; 10 | 2 2 110.0 40.0 0.0 0.0 1 0.92617 7.25883 240.0 1 1.10000 0.90000; 11 | 3 2 95.0 50.0 0.0 0.0 1 0.90000 -17.26710 240.0 2 1.10000 0.90000; 12 | ]; 13 | 14 | mpc.gen = [ 15 | 1 158.067 28.79 1000.0 -1000.0 1.1 100.0 1 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 16 | 2 160.006 -4.63 1000.0 -1000.0 0.92617 100.0 1 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 17 | 3 0.0 -4.843 1000.0 -1000.0 0.9 100.0 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 18 | ]; 19 | 20 | mpc.gencost = [ 21 | 2 0.0 0.0 3 0.110000 5.000000 0.000000; 22 | 2 0.0 0.0 3 0.085000 1.200000 0.000000; 23 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; 24 | ]; 25 | 26 | mpc.branch = [ 27 | 1 3 0.065 0.62 0.45 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 28 | 3 2 0.025 0.75 0.7 50.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 29 | 1 2 0.042 0.9 0.3 9000.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 30 | ]; 31 | 32 | mpc.dcline = [ 33 | 1 2 1 10 10 25.91 -4.16 1.1 0.92617 10 900 -900 900 -900 900 0 0 0 0 0 0 0 0 34 | ] 35 | 36 | 37 | % matpower data format extentions 38 | 39 | % adding single values 40 | mpc.const_int = 123; 41 | mpc.const_float = 4.56 42 | mpc.const_str = 'a string'; 43 | 44 | 45 | % adding extra matrix values 46 | 47 | % generic table, comes in a matrix 48 | mpc.areas = [ 49 | 1 1; 50 | 2 3; 51 | ]; 52 | 53 | % named column table 54 | %column_names% area refbus 55 | mpc.areas_named = [ 56 | 4 5; 57 | 5 6; 58 | ]; 59 | 60 | % add two new columns to "branch" matrix 61 | %column_names% rate_i rate_p 62 | mpc.branch_limit = [ 63 | 50.2 45; 64 | 36 60.1; 65 | 12 30; 66 | ]; 67 | 68 | 69 | % adding extra cell values 70 | 71 | mpc.areas_cells = { 72 | 'Area 1' 123 987 'Slack \"Bus\" 1' 1.23 ; 73 | 'Area 2' 456 987 'Slack Bus 3' 4.56 ; 74 | }; 75 | 76 | %column_names% area_name area area2 refbus_name refbus 77 | mpc.areas_named_cells = { 78 | 'Area 1' 123 987 'Slack Bus 1' 1.23; 79 | 'Area 2' 456 987 'Slack Bus 3' 4.56; 80 | }; 81 | 82 | %column_names% name number_id 83 | mpc.branch_names = { 84 | 'Branch 1' 123; 85 | 'Branch 2' 456; 86 | 'Branch 3' 789; 87 | }; 88 | -------------------------------------------------------------------------------- /test/data/pti/three_winding_test.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing three-winding transformers 3 | developed by Carleton Coffrin (cjc@lanl.gov) & David Fobes (dfobes@lanl.gov) April 2018 4 | 1001,'FAV SPOT 01', 250.0000,1, 101, 201, 301, 1.10000, -4.0000,1.10000, 0.90000, 1.10000, 0.90000 5 | 1002,'FAV SPOT 02', 10.0000,3, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 6 | 1003,'FAV SPOT 03', 10.0000,2, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 7 | 0 / END OF BUS DATA, BEGIN LOAD DATA 8 | 1001,'L0',1, 101, 201, 10.000, 2.500, 0.000, 0.000, 0.000, 0.000, 301,1 9 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 10 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 11 | 1002,'W1', 40.000, 0.050, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 12 | 1003,'W2', 40.000, 1.000, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 13 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 14 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 15 | 1001,1002,1003,'1 ',1,1,1, 0.00000, 0.00000,2,'T1 3W',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 16 | 4.50000E-3,2.00000E-1, 100.00,7.00000E-4,3.00000E-1, 100.00,7.00000E-4,2.00000E-1, 100.00,1.00000, -5.00000 17 | 1.10000, 0.000, 0.000, 200.00, 200.00, 400.00, 0, 1002, 1.25000, 0.75000, 1.10000, 0.90000, 23, 0, 0.00000, 0.00000, 0.0 18 | 1.00000, 0.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 19 | 1.00000, 0.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 20 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 21 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 22 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 23 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 24 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 25 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 26 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 27 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 28 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 29 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 30 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 31 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 32 | 0 /END OF GNE DEVICE DATA 33 | Q 34 | -------------------------------------------------------------------------------- /test/data/pti/three_winding_test_2.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing three-winding transformers 3 | developed by Carleton Coffrin (cjc@lanl.gov) & David Fobes (dfobes@lanl.gov) April 2018 4 | 1001,'FAV SPOT 01', 250.0000,1, 101, 201, 301, 1.10000, -4.0000,1.10000, 0.90000, 1.10000, 0.90000 5 | 1002,'FAV SPOT 02', 10.0000,3, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 6 | 1003,'FAV SPOT 03', 10.0000,2, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 7 | 0 / END OF BUS DATA, BEGIN LOAD DATA 8 | 1001,'L0',1, 101, 201, 10.000, 2.500, 0.000, 0.000, 0.000, 0.000, 301,1 9 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 10 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 11 | 1002,'W1', 40.000, 0.050, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 12 | 1003,'W2', 40.000, 1.000, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 13 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 14 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 15 | 1001,1002,1003,'1 ',3,3,1, 0.00000, 0.00000,2,'T1 3W',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 16 | 4.50000E-3,2.00000E-1, 100.00,7.00000E-4,3.00000E-1, 100.00,7.00000E-4,2.00000E-1, 100.00,1.00000, -5.00000 17 | 1.10000, 250.000, 0.000, 200.00, 200.00, 400.00, 0, 1002, 1.25000, 0.75000, 1.10000, 0.90000, 23, 0, 0.00000, 0.00000, 0.0 18 | 1.00000, 10.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 19 | 1.00000, 10.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 20 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 21 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 22 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 23 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 24 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 25 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 26 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 27 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 28 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 29 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 30 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 31 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 32 | 0 /END OF GNE DEVICE DATA 33 | Q 34 | -------------------------------------------------------------------------------- /test/data/matpower/case5_pwlc.m: -------------------------------------------------------------------------------- 1 | % NESTA v0.6.0 2 | % tests non-contiguous bus ids 3 | 4 | function mpc = nesta_case5_pjm 5 | mpc.version = '2'; 6 | mpc.baseMVA = 100.0; 7 | 8 | %% area data 9 | % area refbus 10 | mpc.areas = [ 11 | 1 4; 12 | ]; 13 | 14 | %% bus data 15 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 16 | mpc.bus = [ 17 | 1 2 0.0 0.0 0.0 0.0 1 1.07762 2.80377 230.0 1 1.10000 0.90000; 18 | 2 1 300.0 98.61 0.0 0.0 1 1.08407 -0.73465 230.0 1 1.10000 0.90000; 19 | 3 2 300.0 98.61 0.0 0.0 1 1.10000 -0.55972 230.0 1 1.10000 0.90000; 20 | 4 3 400.0 131.47 0.0 0.0 1 1.06414 0.00000 230.0 1 1.10000 0.90000; 21 | 10 2 0.0 0.0 0.0 0.0 1 1.06907 3.59033 230.0 1 1.10000 0.90000; 22 | ]; 23 | 24 | %% generator data 25 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 26 | mpc.gen = [ 27 | 1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 28 | 1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 29 | 3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 30 | 4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 31 | 10 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 32 | ]; 33 | 34 | %% generator cost data 35 | % 1 startup shutdown n x1 y1 ... xn yn 36 | mpc.gencost = [ 37 | 1 0.0 0.0 4 -0.1 0.0 0.0 0.0 0.1 0.0 0.2 0.0; % tests zero cost 38 | 1 0.0 0.0 4 0.0 841.0 20.0 841.0 100.0 841.0 150.0 841.0; % tests constant cost 39 | 1 0.0 0.0 4 170.0 4772.0 231.0 6203.0 293.0 7855.0 355.0 9738.0; 40 | 1 0.0 0.0 4 22.0 1122.0 33.0 1417.0 44.0 1742.0 55.0 2075.0; 41 | 1 0.0 0.0 4 7.0 897.0 8.0 1187.0 9.0 1479.0 10.0 1791.0; 42 | ]; 43 | 44 | %% branch data 45 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 46 | mpc.branch = [ 47 | 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 -30.0 30.0; 48 | 1 4 0.00304 0.0304 0.00658 426 426 426 0.0 0.0 1 -30.0 30.0; 49 | 1 10 0.00064 0.0064 0.03126 426 426 426 0.0 0.0 1 -30.0 30.0; 50 | 2 3 0.00108 0.0108 0.01852 426 426 426 0.0 0.0 1 -30.0 30.0; 51 | 3 4 0.00297 0.0297 0.00674 426 426 426 0.0 0.0 1 -30.0 30.0; 52 | 4 10 0.00297 0.0297 0.00674 240.0 240.0 240.0 0.0 0.0 1 -30.0 30.0; 53 | ]; 54 | 55 | -------------------------------------------------------------------------------- /test/data/pti/three_winding_mag_test.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing three-winding transformers with magnetizing admittance 3 | developed by Carleton Coffrin (cjc@lanl.gov) & David Fobes (dfobes@lanl.gov) April 2018 4 | 1001,'FAV SPOT 01', 250.0000,1, 101, 201, 301, 1.10000, -4.0000,1.10000, 0.90000, 1.10000, 0.90000 5 | 1002,'FAV SPOT 02', 10.0000,3, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 6 | 1003,'FAV SPOT 03', 10.0000,2, 101, 201, 301, 1.00000, 0.0000,1.10000, 0.90000, 1.10000, 0.90000 7 | 0 / END OF BUS DATA, BEGIN LOAD DATA 8 | 1001,'L0',1, 101, 201, 10.000, 2.500, 0.000, 0.000, 0.000, 0.000, 301,1 9 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 10 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 11 | 1002,'W1', 40.000, 0.050, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 12 | 1003,'W2', 40.000, 1.000, 40.000, -35.000,1.00000, 0, 90.000, 0.00000, 0.20000, 0.00000, 0.00000,1.00000,1, 50.0, 75.000, -75.000, 3,1.0000 13 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 14 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 15 | 1001,1002,1003,'1 ',1,1,1, 5.00000E-3, 6.74000E-3,2,'T1 3W',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 16 | 4.50000E-3,2.00000E-1, 100.00,7.00000E-4,3.00000E-1, 100.00,7.00000E-4,2.00000E-1, 100.00,1.00000, -5.00000 17 | 1.10000, 0.000, 0.000, 200.00, 200.00, 400.00, 0, 1002, 1.25000, 0.75000, 1.10000, 0.90000, 23, 0, 0.00000, 0.00000, 0.0 18 | 1.00000, 0.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 19 | 1.00000, 0.000, 0.000, 100.00, 100.00, 100.00, 0, 0, 1.10000, 0.90000, 1.10000, 0.90000, 33, 0, 0.00000, 0.00000, 0.0 20 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 21 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 22 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 23 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 24 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 25 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 26 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 27 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 28 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 29 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 30 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 31 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 32 | 0 /END OF GNE DEVICE DATA 33 | Q 34 | -------------------------------------------------------------------------------- /test/data/matpower/case5.m: -------------------------------------------------------------------------------- 1 | % NESTA v0.6.0 2 | % used in tests of, 3 | % - non-contiguous bus ids 4 | % - tranformer orentation swapping 5 | % - dual values 6 | % 7 | 8 | function mpc = nesta_case5_pjm 9 | mpc.version = '2'; 10 | mpc.baseMVA = 100.0; 11 | 12 | %% area data 13 | % area refbus 14 | mpc.areas = [ 15 | 1 4; 16 | ]; 17 | 18 | %% bus data 19 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 20 | mpc.bus = [ 21 | 1 2 0.0 0.0 0.0 0.0 1 1.00000 2.80377 230.0 1 1.10000 0.90000; 22 | 2 1 300.0 98.61 0.0 0.0 1 1.08407 -0.73465 230.0 1 1.10000 0.90000; 23 | 3 2 300.0 98.61 0.0 0.0 1 1.00000 -0.55972 230.0 1 1.10000 0.90000; 24 | 4 3 400.0 131.47 0.0 0.0 1 1.00000 0.00000 230.0 1 1.10000 0.90000; 25 | 10 2 0.0 0.0 0.0 0.0 1 1.00000 3.59033 230.0 1 1.10000 0.90000; 26 | ]; 27 | 28 | %% generator data 29 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 30 | mpc.gen = [ 31 | 1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 32 | 1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 33 | 3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 34 | 4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 35 | 10 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 36 | ]; 37 | 38 | %% generator cost data 39 | % 2 startup shutdown n c(n-1) ... c0 40 | mpc.gencost = [ 41 | 2 0.0 0.0 3 0.000000 14.000000 0.000000; 42 | 2 0.0 0.0 3 0.000000 15.000000 0.000000; 43 | 2 0.0 0.0 3 0.000000 30.000000 0.000000; 44 | 2 0.0 0.0 3 0.000000 40.000000 0.000000; 45 | 2 0.0 0.0 3 0.000000 10.000000 0.000000; 46 | ]; 47 | 48 | %% branch data 49 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 50 | mpc.branch = [ 51 | 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 -30.0 30.0; 52 | 1 4 0.00304 0.0304 0.00658 426 426 426 0.0 0.0 1 -30.0 30.0; 53 | 1 10 0.00064 0.0064 0.03126 426 426 426 0.0 0.0 1 -30.0 30.0; 54 | 2 3 0.00108 0.0108 0.01852 426 426 426 0.0 0.0 1 -30.0 30.0; 55 | 3 4 0.00297 0.0297 0.00674 426 426 426 1.05 1.0 1 -30.0 30.0; 56 | 4 3 0.00297 0.0297 0.00674 426 426 426 1.05 -1.0 1 -30.0 30.0; 57 | 4 10 0.00297 0.0297 0.00674 240.0 240.0 240.0 0.0 0.0 1 -30.0 30.0; 58 | ]; 59 | 60 | -------------------------------------------------------------------------------- /test/data/matpower/case7_tplgy.m: -------------------------------------------------------------------------------- 1 | % 2 | % Test for component status pre-processing 3 | % 4 | 5 | function mpc = case7_tplgy 6 | mpc.version = '2'; 7 | mpc.baseMVA = 100.0; 8 | 9 | %% bus data 10 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 11 | mpc.bus = [ 12 | 1 3 0.0 0.0 0.0 0.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 13 | 2 2 100.0 50.0 1.0 5.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 14 | 3 1 0.0 0.0 0.0 0.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 15 | 4 1 100.0 50.0 0.0 0.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 16 | 5 2 0.0 0.0 1.0 5.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 17 | 6 4 100.0 50.0 1.0 5.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 18 | 7 1 50.0 10.0 1.0 5.0 1 1.00000 0.00000 240.0 1 1.10000 0.90000; 19 | ]; 20 | 21 | %% generator data 22 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 23 | mpc.gen = [ 24 | 1 0.000 0.000 1000.0 -1000.0 1.00000 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 25 | 2 0.000 0.000 1000.0 -1000.0 1.00000 100.0 1 140.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 26 | 5 0.000 0.000 100.0 -100.0 1.00000 100.0 1 330.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 27 | ]; 28 | 29 | %% generator cost data 30 | % 2 startup shutdown n c(n-1) ... c0 31 | mpc.gencost = [ 32 | 2 0.0 0.0 3 0.000000 1.000000 0.000000; 33 | 2 0.0 0.0 3 0.000000 1.000000 0.000000; 34 | 2 0.0 0.0 3 0.000000 10.000000 0.000000; 35 | ]; 36 | 37 | %% branch data 38 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 39 | mpc.branch = [ 40 | 1 3 0.065 0.62 0.00 30.0 0.0 0.0 0.0 0.0 0 -30.0 30.0; 41 | 1 4 0.012 0.53 0.00 60.0 0.0 0.0 0.0 0.0 0 -30.0 30.0; 42 | 1 5 0.042 0.90 0.00 60.0 0.0 0.0 0.0 0.0 0 -30.0 30.0; 43 | 2 3 0.075 0.51 0.00 45.0 0.0 0.0 0.0 0.0 0 -30.0 30.0; 44 | 3 5 0.025 0.75 0.25 30.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 45 | 3 6 0.025 0.75 0.25 30.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 46 | 5 6 0.025 0.75 0.25 30.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 47 | 4 5 0.025 0.07 0.05 300.0 0.0 0.0 0.0 0.0 1 -30.0 30.0; 48 | ]; 49 | 50 | %% dcline data 51 | % fbus tbus status Pf Pt Qf Qt Vf Vt Pmin Pmax QminF QmaxF QminT QmaxT loss0 loss1 52 | mpc.dcline = [ 53 | 1 2 0 10 9.0 99.0 -10.0 1.0000 1.0000 10 100 -100 100 -100 100 10.00 0.00; 54 | 5 6 1 10 9.0 99.0 -10.0 1.0000 1.0000 0 200 -100 100 -100 100 10.00 0.00; 55 | 7 4 1 10 9.0 99.0 -10.0 1.0000 1.0000 -200 0 -100 100 -100 100 10.00 0.00; 56 | ]; 57 | 58 | -------------------------------------------------------------------------------- /test/data/matpower/case5_dc.m: -------------------------------------------------------------------------------- 1 | % based on NESTA v0.6.0 2 | % tests dc line with costs 3 | % tests generator and dc line voltage setpoint warnings 4 | 5 | function mpc = nesta_case5_pjm 6 | mpc.version = '2'; 7 | mpc.baseMVA = 100.0; 8 | 9 | %% bus data 10 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 11 | mpc.bus = [ 12 | 1 1 0.0 0.00 0.0 0.0 1 1.06355 2.87619 230.0 1 1.10000 0.90000; 13 | 2 1 300.0 98.61 0.0 0.0 1 1.08009 -0.79708 230.0 1 1.10000 0.90000; 14 | 3 1 300.0 98.61 0.0 0.0 1 1.10000 -0.64925 230.0 1 1.10000 0.90000; 15 | 4 3 400.0 131.47 0.0 0.0 1 1.06414 0.00000 230.0 1 1.10000 0.90000; 16 | 5 1 0.0 0.00 0.0 0.0 1 1.05304 3.70099 230.0 1 1.10000 0.90000; 17 | ]; 18 | 19 | %% generator data 20 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 21 | mpc.gen = [ 22 | 1 40.0 30.0 30.0 -30.0 1.06355 100.0 1 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 23 | 1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 24 | 3 333.6866 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 25 | 4 0.0 -70.8186 150.0 -150.0 1.06414 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 26 | 5 463.5555 -184.9224 450.0 -450.0 1.06907 100.0 1 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 27 | ]; 28 | 29 | %% generator cost data 30 | % 2 startup shutdown n c(n-1) ... c0 31 | mpc.gencost = [ 32 | 2 0.0 0.0 3 0.000000 14.000000 0.000000; 33 | 2 0.0 0.0 3 0.000000 15.000000 0.000000; 34 | 2 0.0 0.0 3 0.000000 30.000000 0.000000; 35 | 2 0.0 0.0 3 0.000000 40.000000 0.000000; 36 | 2 0.0 0.0 3 0.000000 10.000000 0.000000; 37 | ]; 38 | 39 | %% branch data 40 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 41 | mpc.branch = [ 42 | 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 -30.0 30.0; 43 | 1 4 0.00304 0.0304 0.00658 426 426 426 0.0 0.0 1 -30.0 30.0; 44 | 1 5 0.00064 0.0064 0.03126 426 426 426 0.0 0.0 1 -30.0 30.0; 45 | 2 3 0.00108 0.0108 0.01852 426 426 426 0.0 0.0 1 -30.0 30.0; 46 | 3 4 0.00297 0.0297 0.00674 426 426 426 0.0 0.0 1 -30.0 30.0; 47 | 4 5 0.00297 0.0297 0.00674 240.0 240.0 240.0 0.0 0.0 1 -30.0 30.0; 48 | ]; 49 | 50 | %% dcline data 51 | % fbus tbus status Pf Pt Qf Qt Vf Vt Pmin Pmax QminF QmaxF QminT QmaxT loss0 loss1 52 | mpc.dcline = [ 53 | 3 5 1 10 8.9 99.9934 -10.4049 1.1 1.05555 10 100 -100 100 -100 100 1 0.01; 54 | ]; 55 | 56 | %% dcline cost data 57 | % 2 startup shutdown n c(n-1) ... c0 58 | mpc.dclinecost = [ 59 | 2 0.0 0.0 4 0.000000 0.000000 40.000000 0.000000; 60 | ]; 61 | -------------------------------------------------------------------------------- /docs/src/result-data.md: -------------------------------------------------------------------------------- 1 | # PowerModels Result Data Format 2 | 3 | ## The Result Data Dictionary 4 | 5 | PowerModels utilizes a dictionary to organize the results of a run command. The dictionary uses strings as key values so it can be serialized to JSON for algorithmic data exchange. 6 | The data dictionary organization is designed to be consistent with the PowerModels [The Network Data Dictionary](@ref). 7 | 8 | At the top level the results data dictionary is structured as follows: 9 | 10 | ```json 11 | { 12 | "solver":, # name of the Julia class used to solve the model 13 | "status":, # solver status at termination 14 | "solve_time":, # reported solve time (seconds) 15 | "objective":, # the final evaluation of the objective function 16 | "objective_lb":, # the final lower bound of the objective function (if available) 17 | "machine":{...}, # computer hardware information (details below) 18 | "data":{...}, # test case information (details below) 19 | "solution":{...} # complete solution information (details below) 20 | } 21 | ``` 22 | 23 | ### Machine Data 24 | 25 | This object provides basic information about the hardware that was 26 | used when the run command was called. 27 | 28 | ```json 29 | { 30 | "cpu":, # CPU product name 31 | "memory": # the amount of system memory (units given) 32 | } 33 | ``` 34 | 35 | ### Case Data 36 | 37 | This object provides basic information about the network cases that was 38 | used when the run command was called. 39 | 40 | ```json 41 | { 42 | "name":, # the name from the network data structure 43 | "bus_count":, # the number of buses in the network data structure 44 | "branch_count": # the number of branches in the network data structure 45 | } 46 | ``` 47 | 48 | ### Solution Data 49 | 50 | The solution object provides detailed information about the solution 51 | produced by the run command. The solution is organized similarly to 52 | [The Network Data Dictionary](@ref) with the same nested structure and 53 | parameter names, when available. A network solution most often only includes 54 | a small subset of the data included in the network data. 55 | 56 | For example the data for a bus, `data["bus"]["1"]` is structured as follows, 57 | 58 | ``` 59 | { 60 | "bus_i": 1, 61 | "bus_type": 3, 62 | "vm":1.0, 63 | "va":0.0, 64 | ... 65 | } 66 | ``` 67 | 68 | A solution specifying a voltage magnitude and angle would for the same case, i.e. `result["solution"]["bus"]["1"]`, would result in, 69 | 70 | ``` 71 | { 72 | "vm":1.12, 73 | "va":-3.59, 74 | } 75 | ``` 76 | 77 | A table-like text summary of the solution data can be generated using the standard data summary function as follows, 78 | 79 | ``` 80 | PowerModels.print_summary(result["solution"]) 81 | ``` 82 | 83 | Because the data dictionary and the solution dictionary have the same structure 84 | PowerModels provides an `update_data` helper function which can be used to 85 | update a data dictionary with the values from a solution as follows, 86 | 87 | ``` 88 | PowerModels.update_data(data, result["solution"]) 89 | ``` 90 | 91 | -------------------------------------------------------------------------------- /src/form/wrm.jl: -------------------------------------------------------------------------------- 1 | export 2 | SDPWRMPowerModel, SDPWRMForm 3 | 4 | "" 5 | abstract type AbstractWRMForm <: AbstractConicPowerFormulation end 6 | 7 | "" 8 | abstract type SDPWRMForm <: AbstractWRMForm end 9 | 10 | "" 11 | const SDPWRMPowerModel = GenericPowerModel{SDPWRMForm} 12 | 13 | "" 14 | SDPWRMPowerModel(data::Dict{String,Any}; kwargs...) = GenericPowerModel(data, SDPWRMForm; kwargs...) 15 | 16 | 17 | "" 18 | function variable_voltage(pm::GenericPowerModel{T}, n::Int=pm.cnw; bounded = true) where T <: AbstractWRMForm 19 | wr_min, wr_max, wi_min, wi_max = calc_voltage_product_bounds(pm.ref[:nw][n][:buspairs]) 20 | 21 | w_index = 1:length(keys(pm.ref[:nw][n][:bus])) 22 | lookup_w_index = Dict([(bi,i) for (i,bi) in enumerate(keys(pm.ref[:nw][n][:bus]))]) 23 | 24 | WR = pm.var[:nw][n][:WR] = @variable(pm.model, 25 | [1:length(keys(pm.ref[:nw][n][:bus])), 1:length(keys(pm.ref[:nw][n][:bus]))], Symmetric, basename="$(n)_WR" 26 | ) 27 | WI = pm.var[:nw][n][:WI] = @variable(pm.model, 28 | [1:length(keys(pm.ref[:nw][n][:bus])), 1:length(keys(pm.ref[:nw][n][:bus]))], basename="$(n)_WI" 29 | ) 30 | 31 | # bounds on diagonal 32 | for (i, bus) in pm.ref[:nw][n][:bus] 33 | w_idx = lookup_w_index[i] 34 | wr_ii = WR[w_idx,w_idx] 35 | wi_ii = WR[w_idx,w_idx] 36 | 37 | if bounded 38 | setlowerbound(wr_ii, bus["vmin"]^2) 39 | setupperbound(wr_ii, bus["vmax"]^2) 40 | 41 | #this breaks SCS on the 3 bus exmple 42 | #setlowerbound(wi_ii, 0) 43 | #setupperbound(wi_ii, 0) 44 | else 45 | setlowerbound(wr_ii, 0) 46 | end 47 | end 48 | 49 | # bounds on off-diagonal 50 | for (i,j) in keys(pm.ref[:nw][n][:buspairs]) 51 | wi_idx = lookup_w_index[i] 52 | wj_idx = lookup_w_index[j] 53 | 54 | if bounded 55 | setupperbound(WR[wi_idx, wj_idx], wr_max[(i,j)]) 56 | setlowerbound(WR[wi_idx, wj_idx], wr_min[(i,j)]) 57 | 58 | setupperbound(WI[wi_idx, wj_idx], wi_max[(i,j)]) 59 | setlowerbound(WI[wi_idx, wj_idx], wi_min[(i,j)]) 60 | end 61 | end 62 | 63 | pm.var[:nw][n][:w] = Dict{Int,Any}() 64 | for (i, bus) in pm.ref[:nw][n][:bus] 65 | w_idx = lookup_w_index[i] 66 | pm.var[:nw][n][:w][i] = WR[w_idx,w_idx] 67 | end 68 | 69 | pm.var[:nw][n][:wr] = Dict{Tuple{Int,Int},Any}() 70 | pm.var[:nw][n][:wi] = Dict{Tuple{Int,Int},Any}() 71 | for (i,j) in keys(pm.ref[:nw][n][:buspairs]) 72 | w_fr_index = lookup_w_index[i] 73 | w_to_index = lookup_w_index[j] 74 | 75 | pm.var[:nw][n][:wr][(i,j)] = WR[w_fr_index, w_to_index] 76 | pm.var[:nw][n][:wi][(i,j)] = WI[w_fr_index, w_to_index] 77 | end 78 | 79 | end 80 | 81 | 82 | "" 83 | function constraint_voltage(pm::GenericPowerModel{T}, n::Int) where T <: AbstractWRMForm 84 | WR = pm.var[:nw][n][:WR] 85 | WI = pm.var[:nw][n][:WI] 86 | 87 | @SDconstraint(pm.model, [WR WI; -WI WR] >= 0) 88 | 89 | # place holder while debugging sdp constraint 90 | #for (i,j) in keys(pm.ref[:nw][n][:buspairs]) 91 | # relaxation_complex_product(pm.model, w[i], w[j], wr[(i,j)], wi[(i,j)]) 92 | #end 93 | end 94 | -------------------------------------------------------------------------------- /docs/src/constraints.md: -------------------------------------------------------------------------------- 1 | # Constraints 2 | 3 | ```@meta 4 | CurrentModule = PowerModels 5 | ``` 6 | 7 | ## Constraint Templates 8 | Constraint templates help simplify data wrangling across multiple Power Flow formulations by providing an abstraction layer between the network data and network constraint definitions. The constraint template's job is to extract the required parameters from a given network data structure and pass the data as named arguments to the Power Flow formulations. 9 | 10 | These templates should be defined over `GenericPowerModel` and should not refer to model variables. For more details, see the files: `core/constraint_template.jl` and `core/constraint.jl`. 11 | 12 | ## Generator Constraints 13 | 14 | ```@docs 15 | constraint_active_gen_setpoint 16 | constraint_reactive_gen_setpoint 17 | ``` 18 | 19 | ## Bus Constraints 20 | 21 | ### Setpoint Constraints 22 | 23 | ```@docs 24 | constraint_theta_ref 25 | constraint_voltage_magnitude_setpoint 26 | ``` 27 | 28 | ### KCL Constraints 29 | 30 | ```@docs 31 | constraint_kcl_shunt 32 | constraint_kcl_shunt_ne 33 | ``` 34 | 35 | ## Branch Constraints 36 | 37 | ### Ohm's Law Constraints 38 | 39 | ```@docs 40 | constraint_ohms_yt_from 41 | constraint_ohms_yt_to 42 | constraint_ohms_y_from 43 | constraint_ohms_y_to 44 | ``` 45 | 46 | ### On/Off Ohm's Law Constraints 47 | 48 | ```@docs 49 | constraint_ohms_yt_from_on_off 50 | constraint_ohms_yt_to_on_off 51 | constraint_ohms_yt_from_ne 52 | constraint_ohms_yt_to_ne 53 | ``` 54 | 55 | ### Current 56 | 57 | ```@docs 58 | constraint_power_magnitude_sqr 59 | constraint_power_magnitude_link 60 | ``` 61 | 62 | ### Thermal Limit Constraints 63 | 64 | ```@docs 65 | constraint_thermal_limit_from 66 | constraint_thermal_limit_to 67 | constraint_thermal_limit_from_on_off 68 | constraint_thermal_limit_to_on_off 69 | constraint_thermal_limit_from_ne 70 | constraint_thermal_limit_to_ne 71 | ``` 72 | 73 | ### Phase Angle Difference Constraints 74 | 75 | ```@docs 76 | constraint_voltage_angle_difference 77 | constraint_voltage_angle_difference_on_off 78 | constraint_voltage_angle_difference_ne 79 | ``` 80 | 81 | ### Loss Constraints 82 | 83 | ```@docs 84 | constraint_loss_lb 85 | ``` 86 | 87 | ## DC Line Constraints 88 | ### Network Flow Constraints 89 | 90 | ```@docs 91 | constraint_dcline 92 | ``` 93 | 94 | ## Commonly Used Constraints 95 | The following methods generally assume that the model contains `p` and `q` values for branches line flows and bus flow conservation. 96 | 97 | ### Generic thermal limit constraint 98 | 99 | ```julia 100 | constraint_thermal_limit_from(pm::GenericPowerModel, f_idx, rate_a) 101 | constraint_thermal_limit_to(pm::GenericPowerModel, t_idx, rate_a) 102 | ``` 103 | 104 | ### Generic on/off thermal limit constraint 105 | 106 | ```julia 107 | constraint_thermal_limit_from_on_off(pm::GenericPowerModel, i, f_idx, rate_a) 108 | constraint_thermal_limit_to_on_off(pm::GenericPowerModel, i, t_idx, rate_a) 109 | constraint_thermal_limit_from_ne(pm::GenericPowerModel, i, f_idx, rate_a) 110 | constraint_thermal_limit_to_ne(pm::GenericPowerModel, i, t_idx, rate_a) 111 | constraint_active_gen_setpoint(pm::GenericPowerModel, i, pg) 112 | constraint_reactive_gen_setpoint(pm::GenericPowerModel, i, qg) 113 | ``` 114 | -------------------------------------------------------------------------------- /test/data/matpower/case5_tnep.m: -------------------------------------------------------------------------------- 1 | % based on NESTA v0.6.0 2 | function mpc = case5_pjm_tnep 3 | mpc.version = '2'; 4 | mpc.baseMVA = 100.0; 5 | 6 | %% area data 7 | % area refbus 8 | mpc.areas = [ 9 | 1 4; 10 | ]; 11 | 12 | %% bus data 13 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 14 | mpc.bus = [ 15 | 1 2 0.0 0.0 0.0 0.0 1 1.07762 2.80377 230.0 1 1.10000 0.90000; 16 | 2 1 300.0 98.61 0.0 0.0 1 1.08407 -0.73465 230.0 1 1.10000 0.90000; 17 | 3 2 300.0 98.61 0.0 0.0 1 1.10000 -0.55972 230.0 1 1.10000 0.90000; 18 | 4 3 400.0 131.47 0.0 0.0 1 1.06414 0.00000 230.0 1 1.10000 0.90000; 19 | 5 2 0.0 0.0 0.0 0.0 1 1.06907 3.59033 230.0 1 1.10000 0.90000; 20 | ]; 21 | 22 | %% generator data 23 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 24 | mpc.gen = [ 25 | 1 40.0 30.0 30.0 -30.0 1.07762 100.0 1 40.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 26 | 1 170.0 127.5 127.5 -127.5 1.07762 100.0 1 170.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 27 | 3 324.498 390.0 390.0 -390.0 1.1 100.0 1 520.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 28 | 4 0.0 -10.802 150.0 -150.0 1.06414 100.0 1 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 29 | 5 470.694 -165.039 450.0 -450.0 1.06907 100.0 1 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; 30 | ]; 31 | 32 | %% generator cost data 33 | % 2 startup shutdown n c(n-1) ... c0 34 | mpc.gencost = [ 35 | 2 0.0 0.0 3 0.000000 14.000000 0.000000; 36 | 2 0.0 0.0 3 0.000000 15.000000 0.000000; 37 | 2 0.0 0.0 3 0.000000 30.000000 0.000000; 38 | 2 0.0 0.0 3 0.000000 40.000000 0.000000; 39 | 2 0.0 0.0 3 0.000000 10.000000 0.000000; 40 | ]; 41 | 42 | %% branch data 43 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 44 | mpc.branch = [ 45 | % 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 -30.0 30.0; 46 | % 1 4 0.00304 0.0304 0.00658 426 426 426 0.0 0.0 1 -30.0 30.0; 47 | 1 5 0.00064 0.0064 0.03126 426 426 426 0.0 0.0 1 -30.0 30.0; 48 | 2 3 0.00108 0.0108 0.01852 426 426 426 0.0 0.0 1 -30.0 30.0; 49 | 3 4 0.00297 0.0297 0.00674 426 426 426 0.0 0.0 1 -30.0 30.0; 50 | 4 5 0.00297 0.0297 0.00674 240.0 240.0 240.0 0.0 0.0 1 -30.0 30.0; 51 | ]; 52 | 53 | %column_names% f_bus t_bus br_r br_x br_b rate_a rate_b rate_c tap shift br_status angmin angmax construction_cost 54 | mpc.ne_branch = [ 55 | 1 2 0.00281 0.0281 0.00712 400.0 400.0 400.0 0.0 0.0 1 -30.0 30.0 1; 56 | 1 4 0.00304 0.0304 0.00658 426 426 426 0.0 0.0 1 -30.0 30.0 1; 57 | 1 4 0.00304 0.0304 0.00658 0.0 0.0 0.0 0.0 0.0 1 -30.0 30.0 0; 58 | ]; 59 | 60 | %% dcline data 61 | % fbus tbus status Pf Pt Qf Qt Vf Vt Pmin Pmax QminF QmaxF QminT QmaxT loss0 loss1 62 | mpc.dcline = [ 63 | 3 5 1 10 8.9 99.9934 -10.4049 1.1 1.05304 10 100 -100 100 -100 100 1 0.01; 64 | ]; 65 | 66 | %% dcline cost data 67 | % 2 startup shutdown n c(n-1) ... c0 68 | mpc.dclinecost = [ 69 | 2 0.0 0.0 3 0.000000 40.000000 0.000000; 70 | ]; 71 | -------------------------------------------------------------------------------- /test/data/pti/frankenstein_00.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing all of the core features of v33 data files 3 | developed by Carleton Coffrin (cjc@lanl.gov) June 2017 4 | 1002,'FAV SPOT 02', 345.0000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 1005,'FAV PLACE 05', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 1008,'FAV PLC 08', 87.0000, 2, 101, 201, 301,0.95000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 7 | 1009,'FAV PLACE 09', 87.0000, 3, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 0 / END OF BUS DATA, BEGIN LOAD DATA 9 | 1008,'LW',1, 101, 201, 18.900, 6.900, 0.000, 0.000, 0.000, 0.000, 301,1 10 | 1009,'Z0',1, 101, 201, 10.500, 2.300, 0.000, 0.000, 0.000, 0.000, 301,1 11 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 12 | 1009,'1 ', 1, 0.000, 105.300 13 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 14 | 1002,'1 ', 27.500, 2.000, 2.000, 2.000,1.02000, 0, 31.300, 0.00000, 0.23000, 0.00000, 0.00000,1.00000,1, 100.0, 27.500, 16.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 15 | 1009,'1 ', -22.000, -88.041, 250.000, -250.000,1.03000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 250.000, -250.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 16 | 1005,'1 ', 20.000, -23.413, 250.000, -250.000,1.02000, 0, 320.000, 0.00000, 0.15000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, -200.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 17 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 18 | 1008,1005,'1 ',1.27800E-3,1.22940E-2,2.27080E-1,1086.00,1195.00,1086.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 25.5, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 19 | 1005,1009,'1 ',4.75000E-4,4.68000E-3,8.20000E-2,1044.00,1170.00,1044.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 9.4, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 20 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 21 | 1005,1002, 0,'1 ',1,1,1,0.00000E0,0.00000E0,2,'T2 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 22 | 5.21000E-3,1.77370E-1, 100.00 23 | 1.025000, 115.000, 0.000, 84.00, 84.00, 84.00,0, 0,1.500000,0.500000,1.500000,0.500000,9999, 0, 0.00000, 0.00000, 0.000 24 | 1.000000, 13.800 25 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 26 | 101, 0, -1307.000, 1.000,'BEST AREA ' 27 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 28 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 29 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 30 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 31 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 32 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 33 | 201,'FOO ' 34 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 35 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 36 | 301,'BAR ' 37 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 38 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 39 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 40 | 0 /END OF GNE DEVICE DATA 41 | Q 42 | -------------------------------------------------------------------------------- /test/data/pti/frankenstein_00_2.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing all of the core features of v33 data files 3 | developed by Carleton Coffrin (cjc@lanl.gov) June 2017 4 | 1002,'FAV SPOT 02', 345.0000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 1005,'FAV PLACE 05', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 1008,'FAV PLC 08', 87.0000, 2, 101, 201, 301,0.95000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 7 | 1009,'FAV PLACE 09', 87.0000, 3, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 0 / END OF BUS DATA, BEGIN LOAD DATA 9 | 1008,'LW',1, 101, 201, 18.900, 6.900, 0.000, 0.000, 0.000, 0.000, 301,1 10 | 1009,'Z0',1, 101, 201, 10.500, 2.300, 0.000, 0.000, 0.000, 0.000, 301,1 11 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 12 | 1009,'1 ', 1, 0.000, 105.300 13 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 14 | 1002,'1 ', 27.500, 2.000, 2.000, 2.000,1.02000, 0, 31.300, 0.00000, 0.23000, 0.00000, 0.00000,1.00000,1, 100.0, 27.500, 16.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 15 | 1009,'1 ', -22.000, -88.041, 250.000, -250.000,1.03000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 250.000, -250.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 16 | 1005,'1 ', 20.000, -23.413, 250.000, -250.000,1.02000, 0, 320.000, 0.00000, 0.15000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, -200.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 17 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 18 | 1008,1005,'1 ',1.27800E-3,1.22940E-2,2.27080E-1,1086.00,1195.00,1086.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 25.5, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 19 | 1005,1009,'1 ',4.75000E-4,4.68000E-3,8.20000E-2,1044.00,1170.00,1044.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 9.4, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 20 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 21 | 1005,1002, 0,'1 ',3,3,1,0.00000E0,0.00000E0,2,'T2 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 22 | 5.21000E-3,1.77370E-1, 100.00 23 | 1.025000, 87.000, 0.000, 84.00, 84.00, 84.00,0, 0,1.500000,0.500000,1.500000,0.500000,9999, 0, 0.00000, 0.00000, 0.000 24 | 1.000000, 347.000 25 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 26 | 101, 0, -1307.000, 1.000,'BEST AREA ' 27 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 28 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 29 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 30 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 31 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 32 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 33 | 201,'FOO ' 34 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 35 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 36 | 301,'BAR ' 37 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 38 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 39 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 40 | 0 /END OF GNE DEVICE DATA 41 | Q 42 | -------------------------------------------------------------------------------- /test/data/pti/case3.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 0, 60.00 2 | tests basic network fetures 3 | this case does not have an HVDC line that occurs in the Matpower case 4 | 1,'1 ', 240.0000,3, 1, 1, 1,1.10000002, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 2,'2 ', 240.0000,2, 1, 1, 1,0.92616999, 7.258830, 1.10000, 0.90000, 1.10000, 0.90000 6 | 3,'3 ', 240.0000,2, 1, 2, 1,0.89999998, -17.267101, 1.10000, 0.90000, 1.10000, 0.90000 7 | 0 / END OF BUS DATA, BEGIN LOAD DATA 8 | 1,'1 ',1, 1, 1, 110.000, 40.000, 0.000, 0.000, 0.000, 0.000, 1,1 9 | 2,'1 ',1, 1, 1, 110.000, 40.000, 0.000, 0.000, 0.000, 0.000, 1,1 10 | 3,'1 ',1, 1, 1, 95.000, 50.000, 0.000, 0.000, 0.000, 0.000, 1,1 11 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 12 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 13 | 1,'1 ', 158.067, 28.790, 1000.000, -1000.000,1.10000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 2000.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 14 | 1,'DC', -10.000, 25.910, 25.910, 25.910,1.10000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, -10.000, -10.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 15 | 2,'1 ', 160.006, -4.630, 1000.000, -1000.000,0.92617, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 1500.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 16 | 2,'DC', 10.000, -4.160, -4.160, -4.160,0.92617, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 10.000, 10.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 17 | 3,'1 ', 0.000, -4.843, 1000.000, -1000.000,0.90000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 0.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 18 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 19 | 1, 2,'1 ',4.20000E-2,9.00000E-1,3.00000E-1,9000.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 20 | 1, 3,'1 ',6.50000E-2,6.20000E-1,4.50000E-1,9000.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 21 | 3, 2,'1 ',2.50000E-2,7.50000E-1,7.00000E-1, 50.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 22 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 23 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 24 | 1, 0, 0.000, 1.000,'1 ' 25 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 26 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 27 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 28 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 29 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 30 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 31 | 1,'1 ' 32 | 2,'2 ' 33 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 34 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 35 | 1,'1' 36 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 37 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 38 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 39 | 0 /END OF GNE DEVICE DATA 40 | Q 41 | -------------------------------------------------------------------------------- /docs/src/quickguide.md: -------------------------------------------------------------------------------- 1 | # Quick Start Guide 2 | 3 | Once PowerModels is installed, Ipopt is installed, and a network data file (e.g. `"nesta_case3_lmbd.m"`) has been acquired, an AC Optimal Power Flow can be executed with, 4 | 5 | ```julia 6 | using PowerModels 7 | using Ipopt 8 | 9 | run_ac_opf("nesta_case3_lmbd.m", IpoptSolver()) 10 | ``` 11 | 12 | Similarly, a DC Optimal Power Flow can be executed with 13 | 14 | ```julia 15 | run_dc_opf("nesta_case3_lmbd.m", IpoptSolver()) 16 | ``` 17 | 18 | 19 | ## Getting Results 20 | 21 | The run commands in PowerModels return detailed results data in the form of a dictionary. 22 | This dictionary can be saved for further processing as follows, 23 | 24 | ```julia 25 | result = run_ac_opf("nesta_case3_lmbd.m", IpoptSolver()) 26 | ``` 27 | 28 | For example, the algorithm's runtime and final objective value can be accessed with, 29 | 30 | ``` 31 | result["solve_time"] 32 | result["objective"] 33 | ``` 34 | 35 | The `"solution"` field contains detailed information about the solution produced by the run method. 36 | For example, the following dictionary comprehension can be used to inspect the bus phase angles in the solution, 37 | 38 | ``` 39 | Dict(name => data["va"] for (name, data) in result["solution"]["bus"]) 40 | ``` 41 | 42 | For more information about PowerModels result data see the [PowerModels Result Data Format](@ref) section. 43 | 44 | 45 | ## Accessing Different Formulations 46 | 47 | The function "run_ac_opf" and "run_dc_opf" are shorthands for a more general formulation-independent OPF execution, "run_opf". 48 | For example, `run_ac_opf` is equivalent to, 49 | 50 | ```julia 51 | run_opf("nesta_case3_lmbd.m", ACPPowerModel, IpoptSolver()) 52 | ``` 53 | 54 | where "ACPPowerModel" indicates an AC formulation in polar coordinates. This more generic `run_opf()` allows one to solve an OPF problem with any power network formulation implemented in PowerModels. For example, an SOC Optimal Power Flow can be run with, 55 | 56 | ```julia 57 | run_opf("nesta_case3_lmbd.m", SOCWRPowerModel, IpoptSolver()) 58 | ``` 59 | 60 | ## Modifying Network Data 61 | The following example demonstrates one way to perform multiple PowerModels solves while modifing the network data in Julia, 62 | 63 | ```julia 64 | network_data = PowerModels.parse_file("nesta_case3_lmbd.m") 65 | 66 | run_opf(network_data, ACPPowerModel, IpoptSolver()) 67 | 68 | network_data["load"]["3"]["pd"] = 0.0 69 | network_data["load"]["3"]["qd"] = 0.0 70 | 71 | run_opf(network_data, ACPPowerModel, IpoptSolver()) 72 | ``` 73 | 74 | For additional details about the network data, see the [PowerModels Network Data Format](@ref) section. 75 | 76 | ## Inspecting AC and DC branch flow results 77 | The flow AC and DC branch results are not written to the result by default. To inspect the flow results, pass a settings Dict 78 | ```julia 79 | result = run_opf("case3_dc.m", ACPPowerModel, IpoptSolver(), setting = Dict("output" => Dict("line_flows" => true))) 80 | result["solution"]["dcline"]["1"] 81 | result["solution"]["branch"]["2"] 82 | ``` 83 | 84 | The losses of a AC or DC branch can be derived: 85 | ```julia 86 | loss_ac = Dict(name => data["p_to"]+data["p_from"] for (name, data) in result["solution"]["branch"]) 87 | loss_dc = Dict(name => data["p_to"]+data["p_from"] for (name, data) in result["solution"]["dcline"]) 88 | ``` 89 | 90 | 91 | ## Inspecting the Formulation 92 | The following example demonstrates how to break a `run_opf` call into seperate model building and solving steps. This allows inspection of the JuMP model created by PowerModels for the AC-OPF problem, 93 | 94 | ```julia 95 | pm = build_generic_model("nesta_case3_lmbd.m", ACPPowerModel, PowerModels.post_opf) 96 | 97 | print(pm.model) 98 | 99 | solve_generic_model(pm, IpoptSolver()) 100 | ``` 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerModels.jl 2 | 3 | Release: [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.4.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.5.svg)](http://pkg.julialang.org/?pkg=PowerModels), [![PowerModels](http://pkg.julialang.org/badges/PowerModels_0.6.svg)](http://pkg.julialang.org/?pkg=PowerModels), 4 | [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://lanl-ansi.github.io/PowerModels.jl/stable) 5 | 6 | Dev: 7 | [![Build Status](https://travis-ci.org/lanl-ansi/PowerModels.jl.svg?branch=master)](https://travis-ci.org/lanl-ansi/PowerModels.jl) 8 | [![codecov](https://codecov.io/gh/lanl-ansi/PowerModels.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/lanl-ansi/PowerModels.jl) 9 | [![](https://img.shields.io/badge/docs-latest-blue.svg)](https://lanl-ansi.github.io/PowerModels.jl/latest) 10 | 11 | PowerModels.jl is a Julia/JuMP package for Steady-State Power Network Optimization. 12 | It is designed to enable computational evaluation of emerging power network formulations and algorithms in a common platform. 13 | The code is engineered to decouple problem specifications (e.g. Power Flow, Optimal Power Flow, ...) from the power network formulations (e.g. AC, DC-approximation, SOC-relaxation, ...). 14 | This enables the definition of a wide variety of power network formulations and their comparison on common problem specifications. 15 | 16 | **Core Problem Specifications** 17 | * Power Flow (pf) 18 | * Optimal Power Flow (opf) 19 | * Optimal Transmission Switching (ots) 20 | * Transmission Network Expansion Planning (tnep) 21 | 22 | **Core Network Formulations** 23 | * AC (polar and rectangular coordinates) 24 | * DC Approximation (polar coordinates) 25 | * SOC Relaxation (W-space) 26 | * QC Relaxation (W+L-space) 27 | 28 | **Network Data Formats** 29 | * Matpower ".m" files 30 | 31 | For further information, consult the package [documentation](https://lanl-ansi.github.io/PowerModels.jl/stable/). 32 | 33 | 34 | ## Development 35 | 36 | Community-driven development and enhancement of PowerModels are welcome and encouraged. Please fork this repository and share your contributions to the master with pull requests. See [CONTRIBUTING.md](https://github.com/lanl-ansi/PowerModels.jl/blob/master/CONTRIBUTING.md) for code contribution guidelines. 37 | 38 | 39 | ## Acknowledgments 40 | 41 | This code has been developed as part of the Advanced Network Science Initiative at Los Alamos National Laboratory. 42 | The primary developer is Carleton Coffrin(@ccoffrin) with support from the following contributors, 43 | - Russell Bent (@rb004f) LANL, TNEP problem specification 44 | - David Fobes (@pseudocubic) LANL, PSSE raw data support 45 | - Rory Finnegan (@rofinn) Invenia, Memento Logging 46 | - Frederik Geth (@frederikgeth) and Hakan Ergun (@hakanergun) KU Leuven, Branch Flow formulation and HVDC lines 47 | - Miles Lubin (@mlubin) MIT, Julia/JuMP advise 48 | - Yeesian Ng (@yeesian) MIT, Documenter.jl setup 49 | 50 | 51 | ## Citing PowerModels 52 | 53 | If you find PowerModels useful in your work, we kindly request that you cite the following [technical report](https://arxiv.org/abs/1711.01728): 54 | ``` 55 | @misc{1711.01728, 56 | author = {Carleton Coffrin and Russell Bent and Kaarthik Sundar and Yeesian Ng and Miles Lubin}, 57 | title = {PowerModels.jl: An Open-Source Framework for Exploring Power Flow Formulations}, 58 | year = {2017}, 59 | eprint = {arXiv:1711.01728}, 60 | url = {http://arxiv.org/abs/1711.01728} 61 | } 62 | ``` 63 | Citation of the orginal works for problem denifitions (e.g. OPF) and power flow formulations (e.g. SOC) is also encuraged when publishing works that use PowerModels. 64 | 65 | 66 | ## License 67 | 68 | This code is provided under a BSD license as part of the Multi-Infrastructure Control and Optimization Toolkit (MICOT) project, LA-CC-13-108. 69 | -------------------------------------------------------------------------------- /test/tnep.jl: -------------------------------------------------------------------------------- 1 | 2 | 3 | function check_tnep_status(sol) 4 | for (idx,val) in sol["ne_branch"] 5 | @test isapprox(val["built"], 0.0, rtol=1e-6) || isapprox(val["built"], 1.0, rtol=1e-6) 6 | end 7 | end 8 | 9 | 10 | @testset "test ac tnep" begin 11 | @testset "3-bus case" begin 12 | result = run_tnep("../test/data/matpower/case3_tnep.m", ACPPowerModel, juniper_solver) 13 | 14 | check_tnep_status(result["solution"]) 15 | 16 | @test result["status"] == :LocalOptimal 17 | @test isapprox(result["objective"], 2; atol = 1e-2) 18 | end 19 | # omitting due to numerical stability issues on Linux 20 | #@testset "5-bus case" begin 21 | # result = run_tnep("../test/data/matpower/case5_tnep.m", ACPPowerModel, juniper_solver) 22 | 23 | # check_tnep_status(result["solution"]) 24 | 25 | # @test result["status"] == :LocalOptimal 26 | # @test isapprox(result["objective"], 1; atol = 1e-2) 27 | #end 28 | end 29 | 30 | 31 | @testset "test soc tnep" begin 32 | @testset "3-bus case" begin 33 | result = run_tnep("../test/data/matpower/case3_tnep.m", SOCWRPowerModel, pajarito_solver; setting = Dict("output" => Dict("branch_flows" => true))) 34 | 35 | check_tnep_status(result["solution"]) 36 | 37 | @test result["status"] == :Optimal 38 | @test isapprox(result["objective"], 2; atol = 1e-2) 39 | end 40 | @testset "5-bus rts case" begin 41 | result = run_tnep("../test/data/matpower/case5_tnep.m", SOCWRPowerModel, pajarito_solver) 42 | 43 | check_tnep_status(result["solution"]) 44 | 45 | @test result["status"] == :Optimal 46 | @test isapprox(result["objective"], 1; atol = 1e-2) 47 | end 48 | end 49 | 50 | @testset "test dc tnep" begin 51 | @testset "3-bus case" begin 52 | result = run_tnep("../test/data/matpower/case3_tnep.m", DCPPowerModel, pajarito_solver) 53 | 54 | check_tnep_status(result["solution"]) 55 | 56 | @test result["status"] == :Optimal 57 | @test isapprox(result["objective"], 2; atol = 1e-2) 58 | end 59 | 60 | #= 61 | # skip this one becouse it is breaking Julia package tests 62 | @testset "5-bus case" begin 63 | result = run_tnep("../test/data/matpower/case5_tnep.m", DCPPowerModel, pajarito_solver) 64 | 65 | check_tnep_status(result["solution"]) 66 | 67 | @test result["status"] == :Optimal 68 | @test isapprox(result["objective"], 1; atol = 1e-2) 69 | end 70 | =# 71 | end 72 | 73 | @testset "test dc-losses tnep" begin 74 | @testset "3-bus case" begin 75 | result = run_tnep("../test/data/matpower/case3_tnep.m", DCPLLPowerModel, pajarito_solver) 76 | 77 | check_tnep_status(result["solution"]) 78 | 79 | @test result["status"] == :Optimal 80 | @test isapprox(result["objective"], 2; atol = 1e-2) 81 | end 82 | 83 | @testset "5-bus case" begin 84 | result = run_tnep("../test/data/matpower/case5_tnep.m", DCPLLPowerModel, pajarito_solver) 85 | 86 | check_tnep_status(result["solution"]) 87 | 88 | @test result["status"] == :Optimal 89 | @test isapprox(result["objective"], 1; atol = 1e-2) 90 | end 91 | end 92 | 93 | 94 | @testset "test tnep branch flow output" begin 95 | @testset "3-bus case" begin 96 | result = run_tnep("../test/data/matpower/case3_tnep.m", SOCWRPowerModel, pajarito_solver; setting = Dict("output" => Dict("branch_flows" => true))) 97 | 98 | check_tnep_status(result["solution"]) 99 | 100 | @test result["status"] == :Optimal 101 | @test isapprox(result["objective"], 2; atol = 1e-2) 102 | 103 | branches = result["solution"]["branch"] 104 | ne_branches = result["solution"]["ne_branch"] 105 | flow_keys = ["pf","qf","pt","qt"] 106 | 107 | for fk in flow_keys 108 | @test !isnan(branches["1"][fk]) 109 | @test !isnan(ne_branches["1"][fk]) 110 | @test !isnan(ne_branches["2"][fk]) 111 | @test !isnan(ne_branches["3"][fk]) 112 | end 113 | end 114 | end 115 | -------------------------------------------------------------------------------- /test/data/pti/frankenstein_20.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing all of the core features of v33 data files 3 | developed by Carleton Coffrin (cjc@lanl.gov) June 2017 4 | 1002,'FAV SPOT 02', 345.0000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 1003,'FAV SPOT 03', 24.9000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 1005,'FAV PLACE 05', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000, 1.10000, 0.90000, 1.10000, 0.90000 7 | 1007,'FAV PLACE 07', 230.0000, 1, 101, 201, 301,1.00000000, 2.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 1008,'FAV PLC 08', 87.0000, 2, 101, 201, 301,0.95000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 9 | 1009,'FAV PLACE 09', 87.0000, 3, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 10 | 0 / END OF BUS DATA, BEGIN LOAD DATA 11 | 1008,'LW',1, 101, 201, 18.900, 6.900, 0.000, 0.000, 0.000, 0.000, 301,1 12 | 1009,'Z0',1, 101, 201, 10.500, 2.300, 0.000, 0.000, 0.000, 0.000, 301,1 13 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 14 | 1009,'1 ', 1, 0.000, 105.300 15 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 16 | 1002,'1 ', 27.500, 2.000, 2.000, 2.000,1.02000, 0, 31.300, 0.00000, 0.23000, 0.00000, 0.00000,1.00000,1, 100.0, 27.500, 16.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 17 | 1009,'1 ', -22.000, -88.041, 250.000, -250.000,1.03000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 250.000, -250.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 18 | 1003,'W1', 3.700, -3.900, -3.900, -3.900,1.00000, 0, 20.500, 0.00000, 0.30220, 0.00000, 0.00000,1.00000,1, 100.0, 18.700, 0.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,1, 1.0000 19 | 1005,'1 ', 20.000, -23.413, 250.000, -250.000,1.02000, 0, 320.000, 0.00000, 0.15000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, -200.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 20 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 21 | 1008,1005,'1 ',1.27800E-3,1.22940E-2,2.27080E-1,1086.00,1195.00,1086.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 25.5, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 22 | 1005,1009,'1 ',4.75000E-4,4.68000E-3,8.20000E-2,1044.00,1170.00,1044.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 9.4, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 23 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 24 | 1005,1002, 0,'1 ',1,1,1,0.00000E0,0.00000E0,2,'T2 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 25 | 5.21000E-3,1.77370E-1, 100.00 26 | 1.025000, 115.000, 0.000, 84.00, 84.00, 84.00,0, 0,1.500000,0.500000,1.500000,0.500000,9999, 0, 0.00000, 0.00000, 0.000 27 | 1.000000, 13.800 28 | 1007,1005,1003,'1 ',2,1,2,9.75350E4,2.51000E-3,1,'T3 3W',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 29 | 1.06000E-3,3.60970E-2, 144.00,4.95400E-3,2.01040E-1, 100.00,4.35300E-3,2.38183E-1, 100.00,0.98220001, -46.128800 30 | 345.0000,345.000, 0.000, 336.00, 336.00, 0.00,0, 0,1.500000,0.510000,1.500000,0.510000, 2, 0, 0.00000, 0.00000, 0.000 31 | 141.4500,138.000, 0.000, 268.00, 268.00, 0.00,0, 0,1.500000,0.510000,1.500000,0.510000, 5, 0, 0.00000, 0.00000, 0.000 32 | 26.22000, 27.600, 0.000, 84.00, 84.00, 0.00,1, 1003,30.36000,24.84000,1.050000,1.025000, 17, 0, 0.00000, 0.00000, 0.000 33 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 34 | 101, 0, -1307.000, 1.000,'BEST AREA ' 35 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 36 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 37 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 38 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 39 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 40 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 41 | 201,'FOO ' 42 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 43 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 44 | 301,'BAR ' 45 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 46 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 47 | 1003,0,0,1,1.05000,0.95000, 0,100.0,' ', 3.80, 9, 0.10, 7, 0.10, 7, 1.00 48 | 1005,0,0,1,1.04500,0.98000, 0,100.0,' ', 6.00, 1, 6.00 49 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 50 | 0 /END OF GNE DEVICE DATA 51 | Q 52 | -------------------------------------------------------------------------------- /src/core/constraint.jl: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # This file defines commonly used constraints for power flow models 3 | # These constraints generally assume that the model contains p and q values 4 | # for branches flows and bus flow conservation 5 | ############################################################################### 6 | 7 | # Generic thermal limit constraint 8 | "`p[f_idx]^2 + q[f_idx]^2 <= rate_a^2`" 9 | function constraint_thermal_limit_from(pm::GenericPowerModel, n::Int, f_idx, rate_a) 10 | p_fr = pm.var[:nw][n][:p][f_idx] 11 | q_fr = pm.var[:nw][n][:q][f_idx] 12 | @constraint(pm.model, p_fr^2 + q_fr^2 <= rate_a^2) 13 | end 14 | 15 | "`p[t_idx]^2 + q[t_idx]^2 <= rate_a^2`" 16 | function constraint_thermal_limit_to(pm::GenericPowerModel, n::Int, t_idx, rate_a) 17 | p_to = pm.var[:nw][n][:p][t_idx] 18 | q_to = pm.var[:nw][n][:q][t_idx] 19 | @constraint(pm.model, p_to^2 + q_to^2 <= rate_a^2) 20 | end 21 | 22 | "`norm([p[f_idx]; q[f_idx]]) <= rate_a`" 23 | function constraint_thermal_limit_from(pm::GenericPowerModel{T}, n::Int, f_idx, rate_a) where T<:AbstractConicPowerFormulation 24 | p_fr = pm.var[:nw][n][:p][f_idx] 25 | q_fr = pm.var[:nw][n][:q][f_idx] 26 | @constraint(pm.model, norm([p_fr; q_fr]) <= rate_a) 27 | end 28 | 29 | "`norm([p[t_idx]; q[t_idx]]) <= rate_a`" 30 | function constraint_thermal_limit_to(pm::GenericPowerModel{T}, n::Int, t_idx, rate_a) where T<:AbstractConicPowerFormulation 31 | p_to = pm.var[:nw][n][:p][t_idx] 32 | q_to = pm.var[:nw][n][:q][t_idx] 33 | @constraint(pm.model, norm([p_to; q_to]) <= rate_a) 34 | end 35 | 36 | # Generic on/off thermal limit constraint 37 | 38 | "`p[f_idx]^2 + q[f_idx]^2 <= (rate_a * branch_z[i])^2`" 39 | function constraint_thermal_limit_from_on_off(pm::GenericPowerModel, n::Int, i, f_idx, rate_a) 40 | p_fr = pm.var[:nw][n][:p][f_idx] 41 | q_fr = pm.var[:nw][n][:q][f_idx] 42 | z = pm.var[:nw][n][:branch_z][i] 43 | @constraint(pm.model, p_fr^2 + q_fr^2 <= rate_a^2*z^2) 44 | end 45 | 46 | "`p[t_idx]^2 + q[t_idx]^2 <= (rate_a * branch_z[i])^2`" 47 | function constraint_thermal_limit_to_on_off(pm::GenericPowerModel, n::Int, i, t_idx, rate_a) 48 | p_to = pm.var[:nw][n][:p][t_idx] 49 | q_to = pm.var[:nw][n][:q][t_idx] 50 | z = pm.var[:nw][n][:branch_z][i] 51 | @constraint(pm.model, p_to^2 + q_to^2 <= rate_a^2*z^2) 52 | end 53 | 54 | "`p_ne[f_idx]^2 + q_ne[f_idx]^2 <= (rate_a * branch_ne[i])^2`" 55 | function constraint_thermal_limit_from_ne(pm::GenericPowerModel, n::Int, i, f_idx, rate_a) 56 | p_fr = pm.var[:nw][n][:p_ne][f_idx] 57 | q_fr = pm.var[:nw][n][:q_ne][f_idx] 58 | z = pm.var[:nw][n][:branch_ne][i] 59 | @constraint(pm.model, p_fr^2 + q_fr^2 <= rate_a^2*z^2) 60 | end 61 | 62 | "`p_ne[t_idx]^2 + q_ne[t_idx]^2 <= (rate_a * branch_ne[i])^2`" 63 | function constraint_thermal_limit_to_ne(pm::GenericPowerModel, n::Int, i, t_idx, rate_a) 64 | p_to = pm.var[:nw][n][:p_ne][t_idx] 65 | q_to = pm.var[:nw][n][:q_ne][t_idx] 66 | z = pm.var[:nw][n][:branch_ne][i] 67 | @constraint(pm.model, p_to^2 + q_to^2 <= rate_a^2*z^2) 68 | end 69 | 70 | "`pg[i] == pg`" 71 | function constraint_active_gen_setpoint(pm::GenericPowerModel, n::Int, i, pg) 72 | pg_var = pm.var[:nw][n][:pg][i] 73 | @constraint(pm.model, pg_var == pg) 74 | end 75 | 76 | "`qq[i] == qq`" 77 | function constraint_reactive_gen_setpoint(pm::GenericPowerModel, n::Int, i, qg) 78 | qg_var = pm.var[:nw][n][:qg][i] 79 | @constraint(pm.model, qg_var == qg) 80 | end 81 | 82 | """ 83 | Creates Line Flow constraint for DC Lines (Matpower Formulation) 84 | 85 | ``` 86 | p_fr + p_to == loss0 + p_fr * loss1 87 | ``` 88 | """ 89 | function constraint_dcline(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, loss0, loss1) where T 90 | p_fr = pm.var[:nw][n][:p_dc][f_idx] 91 | p_to = pm.var[:nw][n][:p_dc][t_idx] 92 | 93 | @constraint(pm.model, (1-loss1) * p_fr + (p_to - loss0) == 0) 94 | end 95 | 96 | "`pf[i] == pf, pt[i] == pt`" 97 | function constraint_active_dcline_setpoint(pm::GenericPowerModel, n::Int, f_idx, t_idx, pf, pt) 98 | p_fr = pm.var[:nw][n][:p_dc][f_idx] 99 | p_to = pm.var[:nw][n][:p_dc][t_idx] 100 | 101 | @constraint(pm.model, p_fr == pf) 102 | @constraint(pm.model, p_to == pt) 103 | end 104 | 105 | "do nothing, this model does not have complex voltage constraints" 106 | function constraint_voltage(pm::GenericPowerModel, n::Int) 107 | end 108 | -------------------------------------------------------------------------------- /test/data/pti/case5.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 0, 60.00 2 | tests an angle shifting transformer 3 | 4 | 1,'1 ', 230.0000,2, 1, 1, 1,1.00000000, 2.803770, 1.10000, 0.90000, 1.10000, 0.90000 5 | 2,'2 ', 230.0000,1, 1, 1, 1,1.08406997, -0.734650, 1.10000, 0.90000, 1.10000, 0.90000 6 | 3,'3 ', 230.0000,2, 1, 1, 1,1.00000000, -0.559720, 1.10000, 0.90000, 1.10000, 0.90000 7 | 4,'4 ', 230.0000,3, 1, 1, 1,1.06413996, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 10,'10 ', 230.0000,2, 1, 1, 1,1.00000000, 3.590330, 1.10000, 0.90000, 1.10000, 0.90000 9 | 0 / END OF BUS DATA, BEGIN LOAD DATA 10 | 2,'1 ',1, 1, 1, 300.000, 98.610, 0.000, 0.000, 0.000, 0.000, 1,1 11 | 3,'1 ',1, 1, 1, 300.000, 98.610, 0.000, 0.000, 0.000, 0.000, 1,1 12 | 4,'1 ',1, 1, 1, 400.000, 131.470, 0.000, 0.000, 0.000, 0.000, 1,1 13 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 14 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 15 | 1,'1 ', 40.000, 30.000, 30.000, -30.000,1.07762, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 40.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 16 | 1,'2 ', 170.000, 127.500, 127.500, -127.500,1.07762, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 170.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 17 | 3,'1 ', 324.498, 390.000, 390.000, -390.000,1.10000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 520.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 18 | 4,'1 ', 0.000, -10.802, 150.000, -150.000,1.06414, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 19 | 10,'1 ', 470.694, -165.039, 450.000, -450.000,1.06907, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 600.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 20 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 21 | 1, 2,'1 ',2.81000E-3,2.81000E-2,7.12000E-3, 400.00, 400.00, 400.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 22 | 1, 4,'1 ',3.04000E-3,3.04000E-2,6.58000E-3, 426.00, 426.00, 426.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 23 | 1, 10,'1 ',6.40000E-4,6.40000E-3,3.12600E-2, 426.00, 426.00, 426.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 24 | 2, 3,'1 ',1.08000E-3,1.08000E-2,1.85200E-2, 426.00, 426.00, 426.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 25 | 4, 10,'1 ',2.97000E-3,2.97000E-2,6.74000E-3, 240.00, 240.00, 240.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 26 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 27 | 4, 3, 0,'1 ',1,1,1,0.00000E0,6.74000E-3,2,' ',1, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 28 | 2.97000E-3,2.97000E-2, 100.00 29 | 1.050000,230.000, -1.000, 426.00, 426.00, 426.00,-3, 0, 30.00, -30.00, 150.00, 51.00,9601, 0, 0.00000, 0.00000, 0.000 30 | 1.000000,230.000 31 | 3, 4, 0,'2 ',1,1,1,0.00000E0,6.74000E-3,2,' ',1, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 32 | 2.97000E-3,2.97000E-2, 100.00 33 | 1.050000,230.000, 1.000, 426.00, 426.00, 426.00,-3, 0, 30.00, -30.00, 150.00, 51.00,9601, 0, 0.00000, 0.00000, 0.000 34 | 1.000000,230.000 35 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 36 | 1, 0, 0.000, 1.000,'1 ' 37 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 38 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 39 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 40 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 41 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 42 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 43 | 1,'1 ' 44 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 45 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 46 | 1,'1' 47 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 48 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 49 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 50 | 0 /END OF GNE DEVICE DATA 51 | Q 52 | -------------------------------------------------------------------------------- /test/data/pti/case7_tplgy.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 0, 60.00 2 | tests component status values and fixed shunts 3 | this case does not have an HVDC line that occurs in the Matpower case 4 | 1,'1 ', 240.0000,3, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 2,'2 ', 240.0000,2, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 3,'3 ', 240.0000,1, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 7 | 4,'4 ', 240.0000,1, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 5,'5 ', 240.0000,2, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 9 | 6,'6 ', 240.0000,4, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 10 | 7,'7 ', 240.0000,1, 1, 1, 1,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 11 | 0 / END OF BUS DATA, BEGIN LOAD DATA 12 | 2,'1 ',1, 1, 1, 100.000, 50.000, 0.000, 0.000, 0.000, 0.000, 1,1 13 | 4,'1 ',1, 1, 1, 100.000, 50.000, 0.000, 0.000, 0.000, 0.000, 1,1 14 | 6,'1 ',0, 1, 1, 100.000, 50.000, 0.000, 0.000, 0.000, 0.000, 1,1 15 | 7,'1 ',1, 1, 1, 50.000, 10.000, 0.000, 0.000, 0.000, 0.000, 1,1 16 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 17 | 2,'1 ', 1, 1.000, 5.000 18 | 5,'1 ', 1, 1.000, 5.000 19 | 6,'1 ', 0, 1.000, 5.000 20 | 7,'1 ', 1, 1.000, 5.000 21 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 22 | 1,'1 ', 0.000, 0.000, 1000.000, -1000.000,1.00000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 23 | 2,'1 ', 0.000, 0.000, 1000.000, -1000.000,1.00000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 140.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 24 | 5,'1 ', 0.000, 0.000, 100.000, -100.000,1.00000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 330.000, 0.000, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 25 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 26 | 1, 3,'1 ',6.50000E-2,6.20000E-1,0.00000E0, 30.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,0,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 27 | 1, 4,'1 ',1.20000E-2,5.30000E-1,0.00000E0, 60.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,0,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 28 | 1, 5,'1 ',4.20000E-2,9.00000E-1,0.00000E0, 60.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,0,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 29 | 2, 3,'1 ',7.50000E-2,5.10000E-1,0.00000E0, 45.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,0,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 30 | 3, 5,'1 ',2.50000E-2,7.50000E-1,2.50000E-1, 30.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 31 | 3, 6,'1 ',2.50000E-2,7.50000E-1,2.50000E-1, 30.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 32 | 4, 5,'1 ',2.50000E-2,7.00000E-2,5.00000E-2, 300.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 33 | 5, 6,'1 ',2.50000E-2,7.50000E-1,2.50000E-1, 30.00, 0.00, 0.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.0, 1,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 34 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 35 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 36 | 1, 0, 0.000, 1.000,'1 ' 37 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 38 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 39 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 40 | '',0,0.0,1,1.0,0,0.0,0,0.0,0,0.0 41 | 1,2,1,10.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 42 | 2,2,1, 9.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 43 | '',1,0.0,1,1.0,0,0.0,0,0.0,0,0.0 44 | 5,2,1,10.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 45 | 6,2,1, 9.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 46 | '',1,0.0,1,1.0,0,0.0,0,0.0,0,0.0 47 | 7,2,1,10.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 48 | 4,2,1, 9.0,1.0,10.0,0.0,0.0,0.0,0.0,1.0,100.0,-100.0,0,100.0 49 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 50 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 51 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 52 | 1,'1 ' 53 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 54 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 55 | 1,'1' 56 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 57 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 58 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 59 | 0 /END OF GNE DEVICE DATA 60 | Q 61 | -------------------------------------------------------------------------------- /test/data/matpower/case14.m: -------------------------------------------------------------------------------- 1 | function mpc = case14 2 | 3 | %CASE14 Power flow data for IEEE 14 bus test case. 4 | % Please see CASEFORMAT for details on the case file format. 5 | % This data was converted from IEEE Common Data Format 6 | % (ieee14cdf.txt) on 15-Oct-2014 by cdf2matp, rev. 2393 7 | % See end of file for warnings generated during conversion. 8 | % 9 | % Converted from IEEE CDF file from: 10 | % http://www.ee.washington.edu/research/pstca/ 11 | % 12 | % 08/19/93 UW ARCHIVE 100.0 1962 W IEEE 14 Bus Test Case 13 | 14 | % MATPOWER 15 | 16 | %% MATPOWER Case Format : Version 2 17 | mpc.version = '2'; 18 | 19 | %%----- Power Flow Data -----%% 20 | %% system MVA base 21 | mpc.baseMVA = 100; 22 | 23 | %% bus data 24 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 25 | mpc.bus = [ 26 | 1 3 0 0 0 0 1 1.06 0 0 1 1.06 0.94; 27 | 2 2 21.7 12.7 0 0 1 1.045 -4.98 0 1 1.06 0.94; 28 | 3 2 94.2 19 0 0 1 1.01 -12.72 0 1 1.06 0.94; 29 | 4 1 47.8 -3.9 0 0 1 1.019 -10.33 0 1 1.06 0.94; 30 | 5 1 7.6 1.6 0 0 1 1.02 -8.78 0 1 1.06 0.94; 31 | 6 2 11.2 7.5 0 0 1 1.07 -14.22 0 1 1.06 0.94; 32 | 7 1 0 0 0 0 1 1.062 -13.37 0 1 1.06 0.94; 33 | 8 1 0 0 0 0 1 1.09 -13.36 0 1 1.06 0.94; 34 | 9 1 29.5 16.6 0 19 1 1.056 -14.94 0 1 1.06 0.94; 35 | 10 1 9 5.8 0 0 1 1.051 -15.1 0 1 1.06 0.94; 36 | 11 1 3.5 1.8 0 0 1 1.057 -14.79 0 1 1.06 0.94; 37 | 12 1 6.1 1.6 0 0 1 1.055 -15.07 0 1 1.06 0.94; 38 | 13 1 13.5 5.8 0 0 1 1.05 -15.16 0 1 1.06 0.94; 39 | 14 1 14.9 5 0 0 1 1.036 -16.04 0 1 1.06 0.94; 40 | ]; 41 | 42 | %% generator data 43 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 44 | mpc.gen = [ 45 | 1 232.4 -16.9 10 0 1.06 100 1 332.4 0 0 0 0 0 0 0 0 0 0 0 0; 46 | 2 40 42.4 50 -40 1.045 100 1 140 0 0 0 0 0 0 0 0 0 0 0 0; 47 | 3 0 23.4 40 0 1.01 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0; 48 | 6 0 12.2 24 -6 1.07 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0; 49 | 8 0 17.4 24 -6 1.09 100 1 100 0 0 0 0 0 0 0 0 0 0 0 0; 50 | ]; 51 | 52 | %% branch data 53 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 54 | mpc.branch = [ 55 | 1 2 0.01938 0.05917 0.0528 0 0 0 0 0 1 -360 360; 56 | 1 5 0.05403 0.22304 0.0492 0 0 0 0 0 1 -360 360; 57 | 2 3 0.04699 0.19797 0.0438 0 0 0 0 0 1 -360 360; 58 | 2 4 0.05811 0.17632 0.034 0 0 0 0 0 1 -360 360; 59 | 2 5 0.05695 0.17388 0.0346 0 0 0 0 0 1 -360 360; 60 | 3 4 0.06701 0.17103 0.0128 0 0 0 0 0 1 -360 360; 61 | 4 5 0.01335 0.04211 0 0 0 0 0 0 1 -360 360; 62 | 4 7 0 0.20912 0 0 0 0 0.978 0 1 -360 360; 63 | 4 9 0 0.55618 0 0 0 0 0.969 0 1 -360 360; 64 | 5 6 0 0.25202 0 0 0 0 0.932 0 1 -360 360; 65 | 6 11 0.09498 0.1989 0 0 0 0 0 0 1 -360 360; 66 | 6 12 0.12291 0.25581 0 0 0 0 0 0 1 -360 360; 67 | 6 13 0.06615 0.13027 0 0 0 0 0 0 1 -360 360; 68 | 7 8 0 0.17615 0 0 0 0 0 0 1 -360 360; 69 | 7 9 0 0.11001 0 0 0 0 0 0 1 -360 360; 70 | 9 10 0.03181 0.0845 0 0 0 0 0 0 1 -360 360; 71 | 9 14 0.12711 0.27038 0 0 0 0 0 0 1 -360 360; 72 | 10 11 0.08205 0.19207 0 0 0 0 0 0 1 -360 360; 73 | 12 13 0.22092 0.19988 0 0 0 0 0 0 1 -360 360; 74 | 13 14 0.17093 0.34802 0 0 0 0 0 0 1 -360 360; 75 | ]; 76 | 77 | %%----- OPF Data -----%% 78 | %% generator cost data 79 | % 1 startup shutdown n x1 y1 ... xn yn 80 | % 2 startup shutdown n c(n-1) ... c0 81 | mpc.gencost = [ 82 | 2 0 0 5 0 0 0.0430292599 20 0; 83 | 2 0 0 5 0 0 0.25 20 0; 84 | 2 0 0 5 0 0 0.01 40 0; 85 | 2 0 0 5 0 0 0.01 40 0; 86 | 2 0 0 5 0 0 0.01 40 0; 87 | ]; 88 | 89 | %% bus names 90 | mpc.bus_name = { 91 | 'Bus 1 HV'; 92 | 'Bus 2 HV'; 93 | 'Bus 3 HV'; 94 | 'Bus 4 HV'; 95 | 'Bus 5 HV'; 96 | 'Bus 6 LV'; 97 | 'Bus 7 ZV'; 98 | 'Bus 8 TV'; 99 | 'Bus 9 LV'; 100 | 'Bus 10 LV'; 101 | 'Bus 11 LV'; 102 | 'Bus 12 LV'; 103 | 'Bus 13 LV'; 104 | 'Bus 14 LV'; 105 | }; 106 | 107 | % Warnings from cdf2matp conversion: 108 | % 109 | % ***** check the title format in the first line of the cdf file. 110 | % ***** Qmax = Qmin at generator at bus 1 (Qmax set to Qmin + 10) 111 | % ***** MVA limit of branch 1 - 2 not given, set to 0 112 | % ***** MVA limit of branch 1 - 5 not given, set to 0 113 | % ***** MVA limit of branch 2 - 3 not given, set to 0 114 | % ***** MVA limit of branch 2 - 4 not given, set to 0 115 | % ***** MVA limit of branch 2 - 5 not given, set to 0 116 | % ***** MVA limit of branch 3 - 4 not given, set to 0 117 | % ***** MVA limit of branch 4 - 5 not given, set to 0 118 | % ***** MVA limit of branch 4 - 7 not given, set to 0 119 | % ***** MVA limit of branch 4 - 9 not given, set to 0 120 | % ***** MVA limit of branch 5 - 6 not given, set to 0 121 | % ***** MVA limit of branch 6 - 11 not given, set to 0 122 | % ***** MVA limit of branch 6 - 12 not given, set to 0 123 | % ***** MVA limit of branch 6 - 13 not given, set to 0 124 | % ***** MVA limit of branch 7 - 8 not given, set to 0 125 | % ***** MVA limit of branch 7 - 9 not given, set to 0 126 | % ***** MVA limit of branch 9 - 10 not given, set to 0 127 | % ***** MVA limit of branch 9 - 14 not given, set to 0 128 | % ***** MVA limit of branch 10 - 11 not given, set to 0 129 | % ***** MVA limit of branch 12 - 13 not given, set to 0 130 | % ***** MVA limit of branch 13 - 14 not given, set to 0 131 | -------------------------------------------------------------------------------- /test/ots.jl: -------------------------------------------------------------------------------- 1 | 2 | # used by OTS models 3 | function check_br_status(sol) 4 | for (i,branch) in sol["branch"] 5 | @test isapprox(branch["br_status"], 0.0, rtol=1e-6) || isapprox(branch["br_status"], 1.0, rtol=1e-6) 6 | end 7 | end 8 | 9 | 10 | @testset "test ac ots" begin 11 | @testset "3-bus case" begin 12 | result = run_ots("../test/data/matpower/case3.m", ACPPowerModel, juniper_solver) 13 | 14 | check_br_status(result["solution"]) 15 | 16 | @test result["status"] == :LocalOptimal 17 | #@test isapprox(result["objective"], 5812; atol = 1e0) # true opt objective 18 | @test isapprox(result["objective"], 5906.8; atol = 1e0) 19 | end 20 | @testset "5-bus case" begin 21 | result = run_ots("../test/data/matpower/case5.m", ACPPowerModel, juniper_solver) 22 | 23 | check_br_status(result["solution"]) 24 | 25 | @test result["status"] == :LocalOptimal 26 | @test isapprox(result["objective"], 15174; atol = 1e0) 27 | end 28 | #Omitting this test, returns local infeasible 29 | #@testset "6-bus case" begin 30 | # result = run_ots("../test/data/matpower/case6.m", ACPPowerModel, juniper_solver) 31 | 32 | # check_br_status(result["solution"]) 33 | 34 | # @test result["status"] == :LocalOptimal 35 | # println(result["objective"]) 36 | # @test isapprox(result["objective"], 15174; atol = 1e0) 37 | #end 38 | end 39 | 40 | 41 | @testset "test dc ots" begin 42 | @testset "3-bus case" begin 43 | result = run_ots("../test/data/matpower/case3.m", DCPPowerModel, pajarito_solver) 44 | 45 | check_br_status(result["solution"]) 46 | 47 | @test result["status"] == :Optimal 48 | @test isapprox(result["objective"], 5782.0; atol = 1e0) 49 | end 50 | @testset "5-bus case" begin 51 | result = run_ots("../test/data/matpower/case5.m", DCPPowerModel, pajarito_solver) 52 | 53 | check_br_status(result["solution"]) 54 | 55 | @test result["status"] == :Optimal 56 | @test isapprox(result["objective"], 14991.2; atol = 1e0) 57 | end 58 | @testset "6-bus case" begin 59 | result = run_ots("../test/data/matpower/case6.m", DCPPowerModel, pajarito_solver) 60 | 61 | check_br_status(result["solution"]) 62 | 63 | @test result["status"] == :Optimal 64 | @test isapprox(result["objective"], 11396.3; atol = 1e0) 65 | end 66 | end 67 | 68 | 69 | @testset "test dc+ll ots" begin 70 | @testset "3-bus case" begin 71 | result = run_ots("../test/data/matpower/case3.m", DCPLLPowerModel, pajarito_solver) 72 | 73 | check_br_status(result["solution"]) 74 | 75 | @test result["status"] == :Optimal 76 | @test isapprox(result["objective"], 5885.2; atol = 1e0) 77 | end 78 | @testset "5-bus case" begin 79 | result = run_ots("../test/data/matpower/case5.m", DCPLLPowerModel, pajarito_solver) 80 | 81 | check_br_status(result["solution"]) 82 | 83 | @test result["status"] == :Optimal 84 | @test isapprox(result["objective"], 15275.2; atol = 1e0) 85 | end 86 | @testset "6-bus case" begin 87 | result = run_ots("../test/data/matpower/case6.m", DCPLLPowerModel, pajarito_solver) 88 | 89 | check_br_status(result["solution"]) 90 | 91 | @test result["status"] == :Optimal 92 | @test isapprox(result["objective"], 11515.6; atol = 1e0) 93 | end 94 | end 95 | 96 | 97 | @testset "test soc ots" begin 98 | @testset "3-bus case" begin 99 | result = run_ots("../test/data/matpower/case3.m", SOCWRPowerModel, pajarito_solver) 100 | 101 | check_br_status(result["solution"]) 102 | 103 | @test result["status"] == :Optimal 104 | @test isapprox(result["objective"], 5746.7; atol = 1e0) 105 | end 106 | @testset "5-bus case" begin 107 | result = run_ots("../test/data/matpower/case5.m", SOCWRPowerModel, pajarito_solver) 108 | 109 | check_br_status(result["solution"]) 110 | 111 | @test result["status"] == :Optimal 112 | @test isapprox(result["objective"], 15051.4; atol = 1e0) 113 | end 114 | @testset "6-bus case" begin 115 | result = run_ots("../test/data/matpower/case6.m", SOCWRPowerModel, pajarito_solver) 116 | 117 | check_br_status(result["solution"]) 118 | 119 | @test result["status"] == :Optimal 120 | @test isapprox(result["objective"], 11559.8; atol = 1e0) 121 | end 122 | end 123 | 124 | 125 | @testset "test qc ots" begin 126 | @testset "3-bus case" begin 127 | result = run_ots("../test/data/matpower/case3.m", QCWRPowerModel, pajarito_solver) 128 | 129 | check_br_status(result["solution"]) 130 | 131 | @test result["status"] == :Optimal 132 | @test isapprox(result["objective"], 5746.7; atol = 1e0) 133 | end 134 | @testset "5-bus case" begin 135 | result = run_ots("../test/data/matpower/case5.m", QCWRPowerModel, pajarito_solver) 136 | 137 | check_br_status(result["solution"]) 138 | 139 | @test result["status"] == :Optimal 140 | @test isapprox(result["objective"], 15051.4; atol = 1e0) 141 | end 142 | @testset "5-bus asymmetric case" begin 143 | result = run_ots("../test/data/matpower/case5_asym.m", QCWRPowerModel, pajarito_solver) 144 | 145 | check_br_status(result["solution"]) 146 | 147 | @test result["status"] == :Optimal 148 | @test isapprox(result["objective"], 14999.7; atol = 1e0) 149 | end 150 | @testset "6-bus case" begin 151 | result = run_ots("../test/data/matpower/case6.m", QCWRPowerModel, pajarito_solver) 152 | 153 | check_br_status(result["solution"]) 154 | 155 | @test result["status"] == :Optimal 156 | @test isapprox(result["objective"], 11567.1; atol = 1e0) 157 | end 158 | end 159 | -------------------------------------------------------------------------------- /docs/src/developer.md: -------------------------------------------------------------------------------- 1 | # Developer Documentation 2 | 3 | ## Variable and parameter naming scheme 4 | 5 | ### Suffixes 6 | 7 | - `_fr`: from-side ('i'-node) 8 | - `_to`: to-side ('j'-node) 9 | 10 | ### Power 11 | 12 | Defining power $s = p + j \cdot q$ and $sm = |s|$ 13 | - `s`: complex power (VA) 14 | - `sm`: apparent power (VA) 15 | - `p`: active power (W) 16 | - `q`: reactive power (var) 17 | 18 | ### Voltage 19 | 20 | Defining voltage $v = vm \angle va = vr + j \cdot vi$: 21 | - `vm`: magnitude of (complex) voltage (V) 22 | - `va`: angle of complex voltage (rad) 23 | - `vr`: real part of (complex) voltage (V) 24 | - `vi`: imaginary part of complex voltage (V) 25 | 26 | ### Current 27 | 28 | Defining current $c = cm \angle ca = cr + j \cdot ci$: 29 | - `cm`: magnitude of (complex) current (A) 30 | - `ca`: angle of complex current (rad) 31 | - `cr`: real part of (complex) current (A) 32 | - `ci`: imaginary part of complex current (A) 33 | 34 | ### Voltage products 35 | 36 | Defining voltage product $w = v_i \cdot v_j$ then 37 | $w = wm \angle wa = wr + j\cdot wi$: 38 | - `wm` (short for vvm): magnitude of (complex) voltage products (V$^2$) 39 | - `wa` (short for vva): angle of complex voltage products (rad) 40 | - `wr` (short for vvr): real part of (complex) voltage products (V$^2$) 41 | - `wi` (short for vvi): imaginary part of complex voltage products (V$^2$) 42 | 43 | ### Current products 44 | 45 | Defining current product $cc = c_i \cdot c_j$ then 46 | $cc = ccm \angle cca = ccr + j\cdot cci$: 47 | - `ccm`: magnitude of (complex) current products (A$^2$) 48 | - `cca`: angle of complex current products (rad) 49 | - `ccr`: real part of (complex) current products (A$^2$) 50 | - `cci`: imaginary part of complex current products (A$^2$) 51 | 52 | ### Transformer ratio 53 | 54 | Defining complex transformer ratio 55 | $t = tm \angle ta = tr + j\cdot ti$: 56 | - `tm`: magnitude of (complex) transformer ratio (-) 57 | - `ta`: angle of complex transformer ratio (rad) 58 | - `tr`: real part of (complex) transformer ratio (-) 59 | - `ti`: imaginary part of complex transformer ratio (-) 60 | 61 | ### Impedance 62 | 63 | Defining impedance 64 | $z = r + j\cdot x$: 65 | - `r`: resistance ($\Omega$) 66 | - `x`: reactance ($\Omega$) 67 | 68 | ### Admittance 69 | 70 | Defining admittance 71 | $y = g + j\cdot b$: 72 | - `g`: conductance ($S$) 73 | - `b`: susceptance ($S$) 74 | 75 | 76 | ## DistFlow derivation 77 | 78 | ### For an asymmetric pi section 79 | Following notation of [^1], but recognizing it derives the SOC BFM without shunts. In a pi-section, part of the total current $ I_{lij}$ at the from side flows through the series impedance, $I ^{s}_{lij}$, part of it flows through the from side shunt admittance $ I^{sh}_{lij}$. Vice versa for the to-side. Indicated by superscripts 's' (series) and 'sh' (shunt). 80 | - Ohm's law: $U^{mag}_{j} \angle \theta_{j} = U^{mag}_{i}\angle \theta_{i} - z^{s}_{lij} \cdot I^{s}_{lij}$ $\forall lij$ 81 | - KCL at shunts: $ I_{lij} = I^{s}_{lij} + I^{sh}_{lij}$, $ I_{lji} = I^{s}_{lji} + I^{sh}_{lji} $ 82 | - Observing: $I^{s}_{lij} = - I^{s}_{lji}$, $ \vert I^{s}_{lij} \vert = \vert I^{s}_{lji} \vert $ 83 | - Ohm's law times its own complex conjugate: $(U^{mag}_{j})^2 = (U^{mag}_{i}\angle \theta_{i} - z^{s}_{lij} \cdot I^{s}_{lij})\cdot (U^{mag}_{i}\angle \theta_{i} - z^{s}_{lij} \cdot I^{s}_{lij})^*$ 84 | - Defining $S^{s}_{lij} = P^{s}_{lij} + j\cdot Q^{s}_{lij} = (U^{mag}_{i}\angle \theta_{i}) \cdot (I^{s}_{lij})^*$ 85 | - Working it out $(U^{mag}_{j})^2 = (U^{mag}_{i})^2 - 2 \cdot(r^{s}_{lij} \cdot P^{s}_{lij} + x^{s}_{lij} \cdot Q^{s}_{lij}) $ + $((r^{s}_{lij})^2 + (x^{s}_{lij})^2)\vert I^{s}_{lij} \vert^2$ 86 | 87 | Power flow balance w.r.t. branch *total* losses 88 | - Active power flow: $P_{lij}$ + $ P_{lji} $ = $ g^{sh}_{lij} \cdot (U^{mag}_{i})^2 + r^{s}_{l} \cdot \vert I^{s}_{lij} \vert^2 + g^{sh}_{lji} \cdot (U^{mag}_{j})^2 $ 89 | - Reactive power flow: $Q_{lij}$ + $ Q_{lji} $ = $ -b^{sh}_{lij} \cdot (U^{mag}_{i})^2 + x^{s}_{l} \cdot \vert I^{s}_{lij} \vert^2 - b^{sh}_{lji} \cdot (U^{mag}_{j})^2 $ 90 | - Current definition: $ \vert S^{s}_{lij} \vert^2 $ $=(U^{mag}_{i})^2 \cdot \vert I^{s}_{lij} \vert^2 $ 91 | 92 | Substitution: 93 | - Voltage from: $(U^{mag}_{i})^2 \rightarrow w_{i}$ 94 | - Voltage to: $(U^{mag}_{j})^2 \rightarrow w_{j}$ 95 | - Series current : $\vert I^{s}_{lij} \vert^2 \rightarrow l^{s}_{l}$ 96 | Note that $l^{s}_{l}$ represents squared magnitude of the *series* current, i.e. the current flow through the series impedance in the pi-model. 97 | 98 | Power flow balance w.r.t. branch *total* losses 99 | - Active power flow: $P_{lij}$ + $ P_{lji} $ = $ g^{sh}_{lij} \cdot w_{i} + r^{s}_{l} \cdot l^{s}_{l} + g^{sh}_{lji} \cdot w_{j} $ 100 | - Reactive power flow: $Q_{lij}$ + $ Q_{lji} $ = $ -b^{sh}_{lij} \cdot w_{i} + x^{s}_{l} \cdot l^{s}_{l} - b^{sh}_{lji} \cdot w_{j} $ 101 | 102 | Power flow balance w.r.t. branch *series* losses: 103 | - Series active power flow : $P^{s}_{lij} + P^{s}_{lji}$ $ = r^{s}_{l} \cdot l^{s}_{l} $ 104 | - Series reactive power flow: $Q^{s}_{lij} + Q^{s}_{lji}$ $ = x^{s}_{l} \cdot l^{s}_{l} $ 105 | 106 | Valid equality to link $w_{i}, l_{lij}, P^{s}_{lij}, Q^{s}_{lij}$: 107 | - Nonconvex current definition: $(P^{s}_{lij})^2$ + $(Q^{s}_{lij})^2$ $=w_{i} \cdot l_{lij} $ 108 | - SOC current definition: $(P^{s}_{lij})^2$ + $(Q^{s}_{lij})^2$ $\leq$ $ w_{i} \cdot l_{lij} $ 109 | 110 | 111 | ### Adding an ideal transformer 112 | Adding an ideal transformer at the from side implicitly creates an internal branch voltage, between the transformer and the pi-section. 113 | - new voltage: $w^{'}_{l}$ 114 | - ideal voltage magnitude transformer: $w^{'}_{l} = \frac{w_{i}}{(t^{mag})^2}$ 115 | 116 | W.r.t to the pi-section only formulation, we effectively perform the following substitution in all the equations above: 117 | - $ w_{i} \rightarrow \frac{w_{i}}{(t^{mag})^2}$ 118 | 119 | The branch's power balance isn't otherwise impacted by adding the ideal transformer, as such transformer is lossless. 120 | 121 | ### Adding total current limits 122 | - Total current from: $ \vert I_{lij} \vert \leq I^{rated}_{l}$ 123 | - Total current to: $ \vert I_{lji} \vert \leq I^{rated}_{l}$ 124 | 125 | In squared voltage magnitude variables: 126 | - Total current from: $ (P_{lij})^2$ + $(Q_{lij})^2 \leq (I^{rated}_{l})^2 \cdot w_{i}$ 127 | - Total current to: $ (P_{lji})^2$ + $(Q_{lji})^2 \leq (I^{rated}_{l})^2 \cdot w_{j}$ 128 | 129 | 130 | 131 | 132 | [^1] Gan, L., Li, N., Topcu, U., & Low, S. (2012). Branch flow model for radial networks: convex relaxation. 51st IEEE Conference on Decision and Control, 1–8. Retrieved from http://smart.caltech.edu/papers/ExactRelaxation.pdf 133 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | PowerModels.jl Change Log 2 | ================= 3 | 4 | ### Staged 5 | - Added support for three-winding transformers in PTI files 6 | - Added support for unit conversion in transformer entries of PTI files 7 | - Added support for transformer magnetizing admittance from PTI files 8 | - Removed multi-network filter option from objective functions (breaking) 9 | - Removed option to run multi-network data in single-network models (breaking) 10 | - Changed test MIP solver from GLPK to CBC 11 | - Improved robustness of matpower data parsing and transformation 12 | 13 | ### v0.6.1 14 | - Moved to Juniper for non-convex MINLP tests 15 | - Fixed minor bug in non-convex MINLP formulations 16 | 17 | ### v0.6.0 18 | - Dropped support for Julia v0.5 (breaking) 19 | - Added basic support for PSSE v33 raw data (incl. buses, loads, shunts, generators, branches and two-winding transformers) 20 | - Added support for table-like data summary, #146 21 | - Added support for network topology processing 22 | - Added basic support for Branch Flow formulation variants 23 | - Added support for parsing PTI files into a Dict 24 | - Refactored implementation of WRM formulation 25 | - Updated branch mathematical model and Matpower parser to support asymmetrical line charging 26 | - Added explicit load and shunt components to the PowerModels network data structure 27 | - Refactored Matlab and Matpower parsing functions 28 | - Leveraging InfrastructureModels package for Matlab data parsing, #233, #247 29 | - Migrated logging tools from Logging to Memento 30 | - Updated struct and type parameter syntax to Julia v0.6 31 | - Fixed a mathematical bug when swapping the orientation of a transformer 32 | - Minor issues closed #51, #131, #220 33 | 34 | ### v0.5.1 35 | - Added support for convex piecewise linear cost functions 36 | - Added lambda-based convex hull relaxation scheme for trilinear products 37 | - Added QCWRTri Power Flow formulation 38 | - Added kcl and thermal limit dual values in linear power flow formulations 39 | - Fixed bug in QC-OTS formulation 40 | 41 | ### v0.5.0 42 | - Standardized around branch name for pi-model lines (breaking) 43 | - Added checking for inconsistent orientation on parallel branches 44 | - Added support for multiple networks in the JuMP model (breaking) 45 | - Removed epsilon parameter from constraint_voltage_magnitude_setpoint (breaking) 46 | - Moved misc models to PowerModelsAnnex (breaking) 47 | - Removed unnecessary NL constraints from ACR and ACT formulations 48 | - Removed redundant quadratic constraint from DCPLL formulation 49 | - Added warning messages for inconsistent voltage set points 50 | - Fixed branch flow units transformation bug 51 | 52 | ### v0.4.0 53 | - Added JuMP v0.18 compatibility 54 | - Added pm.var and made all JuMP variables anonymous (breaking) 55 | - Added support for SDP, ACR, and ACT Power Flow formulations 56 | - Added cost model zero filtering to matpower parser 57 | - Eliminated usage of pm.model.ext, #149 58 | - Made solution default units per-unit (breaking) 59 | - Removed deprecated bus-less constraint_theta_ref function (breaking) 60 | - Renamed polar voltage variables v,t to vm,va (breaking) 61 | - Renamed functions with phase_angle to voltage_angle (breaking) 62 | - Renamed v_from and w_from variables to v_fr w_fr (breaking) 63 | - Removed variable and constraint function return values (breaking) 64 | - Made index_name an optional parameter in add_setpoint (breaking) 65 | - Moved check_cost_models into the objective building function 66 | - Fixed out of range bug in calc_theta_delta_bounds 67 | - Fixed bug in phase angle differences in AbstractACPForms 68 | - Fixed bugs in AbstractDCPLLForm and added OPF test 69 | 70 | ### v0.3.4 71 | - Added support for Matpower data with dclines (thanks to @frederikgeth, @hakanergun) 72 | - Added support for QC-OTS 73 | - Added support for multiple reference buses 74 | - Added rectangular voltage formulation of AC-OPF 75 | - Added w-theta formulation of AC-OPF 76 | - Added data units checks to update_data 77 | - Made branch flow parameter names consistent with Matpower 78 | - Fixed bug in constants for w-space phase angle difference constraints 79 | - Fixed bug when no reference bus was specified 80 | - Fixed dcline parsing bug 81 | 82 | ### v0.3.3 83 | - Added JuMP v0.17 compatibility 84 | - Reorganized documentation into Manual, Library, Developer, and Experimental Results 85 | 86 | ### v0.3.2 87 | - Updated type declarations to Julia v0.6 syntax 88 | - Moved documentation to Documenter.jl (thanks to @yeesian) 89 | - Added basic OPF results to Documentation 90 | - Extended pm.ref include all fields from pm.data 91 | 92 | ### v0.3.1 93 | - Added JuMP v0.16 and Julia v0.6 compatibility 94 | - Added missing function for AC-TNEP models 95 | - Added checks that tap ratios are non-zero 96 | - Made all power model forms abstract types, to support future extensions 97 | - Made matpower parser more robust to cases with line flow values 98 | - Fixed a bug that prevented parsing of bus_names when buses have non-contiguous ids 99 | - Fixed bounds correction units when angmin and angmax are 0.0 100 | 101 | ### v0.3.0 102 | - Updated to JuMP v0.15 syntax 103 | - Replaced PowerModels set data types with "ref" dictionary 104 | - Refactored Matpower data processing to simplify editing network data after parsing 105 | - Unified network data and solution formats and made them valid JSON documents 106 | - Replaced JSON test files with Matpower test files 107 | - Added documentation on internal JSON data format to DATA.md 108 | - Updated TNEP models to work with Matpower parsing extensions 109 | - Strengthened convex formulations with Lifted Nonlinear Cuts (LNCs) 110 | - Added ability to easily inspect the JuMP model produced by PowerModels 111 | - Added constraint templates to provide an abstraction layer between the network data and network constraint definitions 112 | - Moved system wide phase angle difference bounds to the "ref" dictionary 113 | - Refactored model definitions to be based on complex numbers 114 | 115 | ### v0.2.3 116 | - Multiple improvements to Matlab file parsing 117 | - Added support Matlab cell arrays 118 | - Added support for Matpower bus_names 119 | - Added ability for reading non-standard Matpower data elements 120 | - Added JuMP version v0.14 upper bound 121 | 122 | ### v0.2.2 123 | - Added Transmission Network Expansion Planning (tnep) problem. 124 | 125 | ### v0.2.1 126 | - Added support for julia v0.5.0 and OS X 127 | - Added line flows option for solution output 128 | - Added initial documentation and helper functions 129 | - Replaced Gurobi with Pajarito for MISOCP tests 130 | 131 | ### v0.2.0 132 | - Complete re-write to type-based implementation using dynamic dispatch 133 | - Incorporated abstract problem specifications 134 | - Added type-based formulation abstractions 135 | 136 | ### v0.1.0 137 | - Initial function-based implementation 138 | -------------------------------------------------------------------------------- /src/form/acr.jl: -------------------------------------------------------------------------------- 1 | ### rectangular form of the non-convex AC equations 2 | 3 | export 4 | ACRPowerModel, StandardACRForm 5 | 6 | "" 7 | abstract type AbstractACRForm <: AbstractPowerFormulation end 8 | 9 | "" 10 | abstract type StandardACRForm <: AbstractACRForm end 11 | 12 | "" 13 | const ACRPowerModel = GenericPowerModel{StandardACRForm} 14 | 15 | "default rectangular AC constructor" 16 | ACRPowerModel(data::Dict{String,Any}; kwargs...) = 17 | GenericPowerModel(data, StandardACRForm; kwargs...) 18 | 19 | 20 | "" 21 | function variable_voltage(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractACRForm 22 | variable_voltage_real(pm, n; kwargs...) 23 | variable_voltage_imaginary(pm, n; kwargs...) 24 | end 25 | 26 | 27 | "add constraints for voltage magnitude" 28 | function constraint_voltage(pm::GenericPowerModel{T}, n::Int) where T <: AbstractACRForm 29 | vr = pm.var[:nw][n][:vr] 30 | vi = pm.var[:nw][n][:vi] 31 | 32 | for (i,bus) in pm.ref[:nw][n][:bus] 33 | @constraint(pm.model, bus["vmin"]^2 <= (vr[i]^2 + vi[i]^2)) 34 | @constraint(pm.model, bus["vmax"]^2 >= (vr[i]^2 + vi[i]^2)) 35 | end 36 | 37 | # does not seem to improve convergence 38 | #wr_min, wr_max, wi_min, wi_max = calc_voltage_product_bounds(pm.ref[:buspairs]) 39 | #for bp in keys(pm.ref[:buspairs]) 40 | # i,j = bp 41 | # @constraint(pm.model, wr_min[bp] <= vr[i]*vr[j] + vi[i]*vi[j]) 42 | # @constraint(pm.model, wr_max[bp] >= vr[i]*vr[j] + vi[i]*vi[j]) 43 | # 44 | # @constraint(pm.model, wi_min[bp] <= vi[i]*vr[j] - vr[i]*vi[j]) 45 | # @constraint(pm.model, wi_max[bp] >= vi[i]*vr[j] - vr[i]*vi[j]) 46 | #end 47 | end 48 | 49 | 50 | "`v[i] == vm`" 51 | function constraint_voltage_magnitude_setpoint(pm::GenericPowerModel{T}, n::Int, i, vm) where T <: AbstractACRForm 52 | vr = pm.var[:nw][n][:vr][i] 53 | vi = pm.var[:nw][n][:vi][i] 54 | 55 | @constraint(pm.model, (vr^2 + vi^2) == vm^2) 56 | end 57 | 58 | 59 | "reference bus angle constraint" 60 | function constraint_theta_ref(pm::GenericPowerModel{T}, n::Int, i::Int) where T <: AbstractACRForm 61 | @constraint(pm.model, pm.var[:nw][n][:vi][i] == 0) 62 | end 63 | 64 | 65 | function constraint_kcl_shunt(pm::GenericPowerModel{T}, n::Int, i, bus_arcs, bus_arcs_dc, bus_gens, bus_loads, bus_shunts, pd, qd, gs, bs) where T <: AbstractACRForm 66 | vr = pm.var[:nw][n][:vr][i] 67 | vi = pm.var[:nw][n][:vi][i] 68 | p = pm.var[:nw][n][:p] 69 | q = pm.var[:nw][n][:q] 70 | pg = pm.var[:nw][n][:pg] 71 | qg = pm.var[:nw][n][:qg] 72 | p_dc = pm.var[:nw][n][:p_dc] 73 | q_dc = pm.var[:nw][n][:q_dc] 74 | load = pm.ref[:nw][n][:load] 75 | shunt = pm.ref[:nw][n][:shunt] 76 | 77 | @constraint(pm.model, sum(p[a] for a in bus_arcs) + sum(p_dc[a_dc] for a_dc in bus_arcs_dc) == sum(pg[g] for g in bus_gens) - sum(pd[d] for d in bus_loads) - sum(gs[s] for s in bus_shunts)*(vr^2 + vi^2)) 78 | @constraint(pm.model, sum(q[a] for a in bus_arcs) + sum(q_dc[a_dc] for a_dc in bus_arcs_dc) == sum(qg[g] for g in bus_gens) - sum(qd[d] for d in bus_loads) + sum(bs[s] for s in bus_shunts)*(vr^2 + vi^2)) 79 | end 80 | 81 | 82 | """ 83 | Creates Ohms constraints (yt post fix indicates that Y and T values are in rectangular form) 84 | """ 85 | function constraint_ohms_yt_from(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, g, b, g_fr, b_fr, tr, ti, tm) where T <: AbstractACRForm 86 | p_fr = pm.var[:nw][n][:p][f_idx] 87 | q_fr = pm.var[:nw][n][:q][f_idx] 88 | vr_fr = pm.var[:nw][n][:vr][f_bus] 89 | vr_to = pm.var[:nw][n][:vr][t_bus] 90 | vi_fr = pm.var[:nw][n][:vi][f_bus] 91 | vi_to = pm.var[:nw][n][:vi][t_bus] 92 | 93 | @constraint(pm.model, p_fr == (g+g_fr)/tm^2*(vr_fr^2 + vi_fr^2) + (-g*tr+b*ti)/tm^2*(vr_fr*vr_to + vi_fr*vi_to) + (-b*tr-g*ti)/tm^2*(vi_fr*vr_to - vr_fr*vi_to) ) 94 | @constraint(pm.model, q_fr == -(b+b_fr)/tm^2*(vr_fr^2 + vi_fr^2) - (-b*tr-g*ti)/tm^2*(vr_fr*vr_to + vi_fr*vi_to) + (-g*tr+b*ti)/tm^2*(vi_fr*vr_to - vr_fr*vi_to) ) 95 | end 96 | 97 | """ 98 | Creates Ohms constraints (yt post fix indicates that Y and T values are in rectangular form) 99 | """ 100 | function constraint_ohms_yt_to(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, g, b, g_to, b_to, tr, ti, tm) where T <: AbstractACRForm 101 | p_to = pm.var[:nw][n][:p][t_idx] 102 | q_to = pm.var[:nw][n][:q][t_idx] 103 | vr_fr = pm.var[:nw][n][:vr][f_bus] 104 | vr_to = pm.var[:nw][n][:vr][t_bus] 105 | vi_fr = pm.var[:nw][n][:vi][f_bus] 106 | vi_to = pm.var[:nw][n][:vi][t_bus] 107 | 108 | @constraint(pm.model, p_to == (g+g_to)*(vr_to^2 + vi_to^2) + (-g*tr-b*ti)/tm^2*(vr_fr*vr_to + vi_fr*vi_to) + (-b*tr+g*ti)/tm^2*(-(vi_fr*vr_to - vr_fr*vi_to)) ) 109 | @constraint(pm.model, q_to == -(b+b_to)*(vr_to^2 + vi_to^2) - (-b*tr+g*ti)/tm^2*(vr_fr*vr_to + vi_fr*vi_to) + (-g*tr-b*ti)/tm^2*(-(vi_fr*vr_to - vr_fr*vi_to)) ) 110 | end 111 | 112 | 113 | """ 114 | branch phase angle difference bounds 115 | """ 116 | function constraint_voltage_angle_difference(pm::GenericPowerModel{T}, n::Int, f_idx, angmin, angmax) where T <: AbstractACRForm 117 | i, f_bus, t_bus = f_idx 118 | 119 | vr_fr = pm.var[:nw][n][:vr][f_bus] 120 | vr_to = pm.var[:nw][n][:vr][t_bus] 121 | vi_fr = pm.var[:nw][n][:vi][f_bus] 122 | vi_to = pm.var[:nw][n][:vi][t_bus] 123 | 124 | @constraint(pm.model, (vi_fr*vr_to - vr_fr*vi_to) <= tan(angmax)*(vr_fr*vr_to + vi_fr*vi_to)) 125 | @constraint(pm.model, (vi_fr*vr_to - vr_fr*vi_to) >= tan(angmin)*(vr_fr*vr_to + vi_fr*vi_to)) 126 | end 127 | 128 | 129 | "extracts voltage set points from rectangular voltage form and converts into polar voltage form" 130 | function add_bus_voltage_setpoint(sol, pm::GenericPowerModel{T}) where T <: AbstractACRForm 131 | sol_dict = get(sol, "bus", Dict{String,Any}()) 132 | 133 | if pm.data["multinetwork"] 134 | bus_dict = pm.data["nw"]["$(pm.cnw)"]["bus"] 135 | else 136 | bus_dict = pm.data["bus"] 137 | end 138 | 139 | if length(bus_dict) > 0 140 | sol["bus"] = sol_dict 141 | end 142 | 143 | for (i,item) in bus_dict 144 | idx = Int(item["bus_i"]) 145 | sol_item = sol_dict[i] = get(sol_dict, i, Dict{String,Any}()) 146 | sol_item["vm"] = NaN 147 | sol_item["va"] = NaN 148 | try 149 | vr = getvalue(var(pm, :vr)[idx]) 150 | vi = getvalue(var(pm, :vi)[idx]) 151 | 152 | vm = sqrt(vr^2 + vi^2) 153 | sol_item["vm"] = vm 154 | 155 | if vr == 0.0 156 | if vi >= 0 157 | va = pi/2 158 | else 159 | va = 3*pi/2 160 | end 161 | else 162 | va = atan(vi/vr) 163 | end 164 | sol_item["va"] = va 165 | catch 166 | end 167 | end 168 | end 169 | -------------------------------------------------------------------------------- /test/output.jl: -------------------------------------------------------------------------------- 1 | 2 | @testset "test output api" begin 3 | @testset "24-bus rts case" begin 4 | result = run_opf("../test/data/matpower/case24.m", ACPPowerModel, ipopt_solver) 5 | 6 | @test haskey(result, "solver") == true 7 | @test haskey(result, "status") == true 8 | @test haskey(result, "objective") == true 9 | @test haskey(result, "objective_lb") == true 10 | @test haskey(result, "solve_time") == true 11 | @test haskey(result, "machine") == true 12 | @test haskey(result, "data") == true 13 | @test haskey(result, "solution") == true 14 | @test haskey(result["solution"], "branch") == false 15 | 16 | @test !isnan(result["solve_time"]) 17 | 18 | @test length(result["solution"]["bus"]) == 24 19 | @test length(result["solution"]["gen"]) == 33 20 | end 21 | end 22 | 23 | @testset "test branch flow output" begin 24 | @testset "24-bus rts case ac opf" begin 25 | result = run_opf("../test/data/matpower/case24.m", ACPPowerModel, ipopt_solver; setting = Dict("output" => Dict("branch_flows" => true))) 26 | 27 | @test haskey(result, "solver") == true 28 | @test haskey(result, "status") == true 29 | @test haskey(result, "objective") == true 30 | @test haskey(result, "objective_lb") == true 31 | @test haskey(result, "solve_time") == true 32 | @test haskey(result, "machine") == true 33 | @test haskey(result, "data") == true 34 | @test haskey(result, "solution") == true 35 | @test haskey(result["solution"], "branch") == true 36 | 37 | @test length(result["solution"]["bus"]) == 24 38 | @test length(result["solution"]["gen"]) == 33 39 | @test length(result["solution"]["branch"]) == 38 40 | 41 | branches = result["solution"]["branch"] 42 | 43 | @test isapprox(branches["2"]["pf"], 0.2001; atol = 1e-3) 44 | @test isapprox(branches["2"]["pt"], -0.1980; atol = 1e-3) 45 | @test isapprox(branches["2"]["qf"], 0.0055; atol = 1e-3) 46 | @test isapprox(branches["2"]["qt"], -0.0571; atol = 1e-3) 47 | end 48 | 49 | # A DCPPowerModel test is important because it does have variables for the reverse side of the branchs 50 | @testset "3-bus case dc opf" begin 51 | result = run_opf("../test/data/matpower/case3.m", DCPPowerModel, ipopt_solver; setting = Dict("output" => Dict("branch_flows" => true))) 52 | 53 | @test haskey(result, "solution") == true 54 | @test haskey(result["solution"], "branch") == true 55 | 56 | @test length(result["solution"]["bus"]) == 3 57 | @test length(result["solution"]["gen"]) == 3 58 | @test length(result["solution"]["branch"]) == 3 59 | @test length(result["solution"]["dcline"]) == 1 60 | 61 | branches = result["solution"]["branch"] 62 | 63 | @test isapprox(branches["3"]["pf"], -0.103497; atol = 1e-3) 64 | @test isapprox(branches["3"]["pt"], 0.103497; atol = 1e-3) 65 | @test isnan(branches["3"]["qf"]) 66 | @test isnan(branches["3"]["qt"]) 67 | end 68 | end 69 | 70 | 71 | @testset "test dual value output" begin 72 | settings = Dict("output" => Dict("duals" => true)) 73 | result = run_dc_opf("../test/data/matpower/case14.m", ipopt_solver, setting = settings) 74 | 75 | PowerModels.make_mixed_units(result["solution"]) 76 | @testset "14 bus - kcl duals" begin 77 | for (i, bus) in result["solution"]["bus"] 78 | @test haskey(bus, "lam_kcl_r") 79 | @test haskey(bus, "lam_kcl_i") 80 | @test isapprox(bus["lam_kcl_r"], -39.02; atol = 1e-2) # Expected result for case14 81 | @test isnan(bus["lam_kcl_i"]) 82 | end 83 | end 84 | 85 | @testset "14 bus - thermal limit duals" begin 86 | for (i, branch) in result["solution"]["branch"] 87 | @test haskey(branch, "mu_sm_fr") 88 | @test haskey(branch, "mu_sm_to") 89 | @test isapprox(branch["mu_sm_fr"], 0.0; atol = 1e-2) 90 | @test isnan(branch["mu_sm_to"]) 91 | end 92 | end 93 | 94 | 95 | result = run_dc_opf("../test/data/matpower/case5.m", ipopt_solver, setting = settings) 96 | 97 | PowerModels.make_mixed_units(result["solution"]) 98 | @testset "5 bus - kcl duals" begin 99 | for (i, bus) in result["solution"]["bus"] 100 | @test bus["lam_kcl_r"] <= -9.00 101 | @test bus["lam_kcl_r"] >= -45.00 102 | end 103 | end 104 | 105 | @testset "5 bus - thermal limit duals" begin 106 | for (i, branch) in result["solution"]["branch"] 107 | if i != "7" 108 | @test isapprox(branch["mu_sm_fr"], 0.0; atol = 1e-2) 109 | else 110 | @test isapprox(branch["mu_sm_fr"], 54.70; atol = 1e-2) 111 | end 112 | @test isnan(branch["mu_sm_to"]) 113 | end 114 | end 115 | end 116 | 117 | 118 | # recomended by @lroald 119 | @testset "test solution feedback" begin 120 | 121 | function solution_feedback(case, ac_opf_obj) 122 | data = PowerModels.parse_file(case) 123 | opf_result = run_ac_opf(data, ipopt_solver) 124 | @test opf_result["status"] == :LocalOptimal 125 | @test isapprox(opf_result["objective"], ac_opf_obj; atol = 1e0) 126 | 127 | PowerModels.update_data(data, opf_result["solution"]) 128 | 129 | pf_result = run_ac_pf(data, ipopt_solver) 130 | @test pf_result["status"] == :LocalOptimal 131 | @test isapprox(pf_result["objective"], 0.0; atol = 1e-3) 132 | 133 | for (i,bus) in data["bus"] 134 | @test isapprox(opf_result["solution"]["bus"][i]["va"], pf_result["solution"]["bus"][i]["va"]; atol = 1e-3) 135 | @test isapprox(opf_result["solution"]["bus"][i]["vm"], pf_result["solution"]["bus"][i]["vm"]; atol = 1e-3) 136 | end 137 | 138 | for (i,gen) in data["gen"] 139 | @test isapprox(opf_result["solution"]["gen"][i]["pg"], pf_result["solution"]["gen"][i]["pg"]; atol = 1e-3) 140 | # cannot check this value solution does not appeat to be unique; verify this! 141 | #@test isapprox(opf_result["solution"]["gen"][i]["qg"], pf_result["solution"]["gen"][i]["qg"]; atol = 1e-3) 142 | end 143 | 144 | for (i,dcline) in data["dcline"] 145 | @test isapprox(opf_result["solution"]["dcline"][i]["pf"], pf_result["solution"]["dcline"][i]["pf"]; atol = 1e-3) 146 | @test isapprox(opf_result["solution"]["dcline"][i]["pt"], pf_result["solution"]["dcline"][i]["pt"]; atol = 1e-3) 147 | end 148 | end 149 | 150 | @testset "3-bus case" begin 151 | solution_feedback("../test/data/matpower/case3.m", 5907) 152 | end 153 | 154 | @testset "5-bus asymmetric case" begin 155 | solution_feedback("../test/data/matpower/case5_asym.m", 17551) 156 | end 157 | 158 | @testset "5-bus with dcline costs" begin 159 | solution_feedback("../test/data/matpower/case5_dc.m", 17760.2) 160 | end 161 | 162 | end 163 | -------------------------------------------------------------------------------- /test/pti.jl: -------------------------------------------------------------------------------- 1 | # Test cases for PTI RAW file parser 2 | 3 | @testset "test .raw file parser" begin 4 | @testset "Check PTI exception handling" begin 5 | setlevel!(getlogger(PowerModels), "warn") 6 | 7 | @test_nowarn PowerModels.parse_pti("../test/data/pti/parser_test_a.raw") 8 | @test_warn(getlogger(PowerModels), 9 | "The PSS(R)E parser is partially implimented, and currently only supports buses, loads, shunts, generators, branches, and transformers", 10 | PowerModels.parse_file("../test/data/pti/frankenstein_00.raw")) 11 | @test_throws(getlogger(PowerModels), 12 | ErrorException, 13 | PowerModels.parse_pti("../test/data/pti/parser_test_b.raw")) 14 | @test_warn(getlogger(PowerModels), 15 | "Version 32 of PTI format is unsupported, parser may not function correctly.", 16 | PowerModels.parse_pti("../test/data/pti/parser_test_c.raw")) 17 | @test_throws(getlogger(PowerModels), ErrorException, PowerModels.parse_pti("../test/data/pti/parser_test_d.raw")) 18 | @test_warn(getlogger(PowerModels), "GNE DEVICE parsing is not supported.", PowerModels.parse_pti("../test/data/pti/parser_test_h.raw")) 19 | 20 | setlevel!(getlogger(PowerModels), "error") 21 | end 22 | 23 | @testset "4-bus frankenstein file" begin 24 | data_dict = PowerModels.parse_pti("../test/data/pti/frankenstein_00.raw") 25 | @test isa(data_dict, Dict) 26 | 27 | @test length(data_dict["CASE IDENTIFICATION"]) == 1 28 | @test length(data_dict["CASE IDENTIFICATION"][1]) == 9 29 | 30 | @test length(data_dict["BUS"]) == 4 31 | for item in data_dict["BUS"] 32 | @test length(item) == 13 33 | end 34 | 35 | @test length(data_dict["LOAD"]) == 2 36 | for item in data_dict["LOAD"] 37 | @test length(item) == 13 38 | end 39 | 40 | @test length(data_dict["FIXED SHUNT"]) == 1 41 | @test length(data_dict["FIXED SHUNT"][1]) == 5 42 | 43 | @test length(data_dict["GENERATOR"]) == 3 44 | for item in data_dict["GENERATOR"] 45 | @test length(item) == 28 46 | end 47 | 48 | @test length(data_dict["TRANSFORMER"]) == 1 49 | @test length(data_dict["TRANSFORMER"][1]) == 43 50 | 51 | @test length(data_dict["AREA INTERCHANGE"]) == 1 52 | @test length(data_dict["AREA INTERCHANGE"][1]) == 5 53 | 54 | @test length(data_dict["ZONE"]) == 1 55 | @test length(data_dict["ZONE"][1]) == 2 56 | 57 | @test length(data_dict["OWNER"]) == 1 58 | @test length(data_dict["OWNER"][1]) == 2 59 | end 60 | 61 | @testset "20-bus frankenstein file" begin 62 | data_dict = PowerModels.parse_pti("../test/data/pti/frankenstein_20.raw") 63 | @test isa(data_dict, Dict) 64 | 65 | @test length(data_dict["BRANCH"]) == 2 66 | for item in data_dict["BRANCH"] 67 | @test length(item) == 24 68 | end 69 | 70 | @test length(data_dict["TRANSFORMER"][2]) == 83 71 | 72 | @test length(data_dict["SWITCHED SHUNT"]) == 2 73 | @test length(data_dict["SWITCHED SHUNT"][1]) == 16 74 | @test length(data_dict["SWITCHED SHUNT"][2]) == 12 75 | end 76 | 77 | @testset "70-bus frankenstein file" begin 78 | data_dict = PowerModels.parse_pti("../test/data/pti/frankenstein_70.raw") 79 | @test isa(data_dict, Dict) 80 | 81 | @test length(data_dict["TWO-TERMINAL DC"]) == 1 82 | @test length(data_dict["TWO-TERMINAL DC"][1]) == 46 83 | 84 | @test length(data_dict["VOLTAGE SOURCE CONVERTER"]) == 1 85 | @test length(data_dict["VOLTAGE SOURCE CONVERTER"][1]) == 12 86 | @test length(data_dict["VOLTAGE SOURCE CONVERTER"][1]["CONVERTER BUSES"]) == 2 87 | for item in data_dict["VOLTAGE SOURCE CONVERTER"][1]["CONVERTER BUSES"] 88 | @test length(item) == 15 89 | end 90 | 91 | @test length(data_dict["IMPEDANCE CORRECTION"]) == 2 92 | @test length(data_dict["IMPEDANCE CORRECTION"][1]) == 23 93 | @test length(data_dict["IMPEDANCE CORRECTION"][2]) == 15 94 | 95 | @test length(data_dict["MULTI-TERMINAL DC"]) == 1 96 | @test length(data_dict["MULTI-TERMINAL DC"][1]) == 11 97 | 98 | @test length(data_dict["MULTI-TERMINAL DC"][1]["CONV"]) == 3 99 | for item in data_dict["MULTI-TERMINAL DC"][1]["CONV"] 100 | @test length(item) == 16 101 | end 102 | 103 | @test length(data_dict["MULTI-TERMINAL DC"][1]["DCBS"]) == 3 104 | for item in data_dict["MULTI-TERMINAL DC"][1]["DCBS"] 105 | @test length(item) == 8 106 | end 107 | 108 | @test length(data_dict["MULTI-TERMINAL DC"][1]["DCLN"]) == 3 109 | for item in data_dict["MULTI-TERMINAL DC"][1]["DCLN"] 110 | @test length(item) == 6 111 | end 112 | 113 | @test length(data_dict["FACTS CONTROL DEVICE"]) == 2 114 | for item in data_dict["FACTS CONTROL DEVICE"] 115 | @test length(item) == 19 116 | end 117 | 118 | data_dict = PowerModels.parse_pti("../test/data/pti/parser_test_e.raw") 119 | @test length(data_dict["MULTI-TERMINAL DC"][1]) == 10 120 | 121 | data_dict = PowerModels.parse_pti("../test/data/pti/parser_test_f.raw") 122 | @test length(data_dict["MULTI-TERMINAL DC"][1]) == 9 123 | 124 | data_dict = PowerModels.parse_pti("../test/data/pti/parser_test_g.raw") 125 | @test length(data_dict["MULTI-TERMINAL DC"][1]) == 8 126 | 127 | end 128 | 129 | @testset "0-bus case file" begin 130 | @test_throws(getlogger(PowerModels), ArgumentError, PowerModels.parse_pti("../test/data/pti/case0.raw")) 131 | end 132 | 133 | @testset "73-bus case file" begin 134 | data_dict = PowerModels.parse_pti("../test/data/pti/case73.raw") 135 | @test isa(data_dict, Dict) 136 | 137 | @test length(data_dict["BUS"]) == 73 138 | for item in data_dict["BUS"] 139 | @test length(item) == 13 140 | end 141 | 142 | @test length(data_dict["LOAD"]) == 51 143 | for item in data_dict["LOAD"] 144 | @test length(item) == 13 145 | end 146 | 147 | @test length(data_dict["GENERATOR"]) == 99 148 | for item in data_dict["GENERATOR"] 149 | @test length(item) == 28 150 | end 151 | 152 | @test length(data_dict["BRANCH"]) == 105 153 | for item in data_dict["BRANCH"] 154 | @test length(item) == 24 155 | end 156 | 157 | @test length(data_dict["TRANSFORMER"]) == 15 158 | for item in data_dict["TRANSFORMER"] 159 | @test length(item) == 43 160 | end 161 | 162 | @test length(data_dict["AREA INTERCHANGE"]) == 3 163 | @test length(data_dict["ZONE"]) == 3 164 | @test length(data_dict["OWNER"]) == 1 165 | 166 | @test length(data_dict["SWITCHED SHUNT"]) == 3 167 | for item in data_dict["SWITCHED SHUNT"] 168 | @test length(item) == 12 169 | end 170 | end 171 | end -------------------------------------------------------------------------------- /src/form/shared.jl: -------------------------------------------------------------------------------- 1 | # 2 | # Shared Formulation Definitions 3 | ################################# 4 | # 5 | # This is the home of functions that are shared across multiple branches 6 | # of the type hierarchy. Hence all function in this file should be over 7 | # union types. 8 | # 9 | # The types defined in this file should not be exported because they exist 10 | # only to prevent code replication 11 | # 12 | # Note that Union types are discouraged in Julia, 13 | # https://docs.julialang.org/en/release-0.6/manual/style-guide/#Avoid-strange-type-Unions-1 14 | # and should be used with discretion. 15 | # 16 | # If you are about to add a union type, 17 | # first double check if a different type hierarchy can resolve the issue 18 | # instead. 19 | # 20 | 21 | AbstractWRForms = Union{AbstractACTForm, AbstractWRForm, AbstractWRMForm} 22 | AbstractWForms = Union{AbstractWRForms, AbstractDFForm} 23 | AbstractPForms = Union{AbstractACPForm, AbstractACTForm, AbstractDCPForm} 24 | 25 | "`t[ref_bus] == 0`" 26 | function constraint_theta_ref(pm::GenericPowerModel{T}, n::Int, i::Int) where T <: AbstractPForms 27 | @constraint(pm.model, pm.var[:nw][n][:va][i] == 0) 28 | end 29 | 30 | """ 31 | ``` 32 | t[f_bus] - t[t_bus] <= angmax 33 | t[f_bus] - t[t_bus] >= angmin 34 | ``` 35 | """ 36 | function constraint_voltage_angle_difference(pm::GenericPowerModel{T}, n::Int, f_idx, angmin, angmax) where T <: AbstractPForms 37 | i, f_bus, t_bus = f_idx 38 | 39 | va_fr = pm.var[:nw][n][:va][f_bus] 40 | va_to = pm.var[:nw][n][:va][t_bus] 41 | 42 | @constraint(pm.model, va_fr - va_to <= angmax) 43 | @constraint(pm.model, va_fr - va_to >= angmin) 44 | end 45 | 46 | 47 | function constraint_voltage_magnitude_setpoint(pm::GenericPowerModel{T}, n::Int, i, vm) where T <: AbstractWForms 48 | w = pm.var[:nw][n][:w][i] 49 | 50 | @constraint(pm.model, w == vm^2) 51 | end 52 | 53 | "Do nothing, no way to represent this in these variables" 54 | function constraint_theta_ref(pm::GenericPowerModel{T}, n::Int, ref_bus::Int) where T <: AbstractWForms 55 | end 56 | 57 | 58 | """ 59 | ``` 60 | sum(p[a] for a in bus_arcs) + sum(p_dc[a_dc] for a_dc in bus_arcs_dc) == sum(pg[g] for g in bus_gens) - sum(pd[d] for d in bus_loads) - sum(gs[s] for d in bus_shunts)*w[i] 61 | sum(q[a] for a in bus_arcs) + sum(q_dc[a_dc] for a_dc in bus_arcs_dc) == sum(qg[g] for g in bus_gens) - sum(qd[d] for d in bus_loads) + sum(bs[s] for d in bus_shunts)*w[i] 62 | ``` 63 | """ 64 | 65 | function constraint_kcl_shunt(pm::GenericPowerModel{T}, n::Int, i, bus_arcs, bus_arcs_dc, bus_gens, bus_loads, bus_shunts, pd, qd, gs, bs) where T <: AbstractWForms 66 | w = pm.var[:nw][n][:w][i] 67 | pg = pm.var[:nw][n][:pg] 68 | qg = pm.var[:nw][n][:qg] 69 | p = pm.var[:nw][n][:p] 70 | q = pm.var[:nw][n][:q] 71 | p_dc = pm.var[:nw][n][:p_dc] 72 | q_dc = pm.var[:nw][n][:q_dc] 73 | load = pm.ref[:nw][n][:load] 74 | shunt = pm.ref[:nw][n][:shunt] 75 | 76 | @constraint(pm.model, sum(p[a] for a in bus_arcs) + sum(p_dc[a_dc] for a_dc in bus_arcs_dc) == sum(pg[g] for g in bus_gens) - sum(pd[d] for d in bus_loads) - sum(gs[s] for s in bus_shunts)*w) 77 | @constraint(pm.model, sum(q[a] for a in bus_arcs) + sum(q_dc[a_dc] for a_dc in bus_arcs_dc) == sum(qg[g] for g in bus_gens) - sum(qd[d] for d in bus_loads) + sum(bs[s] for s in bus_shunts)*w) 78 | end 79 | 80 | 81 | """ 82 | ``` 83 | sum(p[a] for a in bus_arcs) + sum(p_ne[a] for a in bus_arcs_ne) + sum(p_dc[a_dc] for a_dc in bus_arcs_dc) == sum(pg[g] for g in bus_gens) - sum(pd[d] for d in bus_loads) - sum(gs[s] for s in bus_shunts)*w[i] 84 | sum(q[a] for a in bus_arcs) + sum(q_ne[a] for a in bus_arcs_ne) + sum(q_dc[a_dc] for a_dc in bus_arcs_dc) == sum(qg[g] for g in bus_gens) - sum(qd[d] for d in bus_loads) + sum(bs[s] for s in bus_shunts)*w[i] 85 | ``` 86 | """ 87 | function constraint_kcl_shunt_ne(pm::GenericPowerModel{T}, n::Int, i, bus_arcs, bus_arcs_dc, bus_arcs_ne, bus_gens, bus_loads, bus_shunts, pd, qd, gs, bs) where T <: AbstractWRForms 88 | w = pm.var[:nw][n][:w][i] 89 | pg = pm.var[:nw][n][:pg] 90 | qg = pm.var[:nw][n][:qg] 91 | p = pm.var[:nw][n][:p] 92 | q = pm.var[:nw][n][:q] 93 | p_ne = pm.var[:nw][n][:p_ne] 94 | q_ne = pm.var[:nw][n][:q_ne] 95 | p_dc = pm.var[:nw][n][:p_dc] 96 | q_dc = pm.var[:nw][n][:q_dc] 97 | load = pm.ref[:nw][n][:load] 98 | shunt = pm.ref[:nw][n][:shunt] 99 | 100 | @constraint(pm.model, sum(p[a] for a in bus_arcs) + sum(p_ne[a] for a in bus_arcs_ne) + sum(p_dc[a_dc] for a_dc in bus_arcs_dc) == sum(pg[g] for g in bus_gens) - sum(pd[d] for d in bus_loads) - sum(gs[s] for s in bus_shunts)*w) 101 | @constraint(pm.model, sum(q[a] for a in bus_arcs) + sum(q_ne[a] for a in bus_arcs_ne) + sum(q_dc[a_dc] for a_dc in bus_arcs_dc) == sum(qg[g] for g in bus_gens) - sum(qd[d] for d in bus_loads) + sum(bs[s] for s in bus_shunts)*w) 102 | end 103 | 104 | 105 | """ 106 | Creates Ohms constraints (yt post fix indicates that Y and T values are in rectangular form) 107 | """ 108 | function constraint_ohms_yt_from(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, g, b, g_fr, b_fr, tr, ti, tm) where T <: AbstractWRForms 109 | p_fr = pm.var[:nw][n][:p][f_idx] 110 | q_fr = pm.var[:nw][n][:q][f_idx] 111 | w_fr = pm.var[:nw][n][:w][f_bus] 112 | wr = pm.var[:nw][n][:wr][(f_bus, t_bus)] 113 | wi = pm.var[:nw][n][:wi][(f_bus, t_bus)] 114 | 115 | @constraint(pm.model, p_fr == (g+g_fr)/tm^2*w_fr + (-g*tr+b*ti)/tm^2*wr + (-b*tr-g*ti)/tm^2*wi ) 116 | @constraint(pm.model, q_fr == -(b+b_fr)/tm^2*w_fr - (-b*tr-g*ti)/tm^2*wr + (-g*tr+b*ti)/tm^2*wi ) 117 | end 118 | 119 | 120 | """ 121 | Creates Ohms constraints (yt post fix indicates that Y and T values are in rectangular form) 122 | """ 123 | function constraint_ohms_yt_to(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, g, b, g_to, b_to, tr, ti, tm) where T <: AbstractWRForms 124 | q_to = pm.var[:nw][n][:q][t_idx] 125 | p_to = pm.var[:nw][n][:p][t_idx] 126 | w_to = pm.var[:nw][n][:w][t_bus] 127 | wr = pm.var[:nw][n][:wr][(f_bus, t_bus)] 128 | wi = pm.var[:nw][n][:wi][(f_bus, t_bus)] 129 | 130 | @constraint(pm.model, p_to == (g+g_to)*w_to + (-g*tr-b*ti)/tm^2*wr + (-b*tr+g*ti)/tm^2*-wi ) 131 | @constraint(pm.model, q_to == -(b+b_to)*w_to - (-b*tr+g*ti)/tm^2*wr + (-g*tr-b*ti)/tm^2*-wi ) 132 | end 133 | 134 | 135 | "" 136 | function constraint_voltage_angle_difference(pm::GenericPowerModel{T}, n::Int, f_idx, angmin, angmax) where T <: AbstractWRForms 137 | i, f_bus, t_bus = f_idx 138 | 139 | w_fr = pm.var[:nw][n][:w][f_bus] 140 | w_to = pm.var[:nw][n][:w][t_bus] 141 | wr = pm.var[:nw][n][:wr][(f_bus, t_bus)] 142 | wi = pm.var[:nw][n][:wi][(f_bus, t_bus)] 143 | 144 | @constraint(pm.model, wi <= tan(angmax)*wr) 145 | @constraint(pm.model, wi >= tan(angmin)*wr) 146 | cut_complex_product_and_angle_difference(pm.model, w_fr, w_to, wr, wi, angmin, angmax) 147 | end 148 | 149 | 150 | "" 151 | function add_bus_voltage_setpoint(sol, pm::GenericPowerModel{T}) where T <: AbstractWForms 152 | add_setpoint(sol, pm, "bus", "vm", :w; scale = (x,item) -> sqrt(x)) 153 | # What should the default value be? 154 | #add_setpoint(sol, pm, "bus", "va", :va; default_value = 0) 155 | end 156 | -------------------------------------------------------------------------------- /docs/src/specifications.md: -------------------------------------------------------------------------------- 1 | # Problem Specifications 2 | 3 | ## Optimal Power Flow (OPF) 4 | 5 | ### Objective 6 | ```julia 7 | objective_min_fuel_cost(pm) 8 | ``` 9 | 10 | ### Variables 11 | ```julia 12 | variable_voltage(pm) 13 | variable_active_generation(pm) 14 | variable_reactive_generation(pm) 15 | variable_branch_flow(pm) 16 | variable_dcline_flow(pm) 17 | ``` 18 | 19 | ### Constraints 20 | ```julia 21 | constraint_theta_ref(pm) 22 | constraint_voltage(pm) 23 | for (i,bus) in pm.ref[:bus] 24 | constraint_kcl_shunt(pm, bus) 25 | end 26 | for (i,branch) in pm.ref[:branch] 27 | constraint_ohms_yt_from(pm, branch) 28 | constraint_ohms_yt_to(pm, branch) 29 | 30 | constraint_voltage_angle_difference(pm, branch) 31 | 32 | constraint_thermal_limit_from(pm, branch) 33 | constraint_thermal_limit_to(pm, branch) 34 | end 35 | for (i,dcline) in pm.ref[:dcline] 36 | constraint_dcline(pm, dcline) 37 | end 38 | ``` 39 | 40 | ## Optimal Power Flow (OPF) using the Branch Flow Model 41 | 42 | ### Objective 43 | ```julia 44 | objective_min_fuel_cost(pm) 45 | ``` 46 | 47 | ### Variables 48 | ```julia 49 | variable_voltage(pm) 50 | variable_active_generation(pm) 51 | variable_reactive_generation(pm) 52 | variable_branch_flow(pm) 53 | variable_branch_current(pm) 54 | variable_dcline_flow(pm) 55 | ``` 56 | 57 | ### Constraints 58 | ```julia 59 | constraint_theta_ref(pm) 60 | constraint_voltage(pm) 61 | for (i,bus) in pm.ref[:bus] 62 | constraint_kcl_shunt(pm, bus) 63 | end 64 | for (i,branch) in pm.ref[:branch] 65 | constraint_flow_losses(pm, branch) 66 | constraint_voltage_magnitude_difference(pm, branch) 67 | constraint_branch_current(pm, branch) 68 | 69 | constraint_voltage_angle_difference(pm, branch) 70 | 71 | constraint_thermal_limit_from(pm, branch) 72 | constraint_thermal_limit_to(pm, branch) 73 | end 74 | for (i,dcline) in pm.ref[:dcline] 75 | constraint_dcline(pm, dcline) 76 | end 77 | ``` 78 | 79 | ## Optimal Transmission Switching (OTS) 80 | 81 | ### General Assumptions 82 | 83 | - if the branch status is `0` in the input, it is out of service and forced to `0` in OTS 84 | - the network will be maintained as one connected component (i.e. at least `n-1` edges) 85 | 86 | ### Variables 87 | 88 | ```julia 89 | variable_branch_indicator(pm) 90 | variable_voltage_on_off(pm) 91 | variable_active_generation(pm) 92 | variable_reactive_generation(pm) 93 | variable_branch_flow(pm) 94 | variable_dcline_flow(pm) 95 | ``` 96 | 97 | ### Objective 98 | 99 | ```julia 100 | objective_min_fuel_cost(pm) 101 | ``` 102 | 103 | ### Constraints 104 | 105 | ```julia 106 | constraint_theta_ref(pm) 107 | constraint_voltage_on_off(pm) 108 | for (i,bus) in pm.ref[:bus] 109 | constraint_kcl_shunt(pm, bus) 110 | end 111 | for (i,branch) in pm.ref[:branch] 112 | constraint_ohms_yt_from_on_off(pm, branch) 113 | constraint_ohms_yt_to_on_off(pm, branch) 114 | 115 | constraint_voltage_angle_difference_on_off(pm, branch) 116 | 117 | constraint_thermal_limit_from_on_off(pm, branch) 118 | constraint_thermal_limit_to_on_off(pm, branch) 119 | end 120 | for (i,dcline) in pm.ref[:dcline] 121 | constraint_dcline(pm, dcline) 122 | end 123 | ``` 124 | 125 | ## Power Flow (PF) 126 | 127 | ### Assumptions 128 | 129 | ### Variables 130 | ```julia 131 | variable_voltage(pm, bounded = false) 132 | variable_active_generation(pm, bounded = false) 133 | variable_reactive_generation(pm, bounded = false) 134 | variable_branch_flow(pm, bounded = false) 135 | variable_dcline_flow(pm, bounded = false) 136 | ``` 137 | 138 | ### Constraints 139 | ```julia 140 | constraint_theta_ref(pm) 141 | constraint_voltage_magnitude_setpoint(pm, pm.ref[:bus][pm.ref[:ref_bus]]) 142 | constraint_voltage(pm) 143 | 144 | 145 | for (i,bus) in pm.ref[:bus] 146 | constraint_kcl_shunt(pm, bus) 147 | 148 | # PV Bus Constraints 149 | if length(pm.ref[:bus_gens][i]) > 0 && i != pm.ref[:ref_bus] 150 | # this assumes inactive generators are filtered out of bus_gens 151 | @assert bus["bus_type"] == 2 152 | 153 | constraint_voltage_magnitude_setpoint(pm, bus) 154 | for j in pm.ref[:bus_gens][i] 155 | constraint_active_gen_setpoint(pm, pm.ref[:gen][j]) 156 | end 157 | end 158 | end 159 | 160 | for (i,branch) in pm.ref[:branch] 161 | constraint_ohms_yt_from(pm, branch) 162 | constraint_ohms_yt_to(pm, branch) 163 | end 164 | for (i,dcline) in pm.ref[:dcline] 165 | constraint_active_dcline_setpoint(pm, dcline) 166 | end 167 | ``` 168 | 169 | 170 | ## Power Flow (PF) using the Branch Flow Model 171 | 172 | ### Assumptions 173 | 174 | ### Variables 175 | ```julia 176 | variable_voltage(pm, bounded = false) 177 | variable_active_generation(pm, bounded = false) 178 | variable_reactive_generation(pm, bounded = false) 179 | variable_branch_flow(pm, bounded = false) 180 | constraint_branch_current(pm, bounded = false) 181 | variable_branch_current(pm, bounded = false) 182 | ``` 183 | 184 | ### Constraints 185 | ```julia 186 | constraint_theta_ref(pm) 187 | constraint_voltage_magnitude_setpoint(pm, pm.ref[:bus][pm.ref[:ref_bus]]) 188 | constraint_voltage(pm) 189 | 190 | 191 | for (i,bus) in pm.ref[:bus] 192 | constraint_kcl_shunt(pm, bus) 193 | 194 | # PV Bus Constraints 195 | if length(pm.ref[:bus_gens][i]) > 0 && i != pm.ref[:ref_bus] 196 | # this assumes inactive generators are filtered out of bus_gens 197 | @assert bus["bus_type"] == 2 198 | 199 | constraint_voltage_magnitude_setpoint(pm, bus) 200 | for j in pm.ref[:bus_gens][i] 201 | constraint_active_gen_setpoint(pm, pm.ref[:gen][j]) 202 | end 203 | end 204 | end 205 | 206 | for (i,branch) in pm.ref[:branch] 207 | constraint_flow_losses(pm, branch) 208 | constraint_voltage_magnitude_difference(pm, branch) 209 | constraint_branch_current(pm, branch) 210 | end 211 | for (i,dcline) in pm.ref[:dcline] 212 | constraint_active_dcline_setpoint(pm, dcline) 213 | end 214 | ``` 215 | 216 | ## Transmission Network Expansion Planning (TNEP) 217 | 218 | ### Objective 219 | ```julia 220 | objective_tnep_cost(pm) 221 | ``` 222 | 223 | ### Variables 224 | ```julia 225 | variable_branch_ne(pm) 226 | variable_voltage(pm) 227 | variable_voltage_ne(pm) 228 | variable_active_generation(pm) 229 | variable_reactive_generation(pm) 230 | variable_branch_flow(pm) 231 | variable_dcline_flow(pm) 232 | variable_branch_flow_ne(pm) 233 | ``` 234 | 235 | ### Constraints 236 | ```julia 237 | constraint_theta_ref(pm) 238 | constraint_voltage(pm) 239 | constraint_voltage_ne(pm) 240 | 241 | for (i,bus) in pm.ref[:bus] 242 | constraint_kcl_shunt_ne(pm, bus) 243 | end 244 | 245 | for (i,branch) in pm.ref[:branch] 246 | constraint_ohms_yt_from(pm, branch) 247 | constraint_ohms_yt_to(pm, branch) 248 | 249 | constraint_voltage_angle_difference(pm, branch) 250 | 251 | constraint_thermal_limit_from(pm, branch) 252 | constraint_thermal_limit_to(pm, branch) 253 | end 254 | 255 | for (i,branch) in pm.ref[:ne_branch] 256 | constraint_ohms_yt_from_ne(pm, branch) 257 | constraint_ohms_yt_to_ne(pm, branch) 258 | 259 | constraint_voltage_angle_difference_ne(pm, branch) 260 | 261 | constraint_thermal_limit_from_ne(pm, branch) 262 | constraint_thermal_limit_to_ne(pm, branch) 263 | end 264 | for (i,dcline) in pm.ref[:dcline] 265 | constraint_dcline(pm, dcline) 266 | end 267 | ``` 268 | -------------------------------------------------------------------------------- /test/data/matpower/case30.m: -------------------------------------------------------------------------------- 1 | % NESTA v0.6.0 2 | function mpc = nesta_case30_ieee 3 | mpc.version = '2'; 4 | mpc.baseMVA = 100.0; 5 | 6 | %% bus data 7 | % bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin 8 | mpc.bus = [ 9 | 1 3 0.0 0.0 0.0 0.0 1 1.06000 -0.00000 132.0 1 1.06000 0.94000; 10 | 2 2 21.7 12.7 0.0 0.0 1 1.03591 -4.11149 132.0 1 1.06000 0.94000; 11 | 3 1 2.4 1.2 0.0 0.0 1 1.01502 -6.85372 132.0 1 1.06000 0.94000; 12 | 4 1 7.6 1.6 0.0 0.0 1 1.00446 -8.44574 132.0 1 1.06000 0.94000; 13 | 5 2 94.2 19.0 0.0 0.0 1 0.99748 -13.13219 132.0 1 1.06000 0.94000; 14 | 6 1 0.0 0.0 0.0 0.0 1 1.00170 -10.15671 132.0 1 1.06000 0.94000; 15 | 7 1 22.8 10.9 0.0 0.0 1 0.99208 -11.91706 132.0 1 1.06000 0.94000; 16 | 8 2 30.0 30.0 0.0 0.0 1 1.00241 -10.93461 132.0 1 1.06000 0.94000; 17 | 9 1 0.0 0.0 0.0 0.0 1 1.03671 -13.26615 1.0 1 1.06000 0.94000; 18 | 10 1 5.8 2.0 0.0 19.0 1 1.03220 -14.89730 33.0 1 1.06000 0.94000; 19 | 11 2 0.0 0.0 0.0 0.0 1 1.06000 -13.26615 11.0 1 1.06000 0.94000; 20 | 12 1 11.2 7.5 0.0 0.0 1 1.04625 -14.18878 33.0 1 1.06000 0.94000; 21 | 13 2 0.0 0.0 0.0 0.0 1 1.06000 -14.18878 11.0 1 1.06000 0.94000; 22 | 14 1 6.2 1.6 0.0 0.0 1 1.03103 -15.09457 33.0 1 1.06000 0.94000; 23 | 15 1 8.2 2.5 0.0 0.0 1 1.02621 -15.17834 33.0 1 1.06000 0.94000; 24 | 16 1 3.5 1.8 0.0 0.0 1 1.03259 -14.75320 33.0 1 1.06000 0.94000; 25 | 17 1 9.0 5.8 0.0 0.0 1 1.02726 -15.07475 33.0 1 1.06000 0.94000; 26 | 18 1 3.2 0.9 0.0 0.0 1 1.01602 -15.79032 33.0 1 1.06000 0.94000; 27 | 19 1 9.5 3.4 0.0 0.0 1 1.01317 -15.95831 33.0 1 1.06000 0.94000; 28 | 20 1 2.2 0.7 0.0 0.0 1 1.01714 -15.75153 33.0 1 1.06000 0.94000; 29 | 21 1 17.5 11.2 0.0 0.0 1 1.01982 -15.35269 33.0 1 1.06000 0.94000; 30 | 22 1 0.0 0.0 0.0 0.0 1 1.02041 -15.33860 33.0 1 1.06000 0.94000; 31 | 23 1 3.2 1.6 0.0 0.0 1 1.01532 -15.56400 33.0 1 1.06000 0.94000; 32 | 24 1 8.7 6.7 0.0 4.3 1 1.00930 -15.72597 33.0 1 1.06000 0.94000; 33 | 25 1 0.0 0.0 0.0 0.0 1 1.00621 -15.29138 33.0 1 1.06000 0.94000; 34 | 26 1 3.5 2.3 0.0 0.0 1 0.98833 -15.72053 33.0 1 1.06000 0.94000; 35 | 27 1 0.0 0.0 0.0 0.0 1 1.01294 -14.75624 33.0 1 1.06000 0.94000; 36 | 28 1 0.0 0.0 0.0 0.0 1 0.99824 -10.79567 132.0 1 1.06000 0.94000; 37 | 29 1 2.4 0.9 0.0 0.0 1 0.99288 -16.01182 33.0 1 1.06000 0.94000; 38 | 30 1 10.6 1.9 0.0 0.0 1 0.98128 -16.91371 33.0 1 1.06000 0.94000; 39 | ]; 40 | 41 | %% generator data 42 | % bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf 43 | mpc.gen = [ 44 | 1 218.839 9.372 10.0 0.0 1.06 100.0 1 784 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % COW 45 | 2 80.05 24.589 50.0 -40.0 1.03591 100.0 1 100 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % NG 46 | 5 0.0 32.487 40.0 -40.0 0.99748 100.0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % SYNC 47 | 8 0.0 40.0 40.0 -10.0 1.00241 100.0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % SYNC 48 | 11 0.0 11.87 24.0 -6.0 1.06 100.0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % SYNC 49 | 13 0.0 10.414 24.0 -6.0 1.06 100.0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; % SYNC 50 | ]; 51 | 52 | %% generator cost data 53 | % 2 startup shutdown n c(n-1) ... c0 54 | mpc.gencost = [ 55 | 2 0.0 0.0 3 0.000000 0.521378 0.000000; % COW 56 | 2 0.0 0.0 3 0.000000 1.135166 0.000000; % NG 57 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; % SYNC 58 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; % SYNC 59 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; % SYNC 60 | 2 0.0 0.0 3 0.000000 0.000000 0.000000; % SYNC 61 | ]; 62 | 63 | %% branch data 64 | % fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax 65 | mpc.branch = [ 66 | 1 2 0.0192 0.0575 0.0528 138 138 138 0.0 0.0 1 -30.0 30.0; 67 | 1 3 0.0452 0.1652 0.0408 152 152 152 0.0 0.0 1 -30.0 30.0; 68 | 2 4 0.057 0.1737 0.0368 139 139 139 0.0 0.0 1 -30.0 30.0; 69 | 3 4 0.0132 0.0379 0.0084 135 135 135 0.0 0.0 1 -30.0 30.0; 70 | 2 5 0.0472 0.1983 0.0418 144 144 144 0.0 0.0 1 -30.0 30.0; 71 | 2 6 0.0581 0.1763 0.0374 139 139 139 0.0 0.0 1 -30.0 30.0; 72 | 4 6 0.0119 0.0414 0.009 148 148 148 0.0 0.0 1 -30.0 30.0; 73 | 5 7 0.046 0.116 0.0204 127 127 127 0.0 0.0 1 -30.0 30.0; 74 | 6 7 0.0267 0.082 0.017 140 140 140 0.0 0.0 1 -30.0 30.0; 75 | 6 8 0.012 0.042 0.009 148 148 148 0.0 0.0 1 -30.0 30.0; 76 | 6 9 0.0 0.208 0.0 142 142 142 0.978 0.0 1 -30.0 30.0; 77 | 6 10 0.0 0.556 0.0 53 53 53 0.969 0.0 1 -30.0 30.0; 78 | 9 11 0.0 0.208 0.0 142 142 142 0.0 0.0 1 -30.0 30.0; 79 | 9 10 0.0 0.11 0.0 267 267 267 0.0 0.0 1 -30.0 30.0; 80 | 4 12 0.0 0.256 0.0 115 115 115 0.932 0.0 1 -30.0 30.0; 81 | 12 13 0.0 0.14 0.0 210 210 210 0.0 0.0 1 -30.0 30.0; 82 | 12 14 0.1231 0.2559 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 83 | 12 15 0.0662 0.1304 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 84 | 12 16 0.0945 0.1987 0.0 30 30 30 0.0 0.0 1 -30.0 30.0; 85 | 14 15 0.221 0.1997 0.0 20 20 20 0.0 0.0 1 -30.0 30.0; 86 | 16 17 0.0524 0.1923 0.0 38 38 38 0.0 0.0 1 -30.0 30.0; 87 | 15 18 0.1073 0.2185 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 88 | 18 19 0.0639 0.1292 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 89 | 19 20 0.034 0.068 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 90 | 10 20 0.0936 0.209 0.0 30 30 30 0.0 0.0 1 -30.0 30.0; 91 | 10 17 0.0324 0.0845 0.0 33 33 33 0.0 0.0 1 -30.0 30.0; 92 | 10 21 0.0348 0.0749 0.0 30 30 30 0.0 0.0 1 -30.0 30.0; 93 | 10 22 0.0727 0.1499 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 94 | 21 22 0.0116 0.0236 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 95 | 15 23 0.1 0.202 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 96 | 22 24 0.115 0.179 0.0 26 26 26 0.0 0.0 1 -30.0 30.0; 97 | 23 24 0.132 0.27 0.0 29 29 29 0.0 0.0 1 -30.0 30.0; 98 | 24 25 0.1885 0.3292 0.0 27 27 27 0.0 0.0 1 -30.0 30.0; 99 | 25 26 0.2544 0.38 0.0 25 25 25 0.0 0.0 1 -30.0 30.0; 100 | 25 27 0.1093 0.2087 0.0 28 28 28 0.0 0.0 1 -30.0 30.0; 101 | 28 27 0.0 0.396 0.0 75 75 75 0.968 0.0 1 -30.0 30.0; 102 | 27 29 0.2198 0.4153 0.0 28 28 28 0.0 0.0 1 -30.0 30.0; 103 | 27 30 0.3202 0.6027 0.0 28 28 28 0.0 0.0 1 -30.0 30.0; 104 | 29 30 0.2399 0.4533 0.0 28 28 28 0.0 0.0 1 -30.0 30.0; 105 | 8 28 0.0636 0.2 0.0428 140 140 140 0.0 0.0 1 -30.0 30.0; 106 | 6 28 0.0169 0.0599 0.013 149 149 149 0.0 0.0 1 -30.0 30.0; 107 | ]; 108 | 109 | -------------------------------------------------------------------------------- /test/data/pti/frankenstein_70.raw: -------------------------------------------------------------------------------- 1 | 0, 100.00, 33, 0, 1, 60.00 2 | A Frankenstein network for testing all of the core features of v33 data files 3 | developed by Carleton Coffrin (cjc@lanl.gov) June 2017 4 | 1001,'FAV SPOT 01', 13.8000, 3, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 5 | 1002,'FAV SPOT 02', 345.0000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 6 | 1003,'FAV SPOT 03', 24.9000, 2, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 7 | 1004,'FAV SPOT 04', 87.0000, 1, 101, 201, 301,1.05000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 8 | 1005,'FAV PLACE 05', 87.0000, 2, 101, 201, 301,1.00000000, 3.000000, 1.10000, 0.90000, 1.10000, 0.90000 9 | 1006,'FAV SPOT 06', 87.0000, 1, 101, 201, 301,1.00000000, -1.000000, 1.10000, 0.90000, 1.10000, 0.90000 10 | 1007,'FAV PLACE 07', 230.0000, 1, 101, 201, 301,1.00000000, 2.000000, 1.10000, 0.90000, 1.10000, 0.90000 11 | 1008,'FAV PLC 08', 87.0000, 2, 101, 201, 301,0.95000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 12 | 1009,'FAV PLACE 09', 87.0000, 3, 101, 201, 301,1.00000000, 0.000000, 1.10000, 0.90000, 1.10000, 0.90000 13 | 0 / END OF BUS DATA, BEGIN LOAD DATA 14 | 1006,'L0',1, 101, 201, 6.600, 2.400, 0.000, 0.000, 0.000, 0.000, 301,1 15 | 1008,'LW',1, 101, 201, 18.900, 6.900, 0.000, 0.000, 0.000, 0.000, 301,1 16 | 1009,'Z0',1, 101, 201, 10.500, 2.300, 0.000, 0.000, 0.000, 0.000, 301,1 17 | 0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA 18 | 1009,'1 ', 1, 0.000, 105.300 19 | 0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA 20 | 1001,'1 ', 0.000, 0.000, 12.800, -3.300,1.02000, 0, 31.800, 0.00000, 0.14200, 0.00000, 0.00000,1.00000,0, 100.0, 500.000, 0.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 21 | 1002,'1 ', 27.500, 2.000, 2.000, 2.000,1.02000, 0, 31.300, 0.00000, 0.23000, 0.00000, 0.00000,1.00000,1, 100.0, 27.500, 16.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 22 | 1009,'1 ', -22.000, -88.041, 250.000, -250.000,1.03000, 0, 100.000, 0.00000, 1.00000, 0.00000, 0.00000,1.00000,1, 100.0, 250.000, -250.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 23 | 1003,'W1', 3.700, -3.900, -3.900, -3.900,1.00000, 0, 20.500, 0.00000, 0.30220, 0.00000, 0.00000,1.00000,1, 100.0, 18.700, 0.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,1, 1.0000 24 | 1005,'1 ', 20.000, -23.413, 250.000, -250.000,1.02000, 0, 320.000, 0.00000, 0.15000, 0.00000, 0.00000,1.00000,1, 100.0, 200.000, -200.000, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,0, 1.0000 25 | 0 / END OF GENERATOR DATA, BEGIN BRANCH DATA 26 | 1004,1006,'1 ',7.05000E-3,3.80500E-2,0.00000E0, 1086.00, 1086.00, 1086.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.8, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 27 | 1008,1005,'1 ',1.27800E-3,1.22940E-2,2.27080E-1,1086.00,1195.00,1086.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 25.5, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 28 | 1005,1009,'1 ',4.75000E-4,4.68000E-3,8.20000E-2,1044.00,1170.00,1044.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 9.4, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000 29 | 0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA 30 | 1001,1004, 0,'1 ',1,1,1,1.00000E0,0.00000E0,2,'T1 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 31 | 1.00000E-7,3.66800E-1, 100.00 32 | 1.000000, 13.800, 0.000, 28.00, 28.00, 28.00,0, 0,1.500000,0.500000,0.984000,0.985000,9999, 0, 0.00000, 0.00000, 0.000 33 | 1.000000, 34.500 34 | 1005,1002, 0,'1 ',1,1,1,0.00000E0,0.00000E0,2,'T2 ',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 35 | 5.21000E-3,1.77370E-1, 100.00 36 | 1.025000, 115.000, 0.000, 84.00, 84.00, 84.00,0, 0,1.500000,0.500000,1.500000,0.500000,9999, 0, 0.00000, 0.00000, 0.000 37 | 1.000000, 13.800 38 | 1007,1006,1003,'1 ',2,1,2,9.75350E4,2.51000E-3,1,'T3 3W',1, 301,1.0000, 0,1.0000, 0,1.0000, 0,1.0000,' ' 39 | 1.06000E-3,3.60970E-2, 144.00,4.95400E-3,2.01040E-1, 100.00,4.35300E-3,2.38183E-1, 100.00,0.98220001, -46.128800 40 | 345.0000,345.000, 0.000, 336.00, 336.00, 0.00,0, 0,1.500000,0.510000,1.500000,0.510000, 2, 0, 0.00000, 0.00000, 0.000 41 | 141.4500,138.000, 0.000, 268.00, 268.00, 0.00,0, 0,1.500000,0.510000,1.500000,0.510000, 5, 0, 0.00000, 0.00000, 0.000 42 | 26.22000, 27.600, 0.000, 84.00, 84.00, 0.00,1, 1003,30.36000,24.84000,1.050000,1.025000, 17, 0, 0.00000, 0.00000, 0.000 43 | 0 / END OF TRANSFORMER DATA, BEGIN AREA DATA 44 | 101, 0, -1307.000, 1.000,'BEST AREA ' 45 | 0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA 46 | 'TTDC Ln 1', 0, 0.1000, -20.00, 7.50, 0.00, 0.0000, 0.00000,I, 0.00, 20,1.00000 47 | 1009, 2, 90.00, 18.10, 0.0140, 0.5780, 230.0, 0.09772, 1.00000, 1.00000, 1.00000, 0.00624, 0, 0, 0, 1, 0.00000 48 | 1004, 2, 90.00, 17.40, 0.0140, 0.5670, 230.0, 0.07134, 1.00000, 1.00000, 1.00000, 0.00625, 0, 0, 0, 1, 0.00000 49 | 0 / END OF TWO-TERMINAL DC DATA, BEGIN VOLTAGE SOURCE CONVERTER DATA 50 | 'VSCDC Ln 1 ', 1, 0.0000, 1, 1.0, 0, 1.0, 0, 1.0, 0, 1.0 51 | 1007, 1, 1, 142.000,1.03400,1118.6000,1.6400, 0.00, 226.00, 1499.79,0.5000, 100.00,-100.00,1007,100.00 52 | 1008, 2, 1, -20.000,1.02100,1118.6000,1.6400, 0.00, 226.00, 1499.79,0.5000, 100.00,-100.00,1008,100.00 53 | 0 / END OF VOLTAGE SOURCE CONVERTER DATA, BEGIN IMPEDANCE CORRECTION DATA 54 | 1, -60.00,1.00000, -36.00,0.35800, -24.40,0.19100, -12.40,0.05300, -8.30,0.02300, 0.00,0.01000, 8.30,0.02300, 12.40,0.05300, 24.40,0.19300, 36.00,0.35900, 60.00,1.00000 55 | 2, -70.00,1.00000, -43.00,0.79000, -32.00,0.86000, 0.00,0.50000, 32.00,0.84000, 43.00,0.79000, 70.00,1.00000 56 | 0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA 57 | 'MTDC Ln 1', 3, 3, 3, 0, 0, 0.00, 0 58 | 1001, 2,90.00, 0.00, 0.0000, 0.0000, 138.0,1.00000,1.00000,1.50000,0.51000,0.00625, 0.00, 1.0000, 0.00000, 1 59 | 1002, 2,90.00, 0.00, 0.0000, 0.0000, 138.0,1.00000,1.00000,1.50000,0.51000,0.00625, 0.00, 1.0000, 0.00000, 1 60 | 1003, 2,90.00, 0.00, 0.0000, 0.0000, 138.0,1.00000,1.00000,1.50000,0.51000,0.00625, 0.00, 1.0000, 0.00000, 1 61 | 1,1001, 101, 201,'1 ', 0,9999.0000, 301 62 | 2,1002, 101, 201,'2 ', 0,9999.0000, 301 63 | 3,1003, 101, 201,'2 ', 0,9999.0000, 301 64 | 1, 2,'1',1, 0.0007, 0.00 65 | 1, 3,'1',1, 0.0006, 0.00 66 | 2, 3,'1',1, 0.0005, 0.00 67 | 0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA 68 | 0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA 69 | 201,'FOO ' 70 | 0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA 71 | 0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA 72 | 301,'BAR ' 73 | 0 / END OF OWNER DATA, BEGIN FACTS CONTROL DEVICE DATA 74 | 1,1004, 0, 1, 0.00, 0.00, 1.03477, 204.000, 0.00,0.90000,1.10000,1.00000, 0.000, 0.05000,100.0,301, 0.0000, 0.0000,0 75 | 1,1008, 1009, 1, 0.00, 0.00, 1.03376, 204.000, 0.00,0.90000,1.10000,1.00000, 0.000, 0.05000,100.0,301, 0.0000, 0.0000,0 76 | 0 / END OF FACTS CONTROL DEVICE DATA, BEGIN SWITCHED SHUNT DATA 77 | 1003,0,0,1,1.05000,0.95000, 0,100.0,' ', 3.80, 9, 0.10, 7, 0.10, 7, 1.00 78 | 1005,0,0,1,1.04500,0.98000, 0,100.0,' ', 6.00, 1, 6.00 79 | 0 /END OF SWITCHED SHUNT DATA, BEGIN GNE DEVICE DATA 80 | 0 /END OF GNE DEVICE DATA 81 | Q 82 | -------------------------------------------------------------------------------- /src/form/df.jl: -------------------------------------------------------------------------------- 1 | # this file contains (balanced) convexified DistFlow formulation, in W space 2 | export 3 | SOCDFPowerModel, SOCDFForm 4 | "" 5 | abstract type AbstractDFForm <: AbstractPowerFormulation end 6 | 7 | "" 8 | abstract type SOCDFForm <: AbstractDFForm end 9 | 10 | "" 11 | const SOCDFPowerModel = GenericPowerModel{SOCDFForm} 12 | 13 | "default SOC constructor" 14 | SOCDFPowerModel(data::Dict{String,Any}; kwargs...) = GenericPowerModel(data, SOCDFForm; kwargs...) 15 | 16 | 17 | "" 18 | function variable_branch_flow(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractDFForm 19 | variable_active_branch_flow(pm, n; kwargs...) 20 | variable_reactive_branch_flow(pm, n; kwargs...) 21 | variable_active_branch_series_flow(pm, n; kwargs...) 22 | variable_reactive_branch_series_flow(pm, n; kwargs...) 23 | 24 | end 25 | 26 | 27 | function variable_active_branch_series_flow(pm::GenericPowerModel, n::Int=pm.cnw; bounded = true) 28 | if bounded 29 | pm.var[:nw][n][:p_s] = @variable(pm.model, 30 | [(l,i,j) in pm.ref[:nw][n][:arcs_from]], basename="$(n)_p_s", 31 | lowerbound = -pm.ref[:nw][n][:branch][l]["rate_a"], 32 | upperbound = pm.ref[:nw][n][:branch][l]["rate_a"], 33 | start = getstart(pm.ref[:nw][n][:branch], l, "p_start") 34 | ) 35 | else 36 | pm.var[:nw][n][:p_s] = @variable(pm.model, 37 | [(l,i,j) in pm.ref[:nw][n][:arcs_from]], basename="$(n)_p_s", 38 | start = getstart(pm.ref[:nw][n][:branch], l, "p_start") 39 | ) 40 | end 41 | end 42 | 43 | 44 | function variable_reactive_branch_series_flow(pm::GenericPowerModel, n::Int=pm.cnw; bounded = true) 45 | if bounded 46 | pm.var[:nw][n][:q_s] = @variable(pm.model, 47 | [(l,i,j) in pm.ref[:nw][n][:arcs_from]], basename="$(n)_q_s", 48 | lowerbound = -pm.ref[:nw][n][:branch][l]["rate_a"], 49 | upperbound = pm.ref[:nw][n][:branch][l]["rate_a"], 50 | start = getstart(pm.ref[:nw][n][:branch], l, "q_start") 51 | ) 52 | else 53 | pm.var[:nw][n][:q_s] = @variable(pm.model, 54 | [(l,i,j) in pm.ref[:nw][n][:arcs_from]], basename="$(n)_q_s", 55 | start = getstart(pm.ref[:nw][n][:branch], l, "q_start") 56 | ) 57 | end 58 | end 59 | 60 | 61 | "" 62 | function variable_branch_current(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractDFForm 63 | variable_branch_series_current_magnitude_sqr(pm, n; kwargs...) 64 | end 65 | 66 | "" 67 | function variable_voltage(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractDFForm 68 | variable_voltage_magnitude_sqr(pm, n; kwargs...) 69 | end 70 | 71 | """ 72 | Defines branch flow model power flow equations 73 | """ 74 | function constraint_flow_losses(pm::GenericPowerModel{T}, n::Int, i, f_bus, t_bus, f_idx, t_idx, r, x, g_sh_fr, g_sh_to, b_sh_fr, b_sh_to, tm) where T <: AbstractDFForm 75 | p_fr = pm.var[:nw][n][:p][f_idx] 76 | q_fr = pm.var[:nw][n][:q][f_idx] 77 | p_to = pm.var[:nw][n][:p][t_idx] 78 | q_to = pm.var[:nw][n][:q][t_idx] 79 | w_fr = pm.var[:nw][n][:w][f_bus] 80 | w_to = pm.var[:nw][n][:w][t_bus] 81 | ccm = pm.var[:nw][n][:ccm][i] 82 | 83 | @constraint(pm.model, p_fr + p_to == g_sh_fr*(w_fr/tm^2) + r*ccm + g_sh_to*w_to) 84 | @constraint(pm.model, q_fr + q_to == -b_sh_fr*(w_fr/tm^2) + x*ccm + -b_sh_to*w_to) 85 | end 86 | 87 | 88 | """ 89 | Defines voltage drop over a branch, linking from and to side voltage magnitude 90 | """ 91 | function constraint_voltage_magnitude_difference(pm::GenericPowerModel{T}, n::Int, i, f_bus, t_bus, f_idx, t_idx, r, x, g_sh_fr, b_sh_fr, tm) where T <: AbstractDFForm 92 | p_fr = pm.var[:nw][n][:p][f_idx] 93 | q_fr = pm.var[:nw][n][:q][f_idx] 94 | w_fr = pm.var[:nw][n][:w][f_bus] 95 | w_to = pm.var[:nw][n][:w][t_bus] 96 | ccm = pm.var[:nw][n][:ccm][i] 97 | 98 | #define series flow expressions to simplify Ohm's law 99 | p_fr_s = p_fr - g_sh_fr*(w_fr/tm^2) 100 | q_fr_s = q_fr + b_sh_fr*(w_fr/tm^2) 101 | 102 | #KVL over the line: 103 | @constraint(pm.model, w_to == (w_fr/tm^2) - 2*(r*p_fr_s + x*q_fr_s) + (r^2 + x^2)*ccm) 104 | 105 | end 106 | 107 | """ 108 | Defines relationship between branch (series) power flow, branch (series) current and node voltage magnitude 109 | """ 110 | function constraint_branch_current(pm::GenericPowerModel{T}, n::Int, i, f_bus, f_idx, g_sh_fr, b_sh_fr, tm) where T <: AbstractDFForm 111 | p_fr = pm.var[:nw][n][:p][f_idx] 112 | q_fr = pm.var[:nw][n][:q][f_idx] 113 | p_s_fr = pm.var[:nw][n][:p_s][f_idx] 114 | q_s_fr = pm.var[:nw][n][:q_s][f_idx] 115 | w_fr = pm.var[:nw][n][:w][f_bus] 116 | ccm = pm.var[:nw][n][:ccm][i] 117 | 118 | @constraint(pm.model, p_s_fr == p_fr - g_sh_fr*(w_fr/tm^2)) 119 | @constraint(pm.model, q_s_fr == q_fr + b_sh_fr*(w_fr/tm^2)) 120 | @constraint(pm.model, p_s_fr^2 + q_s_fr^2 <= (w_fr/tm^2)*ccm) 121 | 122 | # define series flow expressions to simplify constraint 123 | #p_fr_s = p_fr - g_sh_fr*(w_fr/tm^2) 124 | #q_fr_s = q_fr + b_sh_fr*(w_fr/tm^2) 125 | 126 | # convex constraint linking p, q, w and ccm 127 | #@constraint(pm.model, p_fr_s^2 + q_fr_s^2 <= (w_fr/tm^2)*ccm) 128 | end 129 | 130 | 131 | function constraint_voltage_angle_difference(pm::GenericPowerModel{T}, n::Int, f_idx, angmin, angmax) where T <: AbstractDFForm 132 | i, f_bus, t_bus = f_idx 133 | t_idx = (i, t_bus, f_bus) 134 | 135 | branch = ref(pm, n, :branch, i) 136 | tm = branch["tap"] 137 | g, b = calc_branch_y(branch) 138 | g_sh_fr = branch["g_fr"] 139 | g_sh_to = branch["g_to"] 140 | b_sh_fr = branch["b_fr"] 141 | b_sh_to = branch["b_to"] 142 | 143 | tr, ti = calc_branch_t(branch) 144 | 145 | # convert series admittance to impedance 146 | z_s = 1/(g + im*b) 147 | r_s = real(z_s) 148 | x_s = imag(z_s) 149 | 150 | # getting the variables 151 | w_fr = pm.var[:nw][n][:w][f_bus] 152 | w_to = pm.var[:nw][n][:w][t_bus] 153 | 154 | p_fr = pm.var[:nw][n][:p][f_idx] 155 | p_to = pm.var[:nw][n][:p][t_idx] 156 | 157 | q_fr = pm.var[:nw][n][:q][f_idx] 158 | q_to = pm.var[:nw][n][:q][t_idx] 159 | 160 | tzr = r_s*tr - x_s*ti 161 | tzi = r_s*ti + x_s*tr 162 | 163 | @constraint(pm.model, 164 | tan(angmin)*(( tr + tzr*g_sh_fr - tzi*b_sh_fr)*(w_fr/tm^2) - tzr*p_fr - tzi*q_fr) 165 | <= ((-ti - tzi*g_sh_fr - tzr*b_sh_fr)*(w_fr/tm^2) - tzr*q_fr + tzi*p_fr) 166 | ) 167 | @constraint(pm.model, 168 | tan(angmax)*(( tr + tzr*g_sh_fr - tzi*b_sh_fr)*(w_fr/tm^2) - tzr*p_fr - tzi*q_fr) 169 | >= ((-ti - tzi*g_sh_fr - tzr*b_sh_fr)*(w_fr/tm^2) - tzr*q_fr + tzi*p_fr) 170 | ) 171 | end 172 | 173 | 174 | "variable: `0 <= i[l] <= (Imax)^2` for `l` in `branch`es" 175 | function variable_branch_series_current_magnitude_sqr(pm::GenericPowerModel, n::Int=pm.cnw; bounded = true) 176 | branches = pm.ref[:nw][n][:branch] 177 | buses = pm.ref[:nw][n][:bus] 178 | cmax = calc_series_current_magnitude_bound(branches, buses) 179 | if bounded 180 | pm.var[:nw][n][:ccm] = @variable(pm.model, 181 | [l in keys(pm.ref[:nw][n][:branch])], basename="$(n)_ccm", 182 | lowerbound = 0, 183 | upperbound = (cmax[l])^2, 184 | start = getstart(pm.ref[:nw][n][:branch], l, "i_start") 185 | ) 186 | else 187 | pm.var[:nw][n][:ccm] = @variable(pm.model, 188 | [l in keys(pm.ref[:nw][n][:branch])], basename="$(n)_ccm", 189 | lowerbound = 0, 190 | start = getstart(pm.ref[:nw][n][:branch], l, "i_start") 191 | ) 192 | end 193 | end 194 | -------------------------------------------------------------------------------- /test/matpower.jl: -------------------------------------------------------------------------------- 1 | using JSON 2 | 3 | 4 | @testset "test matpower parser" begin 5 | @testset "30-bus case file" begin 6 | result = run_opf("../test/data/matpower/case30.m", ACPPowerModel, ipopt_solver) 7 | 8 | @test result["status"] == :LocalOptimal 9 | @test isapprox(result["objective"], 204.96; atol = 1e-1) 10 | end 11 | 12 | @testset "30-bus case matpower data" begin 13 | data = PowerModels.parse_file("../test/data/matpower/case30.m") 14 | @test isa(JSON.json(data), String) 15 | 16 | result = run_opf(data, ACPPowerModel, ipopt_solver) 17 | 18 | @test result["status"] == :LocalOptimal 19 | @test isapprox(result["objective"], 204.96; atol = 1e-1) 20 | end 21 | 22 | @testset "14-bus case file with bus names" begin 23 | data = PowerModels.parse_file("../test/data/matpower/case14.m") 24 | @test data["bus"]["1"]["bus_name"] == "Bus 1 HV" 25 | @test isa(JSON.json(data), String) 26 | end 27 | 28 | @testset "5-bus case file with pwl cost functions" begin 29 | data = PowerModels.parse_file("../test/data/matpower/case5_pwlc.m") 30 | @test data["gen"]["1"]["model"] == 1 31 | @test isa(JSON.json(data), String) 32 | end 33 | 34 | @testset "3-bus case file with hvdc lines" begin 35 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 36 | @test length(data["dcline"]) > 0 37 | @test isa(JSON.json(data), String) 38 | end 39 | 40 | @testset "2-bus case file with spaces" begin 41 | result = run_pf("../test/data/matpower/case2.m", ACPPowerModel, ipopt_solver) 42 | 43 | @test result["status"] == :LocalOptimal 44 | @test isapprox(result["objective"], 0.0; atol = 1e-1) 45 | end 46 | end 47 | 48 | 49 | @testset "test matpower data coercion" begin 50 | @testset "ACP Model" begin 51 | result = run_opf("../test/data/matpower/case14.m", ACPPowerModel, ipopt_solver) 52 | 53 | @test result["status"] == :LocalOptimal 54 | @test isapprox(result["objective"], 8081.5; atol = 1e0) 55 | #@test result["status"] = bus_name 56 | end 57 | @testset "DC Model" begin 58 | result = run_opf("../test/data/matpower/case14.m", DCPPowerModel, ipopt_solver) 59 | 60 | @test result["status"] == :LocalOptimal 61 | @test isapprox(result["objective"], 7642.6; atol = 1e0) 62 | end 63 | @testset "QC Model" begin 64 | result = run_opf("../test/data/matpower/case14.m", QCWRPowerModel, ipopt_solver) 65 | 66 | @test result["status"] == :LocalOptimal 67 | @test isapprox(result["objective"], 8075.1; atol = 1e0) 68 | end 69 | end 70 | 71 | 72 | @testset "test matpower extentions parser" begin 73 | @testset "3-bus extended constants" begin 74 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 75 | 76 | @test data["const_int"] == 123 77 | @test data["const_float"] == 4.56 78 | @test data["const_str"] == "a string" 79 | @test isa(JSON.json(data), String) 80 | end 81 | 82 | @testset "3-bus extended matrix" begin 83 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 84 | 85 | @test haskey(data, "areas") 86 | @test data["areas"]["1"]["col_1"] == 1 87 | @test data["areas"]["1"]["col_2"] == 1 88 | @test data["areas"]["2"]["col_1"] == 2 89 | @test data["areas"]["2"]["col_2"] == 3 90 | @test isa(JSON.json(data), String) 91 | end 92 | 93 | @testset "3-bus extended named matrix" begin 94 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 95 | 96 | @test haskey(data, "areas_named") 97 | @test data["areas_named"]["1"]["area"] == 4 98 | @test data["areas_named"]["1"]["refbus"] == 5 99 | @test data["areas_named"]["2"]["area"] == 5 100 | @test data["areas_named"]["2"]["refbus"] == 6 101 | @test isa(JSON.json(data), String) 102 | end 103 | 104 | @testset "3-bus extended predefined matrix" begin 105 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 106 | 107 | @test haskey(data, "areas_named") 108 | @test data["branch"]["1"]["rate_i"] == 50.2 109 | @test data["branch"]["1"]["rate_p"] == 45 110 | @test data["branch"]["2"]["rate_i"] == 36 111 | @test data["branch"]["2"]["rate_p"] == 60.1 112 | @test data["branch"]["3"]["rate_i"] == 12 113 | @test data["branch"]["3"]["rate_p"] == 30 114 | @test isa(JSON.json(data), String) 115 | end 116 | 117 | @testset "3-bus extended matrix from cell" begin 118 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 119 | 120 | @test haskey(data, "areas_cells") 121 | @test data["areas_cells"]["1"]["col_1"] == "Area 1" 122 | @test data["areas_cells"]["1"]["col_2"] == 123 123 | @test data["areas_cells"]["1"]["col_4"] == "Slack \\\"Bus\\\" 1" 124 | @test data["areas_cells"]["1"]["col_5"] == 1.23 125 | @test data["areas_cells"]["2"]["col_1"] == "Area 2" 126 | @test data["areas_cells"]["2"]["col_2"] == 456 127 | @test data["areas_cells"]["2"]["col_4"] == "Slack Bus 3" 128 | @test data["areas_cells"]["2"]["col_5"] == 4.56 129 | @test isa(JSON.json(data), String) 130 | end 131 | 132 | @testset "3-bus extended named matrix from cell" begin 133 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 134 | 135 | @test haskey(data, "areas_named_cells") 136 | @test data["areas_named_cells"]["1"]["area_name"] == "Area 1" 137 | @test data["areas_named_cells"]["1"]["area"] == 123 138 | @test data["areas_named_cells"]["1"]["area2"] == 987 139 | @test data["areas_named_cells"]["1"]["refbus_name"] == "Slack Bus 1" 140 | @test data["areas_named_cells"]["1"]["refbus"] == 1.23 141 | @test data["areas_named_cells"]["2"]["area_name"] == "Area 2" 142 | @test data["areas_named_cells"]["2"]["area"] == 456 143 | @test data["areas_named_cells"]["2"]["area2"] == 987 144 | @test data["areas_named_cells"]["2"]["refbus_name"] == "Slack Bus 3" 145 | @test data["areas_named_cells"]["2"]["refbus"] == 4.56 146 | @test isa(JSON.json(data), String) 147 | end 148 | 149 | @testset "3-bus extended predefined matrix from cell" begin 150 | data = PowerModels.parse_file("../test/data/matpower/case3.m") 151 | 152 | @test haskey(data, "areas_named") 153 | @test data["branch"]["1"]["name"] == "Branch 1" 154 | @test data["branch"]["1"]["number_id"] == 123 155 | @test data["branch"]["2"]["name"] == "Branch 2" 156 | @test data["branch"]["2"]["number_id"] == 456 157 | @test data["branch"]["3"]["name"] == "Branch 3" 158 | @test data["branch"]["3"]["number_id"] == 789 159 | @test isa(JSON.json(data), String) 160 | end 161 | 162 | @testset "3-bus tnep case" begin 163 | data = PowerModels.parse_file("../test/data/matpower/case3_tnep.m") 164 | 165 | @test haskey(data, "ne_branch") 166 | @test data["ne_branch"]["1"]["f_bus"] == 1 167 | @test data["ne_branch"]["1"]["construction_cost"] == 1 168 | @test isa(JSON.json(data), String) 169 | end 170 | 171 | @testset "`build_ref` for 3-bus tnep case" begin 172 | data = PowerModels.parse_file("../test/data/matpower/case3_tnep.m") 173 | ref = PowerModels.build_ref(data) 174 | 175 | @assert !(data["multinetwork"]) 176 | ref = ref[:nw][0] 177 | 178 | @test haskey(data, "name") 179 | @test haskey(ref, :name) 180 | @test data["name"] == ref[:name] 181 | end 182 | end 183 | --------------------------------------------------------------------------------