Quick Start Guide
Installation
The latest stable release of GasPowerModels can be installed using the Julia package manager with
] add GasPowerModels
For the current development version, install the package using
] add GasPowerModels#master
Finally, test that the package works as expected by executing
] test GasPowerModels
Installation of Optimization Solvers
At least one optimization solver is required to run GasPowerModels. The solver selected typically depends on the type of problem formulation being employed. As an example, the mixed-integer nonlinear programming solver Juniper can be used for testing any of the problem formulations considered in this package. Juniper itself depends on the installation of a nonlinear programming solver (e.g., Ipopt) and a mixed-integer linear programming solver (e.g., CBC). Installation of the JuMP interfaces to Juniper, Ipopt, and CBC can be performed via the Julia package manager, i.e.,
] add JuMP Juniper Ipopt Cbc
Solving a Problem
Once the above dependencies have been installed, obtain the files GasLib-11-NE.m
, case5-NE.m
, and GasLib-11-case5.json
. Here, GasLib-11-NE.m
is a MATGAS file describing a small GasLib network. In accord, case5-NE.m
is a MATPOWER file specifying a five-bus power network. Finally, GasLib-11-case5.json
is a JSON file specifying interdependencies between the two networks. The combination of data from these three files provides the required information to set up the problem. After downloading the data, the optimal power flow with network expansion (ne_opf
) problem can be solved with
using JuMP, Juniper, Ipopt, Cbc
using GasPowerModels
# Set up the optimization solvers.
ipopt = JuMP.optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0, "sb" => "yes")
cbc = JuMP.optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
juniper = JuMP.optimizer_with_attributes(Juniper.Optimizer, "nl_solver" => ipopt, "mip_solver" => cbc)
# Specify paths to the gas and power network files.
g_file = "test/data/matgas/GasLib-11-NE.m" # Gas network.
p_file = "test/data/matpower/case5-NE.m" # Power network.
link_file = "test/data/json/GasLib-11-case5.json" # Linking data.
# Specify the gas-power formulation type.
gpm_type = GasPowerModel{CRDWPGasModel, SOCWRPowerModel}
# Solve the optimal power flow with network expansion problem.
result = run_ne_opf(g_file, p_file, link_file, gpm_type, juniper;
solution_processors = [GasPowerModels._GM.sol_psqr_to_p!,
GasPowerModels._PM.sol_data_model!])
Obtaining Results
The run
commands in GasPowerModels return detailed results data in the form of a Julia Dict
. This dictionary can be saved for further processing as follows:
result = run_ne_opf(g_file, p_file, link_file, gpm_type, juniper;
solution_processors = [GasPowerModels._GM.sol_psqr_to_p!,
GasPowerModels._PM.sol_data_model!])
For example, the algorithm's runtime and final objective value can be accessed with
result["solve_time"] # Total solve time required (seconds).
result["objective"] # Final objective value (in units of the objective).
The "solution"
field contains detailed information about the solution produced by the run
method. For example, the following can be used to read the build status of the network expansion pipe in the gas system
result["solution"]["it"]["gm"]["ne_pipe"]["4"]["z"]
As another example, the following can be used to inspect pressures in the solution
Dict(name => data["p"] for (name, data) in result["solution"]["it"]["gm"]["junction"])
As a final example, the following can be used to inspect real power generation in the solution
Dict(name => data["pg"] for (name, data) in result["solution"]["it"]["pm"]["gen"])
For more information about GasPowerModels result data, see the GasPowerModels Result Data Format section.
Accessing Different Formulations
To solve the preceding problem using a mixed-integer nonconvex model for natural gas flow, the following can be executed:
# Specify the gas-power formulation type.
gpm_type = GasPowerModel{DWPGasModel, SOCWRPowerModel}
# Solve the optimal power flow with network expansion problem.
result = run_ne_opf(g_file, p_file, link_file, gpm_type, juniper;
solution_processors = [GasPowerModels._GM.sol_psqr_to_p!,
GasPowerModels._PM.sol_data_model!])
Modifying Network Data
The following example demonstrates one way to perform GasPowerModels solves while modifying network data.
# Read in the gas, power, and linking data.
data = parse_files(g_file, p_file, link_file)
# Reduce the minimum pressures at selected junctions.
data["it"]["gm"]["junction"]["1"]["p_min"] *= 0.1
data["it"]["gm"]["junction"]["2"]["p_min"] *= 0.1
data["it"]["gm"]["junction"]["3"]["p_min"] *= 0.1
# Solve the problem using `data`.
result_mod = run_ne_opf(data, gpm_type, juniper;
solution_processors = [GasPowerModels._GM.sol_psqr_to_p!,
GasPowerModels._PM.sol_data_model!])
Alternate Methods for Building and Solving Models
The following example demonstrates how to decompose a run_ne_opf
call into separate model building and solving steps. This allows for inspection of the JuMP model created by GasPowerModels:
# Read in the gas, power, and linking data.
data = parse_files(g_file, p_file, link_file)
# Store the required `ref` extensions for the problem.
ref_extensions = [GasPowerModels._GM.ref_add_ne!, ref_add_price_zones!,
GasPowerModels._PM.ref_add_on_off_va_bounds!,
GasPowerModels._PM.ref_add_ne_branch!]
# Instantiate the model.
gpm = instantiate_model(data, gpm_type, build_ne_opf, ref_extensions = ref_extensions)
# Print the contents of the JuMP model.
println(gpm.model)
The problem can then be solved and its two result dictionaries can be stored via:
# Solve the GasPowerModels problem and store the result.
result = GasPowerModels._IM.optimize_model!(gpm, optimizer = juniper)