Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use crate::simulation::investment::appraisal::LCOXMetric;
use crate::simulation::investment::appraisal::{
AppraisalOutput, coefficients::ObjectiveCoefficients,
};
use crate::time_slice::{TimeSliceID, TimeSliceInfo, TimeSliceLevel};
use crate::time_slice::{TimeSliceID, TimeSliceInfo, TimeSliceLevel, TimeSliceSelection};
use crate::units::{
Activity, ActivityPerCapacity, Capacity, Dimensionless, Flow, MoneyPerActivity,
MoneyPerCapacity, MoneyPerCapacityPerYear, MoneyPerFlow, Year,
MoneyPerCapacity, MoneyPerCapacityPerYear, Year,
};
use anyhow::Result;
use indexmap::indexmap;
Expand Down Expand Up @@ -75,7 +75,7 @@ pub(crate) use patch_and_validate_simple;
/// Check whether validation succeeds for simple example with patches
macro_rules! assert_validate_ok_simple {
($file_patches:expr) => {
assert!(crate::fixture::patch_and_validate_simple!($file_patches).is_ok())
crate::fixture::patch_and_validate_simple!($file_patches).unwrap();
};
}
pub(crate) use assert_validate_ok_simple;
Expand Down Expand Up @@ -116,7 +116,7 @@ pub(crate) use patch_and_run_simple;
/// Check whether the simple example runs successfully after applying file patches
macro_rules! assert_patched_runs_ok_simple {
($file_patches:expr) => {
assert!(crate::fixture::patch_and_run_simple!($file_patches).is_ok())
crate::fixture::patch_and_run_simple!($file_patches).unwrap();
};
}
pub(crate) use assert_patched_runs_ok_simple;
Expand Down Expand Up @@ -403,15 +403,13 @@ pub fn appraisal_output(asset: Asset, time_slice: TimeSliceID) -> AppraisalOutpu
let activity_coefficients = indexmap! { time_slice.clone() => MoneyPerActivity(0.5) };
let market_costs = indexmap! { time_slice.clone() => MoneyPerActivity(0.4) };
let activity = indexmap! { time_slice.clone() => Activity(10.0) };
let unmet_demand = indexmap! { time_slice.clone() => Flow(5.0) };
let unmet_demand = indexmap! { TimeSliceSelection::Single(time_slice.clone()) => Flow(5.0) };
AppraisalOutput {
asset: AssetRef::from(asset),
capacity: AssetCapacity::Continuous(Capacity(42.0)),
coefficients: Rc::new(ObjectiveCoefficients {
capacity_coefficient: MoneyPerCapacity(2.14),
activity_coefficients,
market_costs,
unmet_demand_coefficient: MoneyPerFlow(10000.0),
}),
activity,
unmet_demand,
Expand Down
47 changes: 28 additions & 19 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ use crate::region::RegionID;
use crate::simulation::investment::appraisal::AppraisalOutput;
use crate::simulation::optimisation::{FlowMap, Solution};
use crate::simulation::prices::PriceMap;
use crate::time_slice::TimeSliceID;
use crate::units::{
Activity, Capacity, Flow, Money, MoneyPerActivity, MoneyPerCapacity, MoneyPerFlow,
};
use crate::time_slice::{TimeSliceID, TimeSliceLevel, TimeSliceSelection};
use crate::units::{Activity, Capacity, Flow, Money, MoneyPerActivity, MoneyPerFlow};
use anyhow::{Context, Result, ensure};
use csv;
use indexmap::IndexMap;
Expand Down Expand Up @@ -261,7 +259,6 @@ struct AppraisalResultsRow {
process_id: ProcessID,
region_id: RegionID,
capacity: Capacity,
capacity_coefficient: MoneyPerCapacity,
metric: Option<f64>,
}

Expand All @@ -274,10 +271,11 @@ struct AppraisalResultsTimeSliceRow {
process_id: ProcessID,
region_id: RegionID,
time_slice: TimeSliceID,
time_slice_level: TimeSliceLevel,
activity: Activity,
activity_coefficient: MoneyPerActivity,
demand: Flow,
unmet_demand: Flow,
demand_for_selection: Flow,
unmet_demand_for_selection: Flow,
}

/// For writing extra debug information about the model
Expand Down Expand Up @@ -495,7 +493,6 @@ impl DebugDataWriter {
process_id: result.asset.process_id().clone(),
region_id: result.asset.region_id().clone(),
capacity: result.capacity.total_capacity(),
capacity_coefficient: result.coefficients.capacity_coefficient,
metric: result.metric.as_ref().map(|m| m.value()),
};
self.appraisal_results_writer.serialize(row)?;
Expand All @@ -510,24 +507,33 @@ impl DebugDataWriter {
milestone_year: u32,
run_description: &str,
appraisal_results: &[AppraisalOutput],
demand: &IndexMap<TimeSliceID, Flow>,
demand: &IndexMap<TimeSliceSelection, Flow>,
time_slice_level: TimeSliceLevel,
) -> Result<()> {
for result in appraisal_results {
for (time_slice, activity) in &result.activity {
let activity_coefficient = result.coefficients.activity_coefficients[time_slice];
let demand = demand[time_slice];
let unmet_demand = result.unmet_demand[time_slice];
// Map the individual time slice back to its containing selection so we can look
// up selection-level demand and unmet demand.
let selection = match time_slice_level {
TimeSliceLevel::Annual => TimeSliceSelection::Annual,
TimeSliceLevel::Season => TimeSliceSelection::Season(time_slice.season.clone()),
TimeSliceLevel::DayNight => TimeSliceSelection::Single(time_slice.clone()),
};
let demand = demand[&selection];
let unmet_demand = result.unmet_demand[&selection];
let row = AppraisalResultsTimeSliceRow {
milestone_year,
run_description: self.with_context(run_description),
asset_id: result.asset.id(),
process_id: result.asset.process_id().clone(),
region_id: result.asset.region_id().clone(),
time_slice: time_slice.clone(),
time_slice_level,
activity: *activity,
activity_coefficient,
demand,
unmet_demand,
demand_for_selection: demand,
unmet_demand_for_selection: unmet_demand,
};
self.appraisal_results_time_slice_writer.serialize(row)?;
}
Expand Down Expand Up @@ -610,7 +616,8 @@ impl DataWriter {
milestone_year: u32,
run_description: &str,
appraisal_results: &[AppraisalOutput],
demand: &IndexMap<TimeSliceID, Flow>,
demand: &IndexMap<TimeSliceSelection, Flow>,
time_slice_level: TimeSliceLevel,
) -> Result<()> {
if let Some(wtr) = &mut self.debug {
wtr.write_appraisal_results(milestone_year, run_description, appraisal_results)?;
Expand All @@ -619,6 +626,7 @@ impl DataWriter {
run_description,
appraisal_results,
demand,
time_slice_level,
)?;
}

Expand Down Expand Up @@ -760,7 +768,7 @@ mod tests {
appraisal_output, asset, asset_divisible, assets, commodity_id, region_id, time_slice,
};
use crate::simulation::investment::appraisal::AppraisalOutput;
use crate::time_slice::TimeSliceID;
use crate::time_slice::{TimeSliceID, TimeSliceLevel, TimeSliceSelection};
use indexmap::indexmap;
use itertools::{Itertools, assert_equal};
use rstest::rstest;
Expand Down Expand Up @@ -1195,7 +1203,6 @@ mod tests {
process_id: asset.process_id().clone(),
region_id: asset.region_id().clone(),
capacity: Capacity(42.0),
capacity_coefficient: MoneyPerCapacity(2.14),
metric: Some(4.14),
};
let records: Vec<AppraisalResultsRow> =
Expand All @@ -1216,7 +1223,7 @@ mod tests {
let milestone_year = 2020;
let run_description = "test_run".to_string();
let dir = tempdir().unwrap();
let demand = indexmap! {time_slice.clone() => Flow(100.0) };
let demand = indexmap! {TimeSliceSelection::Single(time_slice.clone()) => Flow(100.0) };

// Write appraisal time slice results
{
Expand All @@ -1227,6 +1234,7 @@ mod tests {
&run_description,
&[appraisal_output],
&demand,
TimeSliceLevel::DayNight,
)
.unwrap();
writer.flush().unwrap();
Expand All @@ -1240,10 +1248,11 @@ mod tests {
process_id: asset.process_id().clone(),
region_id: asset.region_id().clone(),
time_slice: time_slice.clone(),
time_slice_level: TimeSliceLevel::DayNight,
activity: Activity(10.0),
activity_coefficient: MoneyPerActivity(0.5),
demand: Flow(100.0),
unmet_demand: Flow(5.0),
demand_for_selection: Flow(100.0),
unmet_demand_for_selection: Flow(5.0),
};
let records: Vec<AppraisalResultsTimeSliceRow> =
csv::Reader::from_path(dir.path().join(APPRAISAL_RESULTS_TIME_SLICE_FILE_NAME))
Expand Down
Loading
Loading