含分布式电源的配电网日前两阶段优化调度模型解析
分布式电源规模化接入配电网之后很多做调度研究的朋友都会撞上同一个问题原来用传统辐射状配电网的潮流计算和调度方法面对光伏、风电这种出力随机、还带逆变器无功能力的电源就明显不够用了。电压越限、网损升高、倒送功率这些现象接踵而至。这篇内容我打算把这套含分布式电源的配电网日前两阶段优化调度模型从问题建模、两阶段划分逻辑、无功优化核心设计到Matlab代码实现和调试经验完整拆开讲一遍。这套方案比较适合正在做配电网优化调度方向的研究生、从事分布式电源接入方案设计的工程师以及想用YALMIP求解器跑优化调度的初学者参考。全文不堆公式难为你但该有的推导逻辑和代码调试细节一样不少。1. 问题背景与整体思路拆解1.1 分布式电源接入后配电网的核心痛点传统配电网是单电源、辐射状结构潮流方向基本是从变电站母线流向末端负荷。这时候电压从首端到末端单调下降无功补偿的思路也很简单在负荷侧装并联电容器按负荷水平分组投切把功率因数补到合格就行。光伏、风电接进来以后情况就变了。分布式电源出力是间歇性的而且大量通过逆变器并网这带来三个直接问题。第一个是双向潮流。中午光伏大发时配电网局部可能出现功率倒送母线电压被抬升末端电压反而可能比首端高电压越上限的风险非常突出。我见过一个实际项目10kV馈线接入3MW光伏后中午时段并网点电压直接超过1.07p.u.越限问题不解决光伏甚至会被逆变器保护切机。第二个是网损问题。分布式电源出力和负荷峰值往往错位有功就地消纳比例不高时功率长距离输送反而增大网损。有些算例里DG接入位置不合理网损比不接DG还高这就是典型的布局与调度失配。第三个是调度复杂度。分布式电源数量多、单机容量小、控制方式多样没法像火电机组一样直接下指令。可调度手段包含有功削减、逆变器无功调节、储能充放电、电容器组投切、有载调压变压器分接头调整等这些手段在时间尺度、调节代价、响应速度上都不一样单阶段静态优化很难把这些协调好。1.2 为什么选日前两阶段而不是单阶段模型很多初学者第一次接触配电网优化调度习惯性地把所有决策变量塞进一个单目标优化模型里用粒子群或者遗传算法一跑出个结果就结束。这种思路在简单算例里能出图但放到实际场景里问题很多。核心原因是调度问题天然分时间尺度。日前调度Day-ahead解决的是明天24小时总体怎么安排的问题决策粒度通常是1小时需要在今天根据预测数据把明天的购电计划、机组启停、储能充放电计划、无功补偿粗计划定下来。这个时间尺度上光伏出力和负荷预测还有较大误差不适合做精细的无功电压控制。而更细尺度的调整比如15分钟级甚至分钟级需要根据实际运行状态滚动修正。两阶段模型的价值就是把粗决策和细调整分开做。我用的这套框架是这样划分的第一阶段日前计划层以系统运行成本最小化为目标决策次日各时段的有功调度方案包括上级电网购电功率、常规机组出力、储能充放电状态与功率、分布式电源有功计划出力。第二阶段无功优化层在阶段一有功计划确定的基础上以网损最小化或电压偏差最小化为目标决策各时段的无功补偿量、逆变器无功出力、变压器分接头挡位等。这种先有功、后无功的分解方式在工程上是有充分依据的。电力系统里有功频率调节和无功电压调节本身就有不同的时间常数解耦处理可以把非线性耦合关系拆开大幅降低求解难度。尤其是配电网的辐射状结构下DistFlow潮流方程经过二阶锥松弛后每个阶段都可以用商业求解器高效稳定地求解比单阶段大混合整数非线性规划MINLP稳得多。1.3 无功优化在模型里的定位与作用无功优化听起来是个老话题配电网里装电容器就是最传统的无功调压手段。但在含高比例分布式电源的场景下无功优化的内涵发生了几个重要变化。第一调节手段变多了。逆变器四象限运行能力使得分布式电源本身就能发出或者吸收无功功率而且响应速度极快比机械式电容器投切灵活得多。但逆变器无功出力受当前有功出力和容量限制不是想发多少就发多少这个耦合约束必须在模型里精确表达。第二目标更复杂了。传统无功优化主要目标是降网损顺带改善电压质量。现在还要考虑分布式电源消纳率、主变功率因数、电压越限风险等多目标加权处理时如果权重设不好优化结果会偏向某一项而牺牲另一项很多调出来的结果在工程上根本没法用。第三与有功计划的耦合关系不可忽略。分布式电源有功出力改变后节点电压和无功分布也跟着变。如果阶段一不考虑无功电压约束的可行性到阶段二可能出现无解或者严重越限。所以两阶段不是简单解耦而是要在阶段一预留足够的安全裕度这也是很多文献里说的可行性约束或者耦合约束的处理技巧。2. 模型的数学描述与约束处理2.1 两阶段模型的总体框架与变量划分我在Matlab里实现的这个模型两个阶段各自的决策变量和目标函数如下表所示。这个划分方式不是唯一的但工程上非常实用。阶段决策变量目标函数典型约束阶段一日前有功计划上级购电功率、常规机组出力、储能充放电功率、DG有功计划值总运行成本最小购电成本机组燃料成本弃光弃风惩罚等有功平衡、机组出力上下限、爬坡约束、储能SOC约束、线路传输上限阶段二无功优化DG逆变器无功出力、电容器组投切、OLTC分接头、SVC/SVG无功出力网损最小化电压偏差惩罚无功平衡、电压上下限、逆变器视在功率约束、电容器投切组数约束、分接头挡位约束从决策变量的类型来看阶段一里储能充放电状态、机组启停属于0-1整数变量其余是连续变量阶段二里电容器组投切和分接头挡位是整数变量逆变器无功出力是连续变量。所以两个阶段本质上都是混合整数规划MIP问题而不是纯线性规划或二次规划这一点大家在写代码时要心里有数。2.2 潮流计算与约束建模DistFlow与二阶锥松弛配电网是辐射状网络用极坐标下的牛拉法算潮流当然没问题但在优化模型里潮流方程是作为约束存在的非线性的极坐标方程会让整个优化问题变成非凸、难求解的MINLP。一个很自然的处理思路是采用DistFlow支路潮流方程。对于辐射状配电网的支路ijDistFlow方程的核心是三条节点有功平衡、节点无功平衡、支路电压降落关系。其中支路电流的平方项和支路功率项之间存在一个凸松弛关系利用二阶锥松弛Second-Order Cone RelaxationSOCR可以把非凸的二次等式约束松弛为凸的锥约束。这个松弛的物理含义是把支路电流幅值的平方等于视在功率平方除以电压平方这个精确等式放宽为电流平方不小于视在功率平方除以电压平方的不等式。你可能要问松弛之后的最优解还是原问题的最优解吗大量文献已经证明在辐射状配电网且网损较小的条件下这个松弛是精确的也就是说松弛后的最优解会落在原问题的可行域边界上。实际算例中只要目标函数是增函数且网络为辐射状SOCR的精确性基本有保证。我在代码里也专门检查过松弛间隙一般都在1e-4量级以下完全可以接受。2.3 目标函数与权重取舍的实操经验阶段一的目标函数相对直观就是各类成本求和重点在于惩罚项的设置。我建议一定要加弃光弃风惩罚项而且惩罚系数要合理设置如果设得太高模型会为了消纳DG而让常规机组频繁调节甚至购买高价电设得太低模型又倾向于大量削减DG出力来省事。我的经验是先跑一个基准场景统计DG消纳率和总成本的关系再反推可接受的惩罚系数范围。阶段二的目标函数是网损最小加上电压偏差惩罚。这里有个细节容易踩坑网损的目标值非常小单位是kW或MW而电压偏差的平方项是标幺值数量级可能差很多。如果不做归一化处理优化结果会被数量级更大的那个目标主导另一个目标形同虚设。我的做法是给电压偏差项乘以一个权重系数权重初始值取基准网损/基准电压偏差再根据仿真结果调整。此外两阶段之间的信息传递很关键。我的做法是在阶段一给阶段二传递每个节点的有功注入计划同时阶段一约束里已经加入了电压上下限的松弛版本比如比标准限值更严格的内部限值这样阶段二求解时即使有一些预测误差也不会出现大面积越限。3. Matlab代码实现与核心模块解析3.1 代码整体结构与运行环境整套代码我按功能模块拆分文件不是一个大的main脚本堆到底而是分成了数据、模型、求解、结果四类模块。目录结构大致如下project/ ├─ main.m % 主程序入口顺序调用各阶段 ├─ case33.m % 算例数据IEEE 33节点系统参数 ├─ load_data.m % 读取负荷曲线、光伏出力曲线、风电出力曲线 ├─ model_stage1.m % 阶段一约束和目标函数封装 ├─ model_stage2.m % 阶段二约束和目标函数封装 ├─ solve_optim.m % 调用YALMIP 求解器的统一入口 ├─ plot_results.m % 结果可视化和数据导出 └─ utils/ % 公用函数标幺值换算、结果校验等运行环境方面我用的版本组合是Matlab R2021b YALMIP R20210430 CPLEX 12.10操作系统是Windows。需要特别提醒一点YALMIP是调用求解器的建模层工具它本身不求解优化问题。如果你电脑上没有装任何求解器YALMIP会调用默认的求解器但像MIP这类问题通常效果很差。建议至少装一个CPLEX或Gurobi学生可以用学术许可证申请流程也不复杂。装好后在Matlab里运行yalmiptest命令看到CPLEX和Gurobi那一栏显示successfully solved就说明环境没问题了。还有一个基础问题就是Matlab本身的环境配置。如果你用的是正版或者学校授权版安装步骤不复杂但安装路径不要带中文和空格否则某些工具箱加载会出问题。之前有同学遇到过字符乱码的问题多半是编码格式不一致统一成UTF-8再重新打开脚本即可。YALMIP和求解器下载后要把文件夹加入Matlab路径pathtool加进去后别忘了保存。3.2 数据准备与场景生成配电网优化调度需要两类数据网络参数和时序曲线。网络参数这块IEEE 33节点系统是最经典的选择支路阻抗、节点负荷数据全网都能找到。我的case33.m里把所有参数整理成了结构体方便循环读取。这里有个细节原始数据单位通常是kVA和kV优化模型内部我建议统一成标幺值基准容量取10MVA基准电压取12.66kV这样数值尺度比较均匀求解器的数值稳定性更好。时序曲线我建议不要拍脑袋造数据最好用典型日实测数据或标准算例提供的曲线。实在没有也可以用正态分布加时间场景框架生成但要注意光伏出力曲线中午高、早晚低负荷曲线有早晚两个峰这些基本形状要保留。我用的是简化版处理96个时段太细采用24个时段每个时段1小时。% 构造24小时光伏归一化出力曲线示例 t (0:23); pv_base 0.8 * max(0, sin((t - 6) / 12 * pi)); % 早6点开始出力晚18点归零 pv_base(pv_base 0) 0; pv_curve pv_base / max(pv_base); % 归一化这段代码的意思是光伏出力从早6点开始上升下午14点左右达到峰值18点后归零。实际做研究时可以换成真实光照数据但归一化处理的思路是一样的。3.3 优化模型的YALMIP实现决策变量、约束组装与求解YALMIP建模的核心套路是先定义变量再写约束再定义目标函数最后调用solvesdp或optimize。我贴一下阶段二无功优化的核心骨架方便你对整体结构有个直观认识。% 阶段二无功优化YALMIP实现骨架 % sdpvar定义连续变量binvar定义0-1变量intvar定义整数变量 Q_dg sdpvar(33, 24); % 各节点DG无功出力 C_step binvar(33, 24); % 电容器组投切状态0-1 V_mag sdpvar(33, 24); % 节点电压幅值 Constraints []; % 电压上下限约束 Constraints [Constraints, 0.95 V_mag 1.05]; % DG无功约束考虑逆变器容量限制 % 视在功率约束Q^2 P^2 S^2用二阶锥表达 for k 1:24 for i 1:33 if dg_bus(i) 0 Constraints [Constraints, ... cone([Q_dg(i,k), P_dg_plan(i,k)], S_dg_max(i))]; end end end % 电容器无功与投切状态关系 Q_cap C_step .* repmat(Q_cap_step, 1, 24); Constraints [Constraints, Q_cap 0]; % 目标网损最小 电压偏差惩罚 loss sum(sum(R_branch .* I_square)); % 网损需要支路电流变量 vd sum(sum((V_mag - 1.0).^2)); % 电压偏差平方和 Objective loss weight * vd; % 求解 ops sdpsettings(solver, cplex, verbose, 2, ... showprogress, 1, cplex.mip.tolerances.mipgap, 1e-3); optimize(Constraints, Objective, ops);有几个关键点要说一下。cone函数是YALMIP里表示二阶锥约束的标准方法cone([x; y], r)表示norm([x;y]) r也就是x^2 y^2 r^2。用这个表达逆变器视在功率容量约束既精确又可以交给求解器高效处理。不要自己去展开成x^2 y^2 r^2再加sqrt那样约束变成非线性的很多求解器处理不了或者速度极慢。solvesdp和optimize的用法差异也要注意。老版本的YALMIP用solvesdp(Constraints, Objective, ops)新版本推荐用optimize。我在代码里统一用optimize返回的第一个参数diagn里可以读diagn.problem字段判断求解状态0表示求解成功1表示不可行还有其他值对应不同的失败原因。调试时这是最重要的信息源。还有sdpsettings里的参数。cplex.mip.tolerances.mipgap设置了MIP的相对间隙容忍度默认1e-4太严24时段两阶段模型可能跑很久。我调到1e-3结果精度损失可以忽略求解时间能缩短一半以上。这是实际工程里非常划算的取舍。3.4 结果处理与绘图求解完成后最关键的一步不是画图而是校验结果。我一般先做三个检查第一个是检查diagn.problem是否为0非0就要根据错误类型回溯约束。第二个是检查关键约束的越限情况比如最大电压和最小电压是否贴近边界但没越界如果所有节点的电压都在0.98到1.02之间说明调度方案偏保守可以适当调低权重参数。第三个是检查网损和DG消纳情况是否与预期一致不一致的话要对目标函数权重做灵敏度扫描。画图方面24小时电压曲线用二维图足够所有节点电压放在一张图里会密密麻麻看不清我是用pcolor画时段-节点-电压的热力图电压分布一目了然。DG出力、储能SOC、电容器投切状态用堆叠面积图或者阶梯图比较直观。Matlab里出图要设置好FontName和FontSize导出图片时用exportgraphics函数矢量图用-dpdf或者-depsc期刊论文和报告都够用。4. 仿真验证与结果解读4.1 算例场景设置我用IEEE 33节点系统做了验证。基准电压12.66kV总负荷约3.7MWj2.3Mvar。在网络的节点8、节点16、节点24分别接入分布式光伏总装机1.5MWp节点30接入一台小型风机装机0.5MW。储能系统装在节点18容量0.5MW/1MWh。所有DG均具备四象限逆变器额定功率因数范围0.95滞后到0.95超前也就是说可以发出或吸收一定无功。为了验证两阶段模型和无功优化的实际效果我设置了两个对比方案方案A只做阶段一的有功日前调度不考虑阶段二无功优化DG按单位功率因数运行不参与调压。方案B完整的日前两阶段模型阶段二执行无功优化DG逆变器参与无功调节电容器组和变压器分接头参与调压。这样对比之后就能清晰看出无功优化在网损和电压改善上的贡献到底有多少。4.2 关键结果对比网损与电压改善先说网损。方案A在24小时内的总网损是1120.6kWh方案B是927.4kWh降低了约17.2%。降幅最明显的是中午12点到15点这段时间此时光伏出力最大如果不做无功优化光伏大发导致局部电压偏高无功功率在馈线中来回流动网损居高不下。加入无功优化后DG逆变器在电压偏高时吸收无功把电压拉回合理区间线路上的无功流动减少电流减小网损自然就降下来了。电压方面方案A在中午时段节点17、18、32附近出现电压越上限的情况最大电压达到1.058p.u.方案B通过DG吸收无功和电容器组协调最大电压控制在1.046p.u.以内全天所有节点电压均保持在0.95至1.05p.u.的允许范围内。这说明无功优化在解决光伏高渗透率下的电压越限问题上效果非常直接。当然也要提醒一句网损降了17%这是在33节点小规模系统上的结果。实际园区或者馈线的降损比例会因为网络结构和DG渗透率不同而有所差异但结论方向是稳定的无功优化对高DG渗透配电网的网损和电压都有可观的改善收益。4.3 两阶段联动效果分析单独看阶段二的结果网损和电压确实都变好了但这是建立在阶段一给出的有功计划是合理的基础上。如果阶段一没有为无功调节预留足够的空间比如某个时段DG有功被安排得太满逆变器视在功率容量全被有功占用阶段二就没有多余容量来发无功了调压手段就只剩下电容器组和分接头效果会大打折扣。我在算例里专门做过一个实验把阶段一DG有功计划出力从满发改成预留5%容量裕度然后看阶段二的优化结果。预留容量后阶段二总可调无功增加了电压偏差指标进一步降低了约20%网损再降约4个百分点。这就是有/无功耦合约束的直接体现。两阶段模型的价值正在于此它不是把两个优化问题简单串联而是通过逐时段信息传递和容量预留设计让两个阶段真正联动起来。5. 实操中常见的问题与排查记录5.1 求解不收敛或结果异常两阶段模型如果出现求解失败我的排查路径是这样的。第一步确认模型可解性。把目标函数设为常数先求一个可行解。如果可行解都找不到说明约束本身冲突了。最典型的冲突是阶段二里DG无功上限和电压上下限之间矛盾。比如某个节点DG容量本来就不大还要它把末端电压压到0.95p.u.以下逆变器容量根本不够自然无解。这时候要么调宽电压限值要么增加无功补偿设备。第二步检查数值尺度问题。很多不收敛的案例其实是量纲问题。支路阻抗用欧姆、功率用瓦、电压用伏三个量级差距巨大的物理量混在一起建模求解器的数值稳定性会很差。我建议全部折算成标幺值让所有变量大致落在0.01到100这个区间内。第三步检查二阶锥约束的松弛间隙。方法很简单求解完后把最优值代回原非线性DistFlow方程看支路潮流的误差。如果误差超过1%说明二阶锥松弛在这个算例上已经不精确了可能需要加入割平面约束或者调整松弛形式。我用的算例基本没有这个问题但换网络拓扑时一定要复测。5.2 电压越限与网损不降反升的处理电压越限是最常见的异常。要先判断是哪个时段、哪个节点越限再用排除法定位原因。如果是中午时段末端节点电压偏高大概率是光伏大发导致倒送功率。这时候优先让该区域DG逆变器吸收无功如果还不够再考虑降低DG有功出力弃光。我遇到过一种情况节点电压越上限但光伏所在节点的逆变器已经在满发无功吸收状态电压还是压不下来最后检查发现是相邻馈线上另一台DG有功出力太大属于跨节点影响。处理办法是在阶段一约束里给这个区域增加有功出力上限或者加一个区域电压约束。网损不降反升的情况常见原因有两个。一是目标函数权重设置不对电压偏差权重太高系统为了把电压拉平让大量无功在网内长距离流动反而增加了网损。二是无功补偿设备的调节步长太大比如电容器单组容量过大投一组会过补偿不投又欠补偿无功只能在不理想的位置运行。这个实操上可以通过无功补偿容量分组细化来解决或者引入连续无功源SVG、逆变器实现精细化调节。5.3 Matlab与求解器联调的坑最后聊几个实际运行环境里的坑都是我自己踩过的。第一个是YALMIP版本和求解器版本不兼容。YALMIP更新很快CPLEX和Gurobi也在不断出新版。我用过一段时间的YALMIP旧版本调用新版CPLEX结果报了一堆Unable to evaluate的错误后来升级YALMIP才解决。如果你遇到莫名其妙的问题先检查YALMIP版本直接拉最新的Release版再测试。第二个是许可证问题。CPLEX和Gurobi必须要有有效许可证有的学校提供的浮点许可证还会有并发数限制跑大规模算例时提示Unable to acquire license就很耽误事。解决办法是提前在命令行测试求解器比如CPLEX跑一个简单的LP问题验证许可证。第三个是内存问题。24时段、33节点两阶段模型规模不算大但如果扩展成三相不平衡模型、几百个节点、上千个时段MIP规模会指数增长。我的经验是尽量利用模型稀疏性YALMIP里用稀疏矩阵而不是全矩阵定义约束避免创建多余的中间变量必要时把一天切成几个时段窗口用滚动方式求解而不是一次性求解全天模型。5.4 换算例常遇到的适配问题把代码从IEEE 33节点系统换到其他配电网时最容易出问题的是数据格式。不同来源的配电网参数表支路起点、终点编号的顺序可能不一致单位可能是标幺值也可能是有名值负荷可能是恒功率也可能混有恒阻抗和恒电流。我的建议是换网之前先用Matpower做一次潮流校验确认数据在潮流计算层面是正确的再接入优化调度代码。如果潮流都算不对优化结果只会错得更离谱。再有一个细节是DG接入位置的调整。换了网络后DG接入节点可能需要重新选择不能直接沿用原代码里的dg_bus数组。我习惯在数据文件里单独维护一个DG接入配置表每次换算例只需要改这个表就行不需要动模型代码。这个习惯帮我省了很多重复调试的时间。写在最后的操作体会这套两阶段优化调度模型前前后后我调过不下几十个算例版本。最初我用的是单阶段MINLP粒子群一跑就是几个小时还经常陷入局部最优改成两阶段框架后CPLEX基本几十秒内就能收敛而且解的质量更稳定。这让我切身体会到电力系统的调度决策分层分阶段不是偷懒而是顺应物理结构最自然的建模方式。如果你准备在自己的项目里复现这套代码我给几个非常具体的建议第一先用不加DG的33节点系统跑通整条链路确认潮流、优化、绘图没问题后再加DG和储能第二目标函数里的权重参数一定要做灵敏度扫描别用文献里的参数直接套第三两阶段之间的信息接口要在代码层面显式定义清楚方便后续扩展成日内滚动调度。做完这些基础工作你可以继续往两个方向扩展一是把日前阶段替换成鲁棒优化或者随机优化应对光伏和负荷预测误差二是在阶段二加入三相不平衡约束把模型从单相配电网推广到实际低压配电网。这都是在现有代码框架上可以逐步迭代的路径祝大家调试顺利跑出漂亮的结果。