PyBaMM 的容量衰减到底在量什么:80% capacity、Capacity [A.h] 与 Loss of capacity 实测
PyBaMM 的容量衰减到底在量什么:80% capacity、Capacity [A.h] 与 Loss of capacity 实测
站内搜索
直接问 AI

PyBaMM 的容量衰减到底在量什么:80% capacity、Capacity [A.h] 与 Loss of capacity 实测

关于 PyBaMM 退化仿真,人们问的大多数问题最后都归结到同一个词上。为什么衰减曲线的起点和标称容量毫无关系?为什么 termination="80% capacity" 从不触发,或者触发得晚?为什么那几个”loss of capacity to SEI / plating”变量加起来不等于电池损失的容量?为什么容量会上升?每一个问题的答案都是:PyBaMM 里有好几样不同的东西都叫容量,而退化研究会不知不觉地把它们混在一起。本文用 PyBaMM 26.5.0 逐一实测。除非另有说明,模型都是 DFN,参数集为 OKane2022(LG M50,5 A·h),温度 25 °C。

PyBaMM 电池建模系列 · 静默错误实测(第 4 / 7 篇):上一篇 PyBaMM 热模型实测:产热为零、缺失的熵热与从 25 °C 开始的低温仿真 · 下一篇 PyBaMM SEI 与析锂实测:按时间老化的 SEI、占位速率常数、温度与孔隙堵塞 · 专题页:数据管线 4 篇 + 静默错误实测 7 篇 · RSS 订阅。

一、一颗新电池里的几种容量

同一颗电池,不打开任何退化机制:

量 25 °C 0 °C
"Nominal cell capacity [A.h]" 5.0 A·h:只决定”1C”是多少,别无他用
汇总变量 "Capacity [A.h]" 5.110 A·h 5.110 A·h
C/20 充电并恒压至 C/100 之后的 C/20 放电 5.088 A·h(−0.4%) 5.046 A·h(−1.3%)
C/3 充电并恒压至 C/20 之后的 1C 放电 4.884 A·h(−4.4%) 4.469 A·h(−12.5%)

汇总变量 "Capacity [A.h]" 是一个电极健康状态(eSOH)量:在零电流、参考温度下,参数集开路电压上下限(这里是 2.5 V 和 4.2 V)之间的电量,由电极容量和颗粒中的锂算出。所以它在 0 °C 下读数是 5.110 A·h,而电池在该温度下以 1C 实际放出的是 4.469 A·h。还有一个候选,变量 "Discharge capacity [A.h]",是从 t = 0 起对电流的累计积分——充电时它会再往回走,所以在循环仿真里,它的终值根本不是容量。

这些都没有错。它们回答的是不同的问题,而一条衰减曲线只有在每个点都回答同一个问题时才有意义。

二、termination="80% capacity" 实际比较的是什么

Experiment 的文档字符串只写了”e.g. 80% capacity”。代码(simulation.py 第 1097–1129 行)做的是:

  • 在每个完整循环之后,读取汇总变量 "Capacity [A.h]"——也就是上面那个 eSOH 值,在该循环的最后状态上求值。
  • 拿它和同一个量在第 1 个循环结束时(或 starting_solution 的第一个循环结束时)的值的 80% 比较。不是标称容量,不是全新状态,也不是某次放电。
  • 进度和最终的停止都以 NOTICE 级别写入日志。PyBaMM 的默认日志级别是 WARNING,所以默认情况下你什么都看不到。

我用一次原生运行核对过这一点(每个 SEI 分子含两个锂,SEI 溶剂扩散系数 ×3000,孔隙堵塞关闭):PyBaMM 正好停在离线规则预测的那个循环(第 143 个循环,eSOH 吻合到 1.2 × 10⁻⁶ A·h 以内)。WARNING 及以上级别没有任何记录;停止只以一行 NOTICE 出现:“Stopping experiment since capacity (4.013 Ah) is below stopping capacity (4.014 Ah).”

所以 "80% capacity" 的意思是:由每个循环最后状态算出的、参考温度下的零电流容量,降到它自己在第 1 个循环结束时数值的 80% 时停止。而在充放电测试仪上,寿命终点通常指电池实际放出容量的 80%。两者相差多远,第三节来测。

三、两种定义何时分道扬镳

eSOH 看得见锂库存和电极容量,看不见电阻、电解液输运,也看不见电池是否还能接受充电。所以两者差多少,取决于是什么在驱动衰减。本节中的”实测”指协议自身在 C/3 恒流恒压充电之后的 1C 放电,相对第 2 个循环计算;慢速的参考测试会离 eSOH 近得多,所以这里给出的是 eSOH 与测试中 1C 容量之间的差距。所有行都是 DFN,打开了 OKane2022 的部分可逆析锂,也打开了孔隙堵塞("SEI porosity change": "true");我们放大过的参数写在第一列里:

衰减由什么驱动 实测 1C 容量降到 80% PyBaMM 的”80% capacity”停止 PyBaMM 停止时的 1C 容量 SEI 占孔隙填满量的比例
SEI,孔隙容纳量提高到 4 倍(见补充说明),SEI 溶剂扩散系数 ×3000 第 68 个循环 第 77 个循环(+13%) 78.6% 47%
同上,SEI 溶剂扩散系数 ×1000 第 183 个循环 第 211 个循环(+15%) 78.5% 46%
正极活性材料损失,电流驱动,1 × 10⁻⁸ (A/m²)⁻¹ s⁻¹(我们自选的值) 第 62 个循环 第 82 个循环(+32%) 69.7% 1%
同上,取 5 × 10⁻⁹ (A/m²)⁻¹ s⁻¹ 第 122 个循环 第 164 个循环(+34%) 69.4% 2%
SEI,采用 OKane2022 自带的孔隙容纳量,SEI 溶剂扩散系数 ×1000 在第 143 个循环骤降(87.9% → 68.5%)¹ 骤降时未触发(eSOH 91.1%);不可能有效触发(见补充说明) — 80%
0 °C 析锂,1C 充电,死锂生成 ×10 在第 144 个循环骤降(87% → 54%)² 未触发(eSOH 89.3%) — 1%

¹ x_n = 80;默认网格(x_n = 20)下骤降出现在第 145 个循环(87.9% → 65.7%)。² x_n = 80,或向隔膜方向加密的网格。x_n = 40 时骤降出现在第 151 个循环,默认的 x_n = 20 则完全错过这次骤降,只是逐渐衰减,直到第 166 个循环电解液浓度变为负值。另外,OKane2022 的析锂动力学也不带任何温度依赖(见姊妹篇)。

可以分成三种情形。衰减来自锂损失时,两次运行中 PyBaMM 停下时 1C 容量都在 78.5% 左右——比实测的 80% 多走了约 1.5 个百分点;按循环数算,在这样的加速程度下晚了 13–15%,未加速时的滞后我们没有测。衰减来自正极活性材料损失时,停止晚了大约三分之一的寿命,此时电池在 69.5% 左右。衰减来自充电接受能力的丧失时——隔膜附近的孔隙被 SEI 和析出的锂堵住,恒压步骤提前达到截止条件——eSOH 容量几乎不动,所以在实际放出容量骤降时,这个判据还没有触发。

还有两个因素会拉大差距。eSOH 的基准(第一行中第 1 个循环结束时为 4.99 A·h)比 1C 的基准(第 2 个循环时为 4.75 A·h)大 5%,所以同样的 A·h 损失,占它的百分比更小。另外,默认的 "SEI film resistance": "distributed" 会吃掉一部分 1C 容量,而 eSOH 不管这部分。在每个 SEI 分子两个锂、SEI 溶剂扩散系数 ×3000、孔隙堵塞关闭的运行中——那里的 SEI 占据了 86–93% 的孔隙,而模型此时并不计入孔隙被占据带来的输运损失——把膜电阻改成 "none",滞后从 +18%(121 对 143 个循环)缩小到 +7%(136 对 145),所以在那种设置下,滞后的大部分来自膜电阻。

补充说明:为什么 OKane2022 的 SEI 单靠自己到不了 80%。按 OKane2022 的 SEI 几何参数(比表面积 3.84 × 10⁵ m⁻¹,孔隙率 0.25,SEI 摩尔体积 9.585 × 10⁻⁵ m³/mol,每个 SEI 分子一个锂——参数文件自己把这个值标注为”not physical but true to paper”),SEI 长到 651 nm 就会填满负极的初始孔隙。这相当于 0.612 A·h 的锂,是颗粒中锂的 8.04%。而 eSOH 容量要损失 1.07 A·h 的锂之后才会降到 80%。所以在自带的化学计量比下,任何几何上可能的、只有 SEI 的 OKane2022 运行都触发不了停止。每个 SEI 分子两个锂时,孔隙能容纳足够的量(1.22 A·h),但在我们的运行里,电解液先耗尽了,在第 115 个循环。

当 "SEI porosity change" 取默认值 "false" 时,模型根本不跟踪膜的体积,没有任何东西阻止 SEI 超出孔隙体积,于是停止条件最终确实会触发。在我们的一次运行中(SEI 溶剂扩散系数 ×3000,部分可逆析锂,默认膜电阻),它在第 267 个循环触发,而实测是第 194 个,看起来像是 38% 的滞后。这不能算一个结果:实测容量跌破 80% 时,SEI 所含的锂已经是孔隙填满量的 1.57 倍,停止时是 1.83 倍。这就是为什么表中前两行改为提高孔隙容纳量(每个 SEI 分子两个锂、摩尔体积减半,两者都已写明)。

无效状态会静默通过

上面 SEI + 析锂那个例子,在 PyBaMM 默认网格上跑(拐点在第 145 个循环)并一直延续到 300 个循环,从第 163 个循环起,每次充电结束时电解液浓度的最小值都是负的(到第 300 个循环为 −0.57 mol/m³)。没有警告,也没有报错;运行正常结束并交回一条衰减曲线,而第 162 个循环之后的每个数字,包括 eSOH,描述的都是任何电池都不可能处于的状态。第八节的检查会查这个。

四、读取时刻:汇总变量描述的是每个循环的结束时刻

每个汇总变量,包括 eSOH,都取自每个循环的最后状态(summary_variable.py 第 164–196 行)。如果你的循环元组以充电结尾,你读到的就是一颗处于充电态的电池。打开析锂时,充电态的电池里含有可逆析出的锂,它们会在下一次放电时溶出回去——而 PyBaMM 把它们算作损失。

下面是同一个 20 循环的实验(DFN,部分可逆析锂,孔隙堵塞关闭,30 分钟静置)写了两遍:一遍每个循环在充电后结束,一遍在放电后结束。物理过程完全相同,变的只是元组里的顺序:

20 个循环后 25 °C,C/3 充电:结束于充电态 结束于放电态 −5 °C,1C 充电:结束于充电态 结束于放电态
汇总的析锂”损失” 0.0107 A·h 0.0019 A·h 0.0285 A·h 0.0174 A·h
汇总的 LLI(绝对值,含 SEI) 0.184% 0.069% 0.383% 0.237%
汇总”Capacity”相对无析锂运行的缺口 0.0100 A·h 0.0018 A·h 0.0267 A·h 0.0163 A·h
实测 1C 容量相对无析锂运行的缺口 0.0032 A·h 0.0032 A·h 0.0177 A·h 0.0177 A·h

在 25 °C 下,只调换元组顺序,报告的析锂损失和报告的容量缺口都变化约 5.5 倍,而实测 1C 缺口始终是 0.0032 A·h。在一次 50 循环、5 分钟静置、打开孔隙堵塞的运行中,结束于充电态的循环在 25 °C 下报告有 0.0178 A·h 损失于析锂,其中最后一次放电之后仍然存在的死锂只有 0.0035 A·h;实测缺口为 0.0047 A·h。5 分钟静置时,充电态的读数还会压低 eSOH 本身,幅度从 0.014 A·h(0.27%,25 °C)到 0.029 A·h(0.58%,0 °C、1C 充电),在我们检查的 8 个循环里保持不变;更长的静置让一部分析出的锂先溶出,这个偏差随之缩小(表中 30 分钟静置、25 °C 时约 0.008 A·h)。

修法:把放电放在每个循环元组的最后。在放电步骤结束时从 sol.cycles[i].steps[k] 读取 LLI 和析锂变量,对这些变量同样有效;但 eSOH "Capacity [A.h]" 和 "80% capacity" 停止条件只能靠调整顺序来修正。

五、”Loss of capacity to X”是锂,不是容量

一位 PyBaMM 维护者在 discussion #3502 里说得很直白:这些名字里的”capacity”指的是可循环锂。由此有四个后果。

析锂”损失”是一张快照

"Loss of capacity to negative lithium plating [A.h]" 是当前以金属形式存在的锂,包括可溶出的和死锂两部分(base_plating.py 第 119–126 行)。在 −5 °C、2C 恒流恒压充电、可逆析锂(孔隙堵塞关闭)的条件下,它的峰值为 0.206 A·h,恒压步骤结束时为 0.058 A·h,静置 10 小时后为 0.005 A·h,C/3 放电后为 0。部分可逆析锂会留下 0.0016 A·h。你报告的是哪个数字,只取决于你什么时候看。

LLI [%] 的分母不一样

"Loss of lithium inventory [%]" 除以的是两个电极颗粒中的全部锂——OKane2022 是 7.611 A·h——而不是 5 A·h 的容量。损失的锂如何转化为损失的容量,还取决于电极配比,而且各参数集不同:

参数集 每 1% LLI 对应的 eSOH 容量变化(前 1%)
Ai2020 −1.70%
Chen2020 −1.45%
Ecker2015 −1.33%
OKane2022 −1.28%(10% LLI 时累计 −14.2%,20% 时累计 −28.4%)
Prada2013、Mohtat2020 −1.03%、−1.02%
Ramadass2004³、NCA_Kim2011 −0.09%、−0.02%
ORegan2022 +0.03%
Marquis2019(PyBaMM 默认) +1.40%

³ Ramadass2004 的正极开路电位拟合式有一个极点,所以它的 eSOH 问题有三个根;表中的值取中间那个。对 OKane2022,仿真得到的 C/20 和 C/3 容量与 eSOH 换算结果相差在 2% 以内。最后一行是第六节要讲的。

损失的活性材料里的锂单独记账

打开活性材料损失时,被移除颗粒里的锂会记到一个单独的变量 "Loss of lithium due to loss of active material in negative/positive electrode [mol]" 里。"Loss of lithium inventory [%]" 把它算进去;"Total lithium lost to side reactions [mol]" 不算。这个记录被困锂的变量本身不在默认的汇总变量里。在完整的 OKane2022 退化模型中跑 200 个循环(放电后读取),它占 LLI 的 14%;把 LAM 速率调到自带值的十倍时占 63%。这是各机理的损失加起来不等于总量的原因之一。(另外:"loss of active material": "reaction-driven" 在自带参数下不起任何作用,因为在定义了它的全部 10 个参数集里,包括 OKane2022,它的速率系数都是 0.0。)

早先那个活性材料损失时 SEI 中的锂会”消失”的问题(issue #3006)从 v25.10 起已经修复(PR #4869)。在 19 次 DFN 和 SPM 运行中,负极 LAM 最高达 7.7%(反应驱动 LAM,测试系数被放大),SEI 账目从未减少,并与独立积分 SEI 电流得到的结果相符:DFN 中相差在 8.5 × 10⁻¹² mol 以内,SPM 中在 7.6 × 10⁻¹⁰ mol 以内,而总量约为 5 × 10⁻⁴ mol。

补充说明:从 26.4 起的一个 LLI 错误。从 v26.4.0(PR #5448)开始,PyBaMM 的 x 平均化简器把颗粒变量当作在整个电极上均匀分布,于是 DFN 把颗粒中的锂算成了平均值的乘积。对一个开始时均匀、之后也保持均匀的电极,这无害;打开 LAM 后,活性材料体积分数变得不均匀,账目误差虽小但不为零(按 OKane2022 的 LAM 速率为 1.4 × 10⁻⁶ mol)。对于活性材料体积分数从一开始就沿厚度方向变化的 DFN(我们用的是 0.60 到 0.75),它会在所有退化机制都关闭的情况下报告最高 0.256% 的 LLI,而颗粒中实际的锂逐个网格单元求和,守恒到 3.5 × 10⁻¹⁴ mol 以内。SPM 不受影响。我们已于 2026 年 9 月 27 日向上游提交 issue #5810。它已由 PR #5813 在 main 分支上修复(2026 年 9 月 30 日合并,改的正是 averages.py 中的 _is_independent_of 和 _try_separable)。合并晚于 9 月 28 日发布的 26.9.0.0,所以修复会随下一个版本发布;26.4 到 26.9 的所有版本都受影响。

六、容量为什么会上升:PyBaMM 自己的默认参数集

“打开 SEI 之后容量反而增加”是个反复出现的问题——例如 discussion #2075,其中汇总的”Capacity”上升,而实测容量在下降(该帖没有说明参数集,所以我们假定是 PyBaMM 的默认参数集)。用这个默认参数集——Marquis2019,也就是 SPM、SPMe 和 DFN 的默认值——容量上升正是模型在这组参数下的预测结果;一位维护者曾把某些参数集里多出来的锂称为”参数里的一个 bug”(discussion #2472)。Marquis2019 颗粒中的锂(2.079 A·h)比它的正极能接纳的(1.946 A·h)多 6.8%,所以每次放电都在正极嵌满时结束,而石墨仍处于 18% 的嵌锂状态。损失锂首先会把窗口移到一个更好的位置:

  • eSOH 容量在最初损失 1% 的锂时上升 1.40%,在 LLI 为 9.5% 时达到峰值 +11.9%,此后才开始下降。
  • 实测容量也会上升,用的是自带参数、没有任何加速:用 "SEI": "ec reaction limited" 时,SPM 中 1C 放电量到第 27 个循环从 0.8613 升到 0.9293 A·h(+7.9%);打开孔隙堵塞的 DFN 中,到第 26 个循环为 +7.5%(x_n = 20、40、80 下结果相同,此时 SEI 占据孔隙的 38%)。C/20 放电量上升 8.3%,所以这是电极配比造成的,而不是倍率效应。
  • 换成较温和的 "reaction limited" SEI,实测容量在测试的全部 200 个 SPM 循环里持续上升(+0.37%)。

第五节那张表背后的规律:每损失一个单位的锂,eSOH 容量变化 (f₀ − f₁₀₀),其中 f 是在 0% 和 100% 荷电状态下,正极在两极开路电位斜率之和中所占的份额。Marquis2019 的 f₀ = 0.98、f₁₀₀ = 0.47,所以每损失 1 A·h 锂,容量增加约 0.51 A·h,直到石墨到达它自己的拐点为止;OKane2022 的 f₀ = 0.02、f₁₀₀ = 0.95,于是容量下降。光有多余的锂还不够:NCA_Kim2011 的锂比正极能容纳的多 5%,但它的容量从不上升——在 LLI 的前 1–3% 里保持平坦,然后下降。

同一套机制里还有一个陷阱。PyBaMM 的 eSOH 求解对化学计量比不设边界,并且把上一次的解当作初始猜测。对 Ai2020,它可能落到第二个非物理的根上:石墨化学计量比为 1.0002,是靠外推正极开路电位曲线得到的。一个从缺锂 10% 起步的仿真,于是连续五个循环报告恒定的 2.917 A·h,而实际放出的是 1.98 A·h;唯一的信号是一条外推警告。

七、从老化电池起步,以及拆分长时间运行

调大初始 SEI 厚度并不会让电池老化

论坛上有个回答建议通过调大 "Initial SEI thickness [m]" 来模拟一颗老化电池。在 26.5 里,这会改变电阻和后续 SEI 的生长速率,但不会移除任何锂,也不会占用任何孔隙体积,因为按设计,SEI 锂账目和孔隙率账目只统计超出初始厚度的那部分生长(base_sei.py 第 112–118 行;reaction_driven_porosity.py 第 67–72 行)。从 5 nm 调到 200 nm,10 秒直流电阻从 39.4 升到 51.1 mΩ,后续 SEI 生长慢了约 28 倍,但 C/10 容量只从 5.0893 变到 5.0883 A·h。在 PyBaMM 里真正老化到 200 nm 的电池(存储 87,900 h,SEI 达到孔隙填满量的 30%)损失了 0.183 A·h;模拟出来的电池把 C/10 容量高估了 3.5%。

真正能复现老化电池的——C/10 和 1C 容量以及之后 20 个循环的衰减相差在 10⁻⁵ A·h 以内,10 秒电阻相差在 0.01 mΩ 以内——是同时设置四样东西:老化后的 SEI 厚度;按损失的锂调低 "Initial concentration in negative electrode [mol.m-3]",再用 solve(initial_soc=1) 求解;老化后的负极孔隙率;以及老化后的电解液浓度。孔隙堵塞关闭时,前两项就够了。使用 OKane2022 的析锂时,还要沿用老化后的 "Initial plated lithium concentration [mol.m-3]"(PyBaMM 在副反应总量里把它记为已经损失),并把 "Dead lithium decay constant [s-1]" 乘以 (5 nm / 老化后厚度),因为死锂速率写成了 γ₀·L₀/L。不做这个缩放,”老化”电池在之后 20 个循环里衰减了 2.88 mAh,而真正老化的那颗只有 0.16 mAh。

拆分长时间运行

用 sim.solve(starting_solution=...) 或 model.set_initial_conditions_from(...) 交接状态是安全的:带 SEI 和析锂的 200 个 DFN 循环(x_n = 10,1C 恒流恒压充电)分成四段跑,与一次连续运行相比,每个循环相差不超过 3.3 × 10⁻⁷ A·h。通过参数交接——像 discussion #4786 里那样,更新初始 SEI 厚度再从 initial_soc 重新开始——会静默重置锂库存、析出的锂和死锂、孔隙率以及裂纹上的 SEI。在那套网格上,200 个循环的实测衰减只有连续运行的三分之一左右(8.9 对 24.2 mAh);在默认网格上跑 40 个循环,只有四分之一(1.75 对 6.88 mAh)。用户会逐段累加的那些损失,在 200 个循环里把 LLI 高估了 45%,把析锂高估了 80%。

八、每次退化仿真之后跑一遍的检查

两个函数:一个返回充放电测试仪会测到的容量,另一个标出上面那些能跑完而不报错的陷阱。

import numpy as np
import pybamm


def discharge_capacity(sol):
    """Ah delivered by the discharge steps of each saved cycle (None for unsaved)."""
    out = []
    for cycle in sol.cycles:
        if cycle is None:
            out.append(None)
            continue
        q = 0.0
        for step in cycle.steps:
            dq = step["Discharge capacity [A.h]"].entries
            if dq[-1] > dq[0]:
                q += dq[-1] - dq[0]
        out.append(float(q))
    return out


def fade_audit(sim):
    """Warnings for a solved degradation run whose capacity numbers can mislead."""
    opts, pv, sol = sim.model.options, sim.parameter_values, sim.solution
    out = []

    moving = [s for s in sol.cycles[-1].steps
              if abs(s["Current [A]"].entries).max() > 1e-9]
    dq = moving[-1]["Discharge capacity [A.h]"].entries
    if dq[-1] < dq[0]:
        out.append("cycles end after a charge: summary variables (Capacity, LLI, "
                   "plating) are read in the charged state")

    exp = getattr(sim, "experiment", None)
    if exp is not None and "capacity" in (exp.termination or {}):
        out.append("'% capacity' termination compares the zero-current eSOH "
                   "'Capacity [A.h]', not a measured discharge")

    c_e = sol["Electrolyte concentration [mol.m-3]"].entries
    if c_e.min() < 0:
        out.append(f"electrolyte concentration went negative ({c_e.min():.2f} mol/m3): "
                   "results after that point describe no real cell")

    sei = opts["SEI"][0] if isinstance(opts["SEI"], tuple) else opts["SEI"]
    clogging = "true" in (opts["SEI porosity change"], opts["lithium plating porosity change"])
    if sei not in ("none", "constant") and not clogging:
        v_n = (pv["Negative electrode thickness [m]"] * pv["Electrode height [m]"]
               * pv["Electrode width [m]"])
        pore_mol = (pv["Negative electrode porosity"] * v_n
                    * pv["Ratio of lithium moles to SEI moles"]
                    / pv["SEI partial molar volume [m3.mol-1]"])
        sei_mol = sol["Loss of lithium to negative SEI [mol]"].entries.max()
        if sei_mol > 0.5 * pore_mol:
            out.append(f"SEI holds {sei_mol / pore_mol:.0%} of the lithium that would fill "
                       "the negative pores, and pore clogging is off")
    return out

在四次 OKane2022 运行上的输出:

T1  DFN, SEI + plating, 10 cycles ending on charge, termination="80% capacity"
    discharge_capacity: 4.9547, 4.882, 4.8817 ... 4.88
    cycles end after a charge: summary variables (Capacity, LLI, plating) are read in the charged state
    '% capacity' termination compares the zero-current eSOH 'Capacity [A.h]', not a measured discharge
T2  same model with pore clogging on, cycles ending on discharge
    discharge_capacity: 4.882, 4.8817, 4.8815 ... 4.8797
    (no warnings)
T3  SPM, "ec reaction limited" SEI, 60 cycles, pore clogging off
    discharge_capacity: 4.9305, 4.7684, 4.708 ... 3.7698
    cycles end after a charge: summary variables (Capacity, LLI, plating) are read in the charged state
    SEI holds 174% of the lithium that would fill the negative pores, and pore clogging is off
T4  DFN, SEI solvent diffusivity x1000 + plating + pore clogging, 170 cycles
    discharge_capacity: 4.9379, 4.8389, 4.8217 ... 2.1018
    cycles end after a charge: summary variables (Capacity, LLI, plating) are read in the charged state
    electrolyte concentration went negative (-0.01 mol/m3): results after that point describe no real cell

实测衰减要以第 2 个循环而不是第 1 个循环为基准:第 1 个循环从 initial_soc 对应的平衡态出发,而不是在协议自己的充电之后开始(T1 中为 4.955 对 4.882 A·h)。孔隙检查只覆盖颗粒表面的 SEI;裂纹上的 SEI 和析出的锂同样会占用孔隙体积。这个检查告诉不了你的是,衰减本身是不是对的——自带参数集里的 SEI 速率常数是通用示例值,这是姊妹篇的话题。

九、测量方法

  • PyBaMM 26.5.0,Python 3.13,Apple M3,IDAKLUSolver。除非另有说明,模型为带 OKane2022 的 DFN;除非另有说明,温度为 25 °C 等温;每个循环为 1C 放电至 2.5 V,C/3 充电至 4.2 V 再恒压至 C/20。
  • “实测容量”是每个循环放电步骤按步积分得到的 A·h,相对第 2 个循环计算。
  • 凡是加速过的运行,都写明了被放大的参数。每个 SEI 结果都对照孔隙填满量检查过;超出孔隙填满的结果只作为标注过的反例出现(第三节的补充说明和第八节的 T3)。
  • 大多数主要数字都在 x_n = 20、40、80 和 rtol 10⁻⁶ 下核对过,变化最多零点几个百分点或一个循环。例外都在出现处写明了:SEI + 析锂的拐点(默认网格上为第 145 个循环,更细的网格上为第 142–143 个循环)、0 °C 析锂骤降(默认网格会错过),以及分段运行的对比(200 个循环用 x_n = 10)。
  • 这项工作分两轮进行:先做一轮测量,再按四条固定标准(孔隙填满量、读取时刻、求解器容差、网格)做一轮对抗式复核。第一轮的若干数字没能通过复核,都没有写进本文,只有补充说明里那一处撤回除外。

References

相关阅读:PyBaMM SEI 与析锂实测——衰减到底由什么驱动;PyBaMM Experiment 常见陷阱——不报错却提前结束的实验;PyBaMM 18 个内置参数集实测——”1C”在每个参数集里各意味着什么。

配套资源

下载配套脚本

电池建模与 AI / CODE

fade_audit.py:容量读数审计

检查已求解的退化仿真:循环停在充电态、"% capacity" 终止比较的是 eSOH 容量、电解液浓度变负、孔隙堵塞关闭时 SEI 超过填满负极孔隙所需量的一半。

发表回复

向下探索