高比例新能源电力系统调峰成本量化与分摊的Matlab建模实践
2026/9/15 1:32:55 网站建设 项目流程

最近在做一个高比例可再生能源电力系统的调峰成本量化与分摊模型,用 Matlab 把整套东西实现了一遍。这类研究相信很多人都不陌生:风电、光伏出力一高,系统净负荷的峰谷差被拉得特别大,为了维持电力平衡,常规火电机组就得不断压出力、深调、甚至启停来“调峰”。但调峰不是免费的,煤耗增加、机组寿命损耗、频繁启停,这些都是真金白银的成本。问题在于,这笔钱到底该算多少?又该由谁来承担?前者是调峰成本量化,后者是调峰成本分摊,正好是项目标题里两个核心关键词。

这篇不打算写成教科书,我把模型思路、成本公式怎么落到 Matlab 代码里、分摊逻辑怎么设计、以及实际编程中容易踩的坑,都系统整理一遍。适合正在做电力系统调峰、辅助服务测算、新能源并网影响评估的科研人员和工程技术人员参考。如果你只是想把模型跑通、快速出结果,直接看我后面给的代码框架就行。

1. 先搞清楚调峰成本到底从哪里来

1.1 高比例新能源带来的调峰需求

传统电力系统里,负荷曲线有峰有谷,但总体可预测,调节压力主要靠火电、水电来扛。新能源比例上来以后,问题就复杂了。风电出力半夜可能很高,光伏白天高但晚上直接归零,再加上天气导致的不确定性,系统“净负荷”(负荷减去新能源出力)的峰谷差会显著增大。

举个直观的例子,某地区晚高峰负荷达到 9000MW,而光伏出力为零,风电只有 400MW,那常规机组要发 8600MW。到了凌晨某个时刻,负荷降到 5200MW,风电却可能涨到 2000MW,这时常规机组得压到 3200MW。一天之内,火电可能要经历从 8600MW 到 3200MW 的大范围调节,这就是调峰需求。

在高比例可再生能源场景下,调峰需求已经不只是“晚峰爬坡”那么简单,还包含“光伏落山后的陡升爬坡”“风电骤增时的深压出力”“凌晨低谷期的深度调峰”。每一次大范围出力调整,都在消耗常规机组的调节能力和设备寿命。

我从项目里能够很直观地看到:新能源渗透率越高,净负荷的最小值和最大值之间差距越大,需要付出的调峰代价也越高。所以,量化这些代价,是设计调峰补偿和分摊机制的基础。

1.2 调峰成本的三个主要构成

调峰成本不是单一概念,在项目里我把它拆成了三块:

第一块是运行能耗增量。机组在非经济工况下运行,煤耗率升高。正常工况下,机组可能运行在 60% 到 80% 额定出力,效率较高;但深调时压到 30% 甚至 20% 额定出力,供电煤耗会大幅增加。这部分增量可以通过机组煤耗特性曲线直接算出来。

第二块是机组寿命损耗成本。机组长期深度调峰,转子、汽缸等高温部件承受更大的热应力,会产生低周疲劳损耗,缩短检修周期。工程上常用等效运行小时(EOH)来近似评估这种损耗。简化模型里,可以按深度调峰的比例给一个损耗系数,再折算成钱。

第三块是启停成本。机组启停一次,要消耗大量燃料用于暖炉、冲转、并网,还要考虑启动过程中的额外维护成本。启停调峰在新能源出力波动大时尤其常见,比如日内风电骤降导致需要快速启动机组顶峰。

另外,如果调峰能力不足,系统只能弃风弃光,那么弃电损失也应该纳入广义调峰成本,只是量化时通常单独列项。我在模型里把这部分叫做“缺调峰惩罚成本”,在分摊时同样需要对应承担主体。

1.3 成本量化不是简单“多烧了多少煤”

看到这里你可能会想,调峰成本不就是高峰出力和低谷出力下的燃料费差值吗?我最初也这么认为,但真正做模型时会发现,单纯算煤耗差值是不够的。

深度调峰工况下的寿命损耗必须单独叠加。比如一台 600MW 机组从 480MW 压到 180MW,煤耗差值可能只是几十万元量级,但转子寿命损耗折算综合下来,单位深调电量的成本会显著提升。也因此,我采用的成本函数是不分段线性,而是一个带有“深调惩罚项”的非线性函数。

另一个容易被忽略的是机会成本。当机组因为深度调峰而失去高负荷收益时,这部分损失在电力市场环境下应被计入。在成本型调峰模型里,可以采用“在给定出力区间内,最小运行成本与额定经济出力运行成本的差值”来近似代表。

最终,我在 Matlab 模型里把单台机组的调峰成本定义为:

[ C_i(P)=C_f(P_i)+C_{life}(P_i)+C_{startup}\cdot u_i ]

其中 (C_f) 是煤耗成本函数,(C_{life}) 是深度调峰寿命损耗,(u_i) 是启停指示变量。这个公式看起来简单,实际编程时难点在于 (C_f) 的系数怎么拟合、 (C_{life}) 怎么表达成出力 (P_i) 的连续函数。

2. 调峰成本量化模型:成本构成与计算公式

2.1 煤耗成本函数:用二次曲线拟合机组特性

火电机组煤耗特性在传统经济调度里已经研究得很透,通常采用二次函数拟合。设机组 (i) 在出力 (P) 下的燃料成本为:

[ C_{fuel,i}(P)=a_i+b_iP+c_iP^2 ]

单位是元/小时。系数 (a,b,c) 可以从机组的供电煤耗试验数据拟合得到,也可以用典型机组的经验参数。

在 Matlab 里,我建议用一个结构体数组保存所有机组参数,这样后续循环计算非常方便:

unit(1).Pmax = 1000; % MW unit(1).Pmin = 150; % MW unit(1).Pdeep = 240; % 深度调峰门槛,低于此值认为进入深调区间 unit(1).a = 30; % 元/h unit(1).b = 220; % 元/MWh unit(1).c = 0.03; % 元/MW^2h unit(1).coal_price = 800; % 元/吨 unit(1).life_loss_coef = 0.00012; % 深调寿命损耗系数

这里的系数只是示意,实际项目要根据目标机组重新拟合。我建议用历史运行数据做多项式拟合,而不是网上随便抄一组参数。否则你的量化结果可能偏离真实值非常大。

2.2 深度调峰寿命损耗成本建模

深度调峰寿命损耗是量化模型里最有门槛的部分。工程上很难精确复盘每一次调峰到底对转子寿命影响多大,但可以建一个工程近似模型。

我的做法参考了国内很多文献的常用思路:机组在深度调峰运行时,寿命损耗与“调峰深度”相关。定义调峰深度为:

[ d=\frac{P_{max}-P}{P_{max}} ]

机组在额定工况附近运行时,热应力变化不大,损耗可以忽略。当出力低于某个阈值(比如 (P_{deep}=40%P_{max})),损耗成本按指数或二次函数上升。简化公式:

[ C_{life,i}(P)=\lambda_i \cdot \left(\frac{P_{ref}-P}{P_{ref}}\right)^2 \cdot C_{unit,i} ]

其中 (\lambda_i) 是寿命损耗折算系数,(C_{unit,i}) 是机组单位容量造价,(P_{ref}) 是参考出力,一般取经济出力。在 Matlab 里这种函数写起来没有难度,但要注意:当 (P) 大于 (P_{ref}) 时,这个公式会变成负值,需要加判断。

2.3 启停成本与缺调峰惩罚

启停成本可以按单次启动成本乘以启动次数来计算,公式比较简单:

[ C_{startup,i}=C_{hot,i}\cdot N_{hot}+C_{cold,i}\cdot N_{cold} ]

实际算例中,为了简化,我把它折算到启停时段内,每台机组启停一次直接叠加一个固定成本。

缺调峰惩罚则用来量化如果系统调峰能力不够,必须弃风弃光带来的损失。这个值等于:

[ C_{curtail}=VOLL_{re}\cdot E_{curtail} ]

其中 (E_{curtail}) 是弃风弃光电量,(VOLL_{re}) 是新能源损失电量价值单位,可以按当地上网电价或者综合电价估算。这部分不参与火电调峰成本,但在后续分摊中扮演“责任源”角色,因为弃电往往正是因为某个时段新能源出力过高,系统调不动。

2.4 系统总调峰成本怎么汇总

每个时段,系统总调峰成本是所有开机机组在该时段的调峰成本之和:

[ C_{peak}^{total}(t)=\sum_{i \in G_{on}} \left[ C_{fuel,i}(P_{i,t})+C_{life,i}(P_{i,t}) \right]+C_{startup,t}+C_{curtail,t} ]

其中 (G_{on}) 是并网机组集合。这里隐含了一个前提:我们需要先通过某种调度策略给出每台机组的实际出力 (P_{i,t})。你可以用优化模型求,也可以直接用运行数据。更多的时候,量化模型的核心工作是根据净负荷曲线和历史调度方式模拟出力分配。

在 Matlab 实现中,我写了一个子函数calcUnitCostByPower(P, unit),输入单机出力和机组参数结构体,输出该机组的调峰成本。主程序循环 24 小时,逐时段逐机组累加即可。

3. 调峰成本分摊模型:怎么分,分给谁

3.1 分摊原则:谁引起、谁受益、谁承担

量化出系统总调峰成本之后,下一步是分摊。分摊机制的设计直接影响各方经济性,不能拍脑袋。我采用的三条基本原则是:

第一,谁引起调峰需求,谁承担主要责任。新能源出力波动导致净负荷峰谷差扩大,这是调峰成本上升的直接原因,所以新能源场站应当承担一部分调峰成本。

第二,谁从调峰中受益,谁承担合理补偿。常规火电提供了调峰服务,用户负荷也因系统稳定而受益,因此负荷侧也需要分摊一部分成本。

第三,分摊结果要具备可计算性、可验证性。不能搞一个黑箱模型,输出结果必须能让各方审计和接受。

在这个原则下,分摊模型设计成“总成本 = 新能源责任部分 + 负荷责任部分”,并且两部分可以再细分到每个场站或每个用户。项目里我重点实现了新能源场站内的分摊,因为这是高比例可再生能源场景下最紧迫的问题。

3.2 基于调节责任系数的分摊方法

对新能源场站进行成本分摊时,我采用“多指标责任系数法”。不搞复杂的合作博弈算法,因为实际工程项目中数据可获得性有限,而且参与方希望逻辑透明。责任系数由三部分组成:

[ \omega_j=\alpha\cdot \frac{\sigma_j}{\sum_{k}\sigma_k} +\beta\cdot \frac{r_j}{\sum_{k}r_k} +\gamma\cdot \frac{E_{curt,j}}{\sum_{k}E_{curt,k}} ]

其中:

  • (\sigma_j) 是新能源场站 (j) 的出力标准差,反映出力波动程度;
  • (r_j) 是最大爬坡速率,反映出力骤升骤降的威胁;
  • (E_{curt,j}) 是场站弃电量,反映抢占调峰空间的程度;
  • (\alpha, \beta, \gamma) 是权重系数,三者之和为1。

这个公式的思想很直白:波动越大、爬坡越快、挤占系统调节空间越多的场站,应该承担更多调峰成本。权重系数的设置可以基于实际场景调整,我一般在算例里设为 0.4、0.4、0.2,并在结果里做敏感性分析。

Matlab 实现这个逻辑非常简单。先计算总调峰成本C_total_sum,再算各场站的权重weight,最后分摊到各场站:

sigma = std(power_wind); % 各场站出力标准差 ramp = max(abs(diff(power_wind))); % 各场站最大爬坡 curtail = curt_energy; % 各场站弃电量 w1 = sigma / sum(sigma); w2 = ramp / sum(ramp); w3 = curtail / sum(curtail); weight = alpha * w1 + beta * w2 + gamma * w3; C_alloc_j = C_total_sum * weight;

用这个模型跑出来的结果,不同场站分摊成本差距会很明显。出力平稳的场站分摊少,波动剧烈的场站分摊多,整体合理性比较高。

3.3 负荷侧分摊与双向调节逻辑

光给新能源分摊还不完整。负荷侧的峰谷特性也在影响调峰成本,尤其是一些峰谷差大的工业负荷。实际项目里,我通常把总调峰成本拆成“新能源驱动部分”和“负荷驱动部分”。

怎么拆?一个实用做法是“基准情景对比法”:先计算含新能源的净负荷峰谷差,再计算一个移除新能源后的负荷峰谷差,两者差值所对应的调峰成本增量,由新能源侧承担;剩下部分由负荷侧按峰谷电量比例分摊。

[ \Delta V = V_{net}^{withRES} - V_{load}^{withoutRES} ]

如果 (\Delta V) 大于零,说明新能源加剧了系统调峰压力,这部分增量成本就是新能源的责任,然后交给上文的场站责任系数模型继续细分。如果 (\Delta V) 小于零,说明新能源在某些时段起到了削峰作用,这时甚至可以产生“负调峰成本”,应该给新能源补偿。

这个双向逻辑非常重要。很多模型只做“新能源一定增加调峰成本”的单向假设,结果在光伏渗透率高的午间,负荷低谷时反而算出了不合理的巨额成本。采用基准情景对比法后,结果会真实很多。

4. Matlab 实现:从数据准备到结果输出

4.1 总体代码结构设计

这个模型的代码不复杂,但数据流要理清。我在项目中按模块化方式组织,分四层:

  • 数据层:读取负荷、风电、光伏、机组参数,做数据预处理;
  • 计算层:调峰需求计算、单机成本计算、总成本累计;
  • 分摊层:责任系数计算、新能源/负荷分摊;
  • 输出层:表格、曲线、结果文件。

主程序大概长这样:

% 读取数据 [load_curve, wind_curve, pv_curve] = load_data('case_data.xlsx'); % 净负荷 net_load = load_curve - wind_curve - pv_curve; % 调峰需求 peak_shaving_req = net_load - min(net_load); % 量化成本 C_total = zeros(size(net_load)); for t = 1:length(net_load) C_total(t) = calc_system_cost(t, net_load(t), unit_list); end % 分摊 alloc_result = allocate_cost(C_total, wind_farm, pv_farm); plot_result(net_load, C_total, alloc_result);

实际项目里,我建议把输入数据统一放到一个 Excel 文件或.mat文件中,避免代码里硬编码数据,这样换一个算例只需要改数据文件,代码不用动。

4.2 数据读取与清洗:注意时间粒度和缺失值

时间粒度是个容易被忽略的坑。用 15 分钟数据算出来的调峰成本和用 1 小时数据算出来,结果差异很大。原因很简单:爬坡事件往往发生在 15 分钟甚至更短的时间尺度里,按小时平均后尖峰被抹平了,调峰需求被低估。

我的建议是,如果条件允许,至少用 15 分钟分辨率的数据。如果只能用小时数据,在报告里要明确说明时间粒度差异,不能把小时数据的结果跟 15 分钟数据的结果直接对比。

数据清洗方面,新能源出力数据经常出现零值、空值、明显错误值。我一般在读取后先做这样几步:

% 用上一个有效值填充缺失 data = fillmissing(data, 'previous'); % 限制负值归零 data(data < 0) = 0; % 超过装机的数据按装机截断 data(data > capacity) = capacity;

这几行代码能避免很多后面计算的“灵异”结果。

4.3 成本计算核心函数

单机调峰成本函数是整个模型的核心。我把calc_system_cost设计成接受净负荷和机组列表,先做简单的经济调度分配,再算成本。为了避免优化工具箱带来的复杂依赖,我直接采用“等微增率原则”分配负荷,这是传统调度经典方法,对调峰成本量化足够用。

核心函数片段:

function C = calcUnitCost(P, u) % 煤耗成本 C_fuel = u.a + u.b * P + u.c * P^2; % 深度调峰寿命损耗:P低于Pdeep时开始计入 C_life = 0; if P < u.Pdeep d = (u.Pdeep - P) / u.Pdeep; C_life = u.life_loss_coef * d^2 * u.unit_capacity_cost; end % 启停成本(此处简化为单时段固定值) C_startup = 0; % 由主程序单独叠加 C = C_fuel + C_life + C_startup; end

为了让结果单位统一,建议所有成本都用“元/h”。这样最后算出来,某一时段的系统调峰成本就是所有机组该小时成本之和,再乘以时间跨度就能得到日调峰成本。

4.4 结果输出:表格、曲线和敏感性分析

跑完模型后,输出是重中之重。我用 Matlab 的writetable把结果导出成 CSV,方便 Excel 进一步处理。同时画三种图:净负荷曲线、调峰成本时段分布柱状图、各场站分摊结果饼图。

画净负荷曲线建议用tiledlayout,同时叠加负荷、新能源出力和净负荷三条线。调峰成本柱状图能非常直观地看出哪个时段调峰压力最大,我现在这个算例里,晚高峰前两小时和凌晨低谷期是最贵的两个时段。

敏感性分析我习惯固定其他参数,单独改变新能源渗透率,看总调峰成本怎么变化。这是验证模型合理性的重要手段,如果渗透率上升、调峰成本反而下降,那多半是净负荷计算或者成本函数设置有 bug。

5. 算例演示:一个典型日的调峰成本与分摊结果

5.1 算例系统说明

为了验证代码,我构造了一个简化算例。系统包含:2 台 1000MW 火电、1 台 600MW 火电、总装机 1500MW 的风电场(分为 3 个场站)、总装机 800MW 的光伏电站。负荷数据取自典型夏季日,风电数据用了随机生成但符合出力规律的曲线。

时间分辨率为 1 小时,共 24 个时段。先计算净负荷,再量化调峰成本。

我挑几个关键时段列在下面:

时段负荷(MW)风电(MW)光伏(MW)净负荷(MW)系统调峰成本(万元/h)
02:00480018000300018.5
07:0052001200100390012.2
11:00750080070060005.6
14:00730060075059506.1
19:0092004005087503.8
22:0080001000070008.9

可以看出,凌晨 2 点净负荷最小,系统调峰成本最高,达到 18.5 万元/h。中午光伏出力高,净负荷反而不太高,调峰成本相对低。到晚上 19 点负荷高但净负荷高,火电基本都在高负荷运行,调峰压力小,成本低。

这说明调峰成本跟“负荷大小”不直接相关,而是跟“净负荷相对最小值的大小”相关。只要净负荷被压得越低,机组深调越狠,成本越高。

5.2 新能源场站分摊结果

把全天 24 小时总调峰成本累加,大约 280 万元。按照责任系数法,三个风电场和一个光伏电站分摊结果如下:

场站装机(MW)出力标准差(MW)最大爬坡(MW/h)分摊成本(万元)
风电场A50032026092
风电场B600410340118
风电场C40018015038
光伏电站80042048032

看到没,光伏电站出力标准差挺大、爬坡也最猛,但分摊反而少,因为它的总调峰责任里有一部分被午间削峰抵消了。这就是基准情景法的效果。如果只按波动性分摊,不考虑净负荷峰谷差变化,光伏电站一定被高估。

这个算例说明,分摊模型不能只看单一指标。我在第一次实现时只用了出力标准差,结果光伏分摊占比高得离谱,后来加入“对净负荷峰谷差的贡献”修正,才合理。

5.3 结果合理性验证

模型跑完,我会做三个验证:

第一个,把总调峰成本除以新能源总发电量,得到“单位新能源电量调峰成本”。这个数字是否在合理区间,可以用来判断模型量级。我的算例是 280 万元 / 5000 MWh = 0.56 元/kWh,偏高了一点,但考虑到一天内深调时段多,也算正常。

第二个,观察调峰成本曲线与净负荷曲线的相关性。正常情况下,净负荷越低、调峰成本越高,两者应呈负相关。如果出现正相关,基本是机组出力分配写错了。

第三个,随机改变一个新能源场站出力曲线,看分摊成本是否朝预期方向变化。如果某场站出力波动加大,分摊成本必须上升,否则责任系数计算有 bug。

6. 常见问题与排查技巧

6.1 数据问题:负荷和新能源数据不同步

这是我碰到最多的问题。负荷数据来自调度系统,新能源数据来自场站监控,两者时间戳可能不对齐。有的差半小时,有的差一小时,直接做净负荷计算会得到极其离谱的峰谷值。

排查方法很简单:画一条双 y 轴曲线,同时画负荷和新能源,肉眼检查峰值是否对齐。如果不对齐,就需要重采样。我最常用的做法是用retime函数统一到标准时刻,如果数据没有明确时间戳,至少要做插值对齐。

6.2 成本函数出现负值

有时候算出来某时段总调峰成本是负数,别急着怀疑模型的物理意义。最常见原因是二次函数系数设置不当。二次函数在出力很低时不一定会单调减小,反而可能因为常数项太大而出现负成本。

我采用的处理办法是,在calcUnitCost函数里加一个下限保护:

C_fuel = max(C_fuel, 0);

虽然这有点“物理修正”的味道,但在工程模型里很实用。更重要的是,要先用实际机组数据拟合系数,避免出现这种异常。

6.3 Matlab 版本兼容性问题

这个模型里用到的函数有fillmissingtiledlayoutretime,这些在 R2019b 之后才有,老版本会直接报错。如果你还在用 R2016 这种老版本,就需要改用interp1subplotdatevec那套方案。

我建议在代码开头加一个版本检查:

if verLessThan('matlab', 'R2019b') error('请使用R2019b及以上版本运行本模型'); end

省得换了电脑才发现跑不了。

6.4 计算速度慢:向量化替代循环

24 时段、几十台机组的计算量,用 for 循环其实也不慢。但如果你要扩展成全年 8760 小时、上百台机组,循环就吃力了。我的经验是,凡是能向量化的地方都向量化。

比如计算所有时段净负荷平均值,用:

net_load = load_curve - wind_curve - pv_curve; % 自动向量化 avg_net = mean(net_load, 1);

比显式循环快非常多。对于需要逐台机组计算成本的场景,可以用数组操作替代结构体循环,但结构体在调试时更友好。我建议先用结构体把逻辑调通,再考虑性能优化。

最后再分享一点经验

把这个模型从算法设计到 Matlab 代码落地,我最深的体会是,调峰成本量化的难点不在公式,而在参数和数据。公式的书本上都有,但一组靠得住的机组煤耗系数、一套对齐的高质量新能源出力数据,才是决定模型结果可信度的关键。

另外,分摊模型的“公平性”没有唯一答案。你选择不同的责任系数权重,结果可以相差很大。所以我在项目里都会做敏感性分析,明确告诉使用方:当前结果使用的是什么权重、不同权重下结果怎么变,而不是甩出一个看起来很精确的数字。

如果你准备把模型扩展到实时运行,建议加入机组爬坡约束和备用约束,用linprogquadprog替换等微增率分配方法。这样模型会更接近真实调度,调峰成本量化也会更严谨。但那是另一个项目的事了,先把这个版本跑通,你已经有了一张能用的底图。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询