from pathlib import Path
import pandas as pd
from ... import utils
from .ev_component_gen import (generate_vehicle_trip_population_distribution_df,
generate_vehicle_trip_region_distribution_df,
create_uncoordinated_components,
create_coordinated_components,
create_v2g_components)
import warnings
warnings.filterwarnings("ignore")
utils.print_update(level=1,message="Initializing EV Fleet load component simulator...")
print_level_base=2
[docs]
def get_pypsa_ev_components(start_date:str,
end_date:str,
ev_charging:str,
ev_population:float):
# Description: main script for creating a cutout of the modelled region
# creating the hydro cutout based on hydro site locations and the basins they are located within
# and each basins upstream basins.
# Configuration inputs:
config_file = Path("models/fleet_EV_load_simulator/config/config.yaml")
# (i) read needed data
# Load configuration file here
# NOTE: I will update this likely to pull from my own configuration file later
# NOTE: Please make it a yaml
utils.print_update(level=print_level_base,message="Loading EV fleet scenario configuration...")
cfg = utils.load_config(config_file)
# load some params called by multiple functions
start_date_sim_str = start_date
end_date_sim_str = end_date
p_nom_per_charger = float(cfg["p_nom_per_charger"])
ev_population = float(ev_population)
trip_distribution = cfg["trip_distribution"]
# Accessing is generally: cfg["outter_key"]["inner_key"]
# string for ev penetration scenario
ev_pen_str = str(int(ev_population * 100))
utils.print_update(level=print_level_base+1,message=f"Setting up ev-penetration scenario : {ev_pen_str}")
# (1) load_data here:
# use config for file paths
# df_tp_i = pd.read_csv(cfg['tp_path'])
df_tp_i = pd.read_csv(cfg['travel_pattern_path'])
utils.print_update(level=print_level_base+1,message=f"Travel pattern data loaded from {cfg['travel_pattern_path']}")
# df_battery = pd.read_csv(cfg["battery_path"])
df_battery = pd.read_csv(cfg["EV_typical_range"])
utils.print_update(level=print_level_base+1,message=f"EV typical range data loaded from {cfg['EV_typical_range']}")
df_cvc = pd.read_csv(cfg["cvc_path"])
df_pvc = pd.read_csv(cfg["pvc_path"])
utils.print_update(level=print_level_base+1,message=f"Regional vehicle count data loaded from {cfg['cvc_path']} and {cfg['pvc_path']}")
utils.print_update(level=print_level_base+2,message="Cleaning regional vehicle count data...")
# Combine commercial and residential vehicle fleets
total_vehicles_df = pd.merge(df_cvc, df_pvc, on=['Regional District', 'Representative Vehicle'], how='outer')
total_vehicles_df.fillna(0, inplace=True)
total_vehicles_df['Vehicle Count'] = ev_population * (total_vehicles_df["Vehicle Count_x"] + total_vehicles_df["Vehicle Count_y"])
df_tvc = total_vehicles_df[df_pvc.columns.tolist()].copy()
# (2) Functions to create table of all trips needed:
# Use the gen-load-ts-uncoordinated.ipynb for a starting point since
# we made updates since the other file was used.
# redesign ts_template_gen to take inputs of a start_time: "2019-03-10 00:00:00"
# and an end_time as "2019-03-17 23:00:00"
# These should come from the configuration file
utils.print_update(level=print_level_base,message=f"Processing Trip distribution for : {trip_distribution}")
if trip_distribution == "population":
df_final = generate_vehicle_trip_population_distribution_df(df_tvc, df_tp_i, df_battery, start_date_sim_str, end_date_sim_str)
elif trip_distribution == "region":
df_final = generate_vehicle_trip_region_distribution_df(df_tvc, df_tp_i, df_battery, start_date_sim_str, end_date_sim_str)
else:
utils.print_update(level=print_level_base+1 ,message="ERROR: Trip distribution method must be specified as either 'population' or 'region'!",
alert=True)
# (3) Load timeseries dictionary generation function:
# (4) save pickle date of the pypsa ready dictionaries to results/pypsa-components/
# NOTE: Need 3 different functions once for each charging strategy
# charge_strat = cfg["charging"].lower()
charge_strat=ev_charging.lower()
utils.print_update(level=print_level_base,message=f"Processing scenario data for charging strategy : {charge_strat}")
if charge_strat == "uncoordinated":
utils.print_update(level=print_level_base+1,message=f"Creating pypsa components for charging strategy :{charge_strat}")
load_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_load_path"]
create_uncoordinated_components(df_final, df_battery, start_date_sim_str,
end_date_sim_str, load_fpath, p_nom_per_charger)
elif charge_strat == "coordinated":
utils.print_update(level=print_level_base+1,message=f"Creating pypsa components for charging strategy :{charge_strat}")
load_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_load_path"]
bus_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_bus_path"]
charger_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_charger_path"]
discharger_fpath = cfg["ev_prefix_path"] + charge_strat +"_"+ ev_pen_str + "_" + cfg["ev_discharger_path"]
battery_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_battery_path"]
create_coordinated_components(df_final, df_battery, start_date_sim_str, end_date_sim_str,
cfg['ev_battery_cyclic'], cfg['ev_battery_initial_frac'], p_nom_per_charger,
load_fpath, bus_fpath, charger_fpath, battery_fpath)
elif charge_strat == "v2g":
utils.print_update(level=print_level_base+1,message=f"Creating pypsa components for charging strategy :{charge_strat}")
load_fpath = cfg["ev_prefix_path"] + charge_strat +"_"+ ev_pen_str + "_" + cfg["ev_load_path"]
bus_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_bus_path"]
charger_fpath = cfg["ev_prefix_path"] + charge_strat +"_"+ ev_pen_str + "_" + cfg["ev_charger_path"]
discharger_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_discharger_path"]
battery_fpath = cfg["ev_prefix_path"] + charge_strat + "_"+ev_pen_str + "_" + cfg["ev_battery_path"]
create_v2g_components(df_final, df_battery, start_date_sim_str, end_date_sim_str,
cfg['ev_battery_cyclic'], cfg['ev_battery_initial_frac'], p_nom_per_charger,
cfg['p_nom_per_discharger'], load_fpath, bus_fpath,
charger_fpath, discharger_fpath, battery_fpath)
# elif 'hybrid' in charge_strat:
# utils.print_update(level=print_level_base+1,message=f"Creating pypsa components for charging strategy :{charge_strat}")
# charge_strat_main = "coordinated"
# ev_pen_str_main=ev_pen_str
# utils.print_update(level=print_level_base+2,message=f"Creating pypsa components for main strategy :{charge_strat_main} with {ev_pen_str_main}% EV penetration")
# load_fpath = cfg["ev_prefix_path"] + charge_strat_main + "_"+ev_pen_str_main + "_" + cfg["ev_load_path"]
# bus_fpath = cfg["ev_prefix_path"] + charge_strat_main + "_"+ev_pen_str_main + "_" + cfg["ev_bus_path"]
# charger_fpath = cfg["ev_prefix_path"] + charge_strat_main + "_"+ev_pen_str_main + "_" + cfg["ev_charger_path"]
# discharger_fpath = cfg["ev_prefix_path"] + charge_strat_main +"_"+ ev_pen_str_main + "_" + cfg["ev_discharger_path"]
# battery_fpath = cfg["ev_prefix_path"] + charge_strat_main + "_"+ev_pen_str_main + "_" + cfg["ev_battery_path"]
# create_coordinated_components(df_final, df_battery, start_date_sim_str, end_date_sim_str,
# cfg['ev_battery_cyclic'], cfg['ev_battery_initial_frac'], p_nom_per_charger,
# load_fpath, bus_fpath, charger_fpath, battery_fpath)
# charge_strat_filler = "uncoordinated"
# ev_pen_str_filler= str(100- int(ev_pen_str_main))
# utils.print_update(level=print_level_base+2,message=f"Creating pypsa components for filler strategy :{charge_strat_filler} with {ev_pen_str_filler}% EV penetration")
# ## Recreate 'df_tvc' for remaining vehicles from total population
# total_vehicles_df['Vehicle Count'] = (1-ev_population) * (total_vehicles_df["Vehicle Count_x"] + total_vehicles_df["Vehicle Count_y"])
# df_tvc = total_vehicles_df[df_pvc.columns.tolist()].copy()
# if trip_distribution == "population":
# df_final = generate_vehicle_trip_population_distribution_df(df_tvc, df_tp_i, df_battery, start_date_sim_str, end_date_sim_str)
# elif trip_distribution == "region":
# df_final = generate_vehicle_trip_region_distribution_df(df_tvc, df_tp_i, df_battery, start_date_sim_str, end_date_sim_str)
# else:
# utils.print_update(level=print_level_base+1 ,message="ERROR: Trip distribution method must be specified as either 'population' or 'region'!",
# alert=True)
# load_fpath = cfg["ev_prefix_path"] + charge_strat_filler + "_"+ev_pen_str_filler + "_" + cfg["ev_load_path"]
# create_uncoordinated_components(df_final, df_battery, start_date_sim_str,
# end_date_sim_str, load_fpath, p_nom_per_charger)
else:
utils.print_update(level=print_level_base+1,
message="ERROR: Charging Strategy specified is not implemented!",
alert=True)
# (4) save pickle date of the pypsa ready dictionaries to results/pypsa-components/
#NOTE: Try loading these into a notebook and run our simplified pypsa to make sure they work