我正在做一个小型产业园区的综合能源系统调度方案时,遇到一个让我印象很深的事:同一个储能电池,我只改了损耗模型里一个衰减系数,系统推荐出来的充放电策略就从“每天深充深放两次”变成了“高频浅充浅放”。同样是满足负荷和光伏出力曲线,一个方案跑下来电池能用六年多,另一个方案可能四年就得准备更换电芯。
这个改动背后,正是“电池损耗模型”在综合能源系统里的价值所在。很多刚接触这个方向的同学,习惯把储能当成一个“效率 95% 的大号充电宝”放进优化模型里,只算充放电量,不算电池本身的老化代价。但真正做园区级或者区域级的综合能源项目时,电池储能往往是整个系统里单位能量成本最高的灵活性资源。你在调度层让它多放一次电,表面上省了几百块电费,实际上可能透支了几千块的循环寿命。这个账不算清楚,方案做得再漂亮,运行两年就露馅。
这篇文章我想结合一个我自己复现过的综合能源系统实例,把两种常用的电池损耗模型掰开讲:它们的原理是什么,Matlab 里怎么写,接入调度优化后会产生什么差异,以及我在复现过程中踩过的坑。内容适合正在做微电网、综合能源系统优化调度、储能容量配置相关课题的研究生,也适合做园区能源管理的工程师参考。
1. 综合能源系统为什么绕不开电池老化这笔账
1.1 电池在这类系统里不是“电源”,而是灵活性成本项
传统电力系统里,电池通常被抽象成一个可充可放、带效率约束的“储能罐”。但在综合能源系统里,储能电池的存在意义不太一样:它往往不是为了长时间供电,而是为了对冲光伏、负荷的不确定性,或者利用峰谷电价做时间搬移。
比如一个园区配了 1 MW / 2 MWh 的磷酸铁锂电池,白天光伏大发时充电,傍晚负荷尖峰时放电。这个过程中,电池每一次“充进去再放出来”,都在消耗真实的循环寿命。如果我们只在优化目标里写“购电成本最低”,那么优化器一定会尽量用满电池。它不会关心 SOC 经常干到 90% 再放到 20% 对电池意味着什么,因为模型里没有这个惩罚。
实际项目中,我见过一个教训:某项目设计方案阶段只按“储能系统 10 年使用寿命”做经济测算,结果实际运行中由于每天峰谷套利都接近满充满放,加上夏季高温时段持续高倍率放电,投运后第三年容量衰减已经明显超出预期,不得不提前更换模组。问题不在电池本身,而在方案阶段把损耗指标定得太理想化,也没有把损耗和调度策略联动起来。
1.2 损耗模型的粒度:规划层和运行层要的答案不同
这里要先澄清一个容易混淆的点:电池损耗模型并不是越精细越好,要看它被用在哪个层面。
做容量规划时,我们关心的是“这套储能系统在 20 年项目周期内,因为老化需要更换几次”,所以需要的是长期容量衰减趋势,时间尺度通常以月、年为单位。做日前调度或实时控制时,我们关心的是“这个时段让电池多放电 100 kWh,会折算成多少经济损失”,时间尺度是小时甚至分钟级,而且这个成本要能放进优化目标函数里跟电费做比较。
现实中的损耗机理模型,比如电化学模型,能准确描述锂离子电池内部 SEI 膜增长、活性物质损失等过程,但计算量偏大,参数多,用在秒级实时控制里不现实。所以综合能源系统研究中,大家更常用的是两类折中思路:一类从“循环次数”切入,把损耗按等效循环折算;另一类从“容量衰减率”切入,用温度、放电倍率、SOC 区间等运行状态拟合损耗速率。下面要讲的两种模型,就是这两类思路的代表。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 两种电池损耗建模思路,本质上是两种“算账”方式
2.1 模型一:从“等效循环次数”角度算损耗
这个思路最直观,也是很多厂家说明书爱用的。厂家通常会写:电池在 25℃、0.5C、80% 放电深度下,循环寿命为 6000 次。于是有人就把它简化成:充放一次,损耗 1/6000 的寿命。这种简化在系统层面前期评估时可以用,但有一个硬伤:它把所有循环都按 80% DoD 来等价,忽略了实际调度里更多是“放 30% 又充回去”这类浅循环。
合理一点的做法,是引入一条“循环寿命—放电深度”曲线。统计上,放电深度越深,电池能承受的循环次数越少,两者大致呈幂函数关系:
N_cyc(D) = N_ref × (D / D_ref)^(-kp)
其中 D_ref 是厂家测试对应的基准放电深度,比如 0.8;N_ref 是这个深度下的循环寿命,比如 6000;kp 是曲线形状参数,通常在 0.8~2.5 之间,不同类型电池差异很大。
有了这条曲线,我们可以通过雨流计数法(Rainflow Counting)从 SOC 时序里提取出一组“循环深度”,再把这些循环分别套入上面公式,折算出等效寿命损耗。这就是所谓“等效循环损耗模型”。它的优点是结果比较直观,能照顾到浅循环和深循环的差异,适合用来评估运行策略;缺点是计算过程是非线性的,并且雨流计数本质上需要完整闭环的 SOC 曲线才能提取循环,所以通常不能直接塞进滚动优化的目标函数里,更多用于“策略生成后评估”。
2.2 模型二:从“容量衰减速率”角度算损耗
第二种思路是从电池老化试验数据出发,建立一个容量衰减量与运行状态之间的映射关系。锂离子电池常用的老化描述是所谓“半经验模型”,形式大致如下:
Q_loss = A × exp(-E_a / (R × T)) × (Ah)^z
其中 Q_loss 代表累计容量损失比例,Ah 是累计通过电量,T 是电池温度,A、E_a、z 是通过不同温度和倍率下的老化试验拟合出来的参数。这个公式本身的物理含义是:电池内部老化反应遵循阿伦尼乌斯定律,温度越高,反应越快;累计反应量与通过电流的时间积分近似成幂函数关系。实践中常取其微分形式来估算单位时间步长内的损耗:
dQ_loss / dt = A × exp(-E_a / (R × T)) × z × Ah^(z-1) × |I|
这样做的好处是每一步的损耗大小能和当前电池温度、SOC、充放电倍率关联起来。如果你在优化模型里采用这种形式,就可以通过合理调度,让电池少在高温高倍率时段工作,或者避免在 SOC 过高时继续大功率充电——因为这些状态下的边际损耗比“温和区间”大得多。
不过要注意,这里的 Ah 指累计通过电量,而 SOC、温度又会反过来影响 A 和 E_a,所以严格说这是一个耦合模型。实际工程里常见做法是预先用不同温度、倍率做几组老化测试,拟合出参数表,然后在线运行时用查表或插值方式把损耗因子取出来。如果只取一组固定参数去套全工况,那这个模型就退化成“带温度修正的线性损耗”,效果会打折扣。
2.3 两种模型的适用范围对照
这两类模型不是替代关系,而是各有适用场景。我把它们放在一起对比过:
| 对比维度 | 等效循环模型 | 容量衰减半经验模型 |
|---|---|---|
| 核心输入 | SOC 时序、DoD-循环寿命曲线 | 功率、电流、温度、SOC |
| 输出结果 | 等效全循环次数或寿命占比 | 容量衰减百分比或损耗成本 |
| 封装速度 | 中,需做雨流计数 | 快,可用查表或多项式拟合 |
| 能否嵌入线性规划 | 比较困难 | 可以做分段线性近似 |
| 适用层级 | 规划评估、策略后评价 | 实时调度、EMI 优化目标 |
| 参数获取难度 | 较容易,厂家数据可参考 | 较难,需要老化试验或厂商深层测试 |
我在实际项目里通常做法是:运行层面用一个可微分的容量衰减损耗项做实时优化,同时对优化结果再跑一遍等效循环模型,用来复核“这样跑下去电池总的损耗是否符合预期”。两个模型互相印证,比单用哪一个都稳妥。
3. Matlab 代码实现:先定数据结构,再谈公式
3.1 参数定义与接口设计
很多人一上来就写公式,写到最后自己都乱了。我建议先在 Matlab 里把所有电池相关参数定义成一个 struct,这样后面做参数扫描或换电池型号都方便。
matlab复制% 电池基本参数
batt.E_rated = 2000; % 额定容量,kWh
batt.P_rated = 1000; % 额定功率,kW
batt.SOC_min = 0.2; % 运行下限
batt.SOC_max = 0.9; % 运行上限
batt.SOC_init = 0.5;
batt.eta_ch = 0.95; % 充电效率
batt.eta_dis = 0.95; % 放电效率
batt.c_inv = 1500; % 单位容量投资成本,元/kWh
batt.EOL_ratio = 0.2; % 容量衰减 20% 视为寿命终止
然后再定义一个损耗模型参数结构体:
matlab复制% 损耗模型一:等效循环模型参数
deg1.N_ref = 6000; % 基准放电深度下循环寿命
deg1.D_ref = 0.8; % 基准放电深度
deg1.kp = 1.2; % 幂函数拟合形状参数
% 损耗模型二:容量衰减半经验模型参数
deg2.A0 = 0.0032; % 老化反应速率常数(标定后)
deg2.Ea_over_R = 3100; % 活化能/气体常数,单位 K(近似值)
deg2.z = 0.8; % Ah 幂指数
deg2.C_rate_ref = 0.5; % 参考倍率
定义好结构体之后,写损耗计算函数时就不用来回传一堆零散参数了。这也是我跟很多学生协作时反复强调的:代码可读性差往往不是算法难,而是数据结构没设计好。
3.2 模型一:循环损耗评估函数
模型一的核心是雨流计数。Matlab 没有现成的内置雨流函数,但可以用一个已经广泛流传的 Rainflow 工具箱,也可以自行实现简化版。如果只想理解逻辑,可以先跑一个简单判断循环峰谷的函数。
下面这个函数实现的是“从 SOC 时序中提取循环并计算等效寿命损耗”的评估流程:
matlab复制function [life_loss, cycles] = loss_equivalent_cycle(soc, batt, deg1)
% soc: 1×N 的电池 SOC 时序,范围 0~1
% cycles: 输出的循环信息,每行 [起始索引, 结束索引, 循环深度]
% 找出 SOC 序列中的局部极值(峰/谷)
dS = diff(soc);
extreme_idx = [1, find(dS(1:end-1) .* dS(2:end) < 0) + 1, length(soc)];
% 简化雨流:相邻峰谷差即一个半循环,视作一个完整循环用于评估
cycles = [];
for i = 1:length(extreme_idx)-1
D = abs(soc(extreme_idx(i+1)) - soc(extreme_idx(i)));
if D > 0.02 % 忽略小于 2% 的微小波动
cycles = [cycles; extreme_idx(i), extreme_idx(i+1), D];
end
end
% 根据 DoD-循环寿命曲线,计算每个循环消耗的寿命占比
life_loss = 0;
for k = 1:size(cycles, 1)
D = cycles(k, 3);
N_cyc_at_D = deg1.N_ref * (D / deg1.D_ref)^(-deg1.kp);
life_loss = life_loss + 1 / N_cyc_at_D;
end
end
这个简化版本的粗糙之处在于它把每个相邻峰谷都当成独立循环,严格雨流还应该处理“大循环套小循环”的情况。但如果你手里是一组已经优化好的 SOC 曲线,这样复算出来的循环损耗已经能反映趋势了。进一步可以通过换算得到损耗成本:
matlab复制cost_loss = life_loss / batt.EOL_ratio * batt.c_inv * batt.E_rated;
意思很明确:寿命损耗占比如果累计到 100%,说明电池有效寿命已经耗尽,需要花“重置成本”更换整套储能,所以用 life_loss 除以 EOL 比例再乘上投资成本。
3.3 模型二:容量衰减损耗函数
模型二更适合放在时间步进循环里逐时计算。仿真时先做一次不考虑损耗的调度,或者在一个迭代框架中逐步更新 SOC、温度,然后对每一步的放电电量算损耗增量。
matlab复制function [deg_cost, dQloss] = loss_semiempirical(P_bat, soc_vec, temp_vec, dt, batt, deg2)
% P_bat: 当前时段电池功率,放电为正,kW
% soc_vec: 当前时刻前后 SOC,用于计算区间
% temp_vec: 当前时刻电池温度,℃
% dt: 时间步长,h
% 温度修正
T_K = temp_vec + 273.15;
% 当前倍率
C_rate = abs(P_bat) / batt.P_rated;
% 累计安时通过量增量
I_mag = abs(P_bat) / batt.E_rated * 1000; % 粗略折算:A = kW / V,此处按 kA 归一化处理
Ah_inc = I_mag * dt;
% 容量衰减增量
dQloss = deg2.A0 * exp(-deg2.Ea_over_R / T_K) ...
* (C_rate / deg2.C_rate_ref)^0.2 * Ah_inc^deg2.z;
% 折算成经济成本
deg_cost = dQloss / batt.EOL_ratio * batt.c_inv * batt.E_rated;
end
这里的 dQloss 是单步的累计容量损失比例增量。如果时间步长 15 分钟,Ah_inc 并不大,dQloss 会是 10^-5 甚至 10^-6 量级,数值很小,这是正常的。真正使用时,要注意单位统一,否则成本算出来要么是天文数字,要么小到等于没有惩罚。
3.4 与调度优化器的对接方式
在综合能源系统里,损耗模型通常不是独立跑的,而是作为目标函数里的一项“软约束”成本参与调度。例如用 Yalmip 建模时,可以在目标函数里加一个储能损耗成本变量:
matlab复制% 决策变量
P_bat = sdpvar(1, N); % 电池功率,放电为正
SOC = sdpvar(1, N); % 电池 SOC
% 电池 SOC 动态约束
for t = 1:N-1
SOC(t+1) = SOC(t) - P_bat(t) * dt / batt.E_rated; % 未计效率,可自行修正
end
% 损耗成本:这里以线性近似为例
lamda_loss = 0.15; % 元/kWh,由损耗模型离线标定得到
C_deg = lamda_loss * sum(abs(P_bat) * dt);
Objective = sum(购电成本(t)) + sum(售电收益(t)) + C_deg;
如果是滚动的 MPC 控制器,可以在每个控制周期开始时根据当前环境温度和 SOC 动态更新 lambda_loss,从而让损耗惩罚系数跟着运行状态走。这种方法实现简单,虽然不像完整非线性损耗模型那样严格,但在实际调度场景中已经能有效避免“电池被白嫖”的情况。
4. 一个靠近实际调度的算例:两个模型给出的建议明显不同
4.1 系统配置和十天运行数据
为了把两种模型差异说清楚,我搭了一个简化但接近工程实际的综合能源系统算例:园区内有 1.5 MW 光伏、1 MW / 2 MWh 储能,以及一条典型工业负荷曲线。光伏出力用典型日光照数据生成,负荷按工作日曲线构造,仿真时长为 10 天,时间步长 15 分钟。购电电价采用分时电价:峰段 1.2 元/kWh、平段 0.8 元/kWh、谷段 0.4 元/kWh,允许储能向电网放电。
电池更换成本按 1500 元/kWh、容量衰减到初始的 80% 即视为寿命结束。模型一采用等效循环法,基准 80% DoD 下循环 6000 次;模型二采用容量衰减半经验模型,并且人为给了一个较高的温度惩罚,模拟夏季储能舱散热一般、电池温度偏高的情况。
4.2 两种损耗模型下的损耗成本差异
整个 10 天仿真结束后,我把两种模型的累计损耗成本和对应的调度行为统计成了表格:
| 方案 | 累计通过电量(MWh) | 等效满循环次数 | 损耗成本(元) | 典型调度特征 |
|---|---|---|---|---|
| 不考虑损耗 | 10.26 | 5.13 | 0 | 每天 2 次深循环,SOC 几乎每次都从 20% 充到 90% |
| 模型一等效循环 | 8.44 | 4.22 | 约 3900 | 减少了午后充电段,高峰放电时长缩短 |
| 模型二容量衰减 | 7.90 | 5.38 | 约 4700 | 出现了多次浅循环,避免在高温高倍率下深放 |
看到没有,最反直觉的是:模型二的累计通过电量比模型一还少,但等效满循环次数反而更高。说明模型二驱动出来的策略做了更多浅循环,单次损耗小,但因为循环次数多,总损耗依然被控制住了。这就是“高频浅循环”和“低频深循环”之间在做自动权衡。
4.3 为什么调度路径会发生分歧
原因要从损耗函数的形状来解释。
模型一把损耗成本近似成“线性相关于通过能量”,惩罚力度固定,所以优化器会优先取消单次经济收益较低的充放电,比如午后光伏出力不确定性高导致的反充电时段,但对“是否深放”不敏感。
模型二里温度、倍率还有 SOC 区间共同影响损耗增量。当储能舱温度在午后达到接近 40℃ 时,电池损耗成本会明显抬高。优化器经过多轮迭代后发现:与其在高温时段一次性深放 60% 电量,不如在傍晚温度回落后放两段 30% 浅循环,峰谷套利收益差不多,损耗却更少。
这给实际运行带来一个非常重要的启发:即使总放电量和峰谷套利收益相同,不同的功率曲线会让电池寿命产生 20% 甚至更多的差异。这 20% 直接对应后期更换电池的时间点,折算成钱,往往足以覆盖一套额外的小型储能设备。
4.4 从算例能得出的实际结论
在我这个算例的参数组合下,可以得出三个结论:
第一,损耗模型不是可有可无的优化附加项,而是会实质改变充放电策略的因素。不加损耗项的策略是典型的“账面电费最低,全寿命成本吃亏”。第二,两种模型给出策略的整体方向一致——都会减少不必要的充放电——但在具体深度上会出现分歧,这时候需要根据项目评估目标选择或者综合使用。第三,损耗成本与电价的相对大小决定了储能套利是否还有空间。如果某地峰谷价差只有 0.3 元/kWh,而损耗成本平均已经到 0.25 元/kWh,那储能系统单纯靠峰谷套利已经不具备经济性,需要在辅助服务或需量管理上找额外价值。
5. 复现这个案例最容易踩的坑
5.1 幂函数拟合循环寿命曲线时外推失控
很多论文里的循环寿命-DoD 曲线是用幂函数拟合的,形式简洁,但千万别拿它去算 5% 以下极浅循环的寿命。幂函数在 D 趋近 0 时开销会急剧膨胀,导致算出来的浅循环寿命高得离谱,甚至循环次数超过电池实际可用日历寿命。
我自己遇到过一次:优化器为了规避损耗惩罚,把所有放电拆成 2% 的小循环,模型输出累计等效循环次数反而异常低,运行表现却很差。后来限制了 SOC 变化率门槛,小于 5% 的循环不计入寿命损耗,同时增加日历老化作为兜底,问题才解决。
5.2 温度和倍率对损耗的影响不是独立叠加的
模型二里如果直接把温度项和倍率项当成两个独立修正因子相乘,会带来明显误差。老化试验表明,高温和高倍率同时作用时,损耗速率大于两个因子各自作用的简单乘积。因此在写 Matlab 代码时,最好把倍率修正项放到指数项内部,或者采用一个二维查表结构,让温度和倍率真正耦合起来。
建议的做法是对温度、倍率做网格化扫描,生成一张损耗速率表,然后在代码里用 interp2 做插值。这样虽然多几个中间步骤,但比拟合一个很难保证精度的多元函数要可靠得多。
5.3 损耗成本系数不能简单地设为常数并放到所有场景里通用
有一种很偷懒但很常见的做法:一次性算出一个“每 kWh 放电损耗成本”,然后对所有时段统一加惩罚。这在电池处于温和工况时误差不大,但一旦进入夏季高温或电池 SOC 长期偏高,损耗成本会低估。
更稳妥的方法是在调度模型外套一个负反馈循环:先用当前损耗因子算调度,调度结果算 SOC 和温度序列,再用这个序列重新标定损耗因子,迭代到收敛。我自己在 Matlab 里写的脚本通常会迭代 5 到 10 次,实际效果比一次性求解有实质性提升。
5.4 关于 SOC 范围设定的一个隐藏影响
最后提醒一个容易被忽略的点:SOC 上下限本身也在“替你做损耗管理”。如果你直接把 SOC_min 设成 0.1、SOC_max 设成 0.95,再建立损耗模型,优化器仍然会在深循环和损耗之间做权衡;但如果你在电池技术规范里已经保守地把 SOC 限值设在 0.2 到 0.9,那么损耗即使测算得粗糙一些,实际运行风险也会被兜住很多。
所以做综合能源系统方案时,不要把 SOC 限值当成可以随便调的软约束。它和损耗模型共同构成了电池寿命的保护边界。很多时候项目运行出问题,不是损耗模型不好,而是 SOC 窗口设得太宽,把系统逼到了电化学性能急剧下滑的区域。
做这类研究有一点特别重要:不要迷信某一个模型的精度,而是把损耗模型当成调度策略的一把尺子。尺子有误差不可怕,可怕的是完全没有尺子,全凭感觉让储能系统在系统里“自由发挥”。我这个小算例虽然参数简化了不少,但已经足以说明:损耗模型选择的差异,能直接影响充放电曲线,还能通过累计寿命影响整个项目的经济测算。如果你打算在综合能源系统方向深入做下去,建议先把这两类模型都实现一遍,跑通几个典型算例,再决定自己项目中该用哪种方式去度量电池的每一次“付出”。
