diff --git a/src/core/expressions.jl b/src/core/expressions.jl index edaaa34521..f5ad354a7d 100644 --- a/src/core/expressions.jl +++ b/src/core/expressions.jl @@ -18,5 +18,7 @@ struct PTDFBranchFlow <: ExpressionType end should_write_resulting_value(::Type{<:CostExpressions}) = true should_write_resulting_value(::Type{InterfaceTotalFlow}) = true should_write_resulting_value(::Type{RawACE}) = true +should_write_resulting_value(::Type{ActivePowerBalance}) = true +should_write_resulting_value(::Type{ReactivePowerBalance}) = true convert_result_to_natural_units(::Type{InterfaceTotalFlow}) = true diff --git a/src/core/optimization_container.jl b/src/core/optimization_container.jl index cbf5b61332..e3e7f2ffb7 100644 --- a/src/core/optimization_container.jl +++ b/src/core/optimization_container.jl @@ -410,11 +410,14 @@ function _make_system_expressions!( container.expressions = Dict( ExpressionKey(ActivePowerBalance, PSY.ACBus) => _make_container_array(ac_bus_numbers, time_steps), - ExpressionKey(ActivePowerBalance, PSY.DCBus) => - _make_container_array(dc_bus_numbers, time_steps), ExpressionKey(ReactivePowerBalance, PSY.ACBus) => _make_container_array(ac_bus_numbers, time_steps), ) + + if !isempty(dc_bus_numbers) + container.expressions[ExpressionKey(ActivePowerBalance, PSY.DCBus)] = + _make_container_array(dc_bus_numbers, time_steps) + end return end @@ -434,9 +437,11 @@ function _make_system_expressions!( container.expressions = Dict( ExpressionKey(ActivePowerBalance, PSY.ACBus) => _make_container_array(ac_bus_numbers, time_steps), - ExpressionKey(ActivePowerBalance, PSY.DCBus) => - _make_container_array(dc_bus_numbers, time_steps), ) + if !isempty(dc_bus_numbers) + container.expressions[ExpressionKey(ActivePowerBalance, PSY.DCBus)] = + _make_container_array(dc_bus_numbers, time_steps) + end return end @@ -473,13 +478,16 @@ function _make_system_expressions!( container.expressions = Dict( ExpressionKey(ActivePowerBalance, PSY.System) => _make_container_array(subnetworks, time_steps), - ExpressionKey(ActivePowerBalance, PSY.DCBus) => - _make_container_array(dc_bus_numbers, time_steps), ExpressionKey(ActivePowerBalance, PSY.ACBus) => # Bus numbers are sorted to guarantee consistency in the order between the # containers _make_container_array(sort!(ac_bus_numbers), time_steps), ) + + if !isempty(dc_bus_numbers) + container.expressions[ExpressionKey(ActivePowerBalance, PSY.DCBus)] = + _make_container_array(dc_bus_numbers, time_steps) + end return end @@ -518,41 +526,29 @@ function _make_system_expressions!( else ac_bus_numbers = collect(keys(bus_reduction_map)) end + container.expressions = Dict( + # Enforces the balance by Area + ExpressionKey(ActivePowerBalance, PSY.Area) => + _make_container_array(PSY.get_name.(areas), time_steps), + # Keeps track of the Injections by bus. + ExpressionKey(ActivePowerBalance, PSY.ACBus) => + # Bus numbers are sorted to guarantee consistency in the order between the + # containers + _make_container_array(sort!(ac_bus_numbers), time_steps), + ) + if length(subnetworks) > 1 @warn "The system contains $(length(subnetworks)) synchronous regions. \ When combined with AreaPTDFPowerModel, the model can be infeasible if the data doesn't \ have a well defined topology" subnetworks_ref_buses = collect(keys(subnetworks)) - container.expressions = Dict( - # Enforces the balance by Area - ExpressionKey(ActivePowerBalance, PSY.Area) => - _make_container_array(PSY.get_name.(areas), time_steps), - # Enforces the balance by Synchronous System - ExpressionKey(ActivePowerBalance, PSY.System) => - _make_container_array(subnetworks_ref_buses, time_steps), - # Enforces the balance by DC Buses - ExpressionKey(ActivePowerBalance, PSY.DCBus) => - _make_container_array(dc_bus_numbers, time_steps), - # Keeps track of the Injections by bus. - ExpressionKey(ActivePowerBalance, PSY.ACBus) => - # Bus numbers are sorted to guarantee consistency in the order between the - # containers - _make_container_array(sort!(ac_bus_numbers), time_steps), - ) - else - container.expressions = Dict( - # Enforces the balance by Area - ExpressionKey(ActivePowerBalance, PSY.Area) => - _make_container_array(PSY.get_name.(areas), time_steps), - # Enforces the balance by DC Buses - ExpressionKey(ActivePowerBalance, PSY.DCBus) => - _make_container_array(dc_bus_numbers, time_steps), - # Keeps track of the Injections by bus. - ExpressionKey(ActivePowerBalance, PSY.ACBus) => - # Bus numbers are sorted to guarantee consistency in the order between the - # containers - _make_container_array(sort!(ac_bus_numbers), time_steps), - ) + container.expressions[ExpressionKey(ActivePowerBalance, PSY.System)] = + _make_container_array(subnetworks_ref_buses, time_steps) + end + + if !isempty(dc_bus_numbers) + container.expressions[ExpressionKey(ActivePowerBalance, PSY.DCBus)] = + _make_container_array(dc_bus_numbers, time_steps) end return @@ -799,8 +795,6 @@ function solve_impl!(container::OptimizationContainer, system::PSY.System) end end - status = RunStatus.SUCCESSFULLY_FINALIZED - _, optimizer_stats.timed_calculate_aux_variables = @timed calculate_aux_variables!(container, system) @@ -809,6 +803,9 @@ function solve_impl!(container::OptimizationContainer, system::PSY.System) _, optimizer_stats.timed_calculate_dual_variables = @timed calculate_dual_variables!(container, system, is_milp(container)) + + status = RunStatus.SUCCESSFULLY_FINALIZED + return status end diff --git a/test/test_model_decision.jl b/test/test_model_decision.jl index e8a72c2db1..1958c0bda3 100644 --- a/test/test_model_decision.jl +++ b/test/test_model_decision.jl @@ -64,7 +64,7 @@ end @test length(read_variables(res)) == 4 @test length(read_parameters(res)) == 1 @test length(read_duals(res)) == 0 - @test length(read_expressions(res)) == 1 + @test length(read_expressions(res)) == 2 @test read_variables(res, ["StartVariable__ThermalStandard"])["StartVariable__ThermalStandard"] == read_variable(res, "StartVariable__ThermalStandard") @test read_variables(res, [(StartVariable, ThermalStandard)])["StartVariable__ThermalStandard"] == @@ -347,7 +347,7 @@ end # Manually Multiply by the base power var1_a has natural units and export writes directly from the solver @test var1_a[:, propertynames(var1_a) .!= :DateTime] == var4 .* 100.0 - @test length(readdir(IS.Optimization.export_realized_results(results1))) === 6 + @test length(readdir(IS.Optimization.export_realized_results(results1))) === 7 end @testset "Test Numerical Stability of Constraints" begin diff --git a/test/test_simulation_partitions.jl b/test/test_simulation_partitions.jl index 1a6ea26e8d..ec65bd7275 100644 --- a/test/test_simulation_partitions.jl +++ b/test/test_simulation_partitions.jl @@ -93,7 +93,7 @@ end skip && continue r_sum = 0 p_sum = 0 - atol = occursin("ProductionCostExpression", key) ? 11000 : 0 + atol = occursin("ProductionCostExpression", key) ? 11000 : 1e-6 for i in 2:ncol(rdf) r_sum += sum(rdf[!, i]) p_sum += sum(pdf[!, i]) diff --git a/test/test_simulation_results.jl b/test/test_simulation_results.jl index 21f69c6b60..d3ec744777 100644 --- a/test/test_simulation_results.jl +++ b/test/test_simulation_results.jl @@ -276,7 +276,7 @@ function test_simulation_results( @test isempty(results) verify_export_results(results, export_path) - @test length(readdir(export_realized_results(results_ed))) === 17 + @test length(readdir(export_realized_results(results_ed))) === 18 # Test that you can't read a failed simulation. PSI.set_simulation_status!(sim, PSI.RunStatus.FAILED) @@ -738,7 +738,7 @@ function test_emulation_problem_results(results::SimulationResults, in_memory) end expressions_keys = collect(keys(read_realized_expressions(results_em))) - @test length(expressions_keys) == 3 + @test length(expressions_keys) == 4 expressions_inputs = ( [ "ProductionCostExpression__HydroEnergyReservoir",