Skip to content

Commit e4272e0

Browse files
committed
Allow for output without graph validation
1 parent 99e968b commit e4272e0

6 files changed

Lines changed: 78 additions & 27 deletions

File tree

src/cli.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! The command line interface for the simulation.
2-
use crate::graph::save_commodity_graphs_for_model;
3-
use crate::input::load_model;
2+
use crate::input::{load_commodity_graphs, load_model};
43
use crate::log;
4+
use crate::output::graph::save_commodity_graphs_for_model;
55
use crate::output::{create_output_directory, get_output_dir};
66
use crate::settings::Settings;
77
use ::log::{info, warn};
@@ -207,12 +207,9 @@ pub fn handle_build_commodity_graphs_command(
207207
// Initialise program logger (we won't save log files when running the validate command)
208208
log::init(&settings.log_level, None).context("Failed to initialise logging.")?;
209209

210-
// Load/validate the model
211-
let (model, _) = load_model(model_path).context("Failed to load model.")?;
212-
info!("Loaded model from {}", model_path.display());
213-
214-
// Save commodity flow graphs to file
215-
save_commodity_graphs_for_model(&model.commodity_graphs, output_path)?;
210+
// Load commodity flow graphs and save to file
211+
let commodity_graphs = load_commodity_graphs(model_path)?;
212+
save_commodity_graphs_for_model(&commodity_graphs, output_path)?;
216213
info!("Commodity flow graphs saved to file");
217214

218215
Ok(())

src/graph.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use petgraph::algo::toposort;
1212
use petgraph::graph::Graph;
1313
use std::collections::HashMap;
1414
use std::fmt::Display;
15-
use std::path::Path;
1615
use strum::IntoEnumIterator;
1716

1817
/// A graph of commodity flows for a given region and year
@@ -51,6 +50,15 @@ pub enum GraphEdge {
5150
Demand,
5251
}
5352

53+
impl Display for GraphEdge {
54+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55+
match self {
56+
GraphEdge::Process(id) => write!(f, "{id}"),
57+
GraphEdge::Demand => write!(f, "DEMAND"),
58+
}
59+
}
60+
}
61+
5462
/// Creates a directed graph of commodity flows for a given region and year.
5563
///
5664
/// The graph contains nodes for all commodities that may be consumed/produced by processes in the
@@ -401,19 +409,6 @@ pub fn validate_commodity_graphs_for_model(
401409
Ok(commodity_order)
402410
}
403411

404-
/// Saves commodity graphs to file
405-
///
406-
/// The graphs are saved as DOT files to the specified output path
407-
pub fn save_commodity_graphs_for_model(
408-
commodity_graphs: &HashMap<(RegionID, u32), CommoditiesGraph>,
409-
_output_path: &Path,
410-
) -> Result<()> {
411-
for ((_region_id, _year), _graph) in commodity_graphs {
412-
todo!()
413-
}
414-
Ok(())
415-
}
416-
417412
#[cfg(test)]
418413
mod tests {
419414
use super::*;

src/input.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
//! Common routines for handling input data.
22
use crate::asset::AssetPool;
3-
use crate::graph::{build_commodity_graphs_for_model, validate_commodity_graphs_for_model};
3+
use crate::graph::{
4+
CommoditiesGraph, build_commodity_graphs_for_model, validate_commodity_graphs_for_model,
5+
};
46
use crate::id::{HasID, IDLike};
57
use crate::model::{Model, ModelParameters};
8+
use crate::region::RegionID;
69
use crate::units::UnitType;
710
use anyhow::{Context, Result, bail, ensure};
811
use float_cmp::approx_eq;
@@ -233,12 +236,46 @@ pub fn load_model<P: AsRef<Path>>(model_dir: P) -> Result<(Model, AssetPool)> {
233236
processes,
234237
time_slice_info,
235238
regions,
236-
commodity_graphs,
237239
commodity_order,
238240
};
239241
Ok((model, AssetPool::new(assets)))
240242
}
241243

244+
/// Load commodity flow graphs for a model.
245+
///
246+
/// This begins by reading time slice, region, year, commodity and process data which is necessary
247+
/// to build the graphs. Other model data (agents and assets) that is not necessary for graph
248+
/// building is not read.
249+
///
250+
/// Once data is loaded (and assuming the validation checks for this data pass), this will create a
251+
/// graph of commodity flows for each region and year, where nodes are commodities and edges are
252+
/// processes.
253+
///
254+
/// Graphs validation is NOT performed. This ensures that graphs can be generated even when
255+
/// validation would fail, which may be helpful for debugging.
256+
pub fn load_commodity_graphs<P: AsRef<Path>>(
257+
model_dir: P,
258+
) -> Result<HashMap<(RegionID, u32), CommoditiesGraph>> {
259+
let model_params = ModelParameters::from_path(&model_dir)?;
260+
261+
let time_slice_info = read_time_slice_info(model_dir.as_ref())?;
262+
let regions = read_regions(model_dir.as_ref())?;
263+
let region_ids = regions.keys().cloned().collect();
264+
let years = &model_params.milestone_years;
265+
266+
let commodities = read_commodities(model_dir.as_ref(), &region_ids, &time_slice_info, years)?;
267+
let processes = read_processes(
268+
model_dir.as_ref(),
269+
&commodities,
270+
&region_ids,
271+
&time_slice_info,
272+
years,
273+
)?;
274+
275+
let commodity_graphs = build_commodity_graphs_for_model(&processes, &region_ids, years)?;
276+
Ok(commodity_graphs)
277+
}
278+
242279
#[cfg(test)]
243280
mod tests {
244281
use super::*;

src/model.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! The model represents the static input data provided by the user.
22
use crate::agent::AgentMap;
33
use crate::commodity::{CommodityID, CommodityMap};
4-
use crate::graph::CommoditiesGraph;
54
use crate::process::ProcessMap;
65
use crate::region::{RegionID, RegionMap};
76
use crate::time_slice::TimeSliceInfo;
@@ -27,8 +26,6 @@ pub struct Model {
2726
pub time_slice_info: TimeSliceInfo,
2827
/// Regions for the simulation
2928
pub regions: RegionMap,
30-
/// Commodity flow graphs for each region and year
31-
pub commodity_graphs: HashMap<(RegionID, u32), CommoditiesGraph>,
3229
/// Commodity ordering for each region and year
3330
pub commodity_order: HashMap<(RegionID, u32), Vec<CommodityID>>,
3431
}

src/output.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::fs;
1717
use std::fs::File;
1818
use std::path::{Path, PathBuf};
1919

20+
pub mod graph;
2021
pub mod metadata;
2122
use metadata::write_metadata;
2223

src/output/graph.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! The module responsible for writing commodity flow graphs to file.
2+
use crate::graph::CommoditiesGraph;
3+
use crate::region::RegionID;
4+
use anyhow::Result;
5+
use petgraph::dot::Dot;
6+
use std::collections::HashMap;
7+
use std::fs::File;
8+
use std::io::Write as IoWrite;
9+
use std::path::Path;
10+
11+
/// Saves commodity graphs to file
12+
///
13+
/// The graphs are saved as DOT files to the specified output path
14+
pub fn save_commodity_graphs_for_model(
15+
commodity_graphs: &HashMap<(RegionID, u32), CommoditiesGraph>,
16+
output_path: &Path,
17+
) -> Result<()> {
18+
for ((region_id, year), graph) in commodity_graphs {
19+
let dot = Dot::new(&graph);
20+
let mut file = File::create(output_path.join(format!("{region_id}_{year}.dot")))?;
21+
write!(file, "{dot}")?;
22+
}
23+
Ok(())
24+
}

0 commit comments

Comments
 (0)