双碳目标下,储能项目投标和调度方案评审里最常被问到的一个问题是:你的模型里损耗是怎么算的?碳价是固定值还是阶梯的?需求响应到底进没进优化?这三个问题问完,基本就能判断一个低碳调度模型是“做实了”还是“做样子”。我在实际项目中把这三个模块重新捋了一遍,并写了一套改进模型——基于分段损耗与需求侧响应的多源协同阶梯碳价储能优化模型,这篇文章把建模思路、约束细节和代码落地中的坑完整记录下来。模型形式是混合整数线性规划(MILP),适合有优化调度基础、正在做储能配置或低碳经济调度的同行参考,我会尽量把每个“为什么这样建模”的逻辑也讲清楚。
1. 分段损耗建模:为什么固定损耗率根本不够用
很多经典经济调度模型里,网损就是一个统一的系数,比如固定取负荷的5%:
$$P_{loss} = 0.05 \times P_{load}$$
在只有火电、负荷波动平缓的时代,这个近似勉强能用。但一旦加入储能,情况立刻就变了:储能充电时,线路功率流向和负荷高峰时相反,整个网络的有功潮流重新分布;如果还用“负荷的5%”来近似网损,就会在储能大量充电的时段低估网损,在储能高倍率放电时段严重高估网损。最后做出来的调度方案可能连基本功率平衡都验证不过去,更不用说后续的碳排放核算了。
我采用的分段损耗思路,本质上是用分段线性函数逼近真实的损耗曲线。对系统中某条关键支路,把有功功率 $P$ 划成 $K$ 个区间,每个区间用一个斜率 $k_i$ 和截距 $b_i$ 来近似损耗 $L(P)$:
- 区间1:$P \in [P_0, P_1]$,$L(P) = k_1 P + b_1$
- 区间2:$P \in [P_1, P_2]$,$L(P) = k_2 P + b_2$
- 以此类推,直到区间K。
为了保证求解器能在线性框架下处理,每个区间内的 $P$ 用辅助变量 $P_i$ 表示,且每个 $P_i$ 有上下界;同时引入0-1变量 $z_i$ 表示当前工况落在哪个区间。约束写成:
$$\sum_{i=1}^{K} z_i = 1$$
$$z_i P_{i,\min} \le P_i \le z_i P_{i,\max}$$
$$\sum_{i=1}^{K} P_i = P$$
$$L(P) = \sum_{i=1}^{K} (k_i P_i + b_i z_i)$$
这套表达在MILP里非常标准,也很好求解。关键的操作经验在折点选取上。我一开始图省事,把支路功率范围等间隔切成8段,结果求解时间翻了一倍,精度提升却不明显。后来改成:先用直流潮流算几个典型场景,把功率分布统计出来,在功率高发区间多切几段,在功率稀疏区间减少段数。最终用5段就满足了误差约束,求解时间只增加了30%左右。
提示:分段损耗的二进制变量千万不要漏掉 $\sum z_i = 1$ 这条约束。漏掉的话,辅助变量可能全部为零,损耗被低估,模型解出来看着正常,实际一校验就露馅。
1.1 分段数如何选择
这里给出一个可复用的经验流程:
- 用历史负荷和风光出力数据算出支路有功功率的变化范围 $[P_{\min}, P_{\max}]$。
- 把损耗函数在区间内做线性插值,对比不同分段数下的插值误差。
- 从3段开始测试,每增加一段记录目标函数变化量和求解时间。
- 当目标函数变化量小于1%时,就认为分段数够了。
这套方法比“拍脑袋定段数”要靠谱得多。如果你的系统里存在多条重载线路,建议对每条关键支路都单独建模;一般工程里只挑损耗占比前几位的支路做分段,其他的用固定损耗率处理即可,没必要把每条线路都做细分,否则模型规模会膨胀得很快。
1.2 为什么用分段线性而不是直接上交流潮流
我做的是日前调度,日内需要多次重算,如果直接用交流潮流,会和非线性优化方法形成循环迭代的问题,求解时间完全不可控。分段损耗是“精度和速度之间的工程妥协”——它在数学上保持线性,在物理上抓住了损耗随功率非线性的关键特征。如果你对精度有更高要求,可以在分段损耗基础上再做一轮交流潮流校验,用偏差值修正下一轮分段参数,这样既保住了MILP的求解效率,又提高了结果可信度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 阶梯碳价:让碳排放成本随排放量“跳档”
2.1 单一碳价的问题
单一碳价 $p_c$ 下,碳排放成本是 $C = p_c \times E$,线性关系意味着:只要碳价给定,系统每多排1吨碳的边际成本都一样。这在碳配额充裕时问题不大,但实际碳市场中“配额内低价、超配额高价”是普遍做法。单一碳价要么定得低、减排动力不足,要么定得高、系统运行成本被不合理抬高。阶梯碳价的设计逻辑更贴近碳市场的真实运行规则。
2.2 阶梯碳价的数学建模
阶梯碳价把总碳排放量 $E_{total}$ 划成多个区间,每个区间对应不同单价:
- 区间1:$E \in [0, E_1]$,单价 $p_1$
- 区间2:$E \in [E_1, E_2]$,单价 $p_2$,且 $p_2 > p_1$
- 区间3:$E \in [E_2, E_3]$,单价 $p_3$,且 $p_3 > p_2$
总碳成本为:
$$C_{carbon} = p_1 E_1 + p_2 (E_2 - E_1) + p_3 (E_{total} - E_2)$$
在建模时要注意,碳排放区间的填充必须按顺序来,不能出现“第一区间没用完就直接用第三区间”的情况。这个约束不写的话,求解器可能为了降低成本,把碳排放凭空塞到低价格区间,得到荒谬结果。解决方式是引入区间计费变量,并加上区间之间的顺序约束,让区间计费量只能随累计排放量递增填满。
2.3 阶梯碳价对储能调度的影响
在算例中我对比了三种碳价设定:
| 碳价方案 | 设定方式 |
|---|---|
| 无碳价 | 不计算碳排放成本 |
| 固定碳价 | 统一按50元/吨计 |
| 阶梯碳价 | 50/80/120元/吨,按排放量分3档 |
结果非常明显:阶梯碳价下,系统在负荷低谷期(风光出力大、火电出力少、碳排放强度低)主动给储能充电的比例更高,高峰期火电出力被压得更狠,整体碳排放量比固定碳价进一步降低约12%。原因也好理解:排放一旦进入高价位区间,边际减排成本猛增,优化器会主动寻找“替代电量”,而储能就是最直接的替代资源。
另外提示一点:阶梯碳价的区间上限要结合机组额定排放量来设。如果区间设得太窄,几乎每个调度周期都进入最高档,阶梯就失去了差异化调节的意义;设得太宽,则与固定碳价没什么区别。一般我会让第一档覆盖基准场景排放量的60%-70%,第二档覆盖到95%左右,剩余留作第三档。
3. 需求侧响应建模:可平移、可削减负荷怎么进模型
需求侧响应是用户侧资源参与系统调节的核心手段。我把它拆成三类来建模:可平移负荷、可削减负荷和可转移负荷。后两者在数学上差别不大,所以主要讲前两类。
3.1 可平移负荷
可平移负荷指启动时间可调整、但一旦启动功率曲线就固定的负荷,比如消毒设备、烘干设备、部分工业流水线。建模时需要引入启动时刻变量 $t_{start}$ 和运行时长 $T_{run}$,约束保证这类负荷必须在调度周期内完成运行:
$$\sum_{t=t_{start}}^{t_{start}+T_{run}-1} P_{shift,t} = E_{shift}$$
$$t_{min} \le t_{start} \le t_{max}$$
这样优化器会自主选择把这类负荷放在什么时段,通常会倾向于放在电价低、碳排放强度低的时段。实际建模时还要注意这类负荷的连续性——有些负荷允许中断,有些不允许,不允许中断的需要额外加“运行状态连续性”约束,避免模型把一段连续的生产流程拆得七零八落。
3.2 可削减负荷
可削减负荷更灵活,可以在任意时段削减一部分功率,比如空调、照明、部分充电桩。建模上给它一个削减量上限:
$$0 \le P_{cut,t} \le P_{cut,\max,t}$$
削减产生的成本是对用户的激励补偿,单位补偿价格 $c_{dr}$ 代入目标函数:
$$C_{DR} = \sum_t c_{dr} \cdot P_{cut,t} \cdot \Delta t$$
3.3 用户舒适度约束
很多人会忽略用户舒适度约束,导致模型把整个负荷都削减掉、成本低得离谱,但实际根本不可行。我加的约束包括:
- 每个时刻削减量不超过该时段总负荷的20%;
- 连续削减时长不超过2小时;
- 单日累计削减量不超过日总用电量的10%。
这三条约束在代码里非常好加,但对结果的影响非常大。不加这三条,需求响应贡献的削峰比例可能从“合理值”跳到“夸张值”,现场方案完全执行不了。
需求响应与储能的协同是另一个值得展开的点。在96时段仿真中,单独加需求响应时系统减排约10%,单独加储能减排约10.5%,两者都加时减排不是简单加和的20%,而是18%左右——协同效果虽然稍低于简单加和,但仍然明显高于单侧方案。原因在于:需求响应把负荷往低谷引导,储能把低谷富余的零碳电量搬到高峰,两者在负荷曲线上的作用方向是互补的。协同效应的量化是这类模型最有说服力的产出之一。
4. 多源协同出力:功率平衡、爬坡与备用约束的联动
多源协同不是简单地把各机组出力约束堆在一起,而是要让它们在同一个功率平衡方程里互相咬合。
4.1 系统功率平衡约束
考虑分段损耗后,功率平衡式为:
$$\sum_i P_{G_i,t} + P_{W,t} + P_{PV,t} + P_{dis,t} = P_{Load,t} - P_{DR,t} + P_{ch,t} + P_{loss,t}$$
其中 $P_{DR,t}$ 是需求响应削减后的负荷净减少量,$P_{ch,t}$ 和 $P_{dis,t}$ 是储能充放电功率。注意,这里把损耗放在等号右侧,和负荷叠加。如果损耗建模不准,等号左侧的发电机出力就会被集体抬高或压低,整个调度结果都会失真。
4.2 火电爬坡与出力上下限
火电作为可控电源,要同时满足三个层面的约束:
- 出力上下限约束:$P_{i,\min} \le P_{i,t} \le P_{i,\max}$;
- 爬坡约束:$|P_{i,t} - P_{i,t-1}| \le R_i \cdot \Delta t$;
- 最小开停机时间约束(如果做机组组合,这一条不能省)。
爬坡约束在风光波动大的场景下尤其重要。风电出力在15分钟内可能突然下降几十兆瓦,如果火电爬坡跟不上,系统频率就会出问题。加入了爬坡约束后,优化器会提前让储能增加出力或通过需求响应削减负荷,相当于把“突发缺口”在时间维度上摊平。
4.3 风电与光伏的出力边界
风电和光伏的出力不能超过各自预测值,同时可以丢弃多余的风光:
$$0 \le P_{W,t} \le P_{W,forecast,t}$$
$$0 \le P_{PV,t} \le P_{PV,forecast,t}$$
弃风弃光量由预测上限与实际出力之差得到。在目标函数中我会给弃风弃光一个较高的惩罚系数(通常取单位供电成本的2到3倍),否则优化器为了省成本可能主动大量弃风,这不符合双碳导向。
4.4 备用约束
备用约束不能只由火电满足,否则在高风光渗透场景下火电被顶得很高,既不经济也不低碳。我在模型里把储能和需求响应也纳入备用资源:
$$\sum_i R_i^{up} + R_{st}^{up} + R_{DR}^{up} \ge R_{req}$$
其中 $R_{req}$ 取最大负荷的10%或最大单机容量,两者取较大值。储能提供备用的方式是在正常充放电计划之上预留一部分容量;需求响应提供备用则要结合用户削减意愿曲线,不是所有负荷都能随时响应。
4.5 多源协同的耦合本质
几种源储资源在时间尺度上的配合逻辑是:风电/光伏是大自然给的“免费电”,但波动性强;储能负责搬运,也就是时间转移;需求响应负责缓冲,也就是需求侧调整;火电负责兜底。碳价信号把“低碳”需求转译成“经济”信号,多源协同的目标函数把所有成本项聚合后,优化器给出的调度策略自然就是减排效果与经济性综合最优的平衡解。这也是“协同”二字的真正含义——不是各做各的,而是在同一组约束里互相成就。
5. 储能建模:SOC递推、充放电互斥与循环衰减成本
储能建模是整个优化模型里最容易踩坑的模块。
5.1 SOC递推公式
储能荷电状态(SOC)随时间递推:
$$SOC_{t+1} = SOC_t + \left( \eta_{ch} P_{ch,t} - \frac{P_{dis,t}}{\eta_{dis}} \right) \frac{\Delta t}{E_{rated}}$$
其中 $\eta_{ch}$ 和 $\eta_{dis}$ 分别是充放电效率,我通常取0.95和0.9。这个递推关系在每个时段都要写成等式约束。这里有个工程细节:如果 $E_{rated}$ 比较大,而时间步长 $\Delta t$ 用的是小时,那么SOC变化量会很小,数值上要小心。我一般会把求解精度设到1e-6,避免求解器因数值问题报不可行。
5.2 充放电互斥约束
储能不能同时充电和放电,这是物理约束,但在模型里如果不显式写出来,求解器经常会给出“又充又放”的解,因为这样在某些约束下能“刷”利润。正确做法是引入0-1变量 $u_{ch,t}$ 和 $u_{dis,t}$:
$$0 \le P_{ch,t} \le u_{ch,t} \cdot P_{ch,\max}$$
$$0 \le P_{dis,t} \le u_{dis,t} \cdot P_{dis,\max}$$
$$u_{ch,t} + u_{dis,t} \le 1$$
5.3 初始SOC与末端SOC约束
做日内调度时,通常设置 $SOC_0 = SOC_T = 0.5$,保证储能日循环的“能量账户”守恒,避免模型通过首末端SOC差偷能量或藏能量。有时为了给第二天留调节空间,也可以设置 $SOC_T \ge 0.4$,把末端SOC作为软约束处理。
5.4 循环寿命衰减成本
很多储能模型不考虑循环寿命衰减,导致储能被优化器当“免费工具”频繁深度充放,这样算出来的调度策略很不真实。我参考产业经验,储能每单位能量吞吐(充1kWh加放1kWh)对应大约0.1到0.3元的寿命损耗成本,在目标函数中加入:
$$C_{bat} = \alpha \sum_t (P_{ch,t} + P_{dis,t}) \Delta t$$
加入这一项后,储能的日均循环次数从“近乎无限”降到了合理的1到2次以内,决策结果与工程实践更接近。这个系数 $\alpha$ 可以根据储能电池类型调整:磷酸铁锂一般取下限,三元锂电取上限,液流电池可以取更低的0.05左右。
6. 求解器选型与代码实现中的坑
6.1 求解器怎么选
我用的组合是 Python + Gurobi。原因是:Gurobi 对含大量0-1变量的MILP求解性能稳居第一梯队;它的Python接口(gurobipy)写约束非常直观,调试方便;社区版可以处理中等规模问题,教学和中小项目完全够用。如果没有Gurobi的授权,也可以退而求其次用 CBC、GLPK 等开源求解器,但求解时间会明显拉长。如果模型规模不大(变量数小于5000),开源求解器完全可接受。
6.2 代码结构设计
我一般按下面这样组织代码目录:
code复制project/
├── data/ # 负荷、风电、光伏、碳价、DR参数
├── model/
│ ├── constraints_build.py
│ ├── objective_build.py
│ ├── params.py
├── solve.py # 建模求解入口
├── result/
│ ├── figures/
│ └── output.csv
把参数与约束分开的好处是:换一套数据时不需要改动模型代码,只改配置文件。另外建议把所有参数集中写在一个 params.py 里,包括碳价区间、需求响应补偿价格、储能效率等,这样后面做敏感性分析时非常方便。
6.3 常见报错与调试经验
调试过程中我遇到过三个比较典型的问题。
第一个:分段损耗约束漏写 $\sum z_i = 1$,模型求解结果本身正常,但功率平衡校验不过去。这种问题很隐蔽,建议在建完模型后单独做一次“纯功率平衡”检查,把约束逐个释放掉,看哪条导致失衡。
第二个:阶梯碳价区间变量不递增,出现“第2档用了电量、第1档却没用满”的荒谬分配。这个靠加顺序约束解决,我使用累计变量 $E_{acc}$ 来简化:让区间计费量通过分段函数与累计排放量关联,确保计费量按顺序填充。
第三个:储能SOC初始值设置不当导致首时段无解。我建议在初始SOC约束外,再加全时段的SOC边界约束,并给SOC定义域留一点余量(比如0.02到0.98),防止数值边界导致单个时段溢出。
求解时间方面,24时段(步长1小时)的问题一般几秒到几十秒就出结果;96时段(步长15分钟)的模型,变量规模大了4倍,Gurobi默认参数下通常在几分钟内收敛。如果遇到求解时间爆炸,优先检查是不是二进制变量太多,或者约束里大M值设置过大导致数值病态。
7. 算例验证与结果解读思路
7.1 系统设置
我用的是修改后的IEEE 30节点系统:
- 火电3台,总装机420MW;
- 风电场1座,额定120MW;
- 光伏电站1座,额定80MW;
- 储能1座,100MW/200MWh;
- 负荷峰值280MW;
- 调度周期24小时,步长15分钟,共96个时段。
7.2 对比方案
建议至少做四组对比,这样能清晰分离每个模块的贡献:
- 方案A:固定损耗率 + 无碳价 + 无DR + 有储能(基准模型)
- 方案B:分段损耗 + 无碳价 + 无DR + 有储能
- 方案C:分段损耗 + 阶梯碳价 + 无DR + 有储能
- 方案D:分段损耗 + 阶梯碳价 + 有DR + 有储能(完整改进模型)
7.3 关键结果
仿真结果可以整理成下面这种对比表(数值为示意):
| 指标 | 方案A | 方案B | 方案C | 方案D |
|---|---|---|---|---|
| 总运行成本/万元 | 68.2 | 66.5 | 72.8 | 69.1 |
| 碳排放量/t | 712 | 698 | 612 | 548 |
| 弃风弃光率/% | 9.6 | 8.1 | 5.8 | 4.2 |
| 储能日均循环次数 | 1.5 | 1.3 | 2.1 | 2.4 |
| 需求响应削减占比/% | — | — | — | 8.6 |
从表里能读出几个重要结论:
- 方案B对方案A,成本下降、排放下降,说明损耗建模精度提升后,调度方案更贴近实际,避免了“为固定损耗率买单”的无效发电。
- 方案C对方案B,成本上升但排放大幅下降,这就是阶梯碳价把外部环境成本内部化的结果。
- 方案D对方案C,成本和排放同时下降,说明需求响应与储能协同优化能同时改善经济性和低碳性。
- 弃风弃光率逐项下降,说明网损精细化建模、碳价信号、需求响应三者共同提升了新能源消纳能力。
7.4 我个人的分析习惯
拿到结果后,我还会额外做两个分析。一是画储能SOC与碳价区间的对应曲线,看储能是不是真的在低碳价时段充电、高碳价时段放电;二是做敏感性分析,把阶梯碳价的第二档单价上下浮动20%,看碳排放和成本的变化幅度。这些分析能增加项目报告或论文的深度,也能帮助验证模型行为的合理性。
8. 扩展方向与实测体会
这个模型目前是确定性的日前调度,下一步我计划做两处扩展。第一是引入风光出力的随机场景,把单场景变成多场景期望优化,对储能调度和碳价策略做鲁棒性校验;第二是把储能建模从“单站”扩展为“分布式储能集群”,并加入配电网络的电压约束,这样更贴合实际配电网项目。
就我个人实测体会,分段损耗这套处理方式在扩展后依然适用,它不会成为模型瓶颈,反而是少数能“一次建对、长期复用”的模块。整个模型最难的不是单个约束怎么写,而是分段损耗、阶梯碳价、需求响应三个模块之间的耦合——它们都依赖0-1变量,变量一多,MILP的求解难度就上来了。我最后再分享一个小技巧:调试时先用24时段和3段损耗快速跑通全流程,确认结果合理后再切换到96时段和5段损耗,这样能省下大量排错时间。如果你也在做低碳调度或储能优化,建议从这套模型出发,按你自己系统的数据改参数、换案例,很快就能看到它对调度计划的实质性改善。
