考虑一次与二次调频及机组差异的风光水火储双目标动态调度
2026/9/8 7:09:16 网站建设 项目流程

1. 动态调度的核心思路:为什么传统模型搞不定新型电力系统

先把这个题目拆开看。“考虑一次调频与二次调频及机组差异化特性的风光水火储双目标动态调度研究”,这里面其实叠了四层要求,一层比一层接近工程实际。

第一层是“风光水火储”多能源协调,这是当前电力系统调度的基本盘。风光大规模接入之后,系统的净负荷波动远比以前剧烈,单靠火电或者水电去扛已经扛不住了,必须把储能也拉进来一起参与调节。

第二层是“一次调频与二次调频”。常规的调度模型一般只做经济分配,或者只考虑旋转备用容量够不够,把调频需求粗暴地折算成一个固定备用约束。但实际系统里,一次调频是秒级响应、靠调速器动作,二次调频是分钟级响应、靠AGC指令,这两者的时间尺度、调节成本、调用方式完全不同,如果调度模型把它们混在一起处理,算出来的方案在真正运行的时候是要出问题的。

第三层是“机组差异化特性”。这个往往是被忽略的一块。同样是火电,亚临界机组和超超临界机组的爬坡速率、最小技术出力、调频响应速度完全不一样;水电机组调节快但受来水约束;储能响应快但容量有限;风电场和光伏电站的调节能力又受气象条件影响。不同机组在调频过程中的响应行为不一样,但很多研究为了简化,把所有机组都当成“一个能出力、有爬坡限制的抽象电源”来处理,这样出来的结果在工程上意义很小。

第四层是“双目标动态调度”。双目标问题在于,经济性和调频性能往往存在冲突。一味压低运行成本,可能造成调频资源不足,频率质量变差;一味追求调频性能,又会让运行成本大幅上升。动态调度则意味着这不是一个单时段的静态优化问题,而是要在一个调度周期内,考虑负荷变化、新能源出力的时序特征,逐时段做决策,并且时段之间存在耦合,比如火电的爬坡不能瞬间完成、储能的荷电状态要前后衔接。

四层要求叠在一起,整个问题的复杂度就上来了。传统上把这些问题分开处理的办法,在新型电力系统里已经走不通了,这就是这个课题的现实价值所在。

2. 一次调频与二次调频在调度模型中的数学表达

要在调度模型里把一次调频和二次调频“考虑进去”,不能只是嘴上说“预留备用容量”,得有具体的数学表达方式。这是整个建模的第一步,也是后续代码实现的地基。

2.1 一次调频的建模方式

一次调频是机组调速系统的自动响应,特点是响应快(秒级)、持续短、无差调节。当系统频率偏离额定值时,各机组根据自身的调差系数自动调整出力,在几秒到十几秒内做出反应,用来阻止频率继续恶化。

在调度模型里,一次调频的需求通常转化为“频率响应备用容量”约束。工程上常用的是按系统最大功率缺额的一定比例来设定,或者直接指定为系统总容量的一定百分比。这个约束可以写成:

[ \sum_{i} R_{i}^{PFR} \ge R_{PFR}^{req} ]

其中 (R_{i}^{PFR}) 是机组i提供的一次调频备用容量,由机组的调速器死区、调差系数和最大调节速率共同决定。不同机组的 (R_{i}^{PFR}) 上限不同,这就在模型里引入了机组差异化特性。

实现过程中有个细节:一次调频备用虽然和有功出力共享同一个容量空间,但调用时间是秒级,所以它不太受爬坡约束的限制,只需要考虑机组当前运行点是否支持快速增减出力。这个特性在约束建模时一定要体现出来,否则后续优化可能会产出一个在物理上无法实现的结果。

2.2 二次调频的建模方式

二次调频是AGC(自动发电控制)系统通过调整调度设定点实现的频率恢复控制,时间尺度是分钟级。它负责消除频率偏差和联络线功率偏差,让频率回到额定值。

二次调频在调度模型中对应的是AGC调节容量约束。通常需要区分上调和下调两个方向,因为机组的上调能力和下调能力可能不对称。约束形式为:

[ \sum_{i} R_{i}^{AGC,up} \ge R_{AGC}^{req,up},\quad \sum_{i} R_{i}^{AGC,down} \ge R_{AGC}^{req,down} ]

二次调频备用受爬坡约束影响很大,因为AGC调节是分钟级的,机组必须在几分钟内完成指定量的功率调整。所以 (R_{i}^{AGC,up}) 的实际可用值,取决于机组当前出力与最大出力之间的距离,以及爬坡速率给定时的时间窗口。

这里就引入了一个关键技术点:二次调频备用不是一个静态值,它随机组运行点变化,需要在模型中用变量来表示,本质上是一个耦合了出力与备用的复杂可行域刻画问题。

2.3 一次和二次调频的时间尺度配合

两个调频过程在时间上是接力的关系。一次调频响应频率变化但无法消除稳态偏差,二次调频随后介入消除偏差并释放一次调频备用,让系统回到额定频率状态。

在调度模型里,这种时间尺度配合表现为不同时段约束之间的关系。更合理的建模是要设定两阶段的备用需求,比如在发生功率缺额后的10秒内,需要多少一次调频容量;在随后的5到10分钟内,需要多少二次调频容量。这样分层建模,才能真实反映系统频率恢复过程的资源需求。

这个点做完之后,模型已经从“一个简单的经济调度”进化成了“一个同时考虑稳态平衡和动态频率支撑的多时间尺度资源分配问题”。这是整个研究的第一个核心难点,也是区别于普通经济调度的分水岭。

3. 机组差异化特性:如何把“每台机组都不一样”这件事写进模型

做电力系统研究的人容易陷入一个误区:把所有火电看成一类,所有水电看成一类,然后在模型里用一套参数代表一类机组。这在早期的电力系统里误差还能接受,但在风光占比持续提升、系统转动惯量不断下降的今天,这种做法已经不可靠了。

3.1 不同电源的调频特性对照

先整理一张对照表,把五种电源的调频特性放在一起看:

电源类型一次调频响应速度二次调频调节速率调节范围关键约束
燃煤火电中等(3~8s)慢(1%~3%/min)50%~100%额定功率爬坡率、最小技术出力、锅炉动态
水电机组快(1~2s)快(10%/min以上)宽广来水量、水头、振动区
风电场取决于控制策略可实现但受风速限制受可用功率约束风速波动、桨距角控制
光伏电站快(电力电子响应ms级)快但损失发电量只能向下调节光照强度、弃光代价
储能系统极快(ms级)极快取决于剩余容量与功率SOC约束、充放电寿命

这张表是建模的基础。每一种电源的差异化约束都要写进模型里,不能统一当作“可调电源”来对待。

比如储能,它的特点是响应极快,但能量有限。如果调度模型不区分一次和二次调频,把储能的一次调频容量和二次调频容量都设到额定功率,那在连续多个扰动发生后,储能的SOC会很快耗尽,后续时段就丧失了调频能力。这个行为必须在约束里体现:一次和二次调频备用共用同一个功率容量,同时受SOC限制,不能同时承诺全部的调频容量。

3.2 火电的深度调峰与最小技术出力

火电的差异化特性中最关键的是最小技术出力。常规模式下的火电最小出力一般在40%~50%额定功率,但通过灵活性改造后可以达到20%~30%。这个参数直接影响系统的新能源消纳能力:新能源大发时,如果火电压不下去,只能弃风弃光。

在调度模型里,最小技术出力约束是非线性的,因为一旦机组启停状态确定,输出功率必须落在最小技术出力与最大出力之间。这就是一个带有0-1变量的混合整数约束。如果不考虑灵活性改造,只按常规最小值建模,会低估系统的新能源消纳能力,调度结果偏保守。

3.3 水电机组的运行约束处理

水电机组虽然调节性能好,但有严格的水力约束。在短期调度中,通常不考虑水量平衡的动态过程,而是给每个时段设定一个可调功率上限,这个上限取决于当前的水头和机组可用台数。更精细的建模还会加入振动区约束——某些出力区间内水力振动剧烈,不允许机组长时间运行。

水电机组的振动区约束是典型的非凸约束,把原本连续的可行域切成多段。处理方式一般有两种:一是把振动区建模成禁止区间,用大M法引入整数变量;二是对功率进行分段线性化处理。两种方法在Matlab实现中都有成熟方案,后者的计算效率更高,适合用于长时间尺度的动态调度问题。

4. 双目标模型的建立:经济性目标与频率质量目标的博弈

双目标优化是整个研究的核心。目标函数怎么设计、两个目标之间怎么权衡、用哪种多目标求解策略,直接决定模型能回答什么问题。

4.1 目标一:系统运行综合成本最小

第一个目标函数是系统运行总成本最低,包括以下几部分:

  • 火电燃料成本
  • 机组启停成本
  • 储能充放电损耗成本
  • 弃风弃光惩罚成本
  • 一次/二次调频备用容量购买成本

火电燃料成本通常表示为一个二次函数:

[ C_i(P_i) = a_i P_i^2 + b_i P_i + c_i ]

由于二次函数会带来非线性求解困难,工程实现中一般用分段线性化(PWL)来近似。分段数取3左右就能获得足够的精度,计算速度大幅提升。

备用容量购买成本是“考虑调频”的直接体现。在电力市场中,调频备用需要单独购买,价格通常高于电量价格。在调度模型中设置这部分成本,可以自然地在经济性和调频性能之间形成权衡:如果系统要求更高的调频备用,成本就会上升,优化器会在满足最低要求和成本之间寻找平衡。

4.2 目标二:调频性能指标最优

第二个目标函数要量化调频性能。常用的做法是定义一个频率偏差指数,或者定义一个综合调频性能指标。一个实用的指标设计如下:

[ J_{FR} = \sum_{t} \left( |\Delta f_t| + \alpha \cdot P_{AGC,t}^{needed} \right) ]

其中 (\Delta f_t) 是时段t的预计频率偏差,(P_{AGC,t}^{needed}) 是该时段预计需要的AGC调整量。这个指标综合反映了频率质量和调节压力。

在动态调度框架下,频率偏差的计算依赖系统惯量、负荷波动方差、一次调频响应特性等因素。由于这些参数随时间变化(例如风电波动率夜间大白天小),所以 (\Delta f_t) 实际上是动态变化的,这又进一步体现了“动态调度”的必要性。

4.3 双目标处理策略:NSGA-II还是加权求和

双目标处理有两种主流方案:

第一种是加权求和法,把两个目标加权合并成一个单目标。优点是实现简单、求解快速,缺点是权重选择主观,且对Pareto前沿的非凸区段无法搜索到完整的解集。

第二种是NSGA-II等多目标进化算法,直接求解Pareto前沿,给决策者提供一组非支配解。优点是信息量大,缺点是在约束复杂、决策变量多的情况下收敛慢,且早熟问题严重。

我在实际项目中,面对这个具体问题时更推荐混合策略:先跑一轮NSGA-II或者MOPSO获取Pareto前沿,观察两个目标的量级关系,然后根据管理者的偏好,选出几个有代表性的点,用精确求解器再精算一次。这样既利用了进化算法的全局搜索能力,又保证了最终解的精度和可解释性。

5. Matlab代码实现:架构设计与关键函数逻辑

代码是整个研究落地的关键环节。很多人在建模阶段思路很清楚,一到写代码就卡住,往往是因为没有提前规划代码架构。这里分享一个经过验证的代码组织方式。

5.1 代码整体架构

整个项目按功能拆分为五个模块:

  • 数据输入模块:机组参数、负荷曲线、新能源出力数据、调频需求曲线
  • 模型构建模块:约束矩阵生成、目标函数构建
  • 优化求解模块:调用优化求解器
  • 结果分析模块:Pareto前沿绘图、调度结果可视化
  • 场景生成模块:不同新能源渗透率、不同负荷波动场景

这种架构的核心思想是数据与模型分离、模型与算法分离。改参数不用动代码,换算法不用动模型,调试和维护都非常方便。

推荐用Matlab的struct来组织机组数据。把每类电源定义成独立的一个结构体数组,每个元素是同一类电源的不同机组实例,字段包括额定功率、最小技术出力、爬坡率、燃料成本系数、调频备用上限等。这样做的好处是后续在约束构建时可以直接用arrayfun或者循环遍历,逻辑清晰,不易出错。

5.2 基于YALMIP的模型构建

对于这个规模的优化问题,强烈建议用YALMIP工具箱建模,而不是手写矩阵。YALMIP的好处是把优化模型写成自然语法,可读性强,且支持无缝切换不同的底层求解器。

核心的模型构建代码框架如下:

% 决策变量定义 P_gen = sdpvar(n_gen, T); % 常规机组出力 P_sto = sdpvar(n_sto, T); % 储能功率(正为放电) SOC = sdpvar(n_sto, T); % 储能荷电状态 R_pfr = sdpvar(n_gen, T); % 一次调频备用 R_agc = sdpvar(n_gen, T); % 二次调频备用 u = binvar(n_gen, T); % 机组启停状态 % 约束条件集合 Constraints = []; % 功率平衡约束 for t = 1:T Constraints = [Constraints, sum(P_gen(:,t)) + sum(P_sto(:,t)) + P_wind(t) + P_pv(t) == P_load(t)]; end % 火电机组出力与备用耦合约束 for i = 1:n_thermal for t = 1:T Constraints = [Constraints, P_gen(i,t) + R_pfr(i,t) + R_agc(i,t) <= P_max(i) * u(i,t)]; Constraints = [Constraints, P_gen(i,t) - R_agc(i,t) >= P_min(i) * u(i,t)]; end end % 储能SOC递推 for j = 1:n_sto for t = 2:T Constraints = [Constraints, SOC(j,t) == SOC(j,t-1) - P_sto(j,t) * delta_t / Cap(j)]; end end % 定义目标函数 Objective = sum(sum(fuel_cost(P_gen))) + ... sum(sum(reserve_cost(R_pfr + R_agc))) + ... sum(penalty_wind);

这份框架代码有几点值得专门说明。

功率平衡约束是整个模型的骨架,但在动态调度中要注意,储能、风电、光伏的出力在时段间不是独立的。风电和光伏由场景数据给定,储能SOC的递推关系把相邻时段连接了起来。

火电出力与备用的耦合约束是“差异化特性”的核心体现。机组的最大出力限制了它能同时提供的能量和备用的总和。最小出力约束则保证机组不会运行在技术不可行区间。爬坡约束如果被忽略,优化结果可能在调度过程中从100MW瞬间跳到300MW,这在物理上不可能实现。完整的模型必须加上:

Constraints = [Constraints, P_gen(i,t) - P_gen(i,t-1) <= Ramp_up(i)]; Constraints = [Constraints, P_gen(i,t-1) - P_gen(i,t) <= Ramp_down(i)];

储能SOC的递推公式要特别注意符号约定。如果P_sto为正表示放电,那么SOC会下降,公式里就是减号。如果搞反了符号,仿真曲线看起来没问题,但实际物理逻辑完全错误,这种bug特别隐蔽。

5.3 双目标求解的Matlab实现

双目标求解的NSGA-II实现可以直接基于Matlab全局优化工具箱的gamultiobj函数,也可以自己实现一个简版NSGA-II。

gamultiobj时有个关键经验:约束条件的处理。gamultiobj默认支持的约束比较有限,对于大量线性约束的建议是把约束矩阵传入而非写成非线性约束函数。这样可以显著提高求解效率。

如果问题规模大、gamultiobj收敛慢,可以考虑用MOPSO(多目标粒子群)实现。粒子群算法对连续决策变量的问题搜索效率更高,但处理大量0-1整数变量时有些吃力。

我的建议是:决策变量里如果有启停状态的整数变量,优先用gamultiobj配合intcon;如果全部是连续变量(比如固定机组启停方案,只优化各时段出力),MOPSO的效果会好很多。实际研究流程中,通常是先固定机组组合,用连续优化算潮流分布,再在几个候选组合之间做比较。

6. 场景构建与算例验证:怎么设计实验才能说明问题

模型和代码都有了,最关键的一步是设计算例来验证模型的有效性。很多论文的算例做得不充分,评审意见里常出现“缺乏说服力”的评语,大多是因为场景设计没有抓住问题的核心矛盾。

6.1 场景设计原则

核心原则只有一条:形成对比。要有“不采用所提方法”的基准对照组,和“采用所提方法”的实验组。具体到这个课题,至少要有以下对比:

  • 基准模型:没有考虑机组差异化特性,所有机组用平均参数
  • 只考虑一次调频的模型:未区分一次/二次调频的时间尺度差异
  • 只考虑二次调频的模型:忽略了一次调频对紧急频率响应的支撑
  • 完整模型:同时考虑一次与二次调频,机组差异化特性全覆盖

四种场景跑出来,对比系统运行总成本和调频性能指标,就能清楚看到每个约束条件对结果的影响程度。

6.2 参数设置与数据选择

参数设置要贴近实际。火电的爬坡率一般取额定功率的1.5%~3%每分钟,最小技术出力取40%(常规)或30%(灵活性改造后),储能充电效率取0.9~0.95,放电效率略高。

负荷数据选择上尽量用IEEE标准节点系统的公开数据,或者在确保脱敏的前提下,使用某个微网/区域电网的真实负荷曲线。时间分辨率选择1小时还是15分钟,直接决定T的大小和问题规模。15分钟分辨率能更好地体现调频需求的变化,但计算量会增大4倍。

新能源出力数据的处理也要认真。一个常见的坑是直接把全年风电数据拿来用,不做平滑处理,结果优化器被极端波动牵着走,调度结果不稳定。合理的做法是先做聚类,提取典型日场景,再辅以极端场景检验模型的鲁棒性。

6.3 结果分析怎么做才有价值

算例结果的呈现和分析,最能体现研究者对这个问题的理解深度。

首先看Pareto前沿形态。理想的边界应该是一条凸曲线,说明两个目标存在明显的折中关系。如果边界是一条水平线,说明两个目标实际上没有冲突,这时候要回头检查目标函数的设计是否合理。

其次做决策变量的敏感性分析。一个非常有效的方法是画出一组关键时段的最优机组出力与备用分配饼图,直观展示不同类型机组在调频资源配置中的角色分工。实际案例中,通常会看到火电承担大部分二次调频容量、储能承担绝大部分一次调频容量、水电随机性补充的格局。这个结果本身就很有说服力。

最后一定要做对比表格。把基准模型和完整模型在总成本、调频性能、新能源消纳率等指标上的差异列出来,用数据说话。

7. 代码调试与工程化落地中的常见坑

Matlab实现电力系统优化调度时,有几个问题是大家反复踩的,这里集中整理一下,能帮你节省大量调试时间。

7.1 YALMIP报错与求解器选择

YALMIP本身是个建模语言,真正求解靠的是底层solver。这个课题涉及的模型是混合整数二次规划(MIQP)或者混合整数线性规划(MILP),如果目标函数中对成本做了分段线性化处理、不含二次项,那么用MILP求解器即可。

如果用gurobicplex,注意需要先安装相应的Matlab接口。免费的备选方案是intlinprog(Matlab自带),处理中等规模的MILP问题没有问题。模型规模比较大的话,可能会遇到“Out of memory”错误。我的经验是把决策变量分开定义,不要全部放到一个超大矩阵里,能显著减少内存占用。

另一个常见问题是YALMIP报“Unable to prove infeasibility”或者求解器返回NaN。90%的情况是约束写错了——要么是某个变量的维度对不上,要么是某个约束条件过于严格导致没有可行解。排查方法是逐个注释掉约束组,看问题出在哪一组,这个基本功比任何调试技巧都重要。

7.2 求解结果不收敛怎么办

gamultiobj不收敛是高频问题。处理办法有以下几个:

第一,增加种群规模和迭代代数。默认参数偏小,对于这个规模的问题建议把种群规模调到100以上。

第二,引入约束违规惩罚。如果约束处理不当,算法会在不可行区域里浪费时间,收敛很慢。gamultiobj能处理线性约束,但非线性约束如果过多,建议转成惩罚项加入目标函数。

第三,缩小搜索空间。决策变量的上下界设得越紧,搜索效率越高。火电出力上下界、储能功率上下界这些边界条件一定要给定,不要依赖求解器自己去搜。

7.3 运行速度优化

两方面的建议。一是模型层面,尽量减少整数变量数量,比如启停状态变量只在需要时才引入,能缩短求解时间数倍。二是代码层面,避免在for循环中反复定义变量和约束,尽量把约束写成矩阵向量化形式。

一个非常有效的小技巧是:先跑一个24小时、1小时间隔的简化版本验证模型正确性,再跑完整的15分钟间隔版本。如果简化版本的结果都不合理,那大概率模型本身有问题,不是求解器的问题。

8. 一些经验体会

这个课题做完之后,我的整体感受是:真正的难点不在数学建模本身,而在把所有约束条件物理意义搞清楚之后,怎么在代码里把它们用编程语言精确无误地写出来。这个转化过程是最耗时间的。

Mulit-objective动态调度和单目标静态调度的求解体验差别巨大。静态调度只需要求解一个单时段的资源分配问题,而动态调度要考虑上百个时段之间的耦合,时间维度的引入让模型规模成倍增长。这也是为什么很多文章只做24小时、每小时一个点,因为更细的时间分辨率会带来巨大的计算负担。

关于调频的建模,再补充一个实操经验。很多论文把调频备用简化成一个固定比例,比如“预留总负荷的5%作为调频备用”。当你把这个约束写进模型后会发现,真正的瓶颈往往出现在风光同时不出力的时段。如果此时火电都已经压到最小出力,根本无法提供足够的向上调频容量。这时候要么引入储能充电来腾出空间,要么把部分火电运行点提高。但这些代价都会反映在目标函数里,优化器会自己权衡。这正是这个模型的魅力所在——通过目标函数驱动,让系统自动找到最优的资源分配方案,而不是靠人工拍脑袋预设。

最后再分享一个实用技巧:在结果分析时,不要只关注优化值和Pareto前沿,务必要回代验证所有约束条件的满足情况。我遇到过很多次情况,优化结果数值看起来很好,但某台机组的出力序列在相邻时段跳变幅度远超爬坡速率限制,或者储能的SOC在某时段突破了上下限。这些物理约束在编码时的疏漏,往往只有在结果回代检查时才能暴露出来。养成每次跑完算例都做约束校验的习惯,能让你的研究工作质量提升一个档次。

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

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

立即咨询