ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

配电网N-1扩展规划:从DistFlow建模到Matlab实现全解析

配电网N-1扩展规划:从DistFlow建模到Matlab实现全解析 配电网规划说起来简单真正上手做N-1扩展规划很多人第一次就栽在“N-1到底该怎么建模”这个坎上。拿一份IEEE 33节点数据跑通潮流容易但要回答“未来五年该在哪条走廊新建线路、新建几回才能既省钱又保证单一故障下不断电”这就是一个典型的配电网N-1扩展规划问题。这篇文章我打算把这个问题从工程背景、数学建模到Matlab代码实现完整拆一遍顺便把我自己踩过的坑和排查经验都倒出来适合正在做配电网规划课题的研究生、刚接手配网规划项目的工程师以及想复现相关论文算法的同学。1. 配电网N-1扩展规划问题定义与研究价值1.1 N-1准则的工程含义N-1准则最早脱胎于输电网安全稳定运行标准说的是电力系统在任意单一元件线路、变压器、母线等故障退出运行后系统仍然能够保持对全部负荷的供电不切负荷、设备不过载、节点电压不越限。说白了就是最好的路断了车还能从别的路绕过去只不过绕行之后不能把桥压塌。配电网的N-1和输电网并不完全一样。配电网一般是闭环设计、开环运行正常工况下多回馈线在联络开关处断开各自带各自的负荷。一旦某回馈线故障才通过合上联络开关让相邻馈线承接故障段下游负荷。所以在配电网规划阶段做N-1校验本质上是在问当某回馈线或某台配变退出运行后有没有足够的备用容量和联络通道把负荷转带出去。很多初学者会把N-1误当成“所有线路都要双回路”这是不对的。N-1关心的不是“有没有备用元件”而是“任意一个元件退出后系统是不是还安全”。一个三段的辐射状馈线如果中间装了两个联络开关接往两条不同的变电站母线那它完全可能满足N-1并不需要整条线路都拉双回。1.2 扩展规划要解决的核心问题扩展规划就是在已有配电网基础上对未来一定周期内的负荷增长做出应对。常见措施包括新建或更换馈线增大导线截面、新增联络线、新建变电站或新增主变、加装分段开关和联络开关等。这个问题的难点在于组合爆炸。一条规划馈线走廊建与不建是0/1决策一个变电站新增几台主变是整数决策多条候选线路组合起来可行方案数量会随着候选走廊数量呈指数级增长。比如30条候选线路理论上就有2^30种建设方案靠手工枚举根本不现实。同时规划结果还必须满足运行层面的约束包括潮流约束、电压约束、容量约束、辐射状约束以及关键的N-1安全约束。所以配电网N-1扩展规划本质上是一个“投资决策-运行校核”强耦合的组合优化问题也是目前配电网规划方向学术研究和工程落地都绕不开的核心课题。1.3 为什么选择Matlab来做这件事做规划研究业界常用的平台有几种GAMS、PythonPyomo/Pandapower、MatlabYalmip。我之所以在项目里用Matlab主要看重三点。第一Matlab的矩阵运算和内置的优化工具箱让原型开发很快。配电网的DistFlow潮流方程用矩阵形式写出来一段代码就能把整张网的潮流约束组织完改数据也方便。第二Yalmip这个建模工具箱大大降低了混合整数二阶锥规划MISOCP的建模门槛搭配Cplex或Gurobi几行代码就能把复杂的N-1约束丢给求解器。第三Matlab的绘图和数据分析能力对结果展示非常友好规划出的网架结构、电压分布、网损变化都能直接可视化写报告和论文的时候省不少事。需要说明的是Matlab和Yalmip都需要正版授权求解器如Gurobi有学术免费许可Cplex也有社区版具体安装方法网上有官方文档这里不展开。2. 数学模型如何把规划问题变成可求解的优化问题2.1 目标函数投资、损耗与可靠性成本怎么权衡规划模型的目标函数通常是“年综合费用最小”。这里的“年综合费用”不是某一年的一次性投资而是把规划期内的建设投资、运行费用和可靠性成本折算到同一个时间尺度上。我常用的目标函数形式是min C C_inv C_loss C_ens其中C_inv是新建线路投资的等年值计算公式是C_inv (r0 * (1r0)^n) / ((1r0)^n - 1) * Σ c_k * x_k这里r0是贴现率n是设备使用年限c_k是第k条候选线路的建设成本x_k是0/1变量表示是否建设该线路。之所以要做“等年值”折算是因为一个规划项目通常跨越好多年不同方案的建设年份、设备寿命不同不折算到同一年就没法公平比较。C_loss是年网损费用一般按典型日负荷曲线或者最大负荷利用小时数近似计算。简化处理时可以选一个代表日或代表场景算完潮流后把网损乘上利用小时数和电价。C_ens是缺电成本工程上常用期望缺供电量EENS乘以单位停电损失来估计。不过说实话完整地算EENS需要大量故障场景枚举学术论文里经常用工程简化时往往会弱化这一项重点关注C_inv和C_loss。2.2 约束条件潮流、电压、辐射状与N-1之间的逻辑关系约束是规划模型的骨架。上手先排优先级大致是这四类潮流约束决定全网运行状态是否物理可行。配电网用DistFlow方程最合适它是把完整的交流潮流方程在辐射状网络下做了精确的支路化简化精度足够而且具有非常好的凸松弛结构。节点电压约束保证每个节点电压在允许范围内一般取0.93~1.07倍额定电压有些地区标准不同按实际规范来。这里注意N-1故障状态下电压偏差允许范围往往比正常运行要宽这是工程惯例模型里要对正常工况和N-1故障工况分别设电压上下限。支路电流/容量约束每条线路的载流量不能超过上限。新建线路有建设状态变量所以要用“大M”方式处理线路不建电流强制为0线路建设电流上限等于导线载流量。辐射状约束配电网优化理论上应当保持开环运行。如果只用DistFlow方程本身其实是不限制环网的。实际规划中我一般通过“虚拟潮流”法加一个辅助变量强制每个负荷节点只有一个父节点从而保证网络是辐射状森林结构。N-1安全约束的特殊之处在于它不是一组普通不等式而是对“故障后系统”的一组运行可行性约束。也就是说每考虑一个预想故障就要对故障后的网络重新列写一套潮流约束和运行约束再把这些约束和正常工况的约束一起放进同一个优化问题里。这就导致模型规模成倍增长也是N-1扩展规划计算量大的根本原因。2.3 N-1校核的两种处理思路先规划后校验与约束内嵌实际研究里N-1的处理有两种典型思路我项目里两种都写过简单对比一下。第一种是“先规划后校验”迭代法。先把N-1约束暂时去掉解一个只满足正常运行工况的规划问题得到一组建设方案然后对这个方案做全故障扫描找出N-1不满足的场景再把这些场景对应的约束作为“割”加回原模型中重新求解。如此循环直到所有故障场景全部通过。这个方法优点是模型规模小、求解快缺点是迭代次数不确定而且对初始方案敏感有时候要跑很多轮才能收敛。第二种是“约束内嵌”法也就是把每个预想故障场景下的潮流变量和约束直接全部放进优化模型一次性求解。这种方法模型完整求解结果在数学上保证了N-1安全但变量数会膨胀得非常快。比如IEEE 33节点系统如果有15个候选线路、考虑10个故障场景那么潮流变量就要乘以10。对于节点数在100以内的配电网现代求解器还能应付超过几百个节点就得上分解算法或者场景削减了。我自己的经验是做学术研究优先选“约束内嵌”法一次成型、结论干净做实际工程规划如果网络规模大可以先跑“先规划后校验”快速获得可行解再用严格模型做最终校核两条腿走路更稳妥。3. 求解策略为什么MISOCP成了主流启发式算法还有没有用武之地3.1 从非线性潮流到二阶锥松弛配电网DistFlow方程本身是非线性的尤其是支路功率与电压、电流的耦合项直接求解非凸非线性规划既慢又容易陷在局部最优里。2016年前后学术界把“二阶锥松弛”引入DistFlow这一步是配电网规划算法上比较大的进步。二阶锥松弛的核心思想是把约束I²_ij (P²_ij Q²_ij) / V²_i放宽成旋转二阶锥约束I²_ij ≥ (P²_ij Q²_ij) / V²_i或者写成更标准的形式再做一次变量替换最终变成一个可以用商业锥优化求解器高效求解的凸约束。在目标函数单调递增且网络满足一定条件时这个松弛是紧的也就是说求出来的解和原非凸问题的最优解等价。这个发现对规划问题意义重大因为一旦松弛是紧的整个N-1扩展规划就从“非凸混合整数非线性规划”变成了“混合整数二阶锥规划MISOCP”。虽然MISOCP仍然是NP难的整数问题但现代求解器Cplex、Gurobi、Mosek已经能处理中等规模的MISOCP而且能给出最优性间隙的证明。这在工程上非常有用你知道你离最优解还差1%而不是在黑暗里瞎摸索。3.2 商业求解器和Matlab内置求解器怎么选Matlab内置的intlinprog只能解混合整数线性规划不能直接处理二阶锥约束。如果不用Yalmip等建模工具还真不好直接用内置函数求解MISOCP。所以我的建议是装一个Yalmip工具箱再用Gurobi或Cplex做底层求解器。Gurobi对二阶锥的支持非常完善求解速度快学术免费。Cplex社区版也够用但部分老版本对二阶锥的处理不如Gurobi顺手。如果网络规模很小也可以用fmincon配合罚函数处理整数变量但这只能作为教学演示别拿到正式项目里用整数的0/1约束用罚函数很难保证可行性。启发式算法遗传算法、粒子群在纯学术讨论里偶尔能看到但我必须泼一盆冷水这类算法无法保证全局最优面对大规模N-1故障集时每次个体评估都要做一次全网潮流甚至N-1扫描计算量反而更恐怖而且结果不稳定。除非网络结构非常特殊或者你要处理的约束太复杂无法用MISOCP表达否则我很不建议一上来就上启发式。3.3 几种求解思路的对比求解方式数学性质计算速度适用规模能保证最优性吗使用难度MISOCP Gurobi/Cplex凸松弛整数规划快节点数500能给出最优性间隙中MILP线性化近似线性化误差快较大取决于线性化精度中低启发式GA/PSO非凸、随机慢中等不能保证低枚举所有组合精确极慢仅候选线路很少能低实际项目中我倾向于先用MISOCP跑一个小规模样例验证模型正确性再逐步扩大候选线路数量和故障场景数量最后再根据求解时间决定是否做场景削减。4. Matlab代码实现整体框架与关键环节拆解4.1 主程序框架从数据到结果一共分几步一个完整的配电网N-1扩展规划Matlab程序我习惯分成六个模块数据读入、参数设置、变量定义、约束构建、求解调用、结果分析。代码本身不用堆砌得很长关键是每个模块职责清楚后面排查问题才方便。下面是一个主程序的示意结构%% 主程序配电网N-1扩展规划 clear; clc; %% 1. 读入网络数据节点、已有线路、候选线路、负荷 [bus, branch, candidate] load_network_data(case33_N1.xlsx); %% 2. 设置规划参数 para.discount 0.08; % 贴现率 para.life 20; % 设备寿命年 para.price 0.6; % 单位电价元/kWh para.lossHours 3000; % 等效网损利用小时数 para.Vmax 1.07; % 正常运行电压上限 para.Vmin 0.93; % 正常运行电压下限 para.Vmax_N1 1.10; % N-1工况电压上限 para.Vmin_N1 0.90; % N-1工况电压下限 %% 3. 生成故障场景集合预想事故集 faultSet build_fault_set(candidate, ...); %% 4. 调用Yalmip建模函数构建规划模型 model build_N1_planning_model(bus, branch, candidate, faultSet, para); %% 5. 调用Gurobi求解器求解 ops sdpsettings(solver, gurobi, verbose, 2, usex0, 0); sol optimize(model.Constraints, model.Objective, ops); %% 6. 提取结果并绘图 if sol.problem 0 x_opt value(model.x_line); visualize_planning_result(bus, branch, candidate, x_opt); else disp(求解失败请检查约束或求解器设置); end这个框架里最花时间的是build_N1_planning_model这个函数后面几节我会把里面核心部分的写法展开。4.2 数据准备候选线路和故障场景是规划的关键输入做扩展规划数据准备决定了模型质量的一半。我强烈建议把原始数据整理成结构体或者Excel表格包含以下关键字段节点数据节点编号、有功负荷、无功负荷、电压基准值。已有线路数据起始节点、终止节点、电阻、电抗、最大载流量、是否已投运。候选线路数据跟已有线路字段相同另外加一个“单位建设成本”字段。变电站/电源点数据电压幅值、短路容量如果做短路电流校核时要用。候选线路怎么生成是个很讲究的活。最粗糙的办法是把所有“节点对”都作为候选但这会导致整数变量爆炸。一个实用的做法是根据地理坐标找出相邻节点之间的可行走廊然后结合已有线路走向补上“使网络形成环网”的关键联络线。比如在一个33节点配电网里如果已有线路是辐射状那么候选线路常见的是那些能把末端馈线连接起来、形成备用通道的线路。故障场景集的生成也有讲究。严格意义上的N-1要把所有线路逐一断开但配电网里有些线路故障后影响很小可以省略。实际处理时我一般按“变电站主变”“主干馈线段”“重要的联络线”来过滤把N-1预想事故集控制在20个以内这样模型规模可控工程上也说得过去。4.3 DistFlow潮流约束和二阶锥约束的代码表达Yalmip建模的好处是几乎可以直接把数学公式抄成代码。下面这段是构建正常运行工况下DistFlow约束的核心代码我用注释解释每一条语句的含义function F add_distflow_constraints(F, V2, I2, P, Q, bus, branch) % F: 已有的约束集合 % V2: 节点电压平方变量 % I2: 支路电流平方变量 % P, Q: 支路有功和无功变量有向 % bus: 节点数据 % branch: 支路数据 nB size(bus, 1); % 节点数 nL size(branch, 1); % 支路数 % 电源点电压固定例如0号节点为平衡节点 F [F, V2(bus.slack) 1.0^2]; % 对每条支路写出DistFlow方程 for k 1:nL i branch.from(k); % 首端节点 j branch.to(k); % 末端节点 r branch.r(k); x branch.x(k); % 支路末端有功和无功平衡 F [F, P(j) sum(P_all_out_of_j) r * I2(k) bus.Pload(j)]; F [F, Q(j) sum(Q_all_out_of_j) x * I2(k) bus.Qload(j)]; % 电压降落方程 F [F, V2(j) V2(i) - 2*(r*P(k) x*Q(k)) (r^2 x^2) * I2(k)]; % 二阶锥约束I2 (P^2 Q^2) / V2(i) F [F, [I2(k), P(k), Q(k), V2(i)] ... : cone([2*P(k); 2*Q(k); V2(i)-I2(k)], V2(i)I2(k))]; end % 节点电压上下限 F [F, para.Vmin^2 V2 para.Vmax^2]; end上面代码里我用了一个简写P_all_out_of_j真实程序中要把它和节点关联起来一般先建一个“节点-出线”的映射关系再用sum做聚合。Yalmip的cone命令会自动把线性二阶锥表达式转成规划求解器能识别的格式如果读者习惯用Gurobi原生接口也可以手动写二阶锥表达式但Yalmip会更直观。这里尤其要注意对于“有候选线路但没有建设”的支路支路功率必须强制为0否则会发生“没建的线还跑电流”的囧事。做法是对每条候选支路引入大M约束F [F, -M*x(k) P(k) M*x(k)]; F [F, -M*x(k) Q(k) M*x(k)]; F [F, I2(k) I_max(k)^2 * x(k)];M的取值不需要太大取线路容量上限的几倍即可。M太大会让松弛后的数值稳定性变差求解器容易报数值警告这是我在实践中踩过的一个坑。4.4 N-1故障场景的循环建模与求解配置N-1工况的建模思路就是对每个故障场景复制一组潮流变量和约束。代码结构大概是这样的for s 1:nFault % 故障线路集合 if s 1 faultLines []; % 场景0正常运行工况 scenarioName normal; else faultLines faultSet(s-1,:); % 断开的线路编号 scenarioName [N1_, num2str(s)]; end % 为该场景创建独立的电压、电流、功率变量 V2_s{s} sdpvar(nB, 1, full); I2_s{s} sdpvar(nL, 1, full); P_s{s} sdpvar(nL, 1, full); Q_s{s} sdpvar(nL, 1, full); % 构建该场景的DistFlow约束 F [F, add_distflow_constraints(F, V2_s{s}, I2_s{s}, P_s{s}, Q_s{s}, bus, branch, faultLines)]; % 故障线路的开关状态约束断开的线路功率为0 for k 1:length(faultLines) F [F, P_s{s}(faultLines(k)) 0]; F [F, Q_s{s}(faultLines(k)) 0]; F [F, I2_s{s}(faultLines(k)) 0]; end % 该场景下候选线路的建设状态仍然由全局变量x决定 for k 1:nCandidate F [F, P_s{s}(candidateIdx(k)) M * x(k)]; end end这段伪代码只是整体框架实际写的时候还要处理“故障线路对应已有线路还是候选线路”的区别。如果是已有线路故障它直接断开如果是候选线路故障但它本来就没建那这个故障场景实际应该跳过因为该线路不在系统中运行。一个更精致的做法是把网络中的支路分成两类——必建支路和选建支路。只有必建支路才进故障集选建支路不做N-1校验。这种沿用工程惯例的做法能让模型规模下降不少。最后求解配置我一般在sdpsettings里选Gurobi打开数值清洗功能设置MIPGap为0.01%然后开始求解。如果模型规模很大建议给解设置一个时间上限比如600秒先拿到一个可行解再做后处理分析不要干等。5. 算例分析IEEE 33节点系统的N-1扩展规划全过程5.1 算例设置从基础网架到候选方案生成算例我选自经典的IEEE 33节点配电网原始系统是辐射状节点0是变电站母线其余32个节点是负荷节点。为了演示扩展规划我在原始网上做了两处改造一是把原始的辐射状网络当作“现状电网”但设置了6条候选联络走廊这些走廊可以把末端节点连接起来在N-1故障时提供转供路径二是假设未来负荷增长20%部分线路在原方案下会过载。候选线路具体是哪几条我这里列一下候选线路编号起始节点终止节点建设成本万元/km载流量AC182145400C291545400C3122240300C4183350400C5252940300C612840300故障场景集选择了主干线上的10条关键线段模拟“任一主干段断开后系统是不是还能通过联络通道转带负荷”。5.2 规划结果建了哪几条线效果如何用上述模型调用Gurobi求解得到的最优方案是建设C1、C3、C4三条线路总建设投资等年值约为86万元/年。对比不建设任何新线路的场景这个方案把正常工况下的系统网损从245kW降到了176kW年网损费用减少约12万元。更关键的变化发生在N-1校验环节。不建任何新线路时我对故障集进行扫描发现至少有5个故障场景会导致部分节点电压低于0.90p.u.或者部分线路电流超过载流量。而建设C1、C3、C4之后同样的故障集扫描所有场景都能成功转供最严重的电压降落也控制在0.91p.u.以上满足N-1工况下的电压要求。这组结果直观地说明了扩展规划的价值新线路不是简单地“多铺几回线”而是通过优化配置联络走廊让整个网络具备了应对单一故障的自愈能力。C2和C5虽然也能改善网损但它们对N-1转供的作用不如C1、C3、C4明显所以最优解里没有它们。5.3 探索性分析候选线路数量如何影响求解时间我在同一套算例上做了个简单的敏感性分析候选线路从6条逐步增加到18条观察模型求解时间的增长。结论是当候选线路在12条以内时Gurobi通常在30秒内就能找到最优解候选线路增加到18条后求解时间跳到了近300秒而且最优性间隙在10分钟计算时限内只能收敛到0.5%左右。这告诉我们两个教训第一规划模型不是候选线路越多越好实际工程中要结合廊道条件和电网结构筛选出真正有潜力的候选走廊第二如果候选线路特别多一定要想办法做场景削减或采用Benders分解等高级求解框架。如果读者后续要研究更大规模的网络建议从“网架结构约简”和“故障场景聚类”这两个方向入手。6. 常见问题与实操避坑记录6.1 潮流不收敛大部分时候是初始数据的问题很多同学跑计划模型时遇到“infeasible problem”第一反应是改求解器参数。我调试过几十次N-1规划模型可以负责任地说绝大多数不可行问题出在数据一致性上。最典型的几个坑一是节点电压初始值给得太离谱比如把平衡节点电压设成1.1而其他节点电压下限是0.93这样松弛后的二阶锥约束看起来可行实际潮流却没法满足二是负荷数据单位不统一有功用的MW无功用的Mvar但线路阻抗用的欧姆没有归算到统一标幺值三是故障场景里把一个必建线路当成候选线路断开结果网络直接劈成孤岛。排查方法也很简单先用一个不含整数变量的纯潮流模型测试把所有候选线路全部等价位“闭合”看模型能不能收敛能收敛再一步步加入整数变量和N-1故障场景。用这种“最小复现法”逐层缩小问题范围比我瞎试求解器参数快得多。6.2 N-1校验总是失败可能是“转供路径”根本没建起来规划方案在正常工况下很美一进N-1场景就崩这种现象我见得太多了。常见原因是对“故障后网络”的连通性约束缺失。比如候选线路只建了C1但C1只在某个特定故障场景里能转供其他故障场景中转供通道断了N-1自然失败。一个隐蔽的坑是在N-1场景中某个负荷节点可能既不在主网的供电路径上也没有任何备用路径这时潮流方程依然“有解”——解是那个节点电压等于0功耗全部不满足。这种数学上可行、物理上荒谬的结果是因为模型缺少了“每个负荷节点都必须被某个电源点供电”的连通性约束。解决办法是在模型里加一个“虚拟功率注入”变量或者对每个节点加一个“必须有父支路”的约束。用虚拟潮流法构建辐射状约束时这个连通性一般能顺带保证但如果只复制DistFlow方程而忘了辐射状约束N-1结果就会非常不可靠。6.3 求解时间太长先别急着加硬件试试场景削减我在N-1扩展规划里遇到过最痛苦的一次求解是候选线路22条、故障场景60个Gurobi跑了半个多小时才收敛到2%的最优性间隙。后来我做了三件事时间立刻降到了3分钟以内。第一做故障场景聚类。把故障后系统响应类似的线路合并成一个代表场景。比如同一条母线下的好几段馈线故障后的转供路径几乎一样完全可以合并。第二削减候选方案。用一次“不考虑N-1”的快速规划找出有价值的候选线路把收益极低的走廊从候选集中删掉缩小整数变量搜索空间。第三给求解器提供一个初始可行解。先用启发式方法生成一个相对好的建设方案再用Yalmip的assign函数把它赋值给整数变量这样Gurobi可以沿着这个解快速改进而不是从零开始分支剪枝。6.4 关于二阶锥松弛紧度需要留个心眼MISOCP解出来之后我总会做一次“松弛紧度验证”把最优建设方案固定下来跑一个完整的交流潮流程序比如用Matpower或者Pandapower对比节点电压和支路电流看看二阶锥松弛的结果和交直流潮流结果差多少。如果两者偏差在千分之几以内那说明松弛是紧的结果可信如果偏差明显偏大说明模型的目标函数或者约束设置可能缺少了某个能“压紧”松弛的项。出现不紧的情况常见原因是目标函数里网损成本占比太小或者约束里没有对电流下限做限制。这种时候我通常会在目标函数里显式加入一个极小权重的网损项或者在二阶锥约束处增加一个很小的惩罚系数强迫松弛自然紧化。这个技巧在论文复现时特别有用大家可以记一下。7. 一些个人体会做配电网N-1扩展规划这一路下来我最大的感受是这个方向真正难的不是数学推导而是怎么把一个工程问题和一堆约束、变量、场景对应起来。很多人在论文里看到“N-1安全约束”只是简单一句话落到代码里却要处理几十个故障场景的变量复制和约束耦合稍不留神就漏掉一个连通性约束结果算出来的方案根本不满足安全要求。如果你打算自己写一套类似的Matlab程序我建议从一个小网络开始比如33节点系统就够了先把正常运行工况下的扩展规划跑通再逐步加入N-1场景。每加一个故障场景就手动检查一次结果是否合理。这套流程看着慢但远比一口气把大模型堆起来再去debug要省时间。最后再分享一个小技巧规划结果的展示比结果本身更重要。别只丢一个“建设哪些线路”的表格把正常工况和N-1工况下的关键节点电压曲线、支路负载率对比图画出来一眼就能看出规划方案到底好在哪。写得直观评审和导师都会对你高看一眼。
返回列表