Skip to content

Commit

Permalink
Apply review suggestions for economic representation calculation (#1130)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarskul authored Nov 19, 2024
2 parents d894790 + b330d27 commit 739baf6
Showing 1 changed file with 104 additions and 152 deletions.
256 changes: 104 additions & 152 deletions src/data_structure/economic_structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,130 +27,91 @@ function generate_economic_structure!(m; log_level=3)
elseif model_type(model=m.ext[:spineopt].instance) === :spineopt_benders
error("Using economic representation with Benders' decomposition is currently not supported.")
end
!isempty(
[
model__default_investment_temporal_block()
node__investment_temporal_block()
unit__investment_temporal_block()
connection__investment_temporal_block()
],
) || return
# use_economic_representation == true without defining investment temporal blocks will break the investment cost calculation
# in such cases, user would only need to discount operational costs manually
if isempty(model__default_investment_temporal_block()) &&
isempty(node__investment_temporal_block()) &&
isempty(unit__investment_temporal_block()) &&
isempty(connection__investment_temporal_block())
error("Using economic representation without defining investment temporal blocks is currently not supported.")
end
economic_parameters = _create_set_parameters_and_relationships()
for (obj, name) in [(unit, :unit), (node, :storage), (connection, :connection)]
@timelog log_level 3 "- [Generated discounted durations for $(obj)s]" generate_discount_timeslice_duration!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated capacity transfer factors for $(name)s]" generate_capacity_transfer_factor!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated conversion to discounted investments of $(name)s]" generate_conversion_to_discounted_annuities!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated conversion for discounted decommissioning of $(name)s]" generate_decommissioning_conversion_to_discounted_annuities!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated salvage fraction for $(name)s]" generate_salvage_fraction!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated $(name) technology specific discount factors]" generate_tech_discount_factor!(
m,
obj,
economic_parameters,
)
@timelog log_level 3 "- [Generated discounted durations for $(obj)s]" begin
generate_discount_timeslice_duration!(m, obj, economic_parameters)
end
@timelog log_level 3 "- [Generated capacity transfer factors for $(name)s]" begin
generate_capacity_transfer_factor!(m, obj, economic_parameters)
end
@timelog log_level 3 "- [Generated conversion to discounted investments of $(name)s]" begin
generate_conversion_to_discounted_annuities!(m, obj, economic_parameters)
end
@timelog log_level 3 "- [Generated conversion for discounted decommissioning of $(name)s]" begin
generate_decommissioning_conversion_to_discounted_annuities!(m, obj, economic_parameters)
end
@timelog log_level 3 "- [Generated salvage fraction for $(name)s]" begin
generate_salvage_fraction!(m, obj, economic_parameters)
end
@timelog log_level 3 "- [Generated $(name) technology specific discount factors]" begin
generate_tech_discount_factor!(m, obj, economic_parameters)
end
end
end

function _create_set_parameters_and_relationships()
economic_parameters = Dict(
# defined outside this file
# indices
:set_investment_indices => Dict(
unit => units_invested_available_indices,
node => storages_invested_available_indices,
connection => connections_invested_available_indices,
),
# relationships
:set_invest_temporal_block => Dict(
unit => unit__investment_temporal_block,
node => node__investment_temporal_block,
connection => connection__investment_temporal_block,
),
:set_invest_stoch_struct => Dict(
unit => unit__investment_stochastic_structure,
node => node__investment_stochastic_structure,
connection => connection__investment_stochastic_structure,
unit => Dict(
:set_investment_indices => units_invested_available_indices,
:set_invest_temporal_block => unit__investment_temporal_block,
:set_invest_stoch_struct => unit__investment_stochastic_structure,
:set_lead_time => unit_lead_time,
:set_tech_lifetime => unit_investment_tech_lifetime,
:set_econ_lifetime => unit_investment_econ_lifetime,
:set_discnt_rate_tech => unit_discount_rate_technology_specific,
:set_decom_time => unit_decommissioning_time,
:set_decom_cost => unit_decommissioning_cost,
:set_capacity_transfer_factor => :unit_capacity_transfer_factor,
:set_conversion_to_discounted_annuities => :unit_conversion_to_discounted_annuities,
:set_salvage_fraction => :unit_salvage_fraction,
:set_tech_discount_factor => :unit_tech_discount_factor,
:set_discounted_duration => :unit_discounted_duration,
:set_decommissioning_conversion_to_discounted_annuities => :unit_decommissioning_conversion_to_discounted_annuities,
),
# parameters
:set_lead_time =>
Dict(unit => unit_lead_time, node => storage_lead_time, connection => connection_lead_time),
:set_tech_lifetime => Dict(
unit => unit_investment_tech_lifetime,
node => storage_investment_tech_lifetime,
connection => connection_investment_tech_lifetime,
),
:set_econ_lifetime => Dict(
unit => unit_investment_econ_lifetime,
node => storage_investment_econ_lifetime,
connection => connection_investment_econ_lifetime,
),
:set_discnt_rate_tech => Dict(
unit => unit_discount_rate_technology_specific,
node => storage_discount_rate_technology_specific,
connection => connection_discount_rate_technology_specific,
),
:set_decom_time => Dict(
unit => unit_decommissioning_time,
node => storage_decommissioning_time,
connection => connection_decommissioning_time,
),
:set_decom_cost => Dict(
unit => unit_decommissioning_cost,
node => storage_decommissioning_cost,
connection => connection_decommissioning_cost,
),
# internally calculated parameters in this file
:set_capacity_transfer_factor => Dict(
unit => :unit_capacity_transfer_factor,
node => :storage_capacity_transfer_factor,
connection => :connection_capacity_transfer_factor,
),
:set_conversion_to_discounted_annuities => Dict(
unit => :unit_conversion_to_discounted_annuities,
node => :storage_conversion_to_discounted_annuities,
connection => :connection_conversion_to_discounted_annuities,
),
:set_salvage_fraction => Dict(
unit => :unit_salvage_fraction,
node => :storage_salvage_fraction,
connection => :connection_salvage_fraction,
),
:set_tech_discount_factor => Dict(
unit => :unit_tech_discount_factor,
node => :storage_tech_discount_factor,
connection => :connection_tech_discount_factor,
),
:set_discounted_duration => Dict(
unit => :unit_discounted_duration,
node => :storage_discounted_duration,
connection => :connection_discounted_duration,
),
:set_decommissioning_conversion_to_discounted_annuities => Dict(
unit => :unit_decommissioning_conversion_to_discounted_annuities,
node => :storage_decommissioning_conversion_to_discounted_annuities,
connection => :connection_decommissioning_conversion_to_discounted_annuities,
node => Dict(
:set_investment_indices => storages_invested_available_indices,
:set_invest_temporal_block => node__investment_temporal_block,
:set_invest_stoch_struct => node__investment_stochastic_structure,
:set_lead_time => storage_lead_time,
:set_tech_lifetime => storage_investment_tech_lifetime,
:set_econ_lifetime => storage_investment_econ_lifetime,
:set_discnt_rate_tech => storage_discount_rate_technology_specific,
:set_decom_time => storage_decommissioning_time,
:set_decom_cost => storage_decommissioning_cost,
:set_capacity_transfer_factor => :storage_capacity_transfer_factor,
:set_conversion_to_discounted_annuities => :storage_conversion_to_discounted_annuities,
:set_salvage_fraction => :storage_salvage_fraction,
:set_tech_discount_factor => :storage_tech_discount_factor,
:set_discounted_duration => :storage_discounted_duration,
:set_decommissioning_conversion_to_discounted_annuities => :storage_decommissioning_conversion_to_discounted_annuities,
),
connection => Dict(
:set_investment_indices => connections_invested_available_indices,
:set_invest_temporal_block => connection__investment_temporal_block,
:set_invest_stoch_struct => connection__investment_stochastic_structure,
:set_lead_time => connection_lead_time,
:set_tech_lifetime => connection_investment_tech_lifetime,
:set_econ_lifetime => connection_investment_econ_lifetime,
:set_discnt_rate_tech => connection_discount_rate_technology_specific,
:set_decom_time => connection_decommissioning_time,
:set_decom_cost => connection_decommissioning_cost,
:set_capacity_transfer_factor => :connection_capacity_transfer_factor,
:set_conversion_to_discounted_annuities => :connection_conversion_to_discounted_annuities,
:set_salvage_fraction => :connection_salvage_fraction,
:set_tech_discount_factor => :connection_tech_discount_factor,
:set_discounted_duration => :connection_discounted_duration,
:set_decommissioning_conversion_to_discounted_annuities => :connection_decommissioning_conversion_to_discounted_annuities,
)
)
return economic_parameters
end

"""
Expand All @@ -163,11 +124,11 @@ year t_v in a unit u that is still available in the model year t.
function generate_capacity_transfer_factor!(m::Model, obj_cls::ObjectClass, economic_parameters::Dict)
instance = m.ext[:spineopt].instance
capacity_transfer_factor = Dict()
investment_indices = economic_parameters[:set_investment_indices][obj_cls]
lead_time = economic_parameters[:set_lead_time][obj_cls]
tech_lifetime = economic_parameters[:set_tech_lifetime][obj_cls]
invest_temporal_block = economic_parameters[:set_invest_temporal_block][obj_cls]
param_name = economic_parameters[:set_capacity_transfer_factor][obj_cls]
investment_indices = economic_parameters[obj_cls][:set_investment_indices]
lead_time = economic_parameters[obj_cls][:set_lead_time]
tech_lifetime = economic_parameters[obj_cls][:set_tech_lifetime]
invest_temporal_block = economic_parameters[obj_cls][:set_invest_temporal_block]
param_name = economic_parameters[obj_cls][:set_capacity_transfer_factor]

for id in invest_temporal_block(temporal_block=anything)
if (
Expand All @@ -190,10 +151,7 @@ function generate_capacity_transfer_factor!(m::Model, obj_cls::ObjectClass, econ
)...,
)
map_indices = []
count = 0 # count the element; this is to avoid using collect
for _ in investment_indices_vector
count += 1
end
count = length(collect(investment_indices_vector))
sizehint!(map_indices, count)
timeseries_array = []
sizehint!(timeseries_array, count)
Expand Down Expand Up @@ -279,10 +237,10 @@ function generate_conversion_to_discounted_annuities!(m::Model, obj_cls::ObjectC
instance = m.ext[:spineopt].instance
discnt_year = discount_year(model=instance)
conversion_to_discounted_annuities = Dict()
investment_indices = economic_parameters[:set_investment_indices][obj_cls]
lead_time = economic_parameters[:set_lead_time][obj_cls]
econ_lifetime = economic_parameters[:set_econ_lifetime][obj_cls]
param_name = economic_parameters[:set_conversion_to_discounted_annuities][obj_cls] # this is MARKUP^AN
investment_indices = economic_parameters[obj_cls][:set_investment_indices]
lead_time = economic_parameters[obj_cls][:set_lead_time]
econ_lifetime = economic_parameters[obj_cls][:set_econ_lifetime]
param_name = economic_parameters[obj_cls][:set_conversion_to_discounted_annuities] # this is MARKUP^AN

for id in obj_cls()
if (discount_rate(model=model()[1]) == 0 || isnothing(discount_rate(model=model()[1])))
Expand All @@ -296,10 +254,7 @@ function generate_conversion_to_discounted_annuities!(m::Model, obj_cls::ObjectC
for s in stochastic_map_vector
time_series_vector = investment_indices(m; Dict(obj_cls.name => id, :stochastic_scenario => s)...)
timeseries_ind = []
count = 0 # count the element; this is to avoid using collect
for _ in time_series_vector
count += 1
end
count = length(collect(time_series_vector))
sizehint!(timeseries_ind, count)
timeseries_val = []
sizehint!(timeseries_val, count)
Expand Down Expand Up @@ -406,11 +361,11 @@ function generate_salvage_fraction!(m::Model, obj_cls::ObjectClass, economic_par
discnt_year = discount_year(model=instance)
p_eoh = model_end(model=instance)
salvage_fraction = Dict()
investment_indices = economic_parameters[:set_investment_indices][obj_cls]
lead_time = economic_parameters[:set_lead_time][obj_cls]
econ_lifetime = economic_parameters[:set_econ_lifetime][obj_cls]
invest_temporal_block = economic_parameters[:set_invest_temporal_block][obj_cls]
param_name = economic_parameters[:set_salvage_fraction][obj_cls]
investment_indices = economic_parameters[obj_cls][:set_investment_indices]
lead_time = economic_parameters[obj_cls][:set_lead_time]
econ_lifetime = economic_parameters[obj_cls][:set_econ_lifetime]
invest_temporal_block = economic_parameters[obj_cls][:set_invest_temporal_block]
param_name = economic_parameters[obj_cls][:set_salvage_fraction]

for id in invest_temporal_block(temporal_block=anything)
if id in indices(econ_lifetime)
Expand Down Expand Up @@ -476,11 +431,11 @@ Generate technology-specific discount factors for investments (e.g., for risky i
"""
function generate_tech_discount_factor!(m::Model, obj_cls::ObjectClass, economic_parameters::Dict)
instance = m.ext[:spineopt].instance
investment_indices = economic_parameters[:set_investment_indices][obj_cls]
econ_lifetime = economic_parameters[:set_econ_lifetime][obj_cls]
discnt_rate_tech = economic_parameters[:set_discnt_rate_tech][obj_cls]
invest_stoch_struct = economic_parameters[:set_invest_stoch_struct][obj_cls]
param_name = economic_parameters[:set_tech_discount_factor][obj_cls]
investment_indices = economic_parameters[obj_cls][:set_investment_indices]
econ_lifetime = economic_parameters[obj_cls][:set_econ_lifetime]
discnt_rate_tech = economic_parameters[obj_cls][:set_discnt_rate_tech]
invest_stoch_struct = economic_parameters[obj_cls][:set_invest_stoch_struct]
param_name = economic_parameters[obj_cls][:set_tech_discount_factor]

for id in obj_cls()
if (
Expand Down Expand Up @@ -536,9 +491,9 @@ function generate_discount_timeslice_duration!(m::Model, obj_cls::ObjectClass, e
instance = m.ext[:spineopt].instance
discnt_year = discount_year(model=instance)
discounted_duration = Dict()
invest_stoch_struct = economic_parameters[:set_invest_stoch_struct][obj_cls]
invest_temporal_block = economic_parameters[:set_invest_temporal_block][obj_cls]
param_name = economic_parameters[:set_discounted_duration][obj_cls]
invest_stoch_struct = economic_parameters[obj_cls][:set_invest_stoch_struct]
invest_temporal_block = economic_parameters[obj_cls][:set_invest_temporal_block]
param_name = economic_parameters[obj_cls][:set_discounted_duration]

if use_milestone_years(model=instance)
for id in obj_cls()
Expand Down Expand Up @@ -604,10 +559,7 @@ function create_discounted_duration(m; stochastic_scenario=nothing, invest_tempo
time_slice(m; temporal_block=invest_temporal_block),
TimeSlice(last_timestep, last_timestep),
))
count = 0 # count the element; this is to avoid using collect
for _ in timeseries_vector
count += 1
end
count = length(collect(timeseries_vector)) # count the element; this is to avoid using collect
timeseries_ind = []
sizehint!(timeseries_ind, count)
timeseries_val = []
Expand Down Expand Up @@ -643,10 +595,10 @@ function generate_decommissioning_conversion_to_discounted_annuities!(
instance = m.ext[:spineopt].instance
discnt_year = discount_year(model=instance)
decommissioning_conversion_to_discounted_annuities = Dict()
investment_indices = economic_parameters[:set_investment_indices][obj_cls]
decom_time = economic_parameters[:set_decom_time][obj_cls]
decom_cost = economic_parameters[:set_decom_cost][obj_cls]
param_name = economic_parameters[:set_decommissioning_conversion_to_discounted_annuities][obj_cls]
investment_indices = economic_parameters[obj_cls][:set_investment_indices]
decom_time = economic_parameters[obj_cls][:set_decom_time]
decom_cost = economic_parameters[obj_cls][:set_decom_cost]
param_name = economic_parameters[obj_cls][:set_decommissioning_conversion_to_discounted_annuities]

for id in indices(decom_cost)
stochastic_map_vector = unique([x.stochastic_scenario for x in investment_indices(m)])
Expand Down

0 comments on commit 739baf6

Please sign in to comment.