ARTICLE DETAIL

资讯详情

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

主动配电网动态重构与二阶锥规划:从建模到YALMIP/Gurobi实现

主动配电网动态重构与二阶锥规划:从建模到YALMIP/Gurobi实现 主动配电网动态重构这几年在配电网优化领域几乎成了绕不开的考核题。分布式光伏和储能大规模接入后配电网不再是简单的单向输电载体而二阶锥规划则以一种相当优雅的方式把重构这个混合整数非线性问题压到了可求解的尺度。这不是纯理论卖弄而是真正能跑出结果的工程手段。这篇文章以我实际搭建算例的经验为主重点聊聊动态重构的问题本质、SOCP的建模思路、YALMIP/Gurobi实现流程以及调试中踩过的坑。适合正在做配电网重构方向的研究生也适合想理解优化方法怎么落地的调度和规划工程师。动态重构比静态重构难在哪儿为什么要引入时间维度下面从头拆。1. 先理清楚动态重构到底在解决什么问题1.1 传统重构与动态重构的本质差别传统配电网重构通常只看一个潮流断面比如最大负荷或某个典型运行方式在这个断面下求解最优开关组合让目标网损最小。这个思路在负荷平稳、电源集中在变电站侧的时代基本够用因为一天之内拓扑只要按最严酷时刻设计其他时刻不会出大问题。但分布式电源大面积接入后情况变了中午光伏大发馈线可能倒送功率电压被抬高傍晚负荷高峰光伏出力掉到接近零又可能出现电压偏低。一个断面、一套开关组合根本罩不住全天。动态重构把时间轴拉进来在多个时段内同时优化拓扑序列不再要求每个时刻都用同一个拓扑。它真正想解决的是两个层面的问题一是让网络拓扑跟着净负荷曲线走降低全天网损、改善电压二是避免开关动作失去控制。如果每个时段都独立做静态重构最优解很可能在相邻时段频繁切换开关一组开关一天开合几十次这在现场无法接受。动态重构通过对开关动作次数设置惩罚或硬约束让拓扑变化既跟随负荷又不至于太敏感。这里要强调一个观念动态重构不是把静态重构重复做T遍。它是把T个时段的运行变量、开关状态、储能SOC放在同一个优化问题里求解。这样开关状态具备时间耦合储能充放电也能和拓扑变化互相配合。本质上这是一个多时段混合整数非线性规划比静态问题多了一个维度难度也高了一个量级。1.2 主动配电网的“主动”体现在哪里主动配电网和传统配电网的最大区别在于“可调”。传统配电网里分布式电源大概率是被动消纳逆变器不参与调压储能也很少见。主动配电网则具备主动管理能力DG出力可调、储能充放电可调度、网络拓扑可调甚至需求响应也参与运行。重构在这种场景下就不再是孤立的开关优化而要和储能充放电计划、DG削减策略放到同一个框架里协同决策。举个典型场景中午光伏大发节点电压升高最优做法可能是让储能充电、压低馈线倒送功率同时调整联络开关让功率走更合理的路径到了晚高峰光伏出力消失储能进入放电状态拓扑又可能需要从“光伏友好”切换到“负荷平衡”模式。如果只盯拓扑不考虑储能SOC算出来的开关动作可能根本执行不了因为储能已经在早上把电放光了。动态重构的价值就是把“拓扑”和“可控资源”的时间轨迹放在一起找最优配合。所以做主动配电网动态重构不能沿用静态重构的“网损最小”单目标思维。目标里要有网损、电压质量、开关动作次数、储能运行约束甚至DG削减惩罚。目标函数怎么写权重怎么定直接决定算出来的结果能不能用。这也是后面模型部分要细说的重点。2. 为什么是二阶锥规划思路与选型2.1 配电网潮流方程非凸的根子配电网重构本质上要解潮流方程加开关变量。最常用的潮流模型是DistFlow方程它专门为辐射状配电网设计计算精度高形式也相对紧凑。为了说清楚SOCP的来龙去脉我们把支路ij上的潮流关系写一下。节点j的有功平衡、无功平衡和电压递推关系可以表示为P_j P_ij - r_ij * l_ij - sum(P_jk) Q_j Q_ij - x_ij * l_ij - sum(Q_jk) v_j v_i - 2(r_ij * P_ij x_ij * Q_ij) (r_ij^2 x_ij^2) * l_ij其中v_i表示节点i电压幅值的平方l_ij表示支路ij电流幅值的平方。看起来前两个方程是线性的第三个也只有二次项和线性项但问题出在支路电流和功率的关系上l_ij (P_ij^2 Q_ij^2) / v_i这个等号右边的(P_ij^2 Q_ij^2)/v_i是非凸的它让整个问题变成非凸优化。再加上重构需要引入二进制开关变量问题就成了一个混合整数非凸非线性规划直接丢给内点法求解器几乎只能拿到局部最优而且求解时间不可控。很多人一开始会用近似算法绕开这个非凸项比如假设电压近似为1把分母里的v_i当常数这样l_ij近似等于P_ij^2Q_ij^2仍然非凸。再进一步把P和Q线性化就是在用精度换可解性。DG渗透率不高的时候还能用一旦光伏、储能大量接入潮流方向频繁反转线性化误差会明显偏大算出的重构方案可能在实际运行中电压越限。2.2 锥松弛如何把非凸问题“扶正”SOCP的思路很直接既然(P_ij^2 Q_ij^2) / v_i这个等号约束非凸那就把等号松成一个不等式l_ij (P_ij^2 Q_ij^2) / v_i等价写成P_ij^2 Q_ij^2 v_i * l_ij这个不等式的可行域是一个凸的二阶锥。原本非凸的等式约束被放宽后问题变成凸优化求解器可以稳定求解。你可能会担心松弛以后最优解不满足原等式怎么办这就是“精确松弛”要回答的问题。大量理论和实验表明在配电网辐射状、节点电压接近额定值、支路电流有界等条件下SOC松弛在最优解处是紧的也就是说l_ij会自动取到(P_ij^2 Q_ij^2) / v_i的下界松弛前后的最优目标值一致。实际调试中这个“紧性”并不是理所当然的尤其是加了电压上下限和开关变量之后。我会在后面的常见问题里专门讲怎么判断松弛是否紧、怎么补救。这里先说结论SOCP不是拍脑袋选的它是在保留DistFlow物理精度的前提下把非凸问题变成可以用商业求解器全局求解的方法。加入二进制变量之后模型变成混合整数二阶锥规划简称MISOCPGurobi和Mosek都有成熟的分支切平面算法能处理相当规模的动态重构问题。2.3 为什么不用线性规划或纯非线性规划这就得认真对比一下路线。线性化潮流模型比如线性DistFlow速度快模型简单适合配电网状态估计这类不需要高精度的场景。但它默认电压偏差小、支路损耗小当网络中DG出力波动大、潮流方向频繁改变时线性化误差会被放大。动态重构本身是要优化网损和电压如果潮流模型本身算不准优化出来的拓扑也很难让人放心。非线性规划模型比如直接用完整DistFlow加内点法可以精确描述潮流但遇到二进制开关变量就尴尬了。NLP求解器只能处理连续变量虽然可以用闵可夫斯基或罚函数处理离散量但本质上是在解一个非凸问题对初值非常敏感不同初值可能得到完全不同的“最优解”而且无法给出全局最优的保证。重构问题里开关组合动辄几十上百个NLP路线基本不可控。混合整数非线性规划也就是MINLP理论上最精确部分开源求解器也能解但动态重构把时间维度和开关变量叠在一起后变量规模爆炸式增长。我试过在33节点系统、24时段下用MINLP直接求解几个小时都收不了敛而同一个问题转成MISOCP后用Gurobi跑通常几十秒到几分钟就能拿到收敛解。这就是工程上为什么普遍接受SOCP精度足够速度可控配合商用求解器能给出全局或近全局最优解。3. 动态重构的模型怎么建关键变量与约束3.1 时间尺度和场景数据怎么切动态重构模型的第一步是确定时段。典型做法是把一天分成24个时段每小时一个断面研究层面足够如果负荷和光伏波动剧烈也可以分成96个时段每15分钟一个断面。时段越密对负荷变化的刻画越精细但二进制变量数量线性增加MISOCP求解时间会显著上升。我的经验是先用24时段把整个模型调通确认约束没写错、松弛够紧再考虑加密到48或96时段。负荷和DG数据尽量用标幺值基准功率取1 MVA电压基准取12.66 kV。配电网节点负荷曲线通常按典型日负荷系数缩放光伏曲线可以用晴天实测数据或者模拟曲线。重点是要计算每个时段的“净负荷”也就是负荷减去同节点光伏出力它直接反映该时段网络压力有多大。净负荷高的时候网络可能需要更多联络开关合环来分担潮流净负荷低的时候拓扑又可以适当打开减少环流损耗。场景数据Precision一定要统一单位我见过不少人在MATLAB里把MW误写成kW导致约束不等式量级差三四个数量级求解器数值紊乱报错或者给出不可行解。建议所有有功、无功统一到标幺值阻抗保持有名值但换算到同一电压等级节点电压也换算成标幺值这样模型数值条件好很多。3.2 目标函数怎么写才能不打架动态重构的目标函数最常见的写法是网损加开关动作惩罚必要时加入DG削减惩罚min sum_{t1}^{T} [ c_loss * sum_{ij} r_ij * l_ij,t c_sw * sum_{ij} w_ij,t ]其中w_ij,t表示支路ij在时段t是否有开关动作。网损按电量费用折算开关动作按操作成本或寿命损耗折算。但如果权重设得随意很可能出现“开关次数一票否决”或者“网损一票否决”。我的做法是分两步先不带开关惩罚只算最小网损得到开关动作次数上限解再只算最小开关次数得到网损很大的另一个端点。两个端点出来之后把两个目标归一化到0到1再做加权。这样权重w1和w2的含义很直观比如w10.7表示更看重网损。如果还需要控制电压质量我会加一个电压偏移的线性惩罚项比如对低于v_min或高于v_max的偏差使用线性罚避免用max函数引入额外非光滑项。目标函数堆太多项不是不行但每多一项就多一个待调权重建议不超过三项否则调参成本比建模还高。3.3 潮流与运行约束必须盯住每个时段都要写完整的DistFlow约束。以支路ij为例需要满足的有功平衡、无功平衡和电压递推分别加t下标。还要加二阶锥约束v_i,t * l_ij,t P_ij,t^2 Q_ij,t^2这个约束要写成软件能识别的二阶锥形式。在YALMIP里直接写它会自动识别成锥约束如果自己用Mosek接口建模则需要用旋转锥或者标准锥的形式。运行约束还包括节点电压上下限、支路电流上限、DG出力上下限和储能SOC约束。电压上下限不宜设得过宽太宽会削弱SOC松弛的紧性导致算出来的解不可信太窄又可能让原本可达的拓扑组合变得不可行。一般是先把电压范围设为0.95到1.05pu确认重构结果合理后再适当收紧或放宽。这里特别提醒开关变量z_ij,t要控制支路功率和电流为零。很多人在YALMIP里只写DistFlow方程和z忘记把P_ij,t、Q_ij,t、l_ij,t乘上z_ij,t结果断开的支路在模型里仍然有功率流动重构结果自然乱套。最稳妥的方法是给每条支路加“大M”耦合约束-P_ij,max * z_ij,t P_ij,t P_ij,max * z_ij,t -Q_ij,max * z_ij,t Q_ij,t Q_ij,max * z_ij,t 0 l_ij,t I_ij,max^2 * z_ij,t大M的取值不是越大越好I_ij,max^2最好按该支路实际允许电流平方取值不要设成1e6这种离谱的数否则松弛紧性会受影响。3.4 辐射状拓扑、储能与开关动作约束配电网重构要求所有时段网络都保持辐射状不会形成环网也不会出现孤岛。只约束支路闭合数为节点数减一还不够可能形成多个不连通的孤岛每个岛内支路数也满足总数条件。我采用的方法是用单商品流模型也可以叫虚拟潮流法。在一个以变电站为根节点的辐射状网络中定义每个时段从根节点向所有节点发送单位虚拟流量。对每个节点流入的虚拟流量减流出的虚拟流量等于1支路虚拟流量只能通过闭合的开关传输所以虚拟流量上限要乘以z_ij,t。再加上闭合支路总数等于n-1就能同时保证连通和无环。这段约束对数值比较敏感M值尽量取节点数减一不要设太大。储能建模相对标准。设SOC_t SOC_{t-1} eta_ch * P_ch,t * dt - P_dis,t * dt / eta_dis其中充电功率为正放电功率为负分别有上下限。如果严格防止同时充放电需要加二值变量互斥但多数情况下目标函数本身会避免同时充放因为充放电同时进行意味着能量被浪费不过对于电压支撑等场景某些松弛解还是可能出现所以最好加上互斥约束。开关动作约束有两种形式。一种是软约束即目标函数中加w_ij,t惩罚另一种是硬约束设置全时段总动作次数上限sum_{ij} sum_{t1}^{T} w_ij,t N_max线性化w_ij,t可以用两个不等式w_ij,t z_ij,t - z_ij,t-1 w_ij,t z_ij,t-1 - z_ij,t如果需要更严格的限制比如禁止同一个开关在短时间内来回切换需要定义连续模式约束这部分在工程中很重要我会放到常见问题里细说。4. 实操过程从零搭一个动态重构求解流程4.1 测试系统与数据准备做动态重构我建议从IEEE 33节点配电网测试系统开始。它结构经典参数公开节点数不大适合验证模型正确性。33节点系统基准负荷约3.7MW含32条分段开关支路和5条联络开关支路共37条可操作支路。我在基础网络上加了两个光伏节点和一个储能节点改造参数如下表。接入节点类型配置18光伏rated 400kVA晴天出力曲线22光伏rated 500kVA晴天出力曲线25储能300kW / 600kWh初始SOC 0.533储能200kW / 400kWh初始SOC 0.524时段的负荷系数采用典型双峰日负荷曲线光伏出力曲线在12点到14点达到峰值夜间为零。所有数据换算成标幺值后检查每个时段的总负荷和总DG出力确保系统功率平衡。特别注意初始拓扑必须是一个连通的辐射状网络我通常把初始联络开关全部打开分段开关全部闭合作为0时段的z_0。4.2 YALMIP建模代码骨架我用MATLAB加YALMIP加Gurobi搭过好几版动态重构算例。YALMIP对MISOCP支持得很好代码写起来比直接调Gurobi的Python接口省事很多。核心建模代码骨架如下。% 网络参数 branch [...]; % 每行: [from, to, r, x, cap, is_switch] n 33; nb size(branch,1); T 24; z0 zeros(nb,1); % 初始拓扑1为闭合 % 决策变量 z binvar(nb,T); % 支路闭合状态 w binvar(nb,T); % 1表示发生开关动作 p sdpvar(nb,T); % 支路有功 q sdpvar(nb,T); % 支路无功 l sdpvar(nb,T); % 支路电流平方 v sdpvar(n,T); % 节点电压平方 pg sdpvar(ng,T); % 光伏有功注入 ...然后按约束逐个写进去。DistFlow约束用for循环逐支路、逐时段生成别试图用矩阵运算一步到位那样逻辑容易出错且不好排查。SOC约束直接写成v(i,t)*l(j,t) p(j,t)^2 q(j,t)^2YALMIP会自动识别锥结构不需要手动转换成标准锥。辐射状约束我用了虚拟流变量逻辑清晰也方便扩展成三相模型。储能SOC约束单独写在一个函数里输入充放电功率和时段间隔输出SOC变量这样换数据或换储能参数时不用改主循环。最后设置求解器参数并求解ops sdpsettings(solver,gurobi,gurobi.MIPGap,1e-4,verbose,2); optimize(Constraints, Objective, ops);如果Gurobi没有MISOCP许可Mosek也可以替代但Mosek的混合整数能力弱于Gurobi大算例可能需要更多时间。使用开源求解器SCIP也可以支持MISOCP但速度和稳定性差距明显复杂模型不推荐。4.3 结果怎么读不能只看网损下降多少求解完成后第一步不是看目标函数值而是做合理性检查。把结果变量value(z)、value(v)、value(p)带回原始DistFlow方程逐时段验证功率平衡是否满足电压是否在范围内孤岛是否存在。我碰到过YALMIP显示“Successfully solved”但结果明显不对的情况多半是约束漏写或变量范围写错。一个典型结果示例比如基础改造后IEEE 33节点系统静态最大负荷断面重构目标网损约90kW最低电压0.911pu动态重构采用24时段MISOCP网损降到约72kW最低电压改善到0.956pu代价是开关动作总次数从5次增加到8次。这时可以再做一个对比给开关动作次数加硬约束限制总动作次数不超过4次网损会略微回升到75kW左右但拓扑稳定性和可执行性大大提高。这个对比往往比只追求“网损下降百分之多少”更能说明动态重构的价值因为它展示了网损和开关寿命之间的实际权衡。结果展示建议用两个图一个是电压曲线对比另一个是网损逐时段变化。拓扑变化可以用甘特图式的时间轴开关状态图来表示开关动作一目了然。这样写论文和做汇报都方便。5. 常见问题与排查技巧实录5.1 求解速度慢连24时段都算不动动态重构最常见的抱怨是求解太慢。24时段33节点系统如果所有37条支路都设成二进制变量只有888个二进制变量看起来不多但MISOCP的内部变量很多加上虚拟流和M约束计算量并不小。如果系统变成上百节点、时段再加密更是直接卡死。解决办法有几个。第一个是候选支路缩减重构中并不是所有支路都有必要作为决策变量真正可能打开的是环网联络开关所在的环路支路。把树干支路固定闭合只保留基本环路中的开关作为候选二进制数量可以砍掉一半以上。这个方法不改变重构的最优性因为树干支路本来就不可能断开。第二个是时段粗化先用24时段粗算把拓扑序列结果拿到后再在关键时段加密细化。第三个是合理调整求解器MIPGap从默认1e-4放宽到5e-3很多时候目标值变化很小求解时间可以缩短一个数量级。还可以给Gurobi提供初始可行解先解一个不含动作惩罚的松弛版本把z结果作为MIP start传给动态模型能有效减少分支节点的探索。5.2 二阶锥松弛不紧求出来的解不对怎么办SOC松弛最怕不紧。如果求完后l_ij明显大于(P_ij^2 Q_ij^2)/v_i那么支路损耗被虚增目标函数实际不是真实网损拓扑决策也就不可信了。判断方法很简单求解后算松弛间隙gap max(v_i,l_ij - p_ij^2 - q_ij^2)其中v_i和l_ij要按变量值相乘。如果gap超过1e-4标幺值就需要处理。一个有效的做法是目标函数里加一个极小权重的惩罚项比如epsilon * sum(l_ij,t)迫使电流平方结果尽量贴近下界。epsilon取1e-6或更小只会轻微改变目标却能显著改善紧性。另一个做法是迭代收紧先求松弛解找到松弛最大的支路集合在这些支路上加额外的线性化切平面再重新求解一般两三轮就能收敛。还要检查电压上下限是否设得太宽过宽的边界会降低精确松弛成立的充分条件。5.3 开关动作次数和实际可操作量对不上模型里计算出的动作次数只是“二进制状态变化次数”和现场可执行的操作次数往往有区别。比如同一组开关在相邻时段先打开后闭合对运行人员来说就是两次操作而模型可能只统计了两次状态变化没问题但如果一小时内开关反复开合实际执行时根本来不及。更危险的是环网倒闸操作在某个环上为了避开故障电流或潮流过载模型可能同时要求开一条联络开关同时合另一条联络开关也就是“合环-再开断”。实际配网现场合环会产生冲击电流不是随便就能执行的。我建议在动态重构模型中增加最小稳定时间约束让开关动作后至少在K个时段内保持同一状态。这个约束的线性化比较复杂但工程上很需要。如果没有硬约束至少要在结果输出后做顺序校核把不合理的短时切换过滤掉或者把动作次数上限设得比调度允许值更严格一些。5.4 多目标权重调来调去都不合理网损和开关动作次数量纲完全不同直接加权法经常出现“w_sw稍微调大一点开关次数就从8次变成0次网损却涨了20%”的现象。这是因为网损单位是kW而开关次数是整数数值差距过大权重稍有不平衡就会偏向一边。我的建议是归一化加权重。先分别求最小网损和最小开关次数两个单目标解得到目标值域[f1min,f1max]和[f2min,f2max]然后定义f1(f1-f1min)/(f1max-f1min)f2(f2-f2min)/(f2max-f2min)。最终目标为w1f1w2f2。这样w1和w2的含义变成了对两个归一化目标的偏好调参更加直观。更工程化的做法是直接把动作次数改成硬约束目标里只保留网损避免权重调参。运行方式人员一般能给出一天最多允许操作多少次开关这个约束比权重更容易接受。6. 从算例到落地一些经验与扩展6.1 建模型最容易忽略的三件事第一初始拓扑必须连通且辐射状。很多模型加了单商品流约束后仍报不可行原因就是z0本身不满足连通条件模型找不到一个可行的初始状态。第二联络开关和分段开关要区分清楚。分段开关通常是常闭的联络开关通常是常开的重构中真正需要决策的主要是环路中的开关如果把常闭分段开关全部放开不仅变量多还可能算出把主干线路解列的结果。第三求解后的核验不能省。把value(z)、value(p)、value(v)带回DistFlow方程逐时段检查特别是检查是否存在孤立节点。我曾经漏写了一个节点功率平衡约束目标函数值异常低幸好核验时发现某个节点P、Q全为零这才补上约束重新求解。6.2 时间尺度与在线协同动态重构真正落到准实时调度中不能直接把96时段的MISOCP丢给在线系统。一个比较实用的模式是“日前滚动优化加日内修正”日前用24时段或48时段动态重构确定拓扑和储能充放电的粗计划运行日开始后每一小时滚动一次固定已执行的开头状态只对未来4小时做动态重构并在目标里加入对计划偏差的惩罚。这样每个滚动窗口的整数变量大幅减少SOCP的凸性质也能让子问题在几秒内求解具备准实时能力。当然这需要可靠的日前负荷和光伏预测预测误差需要在滚动中吸收。我通常会在模型中为电压越限和功率越限留出少量的备用裕度而不是把约束卡死在上限值这样遇到突发波动时求解器不会轻易报不可行。6.3 后续扩展方向做完了单相平衡模型的动态重构下一步通常就是三相不平衡。三相配电网可以用三相DistFlow加SOCP建模每条支路的三相功率和电流变成向量但锥约束形式类似求解器仍然能处理。另一个方向是鲁棒重构光伏不确定性用盒式集合描述把部分约束写成鲁棒对应式目标里加入最坏情况损失。由于SOCP的凸性鲁棒变换相对好处理。重构结果还应该和继电保护配合校核拓扑变了会改变短路电流分布现场保护定值可能需要重新核对。我的体会是动态重构SOCP这条路已经相当成熟核心价值不在于“模型多复杂”而在于模型和实际运行约束贴合得有多好。把开关动作次数、储能SOC、最小稳定时间这些工程细节写进模型比单纯堆高阶算法更能在现场解决问题。
返回列表