@@ -43,6 +43,14 @@ impl InvestmentSet {
4343 InvestmentSet :: Cycle ( ids) => ids. iter ( ) ,
4444 }
4545 }
46+
47+ /// Converts the investment set to a vector of commodity IDs
48+ pub fn to_vec ( & self ) -> Vec < CommodityID > {
49+ match self {
50+ InvestmentSet :: Single ( id) => vec ! [ id. clone( ) ] ,
51+ InvestmentSet :: Cycle ( ids) => ids. clone ( ) ,
52+ }
53+ }
4654}
4755
4856impl Display for InvestmentSet {
@@ -78,35 +86,39 @@ pub fn perform_agent_investment(
7886 // This includes Commissioned assets that are selected for retention, and new Selected assets
7987 let mut all_selected_assets = Vec :: new ( ) ;
8088
81- // External prices to be used in dispatch optimisation
82- // Once investments are performed for a commodity, the dispatch system will be able to produce
83- // endogenous prices for that commodity, so we'll gradually remove these external prices.
84- let mut external_prices = prices. clone ( ) ;
85-
8689 for region_id in model. iter_regions ( ) {
90+ let investment_order = & model. investment_order [ & ( region_id. clone ( ) , year) ] ;
91+
92+ // External prices to be used in dispatch optimisation
93+ // Once investments are performed for a commodity, the dispatch system will be able to produce
94+ // endogenous prices for that commodity, so we'll gradually remove these external prices.
95+ let cur_commodities: & Vec < _ > = & investment_order
96+ . iter ( )
97+ . flat_map ( InvestmentSet :: iter)
98+ . cloned ( )
99+ . collect ( ) ;
100+ let mut external_prices =
101+ get_prices_for_commodities ( prices, & model. time_slice_info , region_id, cur_commodities) ;
102+
87103 // Keep track of the commodities that have been seen so far. This will be used to apply
88104 // balance constraints in the dispatch optimisation - we only apply balance constraints for
89105 // commodities that have been seen so far.
90106 let mut seen_commodities = Vec :: new ( ) ;
91107
92108 // Iterate over investment sets in the investment order for this region/year
93- let investment_order = & model. investment_order [ & ( region_id. clone ( ) , year) ] ;
94109 for investment_set in investment_order {
95110 // Select assets for the commodity(/ies) of interest
96111 let selected_assets = match investment_set {
97- InvestmentSet :: Single ( commodity_id) => {
98- let commodity = & model. commodities [ commodity_id] ;
99- select_assets_for_commodity (
100- model,
101- commodity,
102- region_id,
103- year,
104- & demand,
105- existing_assets,
106- prices,
107- writer,
108- ) ?
109- }
112+ InvestmentSet :: Single ( commodity_id) => select_assets_for_commodity (
113+ model,
114+ commodity_id,
115+ region_id,
116+ year,
117+ & demand,
118+ existing_assets,
119+ prices,
120+ writer,
121+ ) ?,
110122 InvestmentSet :: Cycle ( _) => {
111123 bail ! (
112124 "Investment cycles are not yet supported. Found cycle for commodities: {investment_set}"
@@ -172,14 +184,16 @@ pub fn perform_agent_investment(
172184#[ allow( clippy:: too_many_arguments) ]
173185fn select_assets_for_commodity (
174186 model : & Model ,
175- commodity : & Commodity ,
187+ commodity_id : & CommodityID ,
176188 region_id : & RegionID ,
177189 year : u32 ,
178190 demand : & AllDemandMap ,
179191 existing_assets : & [ AssetRef ] ,
180192 prices : & CommodityPrices ,
181193 writer : & mut DataWriter ,
182194) -> Result < Vec < AssetRef > > {
195+ let commodity = & model. commodities [ commodity_id] ;
196+
183197 let mut selected_assets = Vec :: new ( ) ;
184198 for ( agent, commodity_portion) in
185199 get_responsible_agents ( model. agents . values ( ) , & commodity. id , region_id, year)
@@ -429,6 +443,21 @@ fn get_candidate_assets<'a>(
429443 } )
430444}
431445
446+ /// Get a map of prices for a subset of commodities
447+ fn get_prices_for_commodities (
448+ prices : & CommodityPrices ,
449+ time_slice_info : & TimeSliceInfo ,
450+ region_id : & RegionID ,
451+ commodities : & [ CommodityID ] ,
452+ ) -> CommodityPrices {
453+ iproduct ! ( commodities. iter( ) , time_slice_info. iter_ids( ) )
454+ . map ( |( commodity_id, time_slice) | {
455+ let price = prices. get ( commodity_id, region_id, time_slice) . unwrap ( ) ;
456+ ( commodity_id, region_id, time_slice, price)
457+ } )
458+ . collect ( )
459+ }
460+
432461/// Get the best assets for meeting demand for the given commodity
433462#[ allow( clippy:: too_many_arguments) ]
434463fn select_best_assets (
0 commit comments