Skip to content

Commit 9aa44e6

Browse files
committed
Better docstrings
1 parent 9c167dd commit 9aa44e6

1 file changed

Lines changed: 76 additions & 27 deletions

File tree

src/simulation/prices.rs

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn calculate_prices(model: &Model, solution: &Solution, year: u32) -> Result
165165
// Add prices for full cost commodities
166166
if let Some(fullcost_set) = pricing_sets.get(&PricingStrategy::FullCost) {
167167
let annual_activities = annual_activities.get_or_insert_with(|| {
168-
calculate_annual_activities(solution.iter_activity_for_existing())
168+
iter_annual_activities(solution.iter_activity_for_existing())
169169
});
170170
add_full_cost_prices(
171171
solution.iter_activity_for_existing(),
@@ -182,7 +182,7 @@ pub fn calculate_prices(model: &Model, solution: &Solution, year: u32) -> Result
182182
// Add prices for full average commodities
183183
if let Some(full_avg_set) = pricing_sets.get(&PricingStrategy::FullCostAverage) {
184184
let annual_activities = annual_activities.get_or_insert_with(|| {
185-
calculate_annual_activities(solution.iter_activity_for_existing())
185+
iter_annual_activities(solution.iter_activity_for_existing())
186186
});
187187
add_full_cost_average_prices(
188188
solution.iter_activity_for_existing(),
@@ -487,7 +487,7 @@ fn add_marginal_cost_prices<'a, I, J>(
487487
J: Iterator<Item = (&'a AssetRef, &'a TimeSliceID)>,
488488
{
489489
// Calculate marginal cost prices from existing assets
490-
let mut group_prices: IndexMap<_, _> = calculate_existing_asset_prices(
490+
let mut group_prices: IndexMap<_, _> = iter_existing_asset_max_prices(
491491
activity_for_existing,
492492
markets_to_price,
493493
existing_prices,
@@ -501,7 +501,7 @@ fn add_marginal_cost_prices<'a, I, J>(
501501

502502
// Calculate marginal cost prices from candidate assets, skipping any groups already covered by
503503
// existing assets
504-
let cand_group_prices = calculate_candidate_asset_prices(
504+
let cand_group_prices = iter_candidate_asset_min_prices(
505505
activity_keys_for_candidates,
506506
markets_to_price,
507507
existing_prices,
@@ -518,19 +518,29 @@ fn add_marginal_cost_prices<'a, I, J>(
518518
existing_prices.extend_selection_prices(&group_prices, time_slice_info);
519519
}
520520

521-
/// Calculate prices using existing assets, taking a weighted average across time slices for
522-
/// seasonal/annual commodities, and taking the max across assets for each commodity/region/selection.
521+
/// Calculate prices as the maximum cost across existing assets, using either a marginal cost or
522+
/// full cost strategy (depending on `pricing_strategy`). Prices are given for each commodity in
523+
/// the granularity of the commodity's time slice level. For seasonal/annual commodities, this
524+
/// involves taking a weighted average across time slices for each asset according to activity
525+
/// (with a backup weight based on potential activity if there is zero activity across the
526+
/// selection, and omitting prices in the extreme case of zero potential activity).
523527
///
524528
/// # Arguments
525529
///
526530
/// * `activity_for_existing` - Iterator over (asset, time slice, activity) tuples for existing assets
527-
/// * `markets_to_price` - Set of (commodity, region) pairs to price
528-
/// * `existing_prices` - Current commodity prices (used for marginal cost filtering)
531+
/// * `markets_to_price` - Set of (commodity, region) pairs to attempt to price
532+
/// * `existing_prices` - Current commodity prices (used to calculate marginal costs)
529533
/// * `year` - Year for which prices are being calculated
530534
/// * `commodities` - Commodity map
531-
/// * `pricing_strategy` - Pricing strategy (determines whether to include fixed costs)
535+
/// * `pricing_strategy` - Pricing strategy, either `MarginalCost` or `FullCost`
532536
/// * `annual_activities` - Optional annual activities (required for full cost pricing)
533-
fn calculate_existing_asset_prices<'a, I>(
537+
///
538+
/// # Returns
539+
///
540+
/// An iterator of ((commodity, region, time slice selection), price) tuples for the calculated
541+
/// prices. This will include all (commodity, region) combinations in `markets_to_price` for
542+
/// time slice selections where a price could be determined.
543+
fn iter_existing_asset_max_prices<'a, I>(
534544
activity_for_existing: I,
535545
markets_to_price: &HashSet<(CommodityID, RegionID)>,
536546
existing_prices: &CommodityPrices,
@@ -628,10 +638,32 @@ where
628638
})
629639
}
630640

631-
/// Calculate candidate-asset prices (marginal or full), taking a weighted average across time
632-
/// slices for seasonal/annual commodities, and taking the min across assets for each
633-
/// commodity/region/selection. Only groups not already covered by existing assets are considered.
634-
fn calculate_candidate_asset_prices<'a, I>(
641+
/// Calculate prices as the minimum cost across candidate assets, using either a marginal cost or
642+
/// full cost strategy (depending on `pricing_strategy`). Prices are given for each commodity in
643+
/// the granularity of the commodity's time slice level. For seasonal/annual commodities, this
644+
/// involves taking a weighted average across time slices for each asset according to potential
645+
/// activity (i.e. the upper activity limit), omitting prices in the extreme case of zero potential
646+
/// activity (Note: this should NOT happen as validation should ensure there is at least one
647+
/// candidate that can provide a price in each timeslice for which a price could be required).
648+
/// Costs for candidates are calculated assuming full utilisation.
649+
///
650+
/// # Arguments
651+
///
652+
/// * `activity_keys_for_candidates` - Iterator over (asset, time slice) tuples for candidate assets
653+
/// * `markets_to_price` - Set of (commodity, region) pairs to attempt to price
654+
/// * `existing_prices` - Current commodity prices (used to calculate marginal costs)
655+
/// * `priced_groups` - Set of (commodity, region, time slice selection) groups that have already
656+
/// been prices using existing assets, so should be skipped when looking at candidates
657+
/// * `year` - Year for which prices are being calculated
658+
/// * `commodities` - Commodity map
659+
/// * `pricing_strategy` - Pricing strategy, either `MarginalCost` or `FullCost`
660+
///
661+
/// # Returns
662+
///
663+
/// An iterator of ((commodity, region, time slice selection), price) tuples for the calculated
664+
/// prices. This will include all (commodity, region) combinations in `markets_to_price` for
665+
/// time slice selections not covered by `priced_groups`, and for which a price could be determined
666+
fn iter_candidate_asset_min_prices<'a, I>(
635667
activity_keys_for_candidates: I,
636668
markets_to_price: &HashSet<(CommodityID, RegionID)>,
637669
existing_prices: &CommodityPrices,
@@ -747,7 +779,7 @@ fn add_marginal_cost_average_prices<'a, I, J>(
747779
J: Iterator<Item = (&'a AssetRef, &'a TimeSliceID)>,
748780
{
749781
// Calculate marginal cost prices from existing assets
750-
let mut group_prices: IndexMap<_, _> = calculate_existing_asset_average_prices(
782+
let mut group_prices: IndexMap<_, _> = iter_existing_asset_average_prices(
751783
activity_for_existing,
752784
markets_to_price,
753785
existing_prices,
@@ -761,7 +793,7 @@ fn add_marginal_cost_average_prices<'a, I, J>(
761793

762794
// Calculate marginal cost prices from candidate assets, skipping any groups already covered by
763795
// existing assets
764-
let cand_group_prices = calculate_candidate_asset_prices(
796+
let cand_group_prices = iter_candidate_asset_min_prices(
765797
activity_keys_for_candidates,
766798
markets_to_price,
767799
existing_prices,
@@ -778,12 +810,29 @@ fn add_marginal_cost_average_prices<'a, I, J>(
778810
existing_prices.extend_selection_prices(&group_prices, time_slice_info);
779811
}
780812

781-
/// Calculate average prices for existing assets using a weighted average across time slices for
782-
/// seasonal/annual commodities, and a weighted average across assets according to output (with a
783-
/// backup weight based on potential output if there is zero activity across the selection).
813+
/// Calculate prices as the load-weighted average cost across existing assets, using either a
814+
/// marginal cost or full cost strategy (depending on `pricing_strategy`). Prices are given for each
815+
/// commodity in the granularity of the commodity's time slice level. For seasonal/annual
816+
/// commodities, this involves taking a weighted average across time slices for each asset according
817+
/// to activity (with a backup weight based on potential activity if there is zero activity across
818+
/// the selection, and omitting prices in the extreme case of zero potential activity).
819+
///
820+
/// # Arguments
821+
///
822+
/// * `activity_for_existing` - Iterator over (asset, time slice, activity) tuples for existing assets
823+
/// * `markets_to_price` - Set of (commodity, region) pairs to attempt to price
824+
/// * `existing_prices` - Current commodity prices (used to calculate marginal costs)
825+
/// * `year` - Year for which prices are being calculated
826+
/// * `commodities` - Commodity map
827+
/// * `pricing_strategy` - Pricing strategy, either `MarginalCost` or `FullCost`
828+
/// * `annual_activities` - Optional annual activities (required for full cost pricing)
829+
///
830+
/// # Returns
784831
///
785-
/// `FullCost` adds annual fixed costs per flow and skips assets with zero annual activity.
786-
fn calculate_existing_asset_average_prices<'a, I>(
832+
/// An iterator of ((commodity, region, time slice selection), price) tuples for the calculated
833+
/// prices. This will include all (commodity, region) combinations in `markets_to_price` for
834+
/// time slice selections where a price could be determined.
835+
fn iter_existing_asset_average_prices<'a, I>(
787836
activity_for_existing: I,
788837
markets_to_price: &HashSet<(CommodityID, RegionID)>,
789838
existing_prices: &CommodityPrices,
@@ -883,8 +932,8 @@ where
883932
.filter_map(|(key, accum)| accum.finalise().map(|v| (key, v)))
884933
}
885934

886-
/// Calculate annual activities for each asset by summing across all time slices
887-
fn calculate_annual_activities<'a, I>(activities: I) -> HashMap<AssetRef, Activity>
935+
/// Iterate over annual activities for each asset by summing across all time slices
936+
fn iter_annual_activities<'a, I>(activities: I) -> HashMap<AssetRef, Activity>
888937
where
889938
I: IntoIterator<Item = (&'a AssetRef, &'a TimeSliceID, Activity)>,
890939
{
@@ -971,7 +1020,7 @@ fn add_full_cost_prices<'a, I, J>(
9711020
J: Iterator<Item = (&'a AssetRef, &'a TimeSliceID)>,
9721021
{
9731022
// Calculate full cost prices from existing assets
974-
let mut group_prices: IndexMap<_, _> = calculate_existing_asset_prices(
1023+
let mut group_prices: IndexMap<_, _> = iter_existing_asset_max_prices(
9751024
activity_for_existing,
9761025
markets_to_price,
9771026
existing_prices,
@@ -985,7 +1034,7 @@ fn add_full_cost_prices<'a, I, J>(
9851034

9861035
// Calculate full cost prices from candidate assets, skipping any groups already covered by
9871036
// existing assets
988-
let cand_group_prices = calculate_candidate_asset_prices(
1037+
let cand_group_prices = iter_candidate_asset_min_prices(
9891038
activity_keys_for_candidates,
9901039
markets_to_price,
9911040
existing_prices,
@@ -1025,7 +1074,7 @@ fn add_full_cost_average_prices<'a, I, J>(
10251074
J: Iterator<Item = (&'a AssetRef, &'a TimeSliceID)>,
10261075
{
10271076
// Calculate full cost prices from existing assets
1028-
let mut group_prices: IndexMap<_, _> = calculate_existing_asset_average_prices(
1077+
let mut group_prices: IndexMap<_, _> = iter_existing_asset_average_prices(
10291078
activity_for_existing,
10301079
markets_to_price,
10311080
existing_prices,
@@ -1038,7 +1087,7 @@ fn add_full_cost_average_prices<'a, I, J>(
10381087
let priced_groups: HashSet<_> = group_prices.keys().cloned().collect();
10391088

10401089
// Calculate full cost prices from candidate assets, skipping any groups already covered by existing assets
1041-
let cand_group_prices = calculate_candidate_asset_prices(
1090+
let cand_group_prices = iter_candidate_asset_min_prices(
10421091
activity_keys_for_candidates,
10431092
markets_to_price,
10441093
existing_prices,

0 commit comments

Comments
 (0)