@@ -13,13 +13,14 @@ use anyhow::{Context, Result, ensure};
1313use indexmap:: IndexMap ;
1414use itertools:: { Itertools , chain} ;
1515use log:: debug;
16- use std:: cmp:: Ordering ;
1716use std:: collections:: { HashMap , HashSet } ;
1817use std:: fmt:: Display ;
1918
2019pub mod appraisal;
2120use appraisal:: coefficients:: calculate_coefficients_for_assets;
22- use appraisal:: { AppraisalOutput , appraise_investment} ;
21+ use appraisal:: {
22+ AppraisalOutput , appraise_investment, sort_appraisal_outputs_by_investment_priority,
23+ } ;
2324
2425/// A map of demand across time slices for a specific market
2526type DemandMap = IndexMap < TimeSliceID , Flow > ;
@@ -745,16 +746,7 @@ fn select_best_assets(
745746 & outputs_for_opts,
746747 ) ?;
747748
748- // Sort assets by appraisal metric
749- let assets_sorted_by_metric = outputs_for_opts
750- . into_iter ( )
751- . filter ( |output| output. capacity . total_capacity ( ) > Capacity ( 0.0 ) )
752- . sorted_by ( |output1, output2| match output1. compare_metric ( output2) {
753- // If equal, we fall back on comparing asset properties
754- Ordering :: Equal => compare_asset_fallback ( & output1. asset , & output2. asset ) ,
755- cmp => cmp,
756- } )
757- . collect_vec ( ) ;
749+ sort_appraisal_outputs_by_investment_priority ( & mut outputs_for_opts) ;
758750
759751 // Check if all options have zero capacity. If so, we cannot meet demand, so have to bail
760752 // out.
@@ -765,20 +757,15 @@ fn select_best_assets(
765757 // - known issue with the NPV objective
766758 // (see https://github.com/EnergySystemsModellingLab/MUSE2/issues/716).
767759 ensure ! (
768- !assets_sorted_by_metric . is_empty( ) ,
760+ !outputs_for_opts . is_empty( ) ,
769761 "No feasible investment options for commodity '{}' after appraisal" ,
770762 & commodity. id
771763 ) ;
772764
773765 // Warn if there are multiple equally good assets
774- warn_on_equal_appraisal_outputs (
775- & assets_sorted_by_metric,
776- & agent. id ,
777- & commodity. id ,
778- region_id,
779- ) ;
766+ warn_on_equal_appraisal_outputs ( & outputs_for_opts, & agent. id , & commodity. id , region_id) ;
780767
781- let best_output = assets_sorted_by_metric . into_iter ( ) . next ( ) . unwrap ( ) ;
768+ let best_output = outputs_for_opts . into_iter ( ) . next ( ) . unwrap ( ) ;
782769
783770 // Log the selected asset
784771 debug ! (
@@ -819,16 +806,6 @@ fn is_any_remaining_demand(demand: &DemandMap) -> bool {
819806 demand. values ( ) . any ( |flow| * flow > Flow ( 0.0 ) )
820807}
821808
822- /// Compare assets as a fallback if metrics are equal.
823- ///
824- /// Commissioned assets are ordered before uncommissioned and newer before older.
825- ///
826- /// Used as a fallback to sort assets when they have equal appraisal tool outputs.
827- fn compare_asset_fallback ( asset1 : & Asset , asset2 : & Asset ) -> Ordering {
828- ( asset2. is_commissioned ( ) , asset2. commission_year ( ) )
829- . cmp ( & ( asset1. is_commissioned ( ) , asset1. commission_year ( ) ) )
830- }
831-
832809/// Update capacity of chosen asset, if needed, and update both asset options and chosen assets
833810fn update_assets (
834811 mut best_asset : AssetRef ,
@@ -875,15 +852,12 @@ fn update_assets(
875852#[ cfg( test) ]
876853mod tests {
877854 use super :: * ;
878- use crate :: agent:: AgentID ;
879- use crate :: asset:: Asset ;
880855 use crate :: commodity:: Commodity ;
881856 use crate :: fixture:: {
882- agent_id , asset, process, process_activity_limits_map, process_flows_map, region_id ,
883- svd_commodity , time_slice , time_slice_info, time_slice_info2,
857+ asset, process, process_activity_limits_map, process_flows_map, svd_commodity , time_slice ,
858+ time_slice_info, time_slice_info2,
884859 } ;
885860 use crate :: process:: { ActivityLimits , FlowType , Process , ProcessFlow } ;
886- use crate :: region:: RegionID ;
887861 use crate :: time_slice:: { TimeSliceID , TimeSliceInfo } ;
888862 use crate :: units:: { Capacity , Flow , FlowPerActivity , MoneyPerFlow } ;
889863 use indexmap:: indexmap;
@@ -971,32 +945,4 @@ mod tests {
971945 // Maximum = 20.0
972946 assert_eq ! ( result, Capacity ( 20.0 ) ) ;
973947 }
974-
975- #[ rstest]
976- fn compare_assets_fallback ( process : Process , region_id : RegionID , agent_id : AgentID ) {
977- let process = Rc :: new ( process) ;
978- let capacity = Capacity ( 2.0 ) ;
979- let asset1 = Asset :: new_commissioned (
980- agent_id. clone ( ) ,
981- process. clone ( ) ,
982- region_id. clone ( ) ,
983- capacity,
984- 2015 ,
985- )
986- . unwrap ( ) ;
987- let asset2 =
988- Asset :: new_candidate ( process. clone ( ) , region_id. clone ( ) , capacity, 2015 ) . unwrap ( ) ;
989- let asset3 =
990- Asset :: new_commissioned ( agent_id, process, region_id. clone ( ) , capacity, 2010 ) . unwrap ( ) ;
991-
992- assert ! ( compare_asset_fallback( & asset1, & asset1) . is_eq( ) ) ;
993- assert ! ( compare_asset_fallback( & asset2, & asset2) . is_eq( ) ) ;
994- assert ! ( compare_asset_fallback( & asset3, & asset3) . is_eq( ) ) ;
995- assert ! ( compare_asset_fallback( & asset1, & asset2) . is_lt( ) ) ;
996- assert ! ( compare_asset_fallback( & asset2, & asset1) . is_gt( ) ) ;
997- assert ! ( compare_asset_fallback( & asset1, & asset3) . is_lt( ) ) ;
998- assert ! ( compare_asset_fallback( & asset3, & asset1) . is_gt( ) ) ;
999- assert ! ( compare_asset_fallback( & asset3, & asset2) . is_lt( ) ) ;
1000- assert ! ( compare_asset_fallback( & asset2, & asset3) . is_gt( ) ) ;
1001- }
1002948}
0 commit comments