diff --git a/data_energy/techno_production_historic/cleanenergysimpletechno.csv b/data_energy/techno_production_historic/cleanenergysimpletechno.csv index 834addd9..d802ce38 100644 --- a/data_energy/techno_production_historic/cleanenergysimpletechno.csv +++ b/data_energy/techno_production_historic/cleanenergysimpletechno.csv @@ -1,2 +1,3 @@ years,production,unit 2020,31552.17,TWh +2023,36306.66,TWh diff --git a/data_energy/techno_production_historic/sources.txt b/data_energy/techno_production_historic/sources.txt index e30874ae..a082af6b 100644 --- a/data_energy/techno_production_historic/sources.txt +++ b/data_energy/techno_production_historic/sources.txt @@ -8,4 +8,5 @@ OilGen : https://www.statista.com/statistics/273273/world-electricity-generation Hydropower : https://www.statista.com/statistics/273273/world-electricity-generation-by-energy-source/ GasTurbine : 25% of Natural gas electricity generation https://www.statista.com/statistics/273273/world-electricity-generation-by-energy-source/ CombinedGasCycleTurbine : 75% of Natural gas electricity generation https://www.statista.com/statistics/273273/world-electricity-generation-by-energy-source/ -Geothermal : https://geothermal-energy-journal.springeropen.com/articles/10.1186/s40517-024-00290-w \ No newline at end of file +Geothermal : https://geothermal-energy-journal.springeropen.com/articles/10.1186/s40517-024-00290-w +CropEnergy : 1972, by reading this graph https://www.iea.org/reports/bioenergy-2#overview we get 3966Twh in 2022 (2361 from convetional crop and 1605 from short rotation) \ No newline at end of file diff --git a/energy_models/core/ccus/ccus_disc.py b/energy_models/core/ccus/ccus_disc.py index 452d5b71..052043c8 100644 --- a/energy_models/core/ccus/ccus_disc.py +++ b/energy_models/core/ccus/ccus_disc.py @@ -77,7 +77,12 @@ class CCUS_Discipline(SoSWrapp): 'carbon_capture_from_energy_mix': {'type': 'dataframe', 'unit': 'Gt', 'visibility': SoSWrapp.SHARED_VISIBILITY, 'namespace': 'ns_energy', 'dataframe_descriptor': {GlossaryEnergy.Years: ('float', None, True), - 'carbon_capture from energy mix (Gt)': ('float', None, True), }, } + 'carbon_capture from energy mix (Gt)': ('float', None, True), },}, + 'co2_for_food': { + 'type': 'dataframe', 'unit': 'Mt', + 'visibility': SoSWrapp.SHARED_VISIBILITY, 'namespace': 'ns_energy', + 'dataframe_descriptor': {GlossaryEnergy.Years: ('float', None, True), f'{GlossaryEnergy.carbon_capture} for food (Mt)': ('float', None, True), } + } } DESC_OUT = { @@ -134,22 +139,23 @@ def setup_sos_disciplines(self): 'namespace': GlossaryEnergy.NS_CCS, "dynamic_dataframe_columns": True} - if GlossaryEnergy.YearStart in self.get_data_in() and GlossaryEnergy.YearEnd in self.get_data_in(): - year_start = self.get_sosdisc_inputs(GlossaryEnergy.YearStart) - year_end = self.get_sosdisc_inputs(GlossaryEnergy.YearEnd) - - if year_start is not None and year_end is not None: - dynamic_inputs['co2_for_food'] = { - 'type': 'dataframe', 'unit': 'Mt', 'default': pd.DataFrame( - {GlossaryEnergy.Years: np.arange(year_start, year_end + 1), f'{GlossaryEnergy.carbon_capture} for food (Mt)': 0.0}), - 'visibility': SoSWrapp.SHARED_VISIBILITY, 'namespace': 'ns_energy', - 'dataframe_descriptor': {GlossaryEnergy.Years: ('float', None, True), - f'{GlossaryEnergy.carbon_capture} for food (Mt)': ('float', None, True), } - } - + self.update_default_values() self.add_inputs(dynamic_inputs), self.add_outputs(dynamic_outputs) + def update_default_values(self): + """ + Update all default dataframes with years + """ + if self.get_data_in() is not None: + if GlossaryEnergy.YearEnd in self.get_data_in() and GlossaryEnergy.YearStart in self.get_data_in() and 'co2_for_food' in self.get_data_in(): + year_start, year_end = self.get_sosdisc_inputs([GlossaryEnergy.YearStart, GlossaryEnergy.YearEnd]) + if year_start is not None and year_end is not None: + default_co2_for_food = pd.DataFrame({ + GlossaryEnergy.Years: np.arange(year_start, year_end + 1), + f'{GlossaryEnergy.carbon_capture} for food (Mt)': 0.0}) + self.update_default_value('co2_for_food', 'in', default_co2_for_food) + def run(self): # -- get inputs inputs_dict = self.get_sosdisc_inputs() @@ -169,8 +175,6 @@ def run(self): EnergyMix.CARBON_STORAGE_CONSTRAINT: self.ccus_model.carbon_storage_constraint, } - - self.store_sos_outputs_values(outputs_dict) def compute_sos_jacobian(self): diff --git a/energy_models/core/investments/investments_redistribution.py b/energy_models/core/investments/investments_redistribution.py index 11deb593..58865265 100644 --- a/energy_models/core/investments/investments_redistribution.py +++ b/energy_models/core/investments/investments_redistribution.py @@ -79,7 +79,7 @@ def compute_total_energy_investment_wo_tax(self): self.total_investments_in_energy_w_biomass_dry += self.inputs_dict[techno][ GlossaryEnergy.InvestmentsValue].values self.energy_investment_wo_tax = pd.DataFrame( - {GlossaryEnergy.Years: self.years.reset_index(drop=True), + {GlossaryEnergy.Years: self.years, GlossaryEnergy.EnergyInvestmentsWoTaxValue: self.total_investments_in_energy_w_biomass_dry / 1e3}) # G$ to T$ def compute_investment_per_technology(self): @@ -89,9 +89,8 @@ def compute_investment_per_technology(self): # compute part of gdp that is used for investment in energy self.total_investments_in_energy = ( self.economics_df[GlossaryEnergy.OutputNetOfDamage].values * 1e3 * # T$ to G$ - self.percentage_gdp_energy_invest[ - GlossaryEnergy.EnergyInvestPercentageGDPName] / 100.) - self.years = self.economics_df[GlossaryEnergy.Years] + self.percentage_gdp_energy_invest[GlossaryEnergy.EnergyInvestPercentageGDPName].values / 100.) + self.years = self.economics_df[GlossaryEnergy.Years].values investments_dict = {} for energy, techno_list in self.techno_list_dict.items(): # biomassdry technologies does not come in percentages @@ -106,7 +105,7 @@ def compute_investment_per_technology(self): # => Reset self.years index so that they are consistent with invests indices and fill out properly the df self.investment_per_technology_dict = { full_techno_name: pd.DataFrame( - {GlossaryEnergy.Years: self.years.reset_index(drop=True), GlossaryEnergy.InvestValue: invests + {GlossaryEnergy.Years: self.years, GlossaryEnergy.InvestValue: invests }) for full_techno_name, invests in investments_dict.items()} def check_data_integrity(self, inputs_dict): diff --git a/energy_models/core/techno_type/base_techno_models/electricity_techno.py b/energy_models/core/techno_type/base_techno_models/electricity_techno.py index 4097bd9a..70736154 100644 --- a/energy_models/core/techno_type/base_techno_models/electricity_techno.py +++ b/energy_models/core/techno_type/base_techno_models/electricity_techno.py @@ -25,8 +25,8 @@ class ElectricityTechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/fossil_techno.py b/energy_models/core/techno_type/base_techno_models/fossil_techno.py index f1231f53..8e3dc174 100644 --- a/energy_models/core/techno_type/base_techno_models/fossil_techno.py +++ b/energy_models/core/techno_type/base_techno_models/fossil_techno.py @@ -26,8 +26,8 @@ class FossilTechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/high_heat_techno.py b/energy_models/core/techno_type/base_techno_models/high_heat_techno.py index 02167f84..a76f013d 100644 --- a/energy_models/core/techno_type/base_techno_models/high_heat_techno.py +++ b/energy_models/core/techno_type/base_techno_models/high_heat_techno.py @@ -25,8 +25,8 @@ class highheattechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/low_heat_techno.py b/energy_models/core/techno_type/base_techno_models/low_heat_techno.py index adaec82c..7070f952 100644 --- a/energy_models/core/techno_type/base_techno_models/low_heat_techno.py +++ b/energy_models/core/techno_type/base_techno_models/low_heat_techno.py @@ -25,8 +25,8 @@ class lowheattechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/medium_heat_techno.py b/energy_models/core/techno_type/base_techno_models/medium_heat_techno.py index 2eb0a362..c7a62a80 100644 --- a/energy_models/core/techno_type/base_techno_models/medium_heat_techno.py +++ b/energy_models/core/techno_type/base_techno_models/medium_heat_techno.py @@ -25,8 +25,8 @@ class mediumheattechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/renewable_techno.py b/energy_models/core/techno_type/base_techno_models/renewable_techno.py index 2dc774a3..6021d840 100644 --- a/energy_models/core/techno_type/base_techno_models/renewable_techno.py +++ b/energy_models/core/techno_type/base_techno_models/renewable_techno.py @@ -26,8 +26,8 @@ class RenewableTechno(TechnoType): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must be in $/MWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/base_techno_models/syngas_techno.py b/energy_models/core/techno_type/base_techno_models/syngas_techno.py index 2f22bd29..48107d7a 100644 --- a/energy_models/core/techno_type/base_techno_models/syngas_techno.py +++ b/energy_models/core/techno_type/base_techno_models/syngas_techno.py @@ -47,7 +47,7 @@ def configure_energy_data(self, inputs_dict): def compute_transport(self): # Electricity has no Calorific value overload # Warning transport cost unit must $/kWh - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 return transport_cost diff --git a/energy_models/core/techno_type/techno_type.py b/energy_models/core/techno_type/techno_type.py index 385edf39..f893317c 100644 --- a/energy_models/core/techno_type/techno_type.py +++ b/energy_models/core/techno_type/techno_type.py @@ -394,11 +394,11 @@ def compute_price(self): # self.cost_details['OPEX_heat_tech'] = self.cost_details[f'Opex_{self.name}'] * self.crf # self.cost_details[GlossaryEnergy.CO2TaxesValue] = self.cost_details[f'Capex_{self.name}'] * self.crf - self.cost_details[f'{self.name}_factory'] = self.cost_details[f'Capex_{self.name}'] * \ + self.cost_details[f'{self.name}_factory'] = self.cost_details[f'Capex_{self.name}'].values * \ (self.capital_recovery_factor + self.techno_infos_dict['Opex_percentage']) if 'decommissioning_percentage' in self.techno_infos_dict: - self.cost_details[f'{self.name}_factory_decommissioning'] = self.cost_details[f'Capex_{self.name}'] * \ + self.cost_details[f'{self.name}_factory_decommissioning'] = self.cost_details[f'Capex_{self.name}'].values * \ self.techno_infos_dict[ 'decommissioning_percentage'] self.cost_details[f'{self.name}_factory'] += self.cost_details[f'{self.name}_factory_decommissioning'] @@ -406,18 +406,18 @@ def compute_price(self): # Compute and add transport self.cost_details['transport'] = self.compute_transport() - self.cost_details[self.name] = self.cost_details[f'{self.name}_factory'] + self.cost_details['transport'] + \ - self.cost_details['energy_costs'] + self.cost_details[self.name] = self.cost_details[f'{self.name}_factory'].values + self.cost_details['transport'].values + \ + self.cost_details['energy_costs'].values # Add margin in % # self.cost_details[GlossaryEnergy.MarginValue] = self.cost_details[self.name] * self.margin.loc[self.margin[GlossaryEnergy.Years]<= self.cost_details[GlossaryEnergy.Years].max()][GlossaryEnergy.MarginValue].values / 100.0 # self.cost_details[self.name] += self.cost_details[GlossaryEnergy.MarginValue] - price_with_margin = self.cost_details[self.name] * self.margin.loc[self.margin[GlossaryEnergy.Years] + price_with_margin = self.cost_details[self.name].values * self.margin.loc[self.margin[GlossaryEnergy.Years] <= self.cost_details[ GlossaryEnergy.Years].max()][ GlossaryEnergy.MarginValue].values / 100.0 - self.cost_details[GlossaryEnergy.MarginValue] = price_with_margin - self.cost_details[self.name] + self.cost_details[GlossaryEnergy.MarginValue] = price_with_margin - self.cost_details[self.name].values self.cost_details[self.name] = price_with_margin self.compute_carbon_emissions() @@ -434,34 +434,34 @@ def compute_price(self): np.array(self.cost_details[f'{self.name}_factory'].values / self.nb_years_amort_capex)).T.sum( axis=0) # pylint: enable=no-member - self.cost_details[f'{self.name}_amort'] = self.cost_details[f'{self.name}_factory_amort'] + \ - self.cost_details['transport'] + \ - self.cost_details['energy_costs'] + self.cost_details[f'{self.name}_amort'] = self.cost_details[f'{self.name}_factory_amort'].values + \ + self.cost_details['transport'].values + \ + self.cost_details['energy_costs'].values self.cost_details[f'{self.name}_amort'] *= self.margin.loc[self.margin[GlossaryEnergy.Years] <= self.cost_details[ GlossaryEnergy.Years].max()][ GlossaryEnergy.MarginValue].values / 100.0 - self.cost_details[f'{self.name}_amort'] += self.cost_details['CO2_taxes_factory'] + self.cost_details[f'{self.name}_amort'] += self.cost_details['CO2_taxes_factory'].values # Add transport and CO2 taxes - self.cost_details[self.name] += self.cost_details['CO2_taxes_factory'] + self.cost_details[self.name] += self.cost_details['CO2_taxes_factory'].values if 'CO2_taxes_factory' in self.cost_details: - self.cost_details[f'{self.name}_wotaxes'] = self.cost_details[self.name] - \ - self.cost_details['CO2_taxes_factory'] + self.cost_details[f'{self.name}_wotaxes'] = self.cost_details[self.name].values - \ + self.cost_details['CO2_taxes_factory'].values else: - self.cost_details[f'{self.name}_wotaxes'] = self.cost_details[self.name] + self.cost_details[f'{self.name}_wotaxes'] = self.cost_details[self.name].values # CAPEX in ($/MWh) - self.cost_details['CAPEX_Part'] = self.cost_details[f'Capex_{self.name}'] * self.capital_recovery_factor + self.cost_details['CAPEX_Part'] = self.cost_details[f'Capex_{self.name}'].values * self.capital_recovery_factor # Running OPEX in ($/MWh) - self.cost_details['OPEX_Part'] = self.cost_details[f'Capex_{self.name}'] * \ + self.cost_details['OPEX_Part'] = self.cost_details[f'Capex_{self.name}'].values * \ (self.techno_infos_dict['Opex_percentage']) + \ - self.cost_details['transport'] + self.cost_details['energy_costs'] + self.cost_details['transport'].values + self.cost_details['energy_costs'].values # CO2 Tax in ($/MWh) - self.cost_details['CO2Tax_Part'] = self.cost_details[self.name] - \ - self.cost_details[f'{self.name}_wotaxes'] + self.cost_details['CO2Tax_Part'] = self.cost_details[self.name].values - \ + self.cost_details[f'{self.name}_wotaxes'].values return self.cost_details @@ -807,8 +807,8 @@ def compute_transport(self): ''' # transport_cost = 5.43 # $/kg - transport_cost = self.transport_cost['transport'] * \ - self.transport_margin[GlossaryEnergy.MarginValue] / 100.0 + transport_cost = self.transport_cost['transport'].values * \ + self.transport_margin[GlossaryEnergy.MarginValue].values / 100.0 # Need to multiply by * 1.0e3 to put it in $/MWh$ if 'calorific_value' in self.data_energy_dict.keys(): @@ -831,7 +831,7 @@ def compute_carbon_emissions(self): self.compute_scope_1_emissions() self.compute_scope_2_emissions() - self.carbon_intensity[self.name] = self.carbon_intensity['production'] + self.carbon_intensity['Scope 2'] + self.carbon_intensity[self.name] = self.carbon_intensity['production'].values + self.carbon_intensity['Scope 2'].values def compute_scope_1_emissions(self): if 'CO2_from_production' not in self.techno_infos_dict: @@ -1140,12 +1140,12 @@ def compute_sum_all_costs(self): def compute_co2_emissions_from_ressources_usage(self): """Computes the co2 emissions due to resources usage""" for resource in self.resources_used_for_production: - self.carbon_intensity_generic[resource] = self.cost_details[f"{resource}_needs"] * self.resources_CO2_emissions[resource] + self.carbon_intensity_generic[resource] = self.cost_details[f"{resource}_needs"].values * self.resources_CO2_emissions[resource].values def compute_co2_emissions_from_streams_usage(self): """Computes the co2 emissions due to streams usage""" for stream in self.streams_used_for_production: - self.carbon_intensity_generic[stream] = self.cost_details[f"{stream}_needs"] * self.streams_CO2_emissions[stream] + self.carbon_intensity_generic[stream] = self.cost_details[f"{stream}_needs"].values * self.streams_CO2_emissions[stream].values def compute_new_power_production_resource_consumption(self): """ diff --git a/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_all_years.pkl b/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_all_years.pkl index 9b61d6cd..393fc368 100644 Binary files a/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_all_years.pkl and b/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_all_years.pkl differ diff --git a/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_poles.pkl b/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_poles.pkl index 1f75b017..6594eec4 100644 Binary files a/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_poles.pkl and b/energy_models/tests/jacobian_pkls/jacobian_investments_profile_builder_disc_poles.pkl differ