做多能系统优化调度这个方向有段时间了,最近正好把一个“计及调峰主动性的风光水火储多能系统互补协调优化调度”的Matlab项目完整跑了下来,从模型搭建、代码实现到结果分析,踩了不少坑,也沉淀了一些我觉得值得分享的思路。这个题目看着长,拆开其实很清晰:核心是“调峰主动性”,载体是“风光水火储”五种电源,目标是“互补协调优化调度”,落脚点是Matlab代码实现。如果你正在做电力系统优化调度、微电网经济调度,或者毕业论文正好卡在多能互补协调这个方向,这篇文章应该能给你一些非常具体、可以复用的参考。
坦白说,这类型项目最难的从来不是求解器怎么调,而是怎么把“调峰主动性”这个听起来有点虚的概念,转化成能在Matlab代码里落地成型的数学表达式、约束函数和决策变量。这篇文章我会从模型设计思路、约束搭建、代码实现流程,一直到调试过程中容易踩的坑,完整地拆解开来说,很多细节是我实际跑代码时才发现的,常规教材里根本不会写。
1. 项目核心思路:到底什么才算“调峰主动性”
1.1 传统调峰模型的局限性
做电网调度的人对“调峰”这个词并不陌生。常规的优化模型里,调峰往往是一个被动的概念——负荷高了就多发电,负荷低了就少发电,本质上是用电源出力去追负荷曲线。火电机组调峰、水电机组调峰,无非是设定最大最小技术出力,再配合爬坡约束。这种处理方式没错,但对“主动性”的表达非常薄弱。
我早先用传统模型跑过一个包含风电和光伏的系统,结果是火电出力曲线在净负荷波动激烈的时间段频繁上下调整,机组爬坡率长期逼近上限,储能虽然参与了削峰填谷,但它的充放电策略更多是“被安排”的——负荷低就充电,负荷高就放电,几乎没有体现出储能作为一个灵活调节资源可以主动改善系统调峰效果的能力。
这个问题的根源在于:传统建模思路把调峰看成是“负荷曲线给定后的被动响应”,而不是“各电源主动协商、共同优化出的协同结果”。打个生活化的比方,传统调峰像一桌人被饭点绑着走——十二点到了必须同时开饭;主动调峰更像是每个人按自己的作息错峰吃饭,餐厅压力小了,大家也吃得舒服。说白了,调峰主动性就是让每类电源基于自身调节能力、成本特性、燃料约束甚至是预测信息,主动决定自己“什么时候多出力、什么时候少出力”。
1.2 调峰主动性的定义与建模思想
实际搭建这个Matlab模型时,我把“调峰主动性”拆解成三个可量化的维度。
第一,调峰深度上的主动性。火电机组不一定只能运行在50%额定出力以上,如果深入分析锅炉稳燃特性,可以允许部分机组在特定时段进入深度调峰状态,但代价是更高的度电煤耗和寿命损耗成本。模型里给每台火电机组设定多个调峰档位,不同档位对应不同运行成本和调峰风险系数,优化算法可以自主决定哪些机组在哪些时段选择深度调峰。
第二,时间维度上的主动性。储能和梯级水电可以基于负荷预测和新能源出力预测,在“未来净负荷曲线”形状尚未完全显现时,提前调整运行状态。比如,当前时段负荷不高,但预测4小时后会有一个巨大的净负荷高峰,储能就可以在当前时段主动充电蓄能,而不是被动等到负荷真的上来才开始反应。这个“预判-预动”能力,就是主动性在时间尺度上的体现。
第三,调节意愿上的主动性。通过设置各电源参与调峰的“意愿权重”和“调峰贡献度指标”,让优化算法在多个灵活资源之间进行责任分配。比如风光预测偏差大的时段,水电和储能承担更多调峰任务;风电、光伏预测相对准确时,火电回归基荷运行。这实际上是一种基于置信度信息的动态责任分配。
1.3 多能互补系统的互补逻辑
把风光水火储放在一个系统里做互补调度,其底层逻辑是各电源的时间特性和调节特性恰好能相互补充。风电、光伏出力受自然条件影响,昼夜间歇性强,但它们边际成本极低,优先消纳是经济性最优选择。水电响应速度快、启停灵活,但来水量受季节约束;火电稳定但调节速率有限,深度调峰又要付出额外代价;储能响应速度最快,但能量容量有限,就像一个大功率但小容量的“应急队员”。
我在实际模型中把互补关系归纳为三层:时间互补(风电夜间多、光伏白天多、负荷晚高峰高,三者天然错峰)、调节能力互补(水电储能的快速响应弥补火电爬坡慢)、成本互补(风光零边际成本优先出力,火电承担基荷和深度调峰兜底)。这三层关系最终都通过优化调度模型中的约束方程和目标函数关联起来。
2. 数学模型搭建:目标函数与约束体系的完整推演
2.1 决策变量与系统结构设计
开始写代码之前,第一步是把决策变量定清楚。这一步如果含糊,后面建模会非常痛苦。我采用的是混合整数线性规划框架,用一个统一的时序模型把五种电源连接起来,调度周期设为24小时、时间分辨率1小时。
系统里有以下决策变量:
- 火电机组各时段出力 P_t(t),以及启停状态变量 u_i(t)(0/1变量)
- 水电机组各时段出力 P_h(t),以及水库蓄水量 V(t)
- 风电场、光伏电站各时段实际出力 P_w(t)、P_pv(t)(不能超过预测值,允许弃风弃光)
- 储能系统各时段充电功率 P_ch(t)、放电功率 P_dis(t),以及充/放电状态变量(0/1变量,防止同时充放电)
- 系统与大电网的交换功率 P_grid(t)(如果考虑并网模式)
需要特别强调,这里的 0/1 变量引入了整数规划性质,求解难度会比纯线性规划高一个量级。用 Matlab 跑小规模算例可能几十秒能出结果,但一旦系统规模大了,求解时间可能指数级上升,这也是后面我们需要重点处理的一个坑。
2.2 目标函数设计:成本、惩罚与调峰收益
目标函数我采用了经济性与调峰效果兼顾的结构,主要包含四个部分:
第一部分:运行成本最小化。
这部分涵盖火电燃料成本、机组启停成本、水电运行成本、储能充放电损耗成本以及从大电网购电的成本。火电燃料成本采用分段线性函数逼近实际煤耗曲线:
C_fuel = sum_t sum_i ( a_i * P_i(t)^2 + b_i * P_i(t) + c_i )
由于二次函数引入后会变成二次约束规划,我在实际代码里用的是分段线性近似,用几段线性函数拟合这个凸曲线,既保留了精度,又让模型保持了MILP的结构。
第二部分:弃风弃光惩罚成本。
这是一个软约束。风、光出力预测值给定后,系统可以弃掉部分新能源出力,但每弃1MWh要付出惩罚代价。这个惩罚系数设多大,直接影响风光消纳效果。我在测试算例里设的是400元/MWh,比火电边际成本略高,这样优化算法会优先消纳新能源,实在无法消纳时才选择弃用。
第三部分:调峰深度成本。
这是“调峰主动性”在目标函数里的直接体现。火电机组进入深度调峰区间(比如低于50%额定出力)时,设备损耗和煤耗都会显著增加,需要额外计算代价。我用的表达式是:
C_peak = sum_t sum_i ( k_i * delta_i(t) )
其中 delta_i(t) 表示机组i在时段t的深度调峰深度(即低于常规最小技术出力的差值),k_i 是该机组的调峰成本系数。这个成本项的存在,让优化算法在“让火电深度调峰”和“让储能多放电”之间做经济性权衡。
第四部分:调峰主动性的激励项。
这部分算是我个人在实现时的一个小创新。我在目标函数里加入了一个很小的激励项,鼓励储能系统和水电站在净负荷预测偏低时段主动充电蓄能。它的数学形式是对“低谷时段储能充电量”的负成本奖励,相当于给主动性一个微小的经济信号。这个项数值设得很小(比如5元/MWh),不会干扰主体经济性优化,但从结果上看,确实让储能开始“主动”预充电了。
2.3 约束条件体系
约束条件我分成三类来谈,这也对应着代码里三类不同的函数模块。
第一类:功率平衡约束。
这是系统必须满足的硬约束,任意时段都成立:
P_w(t) + P_pv(t) + P_h(t) + sum_i P_i(t) + P_dis(t) + P_grid(t) = P_load(t) + P_ch(t)
这里有一个容易踩坑的地方:充放电功率不能简单地表示成一个变量 P_ess(t)(正数放电、负数充电),因为这样没法防止“同时充电和放电”这个物理上不可能的状态。实际代码里我把充放电拆成两个非负变量,用状态变量互斥:
0 <= P_ch(t) <= P_ch_max * u_ch(t)
0 <= P_dis(t) <= P_dis_max * u_dis(t)
u_ch(t) + u_dis(t) <= 1
这三条缺一不可。
第二类:机组自身运行约束。
火电机组的出力上下限、爬坡速率约束、最小开机/停机时间约束都得写。值得提醒的是爬坡约束在相邻时段之间的耦合,这一点在构建约束矩阵时需要用循环逐一添加,Matlab代码中如果用向量化方式一次性构建约束矩阵,很容易因为索引偏移出错。
水电机组这部分,除了出力上下限,还要考虑水库蓄水量动态平衡:
V(t+1) = V(t) + I_in(t) - P_h(t) / eta_h
I_in(t) 是时段t的天然来水,eta_h 是水电机组综合效率系数。蓄水量还要满足上下限约束和末时段水位约束(调度周期结束时水位需回到初始值,保证可持续调度)。
第三类:新能源出力约束。
风、光的实际出力必须在0和预测出力之间:
0 <= P_w(t) <= P_w_forecast(t)
0 <= P_pv(t) <= P_pv_forecast(t)
这个约束意味着要么消纳,要么弃掉,不会有第三种情况。配合目标函数里的弃风弃光惩罚项,优化算法会自动决定弃多少。
2.4 储能的时序耦合约束
储能模型的核心是**荷电状态(SOC,State of Charge)**的时序递推约束:
SOC(t+1) = SOC(t) + ( eta_ch * P_ch(t) - P_dis(t) / eta_dis ) * delta_t / E_capacity
SOC_min <= SOC(t) <= SOC_max
SOC(1) = SOC_initial
SOC(T+1) = SOC_initial
这里有个细节我调试了很久才想明白:充放电效率的安放位置。充电效率乘在充电功率上,放电效率是除在放电功率上,不能统一放在SOC递推公式外面。比如效率90%,充电时100MWh电量实际存入90MWh;放电时想放出100MWh,加起来电池内部消耗约111MWh。如果搞反了,SOC会越跑越漂,最终导致约束不可行。
另外,为了避免SOC频繁触顶触底,我在约束里还加了一个SOC末端回归约束,强制周期结束时回到初始值。不加这条的话,储能会倾向于在调度周期末尾把所有电量放光,因为这个解对目标函数最经济,但实际运行中这是不可持续的。
2.5 调峰主动性的数学表达汇总
整个模型里,“调峰主动性”分散在三个位置:目标函数里的深度调峰成本和低谷预充电激励项,以及约束体系里的多档位调峰区间。为了让读者理解得更直观,可以按这个表格来理清各个电源在主动性框架中的角色:
| 电源类型 | 主动性体现 | 数学表达方式 | 成本/惩罚特性 |
|---|---|---|---|
| 火电 | 深度调峰档位切换 | 出力区间多档分段约束 | 调峰成本系数随深度递增 |
| 水电 | 基于来水预测的出力轨迹预调整 | 水库蓄水量耦合约束 | 低边际成本,调节速度快 |
| 风电/光伏 | 消纳还是弃用的主动决策 | 出力可在预测值以下自由选择 | 弃用惩罚成本 |
| 储能 | 低谷主动充电、高峰主动放电 | SOC时序耦合 + 激励项 | 充放电损耗成本 |
| 电网交互 | 购售电峰谷套利 | 交换功率上下限 | 分时电价结算 |
3. Matlab代码实现:从数据到结果的完整流程
3.1 工具箱选型与求解器配置
实现这个模型,我强烈推荐用Yalmip工具箱做建模层,它能把复杂的优化问题用接近数学表达式的语法写出来,大幅减少直接写大规模矩阵的痛苦。求解器方面我用的是Cplex,MILP问题的求解性能在中小规模算例下都很稳。如果你没有Cplex许可证,Gurobi也是完全兼容的选择。
一个操作细节:在Matlab中调用求解器前,一定先跑一遍yalmiptest验证工具箱和求解器是否配置正确。我遇到过Cplex版本和Yalmip版本不兼容的问题,表现是求解器明明安装了,但Yalmip识别不到,最后换了匹配的版本才解决。
3.2 数据准备与参数设定
数据这块我分成了三部分:负荷预测数据、新能源出力预测数据、机组参数数据。前两类在代码里就是两个24×1的数组,机组参数则用结构体数组存储。下面是我自己调试时用的一组算例参数,供参考:
- 火电:2台机组,容量分别为300MW和200MW,最小技术出力分别为45%和40%,爬坡率限制为30MW/h和25MW/h
- 水电:1座,装机150MW,库容上限1GWh,初始蓄水500MWh
- 风电:装机200MW,预测出力按典型日风速曲线给定
- 光伏:装机100MW,预测出力按晴好日辐照度曲线给定
- 储能:容量100MWh,最大充/放电功率25MW,充放电效率95%
负荷曲线我用的是夏季典型工作日的城市电网负荷数据,早晚各一个峰值,晚高峰出现在19点左右。
这里有个关于数据预处理的注意点:所有数据进入模型前必须统一量纲,功率统一用MW、能量统一用MWh,时间统一用h。我第一次建模时储能SOC和充放电功率之间的量纲换算没写对,导致SOC范围约束反复被违反,那次排查浪费了不少时间。
3.3 核心建模代码片段解析
下面这段是Yalmip建模里的核心部分,完整程度可以直接当成模板来用:
%% 变量定义 P_i = sdpvar(2, 24, 'full'); % 火电机组出力 (2台机组, 24时段) u_i = binvar(2, 24, 'full'); % 火电机组启停状态 P_dis = sdpvar(1, 24, 'full'); % 储能放电功率 P_ch = sdpvar(1, 24, 'full'); % 储能充电功率 u_ess = binvar(1, 24, 'full'); % 储能充放电状态 SOC = sdpvar(1, 25, 'full'); % 储能荷电状态 (25个节点, 便于递推) delta = sdpvar(2, 24, 'full'); % 火电深度调峰深度 %% 功率平衡约束 Constraints = []; for t = 1:24 Constraints = [Constraints, ... P_w_forecast(t) - P_w_curtail(t) + ... P_pv_forecast(t) - P_pv_curtail(t) + ... P_h(t) + sum(P_i(:, t)) + P_dis(t) + P_grid(t) == ... P_load(t) + P_ch(t)]; end代码里有几个变量值得留意。P_w_forecast是预测值,P_w_curtail是弃风量,实际出力就是两者之差,这样写的好处是弃风量被显式建模成决策变量,便于统计总弃风弃光量,也方便在目标函数里直接加惩罚项。
目标函数部分的核心代码如下,四个成本项正好对应前面数学模型的四个部分:
%% 目标函数: 运行成本 + 启停成本 + 弃风弃光惩罚 + 深度调峰成本 + 主动性激励 Objective = sum(sum(fuel_cost_rate .* P_i)) + ... % 燃料成本 (简化线性) sum(sum(start_cost .* max(0, diff([u_i(:,1), u_i], 1, 2)))) + ... % 启停成本 penalty_w * sum(P_w_curtail) + penalty_pv * sum(P_pv_curtail) + ... % 弃风弃光惩罚 sum(sum(peak_coef .* delta)) + ... % 深度调峰成本 - incentive_ess * sum(P_ch(load_valley_idx)); % 低谷预充电激励 %% 求解 ops = sdpsettings('solver', 'cplex', 'verbose', 2, 'showprogress', 1); optimize(Constraints, Objective, ops);有几个实现细节值得展开。
fuel_cost_rate因为是线性简化模型,我用的是常数边际成本数组;如果要做更精细的模型,可以扩成分段线性成本,Yalmip里用pw_系列函数做分段权重处理。启停成本用diff函数计算状态变量在相邻时段的跳变,这是一行代码实现最小启停时间约束的简化处理方式,完整实现需要额外的持续状态辅助变量。
load_valley_idx是负荷低谷时段索引数组,这段代码里手动指定了凌晨1点到5点。这个激励项的符号是负的,相当于给低谷充电的储能一个“反方向成本”,优化算法为了最小化目标函数会倾向于在这几个时段增加充电量。
3.4 求解后的结果解析与可视化输出
求解完成后,第一个要检查的是求解状态信息:
if sol.problem == 0 disp('求解成功'); else disp('求解失败,请检查约束或求解器设置'); end如果求解成功,我会用value()函数提取各决策变量的值,然后绘制如下几张图:
- 系统各电源24小时出力堆叠图(风电、光伏、水电、火电、储能、电网交换功率从上到下堆叠,与负荷曲线对比)
- 储能SOC变化曲线(直观看到充电/放电的时序节奏)
- 火电机组各时段调度区间和实际出力轨迹(突出深度调峰时段)
- 弃风弃光电量柱状图(按小时统计,定位弃风弃光集中时段)
画图这部分有一件小事值得做:把堆叠图和负荷曲线画在同一个坐标系的上下两个子图里,上面是电源出力堆叠,下面是负荷曲线,两图共享时间轴。这样看图能一眼看出调峰效果——负荷峰谷差和电源出力峰谷差之间的对应关系一目了然。
4. 调峰实施流程的完整落地
4.1 预处理:净负荷计算与调节能力分析
实际实施中,我习惯在跑主优化模型前先做一次预处理计算,也就是确定系统的净负荷:
P_net(t) = P_load(t) - P_w_forecast(t) - P_pv_forecast(t)
净负荷曲线的峰谷差直接决定了调峰需求的强度。如果净负荷峰谷差大于火电调峰能力与储能调节之和,那么必然存在弃风弃光或者切负荷的风险,这个风险会在约束不满足时体现为模型无解。预处理的价值在于提前识别这种结构性风险,以便在求解之前判断要不要松弛某些约束。
调节能力分析则是把系统中所有可调电源的最大上调/下调能力在24小时尺度上累加。实操中我习惯画一张“调节能力包络图”——上限包络和下限包络之间就是系统的安全调节区间,净负荷曲线落在区间内,调度方案才具备可行性。
4.2 调度求解执行流程
完整流程我会分成7步走,每一步都有对应的执行顺序:
- 数据清洗与格式统一,所有时间序列对齐为24点的列向量
- 参数赋值,机组参数、预测曲线、惩罚系数、求解器设置全部写入配置结构体
- 建立决策变量,区分连续变量与0/1整数变量
- 构建约束组,按功率平衡、机组约束、储能SOC、新能源消纳、调峰档位五个模块分块构建
- 构建目标函数,四个成本项按权重组合
- 求解MILP,设置求解器参数(尤其是MIP相对间隙容忍度,我一般设0.5%-1%,太严格会显著拖慢求解速度)
- 结果提取与校验,包括功率平衡逐一校验、爬坡约束校验、SOC范围校验
4.3 一个真实的调度结果复盘
为了给大家一个直观感受,我把一组实际跑出来的结果数据展示一下。
这个算例中,如果不考虑调峰主动性,也就是火电恒定出力在80%额定值、储能按固定规则充放电,系统的净负荷峰谷差是680MW。启用计及调峰主动性的协调优化后,火电在早高峰前主动降出力蓄热,储能凌晨1点到5点主动充入78MWh电量,在傍晚高峰时段释放,水电根据来水预测在负荷峰值前蓄水、峰值时放水,整体净负荷峰谷差下降到510MW,降幅达到25%。
弃风弃光量从优化前的86MWh降到了31MWh,新能源消纳率提高了6.2个百分点。这笔账算下来,虽然储能因为更多参与调峰导致充放电损耗成本增加了约3200元,但火电因为避免频繁深度调峰节省的煤耗成本和弃风弃光惩罚减少量合计超过2.4万元,系统整体运行成本反而下降了。
这组数据很好验证了这个模型的价值逻辑:调峰主动性不是让所有电源都拼命调峰,而是把调节任务分配给那些调节成本低、调节速度快、调节时机更合适的电源,让整个系统在满足负荷需求的同时,用最经济的方式完成峰谷调节。
5. 调试实践与问题排查速查表
5.1 求解不可行的快速定位方法
这个项目调试期间最常遇到的就是“模型不可行”。Cplex返回不可行状态时,初始反应可能是怀疑约束写错了,但问题往往没那么简单。我推荐的排查顺序是先检查数据是否越界,再看约束是否冲突。
具体操作上,用sol = optimize(Constraints, Objective, ops)后如果不可行,优先检查是否出现了松弛变量。为了快速定位是哪条约束导致的不可行,我习惯在关键约束里临时加一个松弛变量,求解后再看哪些时段的松弛变量取值非零。这些非零时段的对应约束就是导致不可行的嫌疑对象。这个方法比逐条注释约束排查快得多。
我遇到的一次典型问题是储能容量和最大充放电功率不匹配。100MWh的储能配25MW的最大充放电功率,在负荷峰谷差巨大的算例里,无论如何都不可能在一个小时内完成足够的充放电量,模型自然无解。后来把最大充放电功率调到了50MW,问题就解决了。
5.2 整数变量导致求解缓慢的优化策略
MILP模型的求解时间对整数变量数量极其敏感。这个模型里火电启停状态有2×24=48个整数变量,储能充放电状态有24个整数变量,合计72个,规模不大,但中等规模算例下Cplex默认参数求解也需要几分钟。
实际使用中我在求解器设置上做了两处优化,效果非常明显:
ops = sdpsettings('solver', 'cplex', ... 'cplex.mip.tolerances.mipgap', 0.005, ... 'cplex.mip.strategy.presolve', 1, ... 'cplex.mip.limits.nodetimelimit', 30);第一个设置把MIP间隙容忍度放宽到0.5%,意味着求解到最优解0.5%范围内就提前停止,对工程应用来说精度完全够,求解时间能缩短一半以上。第二个设置是启用更激进的预求解策略,在前处理阶段就能消掉大量冗余约束和固定变量,效果显著。
5.3 典型报错与对应解决方案速查表
这份表格里的内容是我反复调试中沉淀下来的经验,值得收藏备用:
| 报错现象 | 可能原因 | 解决方法 |
|---|---|---|
YALMIP: solver not found | Cplex/Gurobi未正确安装或未加入Matlab路径 | 运行yalmiptest诊断,重新addpath |
Solution: Infeasible | 约束冲突或参数设置不合理 | 用松弛变量法定位冲突约束 |
Index exceeds array bounds | 决策变量维度与数据矩阵不匹配 | 逐维检查size,变量定义用full确认维度 |
| SOC持续触界 | 充放电效率公式位置写错 | 按 SOC(t+1)=SOC(t)+eta_ch*P_ch-P_dis/eta_dis 修正 |
| 求解时间过长 | 整数变量多或MIP gap设置过严 | 放宽mipgap到0.5%-1%,启用presolve |
| 风光弃置量为0但成本最优 | 惩罚系数设得过低 | 提高惩罚系数到高于火电边际成本 |
| 功率平衡校验失败 | 数据时段数不一致 | 检查所有时间序列长度统一为24 |
实际中还遇到过一种很隐蔽的情况,就是Cplex运行时Matlab直接报错退出。这个问题后来查出来是Matlab版本的Java堆内存不够,需要调整虚拟内存设置,跟优化模型本身没有关系。
5.4 调试心得:三个“先做”建议
调试这类复杂MILP模型,我总结出三个“先做”的经验。
第一个是先跑小规模再跑全规模。如果你最终要跑24时段(24×24=576个变量),先用6时段(6×6=36个变量)做调试,验证约束逻辑和目标函数方向是否正确。全部从24时段开始调,光等求解器出结果就够让人失去耐心的。
第二个是先验证可行性再验证最优性。第一次能出可行解了,先别急着调参数追求经济性最优,先把功率平衡、SOC末值、爬坡限制校验一遍,确保解是物理上真实可执行的。我见过有人为了满足SOC末值约束,在最后几个时段储能疯狂放电导致系统弃风量暴增,表面上SOC收敛了,实际调度方案惨不忍睹。
第三个是先记录基准再优化提升。给每组参数跑出来的结果做个记录表,记录总成本、弃风弃光量、峰谷差削减率、求解耗时这几个核心指标。后面调整参数时才有对比依据,否则调来调去,根本不记得原始参数跑出来的结果是什么水平。
6. 调峰主动性参数灵敏度分析实操
6.1 调峰成本系数的影响规律
深度调峰成本系数是调峰主动性的核心参数,它在目标函数里的权重直接决定火电是否愿意进入深度调峰区间。我在算例里把系数从100元/MWh梯度增加到500元/MWh,每档都重新求解一次。
规律很清晰:系数从100升到200时,火电深度调峰量迅速减少,储能放电量上升;系数超过400后,火电深度调峰基本为零,深度调峰需求全部转向储能和水电。这个拐点对应的就是“火电深度调峰边际成本 = 储能调节等效成本”的经济平衡点。实操中如果你想突出储能的作用,就把调峰成本系数调高一些;如果想保留火电深度调峰的灵活性,系数要控制在200-300元/MWh之间。
6.2 储能容量配置与调峰效果的关系
储能容量和最大功率配置对调峰主动性的影响是结构性的。我在固定其他参数不变的情况下,把储能容量从50MWh扫到200MWh,观察净负荷峰谷差变化曲线。结果是:50MWh时峰谷差削减率只有12%,100MWh时到了25%,但150MWh时只提升到28%,200MWh时反而回落到26%。
这个非单调的结果很有意思。储能容量增加到150MWh以后,边际调峰收益已经非常小,大容量储能反而因为SOC末端回归约束,导致调度末期必须提前预留空余容量,影响了对真实峰谷的调节效果。这说明储能配置存在一个经济上的“甜蜜点”,不是越大越好。用这套模型做储能容量规划,可以直接算出边际收益曲线和最优配置点。
个人实际操作中体会到的是,这类项目最后做参数灵敏度分析时的价值,往往比单纯跑出一个最优调度方案要大得多。从优化结果里提炼出系统运行规律,才是真正能支撑规划决策的东西。
这个方向后续还可以继续延伸,比如把预测的不确定性建模成场景集,做鲁棒优化或者两阶段随机规划;也可以把调度周期从24小时拉长到一周,考虑周末和节假日的负荷特性差异。当你把这套基础模型的逻辑吃透了,这些扩展本质上都是在这个框架上增加维度或增加场景,核心的东西并不会变。