含风电光伏与光热电站的N-k安全校核经济调度Matlab建模
发布时间:2026/9/28 15:04:53来源:尧图网络
做电力系统日前调度方案的时候我经常遇到一种尴尬经济性最优的机组组合结果在N-k预想事故校核里一摆直接越限。比如风电光伏大发的时候某条重载联络线一跳潮流瞬间转移到另一条线上那条线也跟着报警。这就是典型的经济调度没考虑安全校核问题。我自己折腾了一个含风电、光伏和光热电站的电力系统N-k安全优化调度模型用Matlab实现前后跑了几个算例今天把建模思路、代码结构和踩坑过程完整捋一遍给准备做新能源电力系统调度优化的朋友参考。这个模型解决的核心问题其实很简单在保证N-k安全的前提下让运行成本最低同时尽量消纳风电和光伏。光热电站不是普通的新能源它带储热可以白天储热晚上发电是可调度的灵活性资源所以模型里它承担的角色和火电很像但约束又完全不同。整个实现是基于MatlabYalmipCplex这一套工具链属于目前学术界和工程界最常用的方案组合下面一步一步拆开讲。1. 先搞清楚模型边界你要优化的是什么1.1 多能互补系统的核心矛盾高比例新能源电力系统的调度问题表面上是怎么分配出力本质上是如何在不确定性和事故风险下找到可执行的运行方案。风电和光伏出力波动大且不可精确预测如果调度方案只盯住成本很可能在某个时段让所有机组都挤在几条通道上送电一旦其中一条通道跳闸剩余通道立刻越限系统就得切负荷。这个风险在传统火电为主的系统里也存在但新能源大发时更突出因为风电光伏出力往往集中在特定区域外送通道压力很大。光热电站CSP聚光太阳能热发电在这个系统里是比较特殊的一环。它先通过镜场收集太阳热能存在熔盐储热罐里再按需释放热量驱动汽轮机发电。所以它既能像风电光伏一样提供清洁电力又能像火电一样在一定范围内调节出力。加入光热电站后系统的可调度资源变多了削峰填谷能力更强但储热罐的充放热时序约束也让模型复杂了一个档次。1.2 为什么光热电站会成为关键灵活性资源我最早做这个模型时把光热电站简单等价成一个带储能的光伏结果跑出来完全不对。光热电站在电气侧只有一个并网功率但它内部有热传递过程镜场集热功率、储热罐充放热功率、汽轮机热功率三者必须每时每刻满足热平衡。而且汽轮机的出力受最小技术出力限制储热罐也有容量上下限这些约束加进去之后光热电站才能体现出可调度的价值。从实际调度的角度看光热电站在白天将多余热量存入储热罐夜间再放出热量发电本质上是一种跨时段能量转移。这个特性和电池储能有点像但它的效率损失来自储热环节而不是充放电循环。因此在模型目标函数里我会把光热电站的发电成本设为很低但不能为零否则优化结果会强迫它满发反而不符合真实运行逻辑。一般取一个象征性的运行维护成本系数比如每兆瓦时20到30元用于让模型在调度优先级上有明确的排序依据。1.3 安全校核与调度优化的耦合逻辑N-k安全校核的核心思想很直白系统在任意k条线路或机组退出运行后剩下的网络仍然可以安全稳定运行所有线路潮流不越限、电压不越界。放到优化调度模型里就是要对每一个预想事故场景单独列出一组潮流安全约束。模型每生成一个机组组合和出力方案都得让正常情况下和事故情况下同时满足约束这相当于给原问题叠加了一个事故场景影子系统。耦合逻辑是正常运行时的发电出力决定节点注入而节点注入决定事故后潮流分布所以事故约束和正常约束共享同一套决策变量。调度员在申报出力计划时必须同时考虑正常方式和事故方式这就是所谓的安全约束经济调度。如果只做经济调度不做N-k校核很可能得到一个成本很低但不可实施的方案反过来如果所有线路都按最严重事故预留大量裕度成本又会高得离谱。模型要做的就是在这两者之间找平衡点。2. 三类电源出力建模从原始数据到时间序列2.1 风电出力场景生成与缩减风电出力的随机性主要通过场景法处理。我常用的做法是根据历史风速数据拟合Weibull分布再用蒙特卡洛抽样生成大量风速场景然后通过风电功率曲线把风速映射成出力。直接生成几千个场景后优化模型规模会爆炸所以需要做场景缩减。最常用的缩减方法是快速前向选择或者同步回代缩减把1000个场景压缩成10到20个典型场景每个场景带概率权重。场景缩减不能只看长得像还要考虑时序相关性。风电爬坡事件往往跨多个时段如果缩减后的场景把连续爬坡过程切碎调度模型就看不到备用需求高峰。所以缩减时我会把每个场景看成一个完整的24时段向量用wasserstein距离衡量场景之间的距离再挑选代表性场景。这样得到的场景集既保持了统计特性又能被MILP求解器接受。2.2 光伏出力特性与相关性处理光伏出力相对确定主要受辐照度和温度影响但云层遮挡会造成分钟级波动。在日前调度尺度下光伏出力可以用晴空模型乘以云量系数生成也可以用Beta分布描述预测误差。这里要注意的是风电和光伏场景不能独立抽样——同一个气象过程往往同时影响风资源和光资源比如强对流天气会带来大风同时也带来多云。所以生成场景时我会先抽样气象状态再从该状态下分别生成风电和光伏出力保持二者相关性。相关性处理直接影响系统备用需求。如果风电和光伏在高负荷时段同时出力很低系统就需要更多向上备用如果它们同时大发则需要更多向下备用和消纳能力。忽略相关性会让模型低估运行风险得到一个偏乐观的调度方案。简单做法是用Copula函数构建联合分布或者直接基于历史风速辐照度数据的同步采样后者实现更简单在工程上足够用。2.3 光热电站的结构化出力模型光场-储热-汽机光热电站的建模是很多人容易做错的地方。我建议把光热电站拆成三个模块光场、储热罐、汽轮发电机组。光场输出热功率Q_sf正比于太阳直射辐射DNI超过储热和发电需求的部分可以丢弃即集热弃热。储热罐状态用热容量E_t表示充热功率Q_ch和放热功率Q_dis需满足上下限约束同时储热效率与放热效率分别取0.95和0.98左右。汽轮发电机组出力P_csp等于输入热功率Q_tb乘以热电转换效率一般取0.35到0.45具体看光热电站的类型。热平衡方程是每个时段必须满足的约束Q_sf[,t] Q_dis[,t] - Q_ch[,t] Q_tb[,t] Q_dump[,t]等待更准确的写法是Q_sf_t Q_dis_t Q_ch_t Q_tb_t Q_dump_t其中Q_dump表示因储热罐满或汽机出力限制而丢弃的热量。电功率与热功率的关系直接约束为P_csp_t eta_pb * Q_tb_t另外汽轮发电机组有最小技术出力约束比如额定功率的25%有爬坡速率约束比如每分钟不超过额定功率的3%。储热罐容量一般可取汽机满负荷运行6到10小时的热量这个容量大小直接决定光热电站的跨时段调节能力。2.4 不确定性与预测误差的处理方式如果追求更严谨风电和光伏预测误差不能只用场景期望来平均。我通常会在模型中加入旋转备用约束上备用要覆盖正误差实际出力小于预测下备用要覆盖负误差实际出力大于预测备用容量来自常规机组的光热电站和储热系统的剩余调节能力。具体做法是sum(up_reserve_g) up_reserve_csp rho * Pw_forecast rho * Ppv_forecast其中rho取预测误差标准差的一定倍数比如2倍或3倍。这样模型在输出经济调度方案的同时还能自动给出备用预留结果避免新能源预测偏差导致的实际运行越限。这个方法比单纯场景法更容易工程化计算量也小。3. N-k安全约束的数学化转化从枚举到可求解3.1 N-k预想事故集怎么生成N-k里的k不是越大越好。k1是所有单线路故障k2是双回线路同时跳闸或单回线路检修叠加N-1k3以上在输电网中一般只针对同塔双回、同母线等特殊场景逐条筛选。实际建模时预想事故集通常由调度运行部门给定但在论文或测试算例里我会采用两阶段筛选法先对所有线路按历史故障概率和潮流水平排序选出前N条高风险线路再在这些线路之间生成K组合。组合数量增长很快。比如一个118节点系统有180条线路N-2的组合数是180*179/2约1.6万个每个事故跑一次直流潮流还能接受但直接嵌入优化模型每个事故对应一组全线路潮流约束模型规模就非常恐怖了。所以工程上常用约束生成思路先只加N-k关键事故对应的约束求解后检查所有事故场景下是否有越限哪一个事故越限最严重就把对应约束补进模型迭代几轮后就能收敛到满足全部N-k条件的调度方案。3.2 基于直流潮流的线路潮流安全约束在优化调度模型里潮流约束我基本都采用直流潮流模型。交流潮流带无功和电压变量引入三角函数后模型变成非凸非线性和机组组合的0-1整数变量混在一起求解难度会指数级上升而且不能保证全局最优。直流潮流把问题简化为线性约束误差在正常运行方式下通常小于5%对安全校核和机组组合这种大规模优化问题精度足够。直流潮流的核心是节点注入与线路潮流的线性关系。假设系统有N个节点、L条线路线路潮流可以写成P_line PTDF * (P_inj - P_load)其中PTDF是功率传输分布因子矩阵维数是L行N列。正常状态下所有节点注入已知潮流可以直接算出来事故状态下线路拓扑变了PTDF也会变。对每一个预想事故要重新算对应的PTDF矩阵这就是N-k约束数量大的原因。3.3 LODF/PTDF引入后的N-k约束表达如果不想为每个事故重新构建全套PTDF可以用LODF线路开断分布因子来近似事故后潮流。开断线路m之后线路l上的潮流等于正常潮流加上一个转移增量P_l^c P_l^0 LODF_lm * P_m^0其中LODF_lm是线路m开断时对线路l的转移因子由网络拓扑决定与运行点无关。这样N-1事故约束就可以写成-P_l^max P_l^0 LODF_lm * P_m^0 P_l^max在Matlab里直接用稀疏矩阵运算批量生成所有单线路事故的约束效率很高。N-2事故可以用两次LODF叠加也可以直接用事故后的PTDF矩阵重新构建。我实测下来LODF法在N-1和大部分N-2场景下都能准确反映潮流转移只有在重载系统且出现较大相角变化时才有一点点偏差但作为安全校核边界是可以接受的。3.4 模型规模膨胀问题Benders分解与约束生成当k较大或者事故集很大时把所有N-k约束一次性塞进模型Yalmip建模时间长Cplex求解时间更长。我的处理办法是行约束生成Row Generation先不加任何事故约束求出经济调度解然后对每个事故场景验证该解是否安全如果发现某条线路越限就把这条线路对应的N-k潮流约束直接加入主问题重新求解重复迭代直到没有越限发生。实际算例中一般迭代5到8轮就能得到稳定解比一次性加入全部约束快一个数量级。更理论一点的做法是用Benders分解把N-k安全校核作为子问题主问题只包含机组组合和常规约束通过迭代切平面让主问题逐步逼近安全边界。但Benders分解在大规模MILP问题上收敛速度不稳定实现起来也复杂。如果项目周期紧我建议先上约束生成它有足够鲁棒性代码也容易调试。4. 优化调度模型整体框架目标、变量与约束体系4.1 目标函数成本最小与弃电惩罚本模型的目标函数是日前24时段总成本最小包含四个部分常规机组燃料成本、光热电站运维成本、弃风弃光惩罚成本、失负荷惩罚成本。燃料成本用二次函数表示对MILP求解器不友好一般会分段线性化处理。简化版表达式如下min C sum_t sum_g (a_g * P_g,t^2 b_g * P_g,t c_g * u_g,t) sum_t sum_csp (c_csp * P_csp,t) lambda_w * sum_t (Pw_avail,t - Pw_used,t) lambda_pv * sum_t (Ppv_avail,t - Ppv_used,t)弃电惩罚系数lambda不宜设得过高否则模型宁可用高成本机组也不弃电违背物理实际。一般取风电上网电价的0.3到0.5倍也就是每兆瓦时100到200元既能体现消纳优先又不至于强制全部消纳。失负荷惩罚系数则要设得非常高比如每兆瓦时5000到10000元确保正常情况下不会出现切负荷。4.2 决策变量的分层设计决策变量分三层。第一层是0-1变量常规机组启停状态u_g,t、光热电站汽轮机组启停如果有、储能充放状态中需要防同时充放时引入的0-1变量。第二层是连续变量常规机组出力P_g,t、光热电站电出力P_csp,t、储热罐充放热功率Q_ch,t和Q_dis,t、风电和光伏实际消纳量。第三层是辅助变量各节点相角、线路潮流、失负荷量、弃风弃光量等。变量分层的意义在于调试时能快速定位问题。比如Cplex报告可行域为空我可以先固定所有0-1变量把问题转成纯LP检查是不是连续变量约束互相矛盾。如果纯LP也无解说明是连续约束写错了如果纯LP有解但MILP无解说明是整数变量引起的逻辑冲突。这个排查习惯能省下大量时间。4.3 关键约束逐条拆解常规机组约束包括出力上下限、爬坡约束、最小启停时间约束。对跨时段优化最小启停时间约束会引入大量二进制变量但实际算例中如果不加调度结果会出现机组频繁启停不符合物理规律。爬坡约束必须同时覆盖相邻时段表达式如下P_g,t1 - P_g,t RU_g * u_g,t SU_g * (1 - u_g,t) P_g,t - P_g,t1 RD_g * u_g,t1 SD_g * (1 - u_g,t1)其中SU_g和SD_g是启动和停机时的额外爬坡容量这个写法比简单写爬坡上下限更贴近真实机组特性。功率平衡约束为全系统每时段发电等于负荷表达式sum(P_g,t) Pw_used,t Ppv_used,t sum(P_csp,t) P_load,t这里不需要单独加节点功率平衡因为直流潮流约束已经通过PTDF矩阵把所有节点注入和线路潮流绑定在一起。储热约束前面已经提过热平衡方程、储热罐容量上下限、充放热功率上下限。另外还需加储热罐始末状态相等约束让日循环周期闭合否则优化模型会把储热罐容量全部抽空到最后一刻实际调度中不可能这么做。一般加E_T0 E_T24或者在目标函数中对最终储热状态加一个期望值惩罚项。4.4 一个33节点算例的参数表为了演示我搭了一个测试算例33节点、5台常规机组、1个风电场、1个光伏电站、1个光热电站。系统峰值负荷120 MW风光渗透率在20%到35%之间。表里给出关键参数真实数据可以替换成自己的系统模型结构不变只改数据文件即可。电源类型装机(MW)最小技术出力比例爬坡限制成本系数备注G1-G3煤电40/30/3030%5 MW/10min0.02/0.03/0.035 元/MW^2分段线性化G4-G5气电20/2020%8 MW/5min0.05/0.06快速启动风电场600波动弃电惩罚200元/MWh10个场景光伏电站400波动弃电惩罚150元/MWh与风电相关光热电站3025%3 MW/min25元/MWh储热6h效率0.42表中各参数需要实际代入Matlab程序我后面会把核心代码片段贴出来。算例规模不大但足以验证N-k约束、储热约束和场景约束之间的相互影响。如果想扩大系统可以换成IEEE 118节点此时模型才会真正感受到N-k约束带来的规模压力。5. Matlab实现关键细节与求解器配置5.1 代码架构主体脚本、数据文件、约束函数我习惯把代码按功能拆分不把几百行约束全塞进一个脚本。目录结构一般是project/ ├── main.m # 主程序数据加载、变量定义、求解、后处理 ├── data/ │ ├── bus_data.mat │ ├── gen_data.mat │ └── scenario_data.mat ├── lib/ │ ├── build_ptdf.m │ ├── build_lodf.m │ ├── constraints_generators.m │ ├── constraints_csp.m │ └── constraints_nk.m └── results/ └── output_*.mat主程序先加载网络参数和场景数据然后定义时间轴T24定义所有决策变量接着按模块添加约束最后设置求解器参数并调用Cplex。这样做的最大好处是调试时不用全局搜索约束在哪个文件出了问题直接看对应函数的变量名和维数就能定位。5.2 Yalmip建模的实用写法Yalmip让Matlab里的建模工作简化很多。核心写法如下面这段示意详细注释让代码可读性更高% 决策变量 Pg sdpvar(ng, T, full); % 常规机组出力 u binvar(ng, T); % 启停状态 Pcsp sdpvar(ncsp, T, full); % 光热电站出力 E_tank sdpvar(ncsp, T1, full); % 储热罐热容量多一个时段用于闭合约束 Pw sdpvar(nw, T, full); % 风电实际消纳 Ppv sdpvar(npv, T, full); % 光伏实际消纳 % 约束收集 C []; C [C, constraints_generators(Pg, u, gen_data, T)]; C [C, constraints_csp(Pcsp, E_tank, csp_data, T)]; C [C, constraints_nk(Pg, Pw, Ppv, Pcsp, network, T)]; % 目标函数 objective fuel_cost(Pg, gen_data) penalty_wind(Pw, Pw_avail) penalty_pv(Ppv, Ppv_avail); % 求解 optimize(C, objective, sdpsettings(solver,cplex,verbose,2));特别注意Yalmip中矩阵维数必须一致我吃过的亏是sdpvar默认是矩阵变量如果不加full选项有时会被当成对称矩阵处理导致约束形状错误报错信息还特别隐晦。5.3 求解器选配Cplex/Gurobi/内置求解器MILP求解器我首推Cplex或Gurobi两者性能接近Cplex在Matlab里兼容性更省心。如果只是验证小算例也可以用Matlab自带的intlinprog但求解速度和稳定性都差不少。Cplex安装后要在Matlab里配置路径用addpath把cplex的matlab接口加载进来Yalmip才会自动识别。求解器参数里最影响效率的两个一个是MIP相对间隙我设成0.01也就是最优性间隙1%对调度问题足够另一个是时间限制设成600秒防止个别算例陷入长时间不收敛。还能利用Cplex的并行计算能力设置线程数为8在N-k约束生成迭代中能明显缩短求解时间。对于大规模N-k模型我会提前用Yalmip的hjsplit或直接输出LP文件检查模型规模。如果约束条数超过几十万大概率是事故集枚举太深或场景太多先用场景缩减和约束生成控制规模再上求解器这是工程上的正确顺序。5.4 调试与性能优化经验调试这类模型我最常用的招数是从小系统跑起。先做一个三节点或五节点系统关闭N-k约束只跑常规机组出力和功率平衡确认基本调度没问题然后逐步加入风电、光伏、光热和储热最后再加N-k约束。每加一步都检查约束违例量和目标函数值是否合理。另一个容易忽略的点是单位统一。Matlab里很多初学者会把功率MW和热功率MWt混用导致光热电站的热平衡约束完全错误。我的习惯是所有热功率统一用MWt电功率用MWe在数据文件里注明单位转换系数单独写成一个常量eta_pb这样一眼就能看出单位是否对齐。还有矩阵索引从1开始Yalmip表达式里不要用0索引这种低级错误在向量化编程里很容易出现。6. 实测效果与调参心得避免模型死在内存里6.1 不同N-k设置下的结果对比我在33节点算例上分别跑了无安全约束、N-1、N-2三种设置差异非常直观。无约束时目标成本最低但线路越限支路数在预想事故检查中达到5条加N-1约束后成本上升约7%越限为0再加N-2约束后成本又上升约4%。这个规律说明安全约束对成本的影响不是线性的N-1解决的是单点故障风险N-2开始涉及的组合故障对调度方案的限制更多来自风电光伏外送通道的容量预占。从结果里还能看到加入光热电站后N-2场景下系统切负荷量明显减少。这是因为光热储热让系统在事故后有能力快速增加出力弥补损失的风电或联络线功率。对比测试时我习惯把光热电站在模型中去掉再跑一遍计算同样的N-k指标这样就能量化光热电站对系统安全性的贡献这个数据在论文和报告中都非常有用。6.2 储热容量与弃电率的关系光热电站储热容量从2小时增加到10小时弃电率会出现一个明显的拐点。我记录的测试结果是储热2小时时夜间光伏为零、风电低谷时段光热无法补充弃电率在系统整体约6%储热加到6小时弃电率降到3.5%再加到10小时弃电率只降到3.2%边际收益迅速衰减。这说明储热容量和风光消纳率之间是一个饱和曲线在规划中不必无脑加储热。这个拐点的原因在于储热增大后限制光热出力的瓶颈从有没有热可用变成了汽轮机爬坡和最小技术出力约束。所以单纯增加储热而不优化汽机运行策略效果有限。在调度模型里储热容量变量如果也是待优化变量可以通过目标函数增加投资成本项来求解最优储热容量配置那又是另一个层面的规划问题了。6.3 常见报错及排查思路我把运行过程中最常碰到的坑整理成一个表对应Yalmip/Cplex的常见报错信息、原因和解决方法。新手遇到这些问题时可以按表直接对照。报错现象常见原因我的排查方法“Unable to assign memory”约束矩阵维数过大事故集枚举太多先做场景缩减再试约束生成迭代“Infeasible problem”功率平衡约束和机组上下限矛盾临时把负荷需求调低看是否有解Yalmip报“Expression is not linear”目标函数里写了P^2且没有分段线性化用yalmip的pw_poly函数或手动分段线性化变量维数错误sdpvar默认当成对称矩阵显式加full选项求解器长时间无进展MILP间隙无法收敛设置相对间隙0.01或时间限制还有一个典型问题初始点设置不当导致MILP求解慢。Yalmip可以对0-1变量提供初始可行解比如先跑一个不考虑N-k约束的模型把启停方案作为热启动点传给N-k模型Cplex的MIP start机制能大幅缩短求解时间。我自己实测在118节点N-2算例里热启动大约能减少30%的求解时间。6.4 对后续研究的扩展建议这个模型的可扩展方向很多。如果想要更精细可以把直流潮流换成交流潮流线性化模型用LAC模型或者二阶锥松弛这样能同时校核电压越限问题代价是计算时间翻倍。想加入更多储能资源可以扩展储电、储氢等模块约束结构与光热储热类似只需要修改能量转换效率。想考虑市场环境可以在目标函数中加入节点边际电价结算模型把调度结果和现货市场出清联动。如果要做更长时间尺度的运行模拟比如8760小时的全年经济性评估直接把T改成8760会撑爆内存。此时需要用滚动时域方法比如以24小时为窗口每12小时推进一次窗口重叠部分用终端价值函数衔接。这个方法和N-k约束生成的思路可以组合形成一套完整的全年安全约束经济调度工具适合做中长期规划评估。我在实际使用中最大的体会是这个模型的核心不是Matlab代码本身而是你对安全约束的理解深度和对求解器特性的把握。代码结构再漂亮约束逻辑错了照样跑不出正确结果。我建议每个做这类研究的人都自己动手从三节点系统开始搭一遍先跑通无安全约束版本再一层层加复杂度。哪怕最后只是把IEEE 118节点系统光热N-2跑通了你对电力系统调度的理解也会比看十篇论文更深入。调试过程中最值得养成的习惯是给每个约束模块写独立的日志输出每次求解后检查到约束违例量和变量边界。这个习惯我坚持到现在基本没有遇到解出来但完全不知道它怎么来的情况。
网站建设高端定制企业官网