From 7894e22faa02deba3798fd4537e4c5fc3bb45365 Mon Sep 17 00:00:00 2001 From: Aurash Karimi Date: Fri, 7 Nov 2025 17:24:54 +0000 Subject: [PATCH 1/5] add temporary npv enabled model for testing update objective fxn --- examples/missing_commodity_test/README.txt | 3 +++ .../agent_commodity_portions.csv | 7 ++++++ .../agent_cost_limits.csv | 5 ++++ .../agent_objectives.csv | 7 ++++++ examples/missing_commodity_test/agents.csv | 7 ++++++ examples/missing_commodity_test/assets.csv | 7 ++++++ .../missing_commodity_test/commodities.csv | 8 ++++++ .../commodity_levies.csv | 2 ++ examples/missing_commodity_test/demand.csv | 4 +++ .../missing_commodity_test/demand_slicing.csv | 17 +++++++++++++ examples/missing_commodity_test/model.toml | 2 ++ .../process_availabilities.csv | 25 +++++++++++++++++++ .../missing_commodity_test/process_flows.csv | 20 +++++++++++++++ .../process_parameters.csv | 10 ++++++++ examples/missing_commodity_test/processes.csv | 10 ++++++++ examples/missing_commodity_test/regions.csv | 2 ++ .../missing_commodity_test/time_slices.csv | 17 +++++++++++++ .../investment/appraisal/coefficients.rs | 5 +++- .../investment/appraisal/optimisation.rs | 4 +-- src/simulation/optimisation.rs | 6 ++++- 20 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 examples/missing_commodity_test/README.txt create mode 100644 examples/missing_commodity_test/agent_commodity_portions.csv create mode 100644 examples/missing_commodity_test/agent_cost_limits.csv create mode 100644 examples/missing_commodity_test/agent_objectives.csv create mode 100644 examples/missing_commodity_test/agents.csv create mode 100644 examples/missing_commodity_test/assets.csv create mode 100644 examples/missing_commodity_test/commodities.csv create mode 100644 examples/missing_commodity_test/commodity_levies.csv create mode 100644 examples/missing_commodity_test/demand.csv create mode 100644 examples/missing_commodity_test/demand_slicing.csv create mode 100644 examples/missing_commodity_test/model.toml create mode 100644 examples/missing_commodity_test/process_availabilities.csv create mode 100644 examples/missing_commodity_test/process_flows.csv create mode 100644 examples/missing_commodity_test/process_parameters.csv create mode 100644 examples/missing_commodity_test/processes.csv create mode 100644 examples/missing_commodity_test/regions.csv create mode 100644 examples/missing_commodity_test/time_slices.csv diff --git a/examples/missing_commodity_test/README.txt b/examples/missing_commodity_test/README.txt new file mode 100644 index 000000000..8aeb84214 --- /dev/null +++ b/examples/missing_commodity_test/README.txt @@ -0,0 +1,3 @@ +This model is like the "simple" example, except that it includes a separate biomass supply chain, +which has no capacity in the base year. This is partly done to exemplify how MUSE2 can generate +prices for commodities not utilised in a given year. diff --git a/examples/missing_commodity_test/agent_commodity_portions.csv b/examples/missing_commodity_test/agent_commodity_portions.csv new file mode 100644 index 000000000..7cf371879 --- /dev/null +++ b/examples/missing_commodity_test/agent_commodity_portions.csv @@ -0,0 +1,7 @@ +agent_id,commodity_id,years,commodity_portion +A0_GEX,GASPRD,all,1 +A0_GPR,GASNAT,all,1 +A0_BPD,BIOPRD,all,1 +A0_BPL,BIOPEL,all,1 +A0_ELC,ELCTRI,all,1 +A0_RES,RSHEAT,all,1 diff --git a/examples/missing_commodity_test/agent_cost_limits.csv b/examples/missing_commodity_test/agent_cost_limits.csv new file mode 100644 index 000000000..b8bccef9f --- /dev/null +++ b/examples/missing_commodity_test/agent_cost_limits.csv @@ -0,0 +1,5 @@ +agent_id,years,capex_limit,annual_cost_limit +A0_GEX,all,, +A0_GPR,all,, +A0_ELC,all,, +A0_RES,all,, diff --git a/examples/missing_commodity_test/agent_objectives.csv b/examples/missing_commodity_test/agent_objectives.csv new file mode 100644 index 000000000..8521755e6 --- /dev/null +++ b/examples/missing_commodity_test/agent_objectives.csv @@ -0,0 +1,7 @@ +agent_id,years,objective_type,decision_weight,decision_lexico_order +A0_GEX,all,lcox,, +A0_GPR,all,lcox,, +A0_BPD,all,lcox,, +A0_BPL,all,lcox,, +A0_ELC,all,lcox,, +A0_RES,all,npv,, diff --git a/examples/missing_commodity_test/agents.csv b/examples/missing_commodity_test/agents.csv new file mode 100644 index 000000000..0f14a98e3 --- /dev/null +++ b/examples/missing_commodity_test/agents.csv @@ -0,0 +1,7 @@ +id,description,regions,decision_rule,decision_lexico_tolerance +A0_GEX,Gas extractors,all,single, +A0_GPR,Gas processors,all,single, +A0_BPD,Biomass producer,all,single, +A0_BPL,Biomass pelletiser,all,single, +A0_ELC,Electricity generators,all,single, +A0_RES,Residential consumer,all,single, diff --git a/examples/missing_commodity_test/assets.csv b/examples/missing_commodity_test/assets.csv new file mode 100644 index 000000000..6875fab99 --- /dev/null +++ b/examples/missing_commodity_test/assets.csv @@ -0,0 +1,7 @@ +process_id,region_id,agent_id,capacity,commission_year +GASDRV,GBR,A0_GEX,4002.26,2020 +GASPRC,GBR,A0_GPR,3782.13,2020 +WNDFRM,GBR,A0_ELC,3.964844,2020 +GASCGT,GBR,A0_ELC,2.43,2020 +RGASBR,GBR,A0_RES,2900.0,2020 +RELCHP,GBR,A0_RES,399.98,2020 diff --git a/examples/missing_commodity_test/commodities.csv b/examples/missing_commodity_test/commodities.csv new file mode 100644 index 000000000..eb5ed39c2 --- /dev/null +++ b/examples/missing_commodity_test/commodities.csv @@ -0,0 +1,8 @@ +id,description,type,time_slice_level +GASPRD,Gas produced,sed,season +GASNAT,Natural gas,sed,season +BIOPRD,Biomass produced,sed,season +BIOPEL,Biomass pellets,sed,season +ELCTRI,Electricity,sed,daynight +RSHEAT,Residential heating,svd,daynight +CO2EMT,CO2 emitted,oth,annual diff --git a/examples/missing_commodity_test/commodity_levies.csv b/examples/missing_commodity_test/commodity_levies.csv new file mode 100644 index 000000000..00e64fa89 --- /dev/null +++ b/examples/missing_commodity_test/commodity_levies.csv @@ -0,0 +1,2 @@ +commodity_id,regions,years,time_slice,balance_type,value +CO2EMT,all,all,annual,net,0.04 diff --git a/examples/missing_commodity_test/demand.csv b/examples/missing_commodity_test/demand.csv new file mode 100644 index 000000000..d32ed9de2 --- /dev/null +++ b/examples/missing_commodity_test/demand.csv @@ -0,0 +1,4 @@ +commodity_id,region_id,year,demand +RSHEAT,GBR,2020,927.38 +RSHEAT,GBR,2030,1027.38 +RSHEAT,GBR,2040,1127.38 diff --git a/examples/missing_commodity_test/demand_slicing.csv b/examples/missing_commodity_test/demand_slicing.csv new file mode 100644 index 000000000..4e043388a --- /dev/null +++ b/examples/missing_commodity_test/demand_slicing.csv @@ -0,0 +1,17 @@ +commodity_id,region_id,time_slice,fraction +RSHEAT,GBR,winter.night,0.065498087 +RSHEAT,GBR,winter.day,0.226148097 +RSHEAT,GBR,winter.peak,0.111199678 +RSHEAT,GBR,winter.evening,0.076688397 +RSHEAT,GBR,peak.night,0.045882959 +RSHEAT,GBR,peak.day,0.121987853 +RSHEAT,GBR,peak.peak,0.068135438 +RSHEAT,GBR,peak.evening,0.041334529 +RSHEAT,GBR,summer.night,0.005698366 +RSHEAT,GBR,summer.day,0.009494171 +RSHEAT,GBR,summer.peak,0.003126411 +RSHEAT,GBR,summer.evening,0.002327863 +RSHEAT,GBR,autumn.night,0.037269058 +RSHEAT,GBR,autumn.day,0.098086985 +RSHEAT,GBR,autumn.peak,0.054500569 +RSHEAT,GBR,autumn.evening,0.032621538 diff --git a/examples/missing_commodity_test/model.toml b/examples/missing_commodity_test/model.toml new file mode 100644 index 000000000..b26bb0a81 --- /dev/null +++ b/examples/missing_commodity_test/model.toml @@ -0,0 +1,2 @@ +milestone_years = [2020, 2030, 2040] +please_give_me_broken_results = true diff --git a/examples/missing_commodity_test/process_availabilities.csv b/examples/missing_commodity_test/process_availabilities.csv new file mode 100644 index 000000000..c9d9c4471 --- /dev/null +++ b/examples/missing_commodity_test/process_availabilities.csv @@ -0,0 +1,25 @@ +process_id,regions,commission_years,time_slice,limit_type,value +GASDRV,all,all,annual,up,0.9 +GASPRC,all,all,annual,up,0.9 +BIOPRO,all,all,annual,up,1.0 +BIOPLL,all,all,annual,up,0.95 +GASCGT,all,all,annual,up,0.9 +RGASBR,all,all,annual,up,1.0 +RELCHP,all,all,annual,up,1.0 +RBIOBL,all,all,annual,up,1.0 +WNDFRM,all,all,winter.night,up,0.486418015 +WNDFRM,all,all,winter.day,up,0.543166784 +WNDFRM,all,all,winter.peak,up,0.504433498 +WNDFRM,all,all,winter.evening,up,0.493173821 +WNDFRM,all,all,peak.night,up,0.312697296 +WNDFRM,all,all,peak.day,up,0.489120338 +WNDFRM,all,all,peak.peak,up,0.454890922 +WNDFRM,all,all,peak.evening,up,0.331034483 +WNDFRM,all,all,summer.night,up,0.17951141 +WNDFRM,all,all,summer.day,up,0.349950739 +WNDFRM,all,all,summer.peak,up,0.342294159 +WNDFRM,all,all,summer.evening,up,0.202674173 +WNDFRM,all,all,autumn.night,up,0.3513019 +WNDFRM,all,all,autumn.day,up,0.460745954 +WNDFRM,all,all,autumn.peak,up,0.396340605 +WNDFRM,all,all,autumn.evening,up,0.364813512 diff --git a/examples/missing_commodity_test/process_flows.csv b/examples/missing_commodity_test/process_flows.csv new file mode 100644 index 000000000..6fda05c2b --- /dev/null +++ b/examples/missing_commodity_test/process_flows.csv @@ -0,0 +1,20 @@ +process_id,commodity_id,regions,commission_years,coeff,type,cost +GASDRV,GASPRD,all,all,1.0,fixed, +GASPRC,GASPRD,all,all,-1.05,fixed, +GASPRC,GASNAT,all,all,1.0,fixed, +BIOPRO,BIOPRD,all,all,1.0,fixed, +BIOPLL,BIOPRD,all,all,-1.05,fixed, +BIOPLL,BIOPEL,all,all,1.0,fixed, +WNDFRM,ELCTRI,all,all,1.0,fixed, +GASCGT,GASNAT,all,all,-1.5,fixed, +GASCGT,ELCTRI,all,all,1.0,fixed, +RGASBR,GASNAT,all,all,-1.15,fixed, +RGASBR,RSHEAT,all,all,1.0,fixed, +RELCHP,ELCTRI,all,all,-0.33,fixed, +RELCHP,RSHEAT,all,all,1.0,fixed, +GASDRV,CO2EMT,all,all,5.113,fixed, +GASPRC,CO2EMT,all,all,2.5565,fixed, +GASCGT,CO2EMT,all,all,76.695,fixed, +RGASBR,CO2EMT,all,all,58.7995,fixed, +RBIOBL,BIOPEL,all,all,-1.2,fixed, +RBIOBL,RSHEAT,all,all,1,fixed, diff --git a/examples/missing_commodity_test/process_parameters.csv b/examples/missing_commodity_test/process_parameters.csv new file mode 100644 index 000000000..0504d0d44 --- /dev/null +++ b/examples/missing_commodity_test/process_parameters.csv @@ -0,0 +1,10 @@ +process_id,regions,commission_years,capital_cost,fixed_operating_cost,variable_operating_cost,lifetime,discount_rate +GASDRV,all,all,10.0,0.3,2.0,25,0.1 +GASPRC,all,all,7.0,0.21,0.5,25,0.1 +BIOPRO,all,all,1.0,0.2,0.25,20,0.09 +BIOPLL,all,all,2.0,0.22,0.26,20,0.1 +WNDFRM,all,all,1000.0,30.0,0.4,25,0.1 +GASCGT,all,all,700.0,21.0,0.55,30,0.1 +RGASBR,all,all,55.56,1.6668,0.16,15,0.1 +RELCHP,all,all,138.9,4.167,0.17,15,0.1 +RBIOBL,all,all,60,1.05,0.2,20,0.1 diff --git a/examples/missing_commodity_test/processes.csv b/examples/missing_commodity_test/processes.csv new file mode 100644 index 000000000..f8b70cbe6 --- /dev/null +++ b/examples/missing_commodity_test/processes.csv @@ -0,0 +1,10 @@ +id,description,regions,primary_output,start_year,end_year,capacity_to_activity +GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0 +GASPRC,Gas processing,all,GASNAT,2020,2040,1.0 +BIOPRO,Biomass production,all,BIOPRD,2020,2040,1.0 +BIOPLL,Biomass pelletiser,all,BIOPEL,2020,2040,1.0 +WNDFRM,Wind farm,all,ELCTRI,2020,2040,31.54 +GASCGT,Gas combined cycle turbine,all,ELCTRI,2020,2040,31.54 +RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0 +RELCHP,Heat pump,all,RSHEAT,2020,2040,1.0 +RBIOBL,Biomass boiler,all,RSHEAT,2020,2040,1.0 diff --git a/examples/missing_commodity_test/regions.csv b/examples/missing_commodity_test/regions.csv new file mode 100644 index 000000000..a1d2d74c5 --- /dev/null +++ b/examples/missing_commodity_test/regions.csv @@ -0,0 +1,2 @@ +id,description +GBR,United Kingdom diff --git a/examples/missing_commodity_test/time_slices.csv b/examples/missing_commodity_test/time_slices.csv new file mode 100644 index 000000000..76583f12c --- /dev/null +++ b/examples/missing_commodity_test/time_slices.csv @@ -0,0 +1,17 @@ +season,time_of_day,fraction +winter,night,0.072916667 +winter,day,0.104166667 +winter,peak,0.03125 +winter,evening,0.041666667 +peak,night,0.072916667 +peak,day,0.104166667 +peak,peak,0.03125 +peak,evening,0.041666667 +summer,night,0.072916667 +summer,day,0.104166667 +summer,peak,0.03125 +summer,evening,0.041666667 +autumn,night,0.072916667 +autumn,day,0.104166667 +autumn,peak,0.03125 +autumn,evening,0.041666667 diff --git a/src/simulation/investment/appraisal/coefficients.rs b/src/simulation/investment/appraisal/coefficients.rs index 47b40edf6..0b5940b42 100644 --- a/src/simulation/investment/appraisal/coefficients.rs +++ b/src/simulation/investment/appraisal/coefficients.rs @@ -89,11 +89,14 @@ pub fn calculate_coefficients_for_npv( // Capacity coefficient let capacity_coefficient = -annual_fixed_cost(asset); + // Small epsilon to ensure break-even assets are dispatched + let epsilon = MoneyPerActivity(1e-14); + // Activity coefficients let mut activity_coefficients = IndexMap::new(); for time_slice in time_slice_info.iter_ids() { let coefficient = calculate_activity_coefficient_for_npv(asset, time_slice, prices, year); - activity_coefficients.insert(time_slice.clone(), coefficient); + activity_coefficients.insert(time_slice.clone(), coefficient + epsilon); } // Unmet demand coefficient (we don't apply a cost to unmet demand, so we set this to zero) diff --git a/src/simulation/investment/appraisal/optimisation.rs b/src/simulation/investment/appraisal/optimisation.rs index 6216a9808..75f7c201d 100644 --- a/src/simulation/investment/appraisal/optimisation.rs +++ b/src/simulation/investment/appraisal/optimisation.rs @@ -38,8 +38,8 @@ pub struct ResultsMap { /// Add variables to the problem based on cost coefficients fn add_variables(problem: &mut Problem, cost_coefficients: &ObjectiveCoefficients) -> VariableMap { - // Create capacity variable - let capacity_var = problem.add_column(cost_coefficients.capacity_coefficient.value(), 0.0..); + // Create (Zeroed) capacity variable - does not contribute to objective + let capacity_var = problem.add_column(0.0, 0.0..); // Create activity variables let mut activity_vars = IndexMap::new(); diff --git a/src/simulation/optimisation.rs b/src/simulation/optimisation.rs index 4e2a3b5c5..6f0b8e00d 100644 --- a/src/simulation/optimisation.rs +++ b/src/simulation/optimisation.rs @@ -541,9 +541,13 @@ fn add_asset_variables( ) -> Range { // This line **must** come before we add more variables let start = problem.num_cols(); + // allow zero/slightly negative cost coefficients to be switched on + // let cost_coefficient_epsilon: MoneyPerActivity = MoneyPerActivity(1e-14); + let cost_coefficient_epsilon = MoneyPerActivity(0.0); for (asset, time_slice) in iproduct!(assets.iter(), time_slice_info.iter_ids()) { - let coeff = calculate_cost_coefficient(asset, year, time_slice, input_prices); + let coeff = calculate_cost_coefficient(asset, year, time_slice, input_prices) + + cost_coefficient_epsilon; let var = problem.add_column(coeff.value(), 0.0..); let key = (asset.clone(), time_slice.clone()); let existing = variables.insert(key, var).is_some(); From c4c1f5bf8ae79ba3fde602e50473a38849f9a3fe Mon Sep 17 00:00:00 2001 From: Aurash Karimi Date: Mon, 10 Nov 2025 22:31:33 +0000 Subject: [PATCH 2/5] remove tmp file --- examples/missing_commodity_test/README.txt | 3 --- .../agent_commodity_portions.csv | 7 ------ .../agent_cost_limits.csv | 5 ---- .../agent_objectives.csv | 7 ------ examples/missing_commodity_test/agents.csv | 7 ------ examples/missing_commodity_test/assets.csv | 7 ------ .../missing_commodity_test/commodities.csv | 8 ------ .../commodity_levies.csv | 2 -- examples/missing_commodity_test/demand.csv | 4 --- .../missing_commodity_test/demand_slicing.csv | 17 ------------- examples/missing_commodity_test/model.toml | 2 -- .../process_availabilities.csv | 25 ------------------- .../missing_commodity_test/process_flows.csv | 20 --------------- .../process_parameters.csv | 10 -------- examples/missing_commodity_test/processes.csv | 10 -------- examples/missing_commodity_test/regions.csv | 2 -- .../missing_commodity_test/time_slices.csv | 17 ------------- .../investment/appraisal/optimisation.rs | 4 +-- src/simulation/optimisation.rs | 6 +---- 19 files changed, 3 insertions(+), 160 deletions(-) delete mode 100644 examples/missing_commodity_test/README.txt delete mode 100644 examples/missing_commodity_test/agent_commodity_portions.csv delete mode 100644 examples/missing_commodity_test/agent_cost_limits.csv delete mode 100644 examples/missing_commodity_test/agent_objectives.csv delete mode 100644 examples/missing_commodity_test/agents.csv delete mode 100644 examples/missing_commodity_test/assets.csv delete mode 100644 examples/missing_commodity_test/commodities.csv delete mode 100644 examples/missing_commodity_test/commodity_levies.csv delete mode 100644 examples/missing_commodity_test/demand.csv delete mode 100644 examples/missing_commodity_test/demand_slicing.csv delete mode 100644 examples/missing_commodity_test/model.toml delete mode 100644 examples/missing_commodity_test/process_availabilities.csv delete mode 100644 examples/missing_commodity_test/process_flows.csv delete mode 100644 examples/missing_commodity_test/process_parameters.csv delete mode 100644 examples/missing_commodity_test/processes.csv delete mode 100644 examples/missing_commodity_test/regions.csv delete mode 100644 examples/missing_commodity_test/time_slices.csv diff --git a/examples/missing_commodity_test/README.txt b/examples/missing_commodity_test/README.txt deleted file mode 100644 index 8aeb84214..000000000 --- a/examples/missing_commodity_test/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This model is like the "simple" example, except that it includes a separate biomass supply chain, -which has no capacity in the base year. This is partly done to exemplify how MUSE2 can generate -prices for commodities not utilised in a given year. diff --git a/examples/missing_commodity_test/agent_commodity_portions.csv b/examples/missing_commodity_test/agent_commodity_portions.csv deleted file mode 100644 index 7cf371879..000000000 --- a/examples/missing_commodity_test/agent_commodity_portions.csv +++ /dev/null @@ -1,7 +0,0 @@ -agent_id,commodity_id,years,commodity_portion -A0_GEX,GASPRD,all,1 -A0_GPR,GASNAT,all,1 -A0_BPD,BIOPRD,all,1 -A0_BPL,BIOPEL,all,1 -A0_ELC,ELCTRI,all,1 -A0_RES,RSHEAT,all,1 diff --git a/examples/missing_commodity_test/agent_cost_limits.csv b/examples/missing_commodity_test/agent_cost_limits.csv deleted file mode 100644 index b8bccef9f..000000000 --- a/examples/missing_commodity_test/agent_cost_limits.csv +++ /dev/null @@ -1,5 +0,0 @@ -agent_id,years,capex_limit,annual_cost_limit -A0_GEX,all,, -A0_GPR,all,, -A0_ELC,all,, -A0_RES,all,, diff --git a/examples/missing_commodity_test/agent_objectives.csv b/examples/missing_commodity_test/agent_objectives.csv deleted file mode 100644 index 8521755e6..000000000 --- a/examples/missing_commodity_test/agent_objectives.csv +++ /dev/null @@ -1,7 +0,0 @@ -agent_id,years,objective_type,decision_weight,decision_lexico_order -A0_GEX,all,lcox,, -A0_GPR,all,lcox,, -A0_BPD,all,lcox,, -A0_BPL,all,lcox,, -A0_ELC,all,lcox,, -A0_RES,all,npv,, diff --git a/examples/missing_commodity_test/agents.csv b/examples/missing_commodity_test/agents.csv deleted file mode 100644 index 0f14a98e3..000000000 --- a/examples/missing_commodity_test/agents.csv +++ /dev/null @@ -1,7 +0,0 @@ -id,description,regions,decision_rule,decision_lexico_tolerance -A0_GEX,Gas extractors,all,single, -A0_GPR,Gas processors,all,single, -A0_BPD,Biomass producer,all,single, -A0_BPL,Biomass pelletiser,all,single, -A0_ELC,Electricity generators,all,single, -A0_RES,Residential consumer,all,single, diff --git a/examples/missing_commodity_test/assets.csv b/examples/missing_commodity_test/assets.csv deleted file mode 100644 index 6875fab99..000000000 --- a/examples/missing_commodity_test/assets.csv +++ /dev/null @@ -1,7 +0,0 @@ -process_id,region_id,agent_id,capacity,commission_year -GASDRV,GBR,A0_GEX,4002.26,2020 -GASPRC,GBR,A0_GPR,3782.13,2020 -WNDFRM,GBR,A0_ELC,3.964844,2020 -GASCGT,GBR,A0_ELC,2.43,2020 -RGASBR,GBR,A0_RES,2900.0,2020 -RELCHP,GBR,A0_RES,399.98,2020 diff --git a/examples/missing_commodity_test/commodities.csv b/examples/missing_commodity_test/commodities.csv deleted file mode 100644 index eb5ed39c2..000000000 --- a/examples/missing_commodity_test/commodities.csv +++ /dev/null @@ -1,8 +0,0 @@ -id,description,type,time_slice_level -GASPRD,Gas produced,sed,season -GASNAT,Natural gas,sed,season -BIOPRD,Biomass produced,sed,season -BIOPEL,Biomass pellets,sed,season -ELCTRI,Electricity,sed,daynight -RSHEAT,Residential heating,svd,daynight -CO2EMT,CO2 emitted,oth,annual diff --git a/examples/missing_commodity_test/commodity_levies.csv b/examples/missing_commodity_test/commodity_levies.csv deleted file mode 100644 index 00e64fa89..000000000 --- a/examples/missing_commodity_test/commodity_levies.csv +++ /dev/null @@ -1,2 +0,0 @@ -commodity_id,regions,years,time_slice,balance_type,value -CO2EMT,all,all,annual,net,0.04 diff --git a/examples/missing_commodity_test/demand.csv b/examples/missing_commodity_test/demand.csv deleted file mode 100644 index d32ed9de2..000000000 --- a/examples/missing_commodity_test/demand.csv +++ /dev/null @@ -1,4 +0,0 @@ -commodity_id,region_id,year,demand -RSHEAT,GBR,2020,927.38 -RSHEAT,GBR,2030,1027.38 -RSHEAT,GBR,2040,1127.38 diff --git a/examples/missing_commodity_test/demand_slicing.csv b/examples/missing_commodity_test/demand_slicing.csv deleted file mode 100644 index 4e043388a..000000000 --- a/examples/missing_commodity_test/demand_slicing.csv +++ /dev/null @@ -1,17 +0,0 @@ -commodity_id,region_id,time_slice,fraction -RSHEAT,GBR,winter.night,0.065498087 -RSHEAT,GBR,winter.day,0.226148097 -RSHEAT,GBR,winter.peak,0.111199678 -RSHEAT,GBR,winter.evening,0.076688397 -RSHEAT,GBR,peak.night,0.045882959 -RSHEAT,GBR,peak.day,0.121987853 -RSHEAT,GBR,peak.peak,0.068135438 -RSHEAT,GBR,peak.evening,0.041334529 -RSHEAT,GBR,summer.night,0.005698366 -RSHEAT,GBR,summer.day,0.009494171 -RSHEAT,GBR,summer.peak,0.003126411 -RSHEAT,GBR,summer.evening,0.002327863 -RSHEAT,GBR,autumn.night,0.037269058 -RSHEAT,GBR,autumn.day,0.098086985 -RSHEAT,GBR,autumn.peak,0.054500569 -RSHEAT,GBR,autumn.evening,0.032621538 diff --git a/examples/missing_commodity_test/model.toml b/examples/missing_commodity_test/model.toml deleted file mode 100644 index b26bb0a81..000000000 --- a/examples/missing_commodity_test/model.toml +++ /dev/null @@ -1,2 +0,0 @@ -milestone_years = [2020, 2030, 2040] -please_give_me_broken_results = true diff --git a/examples/missing_commodity_test/process_availabilities.csv b/examples/missing_commodity_test/process_availabilities.csv deleted file mode 100644 index c9d9c4471..000000000 --- a/examples/missing_commodity_test/process_availabilities.csv +++ /dev/null @@ -1,25 +0,0 @@ -process_id,regions,commission_years,time_slice,limit_type,value -GASDRV,all,all,annual,up,0.9 -GASPRC,all,all,annual,up,0.9 -BIOPRO,all,all,annual,up,1.0 -BIOPLL,all,all,annual,up,0.95 -GASCGT,all,all,annual,up,0.9 -RGASBR,all,all,annual,up,1.0 -RELCHP,all,all,annual,up,1.0 -RBIOBL,all,all,annual,up,1.0 -WNDFRM,all,all,winter.night,up,0.486418015 -WNDFRM,all,all,winter.day,up,0.543166784 -WNDFRM,all,all,winter.peak,up,0.504433498 -WNDFRM,all,all,winter.evening,up,0.493173821 -WNDFRM,all,all,peak.night,up,0.312697296 -WNDFRM,all,all,peak.day,up,0.489120338 -WNDFRM,all,all,peak.peak,up,0.454890922 -WNDFRM,all,all,peak.evening,up,0.331034483 -WNDFRM,all,all,summer.night,up,0.17951141 -WNDFRM,all,all,summer.day,up,0.349950739 -WNDFRM,all,all,summer.peak,up,0.342294159 -WNDFRM,all,all,summer.evening,up,0.202674173 -WNDFRM,all,all,autumn.night,up,0.3513019 -WNDFRM,all,all,autumn.day,up,0.460745954 -WNDFRM,all,all,autumn.peak,up,0.396340605 -WNDFRM,all,all,autumn.evening,up,0.364813512 diff --git a/examples/missing_commodity_test/process_flows.csv b/examples/missing_commodity_test/process_flows.csv deleted file mode 100644 index 6fda05c2b..000000000 --- a/examples/missing_commodity_test/process_flows.csv +++ /dev/null @@ -1,20 +0,0 @@ -process_id,commodity_id,regions,commission_years,coeff,type,cost -GASDRV,GASPRD,all,all,1.0,fixed, -GASPRC,GASPRD,all,all,-1.05,fixed, -GASPRC,GASNAT,all,all,1.0,fixed, -BIOPRO,BIOPRD,all,all,1.0,fixed, -BIOPLL,BIOPRD,all,all,-1.05,fixed, -BIOPLL,BIOPEL,all,all,1.0,fixed, -WNDFRM,ELCTRI,all,all,1.0,fixed, -GASCGT,GASNAT,all,all,-1.5,fixed, -GASCGT,ELCTRI,all,all,1.0,fixed, -RGASBR,GASNAT,all,all,-1.15,fixed, -RGASBR,RSHEAT,all,all,1.0,fixed, -RELCHP,ELCTRI,all,all,-0.33,fixed, -RELCHP,RSHEAT,all,all,1.0,fixed, -GASDRV,CO2EMT,all,all,5.113,fixed, -GASPRC,CO2EMT,all,all,2.5565,fixed, -GASCGT,CO2EMT,all,all,76.695,fixed, -RGASBR,CO2EMT,all,all,58.7995,fixed, -RBIOBL,BIOPEL,all,all,-1.2,fixed, -RBIOBL,RSHEAT,all,all,1,fixed, diff --git a/examples/missing_commodity_test/process_parameters.csv b/examples/missing_commodity_test/process_parameters.csv deleted file mode 100644 index 0504d0d44..000000000 --- a/examples/missing_commodity_test/process_parameters.csv +++ /dev/null @@ -1,10 +0,0 @@ -process_id,regions,commission_years,capital_cost,fixed_operating_cost,variable_operating_cost,lifetime,discount_rate -GASDRV,all,all,10.0,0.3,2.0,25,0.1 -GASPRC,all,all,7.0,0.21,0.5,25,0.1 -BIOPRO,all,all,1.0,0.2,0.25,20,0.09 -BIOPLL,all,all,2.0,0.22,0.26,20,0.1 -WNDFRM,all,all,1000.0,30.0,0.4,25,0.1 -GASCGT,all,all,700.0,21.0,0.55,30,0.1 -RGASBR,all,all,55.56,1.6668,0.16,15,0.1 -RELCHP,all,all,138.9,4.167,0.17,15,0.1 -RBIOBL,all,all,60,1.05,0.2,20,0.1 diff --git a/examples/missing_commodity_test/processes.csv b/examples/missing_commodity_test/processes.csv deleted file mode 100644 index f8b70cbe6..000000000 --- a/examples/missing_commodity_test/processes.csv +++ /dev/null @@ -1,10 +0,0 @@ -id,description,regions,primary_output,start_year,end_year,capacity_to_activity -GASDRV,Dry gas extraction,all,GASPRD,2020,2040,1.0 -GASPRC,Gas processing,all,GASNAT,2020,2040,1.0 -BIOPRO,Biomass production,all,BIOPRD,2020,2040,1.0 -BIOPLL,Biomass pelletiser,all,BIOPEL,2020,2040,1.0 -WNDFRM,Wind farm,all,ELCTRI,2020,2040,31.54 -GASCGT,Gas combined cycle turbine,all,ELCTRI,2020,2040,31.54 -RGASBR,Gas boiler,all,RSHEAT,2020,2040,1.0 -RELCHP,Heat pump,all,RSHEAT,2020,2040,1.0 -RBIOBL,Biomass boiler,all,RSHEAT,2020,2040,1.0 diff --git a/examples/missing_commodity_test/regions.csv b/examples/missing_commodity_test/regions.csv deleted file mode 100644 index a1d2d74c5..000000000 --- a/examples/missing_commodity_test/regions.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,description -GBR,United Kingdom diff --git a/examples/missing_commodity_test/time_slices.csv b/examples/missing_commodity_test/time_slices.csv deleted file mode 100644 index 76583f12c..000000000 --- a/examples/missing_commodity_test/time_slices.csv +++ /dev/null @@ -1,17 +0,0 @@ -season,time_of_day,fraction -winter,night,0.072916667 -winter,day,0.104166667 -winter,peak,0.03125 -winter,evening,0.041666667 -peak,night,0.072916667 -peak,day,0.104166667 -peak,peak,0.03125 -peak,evening,0.041666667 -summer,night,0.072916667 -summer,day,0.104166667 -summer,peak,0.03125 -summer,evening,0.041666667 -autumn,night,0.072916667 -autumn,day,0.104166667 -autumn,peak,0.03125 -autumn,evening,0.041666667 diff --git a/src/simulation/investment/appraisal/optimisation.rs b/src/simulation/investment/appraisal/optimisation.rs index 75f7c201d..6216a9808 100644 --- a/src/simulation/investment/appraisal/optimisation.rs +++ b/src/simulation/investment/appraisal/optimisation.rs @@ -38,8 +38,8 @@ pub struct ResultsMap { /// Add variables to the problem based on cost coefficients fn add_variables(problem: &mut Problem, cost_coefficients: &ObjectiveCoefficients) -> VariableMap { - // Create (Zeroed) capacity variable - does not contribute to objective - let capacity_var = problem.add_column(0.0, 0.0..); + // Create capacity variable + let capacity_var = problem.add_column(cost_coefficients.capacity_coefficient.value(), 0.0..); // Create activity variables let mut activity_vars = IndexMap::new(); diff --git a/src/simulation/optimisation.rs b/src/simulation/optimisation.rs index 6f0b8e00d..4e2a3b5c5 100644 --- a/src/simulation/optimisation.rs +++ b/src/simulation/optimisation.rs @@ -541,13 +541,9 @@ fn add_asset_variables( ) -> Range { // This line **must** come before we add more variables let start = problem.num_cols(); - // allow zero/slightly negative cost coefficients to be switched on - // let cost_coefficient_epsilon: MoneyPerActivity = MoneyPerActivity(1e-14); - let cost_coefficient_epsilon = MoneyPerActivity(0.0); for (asset, time_slice) in iproduct!(assets.iter(), time_slice_info.iter_ids()) { - let coeff = calculate_cost_coefficient(asset, year, time_slice, input_prices) - + cost_coefficient_epsilon; + let coeff = calculate_cost_coefficient(asset, year, time_slice, input_prices); let var = problem.add_column(coeff.value(), 0.0..); let key = (asset.clone(), time_slice.clone()); let existing = variables.insert(key, var).is_some(); From a893229f52e4a67c7519de5895136d18905e6fb0 Mon Sep 17 00:00:00 2001 From: Aurash Karimi Date: Tue, 11 Nov 2025 16:39:21 +0000 Subject: [PATCH 3/5] use const and clearer comment for ac epsilon --- src/simulation/investment/appraisal/coefficients.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/simulation/investment/appraisal/coefficients.rs b/src/simulation/investment/appraisal/coefficients.rs index 0b5940b42..8027cb707 100644 --- a/src/simulation/investment/appraisal/coefficients.rs +++ b/src/simulation/investment/appraisal/coefficients.rs @@ -86,17 +86,21 @@ pub fn calculate_coefficients_for_npv( prices: &CommodityPrices, year: u32, ) -> ObjectiveCoefficients { + // Small constant added toeach activity coefficient to ensure break-even/slightly negative + // assets are still dispatched + const EPSILON_ACTIVITY_COEFFICIENT: MoneyPerActivity = MoneyPerActivity(1e-14); + // Capacity coefficient let capacity_coefficient = -annual_fixed_cost(asset); - // Small epsilon to ensure break-even assets are dispatched - let epsilon = MoneyPerActivity(1e-14); - // Activity coefficients let mut activity_coefficients = IndexMap::new(); for time_slice in time_slice_info.iter_ids() { let coefficient = calculate_activity_coefficient_for_npv(asset, time_slice, prices, year); - activity_coefficients.insert(time_slice.clone(), coefficient + epsilon); + activity_coefficients.insert( + time_slice.clone(), + coefficient + EPSILON_ACTIVITY_COEFFICIENT, + ); } // Unmet demand coefficient (we don't apply a cost to unmet demand, so we set this to zero) From c6b6b909b5d68e68a331665871a807e2538a6f29 Mon Sep 17 00:00:00 2001 From: Aurash Karimi Date: Tue, 11 Nov 2025 16:41:23 +0000 Subject: [PATCH 4/5] use f64::EPSILON --- src/simulation/investment/appraisal/coefficients.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation/investment/appraisal/coefficients.rs b/src/simulation/investment/appraisal/coefficients.rs index 8027cb707..75cd73622 100644 --- a/src/simulation/investment/appraisal/coefficients.rs +++ b/src/simulation/investment/appraisal/coefficients.rs @@ -88,7 +88,7 @@ pub fn calculate_coefficients_for_npv( ) -> ObjectiveCoefficients { // Small constant added toeach activity coefficient to ensure break-even/slightly negative // assets are still dispatched - const EPSILON_ACTIVITY_COEFFICIENT: MoneyPerActivity = MoneyPerActivity(1e-14); + const EPSILON_ACTIVITY_COEFFICIENT: MoneyPerActivity = MoneyPerActivity(f64::EPSILON * 100.0); // Capacity coefficient let capacity_coefficient = -annual_fixed_cost(asset); From 26d18c2627be12dedd3f2ef7a01bc5c9ef10fed8 Mon Sep 17 00:00:00 2001 From: Aurashk Date: Thu, 13 Nov 2025 17:12:58 +0000 Subject: [PATCH 5/5] Update src/simulation/investment/appraisal/coefficients.rs Co-authored-by: Tom Bland --- src/simulation/investment/appraisal/coefficients.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation/investment/appraisal/coefficients.rs b/src/simulation/investment/appraisal/coefficients.rs index 75cd73622..71a268fc5 100644 --- a/src/simulation/investment/appraisal/coefficients.rs +++ b/src/simulation/investment/appraisal/coefficients.rs @@ -86,7 +86,7 @@ pub fn calculate_coefficients_for_npv( prices: &CommodityPrices, year: u32, ) -> ObjectiveCoefficients { - // Small constant added toeach activity coefficient to ensure break-even/slightly negative + // Small constant added to each activity coefficient to ensure break-even/slightly negative // assets are still dispatched const EPSILON_ACTIVITY_COEFFICIENT: MoneyPerActivity = MoneyPerActivity(f64::EPSILON * 100.0);