utils¶
This module contains utility functions for the model.
Here, we determine factors to covert future value to present value for costs and benefits. To account for the variable factor, fixed factor, and capital factor, we need to convert all future costs to their net present value. This means adjusting for the time value of money so that all costs are expressed in terms of today's dollars.
We also assume that variable cost and fixed cost for non-modelled years are assumed to be equal to the cost of the last modelled year preceding them. This allows for consistent comparison across different time periods and technologies.
Variable Factor
Given the following:
Variable cost of modeled year: \(B\)
Discount rate: \(r\)
\(m\)-th modeled year: \(m = y - y_\text{min}\)
Depreciation periods: \(n\)
The total present value can be calculated as follows:
And we can calculate the variable factor as follows:
Fixed Factor
We can equate the fixed factor with the variable factor as follows:
Investment Factor
Given the following:
Weighted Average Cost of Capital (WACC, or otherwise known as the interest rate): \(i\)
Discount rate: \(r\)
\(m\)-th modeled year: \(m = y - y_\text{min}\)
Length of \(m\)-th planning periods: \(k\)
The total present value can be calculated as follows:
From the above, we can solve for the annualized cost of depreciation periods, \(A\), as:
The capital recovery factor is then calculated as:
Let's focus on the time periods that fall within the modelled time horizon (indicated in black colour). We can calculate the length of time periods, \(k\), as follows:
Using \(k\), we can calculate the net present value as follows:
And we can calculate the investment factor as follows:
- prepshot.utils.calc_cost_factor(discount_rate, modeled_year, year_min, next_modeled_year)[source]¶
Compute the variable and fixed cost factor while considering the multi-stage planning horizon.
- Parameters
discount_rate (float) -- The discount rate to apply.
modeled_year (int) -- The year in which the cost occurs.
year_min (int) -- The first year of the planning horizon. All costs are discounted to this year.
next_modeled_year (int) -- The subsequent modeled year. The cost incurred bewteen modeled_year and modeled_year and next_modeled_year is calculated.
- Returns
The computed cost factor.
- Return type
float
- Raises
ValueError -- if next_modeled_year < modeled_year.
Examples
Given annual cost incurred in 2025, next_modeled_year = 2030, and starting year = 2020, compute present value in 2020 of the cost incurred in 2025-2029:
>>> calc_cost_factor(0.05, 2025, 2020, 2030) 3.561871
- prepshot.utils.calc_interest_rate(public_debt_ratio, private_debt_ratio, cost_of_public_debt, cost_of_private_equity, cost_of_private_debt)[source]¶
Weighted-average cost of capital for a single project.
Combines public-debt, private-debt and equity tranches into a single project-level interest rate that the investment cost factor uses to discount construction outlays. Equity ratio is the residual
1 - public_debt_ratio - private_debt_ratio.- Parameters
public_debt_ratio (float) -- Share of project capital financed by public debt, in [0, 1].
private_debt_ratio (float) -- Share financed by private debt, in [0, 1].
cost_of_public_debt (float) -- Annual interest rate on the public-debt tranche.
cost_of_private_equity (float) -- Required annual return on the equity tranche.
cost_of_private_debt (float) -- Annual interest rate on the private-debt tranche.
- Returns
Weighted-average interest rate for the project.
- Return type
float
- Raises
ValueError -- If any of the three ratios is negative or their sum exceeds 1.
- prepshot.utils.calc_inv_cost_factor(dep_period, interest_rate, year_built, discount_rate, year_min, year_max)[source]¶
Compute the investment cost factor. When the depreciation period is greater than the planning horizon, the investment cost factor is calculated by only considering the period within the planning horizon.
- Parameters
dep_period (int) -- Depreciation period, in years, i.e., lifetime of the infrastructure.
interest_rate (float) -- Interest rate.
year_built (int) -- Year of investment.
discount_rate (float) -- Discount rate.
year_min (int) -- Minimum year, i.e., the first year of the planning horizon.
year_max (int) -- Maximum year, i.e., the last year of the planning horizon.
- Returns
Investment cost factor.
- Return type
float
- Raises
ValueError -- If year_max <= year_min, year_max < year_built, or year_built < year_min.
Examples
Given a depreciation period of 20 years, interest rate of 0.05, year of investment in 2025, discount rate of 0.05, planning horizon from 2020 to 2050, compute the investment cost factor:
>>> calc_inv_cost_factor(20, 0.05, 2025, 0.05, 2020, 2050) 0.783526
If the depreciation perios is 100 years, compute the investment cost factor for the same scenario:
>>> calc_inv_cost_factor(100, 0.05, 2025, 0.05, 2020, 2050) 0.567482
- prepshot.utils.cartesian_product(*args)[source]¶
Generate cartesian product of input iterables.
- Parameters
args (List[Union[int, str]]) -- Iterables to be combined.
- Returns
List of tuples representing the Cartesian product.
- Return type
List[Tuple[Union[int, str]]]
Examples
Combine two lists [1, 2] and [7, 8]:
>>> cartesian_product([1, 2], [7, 8]) [(1, 7), (1, 8), (2, 7), (2, 8)]
- prepshot.utils.check_positive(*values)[source]¶
Ensure all values are greater than 0.
- Parameters
values (Union[int, float]) -- Values to be checked.
- Raises
ValueError -- If any value is less than or equal to 0.
- Return type
None
- prepshot.utils.interpolate_z_by_q_or_s(name, qs, zqv)[source]¶
Interpolate forebay water level (Z) by reservoir storage (S) or tailrace water level (Z) by the reservoir outflow (Q).
- Parameters
name (str) -- Code of the hydropower station.
qs (Union[np.ndarray, float]) -- Reservoir storage or outflow values.
zqv (pandas.DataFrame) -- DataFrame of ZQ or ZV values.
- Returns
Interpolated values.
- Return type
Union[np.ndarray, float]
- prepshot.utils.sparse_tupledict(index_iter, rule)[source]¶
Like
poi.make_tupledictbut iterates an explicit list of multi-dim keys instead of a Cartesian product of axes.The stock
poi.make_tupledict(I, J, K, rule=...)callsrule(*coord)overlen(I)*len(J)*len(K)tuples and routes every tuple throughflatten_tuple(one call) plus anisinstancecheck (per element). For dense, structurally full grids that's the right thing. For PREP-SHOT's(h, m, y, z, te)-style grids though, the (z, te) sub-axis is overwhelmingly sparse -- a thermal unit lives at exactly one bus, so 99% of the (z, te) pairs are 0-by-construction. Walking those pairs through the rule is wasted work.This helper takes a pre-built iterable of keys (each key is the full multi-dim tuple, e.g.
(h, m, y, z, te)) and avoids the Cartesian / flatten overhead. It otherwise behaves likemake_tupledict: returns apoi.tupledict(so.select()still works), and skips entries whose rule returnsNone.- Parameters
index_iter (iterable of tuple) -- Each element is a complete multi-dim key. Single-element keys may be passed as a bare value rather than a 1-tuple.
rule (callable) -- Called as
rule(*key)per key.
- Returns
Mapping
key -> rule(*key)for keys whose rule returned a non-None value.- Return type
poi.tupledict