diff --git a/psy5/Project.toml b/psy5/Project.toml new file mode 100644 index 0000000..e711f56 --- /dev/null +++ b/psy5/Project.toml @@ -0,0 +1,24 @@ +[deps] +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +HydroPowerSimulations = "fc1677e0-6ad7-4515-bf3a-bd6bf20a0b1b" +InfrastructureSystems = "2cd47ed4-ca9b-11e9-27f2-ab636a7671f1" +Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +JuMP = "4076af6c-e467-56ae-b986-b466b2749572" +PowerFlows = "94fada2c-fd9a-4e89-8d82-81405f5cb4f6" +PowerModels = "c36e90e8-916a-50a6-bd94-075b64ef4655" +PowerNetworkMatrices = "bed98974-b02a-5e2f-9fe0-a103f5c450dd" +PowerSimulations = "e690365d-45e2-57bb-ac84-44ba829e73c4" +PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd" +TimeSeries = "9e3dc215-6440-5c97-bce1-76c03772f85e" +Xpress = "9e70acf3-d6c9-5be6-b5bd-4e2c73e3e054" + +[compat] +HydroPowerSimulations = "0.13" +InfrastructureSystems = "3" +PowerFlows = "0.13" +PowerNetworkMatrices = "0.17" +PowerSimulations = "0.32" +PowerSystems = "5" diff --git a/psy5/acopf-cats-system-demo.jl b/psy5/acopf-cats-system-demo.jl new file mode 100644 index 0000000..ea2e225 --- /dev/null +++ b/psy5/acopf-cats-system-demo.jl @@ -0,0 +1,136 @@ +# needed to add this due to quirks of my local Xpress installation. +ENV["XPRESSDIR"] = "/Users/lkiernan/Documents/Xpress" + +# right now SynchronousCondenserBasicDispatch isn't implement on main. Remove Pkg.add line +# once https://github.com/NREL-Sienna/PowerSimulations.jl/pull/1507 is merged. +using Pkg +Pkg.add(url="https://github.com/NREL-Sienna/PowerSimulations.jl.git", rev="rh/add_syncon_model") +using PowerSimulations + +using HydroPowerSimulations +using Ipopt +using Xpress +using Dates +using JuMP +using PowerFlows +using PowerNetworkMatrices + +const PSI = PowerSimulations + + +# git clone https://github.com/NREL-Sienna/CATS-CaliforniaTestSystem/tree/lk/redo-Sienna-scripts-rebase +# make sure you're on the branch lk/redo-Sienna-scripts-rebase +CATS_DIR = "/Users/lkiernan/Documents/julia/CATS-project-2/CATS-CaliforniaTestSystem/Sienna/" +include(joinpath(CATS_DIR, "build_CATS.jl")) +# with quadratic cost functions, first time step's optimization problem takes 30+ minutes. +# worth looking into replacing quadratic costs with piecewise linear approximations. +system = build_CATS_system(first_order = true) + + +transform_single_time_series!( + system, + Hour(1), # horizon + Hour(1), # interval +); +const PNM = PowerNetworkMatrices + +# PSI has a hard-coded assumption that parallel lines have identical impedances. +# will open PR to remove that assumption. +arc_to_line_impedance = Dict{Tuple{Int, Int}, ComplexF64}() +for line in get_components(Line, system) + arc = get_arc(line) + arc_tuple = (arc.from.number, arc.to.number) + if haskey(arc_to_line_impedance, arc_tuple) + set_r!(line, real(arc_to_line_impedance[arc_tuple])) + set_x!(line, imag(arc_to_line_impedance[arc_tuple])) + else + @assert !haskey(arc_to_line_impedance, reverse(arc_tuple)) + end + arc_to_line_impedance[arc_tuple] = get_r(line) + im * get_x(line) +end + +# UC PTDF +template_uc = ProblemTemplate( + NetworkModel(PTDFPowerModel; + use_slacks=true, + duals=[CopperPlateBalanceConstraint] + ) +) + +set_device_model!(template_uc, ThermalStandard, ThermalBasicUnitCommitment) +set_device_model!(template_uc, RenewableDispatch, RenewableFullDispatch) +set_device_model!(template_uc, HydroDispatch, HydroDispatchRunOfRiver) +set_device_model!(template_uc, PowerLoad, StaticPowerLoad) +set_device_model!(template_uc, Line, StaticBranch) +set_device_model!(template_uc, Transformer2W, StaticBranch) +solver_xpress = JuMP.optimizer_with_attributes(Xpress.Optimizer, "MIPRELSTOP" => 0.01, "MAXTIME" => 60*60) + +problem_uc = DecisionModel( + template_uc, + system; + optimizer=solver_xpress, + optimizer_solve_log_print=true, + calculate_conflict=true, + name="UC" +) + +# ED ACOPF +network_model_ed = NetworkModel(ACPPowerModel; use_slacks=true, power_flow_evaluation = PowerFlows.ACPowerFlow(; calculate_loss_factors=true, calculate_voltage_stability_factors = true)) +template_ed = ProblemTemplate(network_model_ed) +set_device_model!(template_ed, ThermalStandard, ThermalBasicDispatch) +set_device_model!(template_ed, RenewableDispatch, RenewableFullDispatch) +set_device_model!(template_ed, HydroDispatch, HydroDispatchRunOfRiver) +set_device_model!(template_ed, PowerLoad, StaticPowerLoad) +set_device_model!(template_ed, Line, StaticBranchUnbounded) +set_device_model!(template_ed, Transformer2W, StaticBranchUnbounded) +set_device_model!(template_ed, SynchronousCondenser, SynchronousCondenserBasicDispatch) + +solver_ipopt = JuMP.optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 3) +problem_ed = DecisionModel( + template_ed, + system; + optimizer = solver_ipopt, + optimizer_solve_log_print = true, + name = "ED" +) + +models = SimulationModels(; + decision_models = [ + problem_uc, + problem_ed, + ], +) + +sequence = SimulationSequence(; + models = models, + feedforwards = Dict( + "ED" => [ + SemiContinuousFeedforward(; + component_type = ThermalStandard, + source = OnVariable, + affected_values = [ActivePowerVariable], + ), + ], + ), + ini_cond_chronology = InterProblemChronology(), +) + +sim = Simulation(; + name = "no_cache", + steps = 5, # adjust appropriately. Runtime is 1-2 minutes per time step. + models = models, + sequence = sequence, + simulation_folder = mktempdir(), +) + + +build!(sim) +execute!(sim) + +results_sim = SimulationResults(sim) +results_ed = get_decision_problem_results(results_sim, "ED") + +# first time step fails to converge, so showing results from second time step +read_aux_variable(results_ed, "PowerFlowLossFactors__ACBus")[DateTime("2019-01-01T01:00:00")] +read_aux_variable(results_ed, "PowerFlowVoltageStabilityFactors__ACBus")[DateTime("2019-01-01T01:00:00")] +