Skip to content

Commit

Permalink
refactor: LDV uses bev_vmt scaling; simplify model_year_profile updat…
Browse files Browse the repository at this point in the history
…es (#321)
  • Loading branch information
dmuldrew committed Nov 14, 2022
1 parent b2dd326 commit 9dc4801
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
veh_type,2017,2030,2040,2050,,,,,,
LDV_100,0.242,0.214,0.211,0.209,,,,,,
LDV_200,0.259,0.22,0.215,0.214,,,,,,
LDV_300,0.274,0.226,0.22,0.217,,,,,,
LDT_100,0.324,0.318,0.315,0.312,,,,,,
LDT_200,0.344,0.324,0.321,0.321,,,,,,
LDT_300,0.355,0.334,0.331,0.327,,,,,,
MDV,2.13,1.60,1.48,1.37,,,,,,
HDV,2.72,2.13,1.99,1.85,,,,,,
Transit,2.59,2.04,1.91,1.78,,,,,,
,,,,,,,,,,
,,,,,,,,,,
veh_type,2017,2030,2040,2050
LDV_100,0.242,0.214,0.211,0.209
LDV_200,0.259,0.22,0.215,0.214
LDV_300,0.274,0.226,0.22,0.217
LDT_100,0.324,0.318,0.315,0.312
LDT_200,0.344,0.324,0.321,0.321
LDT_300,0.355,0.334,0.331,0.327
MDV,2.13,1.60,1.48,1.37
HDV,2.72,2.13,1.99,1.85
Transit,2.59,2.04,1.91,1.78
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def get_kwhmi(model_year, veh_type, veh_range):
data = pd.read_csv(filepath, index_col="veh_type")

if (veh_type.upper() == "LDV") or (veh_type.upper() == "LDT"):
kwhmi = data.loc[f"{veh_type.upper()}_{veh_range}", model_year]
kwhmi = data.loc[f"{veh_type.upper()}_{veh_range}", str(model_year)]

elif (veh_type.upper() == "MDV") or (veh_type.upper() == "HDV"):
kwhmi = data.loc[f"{veh_type.upper()}", str(model_year)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,17 @@ def immediate_charging(
census_region,
model_year,
veh_range,
kwhmi,
power,
location_strategy,
veh_type,
filepath,
trip_strategy=1,
):
"""Immediate charging function
:param int census_region: any of the 9 census regions defined by US census bureau.
:param int model_year: year that is being modelled/projected to, 2017, 2030, 2040, 2050.
:param int veh_range: 100, 200, or 300, represents how far vehicle can travel on single charge.
:param int kwhmi: fuel efficiency, should vary based on vehicle type and model_year.
:param int power: charger power, EVSE kW.
:param int location_strategy: where the vehicle can charge-1, 2, 3, 4, or 5;
1-home only, 2-home and work related, 3-anywhere if possibile,
Expand All @@ -125,16 +124,20 @@ def immediate_charging(
:param int trip_strategy: determine to charge after any trip (1) or only after the last trip (2)
:return: (*numpy.ndarray*) -- charging profiles.
"""
# Constants
battery_capacity = kwhmi * veh_range
input_day = data_helper.get_input_day(data_helper.get_model_year_dti(model_year))

# load NHTS data from function
if veh_type.lower() == "ldv":
trips = data_helper.remove_ldt(data_helper.load_data(census_region, filepath))

elif veh_type.lower() == "ldt":
trips = data_helper.remove_ldv(data_helper.load_data(census_region, filepath))
elif veh_type.lower() == "mdv":
trips = data_helper.load_hdv_data("mhdv", filepath)
elif veh_type.lower() == "hdv":
trips = data_helper.load_hdv_data("hhdv", filepath)

# Constants
kwhmi = data_helper.get_kwhmi(model_year, veh_type, veh_range)
battery_capacity = kwhmi * veh_range
input_day = data_helper.get_input_day(data_helper.get_model_year_dti(model_year))

# updates the weekend and weekday values in the nhts data
trips = data_helper.update_if_weekend(trips)
Expand All @@ -148,6 +151,7 @@ def immediate_charging(
new_columns = [
"trip start battery charge",
"trip end battery charge",
"charging power",
"charging time",
"charging consumption",
"BEV could be used",
Expand All @@ -172,7 +176,11 @@ def immediate_charging(
# Add booleans for whether the dell time is long enough to allow charging
trips["dwell_allowed"] = trips["dwell_time"] > 0.2
# Add boolean for whether this trip allows charging
allowed_cols = ["location_allowed", "trip_allowed", "dwell_allowed"]
allowed_cols = [
"location_allowed",
"trip_allowed",
"dwell_allowed",
]
trips["charging_allowed"] = trips[allowed_cols].apply(all, axis=1)

# Evaluate weekend vs. weekday for each trip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def immediate_charging(
if trip_strategy == 1:
trips["trip_allowed"] = True
elif trip_strategy == 2:
trips["trip_allowed"] = trips["trip_number"] == trips["total vehicle trips"]
trips["trip_allowed"] = trips["trip_number"] == trips["total_trips"]

# Add booleans for whether the dell time is long enough to allow charging -- (1)
trips["dwell_allowed"] = trips["dwell_time"] > 0.2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def smart_charging(
filepath,
daily_values,
load_demand,
bev_vmt,
trip_strategy=1,
):
"""Smart charging function
Expand Down Expand Up @@ -64,11 +65,11 @@ def smart_charging(
"trip start battery charge",
"trip end battery charge",
"BEV could be used",
"trip_number",
"Battery size",
"Electricity cost",
"Battery discharge",
"Battery charge",
"Battery size",
"trip_number",
]
newdata = newdata.reindex(list(newdata.columns) + new_columns, axis=1, fill_value=0)

Expand All @@ -82,7 +83,6 @@ def smart_charging(
daily_vmt_total = data_helper.get_total_daily_vmt(newdata, input_day, daily_values)

kwh = kwhmi * veh_range
emfacvmt = const.emfacvmt
if power > 19.2:
charging_efficiency = 0.95
else:
Expand Down Expand Up @@ -222,7 +222,9 @@ def smart_charging(

segcum = np.cumsum(seg)
trip_g2v_load[:, start : end + 1] = (
x[segcum[n] - seg[n] : segcum[n]] / charging_efficiency
# possibly? x[segcum[n] - seg[n] + 1 : segcum[n]] / charging_efficiency
x[segcum[n] - seg[n] : segcum[n]]
/ charging_efficiency
)
g2v_load[dwell_location, :] += trip_g2v_load[0, :]
individual_g2v_load[i + n][:] = trip_g2v_load
Expand All @@ -237,9 +239,9 @@ def smart_charging(
electricitycost = trip_g2v_cost
tripload = trip_v2g_load + trip_g2v_load

# update the cost function and vonvert from KW to MW
# update the cost function and convert from KW to MW
cost += (
tripload / 1000 / daily_vmt_total[day_iter] * emfacvmt
tripload / 1000 / daily_vmt_total[day_iter] * bev_vmt
)[0, :]

# SOC rise in kwh, from charging
Expand Down Expand Up @@ -278,45 +280,19 @@ def smart_charging(
:, newdata.columns.get_loc("Battery size")
] = batterysize

# copy individual back to newdata if it can be an EV
newdata.iloc[i : i + total_trips] = individual

# update the counter to the next vehicle
i += total_trips

outputelectricload = sum(g2v_load)

if day_iter == len(input_day) - 1:
# MW
model_year_profile[day_iter * 24 :] += (
outputelectricload[:24] / (daily_vmt_total[day_iter] * 1000) * emfacvmt
)
model_year_profile[:24] += (
outputelectricload[24:48]
/ (daily_vmt_total[day_iter] * 1000)
* emfacvmt
)
model_year_profile[24:48] += (
outputelectricload[48:72]
/ (daily_vmt_total[day_iter] * 1000)
* emfacvmt
)

elif day_iter == len(input_day) - 2:
# MW
model_year_profile[day_iter * 24 : day_iter * 24 + 48] += (
outputelectricload[:48] / (daily_vmt_total[day_iter] * 1000) * emfacvmt
)
model_year_profile[:24] += (
outputelectricload[48:72]
/ (daily_vmt_total[day_iter] * 1000)
* emfacvmt
)
# create wrap-around indexing function
profile_window_indices = np.arange(day_iter * 24, day_iter * 24 + 72) % len(
model_year_profile
)

else:
# MW
model_year_profile[day_iter * 24 : day_iter * 24 + 72] += (
outputelectricload / (daily_vmt_total[day_iter] * 1000) * emfacvmt
)
# MW
model_year_profile[profile_window_indices] += (
outputelectricload / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)

return model_year_profile
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ def smart_charging(
"trip end battery charge",
"BEV could be used",
"Battery size",
"Electricity cost",
"Battery discharge",
"Battery charge",
"Electricity cost",
]
newdata = newdata.reindex(list(newdata.columns) + new_columns, axis=1, fill_value=0)

Expand Down Expand Up @@ -95,33 +95,20 @@ def smart_charging(
charging_efficiency,
)

for day_iter in range(model_year_len):

# Expand load vector linearly to 7200 points instead of 72
if day_iter == model_year_len - 1: # 365
adjusted_load = [
load_demand[i] + model_year_profile[i]
for i in range(day_iter * 24, (day_iter + 1) * 24)
]
adjusted_load += [load_demand[i] + model_year_profile[i] for i in range(48)]
day_num = model_year_len
for day_iter in range(day_num):

elif day_iter == model_year_len - 2: # 364
adjusted_load = [
load_demand[i] + model_year_profile[i]
for i in range(day_iter * 24, ((day_iter + 1) * 24) + 24)
]
adjusted_load += [load_demand[i] + model_year_profile[i] for i in range(24)]

elif day_iter == model_year_len - 3: # 363
adjusted_load = [
load_demand[i] + model_year_profile[i]
for i in range(day_iter * 24, ((day_iter + 1) * 24) + 48)
]
adjusted_load = [
load_demand[i] + model_year_profile[i]
for i in range(
day_iter * 24, (day_iter + 1) * 24 + min(day_num - day_iter - 1, 2) * 24
)
]

else:
adjusted_load = [
if 3 - day_num + day_iter > 0:
adjusted_load += [
load_demand[i] + model_year_profile[i]
for i in range(day_iter * 24, (day_iter * 24) + 72)
for i in range(24 * (3 - day_num + day_iter))
]

cost = np.array(adjusted_load)
Expand Down Expand Up @@ -269,39 +256,22 @@ def smart_charging(
:, newdata.columns.get_loc("Battery size")
] = batterysize

# copy individual back to newdata if it can be an EV
newdata.iloc[i : i + total_trips] = individual
# # copy individual back to newdata if it can be an EV
# newdata.iloc[i : i + total_trips] = individual

# update the counter to the next vehicle
i += total_trips

outputelectricload = sum(g2v_load)

if day_iter == model_year_len - 1:
# MW
model_year_profile[day_iter * 24 :] += (
outputelectricload[:24] / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)
model_year_profile[:24] += (
outputelectricload[24:48] / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)
model_year_profile[24:48] += (
outputelectricload[48:72] / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)
# create wrap-around indexing function
profile_window_indices = np.arange(day_iter * 24, day_iter * 24 + 72) % len(
model_year_profile
)

elif day_iter == model_year_len - 2:
# MW
model_year_profile[day_iter * 24 : day_iter * 24 + 48] += (
outputelectricload[:48] / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)
model_year_profile[:24] += (
outputelectricload[48:72] / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)

else:
# MW
model_year_profile[day_iter * 24 : day_iter * 24 + 72] += (
outputelectricload / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)
# MW
model_year_profile[profile_window_indices] += (
outputelectricload / (daily_vmt_total[day_iter] * 1000) * bev_vmt
)

return model_year_profile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ def test_immediate_charging_region1():
census_region=1,
model_year=2017,
veh_range=100,
kwhmi=0.242,
power=6.6,
location_strategy=2,
veh_type="LDV",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def test_smart_charging():
),
daily_values=daily_values,
load_demand=load_demand,
bev_vmt=const.emfacvmt,
trip_strategy=1,
)

Expand Down

0 comments on commit 9dc4801

Please sign in to comment.