含分布式电源的配电网日前两阶段优化调度模型解析
2026/9/24 19:39:25 网站建设 项目流程

分布式电源规模化接入配电网之后,很多做调度研究的朋友都会撞上同一个问题:原来用传统辐射状配电网的潮流计算和调度方法,面对光伏、风电这种出力随机、还带逆变器无功能力的电源,就明显不够用了。电压越限、网损升高、倒送功率这些现象接踵而至。这篇内容我打算把这套"含分布式电源的配电网日前两阶段优化调度模型"从问题建模、两阶段划分逻辑、无功优化核心设计,到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支路潮流方程。

对于辐射状配电网的支路ij,DistFlow方程的核心是三条:

节点有功平衡、节点无功平衡、支路电压降落关系。其中支路电流的平方项和支路功率项之间存在一个凸松弛关系,利用二阶锥松弛(Second-Order Cone Relaxation,SOCR)可以把非凸的二次等式约束松弛为凸的锥约束。这个松弛的物理含义是:把"支路电流幅值的平方等于视在功率平方除以电压平方"这个精确等式,放宽为"电流平方不小于视在功率平方除以电压平方"的不等式。

你可能要问:松弛之后的最优解还是原问题的最优解吗?大量文献已经证明,在辐射状配电网且网损较小的条件下,这个松弛是精确的,也就是说松弛后的最优解会落在原问题的可行域边界上。实际算例中,只要目标函数是增函数且网络为辐射状,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建模的核心套路是:先定义变量,再写约束,再定义目标函数,最后调用solvesdpoptimize。我贴一下阶段二无功优化的核心骨架,方便你对整体结构有个直观认识。

% 阶段二:无功优化(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,那样约束变成非线性的,很多求解器处理不了或者速度极慢。

solvesdpoptimize的用法差异也要注意。老版本的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里出图要设置好FontNameFontSize,导出图片时用exportgraphics函数,矢量图用-dpdf或者-depsc,期刊论文和报告都够用。

4. 仿真验证与结果解读

4.1 算例场景设置

我用IEEE 33节点系统做了验证。基准电压12.66kV,总负荷约3.7MW+j2.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和储能;第二,目标函数里的权重参数一定要做灵敏度扫描,别用文献里的参数直接套;第三,两阶段之间的信息接口要在代码层面显式定义清楚,方便后续扩展成日内滚动调度。

做完这些基础工作,你可以继续往两个方向扩展:一是把日前阶段替换成鲁棒优化或者随机优化,应对光伏和负荷预测误差;二是在阶段二加入三相不平衡约束,把模型从单相配电网推广到实际低压配电网。这都是在现有代码框架上可以逐步迭代的路径,祝大家调试顺利,跑出漂亮的结果。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询