-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dmuldrew/smart calculate charging #324
Closed
dmuldrew
wants to merge
62
commits into
transportation_electrification
from
dmuldrew/smart_calculate_charging
Closed
Changes from all commits
Commits
Show all changes
62 commits
Select commit
Hold shift + click to select a range
09a85f4
feat: adding data processing script (#243)
isond 11d0905
feat: generate profiles for immediate charging (#266)
isond 7dad265
style: update style from #266
danielolsen 3086e56
feat: add function to calculate VMT share for each day of the year (#…
danielolsen 89ec675
fix: negative dwell time calculation in data processing (#299)
isond 41d4cdb
feat: add smart_charging file
isond 1bf9c87
feat: add dwelling file
isond dba5573
refactor: add get_total_daily_vmt function
isond 27e6299
refactor: fix get_segment function
isond ee67a54
refactor: fix get_energy_limit function
isond 938cb77
docs: update docstrings for get_segment and get_energy_limit
isond cdedb6f
refactor: fix how to get daily_vmt_total
isond 1488be8
refactor: update locationstrategy to location_strategy and its usage
isond cfd5c0d
docs: update docstrings for get_total_daily_vmt
isond eb3b775
fix: change type hints in get_total_daily_vmt
isond 65b6890
refactor: add more helper functions
isond 9c4292c
refactor: add additional newdata columns
isond 6204028
refactor: add get_constrtaints function
isond 872b566
refactor: update constraints section in main function
isond a4ecaa5
refactor: add calculate_optimization function
isond 07f07fd
refactor: update optimization section in main function
isond 634c28e
refactor: change start and end values
isond 2653a5b
refactor: fix indexing and tripG2Vload calculation
isond 21d021b
refactor: fix trip start battery charge and trip end battery charge v…
isond 8aee61d
refactor: remove else-statement
isond 3cdc32e
fix: add import statements
isond c77657e
refactor: add location_allowed and why_to_list
isond ba716e9
refactor: remove if-statement in get_total_daily_vmt
isond 259972c
refactor: update daily_vmt_total to a dict
isond dfe007b
refactor: update get_segment calculation
isond cf89d1d
refactor: update get_energy_limit calculation
isond 86ef396
refactor: use math.floor instead of round in get_rates
isond 39c97ca
refactor: add values to trip number
isond 317d603
refactor: fix daily_vmt_total indexing
isond b9812eb
fix: fix smart_charging parameters
isond 9d9fd9b
refactor: update smart_charging function
isond 63db004
refactor: update get_total_daily_vmt
isond dd9d76a
fix: add daily_values to smart_charging params
isond fbde869
refactor: update daily_vmt_total indexing
isond bc38392
fix: update linprog method to default method
isond 6b5d0c4
test: add smart charging test and data
dmuldrew 5362e22
refactor: calculate all optimization constraints at once
dmuldrew b2f56d5
feat: add regional scaling factors
dmuldrew bf31961
chore: additional data files, move all data files to data folder
dmuldrew c8d960e
feat: add immediate hdv implementation
dmuldrew 12e9553
test: add immediate hdv test
dmuldrew 9d06f35
refactor: update total_hdv_daily_vmt function
dmuldrew bee5e71
feat: add HDV smart charging implementation
dmuldrew da28277
refactor: transportation electrification to common data columns (#311)
dmuldrew f2f41d5
refactor: maximum LDV dwell period to 72 hours, finish charging effic…
dmuldrew b2dd326
refactor: short hdv tests, common optimization functions (#318)
dmuldrew 9dc4801
refactor: LDV uses bev_vmt scaling; simplify model_year_profile updat…
dmuldrew 6f44de3
refactor: modify immediate adjust_bev (#323)
dmuldrew b655e7b
refactor: add optional kwhmi parameter
dmuldrew 0830d14
refactor: add calculate daily smart charging function
dmuldrew 316407b
refactor: wraparound loop update
dmuldrew f2b1198
test: update immediate scaling tests
dmuldrew 8831f6d
doc: add transportation architecture diagram to README
dmuldrew 3261571
doc: add mermaid rendering block
dmuldrew 0d14aca
doc: update subgraph text
dmuldrew 679f2f7
refactor: filtered vmt_total; bev_vmt daily_values
dmuldrew d3025c5
test: debugging printouts for optimization failures
dmuldrew File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,4 +144,6 @@ Thumbs.db | |
prereise/gather/winddata/data/StatePowerCurves.csv | ||
|
||
# Jupyter Notebook | ||
share/ | ||
share/ | ||
|
||
.devcontainer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
prereise/gather/demanddata/transportation_electrification/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
## Architecture Diagram | ||
|
||
``` mermaid | ||
graph TD | ||
A[Vehicle Demand Interface Function] -->|choose vehicle type, vehicle range, model year, charging strategy| B(Load Data) | ||
I --> |evaluate whether charging is available| C{calculate charging over \n given trip window} | ||
J --> H[Geospecific Hourly Load Profile] | ||
H --> F[fa:fa-car Vehicle Demand Profiles] | ||
H --> E[Vehicle Load Plots] | ||
H --> G[Vehicle Load Statistics] | ||
B --> |parse out relevant columns| I[Charging availability and strategy] | ||
|
||
subgraph Trip Window Loop | ||
C --> D(Normalized Trip Demand) | ||
D --> |scale for daily/monthly driving patterns, yearly regional scaling factors| J(Scaled Trip Demand) | ||
C --> |loop over days in year| C | ||
end | ||
``` |
Empty file.
189 changes: 189 additions & 0 deletions
189
prereise/gather/demanddata/transportation_electrification/charging_optimization.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import numpy as np | ||
import pandas as pd | ||
|
||
from prereise.gather.demanddata.transportation_electrification import const, dwelling | ||
|
||
|
||
def get_constraints( | ||
constraints_df, | ||
kwhmi, | ||
power, | ||
trip_strategy, | ||
location_strategy, | ||
location_allowed, | ||
charging_efficiency, | ||
): | ||
"""Determine the consumption and charging constraints for each trip (hour segment) | ||
|
||
:param pandas.DataFrame constraints_df: trip data of vehicles for optimization constraints | ||
:param int kwhmi: fuel efficiency, should vary based on vehicle type and model_year. | ||
:param float power: charger power, EVSE kW. | ||
:param int trip_strategy: a toggle that determines if should charge on any trip or | ||
only after last trip (1-anytrip number, 2-last trip) | ||
:param int location_strategy: where the vehicle can charge-1, 2, 3, 4, 5, or 6; | ||
1-home only, 2-home and work related, 3-anywhere if possibile, | ||
4-home and school only, 5-home and work and school, 6-only work | ||
:param dict location_allowed: starting locations allowed in the dataset | ||
:param float charging_efficiency: from grid to battery efficiency. | ||
:return: (*pandas.DataFrame*) -- a DataFrame adding the calculated constraints | ||
to an individual vehicle's data | ||
""" | ||
grouped_trips = constraints_df.groupby("vehicle_number") | ||
|
||
constraints_df.loc[ | ||
constraints_df["dwell_location"].isin(const.dwell_location_list), | ||
"power_allowed", | ||
] = power | ||
constraints_df["power_allowed"].fillna(0, inplace=True) | ||
|
||
# for "power" - location | ||
if location_strategy == 3: | ||
constraints_df["location_allowed"] = True | ||
else: | ||
allowed = location_allowed[location_strategy] | ||
constraints_df["location_allowed"] = constraints_df["dwell_location"].map( | ||
lambda x: x in allowed | ||
) | ||
|
||
# for "power" - trip_number | ||
if trip_strategy == 1: | ||
constraints_df["trip_allowed"] = True | ||
elif trip_strategy == 2: | ||
constraints_df["trip_allowed"] = ( | ||
constraints_df["trip_number"] == constraints_df["total_trips"] | ||
) | ||
|
||
# for "power" - dwell | ||
constraints_df["dwell_allowed"] = constraints_df["dwell_time"] > 0.2 | ||
|
||
# for "power" - determine if can charge | ||
allowed_cols = [ | ||
"power_allowed", | ||
"location_allowed", | ||
"trip_allowed", | ||
"dwell_allowed", | ||
] | ||
constraints_df["charging_allowed"] = constraints_df[allowed_cols].apply(all, axis=1) | ||
|
||
for trip_num, group in grouped_trips: | ||
constraints_df.loc[group.index, "charging consumption"] = ( | ||
constraints_df.loc[group.index, "trip_miles"] * kwhmi * -1 | ||
) | ||
constraints_df.loc[group.index, "seg"] = dwelling.get_segment( | ||
constraints_df.loc[group.index, "trip_end"], | ||
constraints_df.loc[group.index, "dwell_time"], | ||
) | ||
|
||
constraints_df.loc[ | ||
constraints_df["charging_allowed"] == True, "power" # noqa: E712 | ||
] = constraints_df["power_allowed"] | ||
constraints_df["power"].fillna(0, inplace=True) | ||
|
||
constraints_df["segcum"] = constraints_df["seg"].transform(pd.Series.cumsum) | ||
|
||
constraints_df["energy limit"] = constraints_df.apply( | ||
lambda d: dwelling.get_energy_limit( | ||
d["power"], | ||
d["seg"], | ||
d["trip_end"], | ||
d["dwell_time"], | ||
charging_efficiency, | ||
), | ||
axis=1, | ||
) | ||
|
||
return constraints_df | ||
|
||
|
||
def calculate_optimization( | ||
charging_consumption, | ||
rates, | ||
elimit, | ||
seg, | ||
total_trips, | ||
kwh, | ||
charging_efficiency, | ||
): | ||
"""Calculates the minimized charging cost during a specific dwelling activity | ||
|
||
:param list charging_consumption: the charging consumption for each trip | ||
:param list rates: rates to be used for the cost function | ||
:param list elimit: energy limits during the time span of available charging | ||
:param list seg: the amount of the segments in the dwelling activity | ||
:param int total_trips: total number of trips for the current vehicle | ||
:param float kwh: kwhmi * veh_range, amount of energy needed to charge vehicle. | ||
:param float charging_efficiency: from grid to battery efficiency. | ||
:return: (*dict*) -- contains the necessary inputs for the linprog optimization | ||
""" | ||
|
||
segsum = np.sum(seg) | ||
segcum = np.cumsum(seg) | ||
|
||
f = np.array(rates) / charging_efficiency | ||
|
||
# form all the constraints | ||
# equality constraint | ||
Aeq = np.ones((1, segsum)) # noqa: N806 | ||
|
||
# equality constraint | ||
Beq = -sum(charging_consumption) # noqa: N806 | ||
|
||
# G2V power upper bound in DC | ||
ub = elimit | ||
lb = [0] * segsum | ||
bounds = list(zip(lb, ub)) | ||
|
||
# formulate the constraints matrix in Ax <= b, A can be divided into m | ||
# generate the cumulative sum array of seg in segcum | ||
|
||
# the amount of trips. submatrix dimension is m-1 * m | ||
m = total_trips | ||
|
||
# 'a' is a m-1 * segsum matrix | ||
a = np.zeros((m - 1, segsum)) | ||
Aineq = np.zeros(((m - 1) * m, segsum)) # noqa: N806 | ||
|
||
b = np.tril(np.ones((m - 1, m)), 1) | ||
Bineq = np.zeros((m * (m - 1), 1)) # noqa: N806 | ||
|
||
for j in range(m): | ||
# part of the A matrix | ||
a = np.zeros((m - 1, segsum)) | ||
|
||
if j > 0: | ||
# switch components in b matrix | ||
bb = np.concatenate((b[:, m - j : m], b[:, : m - j]), axis=1) | ||
|
||
else: | ||
# do not switch if j is 0 | ||
bb = b | ||
|
||
charging_consumption = np.array(charging_consumption) | ||
cc = charging_consumption.reshape((charging_consumption.shape[0], 1)) | ||
|
||
# set the constraints in DC | ||
Bineq[(m - 1) * j : (m - 1) * (j + 1), :] = kwh + (np.dot(bb, cc)) | ||
|
||
for ii in range(m - 1): | ||
# indicate the number of the trips | ||
k = j + ii | ||
|
||
if k < m: | ||
# ones part of the column | ||
a[ii : m - 1, segcum[k] - seg[k] : segcum[k]] = 1 | ||
|
||
else: | ||
k = k - m | ||
# ones part of the column | ||
a[ii : m - 1, segcum[k] - seg[k] : segcum[k]] = 1 | ||
|
||
Aineq[(m - 1) * j : (m - 1) * (j + 1), :] = -a | ||
|
||
return { | ||
"c": f, | ||
"A_ub": Aineq, | ||
"b_ub": Bineq, | ||
"A_eq": Aeq, | ||
"b_eq": Beq, | ||
"bounds": bounds, | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we are trying to roll into a new line by
\n
here but I don't see this deployed properly in the preview. Not sure what is the right way to do so in mermaid.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the diagram in the branch:
https://github.com/Breakthrough-Energy/PreREISE/tree/dmuldrew/smart_calculate_charging/prereise/gather/demanddata/transportation_electrification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is what I see in the diagram:
![image](https://user-images.githubusercontent.com/52716585/204629071-9dc83545-44d0-4fec-a59e-950209325183.png)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, it worked in the live online editor:
https://mermaid.live/edit#pako:eNp1kk-L2zAQxb_K4FMWEnrPobAbdzdZylJIaQ_xEmalsS2QJaM_Dm6c796x5WRJoTpZ8k_vzTzNORNWUrbOKodtDT_zwgCvx8MvqpXQBDk1aCTsTCBXoiB4jkYEZc07rFZfB1Fb6wm6mQ59S8vbzqGpeNuwg4ae0C1B1OgqZSrwwWGgqh_gafHdooQcAz4k990oDQN1qCNDcKop1OQ-LysP2KHS-KFpgM1ZoBZRj-gNsR1fKFivUh0ZCE61cFJG2tMFksvr5LI9vJD1LQlVKgFbG53uYSroh7Ol0vSe6O1EPx9KXJe4Eujgn4Rm3N_x3245Jkltwz3wcg_sAwblgxJX6ilF0aLjlG0M4EhzLiaAsDo2xg-wO2yuTc-hKK1CD2NR15RZLen5-DG_NAdyPB5_T5GwuW0TMK7NZJov3qxrUKs_JCd87vThE8xTdZ7zJyitA8n-_ZfGmlBzjNKpbiyrxcDTY_xyGgL-4ajiCUIN482R4MkK1nEzr4v9KPY_w1TZoLnc9MISew_KTMI8CYkkI7Nl1hBXryTP9nk8LjKeoYaKbM2fkkqMOhRZYS6MYgx23xuRrYOLtMxiKzm2XCFn1aTDy1-mpBAr