Skip to content

Commit 3914e5e

Browse files
authored
Merge pull request #571 from EnergySystemsModellingLab/output-dual-values-csv
Add option to write dual values to CSV files
2 parents 47b6c26 + e507386 commit 3914e5e

16 files changed

Lines changed: 892 additions & 140 deletions

examples/simple/settings.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Modify this file if you want to change your program settings
22
# log_level = "info"
3+
# debug_model = false

src/asset.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::process::{Process, ProcessFlow, ProcessParameter};
55
use crate::region::RegionID;
66
use crate::time_slice::TimeSliceID;
77
use anyhow::{ensure, Context, Result};
8+
use indexmap::IndexMap;
89
use std::collections::HashSet;
910
use std::ops::RangeInclusive;
1011
use std::rc::Rc;
@@ -108,13 +109,22 @@ impl Asset {
108109
self.capacity * self.process_parameter.capacity_to_activity
109110
}
110111

111-
/// Iterate over the asset's flows
112-
pub fn iter_flows(&self) -> impl Iterator<Item = &ProcessFlow> {
112+
/// Get a specific process flow
113+
pub fn get_flow(&self, commodity_id: &CommodityID) -> Option<&ProcessFlow> {
114+
self.get_flows_map().get(commodity_id)
115+
}
116+
117+
/// Get the process flows map for this asset
118+
fn get_flows_map(&self) -> &IndexMap<CommodityID, ProcessFlow> {
113119
self.process
114120
.flows
115121
.get(&(self.region_id.clone(), self.commission_year))
116122
.unwrap()
117-
.values()
123+
}
124+
125+
/// Iterate over the asset's flows
126+
pub fn iter_flows(&self) -> impl Iterator<Item = &ProcessFlow> {
127+
self.get_flows_map().values()
118128
}
119129

120130
/// Iterate over the asset's Primary Activity Commodity flows

src/commands.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ pub enum Commands {
3636
/// Directory for output files
3737
#[arg(short, long)]
3838
output_dir: Option<PathBuf>,
39+
/// Whether to write additional information to CSV files
40+
#[arg(long)]
41+
debug_model: bool,
3942
},
4043
/// Manage example models.
4144
Example {
@@ -64,13 +67,25 @@ pub enum ExampleSubcommands {
6467
/// Directory for output files
6568
#[arg(short, long)]
6669
output_dir: Option<PathBuf>,
70+
/// Whether to write additional information to CSV files
71+
#[arg(long)]
72+
debug_model: bool,
6773
},
6874
}
6975

7076
/// Handle the `run` command.
71-
pub fn handle_run_command(model_path: &Path, output_path: Option<&Path>) -> Result<()> {
77+
pub fn handle_run_command(
78+
model_path: &Path,
79+
output_path: Option<&Path>,
80+
debug_model: bool,
81+
) -> Result<()> {
7282
// Load program settings
73-
let settings = Settings::from_path(model_path).context("Failed to load settings.")?;
83+
let mut settings = Settings::from_path(model_path).context("Failed to load settings.")?;
84+
85+
// This setting can be overridden by command-line argument
86+
if debug_model {
87+
settings.debug_model = true;
88+
}
7489

7590
// Create output folder
7691
let output_path = match output_path {
@@ -90,7 +105,7 @@ pub fn handle_run_command(model_path: &Path, output_path: Option<&Path>) -> Resu
90105
info!("Output data will be written to {}", output_path.display());
91106

92107
// Run the simulation
93-
crate::simulation::run(model, assets, &output_path)
108+
crate::simulation::run(model, assets, &output_path, settings.debug_model)
94109
};
95110

96111
// Once the logger is initialised, we can write fatal errors to log
@@ -142,9 +157,13 @@ fn extract_example(name: &str, new_path: &Path) -> Result<()> {
142157
}
143158

144159
/// Handle the `example run` command.
145-
pub fn handle_example_run_command(name: &str, output_path: Option<&Path>) -> Result<()> {
160+
pub fn handle_example_run_command(
161+
name: &str,
162+
output_path: Option<&Path>,
163+
debug_model: bool,
164+
) -> Result<()> {
146165
let temp_dir = TempDir::new().context("Failed to create temporary directory.")?;
147166
let model_path = temp_dir.path().join(name);
148167
extract_example(name, &model_path)?;
149-
handle_run_command(&model_path, output_path)
168+
handle_run_command(&model_path, output_path, debug_model)
150169
}

src/fixture.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Fixtures for tests
22
33
use crate::agent::{
4-
Agent, AgentCommodityPortionsMap, AgentCostLimitsMap, AgentMap, AgentObjectiveMap,
4+
Agent, AgentCommodityPortionsMap, AgentCostLimitsMap, AgentID, AgentMap, AgentObjectiveMap,
55
AgentSearchSpaceMap, DecisionRule,
66
};
7+
use crate::asset::{Asset, AssetPool};
78
use crate::commodity::CommodityID;
89
use crate::process::{
910
Process, ProcessEnergyLimitsMap, ProcessFlowsMap, ProcessMap, ProcessParameter,
@@ -29,6 +30,11 @@ macro_rules! assert_error {
2930
}
3031
pub(crate) use assert_error;
3132

33+
#[fixture]
34+
pub fn region_id() -> RegionID {
35+
"GBR".into()
36+
}
37+
3238
#[fixture]
3339
pub fn commodity_ids() -> HashSet<CommodityID> {
3440
iter::once("commodity1".into()).collect()
@@ -39,6 +45,32 @@ pub fn region_ids() -> HashSet<RegionID> {
3945
["GBR".into(), "USA".into()].into_iter().collect()
4046
}
4147

48+
#[fixture]
49+
pub fn agent_id() -> AgentID {
50+
"agent1".into()
51+
}
52+
53+
#[fixture]
54+
pub fn commodity_id() -> CommodityID {
55+
"commodity1".into()
56+
}
57+
58+
#[fixture]
59+
pub fn asset(process: Process) -> Asset {
60+
let region_id: RegionID = "GBR".into();
61+
let agent_id = "agent1".into();
62+
let commission_year = 2015;
63+
Asset::new(agent_id, process.into(), region_id, 2.0, commission_year).unwrap()
64+
}
65+
66+
#[fixture]
67+
pub fn assets(asset: Asset) -> AssetPool {
68+
let year = asset.commission_year;
69+
let mut assets = AssetPool::new(iter::once(asset).collect());
70+
assets.commission_new(year);
71+
assets
72+
}
73+
4274
#[fixture]
4375
pub fn process_parameter_map(region_ids: HashSet<RegionID>) -> ProcessParameterMap {
4476
let parameter = Rc::new(ProcessParameter {

src/main.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,19 @@ fn execute_cli_command(command: Option<Commands>) -> Result<()> {
3535
Commands::Run {
3636
model_dir,
3737
output_dir,
38-
} => handle_run_command(&model_dir, output_dir.as_deref())?,
38+
debug_model,
39+
} => handle_run_command(&model_dir, output_dir.as_deref(), debug_model)?,
3940
Commands::Example { subcommand } => match subcommand {
4041
ExampleSubcommands::List => handle_example_list_command(),
4142
ExampleSubcommands::Extract {
4243
name,
4344
new_path: dest,
4445
} => handle_example_extract_command(&name, dest.as_deref())?,
45-
ExampleSubcommands::Run { name, output_dir } => {
46-
handle_example_run_command(&name, output_dir.as_deref())?
47-
}
46+
ExampleSubcommands::Run {
47+
name,
48+
output_dir,
49+
debug_model,
50+
} => handle_example_run_command(&name, output_dir.as_deref(), debug_model)?,
4851
},
4952
}
5053

0 commit comments

Comments
 (0)