Skip to content
Open
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
2 changes: 1 addition & 1 deletion schemas/input/model.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ properties:
max_ironing_out_iterations:
type: integer
description: The maximum number of iterations to run the "ironing out" step of agent investment for
default: 10
default: 1
price_tolerance:
type: number
description: The relative tolerance for price convergence in the ironing out loop
Expand Down
12 changes: 7 additions & 5 deletions src/cli/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn handle_example_extract_command(name: &str, dest: Option<&Path>, patch: bool)
/// If `patch` is `true`, then the corresponding patched example will be extracted.
fn extract_example(name: &str, patch: bool, dest: &Path) -> Result<()> {
if patch {
let patches = get_patches(name)?;
let (file_patches, toml_patch) = get_patches(name)?;
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_patches(name)? returns a reference to a (Vec<FilePatch>, Option<String>), but this code destructures it as if it were an owned tuple. This won’t compile (type mismatch &(…) vs (…)). Either bind the returned reference and access its fields, or change get_patches to return an owned tuple (e.g., cloned) so destructuring works.

Suggested change
let (file_patches, toml_patch) = get_patches(name)?;
let (file_patches, toml_patch) = get_patches(name)?.clone();

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it does compile...


// NB: All patched models are based on `simple`, for now
let example = Example::from_name("simple").unwrap();
Expand All @@ -114,10 +114,12 @@ fn extract_example(name: &str, patch: bool, dest: &Path) -> Result<()> {

// Patch example and put contents in dest
fs::create_dir(dest).context("Could not create output directory")?;
ModelPatch::new(example_path)
.with_file_patches(patches.to_owned())
.build(dest)
.context("Failed to patch example")
let mut model_patch =
ModelPatch::new(example_path).with_file_patches(file_patches.to_owned());
if let Some(toml_patch) = toml_patch.as_ref() {
model_patch = model_patch.with_toml_patch(toml_patch);
}
model_patch.build(dest).context("Failed to patch example")
} else {
// Otherwise it's just a regular example
let example = Example::from_name(name)?;
Expand Down
47 changes: 29 additions & 18 deletions src/example/patches.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
//! File patches to be used in integration tests.
//! Patches to be used in integration tests.
//!
//! This is used to test small variations on existing example models.
use crate::patch::FilePatch;
use anyhow::{Context, Result};
use std::{collections::BTreeMap, sync::LazyLock};

/// A map of file patches, keyed by name
type PatchMap = BTreeMap<&'static str, Vec<FilePatch>>;
/// Map of patches keyed by name, with the file patches and an optional TOML patch
type PatchMap = BTreeMap<&'static str, (Vec<FilePatch>, Option<String>)>;

/// The file patches, keyed by name
/// The patches, keyed by name
static PATCHES: LazyLock<PatchMap> = LazyLock::new(get_all_patches);

/// Get all patches
fn get_all_patches() -> PatchMap {
[
// The simple example with gas boiler process made divisible
(
// The simple example with gas boiler process made divisible
"simple_divisible",
vec![
FilePatch::new("processes.csv")
.with_deletion("RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0,")
.with_addition("RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0,1000"),
],
(
vec![
FilePatch::new("processes.csv")
.with_deletion("RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0,")
.with_addition("RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0,1000"),
],
None,
),
),
// The simple example with objective type set to NPV for one agent
(
"simple_npv",
vec![
FilePatch::new("agent_objectives.csv")
.with_deletion("A0_RES,all,lcox,,")
.with_addition("A0_RES,all,npv,,"),
],
(
vec![
FilePatch::new("agent_objectives.csv")
.with_deletion("A0_RES,all,lcox,,")
.with_addition("A0_RES,all,npv,,"),
],
None,
),
),
// The simple example with the ironing-out loop turned on
(
"simple_ironing_out",
(vec![], Some("max_ironing_out_iterations = 10".to_string())),
),
]
.into_iter()
Expand All @@ -43,8 +54,8 @@ pub fn get_patch_names() -> impl Iterator<Item = &'static str> {
}

/// Get patches for the named patched example
pub fn get_patches(name: &str) -> Result<&[FilePatch]> {
Ok(PATCHES
pub fn get_patches(name: &str) -> Result<&'static (Vec<FilePatch>, Option<String>)> {
PATCHES
.get(name)
.with_context(|| format!("Patched example '{name}' not found"))?)
.with_context(|| format!("Patched example '{name}' not found"))
}
2 changes: 1 addition & 1 deletion src/model/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ define_unit_param_default!(default_capacity_limit_factor, Dimensionless, 0.1);
define_unit_param_default!(default_value_of_lost_load, MoneyPerFlow, 1e9);
define_unit_param_default!(default_price_tolerance, Dimensionless, 1e-6);
define_unit_param_default!(default_remaining_demand_absolute_tolerance, Flow, 1e-12);
define_param_default!(default_max_ironing_out_iterations, u32, 10);
define_param_default!(default_max_ironing_out_iterations, u32, 1);
define_param_default!(default_capacity_margin, f64, 0.2);
define_param_default!(default_mothball_years, u32, 0);

Expand Down
27 changes: 13 additions & 14 deletions tests/data/circularity/assets.csv
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,23 @@ asset_id,process_id,region_id,agent_id,group_id,commission_year,decommission_yea
4,OILRF2,GBR,A0_OAG,,2020,2030,573.9
5,WNDFRM,GBR,A0_ELC,,2020,,3.964844
6,GASCGT,GBR,A0_ELC,,2020,,2.999
7,H2YGEN,GBR,A0_ELC,,2020,,1.0
8,H2YPRO,GBR,A0_ELC,,2020,2040,31.54
7,H2YGEN,GBR,A0_ELC,,2020,2030,1.0
8,H2YPRO,GBR,A0_ELC,,2020,2030,31.54
9,TPETCR,GBR,A0_TRA,,2020,2030,451.91
10,TDIECR,GBR,A0_TRA,,2020,2030,176.58
11,TELCCR,GBR,A0_TRA,,2020,2030,20.99
12,THYBCR,GBR,A0_TRA,,2020,2030,15.0
13,RGASBR,GBR,A0_RES,,2020,2035,2900.0
14,RELCHP,GBR,A0_RES,,2020,2035,399.98
15,THYBCR,GBR,A0_TRA,,2030,2040,777.3007440837425
15,TDIECR,GBR,A0_TRA,,2030,2040,777.3007440837425
16,RBIOBL,GBR,A0_RES,,2030,,355.83840587648046
17,GASCGT,GBR,A0_ELC,,2030,,19.242225052307102
18,H2YPRO,GBR,A0_ELC,,2030,,30.278400121113602
19,OILRF2,GBR,A0_REF,,2030,,756.7022737069626
20,BIOPLL,GBR,A0_BPL,,2030,,427.00608705177655
21,BIOPRO,GBR,A0_BPD,,2030,,448.35639140436535
22,THYBCR,GBR,A0_TRA,,2040,,912.8939641298439
23,RBIOBL,GBR,A0_RES,,2040,,3655.8189696
24,GASCGT,GBR,A0_ELC,,2040,,0.8124316982834766
25,H2YPRO,GBR,A0_ELC,,2040,,19.235689279503628
26,BIOPLL,GBR,A0_BPL,,2040,,2167.9571005431867
27,BIOPRO,GBR,A0_BPD,,2040,,2276.354955570347
17,OILREF,GBR,A0_REF,,2030,2040,3363.1212161390777
18,BIOPLL,GBR,A0_BPL,,2030,,427.00608705177655
19,OAGRSV,GBR,A0_OAG,,2030,2040,2269.3348308645695
20,BIOPRO,GBR,A0_BPD,,2030,,448.35639140436535
21,THYBCR,GBR,A0_TRA,,2040,,912.8939641298439
22,RBIOBL,GBR,A0_RES,,2040,,3655.8189696
23,GASCGT,GBR,A0_ELC,,2040,,20.92678121560944
24,OILRF2,GBR,A0_REF,,2040,,888.7022733069632
25,BIOPLL,GBR,A0_BPL,,2040,,2167.9571005431867
26,BIOPRO,GBR,A0_BPD,,2040,,2276.354955570347
Loading
Loading