From d1aa036c41ca2b16ee5d530cc82b574a24e52902 Mon Sep 17 00:00:00 2001 From: noracato Date: Thu, 22 Feb 2024 14:45:10 +0100 Subject: [PATCH 01/11] Add costs for biogenic co2 capture to marginal costs --- Gemfile | 2 +- Gemfile.lock | 6 ++--- app/models/qernel/node_api/cost.rb | 17 ++++++++++++-- .../recursive_factor/weighted_carrier.rb | 20 +++++++++++++++++ spec/models/qernel/node_api/cost_spec.rb | 22 +++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index d60d0dcac..5c662fc8d 100644 --- a/Gemfile +++ b/Gemfile @@ -77,7 +77,7 @@ gem 'ruby-progressbar' # own gems gem 'quintel_merit', ref: '421f3fb', github: 'quintel/merit' -gem 'atlas', ref: 'd5c84b5', github: 'quintel/atlas' +gem 'atlas', ref: 'f9d985c', github: 'quintel/atlas' gem 'fever', ref: '2a91194', github: 'quintel/fever' gem 'refinery', ref: '5439199', github: 'quintel/refinery' gem 'rubel', ref: 'e36554a', github: 'quintel/rubel' diff --git a/Gemfile.lock b/Gemfile.lock index 1ca01cb25..886f99445 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,8 +6,8 @@ GIT GIT remote: https://github.com/quintel/atlas.git - revision: d5c84b505494c92f816624f8b30b4b47941ff75d - ref: d5c84b5 + revision: f9d985c4ee9dbd1617e1cdd22f01441f1e810047 + ref: f9d985c specs: atlas (1.0.0) activemodel (>= 7) @@ -252,7 +252,7 @@ GEM gctools (0.2.4) globalid (1.2.1) activesupport (>= 6.1) - gpgme (2.0.23) + gpgme (2.0.24) mini_portile2 (~> 2.7) haml (5.2.2) temple (>= 0.8.0) diff --git a/app/models/qernel/node_api/cost.rb b/app/models/qernel/node_api/cost.rb index 62f7b350b..12751a94a 100644 --- a/app/models/qernel/node_api/cost.rb +++ b/app/models/qernel/node_api/cost.rb @@ -75,7 +75,8 @@ def marginal_costs elsif electricity_output_conversion.zero? 0.0 else - variable_costs_per_typical_input(include_waste: false) * + costs = variable_costs_per_typical_input(include_waste: false) + (costs.negative? ? 0.0 : costs) * SECS_PER_HOUR / # Highlighting electricity_output_conversion end @@ -368,7 +369,8 @@ def variable_costs_per_typical_input(include_waste: true) fetch(cache_key) do costable = weighted_carrier_cost_per_mj + - co2_emissions_costs_per_typical_input + co2_emissions_costs_per_typical_input + + captured_biogenic_co2_emissions_costs_per_typical_input costable *= costable_energy_factor unless include_waste @@ -417,6 +419,17 @@ def co2_emissions_costs_per_typical_input end end + # Internal: Calculates the captured biogenic CO2 emission costs per typical input (in MJ). + # + # Returns a float representing cost per MJ. + def captured_biogenic_co2_emissions_costs_per_typical_input + fetch(:captured_biogenic_co2_emissions_costs_per_typical_input) do + weighted_carrier_potential_co2_per_mj * + - area.captured_biogenic_co2_price * + free_co2_factor + end + end + # Internal: Calculates the fixed operation and maintenance costs for one plant. # # These costs are made up of fixed O&M costs for the plant. diff --git a/app/models/qernel/recursive_factor/weighted_carrier.rb b/app/models/qernel/recursive_factor/weighted_carrier.rb index 726f3a0b0..b026448ab 100644 --- a/app/models/qernel/recursive_factor/weighted_carrier.rb +++ b/app/models/qernel/recursive_factor/weighted_carrier.rb @@ -37,4 +37,24 @@ def weighted_carrier_co2_per_mj_factor(edge) # Else: continue traversing right. end + + # Same as weighted_carrier_cost_per_mj but for co2 potential biogenic capture + def weighted_carrier_potential_co2_per_mj + fetch(:weighted_carrier_potential_co2_per_mj) do + recursive_factor_without_losses(:weighted_carrier_potential_co2_per_mj_factor) + end + end + + def weighted_carrier_potential_co2_per_mj_factor(edge) + return unless edge + + # Carriers with no or zero intrinsic biogenic CO2 capture potential are not + # counted in this calculation. + + if edge.carrier.potential_co2_conversion_per_mj || domestic_dead_end? + edge.carrier.potential_co2_conversion_per_mj + end + + # Else: continue traversing right. + end end diff --git a/spec/models/qernel/node_api/cost_spec.rb b/spec/models/qernel/node_api/cost_spec.rb index 2f4988cfc..6d9f51d30 100644 --- a/spec/models/qernel/node_api/cost_spec.rb +++ b/spec/models/qernel/node_api/cost_spec.rb @@ -232,6 +232,7 @@ def build_slot(node, carrier, direction, conversion = 1.0) { weighted_carrier_cost_per_mj: 200, co2_emissions_costs_per_typical_input: 300, + captured_biogenic_co2_emissions_costs_per_typical_input: 0, variable_operation_and_maintenance_costs_per_typical_input: 400 } end @@ -367,6 +368,27 @@ def build_slot(node, carrier, direction, conversion = 1.0) end end + describe '#captured_biogenic_co2_emissions_costs_per_typical_input' do + let(:attrs) do + { + weighted_carrier_potential_co2_per_mj: 2.0, + free_co2_factor: 1.0 + } + end + + before do + node.with(attrs) + + allow(api).to receive(:area).and_return( + double(captured_biogenic_co2_price: 2.0) + ) + end + + it 'calculates when everything is set' do + expect(api.send(:captured_biogenic_co2_emissions_costs_per_typical_input)).to eq(-4.0) + end + end + describe '#variable_operation_and_maintenance_costs' do it 'calculates when everything is set' do node.with( From 9b36b10c0ccb3757f42f64de26c4b3fb8bf5df9c Mon Sep 17 00:00:00 2001 From: Mathijs Bijkerk Date: Mon, 26 Feb 2024 15:40:20 +0100 Subject: [PATCH 02/11] Add captured biogenic co2 costs method --- app/models/qernel/node_api/cost.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/models/qernel/node_api/cost.rb b/app/models/qernel/node_api/cost.rb index 12751a94a..c75bfb9ed 100644 --- a/app/models/qernel/node_api/cost.rb +++ b/app/models/qernel/node_api/cost.rb @@ -419,7 +419,17 @@ def co2_emissions_costs_per_typical_input end end - # Internal: Calculates the captured biogenic CO2 emission costs per typical input (in MJ). + # Internal: Determines the costs of captured biogenic co2 . + # + # Return the the yearly costs for captured biogenic co2 for one plant. + def captured_biogenic_co2_emissions_costs + fetch(:captured_biogenic_co2_emissions_costs) do + typical_input * captured_biogenic_co2_emissions_costs_per_typical_input + end + end + + # Internal: Calculates the captured biogenic co2 costs per typical input (in MJ). + # A positive price should lead to negative costs i.e., benefits. # # Returns a float representing cost per MJ. def captured_biogenic_co2_emissions_costs_per_typical_input From 6ed17d7a6fb7cb9db77f1601e4107da4ece3c338 Mon Sep 17 00:00:00 2001 From: noracato Date: Mon, 26 Feb 2024 17:23:13 +0100 Subject: [PATCH 03/11] Per unit methods for captured biogenic emissions for nodes --- app/models/qernel/method_meta_data.rb | 6 ++++++ app/models/qernel/node_api/conversion.rb | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/app/models/qernel/method_meta_data.rb b/app/models/qernel/method_meta_data.rb index 7f19722cf..5231b373b 100644 --- a/app/models/qernel/method_meta_data.rb +++ b/app/models/qernel/method_meta_data.rb @@ -50,6 +50,7 @@ def calculation_methods 'variable_costs_per(:plant)' => {}, 'fuel_costs_per(:plant)' => {}, 'co2_emissions_costs_per(:plant)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:plant)' => {}, 'fixed_operation_and_maintenance_costs_per(:plant)' => {}, 'variable_operation_and_maintenance_costs_per(:plant)' => {}, 'total_initial_investment_per(:plant)' => {}, @@ -62,6 +63,7 @@ def calculation_methods 'variable_costs_per(:node)' => {}, 'fuel_costs_per(:node)' => {}, 'co2_emissions_costs_per(:node)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:node)' => {}, 'fixed_operation_and_maintenance_costs_per(:node)' => {}, 'variable_operation_and_maintenance_costs_per(:node)' => {}, 'total_initial_investment_per(:node)' => {}, @@ -74,6 +76,7 @@ def calculation_methods 'variable_costs_per(:mw_electricity)' => {}, 'fuel_costs_per(:mw_electricity)' => {}, 'co2_emissions_costs_per(:mw_electricity)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:mw_electricity)' => {}, 'fixed_operation_and_maintenance_costs_per(:mw_electricity)' => {}, 'variable_operation_and_maintenance_costs_per(:mw_electricity)' => {}, 'total_initial_investment_per(:mw_electricity)' => {}, @@ -86,6 +89,7 @@ def calculation_methods 'variable_costs_per(:mwh_electricity)' => {}, 'fuel_costs_per(:mwh_electricity)' => {}, 'co2_emissions_costs_per(:mwh_electricity)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:mwh_electricity)' => {}, 'fixed_operation_and_maintenance_costs_per(:mwh_electricity)' => {}, 'variable_operation_and_maintenance_costs_per(:mwh_electricity)' => {}, 'total_initial_investment_per(:mwh_electricity)' => {}, @@ -98,6 +102,7 @@ def calculation_methods 'variable_costs_per(:mw_heat)' => {}, 'fuel_costs_per(:mw_heat)' => {}, 'co2_emissions_costs_per(:mw_heat)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:mw_heat)' => {}, 'fixed_operation_and_maintenance_costs_per(:mw_heat)' => {}, 'variable_operation_and_maintenance_costs_per(:mw_heat)' => {}, 'total_initial_investment_per(:mw_heat)' => {}, @@ -110,6 +115,7 @@ def calculation_methods 'variable_costs_per(:mwh_heat)' => {}, 'fuel_costs_per(:mwh_heat)' => {}, 'co2_emissions_costs_per(:mwh_heat)' => {}, + 'captured_biogenic_co2_emissions_costs_per(:mwh_heat)' => {}, 'fixed_operation_and_maintenance_costs_per(:mwh_heat)' => {}, 'variable_operation_and_maintenance_costs_per(:mwh_heat)' => {}, 'total_initial_investment_per(:mwh_heat)' => {}, diff --git a/app/models/qernel/node_api/conversion.rb b/app/models/qernel/node_api/conversion.rb index 9e58e61b3..aa615fd67 100644 --- a/app/models/qernel/node_api/conversion.rb +++ b/app/models/qernel/node_api/conversion.rb @@ -93,6 +93,10 @@ def co2_emissions_costs_per(unit) convert_to(co2_emissions_costs, unit) end + def captured_biogenic_co2_emissions_costs_per(unit) + convert_to(captured_biogenic_co2_emissions_costs, unit) + end + def variable_operation_and_maintenance_costs_per(unit) convert_to(variable_operation_and_maintenance_costs, unit) end From c1163fe618210aa6bfcc0e07470d7830c7b511e5 Mon Sep 17 00:00:00 2001 From: Kas Kranenburg Date: Wed, 13 Mar 2024 14:16:15 +0100 Subject: [PATCH 04/11] Adding biogenic co2 costs to cost export --- app/serializers/costs_parameters_serializer.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/serializers/costs_parameters_serializer.rb b/app/serializers/costs_parameters_serializer.rb index c29235ddb..34ddab5d8 100644 --- a/app/serializers/costs_parameters_serializer.rb +++ b/app/serializers/costs_parameters_serializer.rb @@ -123,7 +123,7 @@ class CostsParametersSerializer 'Capital costs (eur)', 'Depreciation costs (eur)', 'Fixed operation and maintenance costs (eur)', 'Variable operation and maintenance costs (eur)', 'Total investment over lifetime (eur)', 'WACC', 'Construction time (years)', 'Technical lifetime (years)', - 'CO2 emission costs (eur)', 'Number of units' + 'CO2 emission costs (eur)', 'Biogenic Co2 emission costs (eur)', 'Number of units' ] # Creates a new costs csv serializer. @@ -211,7 +211,8 @@ def node_rows_for_subgroup(graph, group, subgroup) subgroup, # Subgroup node.key, # Key format_num(node.query.total_costs_per(:node) - - node.query.fuel_costs_per(:node) - node.query.co2_emissions_costs_per(:node)), # Total costs (eur) + node.query.fuel_costs_per(:node) - node.query.co2_emissions_costs_per(:node) - + node.query.captured_biogenic_co2_emissions_costs_per(:node)), # Total costs (eur) format_num(node.query.capital_expenditures_excluding_ccs_per(:node) + node.query.capital_expenditures_ccs_per(:node)), # Total CAPEX (eur) format_num(node.query.operating_expenses_excluding_ccs_per(:node) + @@ -226,6 +227,7 @@ def node_rows_for_subgroup(graph, group, subgroup) format_num(node.query.construction_time), # 'Construction time (years)' format_num(node.query.technical_lifetime), # 'Technical lifetime (years)' format_num(node.query.co2_emissions_costs_per(:node)), # CO2 emission costs (eur) + format_num(node.query.captured_biogenic_co2_emissions_costs_per(:node)), # Biogenic CO2 emissions costs (eur) format_num(node.query.number_of_units) # Number of units ] end @@ -262,6 +264,7 @@ def query_row(group, subgroup, query, name = '') format_num(@query_results["#{query}_construction_time"]), format_num(@query_results["#{query}_technical_lifetime"]), nil, # CO2 emission costs (eur) + nil, # Biogenic CO2 emission costs (eur) nil # Number of units ] end From 8a4bb220941745184e09ec919853c703f637596a Mon Sep 17 00:00:00 2001 From: Mathijs Bijkerk Date: Thu, 21 Mar 2024 11:15:07 +0100 Subject: [PATCH 05/11] Minor changes to BECCUS modelling --- app/serializers/costs_parameters_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/serializers/costs_parameters_serializer.rb b/app/serializers/costs_parameters_serializer.rb index 34ddab5d8..69a7b3ebe 100644 --- a/app/serializers/costs_parameters_serializer.rb +++ b/app/serializers/costs_parameters_serializer.rb @@ -123,7 +123,7 @@ class CostsParametersSerializer 'Capital costs (eur)', 'Depreciation costs (eur)', 'Fixed operation and maintenance costs (eur)', 'Variable operation and maintenance costs (eur)', 'Total investment over lifetime (eur)', 'WACC', 'Construction time (years)', 'Technical lifetime (years)', - 'CO2 emission costs (eur)', 'Biogenic Co2 emission costs (eur)', 'Number of units' + 'CO2 emission costs (eur)', 'Captured biogenic CO2 costs (eur)', 'Number of units' ] # Creates a new costs csv serializer. From 4ebbaa8d3a7e036d58c9c60a5c32bab043ae10c9 Mon Sep 17 00:00:00 2001 From: Mathijs Bijkerk Date: Thu, 21 Mar 2024 13:25:15 +0100 Subject: [PATCH 06/11] Remove label emissions from captured_biogenic_co2_costs --- app/models/qernel/method_meta_data.rb | 12 ++++++------ app/models/qernel/node_api/conversion.rb | 4 ++-- app/models/qernel/node_api/cost.rb | 12 ++++++------ app/serializers/costs_parameters_serializer.rb | 4 ++-- spec/models/qernel/node_api/cost_spec.rb | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/models/qernel/method_meta_data.rb b/app/models/qernel/method_meta_data.rb index 5231b373b..d4fcc7155 100644 --- a/app/models/qernel/method_meta_data.rb +++ b/app/models/qernel/method_meta_data.rb @@ -50,7 +50,7 @@ def calculation_methods 'variable_costs_per(:plant)' => {}, 'fuel_costs_per(:plant)' => {}, 'co2_emissions_costs_per(:plant)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:plant)' => {}, + 'captured_biogenic_co2_costs_per(:plant)' => {}, 'fixed_operation_and_maintenance_costs_per(:plant)' => {}, 'variable_operation_and_maintenance_costs_per(:plant)' => {}, 'total_initial_investment_per(:plant)' => {}, @@ -63,7 +63,7 @@ def calculation_methods 'variable_costs_per(:node)' => {}, 'fuel_costs_per(:node)' => {}, 'co2_emissions_costs_per(:node)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:node)' => {}, + 'captured_biogenic_co2_costs_per(:node)' => {}, 'fixed_operation_and_maintenance_costs_per(:node)' => {}, 'variable_operation_and_maintenance_costs_per(:node)' => {}, 'total_initial_investment_per(:node)' => {}, @@ -76,7 +76,7 @@ def calculation_methods 'variable_costs_per(:mw_electricity)' => {}, 'fuel_costs_per(:mw_electricity)' => {}, 'co2_emissions_costs_per(:mw_electricity)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:mw_electricity)' => {}, + 'captured_biogenic_co2_costs_per(:mw_electricity)' => {}, 'fixed_operation_and_maintenance_costs_per(:mw_electricity)' => {}, 'variable_operation_and_maintenance_costs_per(:mw_electricity)' => {}, 'total_initial_investment_per(:mw_electricity)' => {}, @@ -89,7 +89,7 @@ def calculation_methods 'variable_costs_per(:mwh_electricity)' => {}, 'fuel_costs_per(:mwh_electricity)' => {}, 'co2_emissions_costs_per(:mwh_electricity)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:mwh_electricity)' => {}, + 'captured_biogenic_co2_costs_per(:mwh_electricity)' => {}, 'fixed_operation_and_maintenance_costs_per(:mwh_electricity)' => {}, 'variable_operation_and_maintenance_costs_per(:mwh_electricity)' => {}, 'total_initial_investment_per(:mwh_electricity)' => {}, @@ -102,7 +102,7 @@ def calculation_methods 'variable_costs_per(:mw_heat)' => {}, 'fuel_costs_per(:mw_heat)' => {}, 'co2_emissions_costs_per(:mw_heat)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:mw_heat)' => {}, + 'captured_biogenic_co2_costs_per(:mw_heat)' => {}, 'fixed_operation_and_maintenance_costs_per(:mw_heat)' => {}, 'variable_operation_and_maintenance_costs_per(:mw_heat)' => {}, 'total_initial_investment_per(:mw_heat)' => {}, @@ -115,7 +115,7 @@ def calculation_methods 'variable_costs_per(:mwh_heat)' => {}, 'fuel_costs_per(:mwh_heat)' => {}, 'co2_emissions_costs_per(:mwh_heat)' => {}, - 'captured_biogenic_co2_emissions_costs_per(:mwh_heat)' => {}, + 'captured_biogenic_co2_costs_per(:mwh_heat)' => {}, 'fixed_operation_and_maintenance_costs_per(:mwh_heat)' => {}, 'variable_operation_and_maintenance_costs_per(:mwh_heat)' => {}, 'total_initial_investment_per(:mwh_heat)' => {}, diff --git a/app/models/qernel/node_api/conversion.rb b/app/models/qernel/node_api/conversion.rb index aa615fd67..d0bd1b92b 100644 --- a/app/models/qernel/node_api/conversion.rb +++ b/app/models/qernel/node_api/conversion.rb @@ -93,8 +93,8 @@ def co2_emissions_costs_per(unit) convert_to(co2_emissions_costs, unit) end - def captured_biogenic_co2_emissions_costs_per(unit) - convert_to(captured_biogenic_co2_emissions_costs, unit) + def captured_biogenic_co2_costs_per(unit) + convert_to(captured_biogenic_co2_costs, unit) end def variable_operation_and_maintenance_costs_per(unit) diff --git a/app/models/qernel/node_api/cost.rb b/app/models/qernel/node_api/cost.rb index c75bfb9ed..1ee5baec7 100644 --- a/app/models/qernel/node_api/cost.rb +++ b/app/models/qernel/node_api/cost.rb @@ -370,7 +370,7 @@ def variable_costs_per_typical_input(include_waste: true) costable = weighted_carrier_cost_per_mj + co2_emissions_costs_per_typical_input + - captured_biogenic_co2_emissions_costs_per_typical_input + captured_biogenic_co2_costs_per_typical_input costable *= costable_energy_factor unless include_waste @@ -422,9 +422,9 @@ def co2_emissions_costs_per_typical_input # Internal: Determines the costs of captured biogenic co2 . # # Return the the yearly costs for captured biogenic co2 for one plant. - def captured_biogenic_co2_emissions_costs - fetch(:captured_biogenic_co2_emissions_costs) do - typical_input * captured_biogenic_co2_emissions_costs_per_typical_input + def captured_biogenic_co2_costs + fetch(:captured_biogenic_co2_costs) do + typical_input * captured_biogenic_co2_costs_per_typical_input end end @@ -432,8 +432,8 @@ def captured_biogenic_co2_emissions_costs # A positive price should lead to negative costs i.e., benefits. # # Returns a float representing cost per MJ. - def captured_biogenic_co2_emissions_costs_per_typical_input - fetch(:captured_biogenic_co2_emissions_costs_per_typical_input) do + def captured_biogenic_co2_costs_per_typical_input + fetch(:captured_biogenic_co2_costs_per_typical_input) do weighted_carrier_potential_co2_per_mj * - area.captured_biogenic_co2_price * free_co2_factor diff --git a/app/serializers/costs_parameters_serializer.rb b/app/serializers/costs_parameters_serializer.rb index 69a7b3ebe..48b392fa6 100644 --- a/app/serializers/costs_parameters_serializer.rb +++ b/app/serializers/costs_parameters_serializer.rb @@ -212,7 +212,7 @@ def node_rows_for_subgroup(graph, group, subgroup) node.key, # Key format_num(node.query.total_costs_per(:node) - node.query.fuel_costs_per(:node) - node.query.co2_emissions_costs_per(:node) - - node.query.captured_biogenic_co2_emissions_costs_per(:node)), # Total costs (eur) + node.query.captured_biogenic_co2_costs_per(:node)), # Total costs (eur) format_num(node.query.capital_expenditures_excluding_ccs_per(:node) + node.query.capital_expenditures_ccs_per(:node)), # Total CAPEX (eur) format_num(node.query.operating_expenses_excluding_ccs_per(:node) + @@ -227,7 +227,7 @@ def node_rows_for_subgroup(graph, group, subgroup) format_num(node.query.construction_time), # 'Construction time (years)' format_num(node.query.technical_lifetime), # 'Technical lifetime (years)' format_num(node.query.co2_emissions_costs_per(:node)), # CO2 emission costs (eur) - format_num(node.query.captured_biogenic_co2_emissions_costs_per(:node)), # Biogenic CO2 emissions costs (eur) + format_num(node.query.captured_biogenic_co2_costs_per(:node)), # Biogenic CO2 emissions costs (eur) format_num(node.query.number_of_units) # Number of units ] end diff --git a/spec/models/qernel/node_api/cost_spec.rb b/spec/models/qernel/node_api/cost_spec.rb index 6d9f51d30..d0f77334d 100644 --- a/spec/models/qernel/node_api/cost_spec.rb +++ b/spec/models/qernel/node_api/cost_spec.rb @@ -232,7 +232,7 @@ def build_slot(node, carrier, direction, conversion = 1.0) { weighted_carrier_cost_per_mj: 200, co2_emissions_costs_per_typical_input: 300, - captured_biogenic_co2_emissions_costs_per_typical_input: 0, + captured_biogenic_co2_costs_per_typical_input: 0, variable_operation_and_maintenance_costs_per_typical_input: 400 } end @@ -368,7 +368,7 @@ def build_slot(node, carrier, direction, conversion = 1.0) end end - describe '#captured_biogenic_co2_emissions_costs_per_typical_input' do + describe '#captured_biogenic_co2_costs_per_typical_input' do let(:attrs) do { weighted_carrier_potential_co2_per_mj: 2.0, @@ -385,7 +385,7 @@ def build_slot(node, carrier, direction, conversion = 1.0) end it 'calculates when everything is set' do - expect(api.send(:captured_biogenic_co2_emissions_costs_per_typical_input)).to eq(-4.0) + expect(api.send(:captured_biogenic_co2_costs_per_typical_input)).to eq(-4.0) end end From 17c55ec00085d117d2b2c60571c4ec22e0b5233e Mon Sep 17 00:00:00 2001 From: Mathijs Bijkerk Date: Thu, 21 Mar 2024 13:55:34 +0100 Subject: [PATCH 07/11] Add migration to allocate existing biomass CHP to explicit dispatchable biomass CHP --- ...0240321134650_rename_biomass_chp_inputs.rb | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 db/migrate/20240321134650_rename_biomass_chp_inputs.rb diff --git a/db/migrate/20240321134650_rename_biomass_chp_inputs.rb b/db/migrate/20240321134650_rename_biomass_chp_inputs.rb new file mode 100644 index 000000000..0266de88c --- /dev/null +++ b/db/migrate/20240321134650_rename_biomass_chp_inputs.rb @@ -0,0 +1,21 @@ +require 'etengine/scenario_migration' + +class RenameBiomassChpInputs < ActiveRecord::Migration[7.0] + include ETEngine::ScenarioMigration + + KEYS = { + 'capacity_of_energy_chp_local_wood_pellets' => 'capacity_of_energy_chp_local_wood_pellets_dispatchable', + 'share_of_energy_chp_local_ht_wood_pellets' => 'share_of_energy_chp_local_ht_wood_pellets_dispatchable', + 'share_of_energy_chp_local_mt_wood_pellets' => 'share_of_energy_chp_local_mt_wood_pellets_dispatchable' + }.freeze + + def up + migrate_scenarios do |scenario| + KEYS.each do |old_key, new_key| + if scenario.user_values.key?(old_key) + scenario.user_values[new_key] = scenario.user_values.delete(old_key) + end + end + end + end +end From 1d266d4a3a79514ac0cf3b00c3dee4a1a6a7bb39 Mon Sep 17 00:00:00 2001 From: noracato Date: Mon, 25 Mar 2024 08:47:04 +0100 Subject: [PATCH 08/11] Use existing molecule graph for costs download instead of creating a new one --- app/serializers/costs_parameters_serializer.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/serializers/costs_parameters_serializer.rb b/app/serializers/costs_parameters_serializer.rb index 48b392fa6..85e45642e 100644 --- a/app/serializers/costs_parameters_serializer.rb +++ b/app/serializers/costs_parameters_serializer.rb @@ -133,7 +133,7 @@ class CostsParametersSerializer # Returns a CostsCsvSerializer. def initialize(scenario) @graph = scenario.gql.future.graph - @molecule_graph = Qernel::Plugins::Molecules.new(@graph).molecule_graph + @molecule_graph = scenario.gql.future.molecules @gql = scenario.gql end @@ -210,12 +210,12 @@ def node_rows_for_subgroup(graph, group, subgroup) group, # Group subgroup, # Subgroup node.key, # Key - format_num(node.query.total_costs_per(:node) - - node.query.fuel_costs_per(:node) - node.query.co2_emissions_costs_per(:node) - + format_num(node.query.total_costs_per(:node) - + node.query.fuel_costs_per(:node) - node.query.co2_emissions_costs_per(:node) - node.query.captured_biogenic_co2_costs_per(:node)), # Total costs (eur) - format_num(node.query.capital_expenditures_excluding_ccs_per(:node) + + format_num(node.query.capital_expenditures_excluding_ccs_per(:node) + node.query.capital_expenditures_ccs_per(:node)), # Total CAPEX (eur) - format_num(node.query.operating_expenses_excluding_ccs_per(:node) + + format_num(node.query.operating_expenses_excluding_ccs_per(:node) + node.query.operating_expenses_ccs_per(:node)), # Total OPEX (eur) format_num(node.query.cost_of_capital_per(:node)), # 'Capital costs (eur)' format_num(node.query.depreciation_costs_per(:node)), # 'Depreciation costs (eur)' @@ -276,7 +276,7 @@ def query_row(group, subgroup, query, name = '') # For each base key it performs a set of queries: [{key}, {key}_capex, ...] # Skips queries that could not be found. Saves the results in @query_results. def perform_queries! - as_queries = queries.flat_map do |key| + as_queries = queries.flat_map do |key| [ Gquery.get(key), Gquery.get("#{key}_annualised_costs"), From bdd5dcbbf5121d67c727ec172083d34c9a23348a Mon Sep 17 00:00:00 2001 From: noracato Date: Mon, 25 Mar 2024 09:22:18 +0100 Subject: [PATCH 09/11] Run migrations --- db/schema.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index a38d5917a..7c27d9800 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2024_01_26_141138) do +ActiveRecord::Schema[7.0].define(version: 2024_03_21_134650) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.string "name", limit: 191, null: false t.string "record_type", limit: 191, null: false @@ -53,7 +53,7 @@ t.index ["scenario_id"], name: "index_heat_network_orders_on_scenario_id" end - create_table "households_space_heating_producer_orders", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + create_table "households_space_heating_producer_orders", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.integer "scenario_id" t.text "order" t.index ["scenario_id"], name: "index_households_space_heating_producer_orders_on_scenario_id", unique: true From 002373daa1498bac148bfab3e72fb674a25247ba Mon Sep 17 00:00:00 2001 From: noracato Date: Mon, 25 Mar 2024 10:51:30 +0100 Subject: [PATCH 10/11] Add separate molecule node costs method for captured biogenic co2 --- app/models/qernel/node_api/molecule_api.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/qernel/node_api/molecule_api.rb b/app/models/qernel/node_api/molecule_api.rb index fd0da0134..9a4bc9462 100644 --- a/app/models/qernel/node_api/molecule_api.rb +++ b/app/models/qernel/node_api/molecule_api.rb @@ -29,6 +29,12 @@ def co2_emissions_costs_per_typical_input 0.0 end + # Public: The price of captured biogenic CO2 emissions by the node. Molecule nodes do not have + # CO2 emissions so this is always zero. + def captured_biogenic_co2_costs_per_typical_input + 0.0 + end + private # Molecule nodes define demand in kg (kg/year), while capacities are specified in kg/hour. From 518260b11984f53cbd5db265f50de6566f6f8498 Mon Sep 17 00:00:00 2001 From: Mathijs Bijkerk Date: Mon, 25 Mar 2024 14:46:37 +0100 Subject: [PATCH 11/11] Bump Atlas to quintel/atlas@cdb74be --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 5c662fc8d..93e9ac239 100644 --- a/Gemfile +++ b/Gemfile @@ -77,7 +77,7 @@ gem 'ruby-progressbar' # own gems gem 'quintel_merit', ref: '421f3fb', github: 'quintel/merit' -gem 'atlas', ref: 'f9d985c', github: 'quintel/atlas' +gem 'atlas', ref: 'cdb74be', github: 'quintel/atlas' gem 'fever', ref: '2a91194', github: 'quintel/fever' gem 'refinery', ref: '5439199', github: 'quintel/refinery' gem 'rubel', ref: 'e36554a', github: 'quintel/rubel' diff --git a/Gemfile.lock b/Gemfile.lock index 886f99445..04d6c18e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,8 +6,8 @@ GIT GIT remote: https://github.com/quintel/atlas.git - revision: f9d985c4ee9dbd1617e1cdd22f01441f1e810047 - ref: f9d985c + revision: cdb74be0ed878ecfd83a98b3528c538f6aa47bec + ref: cdb74be specs: atlas (1.0.0) activemodel (>= 7) @@ -170,7 +170,7 @@ GEM dry-validation (~> 1.0, >= 1.0.0) connection_pool (2.4.1) crass (1.0.6) - csv (3.2.8) + csv (3.3.0) dalli (3.2.3) date (3.3.4) debug_inspector (1.1.0)