-
Hi all! I am currently investigating some effects of different parameters on cell degradation. Looking at some factors like Loss of Li Inventory, Reduction in discharge capacity etc... However, when running the experiment for a large number of cycles, I start to encounter this issue: "Experiment is infeasible: 'event: Zero negative electrode porosity cut-off' was triggered during 'Charge at 1C until 4.2V'" The foundation of the code is inherited from https://docs.pybamm.org/en/latest/source/examples/notebooks/simulations_and_experiments/rpt-experiment.html. I am similarly discharge and charging cycles. I'm simply playing around with a different parameter set, and modified it to also plot some of the other cell variables. I have attached below:
Funnily enoug, when I set the SEI: to difufusion limited, it does not actually run into this error. It only appears to happen, and almost consistently around cycles 46-49 when the "SEI" parameter is set to "ec reaction limited". Hopefully that is enough information, would really appreciate your help! import pybamm
import matplotlib.pyplot as plt
pybamm.set_logging_level("NOTICE")
# See how it changes when this setting is given: "SEI": "solvent-diffusion limited" or "ec reaction limited"
filename = "EC_reaction_limited"
#filename = "solvent-diffusion limited"
model = pybamm.lithium_ion.SPM({"SEI": "ec reaction limited",
"SEI film resistance": "distributed",
"lithium plating": "irreversible",
"lithium plating porosity change": "true",
"loss of active material": "stress-driven",
"thermal": "lumped",
"SEI porosity change" :"true"})
parameter_values = pybamm.ParameterValues("OKane2022")
parameter_values.update({"SEI kinetic rate constant [m.s-1]": 1e-14})
# Set the solver mode to be used for the simulation - this will update in each execution of Pybamm.solve()
solver_mode = pybamm.CasadiSolver(mode="fast with events")
N = 10
cccv_experiment = pybamm.Experiment(
[
(
"Charge at 1C until 4.2V",
"Hold at 4.2V until C/20",
"Discharge at 1C until 2.8V",
"Rest for 20 minutes",
)
]
* N
)
charge_experiment = pybamm.Experiment(
[
(
"Charge at 1C until 4.2V",
"Hold at 4.2V until C/20",
)
]
)
rpt_experiment = pybamm.Experiment([("Discharge at C/3 until 2.8V",)])
# Performing an initial full experiment cycle
sim = pybamm.Simulation(
model, experiment=cccv_experiment, parameter_values=parameter_values)
cccv_sol = sim.solve(solver=solver_mode)
sim = pybamm.Simulation(
model, experiment=charge_experiment, parameter_values=parameter_values)
charge_sol = sim.solve(starting_solution=cccv_sol, solver=solver_mode)
sim = pybamm.Simulation(
model, experiment=rpt_experiment, parameter_values=parameter_values)
rpt_sol = sim.solve(starting_solution=charge_sol, solver=solver_mode)
M = 4 # Overall expect a total of M * (N + 2) cycles to be performed, with N being the number of cycles in the CCCV process
cccv_sols = []
charge_sols = []
rpt_sols = []
# Some varibles of the cell we want to keep an eye on, and how they change over time during the degradation process
degradation_sols = {"Total lithium lost [mol]": [], "Loss of lithium inventory [%]": [], "Total capacity lost to side reactions [A.h]": [] , "Loss of lithium to negative SEI [mol]": [], "X-averaged negative electrode active material volume fraction": []}
for i in range(M):
if i != 0: # skip the first set of ageing cycles because it's already been done
sim = pybamm.Simulation(
model, experiment=cccv_experiment, parameter_values=parameter_values
)
cccv_sol = sim.solve(starting_solution=rpt_sol, solver=solver_mode)
sim = pybamm.Simulation(
model, experiment=charge_experiment, parameter_values=parameter_values
)
charge_sol = sim.solve(starting_solution=cccv_sol, solver=solver_mode)
sim = pybamm.Simulation(
model, experiment=rpt_experiment, parameter_values=parameter_values
)
rpt_sol = sim.solve(starting_solution=charge_sol, solver=solver_mode)
cccv_sols.append(cccv_sol)
charge_sols.append(charge_sol)
rpt_sols.append(rpt_sol)
# Each _sol object is the Pybam.solve() object, which contains the entries for the cell variables of interest
# pb.dynamic_plot(calibration_sols[-1].cycles[-1], ["Current [A]", "Voltage [V]"])
# pb.plot_summary_variables(calibration_sol)
'''
This section takes the entries from the Pybamm.solve() objects, and obtains the 'Discharge capacity [A.h]' variable. Note the +2 offset is due to the cc_charging and rpt step
The CCCV_cycle graphs will always be lower in the 'Discharge capacity [A.h]' than the RPT_cycle graphs, as the CCCV cycles are shorter in duration and therefore have less capacity loss.
While not strictly transient, the current flow is much larger, with greater resistances faced due to hgiher rate of electron/ ionic propagation.
'''
cccv_cycles = []
cccv_capacities = []
rpt_cycles = []
rpt_capacities = []
for i in range(M):
for j in range(N):
cccv_cycles.append(i * (N + 2) + j + 1)
start_capacity = (
rpt_sol.cycles[i * (N + 2) + j]
.steps[2]["Discharge capacity [A.h]"]
.entries[0]
)
end_capacity = (
rpt_sol.cycles[i * (N + 2) + j]
.steps[2]["Discharge capacity [A.h]"]
.entries[-1]
)
cccv_capacities.append(end_capacity - start_capacity)
# 1. Find Lithium lost at the end of the CCCV cycle
rpt_cycles.append((i + 1) * (N + 2))
start_capacity = rpt_sol.cycles[(i + 1) * (N + 2) - 1][
"Discharge capacity [A.h]"
].entries[0]
end_capacity = rpt_sol.cycles[(i + 1) * (N + 2) - 1][
"Discharge capacity [A.h]"
].entries[-1]
rpt_capacities.append(end_capacity - start_capacity)
# 2. Find Lithium lost at the end of the RPT event
for key in degradation_sols.keys():
degradation_sols[key].append(
rpt_sol.cycles[i * (N + 2) + j].steps[2][key].entries[-1]
)
print("\n Length of variable arrays: \n")
#print(len(rpt_cycles))
#print(len(degradation_sols["Negative total SEI thickness [m]"]))
# Plotting the results of the cycling ageing process
plt.figure(figsize=(15, 10))
# Plot 1:
plt.subplot(3, 2, 1)
plt.scatter(cccv_cycles, cccv_capacities, label="Ageing cycles - CCCV process")
plt.scatter(rpt_cycles, rpt_capacities, label="RPT cycles")
plt.xlabel("Cycle")
plt.ylabel("Cell Capacity [A.h]")
plt.title("Cell Capacity Measurement")
plt.legend()
# Plot 2: Side reaction Capacity Loss
plt.subplot(3, 2, 2)
plt.scatter(rpt_cycles, degradation_sols["Total capacity lost to side reactions [A.h]"], label="Capacity Loss to Side reactions [Ah]")
plt.xlabel("Cycle")
plt.ylabel("Capacity Loss to Side reactions [Ah]")
plt.title("Side Reaction Capacity Loss")
plt.legend()
# Plot 3: Loss of lithium to negative SEI and general Li (moles) lost
plt.subplot(3, 2, 3)
plt.scatter(rpt_cycles, degradation_sols["Loss of lithium to negative SEI [mol]"], label="Loss of lithium to negative SEI [mol]", color = "green")
plt.scatter(rpt_cycles, degradation_sols["Total lithium lost [mol]"], label="Total lithium lost [mol]", color = "red")
plt.xlabel("Cycle")
plt.ylabel("Loss of lithium to negative SEI [mol] and Total lithium lost [mol]")
plt.title("Loss of Lithium")
plt.legend()
# Plot 4: X-averaged negative electrode active material volume fraction
plt.subplot(3, 2, 4)
plt.scatter(rpt_cycles, degradation_sols["X-averaged negative electrode active material volume fraction"], label="X-averaged negative electrode active material volume fraction")
plt.xlabel("Cycle")
plt.ylabel("X-averaged negative electrode active material volume fraction")
plt.title("X-averaged Negative Electrode Active Material Volume Fraction")
plt.legend()
# Adjust layout and show/save plots
plt.tight_layout()
plt.savefig(f"{filename}.png")
# plt.show() |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
This is not really an error but a result of the combination of model and parameter values you have chosen. For those particular mechanisms, parameter values and cycling conditions, the model predicts that the porosity goes to zero. @DrSOKane can you comment on reasonable parameter ranges for the mechanisms used in your paper? |
Beta Was this translation helpful? Give feedback.
I've never used the EC reaction limited model, but from my own research I recommend between 2.5E-22 and 1.25E-20 for
"Outer SEI solvent diffusivity [m2.s-1]"
and between 1E-18 and 2.5E-18 for"Inner SEI lithium interstitial diffusivity [m2.s-1]"
. These are for use with the"solvent-diffusion limited"
and"interstitial-diffusion limited"
mechanisms respectively. I have less experience with the others.More generally, I advise against using the
"irreversible"
plating model. It is simple to use, but not accurate. The"partially reversible"
model captures more physics, and other models have been proposed that include even more physics still! Unfortunately, my attempt to determine the best par…