From 9fc69c4445efc3c63f3c34f793788e2b09d6c8df Mon Sep 17 00:00:00 2001 From: Tom Bland Date: Thu, 23 Jan 2025 13:57:11 +0000 Subject: [PATCH 1/3] Add validate_flows function --- src/input/process/flow.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/input/process/flow.rs b/src/input/process/flow.rs index f5d164f3f..e9a5ff918 100644 --- a/src/input/process/flow.rs +++ b/src/input/process/flow.rs @@ -86,11 +86,36 @@ where }) .process_results(|iter| iter.into_id_map(process_ids))??; + validate_flows(&flows)?; validate_pac_flows(&flows)?; Ok(flows) } +/// Validate that no process has multiple flows for the same commodity. +/// +/// # Arguments +/// * `flows` - A map of process IDs to process flows +/// +/// # Returns +/// An `Ok(())` if the check is successful, or an error. +fn validate_flows(flows: &HashMap, Vec>) -> Result<()> { + for (process_id, flows) in flows.iter() { + let mut commodities: HashSet> = HashSet::new(); + + for flow in flows.iter() { + let commodity_id = &flow.commodity.id; + ensure!( + !commodities.contains(commodity_id), + "Process {process_id} has multiple flows for commodity {commodity_id}", + ); + commodities.insert(Rc::clone(commodity_id)); + } + } + + Ok(()) +} + /// Validate that the PACs for each process are either all inputs or all outputs. /// /// # Arguments From fe55811220e2fe72dbea1f2a0e414ae6435f0bad Mon Sep 17 00:00:00 2001 From: Tom Bland Date: Thu, 23 Jan 2025 14:10:37 +0000 Subject: [PATCH 2/3] Add test --- src/input/process/flow.rs | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/input/process/flow.rs b/src/input/process/flow.rs index e9a5ff918..eeb4af590 100644 --- a/src/input/process/flow.rs +++ b/src/input/process/flow.rs @@ -448,4 +448,48 @@ mod tests { assert!(!is_flow_cost_ok!(f64::INFINITY)); assert!(!is_flow_cost_ok!(f64::NAN)); } + + #[test] + fn test_read_process_flows_from_iter_duplicate_flow() { + let process_ids = iter::once("id1".into()).collect(); + let commodities = ["commodity1"] + .into_iter() + .map(|id| { + let commodity = Commodity { + id: id.into(), + description: "Some description".into(), + kind: CommodityType::InputCommodity, + time_slice_level: TimeSliceLevel::Annual, + costs: CommodityCostMap::new(), + demand: DemandMap::new(), + }; + + (Rc::clone(&commodity.id), commodity.into()) + }) + .collect(); + + let flows_raw = [ + ProcessFlowRaw { + process_id: "id1".into(), + commodity_id: "commodity1".into(), + flow: 1.0, + flow_type: FlowType::Fixed, + flow_cost: Some(1.0), + is_pac: true, + }, + ProcessFlowRaw { + process_id: "id1".into(), + commodity_id: "commodity1".into(), + flow: 1.0, + flow_type: FlowType::Fixed, + flow_cost: Some(1.0), + is_pac: false, + }, + ]; + + assert!( + read_process_flows_from_iter(flows_raw.into_iter(), &process_ids, &commodities) + .is_err() + ); + } } From 6a0852eb33fd390c287ce3f6503486be48582643 Mon Sep 17 00:00:00 2001 From: Tom Bland Date: Thu, 23 Jan 2025 16:07:15 +0000 Subject: [PATCH 3/3] Update src/input/process/flow.rs Co-authored-by: Alex Dewar --- src/input/process/flow.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/input/process/flow.rs b/src/input/process/flow.rs index eeb4af590..e9f0b8123 100644 --- a/src/input/process/flow.rs +++ b/src/input/process/flow.rs @@ -106,10 +106,9 @@ fn validate_flows(flows: &HashMap, Vec>) -> Result<()> { for flow in flows.iter() { let commodity_id = &flow.commodity.id; ensure!( - !commodities.contains(commodity_id), + commodities.insert(Rc::clone(commodity_id)), "Process {process_id} has multiple flows for commodity {commodity_id}", ); - commodities.insert(Rc::clone(commodity_id)); } }