diff --git a/docs/release_notes/upcoming.md b/docs/release_notes/upcoming.md index 8cdb33cde..1d5ebf086 100644 --- a/docs/release_notes/upcoming.md +++ b/docs/release_notes/upcoming.md @@ -34,6 +34,8 @@ ready to be released, carry out the following steps: - Fix parsing and validation of agent search space file ([#1293]) - Use shadow prices rather than market prices for appraisal optimisations and dispatch runs during investment ([#1349]) +- Updated input data validation to ensure `capacity_to_activity > 0`. Previously, + `capacity_to_activity = 0` was permitted. [highs-opts-docs]: ../developer_guide/custom_highs_options.md [#1259]: https://github.com/EnergySystemsModellingLab/MUSE2/pull/1259 diff --git a/schemas/input/processes.yaml b/schemas/input/processes.yaml index f12d1ddac..dfa1ff2dc 100644 --- a/schemas/input/processes.yaml +++ b/schemas/input/processes.yaml @@ -31,7 +31,7 @@ fields: description: Factor relating capacity units (e.g. GW) to activity units (e.g. PJ). It is the maximum activity per year for one unit of capacity. - notes: Must be >=0. Optional (defaults to 1.0). + notes: Must be >0. Optional (defaults to 1.0). - name: unit_size type: number description: diff --git a/src/fixture.rs b/src/fixture.rs index e212a0c12..7363820cf 100644 --- a/src/fixture.rs +++ b/src/fixture.rs @@ -4,7 +4,7 @@ use crate::agent::{ Agent, AgentCommodityPortionsMap, AgentID, AgentMap, AgentObjectiveMap, AgentSearchSpaceMap, DecisionRule, }; -use crate::asset::{Asset, AssetCapacity, AssetPool, AssetRef}; +use crate::asset::{Asset, AssetPool, AssetRef}; use crate::commodity::{ Commodity, CommodityID, CommodityLevyMap, CommodityType, DemandMap, PricingStrategy, }; @@ -406,7 +406,6 @@ pub fn appraisal_output(asset: Asset, time_slice: TimeSliceID) -> AppraisalOutpu let unmet_demand = indexmap! { time_slice.clone() => Flow(5.0) }; AppraisalOutput { asset: AssetRef::from(asset), - capacity: AssetCapacity::Continuous(Capacity(42.0)), coefficients: Rc::new(ObjectiveCoefficients { activity_coefficients, market_costs, diff --git a/src/input/process.rs b/src/input/process.rs index 2f47168d4..895f5f3a8 100644 --- a/src/input/process.rs +++ b/src/input/process.rs @@ -157,8 +157,8 @@ where // Validate capacity_to_activity ensure!( - capacity_to_activity >= ActivityPerCapacity(0.0), - "Error in process {}: capacity_to_activity must be >= 0", + capacity_to_activity > ActivityPerCapacity(0.0), + "Error in process {}: capacity_to_activity must be > 0", process_raw.id ); diff --git a/src/output.rs b/src/output.rs index 794559b40..9479e942e 100644 --- a/src/output.rs +++ b/src/output.rs @@ -486,7 +486,7 @@ impl DebugDataWriter { asset_id: result.asset.id(), process_id: result.asset.process_id().clone(), region_id: result.asset.region_id().clone(), - capacity: result.capacity.total_capacity(), + capacity: result.asset.capacity().total_capacity(), metric: result.metric.as_ref().map(|m| m.value()), }; self.appraisal_results_writer.serialize(row)?; @@ -1183,7 +1183,7 @@ mod tests { asset_id: None, process_id: asset.process_id().clone(), region_id: asset.region_id().clone(), - capacity: Capacity(42.0), + capacity: Capacity(2.0), metric: Some(4.14), }; let records: Vec = diff --git a/src/simulation/investment.rs b/src/simulation/investment.rs index 1a2c60673..fcb9835df 100644 --- a/src/simulation/investment.rs +++ b/src/simulation/investment.rs @@ -292,12 +292,13 @@ fn select_assets_for_single_market( commodity, region_id, year, + model.parameters.capacity_limit_factor, ) .collect::>(); // Calculate investment limits for candidate assets let investment_limits = - calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); + collect_investment_limits_for_candidates(&opt_assets, commodity_portion); // Choose assets from among existing pool and candidates let best_assets = select_best_assets( @@ -655,6 +656,7 @@ fn get_demand_limiting_capacity( } /// Get options from existing and potential assets for the given parameters +#[allow(clippy::too_many_arguments)] fn get_asset_options<'a>( time_slice_info: &'a TimeSliceInfo, all_existing_assets: &'a [AssetRef], @@ -663,6 +665,7 @@ fn get_asset_options<'a>( commodity: &'a Commodity, region_id: &'a RegionID, year: u32, + capacity_limit_factor: Dimensionless, ) -> impl Iterator + 'a { // Get existing assets which produce the commodity of interest let existing_assets = all_existing_assets @@ -673,13 +676,23 @@ fn get_asset_options<'a>( .cloned(); // Get candidates assets which produce the commodity of interest - let candidate_assets = - get_candidate_assets(time_slice_info, demand, agent, region_id, commodity, year); + let candidate_assets = get_candidate_assets( + time_slice_info, + demand, + agent, + region_id, + commodity, + year, + capacity_limit_factor, + ); chain(existing_assets, candidate_assets) } /// Get candidate assets which produce a particular commodity for a given agent +/// +/// Capacities of candidate assets are set to the demand-limiting capacity for the given market, +/// scaled by the `capacity_limit_factor`. fn get_candidate_assets<'a>( time_slice_info: &'a TimeSliceInfo, demand: &'a DemandMap, @@ -687,6 +700,7 @@ fn get_candidate_assets<'a>( region_id: &'a RegionID, commodity: &'a Commodity, year: u32, + capacity_limit_factor: Dimensionless, ) -> impl Iterator + 'a { agent .iter_search_space(region_id, &commodity.id, year) @@ -698,7 +712,8 @@ fn get_candidate_assets<'a>( // Set capacity based on demand // This will serve as the upper limit when appraising the asset let capacity = get_demand_limiting_capacity(time_slice_info, &asset, commodity, demand); - let asset_capacity = AssetCapacity::from_capacity(capacity, asset.unit_size()); + let asset_capacity = AssetCapacity::from_capacity(capacity, asset.unit_size()) + .apply_limit_factor(capacity_limit_factor); asset.set_capacity(asset_capacity); asset.into() @@ -742,30 +757,20 @@ fn log_on_equal_appraisal_outputs( } } -/// Calculate investment limits for an agent's candidate assets in a given year -/// -/// Investment limits are based on demand for the commodity (capacity cannot exceed that needed to -/// meet demand), and any annual addition limits specified by the process (scaled according to the -/// agent's portion of the commodity demand and the number of years elapsed since the previous -/// milestone year). -fn calculate_investment_limits_for_candidates( +/// Investment limits are based on any annual addition limits specified by the process, scaled +/// according to the agent's portion of the commodity demand and the number of years elapsed since +/// the previous milestone year. +fn collect_investment_limits_for_candidates( opt_assets: &[AssetRef], commodity_portion: Dimensionless, ) -> HashMap { - // Calculate limits for each candidate asset opt_assets .iter() .filter(|asset| !asset.is_commissioned()) - .map(|asset| { - // Start off with the demand-limiting capacity (pre-calculated when creating candidate) - let mut cap = asset.capacity(); - - // Cap by the addition limits of the process, if specified - if let Some(limit_capacity) = asset.max_installable_capacity(commodity_portion) { - cap = cap.min(limit_capacity); - } - - (asset.clone(), cap) + .filter_map(|asset| { + asset + .max_installable_capacity(commodity_portion) + .map(|limit_capacity| (asset.clone(), limit_capacity)) }) .collect() } @@ -820,31 +825,38 @@ fn select_best_assets( continue; } - // For candidates, determine the maximum capacity that can be invested in this round. - // This is whichever is the smallest of the tranche size (based on demand limiting - // capacity before investment), the remaining available capacity for the candidate and - // the demand limiting capacity recalculated based on demand unserved by the other - // selected assets. - let max_capacity = (!asset.is_commissioned()).then(|| { - let tranche_capacity = asset - .capacity() - .apply_limit_factor(model.parameters.capacity_limit_factor); + // For candidates, cap the asset's capacity by the current demand-limiting capacity + // and, where an addition constraint exists, the remaining installable capacity. + let mut asset = asset.clone(); + if !asset.is_commissioned() { let dlc = AssetCapacity::from_capacity( - get_demand_limiting_capacity(&model.time_slice_info, asset, commodity, &demand), + get_demand_limiting_capacity( + &model.time_slice_info, + &asset, + commodity, + &demand, + ), asset.unit_size(), ); - let remaining_capacity = remaining_candidate_capacity[asset]; + let cap = asset.capacity().min(dlc); + let max_capacity = remaining_candidate_capacity + .get(&asset) + .copied() + .map_or(cap, |remaining| cap.min(remaining)); + asset.make_mut().set_capacity(max_capacity); + } - tranche_capacity.min(dlc).min(remaining_capacity) - }); + // Skip assets with zero capacity + if asset.capacity().total_capacity() <= Capacity(0.0) { + continue; + } let output = appraise_investment( model, - asset, - max_capacity, + &asset, commodity, objective_type, - &coefficients[asset], + &coefficients[&asset], &demand, )?; outputs_for_opts.push(output); @@ -884,13 +896,12 @@ fn select_best_assets( "Selected {} asset '{}' (capacity: {})", &best_output.asset.state(), &best_output.asset.process_id(), - best_output.capacity.total_capacity() + best_output.asset.capacity().total_capacity() ); // Update the assets and remaining candidate capacity update_assets( best_output.asset, - best_output.capacity, &mut opt_assets, &mut remaining_candidate_capacity, &mut best_assets, @@ -920,8 +931,7 @@ fn is_any_remaining_demand(demand: &DemandMap, absolute_tolerance: Flow) -> bool /// Update capacity of chosen asset, if needed, and update both asset options and chosen assets fn update_assets( - mut best_asset: AssetRef, - capacity: AssetCapacity, + best_asset: AssetRef, opt_assets: &mut Vec, remaining_candidate_capacity: &mut HashMap, best_assets: &mut Vec, @@ -933,27 +943,30 @@ fn update_assets( best_assets.push(best_asset); } AssetState::Candidate => { - // Remove this capacity from the available remaining capacity for this asset - let remaining_capacity = remaining_candidate_capacity.get_mut(&best_asset).unwrap(); - *remaining_capacity = *remaining_capacity - capacity; - - // If there's no capacity remaining, remove the asset from the options - if remaining_capacity.total_capacity() <= Capacity(0.0) { - let old_idx = opt_assets - .iter() - .position(|asset| *asset == best_asset) - .unwrap(); - opt_assets.swap_remove(old_idx); - remaining_candidate_capacity.remove(&best_asset); + // Track remaining capacity for assets that have limits + if let Some(remaining_capacity) = remaining_candidate_capacity.get_mut(&best_asset) { + *remaining_capacity = *remaining_capacity - best_asset.capacity(); + + // If there's no capacity remaining, remove the asset from the options + if remaining_capacity.total_capacity() <= Capacity(0.0) { + let old_idx = opt_assets + .iter() + .position(|asset| *asset == best_asset) + .unwrap(); + + opt_assets.swap_remove(old_idx); + remaining_candidate_capacity.remove(&best_asset); + } } if let Some(existing_asset) = best_assets.iter_mut().find(|asset| **asset == best_asset) { // If the asset is already in the list of best assets, add the additional required capacity - existing_asset.make_mut().increase_capacity(capacity); + existing_asset + .make_mut() + .increase_capacity(best_asset.capacity()); } else { - // Otherwise, update the capacity of the chosen asset and add it to the list of best assets - best_asset.make_mut().set_capacity(capacity); + // Otherwise add it to the list of best assets best_assets.push(best_asset); } } @@ -966,9 +979,8 @@ mod tests { use super::*; use crate::commodity::Commodity; use crate::fixture::{ - agent_id, asset, process, process_activity_limits_map, process_flows_map, - process_investment_constraints, process_parameter_map, region_id, svd_commodity, - time_slice, time_slice_info, time_slice_info2, + asset, process, process_activity_limits_map, process_flows_map, process_parameter_map, + region_id, svd_commodity, time_slice, time_slice_info, time_slice_info2, }; use crate::process::{ ActivityLimits, FlowType, Process, ProcessActivityLimitsMap, ProcessFlow, ProcessFlowsMap, @@ -977,10 +989,11 @@ mod tests { use crate::region::RegionID; use crate::time_slice::{TimeSliceID, TimeSliceInfo, TimeSliceSelection}; use crate::units::Dimensionless; - use crate::units::{ActivityPerCapacity, Capacity, Flow, FlowPerActivity, MoneyPerFlow}; + use crate::units::{ActivityPerCapacity, Flow, FlowPerActivity, MoneyPerFlow}; use indexmap::{IndexSet, indexmap}; - use rstest::rstest; + use rstest::{fixture, rstest}; use std::rc::Rc; + use std::slice::from_ref; #[rstest] fn get_demand_limiting_capacity_works( @@ -1127,101 +1140,44 @@ mod tests { } #[rstest] - fn calculate_investment_limits_for_candidates_empty_list() { - // Test with empty list of assets - let opt_assets: Vec = vec![]; - let commodity_portion = Dimensionless(1.0); - - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); - + fn collect_investment_limits_for_candidates_empty_list() { + let result = collect_investment_limits_for_candidates(&[], Dimensionless(1.0)); assert!(result.is_empty()); } - #[rstest] - fn calculate_investment_limits_for_candidates_commissioned_assets_filtered( - process: Process, - region_id: RegionID, - agent_id: AgentID, - ) { - // Create a mix of commissioned and candidate assets - let process_rc = Rc::new(process); - let capacity = Capacity(10.0); - - // Create commissioned asset - should be filtered out - let commissioned_asset = Asset::new_commissioned( - agent_id.clone(), - process_rc.clone(), - region_id.clone(), - capacity, - 2015, - ) - .unwrap(); - - // Create candidate asset - should be included - let candidate_asset = - Asset::new_candidate(process_rc.clone(), region_id.clone(), capacity, 2015).unwrap(); - - let candidate_asset_ref = AssetRef::from(candidate_asset); - let opt_assets = vec![ - AssetRef::from(commissioned_asset), - candidate_asset_ref.clone(), - ]; - let commodity_portion = Dimensionless(1.0); - - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); - - // Only the candidate asset should be in the result - assert_eq!(result.len(), 1); - assert!(result.contains_key(&candidate_asset_ref)); + #[fixture] + fn commissioned_asset(asset: Asset) -> AssetRef { + asset.into() } - #[rstest] - fn calculate_investment_limits_for_candidates_no_investment_constraints( - process: Process, - region_id: RegionID, - ) { - // Create candidate asset without investment constraints - let process_rc = Rc::new(process); - let capacity = Capacity(15.0); - - let candidate_asset = Asset::new_candidate(process_rc, region_id, capacity, 2015).unwrap(); - - let opt_assets = vec![AssetRef::from(candidate_asset.clone())]; - let commodity_portion = Dimensionless(0.8); - - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); - - // Should return the asset's original capacity since no constraints apply - assert_eq!(result.len(), 1); - let asset_ref = AssetRef::from(candidate_asset); - assert_eq!(result[&asset_ref], AssetCapacity::Continuous(capacity)); + #[fixture] + fn uncommissioned_asset_without_limit(process: Process, region_id: RegionID) -> AssetRef { + Asset::new_candidate(Rc::new(process), region_id, Capacity(10.0), 2015) + .unwrap() + .into() } - #[rstest] - // Asset capacity higher than constraint -> limited by constraint - #[case(Capacity(15.0), Capacity(10.0))] - // Asset capacity lower than constraint -> limited by asset capacity - #[case(Capacity(5.0), Capacity(5.0))] - fn calculate_investment_limits_for_candidates_with_constraints( + #[fixture] + fn uncommissioned_asset_with_limit( region_id: RegionID, process_activity_limits_map: ProcessActivityLimitsMap, process_flows_map: ProcessFlowsMap, process_parameter_map: ProcessParameterMap, - #[case] asset_capacity: Capacity, - #[case] expected_limit: Capacity, - ) { + ) -> AssetRef { let region_ids: IndexSet = [region_id.clone()].into(); - // Add investment constraint with addition limit - let constraint = ProcessInvestmentConstraint { - addition_limit: Some(Capacity(10.0)), - }; let mut constraints = ProcessInvestmentConstraintsMap::new(); - constraints.insert((region_id.clone(), 2015), Rc::new(constraint)); + + constraints.insert( + (region_id.clone(), 2015), + Rc::new(ProcessInvestmentConstraint { + addition_limit: Some(Capacity(10.0)), + }), + ); let process = Process { id: "constrained_process".into(), - description: "Process with constraints".into(), + description: String::new(), years: 2010..=2020, activity_limits: process_activity_limits_map, flows: process_flows_map, @@ -1233,152 +1189,38 @@ mod tests { unit_size: None, }; - let process_rc = Rc::new(process); - - let candidate_asset = - Asset::new_candidate(process_rc, region_id, asset_capacity, 2015).unwrap(); - - let opt_assets = vec![AssetRef::from(candidate_asset.clone())]; - let commodity_portion = Dimensionless(1.0); - - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); - - // Should be limited by the minimum of asset capacity and constraint - assert_eq!(result.len(), 1); - let asset_ref = AssetRef::from(candidate_asset); - assert_eq!( - result[&asset_ref], - AssetCapacity::Continuous(expected_limit) - ); + Asset::new_candidate(Rc::new(process), region_id, Capacity(15.0), 2015) + .unwrap() + .into() } #[rstest] - fn calculate_investment_limits_for_candidates_multiple_assets( - region_id: RegionID, - process_activity_limits_map: ProcessActivityLimitsMap, - process_flows_map: ProcessFlowsMap, - process_parameter_map: ProcessParameterMap, - ) { - let region_ids: IndexSet = [region_id.clone()].into(); - - // Create first process with constraints - let constraint1 = ProcessInvestmentConstraint { - addition_limit: Some(Capacity(12.0)), - }; - let mut constraints1 = ProcessInvestmentConstraintsMap::new(); - constraints1.insert((region_id.clone(), 2015), Rc::new(constraint1)); - - let process1 = Process { - id: "process1".into(), - description: "First process".into(), - years: 2010..=2020, - activity_limits: process_activity_limits_map.clone(), - flows: process_flows_map.clone(), - parameters: process_parameter_map.clone(), - regions: region_ids.clone(), - primary_output: None, - capacity_to_activity: ActivityPerCapacity(1.0), - investment_constraints: constraints1, - unit_size: None, - }; - - // Create second process without constraints - let process2 = Process { - id: "process2".into(), - description: "Second process".into(), - years: 2010..=2020, - activity_limits: process_activity_limits_map, - flows: process_flows_map, - parameters: process_parameter_map, - regions: region_ids, - primary_output: None, - capacity_to_activity: ActivityPerCapacity(1.0), - investment_constraints: process_investment_constraints(), - unit_size: None, - }; - - let process1_rc = Rc::new(process1); - let process2_rc = Rc::new(process2); - - let candidate1 = - Asset::new_candidate(process1_rc, region_id.clone(), Capacity(20.0), 2015).unwrap(); - - let candidate2 = Asset::new_candidate(process2_rc, region_id, Capacity(8.0), 2015).unwrap(); - - let opt_assets = vec![ - AssetRef::from(candidate1.clone()), - AssetRef::from(candidate2.clone()), - ]; - let commodity_portion = Dimensionless(0.75); - - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); - - // Should have both assets in result - assert_eq!(result.len(), 2); - - // First asset should be limited by constraint: 12.0 * 0.75 = 9.0 - let asset1_ref = AssetRef::from(candidate1); - assert_eq!( - result[&asset1_ref], - AssetCapacity::Continuous(Capacity(9.0)) + fn commissioned_assets_are_excluded(commissioned_asset: AssetRef) { + let result = collect_investment_limits_for_candidates( + from_ref(&commissioned_asset), + Dimensionless(1.0), ); - // Second asset should use its original capacity (no constraints) - let asset2_ref = AssetRef::from(candidate2); - assert_eq!( - result[&asset2_ref], - AssetCapacity::Continuous(Capacity(8.0)) - ); + assert!(!result.contains_key(&commissioned_asset)); } #[rstest] - fn calculate_investment_limits_for_candidates_discrete_capacity( - region_id: RegionID, - process_activity_limits_map: crate::process::ProcessActivityLimitsMap, - process_flows_map: crate::process::ProcessFlowsMap, - process_parameter_map: crate::process::ProcessParameterMap, - ) { - let region_ids: IndexSet = [region_id.clone()].into(); - - // Add investment constraint - let constraint = ProcessInvestmentConstraint { - addition_limit: Some(Capacity(35.0)), // Enough for 3.5 units at 10.0 each - }; - let mut constraints = ProcessInvestmentConstraintsMap::new(); - constraints.insert((region_id.clone(), 2015), Rc::new(constraint)); - - let process = Process { - id: "discrete_process".into(), - description: "Process with discrete units".into(), - years: 2010..=2020, - activity_limits: process_activity_limits_map, - flows: process_flows_map, - parameters: process_parameter_map, - regions: region_ids, - primary_output: None, - capacity_to_activity: ActivityPerCapacity(1.0), - investment_constraints: constraints, - unit_size: Some(Capacity(10.0)), // Discrete units of 10.0 capacity each - }; - - let process_rc = Rc::new(process); - let capacity = Capacity(50.0); // 5 units at 10.0 each - - let candidate_asset = Asset::new_candidate(process_rc, region_id, capacity, 2015).unwrap(); - - let opt_assets = vec![AssetRef::from(candidate_asset.clone())]; - let commodity_portion = Dimensionless(1.0); + fn candidate_assets_without_limits_are_excluded(uncommissioned_asset_without_limit: AssetRef) { + let result = collect_investment_limits_for_candidates( + from_ref(&uncommissioned_asset_without_limit), + Dimensionless(1.0), + ); - let result = calculate_investment_limits_for_candidates(&opt_assets, commodity_portion); + assert!(!result.contains_key(&uncommissioned_asset_without_limit)); + } - // Should be limited by constraint and rounded down to whole units - // Constraint: 35.0, divided by unit size 10.0 = 3.5 -> floor to 3 units = 30.0 - assert_eq!(result.len(), 1); - let asset_ref = AssetRef::from(candidate_asset); - assert_eq!( - result[&asset_ref], - AssetCapacity::Discrete(3, Capacity(10.0)) + #[rstest] + fn candidate_assets_with_limits_are_included(uncommissioned_asset_with_limit: AssetRef) { + let result = collect_investment_limits_for_candidates( + from_ref(&uncommissioned_asset_with_limit), + Dimensionless(1.0), ); - assert_eq!(result[&asset_ref].total_capacity(), Capacity(30.0)); + + assert!(result.contains_key(&uncommissioned_asset_with_limit)); } } diff --git a/src/simulation/investment/appraisal.rs b/src/simulation/investment/appraisal.rs index c1924c1e4..74b0ddd3f 100644 --- a/src/simulation/investment/appraisal.rs +++ b/src/simulation/investment/appraisal.rs @@ -1,12 +1,12 @@ //! Calculation for investment tools such as Levelised Cost of X (LCOX) and Net Present Value (NPV). use super::DemandMap; use crate::agent::ObjectiveType; -use crate::asset::{Asset, AssetCapacity, AssetRef}; +use crate::asset::{Asset, AssetRef}; use crate::commodity::Commodity; use crate::finance::{lcox, snas}; use crate::model::Model; use crate::time_slice::TimeSliceID; -use crate::units::{Activity, Capacity, MoneyPerActivity, MoneyPerCapacity}; +use crate::units::{Activity, MoneyPerActivity, MoneyPerCapacity}; use anyhow::Result; use costs::annual_fixed_cost; use erased_serde::Serialize as ErasedSerialize; @@ -52,8 +52,6 @@ where pub struct AppraisalOutput { /// The asset being appraised pub asset: AssetRef, - /// The hypothetical capacity to install - pub capacity: AssetCapacity, /// Time slice level activity of the asset pub activity: IndexMap, /// The hypothetical unmet demand following investment in this asset @@ -68,14 +66,12 @@ impl AppraisalOutput { /// Create a new `AppraisalOutput` fn new( asset: AssetRef, - capacity: AssetCapacity, results: ResultsMap, metric: Option, coefficients: Rc, ) -> Self { Self { asset, - capacity, activity: results.activity, unmet_demand: results.unmet_demand, metric: metric.map(|m| Box::new(m) as Box), @@ -91,24 +87,14 @@ impl AppraisalOutput { /// vs. Windows). We want to avoid this, if possible, which is why we use a more approximate /// comparison. pub fn compare_metric(&self, other: &Self) -> Ordering { - assert!( - self.is_valid() && other.is_valid(), - "Cannot compare non-valid outputs" - ); - - // We've already checked the metrics aren't `None` in `is_valid` - self.metric - .as_ref() - .unwrap() - .compare(other.metric.as_ref().unwrap().as_ref()) - } + let (metric1, metric2) = self + .metric + .as_deref() + .zip(other.metric.as_deref()) + .expect("Cannot compare non-valid outputs"); - /// Whether this [`AppraisalOutput`] is a valid output. - /// - /// Specifically, it checks whether the metric is a valid value (not `None`) and that the - /// calculated capacity is greater than zero. - pub fn is_valid(&self) -> bool { - self.metric.is_some() && self.capacity.total_capacity() > Capacity(0.0) + // We've already checked the metrics aren't `None` + metric1.compare(metric2) } } @@ -229,16 +215,14 @@ impl MetricTrait for NPVMetric {} fn calculate_lcox( model: &Model, asset: &AssetRef, - max_capacity: AssetCapacity, commodity: &Commodity, coefficients: &Rc, demand: &DemandMap, ) -> Result { - let results = - perform_optimisation(model, asset, max_capacity, commodity, coefficients, demand)?; + let results = perform_optimisation(model, asset, commodity, coefficients, demand)?; let cost_index = lcox( - max_capacity.total_capacity(), + asset.capacity().total_capacity(), annual_fixed_cost(asset), &results.activity, &coefficients.market_costs, @@ -246,7 +230,6 @@ fn calculate_lcox( Ok(AppraisalOutput::new( asset.clone(), - max_capacity, results, cost_index.map(LCOXMetric::new), coefficients.clone(), @@ -261,13 +244,11 @@ fn calculate_lcox( fn calculate_npv( model: &Model, asset: &AssetRef, - max_capacity: AssetCapacity, commodity: &Commodity, coefficients: &Rc, demand: &DemandMap, ) -> Result { - let results = - perform_optimisation(model, asset, max_capacity, commodity, coefficients, demand)?; + let results = perform_optimisation(model, asset, commodity, coefficients, demand)?; let annual_fixed_cost = annual_fixed_cost(asset); assert!( @@ -276,7 +257,7 @@ fn calculate_npv( ); let snas = snas( - max_capacity.total_capacity(), + asset.capacity().total_capacity(), annual_fixed_cost, &results.activity, &coefficients.market_costs, @@ -284,7 +265,6 @@ fn calculate_npv( Ok(AppraisalOutput::new( asset.clone(), - max_capacity, results, snas.map(NPVMetric::new), coefficients.clone(), @@ -300,18 +280,16 @@ fn calculate_npv( pub fn appraise_investment( model: &Model, asset: &AssetRef, - max_capacity: Option, commodity: &Commodity, objective_type: &ObjectiveType, coefficients: &Rc, demand: &DemandMap, ) -> Result { - let max_capacity = max_capacity.unwrap_or(asset.capacity()); let appraisal_method = match objective_type { ObjectiveType::LevelisedCostOfX => calculate_lcox, ObjectiveType::NetPresentValue => calculate_npv, }; - appraisal_method(model, asset, max_capacity, commodity, coefficients, demand) + appraisal_method(model, asset, commodity, coefficients, demand) } /// Compare assets as a fallback if metrics are equal. @@ -331,17 +309,15 @@ fn compare_asset_fallback(asset1: &Asset, asset2: &Asset) -> Ordering { /// and newer assets are preferred over older ones. The function does not guarantee that all ties /// will be resolved. /// -/// Before sorting, outputs are filtered using [`AppraisalOutput::is_valid`], which excludes entries -/// with invalid metrics (e.g. `None`) as well as zero capacity. This avoids meaningless or `NaN` -/// appraisal metrics that could cause the program to panic, so the length of the returned vector -/// may be less than the input. +/// Before sorting, outputs are filtered to exclude entries with invalid metrics (i.e. `None`), so +/// the length of the returned vector may be less than the input. /// /// # Returns /// /// Returns the number of non-feasible assets which were removed. pub fn sort_and_filter_appraisal_outputs(outputs: &mut Vec) -> usize { let old_len = outputs.len(); - outputs.retain(AppraisalOutput::is_valid); + outputs.retain(|output| output.metric.is_some()); let num_nonfeasible = old_len - outputs.len(); outputs.sort_by(|output1, output2| match output1.compare_metric(output2) { @@ -375,7 +351,7 @@ mod tests { use crate::fixture::{agent_id, asset, process, region_id}; use crate::process::Process; use crate::region::RegionID; - use crate::units::MoneyPerActivity; + use crate::units::{Capacity, MoneyPerActivity}; use float_cmp::assert_approx_eq; use rstest::rstest; use std::rc::Rc; @@ -477,7 +453,6 @@ mod tests { .zip(metrics) .map(|(asset, metric)| AppraisalOutput { asset: AssetRef::from(asset), - capacity: AssetCapacity::Continuous(Capacity(10.0)), coefficients: objective_coeffs(), activity: IndexMap::new(), unmet_demand: IndexMap::new(), @@ -747,41 +722,11 @@ mod tests { ); } - /// Test that appraisal outputs with zero capacity are filtered out during sorting. - #[rstest] - fn appraisal_sort_filters_zero_capacity_outputs(asset: Asset) { - let metric = LCOXMetric::new(MoneyPerActivity(1.0)); - let metrics = [ - Box::new(metric.clone()), - Box::new(metric.clone()), - Box::new(metric), - ]; - - // Create outputs with zero capacity - let mut outputs: Vec = metrics - .into_iter() - .map(|metric| AppraisalOutput { - asset: AssetRef::from(asset.clone()), - capacity: AssetCapacity::Continuous(Capacity(0.0)), - coefficients: objective_coeffs(), - activity: IndexMap::new(), - unmet_demand: IndexMap::new(), - metric: Some(metric), - }) - .collect(); - - sort_and_filter_appraisal_outputs(&mut outputs); - - // All zero capacity outputs should be filtered out - assert_eq!(outputs.len(), 0); - } - /// Test that appraisal outputs with an invalid metric are filtered out #[rstest] fn appraisal_sort_filters_invalid_metric(asset: Asset) { let output = AppraisalOutput { asset: AssetRef::from(asset), - capacity: AssetCapacity::Continuous(Capacity(1.0)), // non-zero capacity coefficients: objective_coeffs(), activity: IndexMap::new(), unmet_demand: IndexMap::new(), diff --git a/src/simulation/investment/appraisal/constraints.rs b/src/simulation/investment/appraisal/constraints.rs index 129db22f6..f8e7483f2 100644 --- a/src/simulation/investment/appraisal/constraints.rs +++ b/src/simulation/investment/appraisal/constraints.rs @@ -1,7 +1,7 @@ //! Constraints for the optimisation problem. use super::DemandMap; use super::optimisation::Variable; -use crate::asset::{AssetCapacity, AssetRef}; +use crate::asset::AssetRef; use crate::commodity::Commodity; use crate::time_slice::{TimeSliceID, TimeSliceInfo}; use crate::units::Flow; @@ -12,17 +12,16 @@ use indexmap::IndexMap; /// /// Constrains the activity variables to be within the asset's activity limits. /// -/// The asset's per-capacity activity limits are scaled by the fixed `max_capacity` to give +/// The asset's per-capacity activity limits are scaled by the asset's capacity to give /// absolute bounds, and a single bounded constraint is added per time-slice selection covering the /// sum of activity in that selection. pub fn add_activity_constraints( problem: &mut Problem, asset: &AssetRef, - max_capacity: AssetCapacity, activity_vars: &IndexMap, time_slice_info: &TimeSliceInfo, ) { - let capacity = max_capacity.total_capacity(); + let capacity = asset.capacity().total_capacity(); for (ts_selection, limits) in asset.iter_activity_per_capacity_limits() { let limits = (capacity * *limits.start()).value()..=(capacity * *limits.end()).value(); diff --git a/src/simulation/investment/appraisal/optimisation.rs b/src/simulation/investment/appraisal/optimisation.rs index f9d0a1939..a57827459 100644 --- a/src/simulation/investment/appraisal/optimisation.rs +++ b/src/simulation/investment/appraisal/optimisation.rs @@ -2,7 +2,6 @@ use super::DemandMap; use super::ObjectiveCoefficients; use super::constraints::{add_activity_constraints, add_demand_constraints}; -use crate::asset::AssetCapacity; use crate::asset::AssetRef; use crate::commodity::Commodity; use crate::model::Model; @@ -50,13 +49,12 @@ fn add_activity_vars( fn add_constraints( problem: &mut Problem, asset: &AssetRef, - max_capacity: AssetCapacity, commodity: &Commodity, activity_vars: &IndexMap, demand: &DemandMap, time_slice_info: &TimeSliceInfo, ) { - add_activity_constraints(problem, asset, max_capacity, activity_vars, time_slice_info); + add_activity_constraints(problem, asset, activity_vars, time_slice_info); add_demand_constraints( problem, asset, @@ -104,14 +102,9 @@ fn compute_unmet_demand( } /// Performs optimisation for an asset, given the coefficients and demand. -/// -/// Maximises the objective function over the activity variables, holding the asset's capacity -/// fixed at `max_capacity`. Capacity is not a decision variable; the activity bounds are derived -/// from `max_capacity` by the activity constraints. pub fn perform_optimisation( model: &Model, asset: &AssetRef, - max_capacity: AssetCapacity, commodity: &Commodity, coefficients: &ObjectiveCoefficients, demand: &DemandMap, @@ -124,7 +117,6 @@ pub fn perform_optimisation( add_constraints( &mut problem, asset, - max_capacity, commodity, &activity_vars, demand, diff --git a/tests/data/muse1_default/asset_capacities.csv b/tests/data/muse1_default/asset_capacities.csv index e5fea2ed7..86ff72bf3 100644 --- a/tests/data/muse1_default/asset_capacities.csv +++ b/tests/data/muse1_default/asset_capacities.csv @@ -2,43 +2,44 @@ milestone_year,asset_id,group_id,capacity,num_units 2020,0,,24.0, 2020,1,,19.0, 2025,2,,23.939952120095757, -2025,3,,13.299973400053199, +2025,3,,14.097971804056394, 2030,2,,23.939952120095757, -2030,3,,13.299973400053199, +2030,3,,14.097971804056394, 2030,4,,5.939988120023763, -2030,5,,14.063371873256253, +2030,5,,13.42917314165371, 2035,2,,23.939952120095757, -2035,3,,13.299973400053199, +2035,3,,14.097971804056394, 2035,4,,5.939988120023763, -2035,5,,14.063371873256253, +2035,5,,13.42917314165371, 2035,6,,6.11998776002448, -2035,7,,8.487823024353967, +2035,7,,8.094703810592398, 2040,2,,23.939952120095757, -2040,3,,13.299973400053199, +2040,3,,14.097971804056394, 2040,4,,5.939988120023763, -2040,5,,14.063371873256253, +2040,5,,13.42917314165371, 2040,6,,6.11998776002448, -2040,7,,8.487823024353967, +2040,7,,8.094703810592398, 2040,8,,5.939988120023764, -2040,9,,1.633020733958506, +2040,9,,2.981386037227901, 2045,2,,23.939952120095757, -2045,3,,13.299973400053199, +2045,3,,14.097971804056394, 2045,4,,5.939988120023763, -2045,5,,14.063371873256253, +2045,5,,13.42917314165371, 2045,6,,6.11998776002448, -2045,7,,8.487823024353967, +2045,7,,8.094703810592398, 2045,8,,5.939988120023764, -2045,9,,1.633020733958506, +2045,9,,2.981386037227901, 2045,10,,5.939988120023764, -2045,11,,9.593747212505615, +2045,11,,7.70603578792847, 2050,2,,23.939952120095757, -2050,3,,13.299973400053199, +2050,3,,14.097971804056394, 2050,4,,5.939988120023763, -2050,5,,14.063371873256253, +2050,5,,13.42917314165371, 2050,6,,6.11998776002448, -2050,7,,8.487823024353967, +2050,7,,8.094703810592398, 2050,8,,5.939988120023764, -2050,9,,1.633020733958506, +2050,9,,2.981386037227901, 2050,10,,5.939988120023764, -2050,11,,9.593747212505615, -2050,12,,6.119987760024478, +2050,11,,7.70603578792847, +2050,12,,6.119987760024469, +2050,13,,5.137589724820562, diff --git a/tests/data/muse1_default/assets.csv b/tests/data/muse1_default/assets.csv index 15d96db6c..3b3df6296 100644 --- a/tests/data/muse1_default/assets.csv +++ b/tests/data/muse1_default/assets.csv @@ -12,3 +12,4 @@ asset_id,group_id,process_id,region_id,agent_id,commission_year 10,,heatpump,R1,A1_RES,2045 11,,windturbine,R1,A1_PWR,2045 12,,heatpump,R1,A1_RES,2050 +13,,windturbine,R1,A1_PWR,2050 diff --git a/tests/data/muse1_default/commodity_flows.csv b/tests/data/muse1_default/commodity_flows.csv index 37cb9c821..3b468af7a 100644 --- a/tests/data/muse1_default/commodity_flows.csv +++ b/tests/data/muse1_default/commodity_flows.csv @@ -117,8 +117,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2035,3,,electricity,all-year.early-peak,1.2 2035,3,,wind,all-year.late-peak,-0.0 2035,3,,electricity,all-year.late-peak,0.0 -2035,3,,wind,all-year.evening,-0.18535999999999753 -2035,3,,electricity,all-year.evening,0.18535999999999753 +2035,3,,wind,all-year.evening,-0.2508799999999969 +2035,3,,electricity,all-year.evening,0.2508799999999969 2035,4,,electricity,all-year.night,-0.392 2035,4,,heat,all-year.night,0.98 2035,4,,electricity,all-year.morning,-0.39600000000000024 @@ -139,8 +139,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2035,5,,electricity,all-year.afternoon,0.0 2035,5,,wind,all-year.early-peak,-0.0 2035,5,,electricity,all-year.early-peak,0.0 -2035,5,,wind,all-year.late-peak,-2.3439 -2035,5,,electricity,all-year.late-peak,2.3439 +2035,5,,wind,all-year.late-peak,-2.238199999999999 +2035,5,,electricity,all-year.late-peak,2.238199999999999 2035,5,,wind,all-year.evening,-0.0 2035,5,,electricity,all-year.evening,0.0 2035,6,,electricity,all-year.night,-0.40800000000000003 @@ -163,10 +163,10 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2035,7,,electricity,all-year.afternoon,0.8 2035,7,,wind,all-year.early-peak,-0.0 2035,7,,electricity,all-year.early-peak,0.0 -2035,7,,wind,all-year.late-peak,-0.05610000000000015 -2035,7,,electricity,all-year.late-peak,0.05610000000000015 -2035,7,,wind,all-year.evening,-1.4146400000000026 -2035,7,,electricity,all-year.evening,1.4146400000000026 +2035,7,,wind,all-year.late-peak,-0.16180000000000117 +2035,7,,electricity,all-year.late-peak,0.16180000000000117 +2035,7,,wind,all-year.evening,-1.3491200000000032 +2035,7,,electricity,all-year.evening,1.3491200000000032 2040,2,,electricity,all-year.night,-0.0 2040,2,,heat,all-year.night,0.0 2040,2,,electricity,all-year.morning,-0.1979999999999995 @@ -187,8 +187,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,3,,electricity,all-year.afternoon,0.0 2040,3,,wind,all-year.early-peak,-0.0 2040,3,,electricity,all-year.early-peak,0.0 -2040,3,,wind,all-year.late-peak,-1.3813599999999981 -2040,3,,electricity,all-year.late-peak,1.3813599999999981 +2040,3,,wind,all-year.late-peak,-1.4468799999999975 +2040,3,,electricity,all-year.late-peak,1.4468799999999975 2040,3,,wind,all-year.evening,-0.0 2040,3,,electricity,all-year.evening,0.0 2040,4,,electricity,all-year.night,-0.12799999999999975 @@ -209,8 +209,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,5,,electricity,all-year.morning,1.3980000000000001 2040,5,,wind,all-year.afternoon,-0.0 2040,5,,electricity,all-year.afternoon,0.0 -2040,5,,wind,all-year.early-peak,-1.1258293333333378 -2040,5,,electricity,all-year.early-peak,1.1258293333333378 +2040,5,,wind,all-year.early-peak,-0.9011013333333375 +2040,5,,electricity,all-year.early-peak,0.9011013333333375 2040,5,,wind,all-year.late-peak,-0.0 2040,5,,electricity,all-year.late-peak,0.0 2040,5,,wind,all-year.evening,-1.8640000000000003 @@ -235,8 +235,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,7,,electricity,all-year.afternoon,0.932 2040,7,,wind,all-year.early-peak,-0.0 2040,7,,electricity,all-year.early-peak,0.0 -2040,7,,wind,all-year.late-peak,-1.4146400000000026 -2040,7,,electricity,all-year.late-peak,1.4146400000000026 +2040,7,,wind,all-year.late-peak,-1.3491200000000032 +2040,7,,electricity,all-year.late-peak,1.3491200000000032 2040,7,,wind,all-year.evening,-0.0 2040,7,,electricity,all-year.evening,0.0 2040,8,,electricity,all-year.night,-0.3960000000000003 @@ -257,8 +257,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,9,,electricity,all-year.morning,0.0 2040,9,,wind,all-year.afternoon,-0.0 2040,9,,electricity,all-year.afternoon,0.0 -2040,9,,wind,all-year.early-peak,-0.27217066666666234 -2040,9,,electricity,all-year.early-peak,0.27217066666666234 +2040,9,,wind,all-year.early-peak,-0.4968986666666626 +2040,9,,electricity,all-year.early-peak,0.4968986666666626 2040,9,,wind,all-year.late-peak,-0.0 2040,9,,electricity,all-year.late-peak,0.0 2040,9,,wind,all-year.evening,-0.0 @@ -299,16 +299,16 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,4,,heat,all-year.late-peak,0.9900000000000005 2045,4,,electricity,all-year.evening,-0.39600000000000024 2045,4,,heat,all-year.evening,0.9900000000000005 -2045,5,,wind,all-year.night,-0.0 -2045,5,,electricity,all-year.night,0.0 +2045,5,,wind,all-year.night,-0.32992138666665577 +2045,5,,electricity,all-year.night,0.32992138666665577 2045,5,,wind,all-year.morning,-0.0 2045,5,,electricity,all-year.morning,0.0 2045,5,,wind,all-year.afternoon,-0.0 2045,5,,electricity,all-year.afternoon,0.0 2045,5,,wind,all-year.early-peak,-0.0 2045,5,,electricity,all-year.early-peak,0.0 -2045,5,,wind,all-year.late-peak,-0.17839893333332457 -2045,5,,electricity,all-year.late-peak,0.17839893333332457 +2045,5,,wind,all-year.late-peak,-0.5585381333333234 +2045,5,,electricity,all-year.late-peak,0.5585381333333234 2045,5,,wind,all-year.evening,-0.0 2045,5,,electricity,all-year.evening,0.0 2045,6,,electricity,all-year.night,-0.2719999999999995 @@ -331,8 +331,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,7,,electricity,all-year.afternoon,0.0 2045,7,,wind,all-year.early-peak,-0.0 2045,7,,electricity,all-year.early-peak,0.0 -2045,7,,wind,all-year.late-peak,-1.4146400000000026 -2045,7,,electricity,all-year.late-peak,1.4146400000000026 +2045,7,,wind,all-year.late-peak,-1.3491200000000032 +2045,7,,electricity,all-year.late-peak,1.3491200000000032 2045,7,,wind,all-year.evening,-0.0 2045,7,,electricity,all-year.evening,0.0 2045,8,,electricity,all-year.night,-0.3960000000000003 @@ -371,16 +371,16 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,10,,heat,all-year.late-peak,0.9900000000000007 2045,10,,electricity,all-year.evening,-0.3960000000000003 2045,10,,heat,all-year.evening,0.9900000000000007 -2045,11,,wind,all-year.night,-1.064 -2045,11,,electricity,all-year.night,1.064 +2045,11,,wind,all-year.night,-0.7340786133333443 +2045,11,,electricity,all-year.night,0.7340786133333443 2045,11,,wind,all-year.morning,-0.0 2045,11,,electricity,all-year.morning,0.0 2045,11,,wind,all-year.afternoon,-1.064 2045,11,,electricity,all-year.afternoon,1.064 2045,11,,wind,all-year.early-peak,-0.0 2045,11,,electricity,all-year.early-peak,0.0 -2045,11,,wind,all-year.late-peak,-1.5989610666666736 -2045,11,,electricity,all-year.late-peak,1.5989610666666736 +2045,11,,wind,all-year.late-peak,-1.2843418666666744 +2045,11,,electricity,all-year.late-peak,1.2843418666666744 2045,11,,wind,all-year.evening,-0.0 2045,11,,electricity,all-year.evening,0.0 2050,2,,electricity,all-year.night,-0.0 @@ -393,50 +393,50 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,2,,heat,all-year.early-peak,0.0 2050,2,,electricity,all-year.late-peak,-1.596 2050,2,,heat,all-year.late-peak,3.9899999999999998 -2050,2,,electricity,all-year.evening,-0.39599999999999946 -2050,2,,heat,all-year.evening,0.9899999999999987 +2050,2,,electricity,all-year.evening,-0.39600000000000013 +2050,2,,heat,all-year.evening,0.9900000000000002 2050,3,,wind,all-year.night,-0.0 2050,3,,electricity,all-year.night,0.0 -2050,3,,wind,all-year.morning,-1.8 -2050,3,,electricity,all-year.morning,1.8 +2050,3,,wind,all-year.morning,-0.0 +2050,3,,electricity,all-year.morning,0.0 2050,3,,wind,all-year.afternoon,-0.0 2050,3,,electricity,all-year.afternoon,0.0 -2050,3,,wind,all-year.early-peak,-1.3033333333333335 -2050,3,,electricity,all-year.early-peak,1.3033333333333335 +2050,3,,wind,all-year.early-peak,-0.0 +2050,3,,electricity,all-year.early-peak,0.0 2050,3,,wind,all-year.late-peak,-0.0 2050,3,,electricity,all-year.late-peak,0.0 -2050,3,,wind,all-year.evening,-2.216666666666667 -2050,3,,electricity,all-year.evening,2.216666666666667 +2050,3,,wind,all-year.evening,-0.0 +2050,3,,electricity,all-year.evening,0.0 2050,4,,electricity,all-year.night,-0.0 2050,4,,heat,all-year.night,0.0 -2050,4,,electricity,all-year.morning,-0.19199999999999956 -2050,4,,heat,all-year.morning,0.47999999999999887 +2050,4,,electricity,all-year.morning,-0.19200000000000017 +2050,4,,heat,all-year.morning,0.4800000000000004 2050,4,,electricity,all-year.afternoon,-0.0 2050,4,,heat,all-year.afternoon,0.0 -2050,4,,electricity,all-year.early-peak,-0.19199999999999956 -2050,4,,heat,all-year.early-peak,0.47999999999999887 +2050,4,,electricity,all-year.early-peak,-0.19200000000000017 +2050,4,,heat,all-year.early-peak,0.4800000000000004 2050,4,,electricity,all-year.late-peak,-0.39600000000000024 2050,4,,heat,all-year.late-peak,0.9900000000000005 2050,4,,electricity,all-year.evening,-0.39600000000000024 2050,4,,heat,all-year.evening,0.9900000000000005 -2050,5,,wind,all-year.night,-0.34478783999999096 -2050,5,,electricity,all-year.night,0.34478783999999096 +2050,5,,wind,all-year.night,-0.8895528533333074 +2050,5,,electricity,all-year.night,0.8895528533333074 2050,5,,wind,all-year.morning,-0.0 2050,5,,electricity,all-year.morning,0.0 2050,5,,wind,all-year.afternoon,-0.0 2050,5,,electricity,all-year.afternoon,0.0 -2050,5,,wind,all-year.early-peak,-0.4966666666666666 -2050,5,,electricity,all-year.early-peak,0.4966666666666666 -2050,5,,wind,all-year.late-peak,-0.5863989333333249 -2050,5,,electricity,all-year.late-peak,0.5863989333333249 +2050,5,,wind,all-year.early-peak,-0.0 +2050,5,,electricity,all-year.early-peak,0.0 +2050,5,,wind,all-year.late-peak,-2.238199999999999 +2050,5,,electricity,all-year.late-peak,2.238199999999999 2050,5,,wind,all-year.evening,-0.0 2050,5,,electricity,all-year.evening,0.0 -2050,6,,electricity,all-year.night,-0.0 -2050,6,,heat,all-year.night,0.0 +2050,6,,electricity,all-year.night,0.0 +2050,6,,heat,all-year.night,-0.0 2050,6,,electricity,all-year.morning,-0.40800000000000003 2050,6,,heat,all-year.morning,1.02 -2050,6,,electricity,all-year.afternoon,-0.0 -2050,6,,heat,all-year.afternoon,0.0 +2050,6,,electricity,all-year.afternoon,0.0 +2050,6,,heat,all-year.afternoon,-0.0 2050,6,,electricity,all-year.early-peak,-0.40800000000000003 2050,6,,heat,all-year.early-peak,1.02 2050,6,,electricity,all-year.late-peak,-0.40800000000000003 @@ -447,20 +447,20 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,7,,electricity,all-year.night,0.0 2050,7,,wind,all-year.morning,-0.0 2050,7,,electricity,all-year.morning,0.0 -2050,7,,wind,all-year.afternoon,-0.0 -2050,7,,electricity,all-year.afternoon,0.0 -2050,7,,wind,all-year.early-peak,-0.0 -2050,7,,electricity,all-year.early-peak,0.0 -2050,7,,wind,all-year.late-peak,-1.4146400000000026 -2050,7,,electricity,all-year.late-peak,1.4146400000000026 -2050,7,,wind,all-year.evening,-0.0 -2050,7,,electricity,all-year.evening,0.0 -2050,8,,electricity,all-year.night,-0.39599999999999985 -2050,8,,heat,all-year.night,0.9899999999999995 +2050,7,,wind,all-year.afternoon,-1.2 +2050,7,,electricity,all-year.afternoon,1.2 +2050,7,,wind,all-year.early-peak,-0.9437333333333314 +2050,7,,electricity,all-year.early-peak,0.9437333333333314 +2050,7,,wind,all-year.late-peak,-0.0 +2050,7,,electricity,all-year.late-peak,0.0 +2050,7,,wind,all-year.evening,-1.0941546666666762 +2050,7,,electricity,all-year.evening,1.0941546666666762 +2050,8,,electricity,all-year.night,-0.3960000000000003 +2050,8,,heat,all-year.night,0.9900000000000007 2050,8,,electricity,all-year.morning,-0.3960000000000003 2050,8,,heat,all-year.morning,0.9900000000000007 -2050,8,,electricity,all-year.afternoon,-0.39599999999999985 -2050,8,,heat,all-year.afternoon,0.9899999999999995 +2050,8,,electricity,all-year.afternoon,-0.3960000000000003 +2050,8,,heat,all-year.afternoon,0.9900000000000007 2050,8,,electricity,all-year.early-peak,-0.3960000000000003 2050,8,,heat,all-year.early-peak,0.9900000000000007 2050,8,,electricity,all-year.late-peak,-0.3960000000000003 @@ -469,8 +469,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,8,,heat,all-year.evening,0.9900000000000007 2050,9,,wind,all-year.night,-0.0 2050,9,,electricity,all-year.night,0.0 -2050,9,,wind,all-year.morning,-0.0 -2050,9,,electricity,all-year.morning,0.0 +2050,9,,wind,all-year.morning,-0.4968986666666626 +2050,9,,electricity,all-year.morning,0.4968986666666626 2050,9,,wind,all-year.afternoon,-0.0 2050,9,,electricity,all-year.afternoon,0.0 2050,9,,wind,all-year.early-peak,-0.0 @@ -491,27 +491,39 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,10,,heat,all-year.late-peak,0.9900000000000007 2050,10,,electricity,all-year.evening,-0.3960000000000003 2050,10,,heat,all-year.evening,0.9900000000000007 -2050,11,,wind,all-year.night,-0.8552121600000091 -2050,11,,electricity,all-year.night,0.8552121600000091 -2050,11,,wind,all-year.morning,-0.0 -2050,11,,electricity,all-year.morning,0.0 -2050,11,,wind,all-year.afternoon,-1.2000000000000002 -2050,11,,electricity,all-year.afternoon,1.2000000000000002 +2050,11,,wind,all-year.night,-0.3104471466666925 +2050,11,,electricity,all-year.night,0.3104471466666925 +2050,11,,wind,all-year.morning,-1.2843418666666744 +2050,11,,electricity,all-year.morning,1.2843418666666744 +2050,11,,wind,all-year.afternoon,-0.0 +2050,11,,electricity,all-year.afternoon,0.0 2050,11,,wind,all-year.early-peak,-0.0 2050,11,,electricity,all-year.early-peak,0.0 -2050,11,,wind,all-year.late-peak,-1.5989610666666736 -2050,11,,electricity,all-year.late-peak,1.5989610666666736 -2050,11,,wind,all-year.evening,-0.18333333333333351 -2050,11,,electricity,all-year.evening,0.18333333333333351 -2050,12,,electricity,all-year.night,-0.4079999999999999 -2050,12,,heat,all-year.night,1.0199999999999998 -2050,12,,electricity,all-year.morning,-0.4079999999999999 -2050,12,,heat,all-year.morning,1.0199999999999998 -2050,12,,electricity,all-year.afternoon,-0.4079999999999999 -2050,12,,heat,all-year.afternoon,1.0199999999999998 -2050,12,,electricity,all-year.early-peak,-0.4079999999999999 -2050,12,,heat,all-year.early-peak,1.0199999999999998 -2050,12,,electricity,all-year.late-peak,-0.4079999999999999 -2050,12,,heat,all-year.late-peak,1.0199999999999998 -2050,12,,electricity,all-year.evening,-0.4079999999999999 -2050,12,,heat,all-year.evening,1.0199999999999998 +2050,11,,wind,all-year.late-peak,-1.0380527999999964 +2050,11,,electricity,all-year.late-peak,1.0380527999999964 +2050,11,,wind,all-year.evening,-0.44957866666665564 +2050,11,,electricity,all-year.evening,0.44957866666665564 +2050,12,,electricity,all-year.night,-0.4079999999999993 +2050,12,,heat,all-year.night,1.0199999999999982 +2050,12,,electricity,all-year.morning,-0.4079999999999993 +2050,12,,heat,all-year.morning,1.0199999999999982 +2050,12,,electricity,all-year.afternoon,-0.4079999999999993 +2050,12,,heat,all-year.afternoon,1.0199999999999982 +2050,12,,electricity,all-year.early-peak,-0.4079999999999993 +2050,12,,heat,all-year.early-peak,1.0199999999999982 +2050,12,,electricity,all-year.late-peak,-0.4079999999999993 +2050,12,,heat,all-year.late-peak,1.0199999999999982 +2050,12,,electricity,all-year.evening,-0.4079999999999993 +2050,12,,heat,all-year.evening,1.0199999999999982 +2050,13,,wind,all-year.night,-0.0 +2050,13,,electricity,all-year.night,0.0 +2050,13,,wind,all-year.morning,-0.018759466666663015 +2050,13,,electricity,all-year.morning,0.018759466666663015 +2050,13,,wind,all-year.afternoon,-0.0 +2050,13,,electricity,all-year.afternoon,0.0 +2050,13,,wind,all-year.early-peak,-0.8562666666666686 +2050,13,,electricity,all-year.early-peak,0.8562666666666686 +2050,13,,wind,all-year.late-peak,-0.32374720000000445 +2050,13,,electricity,all-year.late-peak,0.32374720000000445 +2050,13,,wind,all-year.evening,-0.8562666666666686 +2050,13,,electricity,all-year.evening,0.8562666666666686 diff --git a/tests/data/muse1_default/commodity_prices.csv b/tests/data/muse1_default/commodity_prices.csv index 64282a75d..a71e86bc9 100644 --- a/tests/data/muse1_default/commodity_prices.csv +++ b/tests/data/muse1_default/commodity_prices.csv @@ -23,99 +23,99 @@ milestone_year,commodity_id,region_id,time_slice,price 2025,gas,R1,all-year.early-peak,2.55 2025,gas,R1,all-year.late-peak,2.55 2025,gas,R1,all-year.evening,2.55 -2025,electricity,R1,all-year.night,9.10681905636597 -2025,electricity,R1,all-year.morning,9.10681905636597 -2025,electricity,R1,all-year.afternoon,9.10681905636597 -2025,electricity,R1,all-year.early-peak,9.10681905636597 -2025,electricity,R1,all-year.late-peak,9.10681905636597 -2025,electricity,R1,all-year.evening,9.10681905636597 -2025,heat,R1,all-year.night,5.243983447471488 -2025,heat,R1,all-year.morning,5.243983447471488 -2025,heat,R1,all-year.afternoon,5.243983447471488 -2025,heat,R1,all-year.early-peak,5.243983447471488 -2025,heat,R1,all-year.late-peak,5.243983447471488 -2025,heat,R1,all-year.evening,5.243983447471488 +2025,electricity,R1,all-year.night,9.65322819974793 +2025,electricity,R1,all-year.morning,9.65322819974793 +2025,electricity,R1,all-year.afternoon,9.65322819974793 +2025,electricity,R1,all-year.early-peak,9.65322819974793 +2025,electricity,R1,all-year.late-peak,9.65322819974793 +2025,electricity,R1,all-year.evening,9.65322819974793 +2025,heat,R1,all-year.night,5.462547104824273 +2025,heat,R1,all-year.morning,5.462547104824273 +2025,heat,R1,all-year.afternoon,5.462547104824273 +2025,heat,R1,all-year.early-peak,5.462547104824273 +2025,heat,R1,all-year.late-peak,5.462547104824273 +2025,heat,R1,all-year.evening,5.462547104824273 2030,gas,R1,all-year.night,2.55 2030,gas,R1,all-year.morning,2.55 2030,gas,R1,all-year.afternoon,2.55 2030,gas,R1,all-year.early-peak,2.55 2030,gas,R1,all-year.late-peak,2.55 2030,gas,R1,all-year.evening,2.55 -2030,electricity,R1,all-year.night,13.26623148408186 -2030,electricity,R1,all-year.morning,13.26623148408186 -2030,electricity,R1,all-year.afternoon,13.26623148408186 -2030,electricity,R1,all-year.early-peak,17.144958382502967 -2030,electricity,R1,all-year.late-peak,17.144958382502967 -2030,electricity,R1,all-year.evening,13.26623148408186 -2030,heat,R1,all-year.night,6.643375974667771 -2030,heat,R1,all-year.morning,6.863686344576166 -2030,heat,R1,all-year.afternoon,6.643375974667771 -2030,heat,R1,all-year.early-peak,8.41517710394461 -2030,heat,R1,all-year.late-peak,8.635487473853004 -2030,heat,R1,all-year.evening,6.973841529530363 +2030,electricity,R1,all-year.night,14.062205373126778 +2030,electricity,R1,all-year.morning,14.062205373126778 +2030,electricity,R1,all-year.afternoon,14.062205373126778 +2030,electricity,R1,all-year.early-peak,16.37179310197454 +2030,electricity,R1,all-year.late-peak,16.37179310197454 +2030,electricity,R1,all-year.evening,14.062205373126778 +2030,heat,R1,all-year.night,6.9617655302857395 +2030,heat,R1,all-year.morning,7.182075900194134 +2030,heat,R1,all-year.afternoon,6.9617655302857395 +2030,heat,R1,all-year.early-peak,8.105910991733237 +2030,heat,R1,all-year.late-peak,8.326221361641633 +2030,heat,R1,all-year.evening,7.29223108514833 2035,gas,R1,all-year.night,2.55 2035,gas,R1,all-year.morning,2.55 2035,gas,R1,all-year.afternoon,2.55 2035,gas,R1,all-year.early-peak,2.55 2035,gas,R1,all-year.late-peak,2.55 2035,gas,R1,all-year.evening,2.55 -2035,electricity,R1,all-year.night,10.068872396801476 -2035,electricity,R1,all-year.morning,18.739470472145854 -2035,electricity,R1,all-year.afternoon,10.068872396801476 -2035,electricity,R1,all-year.early-peak,18.739470472145854 -2035,electricity,R1,all-year.late-peak,21.58083307849143 -2035,electricity,R1,all-year.evening,11.07336118383011 -2035,heat,R1,all-year.night,4.9186081545389895 -2035,heat,R1,all-year.morning,8.975706453590364 -2035,heat,R1,all-year.afternoon,4.9186081545389895 -2035,heat,R1,all-year.early-peak,8.975706453590364 -2035,heat,R1,all-year.late-peak,10.7100249310681 -2035,heat,R1,all-year.evening,6.20814945573382 +2035,electricity,R1,all-year.night,9.478501581776042 +2035,electricity,R1,all-year.morning,19.37287769444828 +2035,electricity,R1,all-year.afternoon,9.478501581776042 +2035,electricity,R1,all-year.early-peak,19.37287769444828 +2035,electricity,R1,all-year.late-peak,21.021891393596373 +2035,electricity,R1,all-year.evening,11.02993975624303 +2035,heat,R1,all-year.night,4.682459828528817 +2035,heat,R1,all-year.morning,9.229069342511336 +2035,heat,R1,all-year.afternoon,4.682459828528817 +2035,heat,R1,all-year.early-peak,9.229069342511336 +2035,heat,R1,all-year.late-peak,10.48644825711008 +2035,heat,R1,all-year.evening,6.190780884698987 2040,gas,R1,all-year.night,2.55 2040,gas,R1,all-year.morning,2.55 2040,gas,R1,all-year.afternoon,2.55 2040,gas,R1,all-year.early-peak,2.55 2040,gas,R1,all-year.late-peak,2.55 2040,gas,R1,all-year.evening,2.55 -2040,electricity,R1,all-year.night,9.629845703117574 -2040,electricity,R1,all-year.morning,9.629845703117574 -2040,electricity,R1,all-year.afternoon,13.175812746630996 -2040,electricity,R1,all-year.early-peak,12.01017482197773 -2040,electricity,R1,all-year.late-peak,23.99403044483585 -2040,electricity,R1,all-year.evening,9.629845703117574 -2040,heat,R1,all-year.night,4.777114953370514 -2040,heat,R1,all-year.morning,5.143194195559758 -2040,heat,R1,all-year.afternoon,6.195501770775883 -2040,heat,R1,all-year.early-peak,6.095325843103821 -2040,heat,R1,all-year.late-peak,11.846907489872624 -2040,heat,R1,all-year.evening,5.622213894372534 +2040,electricity,R1,all-year.night,9.601166804801505 +2040,electricity,R1,all-year.morning,9.601166804801505 +2040,electricity,R1,all-year.afternoon,12.926483543513156 +2040,electricity,R1,all-year.early-peak,13.957098141202538 +2040,electricity,R1,all-year.late-peak,24.604632153391805 +2040,electricity,R1,all-year.evening,9.601166804801505 +2040,heat,R1,all-year.night,4.765643394044087 +2040,heat,R1,all-year.morning,5.131722636233331 +2040,heat,R1,all-year.afternoon,6.095770089528747 +2040,heat,R1,all-year.early-peak,6.874095170793744 +2040,heat,R1,all-year.late-peak,12.091148173295005 +2040,heat,R1,all-year.evening,5.610742335046106 2045,gas,R1,all-year.night,2.55 2045,gas,R1,all-year.morning,2.55 2045,gas,R1,all-year.afternoon,2.55 2045,gas,R1,all-year.early-peak,2.55 2045,gas,R1,all-year.late-peak,2.55 2045,gas,R1,all-year.evening,2.55 -2045,electricity,R1,all-year.night,9.376936663519794 -2045,electricity,R1,all-year.morning,9.10681905636597 -2045,electricity,R1,all-year.afternoon,9.376936663519794 -2045,electricity,R1,all-year.early-peak,9.10681905636597 -2045,electricity,R1,all-year.late-peak,30.432763634160555 -2045,electricity,R1,all-year.evening,9.10681905636597 -2045,heat,R1,all-year.night,4.668787873306707 -2045,heat,R1,all-year.morning,4.67110307401771 -2045,heat,R1,all-year.afternoon,4.668787873306707 -2045,heat,R1,all-year.early-peak,4.67110307401771 -2045,heat,R1,all-year.late-peak,14.68886296055626 -2045,heat,R1,all-year.evening,5.4147941017280665 -2050,electricity,R1,all-year.night,16.798923166798442 -2050,electricity,R1,all-year.morning,9.10681905636597 +2045,electricity,R1,all-year.night,23.355937645204538 +2045,electricity,R1,all-year.morning,9.65322819974793 +2045,electricity,R1,all-year.afternoon,9.10681905636597 +2045,electricity,R1,all-year.early-peak,9.65322819974793 +2045,electricity,R1,all-year.late-peak,22.53648194423702 +2045,electricity,R1,all-year.evening,9.65322819974793 +2045,heat,R1,all-year.night,10.260388265980605 +2045,heat,R1,all-year.morning,4.889666731370493 +2045,heat,R1,all-year.afternoon,4.5607408304451775 +2045,heat,R1,all-year.early-peak,4.889666731370493 +2045,heat,R1,all-year.late-peak,11.530350284586847 +2045,heat,R1,all-year.evening,5.633357759080851 +2050,electricity,R1,all-year.night,13.950031755274162 +2050,electricity,R1,all-year.morning,12.62639280378593 2050,electricity,R1,all-year.afternoon,9.106819056365971 -2050,electricity,R1,all-year.early-peak,16.493799811800113 -2050,electricity,R1,all-year.late-peak,18.477613820639725 +2050,electricity,R1,all-year.early-peak,9.106819056365971 +2050,electricity,R1,all-year.late-peak,13.16881440683022 2050,electricity,R1,all-year.evening,9.10681905636597 -2050,heat,R1,all-year.night,7.60915583612221 -2050,heat,R1,all-year.morning,4.729959752198858 +2050,heat,R1,all-year.night,6.469599271512498 +2050,heat,R1,all-year.morning,6.137789251166843 2050,heat,R1,all-year.afternoon,4.532314191949222 -2050,heat,R1,all-year.early-peak,7.684752054372516 -2050,heat,R1,all-year.late-peak,9.932401361740286 -2050,heat,R1,all-year.evening,5.31653823306376 +2050,heat,R1,all-year.early-peak,4.729959752198858 +2050,heat,R1,all-year.late-peak,7.808881596216485 +2050,heat,R1,all-year.evening,5.316538233063761 diff --git a/tests/data/two_regions/asset_capacities.csv b/tests/data/two_regions/asset_capacities.csv index ccb4b86f0..c96a6e127 100644 --- a/tests/data/two_regions/asset_capacities.csv +++ b/tests/data/two_regions/asset_capacities.csv @@ -7,95 +7,95 @@ milestone_year,asset_id,group_id,capacity,num_units 2025,3,,19.0, 2025,4,,23.939952120095757, 2025,5,,4.939952120095759, -2025,6,,13.299973400053199, +2025,6,,14.097971804056394, 2025,7,,3.77034445931108, 2030,2,,24.0, 2030,3,,19.0, 2030,4,,23.939952120095757, 2030,5,,4.939952120095759, -2030,6,,13.299973400053199, +2030,6,,14.097971804056394, 2030,7,,3.77034445931108, 2030,8,,5.939988120023763, 2030,9,,5.939988120023761, -2030,10,,14.063371873256253, +2030,10,,13.42917314165371, 2030,11,,6.890386219227559, 2035,2,,24.0, 2035,3,,19.0, 2035,4,,23.939952120095757, 2035,5,,4.939952120095759, -2035,6,,13.299973400053199, +2035,6,,14.097971804056394, 2035,7,,3.77034445931108, 2035,8,,5.939988120023763, 2035,9,,5.939988120023761, -2035,10,,14.063371873256253, +2035,10,,13.42917314165371, 2035,11,,6.890386219227559, 2035,12,,6.119987760024477, 2035,13,,6.119987760024477, -2035,14,,8.487823024353967, +2035,14,,8.094703810592398, 2035,15,,7.099185801628392, 2040,2,,24.0, 2040,3,,19.0, 2040,4,,23.939952120095757, 2040,5,,4.939952120095759, -2040,6,,13.299973400053199, +2040,6,,14.097971804056394, 2040,7,,3.77034445931108, 2040,8,,5.939988120023763, 2040,9,,5.939988120023761, -2040,10,,14.063371873256253, +2040,10,,13.42917314165371, 2040,11,,6.890386219227559, 2040,12,,6.119987760024477, 2040,13,,6.119987760024477, -2040,14,,8.487823024353967, +2040,14,,8.094703810592398, 2040,15,,7.099185801628392, -2040,16,,5.939988120023762, +2040,16,,5.939988120023764, 2040,17,,5.939988120023761, -2040,18,,1.6330207339585008, +2040,18,,2.981386037227901, 2040,19,,6.8903862192275644, 2045,2,,24.0, 2045,3,,19.0, 2045,4,,23.939952120095757, 2045,5,,4.939952120095759, -2045,6,,13.299973400053199, +2045,6,,14.097971804056394, 2045,7,,3.77034445931108, 2045,8,,5.939988120023763, 2045,9,,5.939988120023761, -2045,10,,14.063371873256253, +2045,10,,13.42917314165371, 2045,11,,6.890386219227559, 2045,12,,6.119987760024477, 2045,13,,6.119987760024477, -2045,14,,8.487823024353967, +2045,14,,8.094703810592398, 2045,15,,7.099185801628392, -2045,16,,5.939988120023762, +2045,16,,5.939988120023764, 2045,17,,5.939988120023761, -2045,18,,1.6330207339585008, +2045,18,,2.981386037227901, 2045,19,,6.8903862192275644, -2045,20,,5.939988120023759, +2045,20,,5.939988120023764, 2045,21,,5.939988120023761, -2045,22,,9.593747212505615, +2045,22,,7.706035787928451, 2045,23,,6.8903862192275644, 2050,2,,24.0, 2050,3,,19.0, 2050,4,,23.939952120095757, 2050,5,,4.939952120095759, -2050,6,,13.299973400053199, +2050,6,,14.097971804056394, 2050,7,,3.77034445931108, 2050,8,,5.939988120023763, 2050,9,,5.939988120023761, -2050,10,,14.063371873256253, +2050,10,,13.42917314165371, 2050,11,,6.890386219227559, 2050,12,,6.119987760024477, 2050,13,,6.119987760024477, -2050,14,,8.487823024353967, +2050,14,,8.094703810592398, 2050,15,,7.099185801628392, -2050,16,,5.939988120023762, +2050,16,,5.939988120023764, 2050,17,,5.939988120023761, -2050,18,,1.6330207339585008, +2050,18,,2.981386037227901, 2050,19,,6.8903862192275644, -2050,20,,5.939988120023759, +2050,20,,5.939988120023764, 2050,21,,5.939988120023761, -2050,22,,9.593747212505615, +2050,22,,7.706035787928451, 2050,23,,6.8903862192275644, -2050,24,,6.1199877600244745, +2050,24,,6.119987760024469, 2050,25,,6.119987760024477, -2050,26,,5.851988296023411, +2050,26,,5.137589724820562, 2050,27,,7.099185801628382, diff --git a/tests/data/two_regions/commodity_flows.csv b/tests/data/two_regions/commodity_flows.csv index e9d74b91d..9db1e1301 100644 --- a/tests/data/two_regions/commodity_flows.csv +++ b/tests/data/two_regions/commodity_flows.csv @@ -301,8 +301,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2035,6,,electricity,all-year.afternoon,0.0 2035,6,,wind,all-year.early-peak,-0.0 2035,6,,electricity,all-year.early-peak,0.0 -2035,6,,wind,all-year.late-peak,-0.05610000000000015 -2035,6,,electricity,all-year.late-peak,0.05610000000000015 +2035,6,,wind,all-year.late-peak,-0.16180000000000117 +2035,6,,electricity,all-year.late-peak,0.16180000000000117 2035,6,,wind,all-year.evening,-1.5999999999999999 2035,6,,electricity,all-year.evening,1.5999999999999999 2035,7,,gas,all-year.night,0.6283919999999998 @@ -349,8 +349,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2035,10,,electricity,all-year.afternoon,0.8 2035,10,,wind,all-year.early-peak,-0.0 2035,10,,electricity,all-year.early-peak,0.0 -2035,10,,wind,all-year.late-peak,-2.3439 -2035,10,,electricity,all-year.late-peak,2.3439 +2035,10,,wind,all-year.late-peak,-2.238199999999999 +2035,10,,electricity,all-year.late-peak,2.238199999999999 2035,10,,wind,all-year.evening,-0.0 2035,10,,electricity,all-year.evening,0.0 2035,11,,gas,all-year.night,1.1483999999999996 @@ -467,8 +467,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,6,,electricity,all-year.morning,1.398 2040,6,,wind,all-year.afternoon,-0.932 2040,6,,electricity,all-year.afternoon,0.932 -2040,6,,wind,all-year.early-peak,-0.4205650666666689 -2040,6,,electricity,all-year.early-peak,0.4205650666666689 +2040,6,,wind,all-year.early-peak,-0.30337386666666916 +2040,6,,electricity,all-year.early-peak,0.30337386666666916 2040,6,,wind,all-year.late-peak,-0.0 2040,6,,electricity,all-year.late-peak,0.0 2040,6,,wind,all-year.evening,-0.0 @@ -517,10 +517,10 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,10,,electricity,all-year.afternoon,0.0 2040,10,,wind,all-year.early-peak,-0.0 2040,10,,electricity,all-year.early-peak,0.0 -2040,10,,wind,all-year.late-peak,-2.3439 -2040,10,,electricity,all-year.late-peak,2.3439 -2040,10,,wind,all-year.evening,-0.17718933333333536 -2040,10,,electricity,all-year.evening,0.17718933333333536 +2040,10,,wind,all-year.late-peak,-2.238199999999999 +2040,10,,electricity,all-year.late-peak,2.238199999999999 +2040,10,,wind,all-year.evening,-0.017981333333334338 +2040,10,,electricity,all-year.evening,0.017981333333334338 2040,11,,gas,all-year.night,0.0 2040,11,,gas,all-year.morning,1.1483999999999996 2040,11,,gas,all-year.afternoon,0.0 @@ -557,18 +557,18 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,13,,gas,all-year.evening,-1.1831999999999994 2040,13,,heat,all-year.evening,1.0199999999999996 2040,13,,CO2f,all-year.evening,66.00419999999997 -2040,14,,wind,all-year.night,-0.6598293333333377 -2040,14,,electricity,all-year.night,0.6598293333333377 +2040,14,,wind,all-year.night,-0.4351013333333375 +2040,14,,electricity,all-year.night,0.4351013333333375 2040,14,,wind,all-year.morning,-0.0 2040,14,,electricity,all-year.morning,0.0 2040,14,,wind,all-year.afternoon,-0.0 2040,14,,electricity,all-year.afternoon,0.0 -2040,14,,wind,all-year.early-peak,-0.9774349333333312 -2040,14,,electricity,all-year.early-peak,0.9774349333333312 -2040,14,,wind,all-year.late-peak,-0.34323173333333523 -2040,14,,electricity,all-year.late-peak,0.34323173333333523 -2040,14,,wind,all-year.evening,-1.4146400000000026 -2040,14,,electricity,all-year.evening,1.4146400000000026 +2040,14,,wind,all-year.early-peak,-1.094626133333331 +2040,14,,electricity,all-year.early-peak,1.094626133333331 +2040,14,,wind,all-year.late-peak,-0.3590405333333363 +2040,14,,electricity,all-year.late-peak,0.3590405333333363 +2040,14,,wind,all-year.evening,-1.3491200000000032 +2040,14,,electricity,all-year.evening,1.3491200000000032 2040,15,,gas,all-year.night,1.1831999999999994 2040,15,,gas,all-year.morning,1.1290079999999998 2040,15,,gas,all-year.afternoon,0.0 @@ -605,18 +605,18 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2040,17,,gas,all-year.evening,-1.1484 2040,17,,heat,all-year.evening,0.9900000000000002 2040,17,,CO2f,all-year.evening,64.06290000000001 -2040,18,,wind,all-year.night,-0.27217066666666234 -2040,18,,electricity,all-year.night,0.27217066666666234 +2040,18,,wind,all-year.night,-0.4968986666666626 +2040,18,,electricity,all-year.night,0.4968986666666626 2040,18,,wind,all-year.morning,-0.0 2040,18,,electricity,all-year.morning,0.0 2040,18,,wind,all-year.afternoon,-0.0 2040,18,,electricity,all-year.afternoon,0.0 2040,18,,wind,all-year.early-peak,-0.0 2040,18,,electricity,all-year.early-peak,0.0 -2040,18,,wind,all-year.late-peak,-0.10886826666666505 -2040,18,,electricity,all-year.late-peak,0.10886826666666505 -2040,18,,wind,all-year.evening,-0.27217066666666234 -2040,18,,electricity,all-year.evening,0.27217066666666234 +2040,18,,wind,all-year.late-peak,-0.198759466666665 +2040,18,,electricity,all-year.late-peak,0.198759466666665 +2040,18,,wind,all-year.evening,-0.4968986666666626 +2040,18,,electricity,all-year.evening,0.4968986666666626 2040,19,,gas,all-year.night,0.0 2040,19,,gas,all-year.morning,1.1484000000000005 2040,19,,gas,all-year.afternoon,1.1484000000000005 @@ -679,14 +679,14 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,5,,CO2f,all-year.evening,53.27749016999999 2045,6,,wind,all-year.night,-1.064 2045,6,,electricity,all-year.night,1.064 -2045,6,,wind,all-year.morning,-1.3238293333333377 -2045,6,,electricity,all-year.morning,1.3238293333333377 +2045,6,,wind,all-year.morning,-1.0991013333333375 +2045,6,,electricity,all-year.morning,1.0991013333333375 2045,6,,wind,all-year.afternoon,-0.0 2045,6,,electricity,all-year.afternoon,0.0 2045,6,,wind,all-year.early-peak,-0.0 2045,6,,electricity,all-year.early-peak,0.0 -2045,6,,wind,all-year.late-peak,-2.216666666666667 -2045,6,,electricity,all-year.late-peak,2.216666666666667 +2045,6,,wind,all-year.late-peak,-2.3496666666666672 +2045,6,,electricity,all-year.late-peak,2.3496666666666672 2045,6,,wind,all-year.evening,-0.0 2045,6,,electricity,all-year.evening,0.0 2045,7,,gas,all-year.night,0.0 @@ -731,12 +731,12 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,10,,electricity,all-year.morning,0.0 2045,10,,wind,all-year.afternoon,-0.0 2045,10,,electricity,all-year.afternoon,0.0 -2045,10,,wind,all-year.early-peak,-1.3238293333333377 -2045,10,,electricity,all-year.early-peak,1.3238293333333377 +2045,10,,wind,all-year.early-peak,-1.0991013333333375 +2045,10,,electricity,all-year.early-peak,1.0991013333333375 2045,10,,wind,all-year.late-peak,-0.0 2045,10,,electricity,all-year.late-peak,0.0 -2045,10,,wind,all-year.evening,-0.5290389333333294 -2045,10,,electricity,all-year.evening,0.5290389333333294 +2045,10,,wind,all-year.evening,-0.8436581333333291 +2045,10,,electricity,all-year.evening,0.8436581333333291 2045,11,,gas,all-year.night,0.0 2045,11,,gas,all-year.morning,0.0 2045,11,,gas,all-year.afternoon,1.1483999999999996 @@ -823,14 +823,14 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,17,,CO2f,all-year.evening,64.06290000000001 2045,18,,wind,all-year.night,-0.0 2045,18,,electricity,all-year.night,0.0 -2045,18,,wind,all-year.morning,-0.27217066666666234 -2045,18,,electricity,all-year.morning,0.27217066666666234 +2045,18,,wind,all-year.morning,-0.4968986666666626 +2045,18,,electricity,all-year.morning,0.4968986666666626 2045,18,,wind,all-year.afternoon,-0.0 2045,18,,electricity,all-year.afternoon,0.0 -2045,18,,wind,all-year.early-peak,-0.27217066666666234 -2045,18,,electricity,all-year.early-peak,0.27217066666666234 -2045,18,,wind,all-year.late-peak,-0.10886826666666505 -2045,18,,electricity,all-year.late-peak,0.10886826666666505 +2045,18,,wind,all-year.early-peak,-0.4968986666666626 +2045,18,,electricity,all-year.early-peak,0.4968986666666626 +2045,18,,wind,all-year.late-peak,-0.198759466666665 +2045,18,,electricity,all-year.late-peak,0.198759466666665 2045,18,,wind,all-year.evening,-0.0 2045,18,,electricity,all-year.evening,0.0 2045,19,,gas,all-year.night,0.0 @@ -877,10 +877,10 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2045,22,,electricity,all-year.afternoon,0.0 2045,22,,wind,all-year.early-peak,-0.0 2045,22,,electricity,all-year.early-peak,0.0 -2045,22,,wind,all-year.late-peak,-0.8664650666666689 -2045,22,,electricity,all-year.late-peak,0.8664650666666689 -2045,22,,wind,all-year.evening,-1.598961066666671 -2045,22,,electricity,all-year.evening,1.598961066666671 +2045,22,,wind,all-year.late-peak,-0.6435738666666685 +2045,22,,electricity,all-year.late-peak,0.6435738666666685 +2045,22,,wind,all-year.evening,-1.2843418666666713 +2045,22,,electricity,all-year.evening,1.2843418666666713 2045,23,,gas,all-year.night,0.0 2045,23,,gas,all-year.morning,0.0 2045,23,,gas,all-year.afternoon,1.1484000000000005 @@ -947,10 +947,10 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,6,,electricity,all-year.morning,0.0 2050,6,,wind,all-year.afternoon,-0.0 2050,6,,electricity,all-year.afternoon,0.0 -2050,6,,wind,all-year.early-peak,-0.11318933333333515 -2050,6,,electricity,all-year.early-peak,0.11318933333333515 -2050,6,,wind,all-year.late-peak,-2.216666666666667 -2050,6,,electricity,all-year.late-peak,2.216666666666667 +2050,6,,wind,all-year.early-peak,-0.0 +2050,6,,electricity,all-year.early-peak,0.0 +2050,6,,wind,all-year.late-peak,-2.3496666666666672 +2050,6,,electricity,all-year.late-peak,2.3496666666666672 2050,6,,wind,all-year.evening,-0.0 2050,6,,electricity,all-year.evening,0.0 2050,7,,gas,all-year.night,0.6283919999999998 @@ -999,8 +999,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,10,,electricity,all-year.early-peak,0.0 2050,10,,wind,all-year.late-peak,-0.0 2050,10,,electricity,all-year.late-peak,0.0 -2050,10,,wind,all-year.evening,-1.424666666666666 -2050,10,,electricity,all-year.evening,1.424666666666666 +2050,10,,wind,all-year.evening,-1.5437333333333316 +2050,10,,electricity,all-year.evening,1.5437333333333316 2050,11,,gas,all-year.night,1.1483999999999996 2050,11,,gas,all-year.morning,0.0 2050,11,,gas,all-year.afternoon,0.0 @@ -1039,12 +1039,12 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,13,,CO2f,all-year.evening,66.00419999999997 2050,14,,wind,all-year.night,-0.0 2050,14,,electricity,all-year.night,0.0 -2050,14,,wind,all-year.morning,-1.4146400000000026 -2050,14,,electricity,all-year.morning,1.4146400000000026 +2050,14,,wind,all-year.morning,-1.3031013333333377 +2050,14,,electricity,all-year.morning,1.3031013333333377 2050,14,,wind,all-year.afternoon,-0.0 2050,14,,electricity,all-year.afternoon,0.0 -2050,14,,wind,all-year.early-peak,-1.4146400000000026 -2050,14,,electricity,all-year.early-peak,1.4146400000000026 +2050,14,,wind,all-year.early-peak,-1.3491200000000032 +2050,14,,electricity,all-year.early-peak,1.3491200000000032 2050,14,,wind,all-year.late-peak,-0.0 2050,14,,electricity,all-year.late-peak,0.0 2050,14,,wind,all-year.evening,-0.0 @@ -1087,12 +1087,12 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,17,,CO2f,all-year.evening,64.06290000000001 2050,18,,wind,all-year.night,-0.0 2050,18,,electricity,all-year.night,0.0 -2050,18,,wind,all-year.morning,-0.27217066666666234 -2050,18,,electricity,all-year.morning,0.27217066666666234 +2050,18,,wind,all-year.morning,-0.4968986666666626 +2050,18,,electricity,all-year.morning,0.4968986666666626 2050,18,,wind,all-year.afternoon,-0.0 2050,18,,electricity,all-year.afternoon,0.0 -2050,18,,wind,all-year.early-peak,-0.27217066666666234 -2050,18,,electricity,all-year.early-peak,0.27217066666666234 +2050,18,,wind,all-year.early-peak,-0.4508799999999969 +2050,18,,electricity,all-year.early-peak,0.4508799999999969 2050,18,,wind,all-year.late-peak,-0.0 2050,18,,electricity,all-year.late-peak,0.0 2050,18,,wind,all-year.evening,-0.0 @@ -1141,8 +1141,8 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,22,,electricity,all-year.afternoon,1.2 2050,22,,wind,all-year.early-peak,-0.0 2050,22,,electricity,all-year.early-peak,0.0 -2050,22,,wind,all-year.late-peak,-1.3833333333333333 -2050,22,,electricity,all-year.late-peak,1.3833333333333333 +2050,22,,wind,all-year.late-peak,-1.2503333333333329 +2050,22,,electricity,all-year.late-peak,1.2503333333333329 2050,22,,wind,all-year.evening,-0.0 2050,22,,electricity,all-year.evening,0.0 2050,23,,gas,all-year.night,0.0 @@ -1183,16 +1183,16 @@ milestone_year,asset_id,group_id,commodity_id,time_slice,flow 2050,25,,CO2f,all-year.evening,66.00419999999997 2050,26,,wind,all-year.night,-0.0 2050,26,,electricity,all-year.night,0.0 -2050,26,,wind,all-year.morning,-0.11318933333333524 -2050,26,,electricity,all-year.morning,0.11318933333333524 +2050,26,,wind,all-year.morning,-0.0 +2050,26,,electricity,all-year.morning,0.0 2050,26,,wind,all-year.afternoon,-0.0 2050,26,,electricity,all-year.afternoon,0.0 2050,26,,wind,all-year.early-peak,-0.0 2050,26,,electricity,all-year.early-peak,0.0 2050,26,,wind,all-year.late-peak,-0.0 2050,26,,electricity,all-year.late-peak,0.0 -2050,26,,wind,all-year.evening,-0.9753333333333343 -2050,26,,electricity,all-year.evening,0.9753333333333343 +2050,26,,wind,all-year.evening,-0.8562666666666686 +2050,26,,electricity,all-year.evening,0.8562666666666686 2050,27,,gas,all-year.night,0.0 2050,27,,gas,all-year.morning,1.1831999999999976 2050,27,,gas,all-year.afternoon,1.1831999999999976 diff --git a/tests/data/two_regions/commodity_prices.csv b/tests/data/two_regions/commodity_prices.csv index c86856942..332f18603 100644 --- a/tests/data/two_regions/commodity_prices.csv +++ b/tests/data/two_regions/commodity_prices.csv @@ -47,24 +47,24 @@ milestone_year,commodity_id,region_id,time_slice,price 2025,gas,R2,all-year.early-peak,2.5499999999999994 2025,gas,R2,all-year.late-peak,2.55 2025,gas,R2,all-year.evening,2.55 -2025,electricity,R1,all-year.night,9.10681905636597 -2025,electricity,R1,all-year.morning,9.10681905636597 -2025,electricity,R1,all-year.afternoon,9.10681905636597 -2025,electricity,R1,all-year.early-peak,9.10681905636597 -2025,electricity,R1,all-year.late-peak,9.10681905636597 -2025,electricity,R1,all-year.evening,9.10681905636597 +2025,electricity,R1,all-year.night,9.65322819974793 +2025,electricity,R1,all-year.morning,9.65322819974793 +2025,electricity,R1,all-year.afternoon,9.65322819974793 +2025,electricity,R1,all-year.early-peak,9.65322819974793 +2025,electricity,R1,all-year.late-peak,9.65322819974793 +2025,electricity,R1,all-year.evening,9.65322819974793 2025,electricity,R2,all-year.night,6.909684587351732 2025,electricity,R2,all-year.morning,6.909684587351731 2025,electricity,R2,all-year.afternoon,6.909684587351732 2025,electricity,R2,all-year.early-peak,6.909684587351731 2025,electricity,R2,all-year.late-peak,6.909684587351732 2025,electricity,R2,all-year.evening,6.909684587351732 -2025,heat,R1,all-year.night,5.243983447471488 -2025,heat,R1,all-year.morning,5.243983447471488 -2025,heat,R1,all-year.afternoon,5.243983447471488 -2025,heat,R1,all-year.early-peak,5.243983447471488 -2025,heat,R1,all-year.late-peak,5.243983447471488 -2025,heat,R1,all-year.evening,5.243983447471488 +2025,heat,R1,all-year.night,5.462547104824273 +2025,heat,R1,all-year.morning,5.462547104824273 +2025,heat,R1,all-year.afternoon,5.462547104824273 +2025,heat,R1,all-year.early-peak,5.462547104824273 +2025,heat,R1,all-year.late-peak,5.462547104824273 +2025,heat,R1,all-year.evening,5.462547104824273 2025,heat,R2,all-year.night,3.5241019932677498 2025,heat,R2,all-year.morning,3.6242273910425467 2025,heat,R2,all-year.afternoon,3.5241019932677498 @@ -83,24 +83,24 @@ milestone_year,commodity_id,region_id,time_slice,price 2030,gas,R2,all-year.early-peak,2.5500000000000003 2030,gas,R2,all-year.late-peak,2.55 2030,gas,R2,all-year.evening,2.5500000000000003 -2030,electricity,R1,all-year.night,12.160712193741707 -2030,electricity,R1,all-year.morning,19.288078180315843 -2030,electricity,R1,all-year.afternoon,19.288078180315843 -2030,electricity,R1,all-year.early-peak,19.288078180315843 -2030,electricity,R1,all-year.late-peak,12.160712193741707 -2030,electricity,R1,all-year.evening,12.160712193741707 +2030,electricity,R1,all-year.night,12.89035492536621 +2030,electricity,R1,all-year.morning,18.41826723972136 +2030,electricity,R1,all-year.afternoon,18.41826723972136 +2030,electricity,R1,all-year.early-peak,18.41826723972136 +2030,electricity,R1,all-year.late-peak,12.890354925366212 +2030,electricity,R1,all-year.evening,12.89035492536621 2030,electricity,R2,all-year.night,6.909684587351732 2030,electricity,R2,all-year.morning,6.909684587351732 2030,electricity,R2,all-year.afternoon,6.909684587351732 2030,electricity,R2,all-year.early-peak,6.909684587351733 2030,electricity,R2,all-year.late-peak,6.909684587351732 2030,electricity,R2,all-year.evening,6.909684587351733 -2030,heat,R1,all-year.night,6.201168258531711 -2030,heat,R1,all-year.morning,9.272425023069758 -2030,heat,R1,all-year.afternoon,9.052114653161365 -2030,heat,R1,all-year.early-peak,9.272425023069758 -2030,heat,R1,all-year.late-peak,6.641788998348498 -2030,heat,R1,all-year.evening,6.531633813394302 +2030,heat,R1,all-year.night,6.493025351181513 +2030,heat,R1,all-year.morning,8.924500646831964 +2030,heat,R1,all-year.afternoon,8.70419027692357 +2030,heat,R1,all-year.early-peak,8.924500646831964 +2030,heat,R1,all-year.late-peak,6.933646090998301 +2030,heat,R1,all-year.evening,6.823490906044104 2030,heat,R2,all-year.night,3.349435775962629 2030,heat,R2,all-year.morning,3.570625076745362 2030,heat,R2,all-year.afternoon,3.349435775962629 @@ -119,24 +119,24 @@ milestone_year,commodity_id,region_id,time_slice,price 2035,gas,R2,all-year.early-peak,2.55 2035,gas,R2,all-year.late-peak,2.55 2035,gas,R2,all-year.evening,2.55 -2035,electricity,R1,all-year.night,9.959201315523021 -2035,electricity,R1,all-year.morning,9.959201315523021 -2035,electricity,R1,all-year.afternoon,9.959201315523021 -2035,electricity,R1,all-year.early-peak,25.76574101979516 -2035,electricity,R1,all-year.late-peak,10.410227509834195 -2035,electricity,R1,all-year.evening,29.254439574824563 +2035,electricity,R1,all-year.night,9.70960219695525 +2035,electricity,R1,all-year.morning,9.70960219695525 +2035,electricity,R1,all-year.afternoon,9.70960219695525 +2035,electricity,R1,all-year.early-peak,24.572383450648974 +2035,electricity,R1,all-year.late-peak,11.020159423915336 +2035,electricity,R1,all-year.evening,29.14926440155464 2035,electricity,R2,all-year.night,6.909684587351731 2035,electricity,R2,all-year.morning,6.909684587351732 2035,electricity,R2,all-year.afternoon,6.909684587351732 2035,electricity,R2,all-year.early-peak,6.909684587351732 2035,electricity,R2,all-year.late-peak,6.909684587351732 2035,electricity,R2,all-year.evening,6.909684587351732 -2035,heat,R1,all-year.night,4.874739722027607 -2035,heat,R1,all-year.morning,5.463598790941231 -2035,heat,R1,all-year.afternoon,4.874739722027607 -2035,heat,R1,all-year.early-peak,11.786214672650088 -2035,heat,R1,all-year.late-peak,6.241782703605208 -2035,heat,R1,all-year.evening,13.4805808121316 +2035,heat,R1,all-year.night,4.774900074600501 +2035,heat,R1,all-year.morning,5.363759143514123 +2035,heat,R1,all-year.afternoon,4.774900074600501 +2035,heat,R1,all-year.early-peak,11.308871644991612 +2035,heat,R1,all-year.late-peak,6.485755469237663 +2035,heat,R1,all-year.evening,13.438510742823631 2035,heat,R2,all-year.night,3.339882498137114 2035,heat,R2,all-year.morning,3.457049148555352 2035,heat,R2,all-year.afternoon,3.3398824981371145 @@ -155,24 +155,24 @@ milestone_year,commodity_id,region_id,time_slice,price 2040,gas,R2,all-year.early-peak,2.55 2040,gas,R2,all-year.late-peak,2.5500000000000003 2040,gas,R2,all-year.evening,2.55 -2040,electricity,R1,all-year.night,9.106819056365968 -2040,electricity,R1,all-year.morning,17.61393612061686 -2040,electricity,R1,all-year.afternoon,17.61393612061686 -2040,electricity,R1,all-year.early-peak,11.666043845541815 -2040,electricity,R1,all-year.late-peak,18.50708122017119 -2040,electricity,R1,all-year.evening,10.172751595699916 +2040,electricity,R1,all-year.night,9.10681905636597 +2040,electricity,R1,all-year.morning,19.50166464120968 +2040,electricity,R1,all-year.afternoon,19.50166464120968 +2040,electricity,R1,all-year.early-peak,11.362559040970398 +2040,electricity,R1,all-year.late-peak,19.17340023174235 +2040,electricity,R1,all-year.evening,9.228128960513171 2040,electricity,R2,all-year.night,6.909684587351732 2040,electricity,R2,all-year.morning,6.909684587351732 2040,electricity,R2,all-year.afternoon,6.909684587351732 2040,electricity,R2,all-year.early-peak,6.909684587351732 2040,electricity,R2,all-year.late-peak,6.909684587351733 2040,electricity,R2,all-year.evening,6.909684587351732 -2040,heat,R1,all-year.night,4.567904294669871 -2040,heat,R1,all-year.morning,8.336830362559471 -2040,heat,R1,all-year.afternoon,7.970751120370229 -2040,heat,R1,all-year.early-peak,5.957673452529455 -2040,heat,R1,all-year.late-peak,9.652127800006756 -2040,heat,R1,all-year.evening,5.83937625140547 +2040,heat,R1,all-year.night,4.567904294669872 +2040,heat,R1,all-year.morning,9.0919217707966 +2040,heat,R1,all-year.afternoon,8.725842528607355 +2040,heat,R1,all-year.early-peak,5.836279530700889 +2040,heat,R1,all-year.late-peak,9.91865540463522 +2040,heat,R1,all-year.evening,5.461527197330772 2040,heat,R2,all-year.night,3.354504273146746 2040,heat,R2,all-year.morning,3.4178807441840786 2040,heat,R2,all-year.afternoon,3.354504273146746 @@ -191,24 +191,24 @@ milestone_year,commodity_id,region_id,time_slice,price 2045,gas,R2,all-year.early-peak,2.5499999999999994 2045,gas,R2,all-year.late-peak,2.55 2045,gas,R2,all-year.evening,2.55 -2045,electricity,R1,all-year.night,10.521950150432732 -2045,electricity,R1,all-year.morning,10.28062360075048 -2045,electricity,R1,all-year.afternoon,29.05910641330281 -2045,electricity,R1,all-year.early-peak,24.4865796077581 -2045,electricity,R1,all-year.late-peak,11.46530828099638 -2045,electricity,R1,all-year.evening,17.524660345687906 +2045,electricity,R1,all-year.night,11.379972119696589 +2045,electricity,R1,all-year.morning,10.672248606978403 +2045,electricity,R1,all-year.afternoon,27.71321441802516 +2045,electricity,R1,all-year.early-peak,20.175858671822397 +2045,electricity,R1,all-year.late-peak,11.879649416846998 +2045,electricity,R1,all-year.evening,18.77059486818403 2045,electricity,R2,all-year.night,6.909684587351732 2045,electricity,R2,all-year.morning,6.909684587351731 2045,electricity,R2,all-year.afternoon,6.909684587351733 2045,electricity,R2,all-year.early-peak,6.909684587351731 2045,electricity,R2,all-year.late-peak,6.909684587351732 2045,electricity,R2,all-year.evening,6.909684587351732 -2045,heat,R1,all-year.night,5.126793268071882 -2045,heat,R1,all-year.morning,5.140624891771514 -2045,heat,R1,all-year.afternoon,12.541655773219913 -2045,heat,R1,all-year.early-peak,10.82300729457456 -2045,heat,R1,all-year.late-peak,7.101880819290589 -2045,heat,R1,all-year.evening,8.78193061745684 +2045,heat,R1,all-year.night,5.4700020557774245 +2045,heat,R1,all-year.morning,5.297274894262683 +2045,heat,R1,all-year.afternoon,12.003298975108855 +2045,heat,R1,all-year.early-peak,9.09871892020028 +2045,heat,R1,all-year.late-peak,7.267617273630837 +2045,heat,R1,all-year.evening,9.280304426455292 2045,heat,R2,all-year.night,3.3514342171658638 2045,heat,R2,all-year.morning,3.3987323197759665 2045,heat,R2,all-year.afternoon,3.351434217165864 @@ -221,18 +221,18 @@ milestone_year,commodity_id,region_id,time_slice,price 2050,gas,R2,all-year.early-peak,2.55 2050,gas,R2,all-year.late-peak,2.5500000000000003 2050,gas,R2,all-year.evening,2.55 -2050,electricity,R1,all-year.night,13.725284368503115 -2050,electricity,R1,all-year.morning,11.472464005188344 -2050,electricity,R1,all-year.afternoon,13.528055949498391 -2050,electricity,R1,all-year.early-peak,11.104072897721645 -2050,electricity,R1,all-year.late-peak,13.649497522311485 -2050,electricity,R1,all-year.evening,29.304049130474574 -2050,heat,R1,all-year.night,6.37970031680408 -2050,heat,R1,all-year.morning,5.6762177317278075 -2050,heat,R1,all-year.afternoon,6.300808949202191 -2050,heat,R1,all-year.early-peak,5.52886128874113 -2050,heat,R1,all-year.late-peak,8.00115484240899 -2050,heat,R1,all-year.evening,13.395430262707203 +2050,electricity,R1,all-year.night,14.46760466409775 +2050,electricity,R1,all-year.morning,11.211930904564163 +2050,electricity,R1,all-year.afternoon,11.456010978232966 +2050,electricity,R1,all-year.early-peak,11.203213058112226 +2050,electricity,R1,all-year.late-peak,13.42163356079416 +2050,electricity,R1,all-year.evening,28.180748009289285 +2050,heat,R1,all-year.night,6.676628435041934 +2050,heat,R1,all-year.morning,5.572004491478135 +2050,heat,R1,all-year.afternoon,5.47199096069602 +2050,heat,R1,all-year.early-peak,5.568517352897361 +2050,heat,R1,all-year.late-peak,7.9100092578020575 +2050,heat,R1,all-year.evening,12.946109814233088 2050,heat,R2,all-year.night,3.3392513725541697 2050,heat,R2,all-year.morning,3.42395660947675 2050,heat,R2,all-year.afternoon,3.33925137255417