主动配电网源-荷-储协同优化调度:IEEE33节点Matlab实现与复现 最近整理自己之前调试过的一个课题把“考虑源-荷-储协同互动的主动配电网优化调度研究【IEEE33节点】Matlab代码实现”这套流程重新跑了一遍。说实话这个项目名字看着很长但拆开来看就三件事一是用IEEE33节点这个经典的配电网测试系统作为算例二是把源光伏/风电等分布式电源、荷可调负荷/需求响应、储储能电池三类资源同时放进调度模型三是在Matlab里用优化求解器把这套模型解出来。这篇内容适合两类人看一类是刚开始做配电网优化方向的研究生想找一个能快速跑通、有公开数据、能和文献对得上的复现框架另一类是已经会跑潮流但对“优化调度”里目标函数和约束条件怎么搭还比较模糊的工程师。下面就当是我的一个项目复盘从模型怎么设计、代码怎么实现到坑在哪里一次性说清楚。1. 项目整体设计源-荷-储协同互动到底在调度什么1.1 为什么是主动配电网而不是传统配电网传统的配电网运行模式其实很“被动”上级电网往馈线送电末端负荷有多少用多少配电网自身基本不做决策。但线路里接入分布式光伏之后情况就变了。光伏出力中午高、晚上低和负荷曲线完全反向再加上用户侧电动汽车、空调这类负荷在峰时扎堆配电网出现的问题已经不再是简单的“带得动带不动”而是电压越限、支路过载、倒送功率这类新型问题。主动配电网的概念就是在这个背景下提出的核心是让配电网具备主动管理能力可以对网内可控资源做统一调度。这里说的“可控资源”就是源-荷-储三件事。源-荷-储协同翻译成大白话就是光伏要尽量多发电但发多了会抬升电压那就让储能把多余的电存起来或者让负荷在光伏多的时候多用一点到了晚上光伏不出力、负荷爬升的时候储能再把电放出来需求侧也适当削减可调负荷。整个优化调度的本质是在一个或多个目标通常是运行成本最小、网损最小或电压偏差最小下决定每个时段分布式电源出多少、储能充还是放、负荷调多少、向主网买多少电。这比单纯做“光伏储能”的容量配置复杂得多因为它是一个包含时间耦合储能SOC、空间耦合潮流和逻辑约束充放电互斥的优化问题。1.2 IEEE33节点测试系统为什么大家都在用它IEEE33节点系统是一个很经典的辐射状配电网算例基准电压12.66kV基准功率一般取10MVA一共33个节点、32条支路末端还有5条联络开关构成闭环但正常运行态开环。整个系统的总有功负荷大约3715kW无功负荷2300kvar左右。这个算例能成为“标配”原因有三个。一是参数公开绝大多数论文里都附带了支路阻抗和节点负荷数据找起来方便不用自己凭空造电网。二是网络规模不大不小33个节点刚好能反映配电网的辐射状结构和电压分布特征末端电压偏低的问题也够典型。三是对比结果容易因为同行都用这套系统优化前后网损多少、电压抬升多少大家心里都有数。在这样一套系统上做源-荷-储协同调度通常的做法是选几个节点接入光伏电站我个人的常用配置是17号、21号节点储能系统放在8号、25号等靠近末端或负荷较重的节点可调负荷一般集中放在几个大的负荷节点上。这样设置的理由也朴素——末端节点电压问题更严重把储能放那里能起到支撑电压的效果光伏放在离首端远的节点更容易体现“高渗透率接入后电压抬升”这个冲突然后调度模型怎么去化解这个冲突就成了值得研究的内容。2. 核心模型拆解成本函数、决策变量和约束这样搭2.1 决策变量和调度周期怎么定配电网的日前优化调度一般以24小时为一个周期时间步长取1小时。这个粒度对日前源-荷-储协调调度来说完全够用因为光伏出力的预测精度在小时尺度上已经能反映基本趋势储能荷电状态的转移用小时级递推就能描述得很准确。要是把步长缩到15分钟模型精度略有提高但求解时间会涨一大截而且对日前调度来说意义不大。模型里的决策变量我建议分成四组。第一组是分布式电源的有功出力包括光伏和风机每个时段的出力是多少。第二组是储能的充放电功率为了建模方便通常把充电功率和放电功率拆成两个非负变量同时引入两个0-1整数变量表示充放电状态避免同一时段既充电又放电。第三组是需求响应量比如可削减负荷或可平移负荷在每个时段的调节量。第四组是配电网与上级电网的交换功率一般就是根节点注入的有功。每组的维度都是24×1全部加起来一个节点规模不大但有源有储有荷的模型决策变量大概在几百个量级对Gurobi这类商用求解器来说并不难处理。2.2 目标函数成本最小怎么才能体现“协同”目标函数是这个项目最核心的部分因为它直接决定了调度策略的倾向。最常见的选择是让系统总运行成本最小但“运行成本”四个字在不同文献里含义差很多。我自己的写法是把它拆成四块每一块代表一类现实代价第一块是向主网购电的成本用分时电价乘以每时段交换功率再求和。这块本质上反映的是“削峰填谷”的经济价值电价高的时段少买电电价低的时段多买电储能就有套利空间。第二块是弃光或弃风的惩罚成本光伏风机若不能全额消纳每弃一度电要付出一个惩罚系数。这个系数设得越高模型越倾向于想尽办法把可再生能源吃掉。第三块是储能的充放电损耗成本有些文献会直接折算成每度电的“用度成本”用来防止储能频繁过度充放这个系数如果设得很小能让电池寿命的影响不至于主导调度结果。第四块是需求响应补偿成本用户响应了调度就要拿补偿这个系数也不能设得太高否则模型会疯狂调用需求响应反而偏离实际。如果你对网损特别关注可以顺手把网损项加进目标函数或者作为第二个目标做多目标优化。不过多目标处理起来要加权重或画帕累托前沿复杂度会上升前期先把单目标跑通后面再扩展更合理。2.3 约束条件哪些必须写哪些容易写错约束是优化模型落到代码时最容易出问题的地方我踩过的坑基本都在这里。按重要程度排序首先是潮流约束。对配电网来说最常用的是DistFlow方程它描述的是一条支路首端流向末端的有功、无功和末端电压之间的关系。原始形式是非线性的直接丢给线性求解器是不行的所以工程里常用两种简化一种是忽略网损项把线路压降近似成线性关系另一种是引入二阶锥松弛把非线性的电流平方项替换成锥约束用Yalmip配合Mosek、Gurobi这类求解器求解。后者的精度更高也是现在论文的主流写法。既然是Matlab实现我个人推荐用Yalmip建模DistFlow二阶锥约束写起来非常方便。然后是节点电压约束通常取0.93到1.07倍额定电压作为上下限。电压约束很容易被忽略但源-荷-储协同调度最大的作用恰恰就体现在电压质量上所以这个约束一定要写进去结果分析时也一定要看电压分布图。储能约束是另一个重灾区。除了充放电功率上下限最重要的是SOC递推约束下一个时段的SOC等于上一时段SOC加上充电电量乘以充电效率减去放电电量除以放电效率。这个约束把24个时段串在了一起是整个模型里唯一的跨时间耦合项。计算时要注意单位统一功率用MW、时间用小时、能量用MWh效率在0.9左右别把充电效率和放电效率的位置写反。另外还要保证一天的调度周期结束后SOC回到初始值否则模型可能给出“一次性把电放完”的不合理策略。需求响应的约束相对简单可削减负荷量要在用户可承受范围内比如总负荷的10%到20%可平移负荷要满足平移前后总量守恒也就是削掉的量要在另一个时段补回来。这一条要不要写取决于你的DR模型是削减型还是转移型千万别用一个模型套两种需求响应类型。3. Matlab代码实现的关键环节与求解器选择3.1 环境准备工具箱和求解器怎么配先说环境。Matlab版本建议至少R2018a以后新版本对优化工具箱支持更好而且Yalmip在新版本上的兼容性也更好老版本容易出现一些莫名其妙的警告。你需要装好Yalmip它是Matlab上一个开源的建模工具箱可以把你写好的约束和目标函数自动转换成求解器能识别的标准形式极大减少自己写矩阵的负担。Yalmip的安装方式很直接去GitHub仓库下载压缩包解压之后在Matlab里addpath一下运行yalmipsetup确认路径没有冲突就行了。求解器方面如果学校有学术许可推荐Gurobi或Cplex。Gurobi对二次规划和二阶锥规划的支持都很好求解速度快给配电网这个规模的模型绰绰有余。没有商业求解器的话Yalmip还支持开源的Cbc、GLPK等但性能要差一些。纯用Matlab自带的quadprog或fmincon也能跑但遇到0-1整数变量就无能为力了而储能充放电互斥是需要整数变量的所以不推荐作为主要方案。实在没有Gurobi可以把充放电互斥约束改成连续变量的互补约束近似或者设一个很小的惩罚项但效果不如整数变量可靠。3.2 数据初始化IEEE33节点的参数录入IEEE33节点的参数录入是整个代码里最琐碎但最关键的一步。支路参数一般可以用一个矩阵存每一行是某条支路的首端节点、末端节点、电阻、电抗。负荷参数是一个数组存放每个节点的有功和无功负荷。这里有个经验基准功率取10MVA阻抗和负荷全部转成标幺值再丢进模型。为什么这么做因为有名值下电阻零点几欧、电压上万伏数值尺度差了好几个量级目标函数和约束里的各项数值病态严重求解器容易收敛困难。标幺化之后电压在1.0附近功率在零点几到几之间数值问题基本消失。DG接入位置我这里给一个常用配置光伏接17号和21号节点一个靠近末端一个在中段储能接8号节点负荷重、距离首端远电压支撑需求明显。你完全可以换别的配置但接点位置改了以后要重新检查末端节点号是不是写成了别的节点这种低级错误能让你排查半天。3.3 关键代码片段Yalmip建模三板斧用Yalmip建模的思路非常固定无非是“定义变量、写约束、写目标、求解”四步。我贴出一段储能部分的核心示意代码你体会一下写法%% 定义储能变量24时段 P_ch sdpvar(24, 1); % 充电功率 P_dis sdpvar(24, 1); % 放电功率 u_ch binvar(24, 1); % 充电状态1表示充电 u_dis binvar(24, 1); % 放电状态1表示放电 SOC sdpvar(24, 1); % 荷电状态 %% 储能约束 C []; C [C, SOC(2:24) SOC(1:23) (P_ch(1:23) * eta_ch - P_dis(1:23) / eta_dis)]; C [C, SOC SOC_min, SOC SOC_max]; C [C, 0 P_ch u_ch * P_ch_max]; C [C, 0 P_dis u_dis * P_dis_max]; C [C, u_ch u_dis 1]; % 同一时刻只能充或放 C [C, SOC(end) SOC(1)]; % 调度周期末恢复初始值目标函数的写法更直观objective sum(price .* P_grid) ... % 购电成本 sum(curtail_penalty .* (P_pv_avail - P_pv)) ... % 弃光惩罚 sum(ess_cost .* (P_ch P_dis)) ... % 储能用度成本 sum(dr_cost .* P_dr); % 需求响应补偿最后调用求解器ops sdpsettings(solver, gurobi, verbose, 0); optimize(C, objective, ops);跑完之后用value()取出各变量比如P_grid、P_pv、P_ch、P_dis、SOC再画图分析。这套流程我试过很多次只要约束和单位没问题基本一遍过。3.4 结果输出画哪些图才算把结论说清楚程序跑通只是第一步图表才是把调度策略讲清楚的关键。我的习惯是至少输出四张图。第一张是24小时的有功功率平衡图把购电、光伏出力、储能充放、负荷画在一起直观看出削峰填谷发生在哪些时段。第二张是储能SOC曲线和充放电功率曲线验证储能策略是否符合预期——正常的策略应该是低谷充电、高峰放电SOC曲线像个平滑的山谷而不是来回剧烈震荡。第三张是优化前后的节点电压分布图横轴节点编号、纵轴电压标幺值画两条曲线对比调度前后末端电压的变化幅度。第四张是需求响应的调节量柱状图一眼看出哪些时段削减了负荷。4. 实操验证从单时段到24小时调度的完整跑通4.1 第一步先验证潮流基础别急着加优化拿到IEEE33节点数据以后第一件事不是写优化而是先把基础潮流跑准。你可以用Matpower加载这段33节点数据跑一次牛拉法潮流记录下首端注入功率和末端电压和文献里的结果对一下。这一步的目的是确认数据没录错如果基础潮流都不对后面所有优化结果都没有意义。我自己第一次录数据的时候把一条支路的电阻多打了一个0潮流结果差得离谱排查了两个小时才定位到是数据录入问题。所以先跑潮流是值得的。没有Matpower的话自己写一个简单的DistFlow递归也能验算方法不限结论要对上就行。4.2 第二步加光伏加储能先把单时段优化跑通在基础潮流确认之后我建议先做一个单时段的优化问题比如选取午间光伏出力最强的那个小时优化这一个小时内光伏出力、储能充放和购电功率。单时段问题没有SOC时间耦合求解非常快特别适合用来检查约束是否写对。如果单时段能给出合理的充放电策略——比如电价高且光伏过剩时就充电说明模型的基本逻辑通了。这一步跑通了再扩展到24时段。扩展以后要重点看SOC曲线。SOC不能跳变不能低于下限更不能出现“充电和放电同时为正”这种违反物理直觉的结果。如果你的模型里用了整数变量表示充放电互斥那同时为正是不可能的除非整数约束被你不小心注释掉了。4.3 第三步做对比实验验证“协同”价值模型跑通之后要验证“源-荷-储协同”到底带来了什么最好的办法是做对比组。我常用的对比设置是这样的方案A新能源全额消纳但储能固定策略比如早上充电晚上放不参与优化方案B储能参与优化但无需求响应方案C源-荷-储全部参与协同调度。三个方案跑同一套数据分别统计购电成本、网损、电压越限情况。在我自己的场景里从方案A到方案C末端电压峰值明显下降购电成本下降幅度随电价参数不同大概在8%到12%之间网损也有改善。具体数值取决于你设的光伏容量、电价曲线和储能参数但这组对比实验至少能让“协同比不协同好”这个结论站得住脚写报告或论文时更有说服力。4.4 参数敏感性调哪些参数结果会怎么变做敏感性分析的时候最有意思的是电价差、弃光惩罚系数和需求响应可调比例。电价差拉大储能峰谷套利更积极SOC曲线的谷底更深弃光惩罚系数提高模型会宁可多向主网买电也要吃掉光伏极端时会出现“为了不弃光而倒送功率”的现象这时要注意反向潮流约束或电压约束会不会被触发DR可调比例放宽峰时的购电量会下降但用户补偿成本上升总成本曲线存在一个拐点那个拐点对应的DR比例就是比较合适的平衡点。5. 常见问题与排查技巧那些我踩过的坑5.1 求解器报错与Yalmip安装问题这类问题最烦人。Yalmip报错常见有两种一是找不到求解器通常是你指定了gurobi但Matlab路径里没有gurobi的mex文件二是约束里用了sdpvar和double混写的表达式维度对不上。排查的办法很土但有效先跑一个只有两个变量的最小线性规划测试Yalmip和Gurobi是否正常工作再把模型里所有约束逐条注释掉看哪条报错。别想着一步定位配电网模型几十条约束逐步隔离是最快路径。5.2 结果不收敛或求解特别慢不收敛大概率出在数值病态上优先检查单位是否统一。如果你坚持用有名值支路电阻可能只有0.5左右而节点电压是上万伏这两个量级放进同一个约束里求解器内部标度很差。解决办法是全部转成标幺值。求解慢则通常是因为整数变量太多比如对每台储能、每个时段都引入了两个binvar。如果储能台数较多可以尝试用Big-M法替代部分整数约束或者直接减少调度时段粒度。对IEEE33节点单配网来说24时段、1到2台储能Gurobi求解时间通常就在几秒到几十秒如果跑到了几分钟以上那大概率是模型有问题不是求解器不给力。5.3 储能SOC长时间保持在边界有一种很常见的“凑热闹”结果SOC一路冲到上限就不动了或者直接顶在上限没有任何波动。出现这种情况先看电价曲线——如果峰谷电价差太小储能套利收益覆盖不了充放电效率损耗和用度成本模型当然选择不用储能。这不是错误但不符合你要展示“储能参与协同”的目标。解决方法很简单把峰谷价差拉大或者把储能用度成本调低。反过来也是一样如果储能疯狂充放每度电都在来回折腾那说明用度成本设得太低加上去就好。5.4 需求响应调度值全是0如果模型里需求响应量全为0说明补偿成本高于它带来的购电节省模型认为调用DR不划算这本身是模型逻辑自洽的表现。但如果你想展示DR的效果可以调高DR的可调比例上限或者降低补偿系数或者把DR约束改成“削峰率不低于某一比例”的硬性约束。另外要注意一点削减型DR和转移型DR的约束不一样。如果你看到DR量全为0先回头确认一下有没有写总量守恒约束别把两种模型混在一个公式里。5.5 常见问题速查表现象可能原因排查方法求解器报“No suitable solver”Yalmip路径未加或求解器未安装运行yalmipsetup跑最小测试用例结果违背物理直觉约束漏写或单位不一致逐条隔离约束检查标幺化参数SOC曲线剧烈震荡充电效率位置写反或SOC递推单位错误核对eta_ch与eta_dis检查步长单位求解时间过长整数变量过多或模型规模偏大减少时段粒度用Big-M替代部分整数电压越限但成本很低目标函数里没有电压惩罚项或电压约束未生效优化后单独检查电压曲线确认约束已写入6. 还能怎么扩展双层、重构和多目标方向这套模型跑通之后后续的扩展空间其实很大。最常见的方向有三个。第一个是把网络重构加进来IEEE33节点本来就有5条联络开关在调度模型里把开关状态作为0-1变量配上辐射状保持约束就变成了“重构源-荷-储协同”的联合优化这类问题现在发论文依然很活跃。第二个是双层优化上层做配电网调度下层模拟用户或负荷聚合商的响应行为用KKT条件或对偶理论把下层问题并入上层形成单层MPEC模型。第三个是多目标把运行成本和碳排放量同时作为目标用加权法或改进型智能算法求帕累托前沿。我个人在实际操作中的体会是扩展功能之前一定要先把基础模型的约束逻辑吃透尤其是SOC递推和潮流约束这两个地方出错的代价最大。另有一个小技巧你可以在主程序里加一个开关参数用来选择是否计入DR、是否允许重构这样调试时能随时回到简单基准模型修改起来效率高得多。如果你正打算做类似研究我建议先不要一上来就堆功能老老实实把“光伏储能DR”的最小闭环跑通再去挑战重构或多目标——这套路径我走过省下的调试时间相当可观。