Source code for bc_combined_modelling.clews_to_pypsa

import pandas as pd
from bc_combined_modelling import utils
from pathlib import Path
from bc_combined_modelling.attributes_parser import AttributesParser

[docs] class FutureTechInvestments: def __init__(self, year, scenario_name:str, storage_algorithm:str='Kotzur', timeslices:int=8, solver_name:str='gurobi'): self.year = year self.scenario_name=scenario_name self.storage_alogorithm=storage_algorithm self.timeslices=timeslices self.solver_name:str=solver_name self.aparser=AttributesParser() self.clewb_cfg = self.aparser.clewsb_config self.get_data_paths() self.clews_total_capacity=self.get_scenario_investment(timeslices) self.PWR_capacity_year = self.clews_total_capacity[self.clews_total_capacity['TECHNOLOGY'].str.startswith('PWR') & ~self.clews_total_capacity['TECHNOLOGY'].str.contains('PWRTRN') & (self.clews_total_capacity['YEAR'] == self.year)] self.techs_wnd = {k: v for k, v in self.clewb_cfg['TECHNOLOGIES'].items() if 'WND' in k} self.techs_sol = {k: v for k, v in self.clewb_cfg['TECHNOLOGIES'].items() if 'SOL' in k} self.techs_nuc = {k: v for k, v in self.clewb_cfg['TECHNOLOGIES'].items() if 'URN' in k}
[docs] def get_data_paths(self): ( self.resource_options_wind, self.resource_options_solar, self.committed_wind, self.committed_solar, self.resource_options_wind_ts, self.resource_options_solar_ts, self.committed_wind_ts, self.committed_solar_ts, )=self.aparser.get_data_paths() self.pypsa_resources_solar_year=Path('data/processed_data/solar/potential') self.pypsa_resources_wind_year=Path('data/processed_data/wind/potential') self.pypsa_committed_solar_year=Path('data/processed_data/solar/committed') self.pypsa_committed_wind_year=Path('data/processed_data/wind/committed') self.pypsa_resources_nuc_year=Path('data/processed_data/nuclear/potential') self.pypsa_resources_nuc_year.mkdir(parents=True, exist_ok=True)
[docs] def get_scenario_investment(self,timeslices): self.clews_results_dir=self.aparser.get_bcnexus_scenario_results_path(scenario=self.scenario_name, storage_algorithm=self.storage_alogorithm) scenario_Total_capacity_annual_data_file='TotalCapacityAnnual.csv' results_dir:Path=self.clews_results_dir/f'{timeslices}ts_csvs_{self.solver_name}' self.clews_total_capacity:pd.DataFrame=pd.read_csv(results_dir/scenario_Total_capacity_annual_data_file) return self.clews_total_capacity
[docs] def get_future_techs(self, techs:list, no_of_existing_techs:int): future_techs = {k: v for k, v in techs.items() if v.get('status') == 'future'} return {k: v for k, v in future_techs.items() if int(k[-2:]) > int(no_of_existing_techs)}
[docs] def get_existing_techs(self, techs): existing_techs:dict = {k: v for k, v in techs.items() if v.get('status') == 'existing'} return existing_techs
[docs] def create_mapping(self, future_techs_resource_options:dict, resource_options:pd.DataFrame, output_path:str|Path): mapping = pd.DataFrame(columns=['clews_id', 'name', 'operational_life', 'start_year', 'potential_capacity_GW', 'clews_investment_year', 'invested_capacity_MW']) rows = [] for k_techid, v_info in future_techs_resource_options.items(): rows.append({ 'clews_id': k_techid, 'name': v_info['name'], 'operational_life': v_info['operational_life'], 'start_year': v_info['start_year'], 'potential_capacity_GW': v_info['potential'], 'invested_capacity_MW': 1E3*self.PWR_capacity_year[self.PWR_capacity_year['TECHNOLOGY'] == k_techid].VALUE.values[0] if k_techid in self.PWR_capacity_year['TECHNOLOGY'].values else 0, 'clews_investment_year': self.year }) mapping = pd.concat([mapping, pd.DataFrame(rows)]) mapping.set_index('name', inplace=True) non_overlapping_cols = mapping.loc[:, ~mapping.columns.isin(resource_options.columns)] resource_options = resource_options.join(non_overlapping_cols, how='left') resource_options.to_csv(output_path)
[docs] def create_mapping_nuclear(self, future_techs_resource_options:dict, resource_options:pd.DataFrame, output_path:str|Path): mapping = pd.DataFrame(columns=['clews_id', 'name', 'operational_life', 'clews_investment_year', 'invested_capacity_MW','capex','fom','vom']) rows = [] for k_techid, v_info in future_techs_resource_options.items(): rows.append({ 'clews_id': k_techid, 'name': v_info['name'], 'operational_life': v_info['operational_life'], # 'start_year': v_info['start_year'], # 'potential_capacity_GW': v_info['potential'], 'invested_capacity_MW': 1E3*self.PWR_capacity_year[self.PWR_capacity_year['TECHNOLOGY'] == k_techid].VALUE.values[0] if k_techid in self.PWR_capacity_year['TECHNOLOGY'].values else 0, 'clews_investment_year': self.year, 'capex': v_info['capital_cost'], # USD/kW # NREL ATB 2024, Moderate Scenario, Market price of 2035 , CAPEX 7863 USD/kW, FOM 136 USD/kW, VOM 2.6 USD/kWh 'fom': v_info['fom'], #USD/kWh 'vom': v_info['vom'] #USD/kWh }) mapping = pd.concat([mapping, pd.DataFrame(rows)]) mapping.set_index('name', inplace=True) if resource_options is None or resource_options.empty: mapping.to_csv(output_path) else: non_overlapping_cols = mapping.loc[:, ~mapping.columns.isin(resource_options.columns)] resource_options = resource_options.join(non_overlapping_cols, how='left') resource_options.to_csv(output_path)
[docs] def get_investments(self): # Solar Resources self.existing_tech_sol:dict=self.get_existing_techs(self.techs_sol) self.future_techs_sol_resource_options = self.get_future_techs(self.techs_sol['PWRSOL'], len(self.existing_tech_sol.keys())) print(len(self.existing_tech_sol.keys())) print(self.future_techs_sol_resource_options) resource_options_solar = pd.read_csv(self.resource_options_solar, index_col='cluster_id') self.create_mapping(self.future_techs_sol_resource_options, resource_options_solar, self.pypsa_resources_solar_year/f'resource_options_investments_solar_{self.year}.csv') # Wind Resources self.existing_tech_wnd:dict=self.get_existing_techs(self.techs_wnd) self.future_techs_wnd_resource_options = self.get_future_techs(self.techs_wnd['PWRWND'], len(self.existing_tech_wnd.keys())) print(len(self.existing_tech_wnd.keys())) resource_options_wind = pd.read_csv(self.resource_options_wind, index_col='cluster_id') self.create_mapping(self.future_techs_wnd_resource_options, resource_options_wind, self.pypsa_resources_wind_year/f'resource_options_investments_wind_{self.year}.csv') # Nuclear Resources if self.techs_nuc: self.existing_tech_nuc:dict=self.get_existing_techs(self.techs_nuc) self.future_techs_nuc_resource_options = self.get_future_techs(self.techs_nuc['PWRURN'], len(self.existing_tech_nuc.keys())) print(len(self.existing_tech_nuc.keys())) self.create_mapping_nuclear(self.future_techs_nuc_resource_options, None, self.pypsa_resources_nuc_year/f'resource_options_investments_nuc_{self.year}.csv')