From 835bbe4aaa968e6cb6e1d1aa62c5814d2ca39b57 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 17 Mar 2024 14:39:12 -0600 Subject: [PATCH 01/10] add solve call --- .github/workflows/performance_comparison.yml | 16 ++++++++++++++++ test/performance/performance_test.jl | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/.github/workflows/performance_comparison.yml b/.github/workflows/performance_comparison.yml index a946c87002..f51c97a444 100644 --- a/.github/workflows/performance_comparison.yml +++ b/.github/workflows/performance_comparison.yml @@ -33,6 +33,14 @@ jobs: body="${body//$'\n'/'%0A'}" body="${body//$'\r'/'%0D'}" echo "::set-output name=body::$body" + - name: Read solve results + id: solve_results + run: | + body="$(cat solve_time.txt)" + body="${body//'%'/'%25'}" + body="${body//$'\n'/'%0A'}" + body="${body//$'\r'/'%0D'}" + echo "::set-output name=body::$body" - name: Find Comment uses: peter-evans/find-comment@v1 id: fc @@ -54,6 +62,10 @@ jobs: | Version | Build Time | | :--- | :----: | ${{ steps.build_results.outputs.body }} + + | Version | Solve Time | + | :--- | :----: | + ${{ steps.solve_results.outputs.body }} - name: Update comment if: steps.fc.outputs.comment-id != '' uses: peter-evans/create-or-update-comment@v1 @@ -69,4 +81,8 @@ jobs: | :--- | :----: | ${{ steps.build_results.outputs.body }} + | Version | Build Time | + | :--- | :----: | + ${{ steps.solve_results.outputs.body }} + edit-mode: replace diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 9d62bc281d..2ad553b056 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -133,6 +133,20 @@ try write(io, "| $(ARGS[1])- Build Time $name | FAILED TO TEST |\n") end end + + solve_out, time_solve, _, _ = execute!(sim; enable_progress_bar = false) + + if solve_out == PSI.RunStatus.SUCCESSFUL + name = i > 1 ? "Postcompile" : "Precompile" + open("solve_time.txt", "a") do io + write(io, "| $(ARGS[1])-Solve Time $name | $(time_solve) |\n") + end + else + open("solve_time.txt", "a") do io + write(io, "| $(ARGS[1])- Solve Time $name | FAILED TO TEST |\n") + end + end + end catch e rethrow(e) From 60acdc0be1da79d92015b4e363013394659f3559 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 17 Mar 2024 14:52:20 -0600 Subject: [PATCH 02/10] add gap stop --- test/performance/performance_test.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 2ad553b056..3f792f87e6 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -49,7 +49,7 @@ try ) template_ed = deepcopy(template_uc) - set_device_model!(template_ed, ThermalMultiStart, ThermalStandardDispatch) + set_device_model!(template_ed, ThermalMultiStart, ThermalBasicDispatch) set_device_model!(template_ed, ThermalStandard, ThermalBasicDispatch) set_device_model!(template_ed, HydroDispatch, HydroDispatchRunOfRiver) set_device_model!(template_ed, HydroEnergyReservoir, HydroDispatchRunOfRiver) @@ -64,7 +64,8 @@ try template_uc, sys_rts_da; name = "UC", - optimizer = optimizer_with_attributes(HiGHS.Optimizer), + optimizer = optimizer_with_attributes(HiGHS.Optimizer, + "mip_rel_gap" => 0.01), system_to_file = false, initialize_model = true, optimizer_solve_log_print = true, @@ -75,7 +76,8 @@ try template_ed, sys_rts_rt; name = "ED", - optimizer = optimizer_with_attributes(HiGHS.Optimizer), + optimizer = optimizer_with_attributes(HiGHS.Optimizer, + "mip_rel_gap" => 0.01), system_to_file = false, initialize_model = true, check_numerical_bounds = false, @@ -146,7 +148,6 @@ try write(io, "| $(ARGS[1])- Solve Time $name | FAILED TO TEST |\n") end end - end catch e rethrow(e) From 19f614d28c88d756f2c7c91596525c5fc6cd6ccb Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:22:47 -0700 Subject: [PATCH 03/10] update performance test code --- test/performance/performance_test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 3f792f87e6..42a6f0e255 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -136,7 +136,7 @@ try end end - solve_out, time_solve, _, _ = execute!(sim; enable_progress_bar = false) + solve_out, time_solve, _, _ = @timed execute!(sim; enable_progress_bar = false) if solve_out == PSI.RunStatus.SUCCESSFUL name = i > 1 ? "Postcompile" : "Precompile" From b8af24a9bb016edbe2dfea3b68795821b9f485b6 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:39:39 -0700 Subject: [PATCH 04/10] refactor datasets for emulator --- src/core/dataset.jl | 2 +- src/simulation/hdf_simulation_store.jl | 78 ++++++-------------------- 2 files changed, 19 insertions(+), 61 deletions(-) diff --git a/src/core/dataset.jl b/src/core/dataset.jl index f263dfb711..a087455870 100644 --- a/src/core/dataset.jl +++ b/src/core/dataset.jl @@ -313,6 +313,6 @@ end function set_value!(s::HDF5Dataset, vals, index::Int) # Temporary while there is no implementation of caching of em_data - _write_dataset!(s.values, vals, index:index) + _write_dataset!(s.values, vals, index) return end diff --git a/src/simulation/hdf_simulation_store.jl b/src/simulation/hdf_simulation_store.jl index 09007a7b07..8643ab5f01 100644 --- a/src/simulation/hdf_simulation_store.jl +++ b/src/simulation/hdf_simulation_store.jl @@ -507,7 +507,7 @@ function _read_result( #end columns = get_column_names(key, dataset) data = permutedims(data) - @assert_op size(data)[2] == length(columns) + @assert_op size(data)[2] == length(columns[1]) @assert_op size(data)[1] == 1 return data, columns end @@ -644,41 +644,15 @@ function write_result!( key::OptimizationContainerKey, index::EmulationModelIndexType, simulation_time::Dates.DateTime, - data::Array{Float64}, + data::DenseAxisArray, ) dataset = _get_em_dataset(store, key) - _write_dataset!(dataset.values, data, index) + _write_dataset!(dataset.values, to_matrix(data), index) set_last_recorded_row!(dataset, index) set_update_timestamp!(dataset, simulation_time) return end -function write_result!( - store::HdfSimulationStore, - model_name::Symbol, - key::OptimizationContainerKey, - index::EmulationModelIndexType, - simulation_time::Dates.DateTime, - data::DenseAxisArray{Float64, 2}, -) - data_array = Array{Float64, 3}(undef, size(data)[1], size(data)[2], 1) - data_array[:, :, 1] = data - write_result!(store, model_name, key, index, simulation_time, data_array) - return -end - -function write_result!( - store::HdfSimulationStore, - model_name::Symbol, - key::OptimizationContainerKey, - index::EmulationModelIndexType, - simulation_time::Dates.DateTime, - data::DenseAxisArray{Float64, 1}, -) - write_result!(store, model_name, key, index, simulation_time, to_matrix(data)) - return -end - function _check_state(store::HdfSimulationStore) if has_dirty(store.cache) error("BUG!!! dirty cache is present at shutdown: $(store.file)") @@ -1014,60 +988,44 @@ function _read_length(::Type{OptimizerStats}, store::HdfSimulationStore) return HDF5.read(HDF5.attributes(dataset), "columns") end +# Specific data set writing function that writes decision model data. It dispatches on the index type of the dataset as a range function _write_dataset!( dataset::HDF5.Dataset, - array::Matrix{Float64}, - row_range::UnitRange{Int64}, - ::Val{3}, -) - dataset[:, 1, row_range] = array - @debug "wrote dataset" dataset row_range - return -end - -function _write_dataset!( - dataset::HDF5.Dataset, - array::Matrix{Float64}, + array::Array{Float64, 3}, row_range::UnitRange{Int64}, - ::Val{2}, ) - dataset[row_range, :] = array - @debug "wrote dataset" dataset row_range + dataset[:, :, row_range] = array + @debug "wrote dm dataset" dataset row_range return end function _write_dataset!( dataset::HDF5.Dataset, - array::Array{Float64, 3}, + array::Array{Float64, 4}, row_range::UnitRange{Int64}, - ::Val{3}, ) - dataset[row_range, :, :] = array - @debug "wrote dataset" dataset row_range - return -end - -function _write_dataset!(dataset::HDF5.Dataset, array::Array{Float64}, index::Int) - _write_dataset!(dataset, array, index:index, Val{ndims(dataset)}()) + dataset[:, :, :, row_range] = array + @debug "wrote dm dataset" dataset row_range return end +# Specific data set writing function that writes emulation model data. It dispatches on the index type of the dataset function _write_dataset!( dataset::HDF5.Dataset, - array::Array{Float64, 3}, - row_range::UnitRange{Int64}, + array::Array{Float64, 2}, + index::EmulationModelIndexType, ) - dataset[:, :, row_range] = array - @debug "wrote dataset" dataset row_range + dataset[index, :] = array + @debug "wrote em dataset" dataset index return end function _write_dataset!( dataset::HDF5.Dataset, array::Array{Float64, 4}, - row_range::UnitRange{Int64}, + index::EmulationModelIndexType, ) - dataset[:, :, :, row_range] = array - @debug "wrote dataset" dataset row_range + dataset[index, :, :] = array + @debug "wrote em dataset" dataset index return end From fe73e6daeb4634c8b1183a3551a9eee61a673296 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:55:44 -0700 Subject: [PATCH 05/10] add fix to market bid cost --- .../devices/common/objective_functions.jl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/devices_models/devices/common/objective_functions.jl b/src/devices_models/devices/common/objective_functions.jl index c5b5655136..d19cb00e4c 100644 --- a/src/devices_models/devices/common/objective_functions.jl +++ b/src/devices_models/devices/common/objective_functions.jl @@ -338,15 +338,26 @@ function _add_service_bid_cost!( start_time = initial_time, len = length(time_steps), ) - forecast_data_values = PSY.get_cost.(TimeSeries.values(forecast_data)) .* base_power + forecast_data_values = PSY.get_cost.(TimeSeries.values(forecast_data)) + # Single Price Bid + if eltype(forecast_data_values) == Float64 + data_values = forecast_data_values + # Single Price/Quantity Bid + elseif eltype(forecast_data_values) == NTuple{2, Float64} + data_values = [v[1] for v in forecast_data_values] + else + error("$(eltype(forecast_data_values)) not supported for MarketBidCost") + end + reserve_variable = get_variable(container, U(), T, PSY.get_name(service)) component_name = PSY.get_name(component) for t in time_steps add_to_objective_invariant_expression!( container, - forecast_data_values[t] * reserve_variable[component_name, t], + data_values[t] * base_power * reserve_variable[component_name, t], ) end + return end function _add_service_bid_cost!(::OptimizationContainer, ::PSY.Component, ::PSY.Service) end From b7ff501c948626a2d6ef496319daa1d82a69ec31 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 17 Mar 2024 14:39:12 -0600 Subject: [PATCH 06/10] add solve call --- .github/workflows/performance_comparison.yml | 16 ++++++++++++++++ test/performance/performance_test.jl | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/.github/workflows/performance_comparison.yml b/.github/workflows/performance_comparison.yml index a946c87002..f51c97a444 100644 --- a/.github/workflows/performance_comparison.yml +++ b/.github/workflows/performance_comparison.yml @@ -33,6 +33,14 @@ jobs: body="${body//$'\n'/'%0A'}" body="${body//$'\r'/'%0D'}" echo "::set-output name=body::$body" + - name: Read solve results + id: solve_results + run: | + body="$(cat solve_time.txt)" + body="${body//'%'/'%25'}" + body="${body//$'\n'/'%0A'}" + body="${body//$'\r'/'%0D'}" + echo "::set-output name=body::$body" - name: Find Comment uses: peter-evans/find-comment@v1 id: fc @@ -54,6 +62,10 @@ jobs: | Version | Build Time | | :--- | :----: | ${{ steps.build_results.outputs.body }} + + | Version | Solve Time | + | :--- | :----: | + ${{ steps.solve_results.outputs.body }} - name: Update comment if: steps.fc.outputs.comment-id != '' uses: peter-evans/create-or-update-comment@v1 @@ -69,4 +81,8 @@ jobs: | :--- | :----: | ${{ steps.build_results.outputs.body }} + | Version | Build Time | + | :--- | :----: | + ${{ steps.solve_results.outputs.body }} + edit-mode: replace diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 9d62bc281d..2ad553b056 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -133,6 +133,20 @@ try write(io, "| $(ARGS[1])- Build Time $name | FAILED TO TEST |\n") end end + + solve_out, time_solve, _, _ = execute!(sim; enable_progress_bar = false) + + if solve_out == PSI.RunStatus.SUCCESSFUL + name = i > 1 ? "Postcompile" : "Precompile" + open("solve_time.txt", "a") do io + write(io, "| $(ARGS[1])-Solve Time $name | $(time_solve) |\n") + end + else + open("solve_time.txt", "a") do io + write(io, "| $(ARGS[1])- Solve Time $name | FAILED TO TEST |\n") + end + end + end catch e rethrow(e) From 8f64da3bee7b201dc9c245f7ebf8dd972f589cb8 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 17 Mar 2024 14:52:20 -0600 Subject: [PATCH 07/10] add gap stop --- test/performance/performance_test.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 2ad553b056..3f792f87e6 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -49,7 +49,7 @@ try ) template_ed = deepcopy(template_uc) - set_device_model!(template_ed, ThermalMultiStart, ThermalStandardDispatch) + set_device_model!(template_ed, ThermalMultiStart, ThermalBasicDispatch) set_device_model!(template_ed, ThermalStandard, ThermalBasicDispatch) set_device_model!(template_ed, HydroDispatch, HydroDispatchRunOfRiver) set_device_model!(template_ed, HydroEnergyReservoir, HydroDispatchRunOfRiver) @@ -64,7 +64,8 @@ try template_uc, sys_rts_da; name = "UC", - optimizer = optimizer_with_attributes(HiGHS.Optimizer), + optimizer = optimizer_with_attributes(HiGHS.Optimizer, + "mip_rel_gap" => 0.01), system_to_file = false, initialize_model = true, optimizer_solve_log_print = true, @@ -75,7 +76,8 @@ try template_ed, sys_rts_rt; name = "ED", - optimizer = optimizer_with_attributes(HiGHS.Optimizer), + optimizer = optimizer_with_attributes(HiGHS.Optimizer, + "mip_rel_gap" => 0.01), system_to_file = false, initialize_model = true, check_numerical_bounds = false, @@ -146,7 +148,6 @@ try write(io, "| $(ARGS[1])- Solve Time $name | FAILED TO TEST |\n") end end - end catch e rethrow(e) From daaf2359ceb4f713a13732e89b10d02e2f207a35 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:22:47 -0700 Subject: [PATCH 08/10] update performance test code --- test/performance/performance_test.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/performance/performance_test.jl b/test/performance/performance_test.jl index 3f792f87e6..42a6f0e255 100644 --- a/test/performance/performance_test.jl +++ b/test/performance/performance_test.jl @@ -136,7 +136,7 @@ try end end - solve_out, time_solve, _, _ = execute!(sim; enable_progress_bar = false) + solve_out, time_solve, _, _ = @timed execute!(sim; enable_progress_bar = false) if solve_out == PSI.RunStatus.SUCCESSFUL name = i > 1 ? "Postcompile" : "Precompile" From e28bac0cfb51e714761c70d89a00dd195a50f06b Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:39:39 -0700 Subject: [PATCH 09/10] refactor datasets for emulator --- src/core/dataset.jl | 2 +- src/simulation/hdf_simulation_store.jl | 78 ++++++-------------------- 2 files changed, 19 insertions(+), 61 deletions(-) diff --git a/src/core/dataset.jl b/src/core/dataset.jl index f263dfb711..a087455870 100644 --- a/src/core/dataset.jl +++ b/src/core/dataset.jl @@ -313,6 +313,6 @@ end function set_value!(s::HDF5Dataset, vals, index::Int) # Temporary while there is no implementation of caching of em_data - _write_dataset!(s.values, vals, index:index) + _write_dataset!(s.values, vals, index) return end diff --git a/src/simulation/hdf_simulation_store.jl b/src/simulation/hdf_simulation_store.jl index 09007a7b07..8643ab5f01 100644 --- a/src/simulation/hdf_simulation_store.jl +++ b/src/simulation/hdf_simulation_store.jl @@ -507,7 +507,7 @@ function _read_result( #end columns = get_column_names(key, dataset) data = permutedims(data) - @assert_op size(data)[2] == length(columns) + @assert_op size(data)[2] == length(columns[1]) @assert_op size(data)[1] == 1 return data, columns end @@ -644,41 +644,15 @@ function write_result!( key::OptimizationContainerKey, index::EmulationModelIndexType, simulation_time::Dates.DateTime, - data::Array{Float64}, + data::DenseAxisArray, ) dataset = _get_em_dataset(store, key) - _write_dataset!(dataset.values, data, index) + _write_dataset!(dataset.values, to_matrix(data), index) set_last_recorded_row!(dataset, index) set_update_timestamp!(dataset, simulation_time) return end -function write_result!( - store::HdfSimulationStore, - model_name::Symbol, - key::OptimizationContainerKey, - index::EmulationModelIndexType, - simulation_time::Dates.DateTime, - data::DenseAxisArray{Float64, 2}, -) - data_array = Array{Float64, 3}(undef, size(data)[1], size(data)[2], 1) - data_array[:, :, 1] = data - write_result!(store, model_name, key, index, simulation_time, data_array) - return -end - -function write_result!( - store::HdfSimulationStore, - model_name::Symbol, - key::OptimizationContainerKey, - index::EmulationModelIndexType, - simulation_time::Dates.DateTime, - data::DenseAxisArray{Float64, 1}, -) - write_result!(store, model_name, key, index, simulation_time, to_matrix(data)) - return -end - function _check_state(store::HdfSimulationStore) if has_dirty(store.cache) error("BUG!!! dirty cache is present at shutdown: $(store.file)") @@ -1014,60 +988,44 @@ function _read_length(::Type{OptimizerStats}, store::HdfSimulationStore) return HDF5.read(HDF5.attributes(dataset), "columns") end +# Specific data set writing function that writes decision model data. It dispatches on the index type of the dataset as a range function _write_dataset!( dataset::HDF5.Dataset, - array::Matrix{Float64}, - row_range::UnitRange{Int64}, - ::Val{3}, -) - dataset[:, 1, row_range] = array - @debug "wrote dataset" dataset row_range - return -end - -function _write_dataset!( - dataset::HDF5.Dataset, - array::Matrix{Float64}, + array::Array{Float64, 3}, row_range::UnitRange{Int64}, - ::Val{2}, ) - dataset[row_range, :] = array - @debug "wrote dataset" dataset row_range + dataset[:, :, row_range] = array + @debug "wrote dm dataset" dataset row_range return end function _write_dataset!( dataset::HDF5.Dataset, - array::Array{Float64, 3}, + array::Array{Float64, 4}, row_range::UnitRange{Int64}, - ::Val{3}, ) - dataset[row_range, :, :] = array - @debug "wrote dataset" dataset row_range - return -end - -function _write_dataset!(dataset::HDF5.Dataset, array::Array{Float64}, index::Int) - _write_dataset!(dataset, array, index:index, Val{ndims(dataset)}()) + dataset[:, :, :, row_range] = array + @debug "wrote dm dataset" dataset row_range return end +# Specific data set writing function that writes emulation model data. It dispatches on the index type of the dataset function _write_dataset!( dataset::HDF5.Dataset, - array::Array{Float64, 3}, - row_range::UnitRange{Int64}, + array::Array{Float64, 2}, + index::EmulationModelIndexType, ) - dataset[:, :, row_range] = array - @debug "wrote dataset" dataset row_range + dataset[index, :] = array + @debug "wrote em dataset" dataset index return end function _write_dataset!( dataset::HDF5.Dataset, array::Array{Float64, 4}, - row_range::UnitRange{Int64}, + index::EmulationModelIndexType, ) - dataset[:, :, :, row_range] = array - @debug "wrote dataset" dataset row_range + dataset[index, :, :] = array + @debug "wrote em dataset" dataset index return end From 7648c87642d255d7a7b9fdbfc90e889af6aaca01 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Mon, 25 Mar 2024 23:55:44 -0700 Subject: [PATCH 10/10] add fix to market bid cost --- .../devices/common/objective_functions.jl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/devices_models/devices/common/objective_functions.jl b/src/devices_models/devices/common/objective_functions.jl index c5b5655136..d19cb00e4c 100644 --- a/src/devices_models/devices/common/objective_functions.jl +++ b/src/devices_models/devices/common/objective_functions.jl @@ -338,15 +338,26 @@ function _add_service_bid_cost!( start_time = initial_time, len = length(time_steps), ) - forecast_data_values = PSY.get_cost.(TimeSeries.values(forecast_data)) .* base_power + forecast_data_values = PSY.get_cost.(TimeSeries.values(forecast_data)) + # Single Price Bid + if eltype(forecast_data_values) == Float64 + data_values = forecast_data_values + # Single Price/Quantity Bid + elseif eltype(forecast_data_values) == NTuple{2, Float64} + data_values = [v[1] for v in forecast_data_values] + else + error("$(eltype(forecast_data_values)) not supported for MarketBidCost") + end + reserve_variable = get_variable(container, U(), T, PSY.get_name(service)) component_name = PSY.get_name(component) for t in time_steps add_to_objective_invariant_expression!( container, - forecast_data_values[t] * reserve_variable[component_name, t], + data_values[t] * base_power * reserve_variable[component_name, t], ) end + return end function _add_service_bid_cost!(::OptimizationContainer, ::PSY.Component, ::PSY.Service) end