muse2/simulation/investment/appraisal/
costs.rs

1//! Costs for the optimisation problem.
2use crate::asset::{AssetRef, AssetState};
3use crate::finance::annual_capital_cost;
4use crate::simulation::prices::ReducedCosts;
5use crate::time_slice::TimeSliceID;
6use crate::units::{MoneyPerActivity, MoneyPerCapacity, Year};
7
8/// Calculates the cost per unit of activity for an asset.
9pub fn activity_cost(
10    asset: &AssetRef,
11    reduced_costs: &ReducedCosts,
12    time_slice: TimeSliceID,
13) -> MoneyPerActivity {
14    reduced_costs.get(asset, &time_slice)
15}
16
17/// Calculates the surplus per unit of activity for an asset.
18pub fn activity_surplus(
19    asset: &AssetRef,
20    reduced_costs: &ReducedCosts,
21    time_slice: TimeSliceID,
22) -> MoneyPerActivity {
23    -reduced_costs.get(asset, &time_slice)
24}
25
26/// Calculates the annual fixed costs per unit of capacity for an asset.
27///
28/// The behaviour depends on whether the asset is commissioned or a candidate:
29/// - For a commissioned asset, this only includes operating costs.
30/// - For a candidate asset, this includes both operating and capital costs.
31pub fn annual_fixed_cost(asset: &AssetRef) -> MoneyPerCapacity {
32    match asset.state() {
33        AssetState::Commissioned { .. } => annual_fixed_cost_for_existing(asset),
34        AssetState::Candidate => annual_fixed_cost_for_candidate(asset),
35        _ => {
36            panic!("annual_fixed_cost should only be called with Commissioned or Candidate assets")
37        }
38    }
39}
40
41fn annual_fixed_cost_for_existing(asset: &AssetRef) -> MoneyPerCapacity {
42    let fixed_operating_cost = asset.process_parameter().fixed_operating_cost;
43    fixed_operating_cost * Year(1.0)
44}
45
46fn annual_capital_cost_for_candidate(asset: &AssetRef) -> MoneyPerCapacity {
47    let capital_cost = asset.process_parameter().capital_cost;
48    let lifetime = asset.process_parameter().lifetime;
49    let discount_rate = asset.process_parameter().discount_rate;
50    annual_capital_cost(capital_cost, lifetime, discount_rate)
51}
52
53fn annual_fixed_cost_for_candidate(asset: &AssetRef) -> MoneyPerCapacity {
54    let fixed_operating_cost = asset.process_parameter().fixed_operating_cost;
55    let annual_fixed_operating_cost = fixed_operating_cost * Year(1.0);
56    let capital_costs = annual_capital_cost_for_candidate(asset);
57    annual_fixed_operating_cost + capital_costs
58}