先说结论。我写了个开源小工具 pvfade,做老化感知的光储容量配置和调度优化。它盯住一个很具体、但几乎所有光储测算都在回避的问题:电池会老化,而调度策略本身决定了它老化多快。你今天定的充放策略,直接改写 25 年后的可用容量和收益。不把这条反馈链写进模型里,算出来的 NPV 就是名义容量下的幻想数字。
看一组实测数字。上海户用算例,4kW 光伏加 5kWh 电池,25 年期,电价相同,唯一的差别是有没有老化模型。不考虑老化,25 年 NPV 是 +¥5,615,看着能投。考虑老化,25 年 NPV 是 −¥9,925,实际是亏的。忽略老化,高估 NPV ¥15,540。可用容量第 8 年就跌到 80% SOH 的寿命线,而「恒定名牌容量」模型假设它是 100%,永远。
为什么做这个。光伏出力算得准的工具很漂亮,但止于电表,说的是 pvlib。电池电化学算得准的工具也很漂亮,但止于电池端子,说的是 PyBaMM。中间的技术经济性研究,通常是拿一个恒定电池往光伏曲线上一搭,就叫容量配置研究了:固定往返效率、固定可用容量、用到天荒地老。现实是,每一次充放循环都在长 SEI 膜、都在偷锂,可用容量一年比一年少。文献里做光储长期配置的人自己也承认,忽略循环老化会系统性扭曲全生命周期成本。pvfade 就是缺的那块耦合层:把物理老化写进经济循环里。
方法逻辑不复杂,我用中文讲一遍,四步闭环。第一,光伏出力,pvlib 算逐小时交流出力,太阳位置、晴空、倾角换算、电池温度、逆变器,一路算下来。第二,调度仿真,按自发自用最大化策略,逐年跑。第三,老化模型,平方根循环老化加日历老化,对应的是 SEI 生长的物理形式,跟 PyBaMM 老化子模型同款。想较真,还可以用一次短时的 PyBaMM 单颗粒模型运行,直接拟合老化速率。第四,经济与选型,NPV、LCOS、回本期全部按衰减后的能量序列算,容量配置在光伏千瓦数乘电池千瓦时的网格上按 NPV 排序优选。关键点:老化不是后处理修正项。调度策略决定循环深度,循环深度决定老化速率,老化速率决定可用容量,可用容量决定下一年怎么调度,这条链是闭环跑的。
跑起来很简单。pip 从 GitHub 装 pvfade,一行命令。示例脚本 examples/shanghai_household.py 是完整可运行的,上面的 ¥15,540 结论就是这个脚本跑出来的。里面三步:先算上海 6kW 朝南光伏的逐小时出力,再建一支带老化的电池,再跑 25 年寿命仿真,老化反馈全在里面,自己的负荷曲线喂进去就行。想选型就用网格搜索,在光伏和电池容量的组合里按 NPV 排序。
跟同类工具的关系说清楚。pvlib 只管光伏出力,算得准。PyBaMM 只管电池电化学和老化,算得准。常规光储测算出结果快,但老化等于零,NPV 系统性偏高。pvfade 不替代它们,它做的是出力到调度到老化到经济的闭环。
有几句诚实的话说在前面。第一,气象用的是晴空辐照乘晴空指数缩放,不是实测 TMY,较真时请换自己的气象序列,支持直接喂自己的光伏出力序列。第二,电池不建模更换,寿命仿真到 EOL 就停,默认 80% SOH;日历老化是 25°C 单一系数,温度和 SOC 相关的老化是后续工作。第三,光伏组件自身衰减 v0.1 还没建模。第四,调度目前是规则式自发自用,PyPSA 的 LP/MILP 调度优化和分时电价套利在 v0.2。二期 roadmap 接 tespy 的热泵和 pandapower 的配网交互。这些是已知局限,不是暗坑。
代码、测试、协议都在 GitHub 上。30 个测试全过,Python 3.11+,BSD-3-Clause 协议。链接:https://github.com/chenyi6758-source/pvfade。
如果你也在做光储测算,欢迎拿自己的负荷曲线和电价跑一遍 examples/shanghai_household.py,看看你的项目里「忽略老化」到底藏了多少水分。issue 和 PR 都欢迎。
Cyrus