-
Notifications
You must be signed in to change notification settings - Fork 4
63 implement cell by cell electrical model in fvs #75
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
base: main-sim-maintenence
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| import numpy as np | ||
| from paramLoader import * | ||
| import matplotlib.pyplot as plt | ||
|
|
||
| np.random.seed(42) | ||
|
|
||
| class Cell: | ||
| def __init__ (self, soc, resistance, capacity_Ah = 5, hysteresis = 0): | ||
| self.soc = soc | ||
| self.resistance = resistance | ||
| self.capacity_Ah = capacity_Ah | ||
| self.hysteresis = hysteresis | ||
|
|
||
| def ocv(self, T_K = 298.15): | ||
| #code from powertrain | ||
| F = Parameters["FaradaysConstant"] | ||
| R = Parameters["GasConstant"] | ||
|
|
||
| V0 = Magic["cellModel_V0"] | ||
| C1 = Magic["cellModel_C1"] | ||
| C2 = Magic["cellModel_C2"] | ||
| C3 = Magic["cellModel_C3"] | ||
| C4 = Magic["cellModel_C4"] | ||
|
|
||
| eps = 1e-9 | ||
|
|
||
| soc_shift = self.soc - (0.1 ** 3) | ||
|
|
||
| denom = np.clip(1.0 - soc_shift + C4, eps, None) | ||
| numer = np.clip(C1 * soc_shift + C3, eps, None) | ||
|
|
||
| log_term = np.log(numer / denom) | ||
| return V0 + (C2 * (R * T_K / F) * log_term) + Magic["cellModel_bias"] | ||
|
rchatterjee5 marked this conversation as resolved.
|
||
|
|
||
| def terminal_voltage(self, current): | ||
| #main function | ||
| return (self.ocv() - self.hysteresis - (current * self.resistance)) | ||
|
|
||
| def update_soc(self, current, dt, capacity_Ah): | ||
| #change w time | ||
| change_soc = (current * dt / 3600) / capacity_Ah | ||
| self.soc = np.clip(self.soc - change_soc, 0.0, 1.0) | ||
|
|
||
| class Parallel_Groups: | ||
| def __init__(self, cells): | ||
| self.cells = cells | ||
|
|
||
| def solve_currents(self, pack_current): | ||
| sum_rhs_over_R = 0 ##rhs is ocv - hysteris (right hand side of equation) | ||
| sum_1_over_R = 0 | ||
|
|
||
| for cell in self.cells: | ||
| rhs = cell.ocv() - cell.hysteresis | ||
| sum_rhs_over_R += rhs/cell.resistance | ||
| sum_1_over_R += 1/cell.resistance | ||
|
|
||
| V_group = (sum_rhs_over_R - pack_current)/sum_1_over_R | ||
| currents = [] | ||
| for cell in self.cells: | ||
| rhs = cell.ocv() - cell.hysteresis | ||
|
rchatterjee5 marked this conversation as resolved.
|
||
| current = (rhs - V_group)/cell.resistance | ||
| currents.append(float(current)) | ||
|
|
||
| return currents, V_group | ||
|
|
||
| def step(self, pack_current, dt, capacity_Ah): | ||
| #for each timestep | ||
| currents, V_group = self.solve_currents(pack_current) | ||
| for cell, current in zip(self.cells, currents): | ||
| cell.update_soc(current, dt, capacity_Ah) | ||
| return currents, V_group | ||
|
|
||
| class Module: | ||
| def __init__(self, groups): | ||
| self.groups = groups | ||
|
|
||
| def step(self, pack_current, dt, capacity_Ah): | ||
| total_voltage = 0 | ||
| all_currents = [] | ||
| for group in self.groups: | ||
| currents, V_group = group.step(pack_current, dt, capacity_Ah) | ||
| total_voltage += V_group | ||
| all_currents.append(currents) | ||
| return all_currents, total_voltage | ||
|
rchatterjee5 marked this conversation as resolved.
|
||
|
|
||
| def build_modules(width = 4, height = 2, resistances = None): | ||
| #if no given csv | ||
| if resistances is None: | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear, this is internal cell resistances right? Worth naming the variable more clearly because there are other resistors in the circuit. |
||
| resistances = np.random.normal(0.008, 0.0005, (height, width)) | ||
| #with importing a csv | ||
| else: | ||
| resistances = np.asarray(resistances) | ||
| if resistances.shape != (height, width): | ||
| raise ValueError(f"Expected shape ({height}, {width}), got {resistances.shape}") | ||
| groups = [] | ||
| for h in range(height): | ||
| cells = [] | ||
| for w in range(width): | ||
| soc = np.random.uniform(0.85, 0.95) | ||
| cells.append(Cell(soc=soc, resistance=resistances[h, w])) | ||
| groups.append(Parallel_Groups(cells)) | ||
| return Module(groups) | ||
|
rchatterjee5 marked this conversation as resolved.
|
||
|
|
||
| module = build_modules(width=4, height=2) | ||
| ##sim | ||
|
|
||
| pack_current = 100.0 | ||
| dt = 1.0 | ||
| capacity_Ah = 5.0 | ||
|
|
||
| num_steps = 10 | ||
|
|
||
| for step in range(num_steps): | ||
| all_currents, module_voltage = module.step(pack_current, dt, capacity_Ah) | ||
| print(f"\nStep {step}") | ||
| print(f"Module Voltage: {module_voltage:.2f} V") | ||
|
|
||
| for g, group_currents in enumerate(all_currents): | ||
| print(f" Group {g}: {group_currents}") | ||
| print(f" Group {g} Sum: {np.sum(group_currents):.2f} A") | ||
|
Comment on lines
+113
to
+120
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we spoke about this already but make sure you're logging not just printing the values. Not only is it easier to process afterward but it is critical for your hysteresis calculation. |
||
Uh oh!
There was an error while loading. Please reload this page.