SEI on cracks#2104
Conversation
|
I thought I'd provide more context as to why this is still a draft. If I do the following: parameter_values = pybamm.ParameterValues("Ai2020") I get back a KeyError on line 231 of base_sei.py saying variables["Negative electrode roughness ratio"] is undefined. Presumably this is because this variable comes from a different submodel and was therefore not passed to the variables dictionary, but I have no idea how to fix this! |
This reverts commit 5b321a7.
|
Update: I have now got the SEI on cracks model to work for the Ai2020 parameter set. I'm now trying to add the degradation parameter set I used for my paper but the crack model fails immediately (t=0) for those parameters, even if there is no SEi on the cracks. This happens for either electrode, so the issue must be with one of the parameters common to both. |
|
I don't think this closes #1807 ? |
|
Sorry about the diff coverage. I'm getting an error when I try to test graphite_volume_change_Ai2020.py, so I commented that line out in the test and just dealt with everything else. Project coverage should be increased overall. |
valentinsulzer
left a comment
There was a problem hiding this comment.
Looks great, some minor comments, including places where you are running up against the horrible mess of different parameter names for the same SEI parameter
| T_ref = Parameter("Reference temperature [K]") | ||
| Eac_cr = Parameter( | ||
| "Negative electrode activation energy for cracking rate [J.mol-1]" | ||
| ) | ||
| arrhenius = exp(Eac_cr / constants.R * (1 / T_dim - 1 / T_ref)) |
There was a problem hiding this comment.
Please specify the activation energy and reference temperature here. The data is measured for a specific reference temperature and activation energy, so I don't think it makes sense to define them as separate parameters.
| T_ref = Parameter("Reference temperature [K]") | ||
| Eac_cr = Parameter( | ||
| "Positive electrode activation energy for cracking rate [J.mol-1]" | ||
| ) |
| # Do not set "sei on cracks" submodel for half-cells | ||
| if reaction_loc == "interface": | ||
| if self.options["SEI"] == "none": | ||
| self.submodels["sei"] = pybamm.sei.NoSEI(self.param, self.options) | ||
| elif self.options["SEI"] == "constant": | ||
| self.submodels["sei"] = pybamm.sei.ConstantSEI(self.param, self.options) | ||
| else: | ||
| self.submodels["sei"] = pybamm.sei.SEIGrowth( | ||
| self.param, reaction_loc, self.options, cracks=False | ||
| ) | ||
| # For full cells, "sei on cracks" submodel must be set, even if it is zero | ||
| else: | ||
| self.submodels["sei"] = pybamm.sei.SEIGrowth( | ||
| self.param, reaction_loc, self.options | ||
| ) | ||
| if self.options["SEI"] == "none": | ||
| self.submodels["sei"] = pybamm.sei.NoSEI(self.param, self.options) | ||
| self.submodels["sei on cracks"] = pybamm.sei.NoSEI( | ||
| self.param, self.options, cracks=True | ||
| ) | ||
| elif self.options["SEI"] == "constant": | ||
| self.submodels["sei"] = pybamm.sei.ConstantSEI(self.param, self.options) | ||
| self.submodels["sei on cracks"] = pybamm.sei.NoSEI( | ||
| self.param, self.options, cracks=True | ||
| ) | ||
| else: | ||
| self.submodels["sei"] = pybamm.sei.SEIGrowth( | ||
| self.param, reaction_loc, self.options, cracks=False | ||
| ) | ||
| if self.options["SEI on cracks"] == "true": | ||
| self.submodels["sei on cracks"] = pybamm.sei.SEIGrowth( | ||
| self.param, reaction_loc, self.options, cracks=True | ||
| ) | ||
| else: | ||
| self.submodels["sei on cracks"] = pybamm.sei.NoSEI( | ||
| self.param, self.options, cracks=True | ||
| ) |
There was a problem hiding this comment.
I think this does the same thing in fewer lines
if self.options["SEI"] == "none":
self.submodels["sei"] = pybamm.sei.NoSEI(self.param, self.options)
elif self.options["SEI"] == "constant":
self.submodels["sei"] = pybamm.sei.ConstantSEI(self.param, self.options)
else:
self.submodels["sei"] = pybamm.sei.SEIGrowth(
self.param, reaction_loc, self.options, cracks=False
)
# Do not set "sei on cracks" submodel for half-cells
# For full cells, "sei on cracks" submodel must be set, even if it is zero
if reaction_loc != "interface":
if self.options["SEI"] in ["none", "constant"] or self.options["SEI on cracks"] == "false":
self.submodels["sei on cracks"] = pybamm.sei.NoSEI(
self.param, self.options, cracks=True
)
else:
self.submodels["sei on cracks"] = pybamm.sei.SEIGrowth(
self.param, reaction_loc, self.options, cracks=True
)| if self.options["SEI"] == "ec reaction limited": | ||
| self.initial_conditions = {L_outer: L_inner_0 + L_outer_0} | ||
| if self.reaction == "SEI on cracks": | ||
| self.initial_conditions = {L_outer: (L_inner_0 + L_outer_0) / 10000} |
There was a problem hiding this comment.
why hard-coded to 10000?
There was a problem hiding this comment.
That is what was done in the paper. We had to choose an initial condition that was as close to zero to get the physics right, but didn't cause a division by zero error.
| # All SEI growth mechanisms assumed to have Arrhenius dependence | ||
| Arrhenius = pybamm.exp(param.E_over_RT_sei * (1 - prefactor)) | ||
|
|
||
| j_inner = alpha * j_sei | ||
| j_outer = (1 - alpha) * j_sei | ||
| j_inner = alpha * Arrhenius * j_sei | ||
| j_outer = (1 - alpha) * Arrhenius * j_sei |
There was a problem hiding this comment.
I understand why you've done it this way, but we should reformat the SEI parameters so that the parameter is j_sei(c, T) to be consistent with intercalation kinetics and plating. The SEI parameters are a mess anyway.
There was a problem hiding this comment.
This is a good idea but probably beyond the scope of this PR, which is to allow others to reproduce the results of the O'Kane 2022 paper.
|
|
||
| def graphite_cracking_rate_Ai2020(T_dim): | ||
| """ | ||
| graphite particle cracking rate as a function of temperature [1, 2]. |
There was a problem hiding this comment.
| graphite particle cracking rate as a function of temperature [1, 2]. | |
| Graphite particle cracking rate as a function of temperature [1, 2]. |
| domain="negative electrode", | ||
| auxiliary_domains={"secondary": "current collector"}, | ||
| ) | ||
| else: |
There was a problem hiding this comment.
Does this case include standard SEI only, or a bunch of different cases? If it is standard SEI, would it be better to do an elif and then keep the else to throw an error if the argument is weird?
There was a problem hiding this comment.
What error should I throw?
| @@ -29,6 +29,24 @@ Negative electrode specific heat capacity [J.kg-1.K-1],700,default, | |||
| Negative electrode thermal conductivity [W.m-1.K-1],1.7,default, | |||
There was a problem hiding this comment.
Are all these parameters presented in O'Kane 2022? If so, should we rename this set to O'Kane 2022 rather than Chen 2020 plating? We can still keep the ref to Chen 2020 in pybamm.citations() but I think the new name would make it clearer to the reader which is the main reference.
There was a problem hiding this comment.
I've gone further and deleted the entire Chen2020_plating chemistry. It was only there in the first place because none of the existing chemistries worked with the plating submodel. Now that OKane2022 exists, it's not needed anymore. OKane2020_Li_plating is still there as that is a published set of plating parameters, but none of the pre-defined chemistries use it.
|
|
||
| class NoMechanics(BaseMechanics): | ||
| """ | ||
| Class for swelling only (no cracking) |
valentinsulzer
left a comment
There was a problem hiding this comment.
Looks good to me! Will let @brosaplanella double-check
| where m_cr is another Paris' law constant | ||
| """ | ||
| k_cr = 3.9e-20 | ||
| Eac_cr = Parameter( |
There was a problem hiding this comment.
this should be hard-coded too
There was a problem hiding this comment.
Fixed (currently 0, sorry to disappoint!)
| where m_cr is another Paris' law constant | ||
| """ | ||
| k_cr = 3.9e-20 | ||
| Eac_cr = Parameter( |
There was a problem hiding this comment.
Fixed (currently 0, sorry to disappoint!)
| Negative electrode Paris' law constant b,1.12,, | ||
| Negative electrode Paris' law constant m,2.2,, | ||
| Negative electrode cracking rate,[function]graphite_cracking_rate_Ai2020,Ai2020, | ||
| Negative electrode activation energy for cracking rate [J.mol-1],0,, |
| Positive electrode Paris' law constant b,1.12,, | ||
| Positive electrode Paris' law constant m,2.2,, | ||
| Positive electrode cracking rate,[function]cracking_rate_Ai2020,Ai2020, | ||
| Positive electrode activation energy for cracking rate [J.mol-1],0,, |
|
You just lost to Ferran in the merge race 😢 just fix the changelog conflict and should be good to go |
Description
Adds a new option "SEI on cracks". If set to "true", whichever SEI model is specified by the "SEI" option is run twice; once on the electrode particle surface, and then a second time on the additional surface created by the particle cracking created by the "particle mechanics": "swelling and cracking" option.
Breaking change: "Loss of lithium to SEI on cracks [mol]" is now a summary variable, so a "particle mechanics" submodel must be set, even if it's "none". The examples have been updated to account for this.
Fixes #1695 (in full), #1807 (in part), #2039 (in full)
Type of change
Key checklist:
$ flake8$ python run-tests.py --unit$ cd docsand then$ make clean; make htmlYou can run all three at once, using
$ python run-tests.py --quick.Further checks: