From c8fd4853f9b6b04079c5d2e52d06a09cf8155543 Mon Sep 17 00:00:00 2001 From: datejada Date: Tue, 3 Sep 2024 16:02:19 +0200 Subject: [PATCH 1/4] Implement changes from code review --- src/run_spineopt_basic.jl | 258 ++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 136 deletions(-) diff --git a/src/run_spineopt_basic.jl b/src/run_spineopt_basic.jl index 7fa71400dc..d93911156c 100644 --- a/src/run_spineopt_basic.jl +++ b/src/run_spineopt_basic.jl @@ -658,14 +658,12 @@ function _populate_economic_parameter_values!( indices_func, value_func, entity::Symbol, - user_outputs, - key_type ) m.ext[:spineopt].values[param_name] = - Dict{key_type,Float64}( + Dict( (entity=>ind[entity], stochastic_scenario=ind[:stochastic_scenario], t=ind[:t]) => value_func(; entity=>ind[entity], stochastic_scenario=ind[:stochastic_scenario], t=ind[:t]) - for ind in indices_func(m) if param_name in user_outputs + for ind in indices_func(m) ) return nothing end @@ -677,147 +675,135 @@ function _save_economic_parameter_values!(m::Model) user_outputs = (out_name for (out_name, _ow) in keys(m.ext[:spineopt].reports_by_output)) # Units - key_type = NamedTuple{( - :unit, :stochastic_scenario, :t), - Tuple{SpineInterface.Object, SpineInterface.Object, SpineInterface.TimeSlice} - } - m.ext[:spineopt].values[:unit_salvage_fraction] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:unit_tech_discount_factor] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:unit_conversion_to_discounted_annuities] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:unit_discounted_duration] = Dict{key_type,Float64}() + m.ext[:spineopt].values[:unit_salvage_fraction] = Dict() + m.ext[:spineopt].values[:unit_tech_discount_factor] = Dict() + m.ext[:spineopt].values[:unit_conversion_to_discounted_annuities] = Dict() + m.ext[:spineopt].values[:unit_discounted_duration] = Dict() if use_economic_representation(model=m.ext[:spineopt].instance) - _populate_economic_parameter_values!( - m, - :unit_salvage_fraction, - units_invested_available_indices, - unit_salvage_fraction, - :unit, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :unit_tech_discount_factor, - units_invested_available_indices, - unit_tech_discount_factor, - :unit, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :unit_conversion_to_discounted_annuities, - units_invested_available_indices, - unit_conversion_to_discounted_annuities, - :unit, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :unit_discounted_duration, - unit_flow_indices, - unit_discounted_duration, - :unit, - user_outputs, - key_type - ) + if :unit_salvage_fraction in user_outputs + _populate_economic_parameter_values!( + m, + :unit_salvage_fraction, + units_invested_available_indices, + unit_salvage_fraction, + :unit + ) + end + if :unit_tech_discount_factor in user_outputs + _populate_economic_parameter_values!( + m, + :unit_tech_discount_factor, + units_invested_available_indices, + unit_tech_discount_factor, + :unit + ) + end + if :unit_conversion_to_discounted_annuities in user_outputs + _populate_economic_parameter_values!( + m, + :unit_conversion_to_discounted_annuities, + units_invested_available_indices, + unit_conversion_to_discounted_annuities, + :unit + ) + end + if :unit_discounted_duration in user_outputs + _populate_economic_parameter_values!( + m, + :unit_discounted_duration, + unit_flow_indices, + unit_discounted_duration, + :unit + ) + end end # Connections - key_type = NamedTuple{( - :connection, :stochastic_scenario, :t), - Tuple{SpineInterface.Object, SpineInterface.Object, SpineInterface.TimeSlice} - } - m.ext[:spineopt].values[:connection_salvage_fraction] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:connection_tech_discount_factor] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:connection_conversion_to_discounted_annuities] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:connection_discounted_duration] = Dict{key_type,Float64}() + m.ext[:spineopt].values[:connection_salvage_fraction] = Dict() + m.ext[:spineopt].values[:connection_tech_discount_factor] = Dict() + m.ext[:spineopt].values[:connection_conversion_to_discounted_annuities] = Dict() + m.ext[:spineopt].values[:connection_discounted_duration] = Dict() if use_economic_representation(model=m.ext[:spineopt].instance) - _populate_economic_parameter_values!( - m, - :connection_salvage_fraction, - connections_invested_available_indices, - connection_salvage_fraction, - :connection, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :connection_tech_discount_factor, - connections_invested_available_indices, - connection_tech_discount_factor, - :connection, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :connection_conversion_to_discounted_annuities, - connections_invested_available_indices, - connection_conversion_to_discounted_annuities, - :connection, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :connection_discounted_duration, - connection_flow_indices, - connection_discounted_duration, - :connection, - user_outputs, - key_type - ) + if :connection_salvage_fraction in user_outputs + _populate_economic_parameter_values!( + m, + :connection_salvage_fraction, + connections_invested_available_indices, + connection_salvage_fraction, + :connection + ) + end + if :connection_tech_discount_factor in user_outputs + _populate_economic_parameter_values!( + m, + :connection_tech_discount_factor, + connections_invested_available_indices, + connection_tech_discount_factor, + :connection + ) + end + if :connection_conversion_to_discounted_annuities in user_outputs + _populate_economic_parameter_values!( + m, + :connection_conversion_to_discounted_annuities, + connections_invested_available_indices, + connection_conversion_to_discounted_annuities, + :connection + ) + end + if :connection_discounted_duration in user_outputs + _populate_economic_parameter_values!( + m, + :connection_discounted_duration, + connection_flow_indices, + connection_discounted_duration, + :connection + ) + end end # Storages - key_type = NamedTuple{( - :node, :stochastic_scenario, :t), - Tuple{SpineInterface.Object, SpineInterface.Object, SpineInterface.TimeSlice} - } - m.ext[:spineopt].values[:storage_salvage_fraction] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:storage_tech_discount_factor] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:storage_conversion_to_discounted_annuities] = Dict{key_type,Float64}() - m.ext[:spineopt].values[:storage_discounted_duration] = Dict{key_type,Float64}() + m.ext[:spineopt].values[:storage_salvage_fraction] = Dict() + m.ext[:spineopt].values[:storage_tech_discount_factor] = Dict() + m.ext[:spineopt].values[:storage_conversion_to_discounted_annuities] = Dict() + m.ext[:spineopt].values[:storage_discounted_duration] = Dict() if use_economic_representation(model=m.ext[:spineopt].instance) - _populate_economic_parameter_values!( - m, - :storage_salvage_fraction, - storages_invested_available_indices, - storage_salvage_fraction, - :node, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :storage_tech_discount_factor, - storages_invested_available_indices, - storage_tech_discount_factor, - :node, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :storage_conversion_to_discounted_annuities, - storages_invested_available_indices, - storage_conversion_to_discounted_annuities, - :node, - user_outputs, - key_type - ) - _populate_economic_parameter_values!( - m, - :storage_discounted_duration, - storages_invested_available_indices, - storage_discounted_duration, - :node, - user_outputs, - key_type - ) + if :storage_salvage_fraction in user_outputs + _populate_economic_parameter_values!( + m, + :storage_salvage_fraction, + storages_invested_available_indices, + storage_salvage_fraction, + :node + ) + end + if :storage_tech_discount_factor in user_outputs + _populate_economic_parameter_values!( + m, + :storage_tech_discount_factor, + storages_invested_available_indices, + storage_tech_discount_factor, + :node + ) + end + if :storage_conversion_to_discounted_annuities in user_outputs + _populate_economic_parameter_values!( + m, + :storage_conversion_to_discounted_annuities, + storages_invested_available_indices, + storage_conversion_to_discounted_annuities, + :node + ) + end + if :storage_discounted_duration in user_outputs + _populate_economic_parameter_values!( + m, + :storage_discounted_duration, + storages_invested_available_indices, + storage_discounted_duration, + :node + ) + end end return nothing end From c08565a40e5eeca049babef2a8abcb6396d07542 Mon Sep 17 00:00:00 2001 From: datejada Date: Tue, 3 Sep 2024 17:24:03 +0200 Subject: [PATCH 2/4] Add the outputs to the test in the economic representation --- test/data_structure/check_economic_structure.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/data_structure/check_economic_structure.jl b/test/data_structure/check_economic_structure.jl index 32ef929234..b23ddc32b9 100644 --- a/test/data_structure/check_economic_structure.jl +++ b/test/data_structure/check_economic_structure.jl @@ -89,6 +89,15 @@ ["report__output", ["report_a", "unit_salvage_fraction"]], ["report__output", ["report_a", "unit_tech_discount_factor"]], ["report__output", ["report_a", "unit_conversion_to_discounted_annuities"]], + ["report__output", ["report_a", "unit_discounted_duration"]], + ["report__output", ["report_a", "connection_salvage_fraction"]], + ["report__output", ["report_a", "connection_tech_discount_factor"]], + ["report__output", ["report_a", "connection_conversion_to_discounted_annuities"]], + ["report__output", ["report_a", "connection_discounted_duration"]], + ["report__output", ["report_a", "storage_salvage_fraction"]], + ["report__output", ["report_a", "storage_tech_discount_factor"]], + ["report__output", ["report_a", "storage_conversion_to_discounted_annuities"]], + ["report__output", ["report_a", "storage_discounted_duration"]], ["model__report", ["instance", "report_a"]], ["unit__node__node", ["unit_ab", "node_a", "node_b"]], ["connection__node__node", ["connection_ab", "node_a", "node_b"]], From 1e6b7467cb077db947bb7ec7d252fd56c61fa677 Mon Sep 17 00:00:00 2001 From: datejada Date: Wed, 4 Sep 2024 16:12:10 +0200 Subject: [PATCH 3/4] Attach economic parameter to the module --- src/data_structure/economic_structure.jl | 12 +- src/run_spineopt_basic.jl | 160 ----------------------- 2 files changed, 6 insertions(+), 166 deletions(-) diff --git a/src/data_structure/economic_structure.jl b/src/data_structure/economic_structure.jl index 7e6e1bedf4..089cba9cc4 100644 --- a/src/data_structure/economic_structure.jl +++ b/src/data_structure/economic_structure.jl @@ -258,7 +258,7 @@ function generate_capacity_transfer_factor!(m::Model, obj_cls::ObjectClass, econ add_object_parameter_values!(obj_cls, Dict(id => Dict(param_name => pvals))) end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end @@ -333,7 +333,7 @@ function generate_conversion_to_discounted_annuities!(m::Model, obj_cls::ObjectC add_object_parameter_values!(obj_cls, Dict(id => Dict(param_name => pvals))) end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end @@ -460,7 +460,7 @@ function generate_salvage_fraction!(m::Model, obj_cls::ObjectClass, economic_par add_object_parameter_values!(obj_cls, Dict(id => Dict(param_name => pvals))) end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end @@ -516,7 +516,7 @@ function generate_tech_discount_factor!(m::Model, obj_cls::ObjectClass, economic add_object_parameter_values!(obj_cls, Dict(id => Dict(param_name => pvals))) end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end @@ -584,7 +584,7 @@ function generate_discount_timeslice_duration!(m::Model, obj_cls::ObjectClass, e end end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end """ @@ -683,6 +683,6 @@ function generate_decommissioning_conversion_to_discounted_annuities!( add_object_parameter_values!(obj_cls, Dict(id => Dict(param_name => pvals))) end @eval begin - $(param_name) = $(Parameter(param_name, [obj_cls])) + $(param_name) = $(Parameter(param_name, [obj_cls]; mod = @__MODULE__)) end end diff --git a/src/run_spineopt_basic.jl b/src/run_spineopt_basic.jl index d93911156c..dfe0a3fe6f 100644 --- a/src/run_spineopt_basic.jl +++ b/src/run_spineopt_basic.jl @@ -613,7 +613,6 @@ function _save_model_results!(m) _save_constraint_values!(m) _save_objective_values!(m) _save_other_values!(m) - _save_economic_parameter_values!(m) end """ @@ -649,165 +648,6 @@ function _save_other_values!(m::Model) end end -""" -Generalized function to initialize and populate economic parameter values. -""" -function _populate_economic_parameter_values!( - m::Model, - param_name::Symbol, - indices_func, - value_func, - entity::Symbol, -) - m.ext[:spineopt].values[param_name] = - Dict( - (entity=>ind[entity], stochastic_scenario=ind[:stochastic_scenario], t=ind[:t]) => - value_func(; entity=>ind[entity], stochastic_scenario=ind[:stochastic_scenario], t=ind[:t]) - for ind in indices_func(m) - ) - return nothing -end - -""" -Save the value of the economic parameters of units, connections, and storages if the user wants to report it. -""" -function _save_economic_parameter_values!(m::Model) - user_outputs = (out_name for (out_name, _ow) in keys(m.ext[:spineopt].reports_by_output)) - - # Units - m.ext[:spineopt].values[:unit_salvage_fraction] = Dict() - m.ext[:spineopt].values[:unit_tech_discount_factor] = Dict() - m.ext[:spineopt].values[:unit_conversion_to_discounted_annuities] = Dict() - m.ext[:spineopt].values[:unit_discounted_duration] = Dict() - if use_economic_representation(model=m.ext[:spineopt].instance) - if :unit_salvage_fraction in user_outputs - _populate_economic_parameter_values!( - m, - :unit_salvage_fraction, - units_invested_available_indices, - unit_salvage_fraction, - :unit - ) - end - if :unit_tech_discount_factor in user_outputs - _populate_economic_parameter_values!( - m, - :unit_tech_discount_factor, - units_invested_available_indices, - unit_tech_discount_factor, - :unit - ) - end - if :unit_conversion_to_discounted_annuities in user_outputs - _populate_economic_parameter_values!( - m, - :unit_conversion_to_discounted_annuities, - units_invested_available_indices, - unit_conversion_to_discounted_annuities, - :unit - ) - end - if :unit_discounted_duration in user_outputs - _populate_economic_parameter_values!( - m, - :unit_discounted_duration, - unit_flow_indices, - unit_discounted_duration, - :unit - ) - end - end - - # Connections - m.ext[:spineopt].values[:connection_salvage_fraction] = Dict() - m.ext[:spineopt].values[:connection_tech_discount_factor] = Dict() - m.ext[:spineopt].values[:connection_conversion_to_discounted_annuities] = Dict() - m.ext[:spineopt].values[:connection_discounted_duration] = Dict() - if use_economic_representation(model=m.ext[:spineopt].instance) - if :connection_salvage_fraction in user_outputs - _populate_economic_parameter_values!( - m, - :connection_salvage_fraction, - connections_invested_available_indices, - connection_salvage_fraction, - :connection - ) - end - if :connection_tech_discount_factor in user_outputs - _populate_economic_parameter_values!( - m, - :connection_tech_discount_factor, - connections_invested_available_indices, - connection_tech_discount_factor, - :connection - ) - end - if :connection_conversion_to_discounted_annuities in user_outputs - _populate_economic_parameter_values!( - m, - :connection_conversion_to_discounted_annuities, - connections_invested_available_indices, - connection_conversion_to_discounted_annuities, - :connection - ) - end - if :connection_discounted_duration in user_outputs - _populate_economic_parameter_values!( - m, - :connection_discounted_duration, - connection_flow_indices, - connection_discounted_duration, - :connection - ) - end - end - - # Storages - m.ext[:spineopt].values[:storage_salvage_fraction] = Dict() - m.ext[:spineopt].values[:storage_tech_discount_factor] = Dict() - m.ext[:spineopt].values[:storage_conversion_to_discounted_annuities] = Dict() - m.ext[:spineopt].values[:storage_discounted_duration] = Dict() - if use_economic_representation(model=m.ext[:spineopt].instance) - if :storage_salvage_fraction in user_outputs - _populate_economic_parameter_values!( - m, - :storage_salvage_fraction, - storages_invested_available_indices, - storage_salvage_fraction, - :node - ) - end - if :storage_tech_discount_factor in user_outputs - _populate_economic_parameter_values!( - m, - :storage_tech_discount_factor, - storages_invested_available_indices, - storage_tech_discount_factor, - :node - ) - end - if :storage_conversion_to_discounted_annuities in user_outputs - _populate_economic_parameter_values!( - m, - :storage_conversion_to_discounted_annuities, - storages_invested_available_indices, - storage_conversion_to_discounted_annuities, - :node - ) - end - if :storage_discounted_duration in user_outputs - _populate_economic_parameter_values!( - m, - :storage_discounted_duration, - storages_invested_available_indices, - storage_discounted_duration, - :node - ) - end - end - return nothing -end - """ Save the value of all constraints if the user wants to report it. """ From 29d120a24a9e1bd273db646208720c3e271e58b5 Mon Sep 17 00:00:00 2001 From: datejada Date: Wed, 4 Sep 2024 16:49:08 +0200 Subject: [PATCH 4/4] Fix economic parameter tests --- test/data_structure/check_economic_structure.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/data_structure/check_economic_structure.jl b/test/data_structure/check_economic_structure.jl index b23ddc32b9..67fe60c557 100644 --- a/test/data_structure/check_economic_structure.jl +++ b/test/data_structure/check_economic_structure.jl @@ -266,17 +266,15 @@ ["unit", "unit_ab", "unit_investment_econ_lifetime", Dict("type" => "duration", "data" => "5Y")], ] SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) - # here `optimize = true` so we can also test the outputs of new parameters - m = run_spineopt(url_in; optimize=true, log_level=1) - values = m.ext[:spineopt].values + m = run_spineopt(url_in; optimize=false, log_level=1) u_ts = [ind.t for ind in units_invested_available_indices(m; unit=unit(:unit_ab))] - key_param = (unit=unit(:unit_ab),stochastic_scenario=stochastic_scenario(:parent),t=u_ts[1]) + key_param = Dict(unit.name => unit(:unit_ab), stochastic_scenario.name => stochastic_scenario(:parent)) tech_fac = 2.189728888 salvage_frac = 0.370998336 conv_to_disc_annuities = 0.613913254 - @test salvage_frac ≈ values[:unit_salvage_fraction][key_param] rtol = 1e-6 - @test tech_fac ≈ values[:unit_tech_discount_factor][key_param] rtol = 1e-6 - @test conv_to_disc_annuities ≈ values[:unit_conversion_to_discounted_annuities][key_param] rtol = 1e-6 + @test salvage_frac ≈ SpineOpt.unit_salvage_fraction(; key_param..., t=u_ts[1]) rtol = 1e-6 + @test tech_fac ≈ SpineOpt.unit_tech_discount_factor(; key_param..., t=u_ts[1]) rtol = 1e-6 + @test conv_to_disc_annuities ≈ SpineOpt.unit_conversion_to_discounted_annuities(; key_param..., t=u_ts[1]) rtol = 1e-6 units_invested = m.ext[:spineopt].variables[:units_invested] observed_coe_obj = coefficient(objective_function(m), units_invested[unit(:unit_ab), stochastic_scenario(:parent), u_ts[1]]) expected_coe_obj = (1 - salvage_frac) * conv_to_disc_annuities * tech_fac * inv_cost