Skip to content

Fix availabilities validation for non-milestone years#935

Merged
alexdewar merged 3 commits intomainfrom
fix-availabilities-required-all-years
Oct 17, 2025
Merged

Fix availabilities validation for non-milestone years#935
alexdewar merged 3 commits intomainfrom
fix-availabilities-required-all-years

Conversation

@alexdewar
Copy link
Copy Markdown
Collaborator

Description

Processes are required to have availabilities, flows and parameters defined for every combination of region and milestone year in which they can be commissioned. However, assets in assets.csv are allowed to have a commission_year before the simulation's start, provided it is not before a the process's start_year and if this is the case then it makes validation tricky. You can provide availabilities for every year by putting all in the year column, but if you want to supply entries for individual years instead and the process can be commissioned before the time horizon then you have to provide an entry for all of the possible years, which is horrid (e.g. if the simulation starts in 2020 but your process's start_year is 2000, then you need entries for 2000, 2001, etc.). There's an analogous problem for flows (#934), but I think we need to improve the validation for flows anyway (#931) so I thought it made sense to hold off on tackling it until later.

I originally thought I'd fixed this in #868 but clearly didn't test it properly. Oops.

I verified the fix worked by modifying the simple example like so:

diff --git a/examples/simple/assets.csv b/examples/simple/assets.csv
index 6875fab9..1d1d062c 100644
--- a/examples/simple/assets.csv
+++ b/examples/simple/assets.csv
@@ -1,4 +1,5 @@
 process_id,region_id,agent_id,capacity,commission_year
+GASDRV,GBR,A0_GEX,4002.26,2010
 GASDRV,GBR,A0_GEX,4002.26,2020
 GASPRC,GBR,A0_GPR,3782.13,2020
 WNDFRM,GBR,A0_ELC,3.964844,2020
diff --git a/examples/simple/process_availabilities.csv b/examples/simple/process_availabilities.csv
index dea5736a..6746b727 100644
--- a/examples/simple/process_availabilities.csv
+++ b/examples/simple/process_availabilities.csv
@@ -1,5 +1,8 @@
 process_id,regions,years,time_slice,limit_type,value
-GASDRV,all,all,annual,up,0.9
+GASDRV,all,2010,annual,up,0.9
+GASDRV,all,2020,annual,up,0.9
+GASDRV,all,2030,annual,up,0.9
+GASDRV,all,2040,annual,up,0.9
 GASPRC,all,all,annual,up,0.9
 GASCGT,all,all,annual,up,0.9
 RGASBR,all,all,annual,up,1.0
diff --git a/examples/simple/processes.csv b/examples/simple/processes.csv
index 63f48a97..de5efc64 100644
--- a/examples/simple/processes.csv
+++ b/examples/simple/processes.csv
@@ -1,5 +1,5 @@
 id,description,regions,primary_output,start_year,end_year,capacity_to_activity
-GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0
+GASDRV,Dry gas extraction,all,GASPRD,2000,2040,1.0
 GASPRC,Gas processing,all,GASNAT,2020,2040,1.0
 WNDFRM,Wind farm,all,ELCTRI,2020,2040,31.54
 GASCGT,Gas combined cycle turbine,all,ELCTRI,2020,2040,31.54

Do we think it would be worth having one or more examples to exercise this part of the code? We could just have one example that has assets commissioned before the time horizon. We could later add assets commissioned between milestone years and after the time horizon when we've done #859. Thoughts? @tsmbland: this may relate to #655.

Fixes #866.

Type of change

  • Bug fix (non-breaking change to fix an issue)
  • New feature (non-breaking change to add functionality)
  • Refactoring (non-breaking, non-functional change to improve maintainability)
  • Optimization (non-breaking change to speed up the code)
  • Breaking change (whatever its nature)
  • Documentation (improve or add documentation)

Key checklist

  • All tests pass: $ cargo test
  • The documentation builds and looks OK: $ cargo doc

Further checks

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes the validation logic for process availabilities to correctly handle cases where processes can be commissioned before the simulation's milestone years. The fix ensures that only milestone years (years >= base_year) require availability entries, while pre-milestone years are checked lazily when needed.

  • Split validation into separate functions for milestone years and time slices
  • Modified validation to only require entries for milestone years, not all process years
  • Updated function signatures to pass the base_year parameter through the call chain

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/input/process/availability.rs Core validation logic split and fixed to handle non-milestone years correctly
src/input/process.rs Updated to pass base_year parameter to availability reading functions
src/input/process/flow.rs Minor formatting fix removing trailing comma
src/asset.rs Improved error message clarity for missing process availabilities

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

.years
.iter()
.copied()
.filter(|&year| year >= base_year);
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

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

The filtering logic for milestone years should be documented to clarify why only years >= base_year are considered milestone years, especially since this is a key part of the bug fix.

Copilot uses AI. Check for mistakes.
time_slice_info
.iter_ids()
.filter(|ts| !map_for_region_year.contains_key(ts))
.map(|ts| (region_id, year, ts)),
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

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

The tuple construction uses year directly, but year is of type &Year from the iterator. This should be *year to dereference the borrowed value for consistency with the tuple type expected.

Suggested change
.map(|ts| (region_id, year, ts)),
.map(|ts| (region_id, *year, ts)),

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 16, 2025

Codecov Report

❌ Patch coverage is 68.85246% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.88%. Comparing base (b80ce22) to head (4704d9c).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
src/input/process/availability.rs 72.72% 9 Missing and 6 partials ⚠️
src/input/process.rs 50.00% 0 Missing and 2 partials ⚠️
src/asset.rs 0.00% 1 Missing ⚠️
src/input/process/flow.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #935      +/-   ##
==========================================
- Coverage   84.93%   84.88%   -0.06%     
==========================================
  Files          50       50              
  Lines        5323     5364      +41     
  Branches     5323     5364      +41     
==========================================
+ Hits         4521     4553      +32     
- Misses        574      579       +5     
- Partials      228      232       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tsmbland tsmbland mentioned this pull request Oct 16, 2025
10 tasks
Copy link
Copy Markdown
Collaborator

@tsmbland tsmbland left a comment

Choose a reason for hiding this comment

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

Looks good!

Copy link
Copy Markdown
Collaborator

@dalonsoa dalonsoa left a comment

Choose a reason for hiding this comment

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

This looks good to me.

Just to make sure I understand the implications, in your modified example, as the process start year is 2000 but the asset commission year is 2010, in the old way you would have needed to provide process availabilities for the whole range 2000-2010 + milestones, but now only is needed from 2010, right?

model_dir: &Path,
processes: &ProcessMap,
time_slice_info: &TimeSliceInfo,
base_year: u32,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Add to the docstring.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Oops! It's a pity there doesn't seem to be any Rust tooling to check these doc comments...

iter: I,
processes: &ProcessMap,
time_slice_info: &TimeSliceInfo,
base_year: u32,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here. This function is missing details in the docstring, anyway.

@alexdewar
Copy link
Copy Markdown
Collaborator Author

Just to make sure I understand the implications, in your modified example, as the process start year is 2000 but the asset commission year is 2010, in the old way you would have needed to provide process availabilities for the whole range 2000-2010 + milestones, but now only is needed from 2010, right?

Not quite. Imagine you have a simulation with milestone years [2020, 2030], a process with start_year 2000 and an asset with a commission year of 2010 (NB: before start of simulation), then:

  • Previously: you need availabilities for all years 2000-2020 and 2030
  • Now: you just need them for [2010, 2020, 2030] (i.e. all milestone years plus any other ones before the simulation you actually use)

Eventually we want to be able to include assets commissioned between milestone years and after the simulation too for completeness (#859).

@alexdewar alexdewar enabled auto-merge October 17, 2025 10:31
@alexdewar alexdewar merged commit 8482274 into main Oct 17, 2025
8 checks passed
@alexdewar alexdewar deleted the fix-availabilities-required-all-years branch October 17, 2025 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Availabilities are required for all of process's years, even those before time horizon

4 participants