11//! Code for updating the simulation state.
22use super :: optimisation:: Solution ;
3- use crate :: asset:: AssetPool ;
43use crate :: commodity:: CommodityID ;
54use crate :: model:: Model ;
65use crate :: region:: RegionID ;
76use crate :: time_slice:: { TimeSliceID , TimeSliceInfo } ;
87use log:: warn;
9- use std:: collections:: { BTreeMap , HashSet } ;
8+ use std:: collections:: { BTreeMap , HashMap , HashSet } ;
109
1110/// A map relating commodity ID + region + time slice to current price (endogenous)
1211#[ derive( Default ) ]
@@ -16,9 +15,9 @@ impl CommodityPrices {
1615 /// Calculate commodity prices based on the result of the dispatch optimisation.
1716 ///
1817 /// Missing prices will be calculated directly from the input data
19- pub fn from_model_and_solution ( model : & Model , solution : & Solution , assets : & AssetPool ) -> Self {
18+ pub fn from_model_and_solution ( model : & Model , solution : & Solution ) -> Self {
2019 let mut prices = CommodityPrices :: default ( ) ;
21- let commodity_regions_updated = prices. add_from_solution ( solution, assets ) ;
20+ let commodity_regions_updated = prices. add_from_solution ( solution) ;
2221
2322 // Find commodity/region combinations not updated in last step
2423 let mut remaining_commodity_regions = HashSet :: new ( ) ;
@@ -44,20 +43,43 @@ impl CommodityPrices {
4443 /// # Arguments
4544 ///
4645 /// * `solution` - The solution to the dispatch optimisation
47- /// * `assets` - The asset pool
4846 ///
4947 /// # Returns
5048 ///
5149 /// The set of commodities for which prices were added.
52- fn add_from_solution (
53- & mut self ,
54- _solution : & Solution ,
55- _assets : & AssetPool ,
56- ) -> HashSet < ( CommodityID , RegionID ) > {
57- // **TODO:** Calculate commodity prices here:
58- // https://github.com/EnergySystemsModellingLab/MUSE_2.0/issues/589
50+ fn add_from_solution ( & mut self , solution : & Solution ) -> HashSet < ( CommodityID , RegionID ) > {
51+ let mut commodity_regions_updated = HashSet :: new ( ) ;
52+
53+ // Calculate highest activity dual for each commodity/region/timeslice
54+ let mut highest_duals = HashMap :: new ( ) ;
55+ for ( asset, time_slice, dual) in solution. iter_activity_duals ( ) {
56+ // Iterate over all output flows
57+ for flow in asset. iter_flows ( ) . filter ( |flow| flow. coeff > 0.0 ) {
58+ // Update the highest dual for this commodity/timeslice
59+ highest_duals
60+ . entry ( (
61+ flow. commodity . id . clone ( ) ,
62+ asset. region_id . clone ( ) ,
63+ time_slice. clone ( ) ,
64+ ) )
65+ . and_modify ( |current_dual| {
66+ if dual > * current_dual {
67+ * current_dual = dual;
68+ }
69+ } )
70+ . or_insert ( dual) ;
71+ }
72+ }
73+
74+ // Add the highest capacity dual for each commodity/timeslice to each commodity balance dual
75+ for ( commodity_id, region_id, time_slice, dual) in solution. iter_commodity_balance_duals ( ) {
76+ let key = ( commodity_id. clone ( ) , region_id. clone ( ) , time_slice. clone ( ) ) ;
77+ let price = dual + highest_duals. get ( & key) . unwrap_or ( & 0.0 ) ;
78+ self . insert ( commodity_id, region_id, time_slice, price) ;
79+ commodity_regions_updated. insert ( ( commodity_id. clone ( ) , region_id. clone ( ) ) ) ;
80+ }
5981
60- HashSet :: new ( )
82+ commodity_regions_updated
6183 }
6284
6385 /// Add prices for any commodity not updated by the dispatch step.
0 commit comments