diff --git a/src/discount.jl b/src/discount.jl index 5677cf6..c2e20ac 100644 --- a/src/discount.jl +++ b/src/discount.jl @@ -56,9 +56,13 @@ end Calculates the discount factor to be used for a time period `t` using a fixed 'discount_rate`. There are two types of discounting -available, either discounting to the start of the time period -or calculating an approximate value for the average discount factor -over the whole time period (`type="avg"`). +available, either discounting to the start of the strategic period +containing the time period (`type="start"`) or calculating an approximate +value for the average discount factor over the whole strategic period. +The average can be calculated either as a continuous average (`type="avg"`) or +as a discrete average that discounts to the start of each year (`type="avg_year"`). +The `timeunit_to_year` parameter is used to convert the time units of +strategic periods in the time structure to years (default value = 1.0). """ function discount( t::TimePeriod, @@ -77,15 +81,14 @@ function discount(disc::Discounter, t::TimePeriod; type = "start", timeunit_to_y end function discount_avg(discount_rate, start_year, duration_years) - if discount_rate > 0 - δ = 1 / (1 + discount_rate) - m = - (δ^start_year - δ^(start_year + duration_years)) / log(1 + discount_rate) / - duration_years - return m - else - return 1.0 - end + δ = 1 / (1 + discount_rate) + return (δ^start_year - δ^(start_year + duration_years)) / log(1 + discount_rate) / + duration_years +end + +function discount_avg_year(discount_rate, start_year, duration_years) + δ = 1 / (1 + discount_rate) + return sum(δ^(start_year + i) for i in 0:(duration_years-1)) / duration_years end function discount_start(discount_rate, start_year) @@ -100,14 +103,19 @@ function discount( type = "start", timeunit_to_year = 1.0, ) - start_year = _to_year(_start_strat(sp, ts), timeunit_to_year) - duration_years = _to_year(duration_strat(sp), timeunit_to_year) - - if type == "start" - return discount_start(discount_rate, start_year) - elseif type == "avg" - return discount_avg(discount_rate, start_year, duration_years) + discount_factor = 1.0 + if discount_rate > 0 + start_year = _to_year(_start_strat(sp, ts), timeunit_to_year) + duration_years = _to_year(duration_strat(sp), timeunit_to_year) + if type == "start" + discount_factor = discount_start(discount_rate, start_year) + elseif type == "avg" + discount_factor = discount_avg(discount_rate, start_year, duration_years) + elseif type == "avg_year" + discount_factor = discount_avg_year(discount_rate, start_year, duration_years) + end end + return discount_factor end """ @@ -115,7 +123,14 @@ end Returns an overall weight to be used for a time period `t` in the objective function considering both discounting, -probability and possible multiplicity. +probability and possible multiplicity. There are two types of discounting +available, either discounting to the start of the strategic period +containing the time period (`type="start"`) or calculating an approximate +value for the average discount factor over the whole strategic period. +The average can be calculated either as a continuous average (`type="avg"`) or +as a discrete average that discounts to the start of each year (`type="avg_year"`). +The `timeunit_to_year` parameter is used to convert the time units of +strategic periods in the time structure to years (default value = 1.0). """ function objective_weight( t::TimePeriod, diff --git a/test/runtests.jl b/test/runtests.jl index 23e4704..565751c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1335,15 +1335,30 @@ end @test discount(disc, t) == δ^(i - 1) end + @test sum( + discount(sp, uniform_years, 0.06; type = "avg_year") for + sp in strat_periods(uniform_years) + ) ≈ 7.8017 atol = 1e-3 + @test sum(objective_weight(t, disc) for t in uniform_years) ≈ 8.435 atol = 1e-3 uniform_day = SimpleTimes(24, 1) - periods = TwoLevel(10, 8760, uniform_day) + periods = TwoLevel(10, 5 * 8760, uniform_day) + + @test sum( + objective_weight(sp, periods, 0.04; timeunit_to_year = 1 / 8760, type = "start") for + sp in strat_periods(periods) + ) ≈ 4.825 atol = 1e-3 + + @test sum( + objective_weight(sp, periods, 0.04; timeunit_to_year = 1 / 8760, type = "avg_year") + for sp in strat_periods(periods) + ) ≈ 4.468 atol = 1e-3 @test sum( - objective_weight(sp, periods, 0.04; timeunit_to_year = 1 / 8760) for + objective_weight(sp, periods, 0.04; timeunit_to_year = 1 / 8760, type = "avg") for sp in strat_periods(periods) - ) ≈ 8.435 atol = 1e-3 + ) ≈ 4.382 atol = 1e-3 uniform_day = SimpleTimes(24, 1u"hr") periods_unit = TwoLevel(10, 365.125u"d", uniform_day)