From b33e55d1d2832a15511787db5326761f4ef32f51 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 26 Mar 2019 16:47:51 +0000 Subject: [PATCH 01/10] Add energy supply prices to fuel price scenario --- config/dimensions/es_fuel_types.yml | 3 ++ config/scenarios/es_prices.yml | 55 ----------------------------- config/scenarios/fuel_price.yml | 17 ++++++++- data/dimensions/es_fuel_types.csv | 6 ++++ 4 files changed, 25 insertions(+), 56 deletions(-) create mode 100644 config/dimensions/es_fuel_types.yml delete mode 100644 config/scenarios/es_prices.yml create mode 100644 data/dimensions/es_fuel_types.csv diff --git a/config/dimensions/es_fuel_types.yml b/config/dimensions/es_fuel_types.yml new file mode 100644 index 00000000..e3356a5b --- /dev/null +++ b/config/dimensions/es_fuel_types.yml @@ -0,0 +1,3 @@ +name: es_fuel_types +description: Fuel types used in the energy supply model +elements: es_fuel_types.csv diff --git a/config/scenarios/es_prices.yml b/config/scenarios/es_prices.yml deleted file mode 100644 index 98280f29..00000000 --- a/config/scenarios/es_prices.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: es_prices -description: Dummy data for energy_supply prices data -provides: - - name: gas_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: electricity_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: gas_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: oil_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: coal_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: nuclearFuel_price - description: '' - dims: - - seasons - dtype: float - unit: GBP/MWh - - name: cost_of_carbon - description: '' - dims: - - seasons - dtype: float - unit: GBP/Mt -variants: - - name: es_prices_dummy - description: Dummy prices data to pass to the energy_supply toy model - data: - gas_price: ../energy_supply/scenarios/price.csv - electricity_price: ../energy_supply/scenarios/price.csv - oil_price: ../energy_supply/scenarios/price.csv - coal_price: ../energy_supply/scenarios/price.csv - nuclearFuel_price: ../energy_supply/scenarios/price.csv - cost_of_carbon: ../energy_supply/scenarios/price.csv \ No newline at end of file diff --git a/config/scenarios/fuel_price.yml b/config/scenarios/fuel_price.yml index dc808a68..dbd0812e 100644 --- a/config/scenarios/fuel_price.yml +++ b/config/scenarios/fuel_price.yml @@ -6,12 +6,27 @@ provides: - transport_fuel_type dtype: float unit: £/l - - name: fuel_price_electricity + - name: tr_fuel_price_electricity dtype: float unit: £/kWh + - name: energy_supply_price + description: '' + dims: + - seasons + - es_fuel_types + dtype: float + unit: £/MWh + - name: cost_of_carbon + description: '' + dims: + - seasons + dtype: float + unit: £/Mt variants: - name: baseline description: Baseline fuel price projections data: fuel_price: transport_fuel_price.csv fuel_price_electricity: transport_fuel_price_electricity.csv + energy_supply_price: energy_supply_price.csv + cost_of_carbon: cost_of_carbon.csv diff --git a/data/dimensions/es_fuel_types.csv b/data/dimensions/es_fuel_types.csv new file mode 100644 index 00000000..15ce29f6 --- /dev/null +++ b/data/dimensions/es_fuel_types.csv @@ -0,0 +1,6 @@ +name +coal +electricity +gas +nuclear +oil From b0bc43809a19daa9d9cfd16ae1566b94694cabc7 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Tue, 26 Mar 2019 16:49:04 +0000 Subject: [PATCH 02/10] Use fuel_price scenario in energy supply config --- config/model_runs/energy_supply_agent.yml | 2 +- config/model_runs/energy_supply_demand.yml | 2 +- config/model_runs/energy_supply_minimal.yml | 2 +- config/model_runs/energy_supply_test.yml | 2 +- config/model_runs/energy_supply_toy.yml | 2 +- config/sector_models/energy_supply.yml | 25 +++--------------- config/sector_models/energy_supply_toy.yml | 25 +++--------------- config/sos_models/energy_supply_demand.yml | 25 ++++-------------- config/sos_models/energy_supply_only.yml | 28 +++++---------------- config/sos_models/energy_supply_toy.yml | 28 +++++---------------- 10 files changed, 28 insertions(+), 113 deletions(-) diff --git a/config/model_runs/energy_supply_agent.yml b/config/model_runs/energy_supply_agent.yml index 574e87ba..9f7ace47 100644 --- a/config/model_runs/energy_supply_agent.yml +++ b/config/model_runs/energy_supply_agent.yml @@ -1,5 +1,5 @@ scenarios: - es_prices: es_prices_dummy + fuel_price: baseline dummy_energy_demands_minimal: es_energy_demand_minimal sos_model: energy_supply_toy name: energy_supply_agent diff --git a/config/model_runs/energy_supply_demand.yml b/config/model_runs/energy_supply_demand.yml index 4577ab2c..cce74c50 100644 --- a/config/model_runs/energy_supply_demand.yml +++ b/config/model_runs/energy_supply_demand.yml @@ -5,7 +5,7 @@ narratives: load_shedding: - high_cost scenarios: - es_prices: es_prices_dummy + fuel_price: baseline gva: gva_baseline population: pop_baseline temperature: NF1 diff --git a/config/model_runs/energy_supply_minimal.yml b/config/model_runs/energy_supply_minimal.yml index e4be5e5b..5fa6ea61 100644 --- a/config/model_runs/energy_supply_minimal.yml +++ b/config/model_runs/energy_supply_minimal.yml @@ -4,7 +4,7 @@ narratives: load_shedding: - high_cost scenarios: - es_prices: es_prices_dummy + fuel_price: baseline dummy_energy_demands_minimal: es_energy_demand_minimal sos_model: energy_supply_toy stamp: '2018-01-31T10:10:41.791Z' diff --git a/config/model_runs/energy_supply_test.yml b/config/model_runs/energy_supply_test.yml index 4b706b0d..9d102f71 100644 --- a/config/model_runs/energy_supply_test.yml +++ b/config/model_runs/energy_supply_test.yml @@ -4,7 +4,7 @@ narratives: load_shedding: - high_cost scenarios: - es_prices: es_prices_dummy + fuel_price: baseline dummy_energy_demands_full: es_energy_demand_dummy_full sos_model: energy_supply_only stamp: '2018-01-31T10:10:41.791Z' diff --git a/config/model_runs/energy_supply_toy.yml b/config/model_runs/energy_supply_toy.yml index 5474407b..649af43c 100644 --- a/config/model_runs/energy_supply_toy.yml +++ b/config/model_runs/energy_supply_toy.yml @@ -4,7 +4,7 @@ stamp: '2018-01-31T10:10:41.791Z' sos_model: energy_supply_toy decision_module: '' scenarios: - es_prices: es_prices_dummy + fuel_price: baseline dummy_energy_demands_minimal: es_energy_demand_minimal narratives: load_shedding: diff --git a/config/sector_models/energy_supply.yml b/config/sector_models/energy_supply.yml index a72f9af8..d5bfcb29 100644 --- a/config/sector_models/energy_supply.yml +++ b/config/sector_models/energy_supply.yml @@ -57,29 +57,10 @@ inputs: - seasons unit: GBP/Mt dtype: float -- name: electricity_price +- name: fuel_price dims: - - seasons - unit: GBP/MWh - dtype: float -- name: gas_price - dims: - - seasons - unit: GBP/MWh - dtype: float -- name: nuclearFuel_price - dims: - - seasons - unit: GBP/MWh - dtype: float -- name: oil_price - dims: - - seasons - unit: GBP/MWh - dtype: float -- name: coal_price - dims: - - seasons + - seasons + - es_fuel_types unit: GBP/MWh dtype: float interventions: diff --git a/config/sector_models/energy_supply_toy.yml b/config/sector_models/energy_supply_toy.yml index 3e9d8d68..6dff13cf 100644 --- a/config/sector_models/energy_supply_toy.yml +++ b/config/sector_models/energy_supply_toy.yml @@ -78,30 +78,11 @@ inputs: dims: - seasons dtype: float -- name: electricity_price - unit: GBP/MWh +- name: fuel_price dims: - - seasons - dtype: float -- name: gas_price + - seasons + - es_fuel_types unit: GBP/MWh - dims: - - seasons - dtype: float -- name: nuclearFuel_price - unit: GBP/MWh - dims: - - seasons - dtype: float -- name: oil_price - unit: GBP/MWh - dims: - - seasons - dtype: float -- name: coal_price - unit: GBP/MWh - dims: - - seasons dtype: float outputs: - name: gasfired_gen_tran diff --git a/config/sos_models/energy_supply_demand.yml b/config/sos_models/energy_supply_demand.yml index ac141593..a17a118e 100644 --- a/config/sos_models/energy_supply_demand.yml +++ b/config/sos_models/energy_supply_demand.yml @@ -1,4 +1,5 @@ scenarios: + - fuel_price - gva - population - temperature @@ -569,27 +570,11 @@ scenario_dependencies: sink_input: gva_per_head source_output: gva_per_head - sink: energy_supply - source: es_prices - sink_input: gas_price - source_output: gas_price + source: fuel_price + sink_input: fuel_price + source_output: energy_supply_price - sink: energy_supply - source: es_prices - sink_input: electricity_price - source_output: electricity_price -- sink: energy_supply - source: es_prices - sink_input: oil_price - source_output: oil_price -- sink: energy_supply - source: es_prices - sink_input: coal_price - source_output: coal_price -- sink: energy_supply - source: es_prices - sink_input: nuclearFuel_price - source_output: nuclearFuel_price -- sink: energy_supply - source: es_prices + source: fuel_price sink_input: cost_of_carbon source_output: cost_of_carbon - sink: energy_demand_constrained diff --git a/config/sos_models/energy_supply_only.yml b/config/sos_models/energy_supply_only.yml index 47cbfd71..30cac997 100644 --- a/config/sos_models/energy_supply_only.yml +++ b/config/sos_models/energy_supply_only.yml @@ -6,7 +6,7 @@ narratives: LoadShed_gas: ../../data/energy_supply/narratives/high_load_shed.csv description: very high cost load shedding name: high_cost - sos_model: energy_supply_toy + sos_model: energy_supply_only description: Costs of shedding load name: load_shedding provides: @@ -15,28 +15,12 @@ narratives: - LoadShed_gas scenario_dependencies: - sink: energy_supply - source_output: gas_price - source: es_prices - sink_input: gas_price -- sink: energy_supply - source_output: electricity_price - source: es_prices - sink_input: electricity_price -- sink: energy_supply - source_output: oil_price - source: es_prices - sink_input: oil_price -- sink: energy_supply - source_output: coal_price - source: es_prices - sink_input: coal_price -- sink: energy_supply - source_output: nuclearFuel_price - source: es_prices - sink_input: nuclearFuel_price + source_output: energy_supply_price + source: fuel_price + sink_input: fuel_price - sink: energy_supply source_output: cost_of_carbon - source: es_prices + source: fuel_price sink_input: cost_of_carbon - sink: energy_supply source_output: residential_gas_non_heating @@ -76,5 +60,5 @@ sector_models: - energy_supply model_dependencies: [] scenarios: -- es_prices +- fuel_price - dummy_energy_demands_full diff --git a/config/sos_models/energy_supply_toy.yml b/config/sos_models/energy_supply_toy.yml index a829d20e..46a05057 100644 --- a/config/sos_models/energy_supply_toy.yml +++ b/config/sos_models/energy_supply_toy.yml @@ -1,5 +1,5 @@ scenarios: -- es_prices +- fuel_price - dummy_energy_demands_minimal description: Links the toy version of the energy supply model to dummy scenarios name: energy_supply_toy @@ -18,30 +18,14 @@ narratives: - LoadShed_elec - LoadShed_gas scenario_dependencies: -- source_output: gas_price - sink_input: gas_price - sink: energy_supply_toy - source: es_prices -- source_output: electricity_price - sink_input: electricity_price - sink: energy_supply_toy - source: es_prices -- source_output: oil_price - sink_input: oil_price - sink: energy_supply_toy - source: es_prices -- source_output: coal_price - sink_input: coal_price - sink: energy_supply_toy - source: es_prices -- source_output: nuclearFuel_price - sink_input: nuclearFuel_price - sink: energy_supply_toy - source: es_prices +- sink: energy_supply_toy + source_output: energy_supply_price + source: fuel_price + sink_input: fuel_price - source_output: cost_of_carbon sink_input: cost_of_carbon sink: energy_supply_toy - source: es_prices + source: fuel_price - source_output: residential_gas_non_heating sink_input: residential_gas_non_heating sink: energy_supply_toy From 6dba3e1cbb1fe893ba88c32d656eb617741e5a5e Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 09:40:20 +0000 Subject: [PATCH 03/10] Read fuel_price in ES wrapper --- models/energy_supply/energy_supply.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/models/energy_supply/energy_supply.py b/models/energy_supply/energy_supply.py index 4c9a193a..0a09acc4 100644 --- a/models/energy_supply/energy_supply.py +++ b/models/energy_supply/energy_supply.py @@ -167,20 +167,8 @@ def get_model_inputs(self, data, now): input_cost_of_carbon = data.get_data("cost_of_carbon") self.logger.debug('Input Cost of carbon: %s', input_cost_of_carbon) - input_electricity_price = data.get_data("electricity_price") - self.logger.debug('Input Electricity price: %s', input_electricity_price) - - input_gas_price = data.get_data("gas_price") - self.logger.debug('Input Gas price: %s', input_gas_price) - - input_nuclearFuel_price = data.get_data("nuclearFuel_price") - self.logger.debug('Input Nuclearfuel price: %s', input_nuclearFuel_price) - - input_oil_price = data.get_data("oil_price") - self.logger.debug('Input Oil price: %s', input_oil_price) - - input_coal_price = data.get_data("coal_price") - self.logger.debug('Input Coal price: %s', input_coal_price) + input_price = data.get_data("fuel_price") + self.logger.debug('Input price: %s', input_price) heatload_res = data.get_data('residential_heatload') self.logger.debug('Residential heatload: %s', heatload_res) From ed7846ee5ed5b22df5a6da47e2311057e44a3b03 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 11:39:07 +0000 Subject: [PATCH 04/10] Fix ES price scenario units --- config/scenarios/fuel_price.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/scenarios/fuel_price.yml b/config/scenarios/fuel_price.yml index dbd0812e..dbbf7aaf 100644 --- a/config/scenarios/fuel_price.yml +++ b/config/scenarios/fuel_price.yml @@ -15,13 +15,13 @@ provides: - seasons - es_fuel_types dtype: float - unit: £/MWh + unit: GBP/MWh - name: cost_of_carbon description: '' dims: - seasons dtype: float - unit: £/Mt + unit: GBP/Mt variants: - name: baseline description: Baseline fuel price projections From e0519211ce8f091d3ef7000b9045ea786e423e04 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 12:17:49 +0000 Subject: [PATCH 05/10] Drop energy_supply_toy model run (duplicate of energy_supply_minimal) --- config/model_runs/energy_supply_toy.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 config/model_runs/energy_supply_toy.yml diff --git a/config/model_runs/energy_supply_toy.yml b/config/model_runs/energy_supply_toy.yml deleted file mode 100644 index 649af43c..00000000 --- a/config/model_runs/energy_supply_toy.yml +++ /dev/null @@ -1,14 +0,0 @@ -strategies: [] -description: '' -stamp: '2018-01-31T10:10:41.791Z' -sos_model: energy_supply_toy -decision_module: '' -scenarios: - fuel_price: baseline - dummy_energy_demands_minimal: es_energy_demand_minimal -narratives: - load_shedding: - - high_cost -timesteps: -- 2015 -name: energy_supply_toy From 22fe2ab4baf4d007729f1e26b94092a6dbff052a Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 13:41:50 +0000 Subject: [PATCH 06/10] Simplify ES model inputs loading --- config/sector_models/energy_supply_toy.yml | 2 +- models/energy_supply/energy_supply.py | 275 +++++++++------------ 2 files changed, 114 insertions(+), 163 deletions(-) diff --git a/config/sector_models/energy_supply_toy.yml b/config/sector_models/energy_supply_toy.yml index 6dff13cf..8aa9cd23 100644 --- a/config/sector_models/energy_supply_toy.yml +++ b/config/sector_models/energy_supply_toy.yml @@ -1,6 +1,6 @@ path: models/energy_supply/energy_supply.py description: Toy version of the CGEN++ energy supply model which uses minimal data -classname: EnergySupplyToyWrapper +classname: EnergySupplyWrapper initial_conditions: - ../energy_supply/initial_conditions/historical_interventions_minimal.csv parameters: diff --git a/models/energy_supply/energy_supply.py b/models/energy_supply/energy_supply.py index 0a09acc4..de991210 100644 --- a/models/energy_supply/energy_supply.py +++ b/models/energy_supply/energy_supply.py @@ -52,7 +52,7 @@ def simulate(self, data): self.clear_input_tables() self.build_interventions(data, now) - self.get_model_inputs(data, now) + self.get_model_inputs(data) self.run_the_model() self.retrieve_outputs(data, now) @@ -142,27 +142,9 @@ def build_interventions(self, data, current_timestep): self.logger.debug('Retiring %s generators', len(retirees)) retire_generator(retirees) - def get_model_inputs(self, data, now): + def get_model_inputs(self, data): # Get model inputs - self.logger.debug("Energy Supply Wrapper received inputs in %s", now) - input_residential_gas_non_heating = data.get_data("residential_gas_non_heating") - - self.logger.debug( - 'Input Residential gas non heating: %s', input_residential_gas_non_heating) - - input_residential_electricity_non_heating = data.get_data( - "residential_electricity_non_heating") - self.logger.debug( - 'Input Residential electricity non heating: %s', - input_residential_electricity_non_heating) - - input_service_gas_non_heating = data.get_data("service_gas_non_heating") - self.logger.debug('Input Service gas non heating: %s', input_service_gas_non_heating) - - input_service_electricity_non_heating = data.get_data( - "service_electricity_non_heating") - self.logger.debug( - 'Input Service electricity non heating: %s', input_service_electricity_non_heating) + self.logger.debug("Energy Supply Wrapper received inputs in %s", data.current_timestep) input_cost_of_carbon = data.get_data("cost_of_carbon") self.logger.debug('Input Cost of carbon: %s', input_cost_of_carbon) @@ -170,52 +152,52 @@ def get_model_inputs(self, data, now): input_price = data.get_data("fuel_price") self.logger.debug('Input price: %s', input_price) - heatload_res = data.get_data('residential_heatload') - self.logger.debug('Residential heatload: %s', heatload_res) - - heatload_com = data.get_data('service_heatload') - self.logger.debug('Service heatload: %s', heatload_com) - - gasload_non_heat_res = input_residential_gas_non_heating - elecload_non_heat_res = input_residential_electricity_non_heating - gasload_non_heat_com = input_service_gas_non_heating - elecload_non_heat_com = input_service_electricity_non_heating - - region_names, interval_names = self.get_names("residential_electricity_non_heating") - self.logger.debug('Writing %s to database', "elecload_non_heat_res") - write_input_timestep(elecload_non_heat_res, "elecload_non_heat_res", - now, region_names, interval_names) - region_names, interval_names = self.get_names("service_electricity_non_heating") - self.logger.debug('Writing %s to database', "elecload_non_heat_com") - write_input_timestep(elecload_non_heat_com, "elecload_non_heat_com", - now, region_names, interval_names) - self.logger.debug('Writing %s to database', "gasload_non_heat_res") - write_input_timestep(gasload_non_heat_res, "gasload_non_heat_res", - now, region_names, interval_names) - self.logger.debug('Writing %s to database', "gasload_non_heat_com") - write_input_timestep(gasload_non_heat_com, "gasload_non_heat_com", - now, region_names, interval_names) - self.logger.debug('Writing %s to database', "heatload_res") - write_input_timestep(heatload_res, "heatload_res", - now, region_names, interval_names) - self.logger.debug('Writing %s to database', "heatload_com") - write_input_timestep(heatload_com, "heatload_com", - now, region_names, interval_names) - - elecload_tran = data.get_data('elecload') - self.logger.debug('Writing %s to database', "elecload") - write_input_timestep(elecload_tran, "elecload", - now, region_names, interval_names) - - self.get_gasload(data, now) - - def get_gasload(self, data, now): - - gasload = data.get_data('gasload') - region_names, interval_names = self.get_names( "gasload", spatial_name='gas_nodes') - self.logger.debug('Writing %s to database', "gasload") - write_input_timestep(gasload, "gasload", - now, region_names, interval_names) + inputs_with_region_and_interval = [ + { + 'name_smif': 'residential_electricity_non_heating', + 'name_database': 'elecload_non_heat_res' + }, + { + 'name_smif': 'service_electricity_non_heating', + 'name_database': 'elecload_non_heat_com' + }, + { + 'name_smif': 'residential_gas_non_heating', + 'name_database': 'gasload_non_heat_res' + }, + { + 'name_smif': 'service_gas_non_heating', + 'name_database': 'gasload_non_heat_com' + }, + { + 'name_smif': 'residential_heatload', + 'name_database': 'heatload_res' + }, + { + 'name_smif': 'service_heatload', + 'name_database': 'heatload_com' + }, + { + 'name_smif': 'elecload', + 'name_database': 'elecload' + }, + { + 'name_smif': 'gasload', + 'name_database': 'gasload' + } + ] + for input_ in inputs_with_region_and_interval: + self._load_input_2d(data, **input_) + + def _load_input_2d(self, data_handle, name_smif, name_database): + data = data_handle.get_data(name_smif) + self.logger.debug("Input %s: %s", name_smif, data) + + region_names, interval_names = self.get_dim_names(data.spec) + + self.logger.debug("Writing %s to database", name_database) + write_input_timestep( + data, name_database, data_handle.current_timestep, region_names, interval_names) def run_the_model(self): """Run the model @@ -234,64 +216,56 @@ def retrieve_outputs(self, data, now): This results mapping maps output_parameters to sectormodel output names external => internal """ - timestep_results = { - 'gasfired_gen_tran': 'tran_gas_fired', - 'coal_gen_tran': 'tran_coal', - 'pumpedHydro_gen_tran': 'tran_pump_power', - 'hydro_gen_tran': 'tran_hydro', - 'nuclear_gen_tran': 'tran_nuclear', - 'interconnector_elec_tran': 'tran_interconnector', - 'renewable_gen_tran': 'tran_renewable', - 'elec_cost': 'e_price', - 'elec_reserve_tran': 'e_reserve', - 'domestic_gas': 'gas_domestic', - 'lng_supply': 'gas_lng', - 'interconnector_gas': 'gas_interconnector', - 'storage_gas': 'gas_storage', - 'storage_level': 'storage_level', - 'wind_gen_tran': 'tran_wind_power', - 'pv_gen_tran': 'tran_pv_power', - 'wind_curtail_tran': 'tran_wind_curtailed', - 'pv_curtail_tran': 'tran_pv_curtailed', - 'total_opt_cost': 'total_opt_cost', - 'eh_gas_fired': 'eh_gas_fired', - 'eh_wind_power': 'eh_wind_power', - 'eh_pv_power': 'eh_pv_power', - 'eh_gas_boiler': 'eh_gas_boiler', - 'eh_heat_pump': 'eh_heat_pump', - 'gas_load_shed': 'gas_load_shed', - 'elec_load_shed': 'elec_load_shed', - 'e_emissions': 'e_emissions', - 'e_emissions_eh': 'e_emissions_eh', - 'gas_load_shed_eh': 'gas_load_shed_eh', - 'elec_load_shed_eh': 'elec_load_shed_eh', - 'fresh_water_demand': 'fresh_water_demand', - 'eh_chp': 'eh_chp', - 'gasdemand_heat': 'gasdemand_heat', - 'elecdemand_heat': 'elecdemand_heat', - 'eh_gasboiler_b': 'eh_gasboiler_b', - 'eh_heatpump_b': 'eh_heatpump_b', - 'eh_gasboiler_dh': 'eh_gasboiler_dh', - 'eh_chp_dh': 'eh_chp_dh', - 'gas_injection': 'gas_injection', - 'gas_withdraw': 'gas_withdraw'} - - annual_results = { - # 'total_opt_cost': 'total_opt_cost', - # 'emissions_elec': 'e_emissions' - } + timestep_results = [ + {'name_smif': 'gasfired_gen_tran', 'name_database': 'tran_gas_fired'}, + {'name_smif': 'coal_gen_tran', 'name_database': 'tran_coal'}, + {'name_smif': 'pumpedHydro_gen_tran', 'name_database': 'tran_pump_power'}, + {'name_smif': 'hydro_gen_tran', 'name_database': 'tran_hydro'}, + {'name_smif': 'nuclear_gen_tran', 'name_database': 'tran_nuclear'}, + {'name_smif': 'interconnector_elec_tran', 'name_database': 'tran_interconnector'}, + {'name_smif': 'renewable_gen_tran', 'name_database': 'tran_renewable'}, + {'name_smif': 'elec_cost', 'name_database': 'e_price'}, + {'name_smif': 'elec_reserve_tran', 'name_database': 'e_reserve'}, + {'name_smif': 'domestic_gas', 'name_database': 'gas_domestic'}, + {'name_smif': 'lng_supply', 'name_database': 'gas_lng'}, + {'name_smif': 'interconnector_gas', 'name_database': 'gas_interconnector'}, + {'name_smif': 'storage_gas', 'name_database': 'gas_storage'}, + {'name_smif': 'storage_level', 'name_database': 'storage_level'}, + {'name_smif': 'wind_gen_tran', 'name_database': 'tran_wind_power'}, + {'name_smif': 'pv_gen_tran', 'name_database': 'tran_pv_power'}, + {'name_smif': 'wind_curtail_tran', 'name_database': 'tran_wind_curtailed'}, + {'name_smif': 'pv_curtail_tran', 'name_database': 'tran_pv_curtailed'}, + {'name_smif': 'total_opt_cost', 'name_database': 'total_opt_cost'}, + {'name_smif': 'eh_gas_fired', 'name_database': 'eh_gas_fired'}, + {'name_smif': 'eh_wind_power', 'name_database': 'eh_wind_power'}, + {'name_smif': 'eh_pv_power', 'name_database': 'eh_pv_power'}, + {'name_smif': 'eh_gas_boiler', 'name_database': 'eh_gas_boiler'}, + {'name_smif': 'eh_heat_pump', 'name_database': 'eh_heat_pump'}, + {'name_smif': 'gas_load_shed', 'name_database': 'gas_load_shed'}, + {'name_smif': 'elec_load_shed', 'name_database': 'elec_load_shed'}, + {'name_smif': 'e_emissions', 'name_database': 'e_emissions'}, + {'name_smif': 'e_emissions_eh', 'name_database': 'e_emissions_eh'}, + {'name_smif': 'gas_load_shed_eh', 'name_database': 'gas_load_shed_eh'}, + {'name_smif': 'elec_load_shed_eh', 'name_database': 'elec_load_shed_eh'}, + {'name_smif': 'fresh_water_demand', 'name_database': 'fresh_water_demand'}, + {'name_smif': 'eh_chp', 'name_database': 'eh_chp'}, + {'name_smif': 'gasdemand_heat', 'name_database': 'gasdemand_heat'}, + {'name_smif': 'elecdemand_heat', 'name_database': 'elecdemand_heat'}, + {'name_smif': 'eh_gasboiler_b', 'name_database': 'eh_gasboiler_b'}, + {'name_smif': 'eh_heatpump_b', 'name_database': 'eh_heatpump_b'}, + {'name_smif': 'eh_gasboiler_dh', 'name_database': 'eh_gasboiler_dh'}, + {'name_smif': 'eh_chp_dh', 'name_database': 'eh_chp_dh'}, + {'name_smif': 'gas_injection', 'name_database': 'gas_injection'}, + {'name_smif': 'gas_withdraw', 'name_database': 'gas_withdraw'} + ] + # Open database connection conn = establish_connection() # Write timestep results to data handler - for external_name, internal_name in timestep_results.items(): - self.logger.info("Writing results for %s", external_name) - self.set_results(internal_name, external_name, data, conn) - - # Write annual results to data handler - for external_name, internal_name in annual_results.items(): - self.set_results(internal_name, external_name, data, conn, is_annual=True) + for output in timestep_results: + self.set_results(data, conn, **output) # Close database connection conn.close() @@ -299,37 +273,32 @@ def retrieve_outputs(self, data, now): self.logger.debug("Energy supplyWrapper produced outputs in %s", now) - def set_results(self, internal_parameter_name, external_parameter_name, data_handle, conn, - is_annual=False): + def set_results(self, data_handle, conn, name_database, name_smif): """Pass results from database to data handle """ - # long way around to get canonical entry names for spatial/temporal resolution - dim_names = self.outputs[external_parameter_name].dims - - intervals = self.outputs[external_parameter_name].dim_coords('seasonal_week').ids - index = dim_names.index('seasonal_week') - dim_names.pop(index) - if dim_names: - regions = self.outputs[external_parameter_name].dim_coords(dim_names[0]).ids - - # read from database - need to be careful with internal vs external param name - if is_annual: - output = get_annual_output( - conn, internal_parameter_name, data_handle.current_timestep, regions, - intervals) - else: - output = get_timestep_output( - conn, internal_parameter_name, data_handle.current_timestep, regions, - intervals) + self.logger.info("Writing results for %s", name_smif) + spec = self.outputs[name_smif] + region_names, interval_names = self.get_dim_names(spec) + + output = get_timestep_output( + conn, name_database, data_handle.current_timestep, region_names, interval_names) # set on smif DataHandle - data_handle.set_results(external_parameter_name, output) + data_handle.set_results(name_smif, output) - def get_names(self, name, spatial_name='energy_hub', temporal_name='seasonal_week'): + def get_dim_names(self, spec): """Get region and interval names for a given input """ - region_names = self.inputs[name].dim_coords(spatial_name).ids - interval_names = self.inputs[name].dim_coords(temporal_name).ids + dims = set(spec.dims) + # HACK Assume two-dimensional, assume seasonal_week is the name for the intervals dim + assert len(dims) == 2, "Expected 2 dimensions, got %s" % dims + assert 'seasonal_week' in dims, "Expected 'seasonal_week' in dims, got %s" % dims + dims.remove('seasonal_week') + interval_dim = 'seasonal_week' + region_dim = dims.pop() + + region_names = spec.dim_coords(region_dim).ids + interval_names = spec.dim_coords(interval_dim).ids return region_names, interval_names @@ -1182,21 +1151,3 @@ def values(input_data): # Close communication with the database cur.close() conn.close() - - -class EnergySupplyToyWrapper(EnergySupplyWrapper): - """Monkey patches methods in full version of wrapper with minimal dimension - definitions - """ - - def get_names(self, name, spatial_name='energy_hub_min', temporal_name='seasonal_week'): - """Get region and interval names for a given input - """ - return super().get_names(name, spatial_name, temporal_name) - - def get_gasload(self, data, now): - gasload = data.get_data('gasload') - region_names, interval_names = self.get_names( - "gasload", spatial_name='gas_nodes_minimal') - self.logger.debug('Writing %s to database', "gasload") - write_input_timestep(gasload, "gasload", now, region_names, interval_names) From 6193e9808bb0dce9f7365cd512590a4f8af38695 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 14:14:15 +0000 Subject: [PATCH 07/10] Write ES fuel prices from smif input --- models/energy_supply/energy_supply.py | 71 +++++++++++++-------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/models/energy_supply/energy_supply.py b/models/energy_supply/energy_supply.py index de991210..f77f0087 100644 --- a/models/energy_supply/energy_supply.py +++ b/models/energy_supply/energy_supply.py @@ -146,11 +146,9 @@ def get_model_inputs(self, data): # Get model inputs self.logger.debug("Energy Supply Wrapper received inputs in %s", data.current_timestep) - input_cost_of_carbon = data.get_data("cost_of_carbon") - self.logger.debug('Input Cost of carbon: %s', input_cost_of_carbon) - - input_price = data.get_data("fuel_price") - self.logger.debug('Input price: %s', input_price) + fuel_prices = data.get_data("fuel_price") + self.logger.debug('Input price: %s', fuel_prices) + write_prices(fuel_prices, data.current_timestep) inputs_with_region_and_interval = [ { @@ -394,49 +392,50 @@ def write_simduration(year): conn.close() -def write_gas_price(year, data): - """ +def write_prices(data_array, year): + """Write fuel price data Arguments --------- - year : int - The current model year - data : numpy.ndarray + data : smif.DataArray Price data """ - conn = establish_connection() # Open a cursor to perform database operations + conn = establish_connection() cur = conn.cursor() - - cur.execute("""DELETE FROM "FuelData" WHERE year=%s AND fuel_id=1;""", (year, )) + cur.execute('DELETE FROM "FuelData" WHERE "Year"=%s;', (year, )) sql = """ - INSERT INTO "FuelData" (fuel_id, fueltype, year, season, fuelcost) - VALUES (%s, %s, %s, %s, %s) - """ - - it = np.nditer(data, flags=['multi_index']) - while not it.finished: - cell = it[0] - - _, interval_index = it.multi_index - fuel_id = 1 - fueltype = 'Gas' - insert_data = (fuel_id, - fueltype, - year, - interval_index + 1, - float(cell)) - - # print("Data: {}".format(insert_data)) + INSERT INTO "FuelData" ("Fuel_ID", "FuelType", "Year", "Season", "FuelCost") + VALUES (%s, %s, %s, %s, %s) + """ - cur.execute(sql, insert_data) - it.iternext() + dataframe = data_array.as_df().reset_index() + + # HACK hard code ids for fuel types - fix is to add a fuel types table that FuelData and + # GeneratorParameters can both reference + fuel_ids = { + 'gas': 1, + 'coal': 2, + 'nuclear': 3, + 'oil': 4, + 'electricity': 5, + } + + for datum in dataframe.itertuples(): + cur.execute( + sql, + ( + fuel_ids[datum.es_fuel_types], + datum.es_fuel_types.capitalize(), + year, + datum.seasons, + datum.energy_supply_price + ) + ) - # Make the changes to the database persistent + # Make the changes to the database persistent and close conn.commit() - - # Close communication with the database cur.close() conn.close() From 3dc4c46683f38bb4800e8ec9b9e63b6d4a359f06 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 14:17:17 +0000 Subject: [PATCH 08/10] Include baseline fuel price scenario data --- data/scenarios/cost_of_carbon.csv | 9 ++++++ data/scenarios/energy_supply_price.csv | 41 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 data/scenarios/cost_of_carbon.csv create mode 100644 data/scenarios/energy_supply_price.csv diff --git a/data/scenarios/cost_of_carbon.csv b/data/scenarios/cost_of_carbon.csv new file mode 100644 index 00000000..aaa7f79c --- /dev/null +++ b/data/scenarios/cost_of_carbon.csv @@ -0,0 +1,9 @@ +timestep,seasons,cost_of_carbon +2015,1,31.9 +2015,2,26.1 +2015,3,26.1 +2015,4,29.0 +2020,1,31.9 +2020,2,26.1 +2020,3,26.1 +2020,4,29.0 diff --git a/data/scenarios/energy_supply_price.csv b/data/scenarios/energy_supply_price.csv new file mode 100644 index 00000000..66d5fb87 --- /dev/null +++ b/data/scenarios/energy_supply_price.csv @@ -0,0 +1,41 @@ +timestep,seasons,energy_supply_price,es_fuel_types +2015,1,31.9,oil +2015,2,26.1,oil +2015,3,26.1,oil +2015,4,29,oil +2020,1,31.9,oil +2020,2,26.1,oil +2020,3,26.1,oil +2020,4,29,oil +2015,1,31.9,nuclear +2015,2,26.1,nuclear +2015,3,26.1,nuclear +2015,4,29,nuclear +2020,1,31.9,nuclear +2020,2,26.1,nuclear +2020,3,26.1,nuclear +2020,4,29,nuclear +2015,1,31.9,gas +2015,2,26.1,gas +2015,3,26.1,gas +2015,4,29,gas +2020,1,31.9,gas +2020,2,26.1,gas +2020,3,26.1,gas +2020,4,29,gas +2015,1,44,coal +2015,2,44,coal +2015,3,44,coal +2015,4,44,coal +2020,1,44,coal +2020,2,44,coal +2020,3,44,coal +2020,4,44,coal +2015,1,31.9,electricity +2015,2,26.1,electricity +2015,3,26.1,electricity +2015,4,29,electricity +2020,1,31.9,electricity +2020,2,26.1,electricity +2020,3,26.1,electricity +2020,4,29,electricity From 183ddd1f2995c945e0ce33d81a376305cb143205 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 15:02:36 +0000 Subject: [PATCH 09/10] Drop unused cost_of_carbon --- config/scenarios/fuel_price.yml | 7 ------- config/sector_models/energy_supply.yml | 5 ----- config/sector_models/energy_supply_toy.yml | 5 ----- config/sos_models/energy_supply_demand.yml | 4 ---- config/sos_models/energy_supply_only.yml | 4 ---- config/sos_models/energy_supply_toy.yml | 4 ---- data/scenarios/cost_of_carbon.csv | 9 --------- 7 files changed, 38 deletions(-) delete mode 100644 data/scenarios/cost_of_carbon.csv diff --git a/config/scenarios/fuel_price.yml b/config/scenarios/fuel_price.yml index dbbf7aaf..44baaba1 100644 --- a/config/scenarios/fuel_price.yml +++ b/config/scenarios/fuel_price.yml @@ -16,12 +16,6 @@ provides: - es_fuel_types dtype: float unit: GBP/MWh - - name: cost_of_carbon - description: '' - dims: - - seasons - dtype: float - unit: GBP/Mt variants: - name: baseline description: Baseline fuel price projections @@ -29,4 +23,3 @@ variants: fuel_price: transport_fuel_price.csv fuel_price_electricity: transport_fuel_price_electricity.csv energy_supply_price: energy_supply_price.csv - cost_of_carbon: cost_of_carbon.csv diff --git a/config/sector_models/energy_supply.yml b/config/sector_models/energy_supply.yml index d5bfcb29..a204fb82 100644 --- a/config/sector_models/energy_supply.yml +++ b/config/sector_models/energy_supply.yml @@ -52,11 +52,6 @@ inputs: - seasonal_week unit: MW dtype: float -- name: cost_of_carbon - dims: - - seasons - unit: GBP/Mt - dtype: float - name: fuel_price dims: - seasons diff --git a/config/sector_models/energy_supply_toy.yml b/config/sector_models/energy_supply_toy.yml index 8aa9cd23..ae36f673 100644 --- a/config/sector_models/energy_supply_toy.yml +++ b/config/sector_models/energy_supply_toy.yml @@ -73,11 +73,6 @@ inputs: - energy_hub_min - seasonal_week dtype: float -- name: cost_of_carbon - unit: GBP/Mt - dims: - - seasons - dtype: float - name: fuel_price dims: - seasons diff --git a/config/sos_models/energy_supply_demand.yml b/config/sos_models/energy_supply_demand.yml index a17a118e..7b2ce113 100644 --- a/config/sos_models/energy_supply_demand.yml +++ b/config/sos_models/energy_supply_demand.yml @@ -573,10 +573,6 @@ scenario_dependencies: source: fuel_price sink_input: fuel_price source_output: energy_supply_price -- sink: energy_supply - source: fuel_price - sink_input: cost_of_carbon - source_output: cost_of_carbon - sink: energy_demand_constrained source: gva sink_input: gva_per_sector diff --git a/config/sos_models/energy_supply_only.yml b/config/sos_models/energy_supply_only.yml index 30cac997..8fa2d365 100644 --- a/config/sos_models/energy_supply_only.yml +++ b/config/sos_models/energy_supply_only.yml @@ -18,10 +18,6 @@ scenario_dependencies: source_output: energy_supply_price source: fuel_price sink_input: fuel_price -- sink: energy_supply - source_output: cost_of_carbon - source: fuel_price - sink_input: cost_of_carbon - sink: energy_supply source_output: residential_gas_non_heating source: dummy_energy_demands_full diff --git a/config/sos_models/energy_supply_toy.yml b/config/sos_models/energy_supply_toy.yml index 46a05057..af79929c 100644 --- a/config/sos_models/energy_supply_toy.yml +++ b/config/sos_models/energy_supply_toy.yml @@ -22,10 +22,6 @@ scenario_dependencies: source_output: energy_supply_price source: fuel_price sink_input: fuel_price -- source_output: cost_of_carbon - sink_input: cost_of_carbon - sink: energy_supply_toy - source: fuel_price - source_output: residential_gas_non_heating sink_input: residential_gas_non_heating sink: energy_supply_toy diff --git a/data/scenarios/cost_of_carbon.csv b/data/scenarios/cost_of_carbon.csv deleted file mode 100644 index aaa7f79c..00000000 --- a/data/scenarios/cost_of_carbon.csv +++ /dev/null @@ -1,9 +0,0 @@ -timestep,seasons,cost_of_carbon -2015,1,31.9 -2015,2,26.1 -2015,3,26.1 -2015,4,29.0 -2020,1,31.9 -2020,2,26.1 -2020,3,26.1 -2020,4,29.0 From 572266a1336ae45f61b3e138e55f740b14ea2734 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Wed, 27 Mar 2019 16:30:02 +0000 Subject: [PATCH 10/10] Include biomass in ES prices --- data/dimensions/es_fuel_types.csv | 1 + data/scenarios/energy_supply_price.csv | 8 ++++++++ models/energy_supply/energy_supply.py | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/data/dimensions/es_fuel_types.csv b/data/dimensions/es_fuel_types.csv index 15ce29f6..40d66e05 100644 --- a/data/dimensions/es_fuel_types.csv +++ b/data/dimensions/es_fuel_types.csv @@ -1,4 +1,5 @@ name +biomass coal electricity gas diff --git a/data/scenarios/energy_supply_price.csv b/data/scenarios/energy_supply_price.csv index 66d5fb87..9af3d565 100644 --- a/data/scenarios/energy_supply_price.csv +++ b/data/scenarios/energy_supply_price.csv @@ -39,3 +39,11 @@ timestep,seasons,energy_supply_price,es_fuel_types 2020,2,26.1,electricity 2020,3,26.1,electricity 2020,4,29,electricity +2015,1,40.5,biomass +2015,2,30.7,biomass +2015,3,25.2,biomass +2015,4,28.6,biomass +2020,1,40.5,biomass +2020,2,30.7,biomass +2020,3,25.2,biomass +2020,4,28.6,biomass diff --git a/models/energy_supply/energy_supply.py b/models/energy_supply/energy_supply.py index f77f0087..f6b93de4 100644 --- a/models/energy_supply/energy_supply.py +++ b/models/energy_supply/energy_supply.py @@ -419,7 +419,8 @@ def write_prices(data_array, year): 'coal': 2, 'nuclear': 3, 'oil': 4, - 'electricity': 5, + 'biomass': 5, + 'electricity': 6 } for datum in dataframe.itertuples():