ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

光热电站在N-K安全约束经济调度中的建模与MATLAB实现

光热电站在N-K安全约束经济调度中的建模与MATLAB实现 这段时间我在做含风电-光伏-光热电站电力系统的N-K安全约束优化调度项目MATLAB模型前后迭代了三个版本最大的体会是安全标准从N-1升到N-K之后光热电站的价值会被显著放大。多数资料把光热当成一台可调发电机组处理可实际它自带储热、功率调节范围极大这两条特性恰恰是N-K故障场景下最稀缺的资源。这篇文章不打算复述某篇论文的推导而是把从问题建模、光热等效、N-K约束写入到MATLAB算例对比的完整过程摆出来顺便记录我踩过的几个坑。适合电力系统调度方向的课题、毕业设计或者想在工程项目中做安全校核的同学参考。如果你之前只做过N-1调度想向前跨一步到N-K这篇文章也能帮你理解故障场景集和基态调度方案之间到底怎么耦合以及光热电站的储热能力在安全约束下是如何变成“真金白银”的。1. 为什么N-1不够用了N-K安全约束调度的问题定义1.1 从N-1到N-K故障集合变了调度逻辑也要变N-1是最经典也最基础的电力系统安全标准它要求任意单一元件线路、变压器、发电机组退出运行后系统不甩负荷、不越限。做调度计划时把所有单重故障逐一列成预想事故集对每个场景校核潮流和电压这个流程在传统电网里运行了很多年效果也不错。但N-1有个隐含前提故障是“单点”的。实际运行中一次极端天气、一次保护拒动或误动完全可能同时造成两回甚至更多线路跳闸。风电光伏大规模接入后潮流方向多变、某些线路长期重载N-K事故出现的概率比以前高得多。工程上常见的做法是加做N-2校核研究上更一般化成N-K把故障数量最多到K重的所有组合都放进预想事故集要求调度方案在这些场景下全都可行。这里有个关键区别N-K安全约束优化调度和事后可靠性评估是两回事。可靠性评估是给定一个运行点统计故障概率和失负荷期望N-K安全约束调度是在优化变量里直接把每种故障场景的可调性约束写进去相当于让优化器“预知”这些坏场景并主动留出可调空间。一个是验算一个是设计。K重故障的复杂度在于不仅要保证基态潮流不过载还要保证故障后的过渡过程和最终运行点不过载、不失负荷。工程上允许一定时间内的校正控制但日前计划阶段通常用简化处理——给各机组一个故障后的快速调节量上限并要求故障网架下潮流满足约束。这个简化后面会详细展开。1.2 光热电站为什么是N-K场景下的关键资源光热电站在N-K调度中的价值要从两个角度理解。第一它是同步机属性。光热电站通过聚光产生高温蒸汽推动汽轮机发电和常规火电一样是旋转设备带惯性、能提供旋转备用和无功支撑。风电光伏都是电力电子接口故障时反而容易脱网而光热在故障扰动下能快速增出力帮系统稳住频率。这个特性在安全约束调度里对应的是“故障后可调容量”。第二它带储热。光热电站的熔盐储热罐可以把中午的太阳能存起来晚上再放热发电相当于一台时间尺度从小时到十几小时的大号储能。在N-K故障场景下如果故障导致某些输电断面受阻、远端风电光伏送不出来光热电厂只要储热罐里有能量就能在负荷中心附近直接顶上去。这是普通火电和纯光伏都做不到的。所以光热电站的“灵活性”不是一句空话而是可以在优化模型里显式量化的出力调节范围接近0到额定值、爬坡速率远高于火电、储热罐提供日内的能量时移能力。这三点分别对应安全约束调度的不同需求。1.3 研究边界与基本假设这个模型涉及一些默认假设先交代清楚后面写MATLAB实现时就不容易糊涂时间尺度是日前24小时分辨率1小时做经济调度潮流模型用直流潮流近似只考虑有功和线路有功极限N-K预想事故集是事先给定的或者按规则筛选出来的本文先讲枚举和简单筛选光热电站按“光场-储热-汽轮机”的等效能量流建模不涉及传热流体温度动态故障发生后所有机组可以在一个较短调整时间内改变出力但改变量有上限模拟自动发电控制AGC的调节能力。这些假设都是这个领域论文里的常见设定不算特别激进但足够把光热的灵活性和经济性讲清楚了。2. 光热电站调度建模不要把它当成普通“电源”2.1 光热电站的运行结构我最早也犯过这个错误把光热当成一台光伏电池的合成体或者干脆当成一台出力上限恒定的火电。实际上光热电站的内部结构决定了它的运行约束非常特殊。光热电站主要分三个块集热场、储热罐、汽轮机发电岛。槽式或塔式集热场把太阳法向直接辐射DNI转化为传热流体的热能热能一部分直接送往汽轮机做功发电另一部分存进熔盐储热罐需要时再从储热罐放出熔盐经换热后驱动汽轮机。塔式系统的熔盐工作温度高储热效率也好是目前主流技术路线。调度建模的核心变量包括集热场收集的热功率、存入储热罐的热功率、从储热罐放出的热功率、汽轮机入口热功率、储热罐的储热量以及最终输出的电功率。这些量之间有一个能量守恒关系和火电的“锅炉-汽轮机”模型还不一样因为中间多了一个可以双向存取的储能环节。2.2 调度层面的等效模型SOC与电出力耦合关系实际编程时我习惯把所有热量单位统一折算成“等效电量”来处理避免热量单位和电功率单位混在一起换算出错。直流潮流本来只关心有功所以引入一个总效率把集热场吸收的热功率折算成等效电功率整个光热模型就简化为集热功率Q_col(t) η_total × A_field × DNI(t)能量平衡Q_col(t) H_dis(t) H_ch(t) P_csp(t) / η_pb储热SOC递推SOC(t) (1 - η_loss) × SOC(t-1) η_ch × H_ch(t) - H_dis(t) / η_dis出力限制0 ≤ P_csp(t) ≤ P_csp_max储放热限制0 ≤ H_ch(t) ≤ H_ch_max0 ≤ H_dis(t) ≤ H_dis_max储热容量限制SOC_min ≤ SOC(t) ≤ SOC_max。其中P_csp是光热电站的电出力H_ch是储热功率H_dis是放热功率SOC是储热罐当前储存的等效电量。这些约束全部是线性的所以最终模型还是LP或者MILP不需要引入非线性求解器。这套等效模型的物理直观性很强白天DNI高的时候光热电站既可以发电又可以把多余热量存起来晚上DNI为零只能靠储热罐放热来维持输出。优化器会自己权衡“现在多发电”和“留着以后发”依据是系统其他电源的成本和负荷情况。光热电站的另一个特点是出力下限可以取0。常规火电有最小技术出力比如30%~50%额定功率而光热汽轮机组配合储热系统理论上可以启停更频繁调度模型里可以直接把出力下限定为0。加上爬坡速率快这让它在N-K故障场景下成了一个非常灵活的调节资源。2.3 灵活性的量化爬坡速率、出力区间的差异化分析我算过一个简单对比一台200MW火电的爬坡速率通常按3MW/min考虑也就是一小时最多爬180MW而光热电站的设计爬坡能力可以到10%额定功率每分钟一台100MW光热一小时理论上可以爬600MW。差距是数量级的。在优化调度模型里爬坡约束直接影响故障场景的可行域。N-K约束要求基态出力与故障后出力不能差太远限制值就是爬坡速率乘以调整时间。如果调整时间按15分钟算火电能调45MW光热能调150MW谁能在故障后快速顶上一目了然。储热容量则用“满负荷小时数”描述。比如50MW的汽轮机配6小时储热罐储热容量就是300MWh等效电量。储热小时数越长光热出力曲线越能往后半夜平移对晚高峰和故障场景的支撑越强。但储热罐不是越大越好——集热场的DNI总量有限储热再多没有太阳时也存不满这就是后面算例里看到的收益递减现象。3. N-K安全约束经济调度的数学模型目标、约束与故障场景处理3.1 目标函数运行成本、弃风弃光惩罚与安全裕度权衡目标函数要回答“经济性”的问题。我用的目标是最小化全天总成本包含常规火电机组的燃料成本用分段线性函数近似二次成本曲线弃风弃光惩罚让优化器尽量避免削掉风电光伏出力切负荷惩罚这是一个很高的虚拟成本仅在故障场景下允许用来避免模型无解光热电站的运行维护成本通常按发电量乘一个很小的系数。写成公式就是min Σ_t [ Σ_g f_g(P_g(t)) λ_w × ΔP_w(t) λ_pv × ΔP_pv(t) λ_shed × P_shed(t) ]其中ΔP_w和ΔP_pv是风电光伏的削减量P_shed是故障场景下的切负荷量。这个目标函数很简单但注意一点λ_shed要比所有机组成本都高得多否则优化器会选择切负荷而不是调用昂贵机组。我用过5000元/MWh这个量级具体看算例规模。3.2 基态约束与故障场景约束的分层写法模型约束分两层基态层和故障场景层。基态层就是常规安全约束经济调度的内容节点功率平衡B × θ P_inject线路潮流F PTDF × P_inject并满足 -F_max ≤ F ≤ F_max机组出力上下限、爬坡约束、最小开停机时间如果引入启停变量风电光伏的实际出力不超过预测可用功率光热电站的SOC递推和储/放热约束。故障场景层对每个预想事故k单独写一套约束。注意这套约束里如果用和基态相同的直流潮流模型就必须用故障后的网架重新计算B矩阵和PTDF矩阵。断开的线路从支路数据里删掉重新形成导纳矩阵得到PTDF_k。故障场景下要同时满足故障后节点功率平衡故障后线路潮流在各自容量范围内故障后机组出力处在合理范围并且与基态出力的偏差不超过快速可调量允许切负荷但切负荷量作为变量计入目标函数。3.3 故障场景再调度能力的建模预防与校正的衔接这个建模细节是我觉得最重要、也最容易被忽略的地方。如果对每个故障场景都直接把机组出力设成独立变量、自由寻优那优化器等于默认“故障瞬间系统可以重新经济调度”所有机组随便改出力完全不考虑故障前后的物理过渡过程。这样得到的方案会过于乐观安全约束形同虚设。正确的做法是给基态出力和故障场景出力建立一个耦合约束。我用的形式是|P_g(k,t) - P_g(0,t)| ≤ R_g × ΔT_adj其中R_g是机组g的爬坡速率ΔT_adj是故障后允许的调整时间。这个约束的意思是故障发生后在短时间内AGC只能把机组出力调整这么多。光热由于爬坡快同样的调整时间内能动的范围更大所以在N-K场景下特别有用。同时故障场景下光热的SOC约束也要和基态相关联。严格说故障发生在某个时段故障前后储热罐里的能量不能突变所以SOC(0,t)和SOC(k,t)之间也要加一个允许偏差约束。我在简化模型里直接让故障场景的光热SOC和基态一致只允许电出力在爬坡范围内调整这样物理上说得通。如果不做这个耦合N-K约束就变成“每个场景独立可行性校验”那本质上是校核而不是优化。审稿人看到这里会问故障后谁来执行这个再调度你的AGC模型在哪里提前把这个问题堵住模型就扎实了。3.4 直流潮流线性化PTDF矩阵与线路越限判断直流潮流是安全约束调度里的标准手段。核心是功率传输分布因子PTDF矩阵。给定系统的节点注入有功和线路参数任意线路l的潮流可以写成F_l Σ_j PTDF(l,j) × P_inject(j)PTDF矩阵只需计算一次基态场景用基态网架算每个故障场景用各自的故障网架算。Matpower里直接用makePTDF(baseMVA, bus, branch)就能得到。注意删除故障线路后如果某些节点变成孤岛需要单独处理不然矩阵奇异求解器直接报错。线路越限判断也是靠这个矩阵对每个时段、每个故障场景算完潮流后和线路容量比较。优化模型里把约束写成- F_max ≤ PTDF_k × P_inject(k,t) ≤ F_max让求解器去满足它。4. MATLAB实现路线从数据准备到求解器调用4.1 算例系统设计在IEEE 30节点系统上“种”风电光伏光热我最初用IEEE 30节点系统跑通模型。这个系统规模小、收敛快、调试方便等逻辑验证完再换大系统不迟。设计思路在节点5接入风电装机80MW节点11接光伏装机50MW节点8接光热电站装机40MW配4小时储热罐容量160MWh。火电机组沿用case30自带的参数负荷用扩展后的典型日曲线。这样改造后新能源渗透率大约占顶峰负荷的30%到40%N-2约束能明显影响调度结果不会出现“有没有约束都一样”的尴尬。所有输入参数放到一个结构体里比如mpc、load_curve、wind_curve、pv_curve、dni_curve、csp_param。这样后面做储热容量敏感性分析时改一个字段就能重跑一组算例。4.2 基于YALMIP的模型搭建变量定义、约束循环的写法MATLAB里我习惯用YALMIP建模求解器接Gurobi或CPLEX。YALMIP的优势是约束可以直接用矩阵形式写省去手工把所有约束拼成大矩阵的过程。下面是一段核心骨架% 定义变量 P_g0 sdpvar(n_g, T); % 基态火电出力 P_csp0 sdpvar(1, T); % 基态光热出力 SOC sdpvar(1, T); % 光热储热SOC H_ch sdpvar(1, T); % 储热功率 H_dis sdpvar(1, T); % 放热功率 Nk length(scenarios); P_gk cell(Nk, 1); P_cspk cell(Nk, 1); for k 1:Nk P_gk{k} sdpvar(n_g, T); % 故障场景k下的火电出力 P_cspk{k} sdpvar(1, T); % 故障场景k下的光热出力 end % 光热SOC递推约束 Cons []; Cons [Cons, SOC(1) SOC_init eta_ch * H_ch(1) - H_dis(1) / eta_dis]; for t 2:T Cons [Cons, SOC(t) (1 - eta_loss) * SOC(t-1) eta_ch * H_ch(t) - H_dis(t) / eta_dis]; end Cons [Cons, 0 SOC SOC_max];这里的变量全部是连续变量整个模型是LP。如果要在机组组合中引入启停变量把P_g0换成sdpvar(n_g, T, binary)和连续出力变量相乘模型会变成MILP规模一大求解时间增长非常明显。故障场景约束用元胞数组循环写入for k 1:Nk % 故障场景k的功率平衡和潮流约束 Cons [Cons, PTDF_k{k} * P_inject_k(k,:) F_max_br(k)]; Cons [Cons, PTDF_k{k} * P_inject_k(k,:) -F_max_br(k)]; % 基态与故障场景的爬坡耦合 Cons [Cons, abs(P_gk{k} - P_g0) R_g * dT]; Cons [Cons, abs(P_cspk{k} - P_csp0) R_csp * dT]; endP_inject_k把火电、风电、光伏、光热、切负荷变量组装成节点注入向量这部分要根据原始网架数据写一个组装函数。我建议把“网架场景生成”和“模型求解”分成两个模块前者专门输出PTDF_k矩阵后者只做优化。4.3 N-K预想事故集的生成与场景削减N-K场景生成最直接的方法是枚举组合elements 1:n_br; Nk_scenarios []; for k 1:K Nk_scenarios [Nk_scenarios; nchoosek(elements, k)]; end但组合数增长很快。20条关键线路的N-2是190个场景50条就是1225个场景。每个场景都要重新算PTDF矩阵、都要写进优化模型很快内存和求解时间都吃不消。工程上常用两种削减思路第一种按故障概率排序只保留累积概率占大头的高风险组合第二种按基态潮流影响度筛选先看哪些线路在基态或N-1下接近重载只在这些重载线路之间组合N-K场景。研究上如果想做得更严谨可以用双层优化的思路用列约束生成CCG迭代筛选最恶劣场景而不是预先枚举全部组合。这个后面在扩展方向里再说。4.4 求解器选择与求解性能调优模型本质是LP或MILP我在MATLAB里的组合是YALMIP Gurobi。没有商业求解器的话先用linprog或intlinprog跑通小算例也可以但N-2场景一多默认求解器的表现会很吃力。性能调优有几个实操经验尽量保持模型为LP。机组组合的启停变量是最大的性能杀手如果研究重点是光热的灵活性和N-K约束可以先固定火电的开停机状态只优化出力YALMIP会把所有约束展开成一个大稀疏矩阵场景多时占用内存很大。可以用sdpsettings(debug,1)先看模型规模再决定是否做场景削减PTDF矩阵是稠密矩阵约束里频繁出现它会让矩阵非零元数量暴涨。对大规模系统可以把每个时段拆开单独建子模型但那样又涉及到场景间耦合思路要重新设计求解结果出现NaN时优先怀疑数值问题检查是否混用了标幺值和有名值。5. 算例结果与对比分析光热电站的灵活性到底值多少钱5.1 无光热vs有光热N-2故障下的成本与弃电对比这套算例跑下来的趋势很有意思。下面这个表格是基于上述30节点测试系统的一组典型结果数值只反映相对关系具体数字会因参数设定和负荷曲线不同而浮动。方案安全标准总运行成本(万元)弃风弃光率故障后切负荷量(MWh)A: 无光热N-0(仅基态)42.61.8%0B: 无光热N-247.35.2%15.4C: 有光热4h储热N-244.52.6%0D: 有光热8h储热N-243.12.1%0先看A和B同样没有光热N-2约束加上后总成本上升了近11%。原因是故障场景约束限制了部分输电断面的输送能力风电光伏送不出去只能弃掉弃风弃光率从1.8%涨到5.2%还有一个场景里切了15.4MWh负荷。再看C和B只加了一个40MW的光热电站和4小时储热罐N-2约束下的成本就回落到44.5万弃电率降了一半多故障场景切负荷直接降到0。这是因为光热电站接在8号节点相当于在负荷中心附近增加了一个可时移电源。N-2断开部分输电线后依赖远端风电的通道受阻而光热可以就地发电替代了被迫削减的清洁电力。D方案把储热从4小时加到8小时成本进一步降到43.1万但下降幅度明显变小。原因不复杂光热发电总量受DNI上限约束储热只是把能量从白天搬到晚上不能凭空创造电量。储热加到一定程度后白天集热场收集的全部热量晚上都能用上再加大容量就没有新增能量了。5.2 储热容量与光热装机对调度结果的影响我做了一组敏感性分析储热时间从2小时逐步增加到10小时光热装机分别取30MW、40MW、50MW。结果是一条典型的单调递减曲线边际收益逐渐下降。2小时储热光热只能在晚高峰前段提供支撑弃电率下降有限4小时储热晚高峰基本能覆盖N-2故障场景下的切负荷量为06小时以上更多储热只是让光热出力峰值后移系统成本的下降幅度开始趋缓。这个结果和直觉一致储热罐的经济容量取决于负荷峰谷差、光热装机和DNI曲线三者之间的匹配程度不是越大越好。算例里4小时到6小时是比较甜区再往上就要算投资回收账了。5.3 故障场景下的线路潮流与光热出力轨迹分析我还单独挑了一个最恶劣的N-2场景两条与节点5风电送出相关的线路同时断开。这个场景下如果没有光热风电出力最多只能送到60%左右其余只能弃掉再加上线路负载率逼近上限系统风险很高。接入光热后优化器的方案是在故障发生前的时段光热储热罐有意保持较高SOC故障发生后的两个时段光热出力从20MW爬升到接近40MW同时火电按照爬坡约束小幅减出力。这样扰动后的最大线路负载率从无光热场景的95%压回82%留出了明显安全裕度。把光热的SOC轨迹画出来看典型形态是白天9点到16点DNI充足SOC从30%爬到90%左右17点到22点晚高峰光热集中放热发电SOC逐步走低夜间维持在15%到20%的低位。在故障场景加入后故障时段的SOC下降比无故障方案快一些相当于储热罐替系统扛了一部分故障冲击。这就是灵活性在经济性上的具体体现。6. 我会踩过的坑和绕过去的方案6.1 场景爆炸组合数增长与预想事故集筛选第一次就把N-2场景全枚举跑40节点系统结果YALMIP建立模型花了十几分钟Gurobi跑起来直接提示内存不足。场景数量一多每个场景都有独立的PTDF矩阵和机组变量约束矩阵会被迅速撑满。后来我把策略改成“先筛选再优化”先用基态和N-1潮流找出重载线路前10条只在这10条里面组合N-2场景场景数从一千多降到几十个求解时间回到可接受范围。要说明的是这种筛选方法依赖基态工况存在漏掉极端场景的风险。更严谨的做法是两阶段鲁棒优化用CCG迭代找出最恶劣场景但入门阶段用筛选法理解问题会更直观。6.2 SOC时序约束缺失光热变成“永动机”让我印象深刻的一个bug是跑完优化后光热电站24小时满出力白天出力接近40MW晚上也接近40MW储热罐的SOC曲线完全不相关。原因是写约束时只加了每个时段的出力上下限把SOC三个递推方程中的某一个漏掉了导致优化器以为储热罐初始就是满的、能量可以凭空跳变。排查方法很简单把SOC曲线画出来如果它一跳就是几十MWh那基本就是递推约束漏写。另外要检查SOC终值时不小于初始值否则等于白拿了储热罐初始能量。我习惯加一个SOC(T) ≥ SOC(1) - eps的约束让储热罐日循环自洽。6.3 故障场景直接沿用基态PTDF断开线路还有潮流这个错误看起来很低级但字符串一多很容易犯。我最初写代码时故障场景k直接复用基态算好的PTDF矩阵结果优化结果里被断开的线路仍然有非零潮流物理上完全不可能。解决方法是每个场景必须重新调用PTDF计算函数并且要小心处理线路删除后的节点编号问题。Matpower里删除一条支路会导致内部节点顺序变化所以最好先复制原branch矩阵再按场景修改不要在原矩阵上直接改。还要检查删除线路后是否形成孤岛孤岛节点的注入功率会自动变为0对应潮流约束也会退化成无意义约束。6.4 不可行问题排查顺序从infeasible到最优解N-K约束加上后最常遇到的就是求解器返回infeasible。我的排查顺序基本固定第一步先跑N-1如果N-1都不可行问题出在基态约束或机组参数上而不是N-K逻辑第二步检查切负荷变量是否已经在所有故障场景中启用惩罚系数是否足够高。很多不可行问题就是故障场景下没有切负荷手段导致的第三步逐个检查故障场景找到是哪条线路、哪个时段的潮流约束卡死方法是用sdsettings(debug,1)开启YALMIP的诊断信息第四步检查量纲。PTDF矩阵和注入功率、线路容量的单位必须一致否则轻微不匹配在N-2场景里会被放大成明显错误。这个顺序目前帮我排掉了绝大多数问题值得留意的是第二步很多工程校核模型不允许切负荷但调度优化模型里必须给这个出口否则无解会挡住后续所有分析。6.5 后续可以扩展的方向两阶段鲁棒、AGC联动做完这套单层LP模型后我建议两条扩展路线。第一条是把N-K故障集换成不确定集用两阶段鲁棒优化配合CCG求解避免场景枚举爆炸这是目前文献里比较主流的方向。第二条是把AGC的响应速度模型建得更细把故障后15分钟内的动态频率约束加入计划层这样光热的快速爬坡优势就能更精确地体现在经济性里而不只是靠一个爬坡耦合约束近似。我个人在做完这版模型后的体会是安全约束经济调度不是约束越严越好关键是让模型看清故障后的可调空间。光热电站的储热和快速调节正好是打开这个空间的两把钥匙。如果你也要复现类似工作建议从N-1开始跑通再扩展N-2最后再考虑场景削减或鲁棒化每一步的调试都可以独立验证反而比一口气上大模型更快。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进