ARTICLE DETAIL

资讯详情

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

多微网能量互联低碳经济调度:Matlab+Yalmip+Gurobi实战解析

多微网能量互联低碳经济调度:Matlab+Yalmip+Gurobi实战解析 多微网能量互联优化调度简单说就是把好几个微电网用联络线连起来在一个统一框架里协调各自的光伏、风电、储能、燃气轮机和买售电策略最终让整个系统在满足负荷需求的同时花最少的钱、排最少的碳。这篇文章要讲的“三微网”场景就是从这里切入的——我有段时间一直在做这个题目在Matlab里搭了一套完整的优化调度模型包含三个微电网通过两条联络线互联目标函数同时纳入了运行成本、储能损耗、弃风弃光惩罚和碳排放成本最后用Yalmip加Gurobi求解。整个过程踩了不少坑今天把思路、模型、代码逻辑以及调试经验一次性整理出来。适合正在做微电网优化调度、综合能源系统调度、低碳电力系统研究的人参考也适合已经入门Matlab优化但还没把多主体协调理清楚的同学。1. 三微网能量互联调度到底在解决什么问题1.1 从单微网到多微网为什么一定要“互联”单个微网看似自给自足实际运行中痛点非常明显光伏夜间完全不出力风电一阵有一阵没储能容量又有限负荷峰谷变化一大会出现本地功率缺口。这时候只能从上级电网买电或者启动燃气轮机。而电网购电峰时电价高火电占比高碳排也高燃气轮机燃料成本和维护成本同样不低。如果周围还有其他微网情况就不一样了。A微网午间光伏大发本地负荷用不完B微网这时候正好负荷冲上来有了联络线A的富余光伏就能送到B双方都省了向主网买高价电的钱。多微网能量互联的核心就是“空间上的功率互济”用网络互联替代单点堆储能用调度的全局协调换取整体经济性和低碳性。这种互联不光是多个微网“接一根线”而是要在调度层面统一决策每个微网内部的电源出力、储能充放电以及微网之间的交换功率。因为每个微网对电价、碳价、负荷和新能源预测的反应不一样分散控制很可能出现“各自为战”明明邻居有富余风电自己还在开燃气轮机整体结果自然不是最优。集中式统一优化调度才能把这种互补潜力挖出来。1.2 低碳目标为什么不是单纯“少买电”如果只盯着经济成本优化器会在主网购电价低的时段大量买电本地燃气轮机能不启就不启。但很多地区电网的隐含碳排放因子很高买电多不代表低碳。反过来如果只盯着碳排放把所有购电压到最低那一遇到负荷高峰就会频繁启动燃气轮机甚至让储能超负荷放电结果可能是总成本暴涨储能的寿命也大幅缩短。所以“低碳经济运行”不是一句口号而是要把碳排放在目标函数里换算成成本让优化器在每个时段都做一次权衡多买一度电要多花多少钱对应多少碳排放多发一度气电要多花多少天然气成本又能比买电少排多少碳。最终形成的是总代价最小、各微网协同的调度方案。这个思路和碳交易市场实际机制也是一致的碳有价格环境有成本调度自然就往低碳方向走。1.3 项目的适用范围与研究价值我做的这个三微网算例可以看作一个最小可用模型实际应用时完全可以扩展到园区微电网群、校园多微网、海岛微网群。从研究角度看可以先做确定性日前调度再扩展不确定性、滚动修正、多场景随机优化从工程角度看日前计划加日内调整也已经足够支撑一个实际系统的能量管理模块。对正在做毕业设计或论文的人来说这套模型可以直接作为基准。代码上最大的价值是把经济目标和低碳目标统一到一个优化框架里后续无论加哪类约束只要按同样的方式写进去就行。很多同学卡在“不知道怎么把目标函数和约束用代码写出来”本文后面给出的Matlab实现思路就是冲这个痛点去的。2. 低碳经济运行优化调度模型设计2.1 三微网系统结构假设我做的算例是三个微网通过两条联络线接成一个链式结构MG1和MG2之间一条线MG2和MG3之间一条线每个微网又通过公共连接点PCC与上级配电网相连。为什么用链式而不是完全互联一方面是方便刻画联络线功率方向和潮流逻辑另一方面链式已经能体现多微网能量互联的核心特征功率流向会随电源和负荷变化而变化一个微网从邻居取电就不用再向主网购电。具体参数如下表调度周期24小时步长1小时所有量纲统一为kW、kWh、元。子微网分布式电源储能配置燃气轮机峰值负荷与主网联络上限MG1光伏600 kW200 kWh / 100 kW无800 kW300 kWMG2风电500 kW150 kWh / 80 kW无700 kW300 kWMG3光伏400 kW100 kWh / 50 kW200 kW600 kW300 kW两条微网间联络线最大传输功率均为200 kW不区分正反向。这里的分布式电源出力用的是预测值也就是确定性日前调度。如果后续要考虑预测误差可以在日内滚动优化中把预测数据不断更新模型结构基本不用动。2.2 目标函数的经济账目标函数不是一个干巴巴的公式这几项成本背后都是实际工程中的钱和碳排放。我用文字拆一遍公式上用统一写法min C_total C_grid C_fuel C_battery C_curtail C_carbon C_link其中 C_grid 是与主网买卖电费用的统一表示每个时段购电花费减去售电收入。这里有个方向问题同一时刻低买高卖不可能出现在优化结果里但为了严谨还是要加二进制互斥约束防止退化解。C_fuel 是燃气轮机消耗天然气折算的成本。C_battery 是储能充放电带来的寿命损耗和运维成本按充电功率加放电功率再乘一个单位老化成本系数。很多人刚开始会漏掉这一项结果储能被优化器当成“免费电池”反复深度充放实际工程里根本不可行。C_curtail 是弃风弃光惩罚。虽然我们希望100%消纳风光但网络和储能限制下偶尔也要弃如果不加惩罚优化器可能为了少用高价燃气而随意切新能源。C_carbon 是碳排放成本对主网购电和燃气轮机排放分别按排放因子折算再乘碳价。C_link 则是联络线传输成本可以理解成网络线损分摊和联络线运维费用的简化表达用联络线功率绝对值的线性函数。2.3 约束条件逐条拆解功率平衡约束是核心。对每个微网每个时段都需要满足本地光伏发出功率 风电发出功率 储能放电功率 主网购电功率 燃气轮机出力 相邻微网输入功率 本地负荷 储能充电功率 向主网售电功率 向相邻微网输出功率。储能约束包括SOC递推方程、SOC上下限、充放电功率上下限和充放电互斥约束。SOC递推方程本质就是把“剩的电量”加上“充进去的”减去“放出来的”充电效率和放电效率都要考虑单位统一需要特别注意。燃气轮机约束包括出力上下限、爬坡约束和启停变量逻辑。我在模型里给MG3加入了启停变量这样更贴近实际机组运行情况否则模型会退化成一个纯线性规划无法反映频繁启停对成本和寿命的影响。联络线约束是两条线路各自的传输功率上下限功率方向可变。与主网交互约束则包括购电功率上限和售电功率上限。最后储能还有一条周期约束一个调度周期结束时SOC要回到初始值附近。这一步特别容易被忽略如果没有它优化器会在最后几个时段把储能放空得到一个“账面最优但实际不可持续”的解。2.4 为什么用碳价而不是碳约束很多人会问低碳目标为什么不直接加一个“总碳排放量不超过某上限”的约束当然可以但效果不一样。硬性碳约束是个不等式边界在约束没达到之前优化器对碳排放完全没有感知一旦达到边界又会突然牺牲经济性调度结果在碳边界附近会出现不自然的陡变。把碳排放转成碳价放进目标函数相当于给每度风光、每度火电都标了环境代价。优化器在每个时段都会主动比较“用电网的代价”和“用燃气轮机的代价”这种连续调节逻辑更符合“低碳经济运行”的目标也更适合做碳价敏感性分析。我在模型里用碳价加可选碳配额的方式后续想切换成硬约束只要把碳排放总量限制写成一行约束即可。3. Matlab代码实现从数据准备到求解器配置3.1 整体代码结构很多初学者喜欢把一整套调度代码堆在脚本里跑通一次还好换场景、换参数就灾难。我建议把代码拆成几个功能文件main_microgrid_optimization.m主函数入口get_base_data.m返回负荷、风电、光伏、电价等基础数据build_opt_model.m用Yalmip搭建模型输出约束和目标函数solve_model.m调用求解器处理结果plot_results.m结果可视化和生成表格。这样拆的好处是数据、建模、求解、后处理互不干扰。换场景时只改数据文件换算法时只改求解文件跑多场景仿真时也方便批量循环。3.2 参数初始化的易错点先给一段示意代码说明负荷、风光、电价这些基础数据怎么组织%% 基础数据单位统一到kW和kWh T 24; % 时段数 N_MG 3; % 微网数量 % 光伏预测出力每行一个微网每列一个时段 Ppv_forecast zeros(N_MG, T); Ppv_forecast(1, :) [100 120 150 180 220 300 400 550 600 580 520 450 380 300 250 200 150 120 80 50 30 20 30 40]; Ppv_forecast(3, :) Ppv_forecast(1, :) * 0.6; % 风电预测出力 Pwt_forecast zeros(N_MG, T); Pwt_forecast(2, :) [350 380 420 480 500 450 380 300 250 200 180 160 200 280 350 420 450 480 500 520 480 420 380 340]; % 负荷 Pload [ 500 450 420 400 420 500 650 780 800 760 700 650 620 680 720 780 750 700 650 620 680 720 700 600; 420 400 380 360 380 450 550 650 700 680 620 580 560 600 650 700 680 620 580 540 580 600 560 500; 350 330 320 300 320 400 480 560 600 580 520 480 460 500 550 600 580 520 480 440 480 500 460 400 ]; % 分时购电价和售电价单位元/kWh buy_price [0.4*ones(1,7), 0.8*ones(1,5), 1.2*ones(1,5), 0.8*ones(1,3), 1.2*ones(1,4)]; sell_price 0.35 * ones(1, T);要特别强调单位统一。很多bug都是因为光伏用了kW、储能用了MWh、电价用了元/MWh最后量纲对不上。建议全部统一成kW、kWh、元。另外风光预测数据本身已经是理论上限不要在后面又加“容量限制”容易重复约束。3.3 Yalmip建模的关键代码Yalmip的伟大之处在于你不需要手动把决策变量拼成一个长向量直接按数学模型的思路写变量和约束就行。我先定义决策变量Pbuy sdpvar(N_MG, T, full); % 购电 Psell sdpvar(N_MG, T, full); % 售电 Pch sdpvar(N_MG, T, full); % 储能充电 Pdis sdpvar(N_MG, T, full); % 储能放电 SOC sdpvar(N_MG, T, full); % 储能SOC Pmt sdpvar(N_MG, T, full); % 燃气轮机出力 u_mt binvar(N_MG, T, full); % 燃气轮机启停 % 联络线变量正方向定义为MG1-MG2和MG2-MG3 P_link12 sdpvar(1, T, full); P_link23 sdpvar(1, T, full); % 联络线功率绝对值辅助变量用于线性化目标函数 P_link12_abs sdpvar(1, T, full); P_link23_abs sdpvar(1, T, full); % 新能源实际出力变量 Ppv_use sdpvar(N_MG, T, full); Pwt_use sdpvar(N_MG, T, full);接着添加约束。MG1的功率平衡示例C []; for t 1:T % P_link12(1,t)为正时表示MG1向MG2输出功率 C [C, Ppv_use(1,t) Pdis(1,t) Pbuy(1,t) Pload(1,t) Pch(1,t) Psell(1,t) P_link12(1,t)]; endMG2的功率平衡则要把P_link12作为输入把P_link23作为输出for t 1:T C [C, Pwt_use(2,t) Pdis(2,t) Pbuy(2,t) P_link12(1,t) Pload(2,t) Pch(2,t) Psell(2,t) P_link23(1,t)]; end目标函数里需要联络线绝对值的线性化做法是加辅助约束C [C, P_link12_abs(1,t) P_link12(1,t), P_link12_abs(1,t) -P_link12(1,t)]; C [C, P_link23_abs(1,t) P_link23(1,t), P_link23_abs(1,t) -P_link23(1,t)];最后求解objective sum( ... ); % 按2.2的表达式拼起来 ops sdpsettings(solver, gurobi, verbose, 2); result optimize(C, objective, ops);如果设置正确Gurobi会在几秒内返回优化解之后直接value(Pbuy)取值再画图。3.4 求解器的选择建议我用过好几类求解器直观感受如下求解器可处理问题优点缺点适用情况GurobiMILP、QP、MIQP快、稳、支持热启动商用授权学术可申请主推方案CPLEXMILP、QP、MIQP与Gurobi相近授权限制类似已有license可用intlinprogMILPMatlab自带零配置大规模效率偏低先验证模型粒子群等任意非线性实现简单不用求解器不保证全局最优调参麻烦算法对比我的建议很明确先装Yalmip再用Gurobi或CPLEX求解MILP。如果临时没有商用求解器把solver改成intlinprog也能跑但求解速度和稳定性就差一些。不要一上来就写粒子群因为粒子群对约束处理很麻烦很容易陷入不可行解。3.5 后处理与图表求解完成之后可以用value()函数把所有决策变量取出来。画图时我习惯这样组织三个微网各自的功率平衡堆叠图包含负荷、光伏、风电、储能、购电、燃气轮机、联络线一张图就能看出每个时段的功率流向储能SOC曲线检查有没有越限、有没有周期末未回到初始值联络线功率曲线确认没有超过200kW传输上限独立运行与互联运行的运行成本、碳排放柱状对比图。绘图用stairs而不是plot因为调度计划是分段常数阶梯图更符合实际。图例和坐标轴标签要写完整后续投期刊可以直接导出高清图。4. 典型调度结果与运行效果分析4.1 场景设置设计一个典型日为了把效果讲清楚我设计了一个夏季典型日白天光伏出力大负荷中有空调高峰晚间风资源好。主要参数如下购电分时电价谷段0.4元/kWh平段0.8元/kWh峰段1.2元/kWh售电价格统一0.35元/kWh天然气发电成本折算0.65元/kWh电网购电碳排放因子0.581 kg/kWh燃气轮机碳排放因子0.201 kg/kWh初始碳价0.08元/kg储能老化成本0.06元/kWh联络线传输损耗成本0.02元/kWh。这里把燃气轮机排放因子设得比电网低是因为天然气机组效率高、单位发电碳排放低于传统燃煤电厂。这样在高碳价下系统才有动力从“多买网电”转向“多开本地气电”和“多用风光”而不是一刀切禁止购电。4.2 独立运行与互联运行的成本/碳排放对比在相同负荷和分布式电源预测数据下我分别算了两套方案。独立运行时三个微网之间没有联络线各自与主网交互储能和燃气轮机只能各管各家互联运行时两条联络线参与优化。结果是独立运行总成本约4620元互联运行总成本约3980元成本下降约13.9%碳排放从2180 kg降到1760 kg下降约19.3%。核心原因有三个MG1午间富余光伏送到了MG2和MG3替代了峰时高价网电MG2夜间富余风电替代了MG3燃气轮机出力储能充放电策略在互联信息下更合理频繁深度充放减少电池损耗下降。光看总成本下降不够还要看功率曲线里有没有“不该出现的外送”。比如MG1自己还没满足负荷就把电送出去那一定是约束或目标函数写错了。我在调试时基本靠功率平衡图来抓这种问题。4.3 碳价变化对调度行为的影响我还把碳价从0逐渐加到0.2元/kg做了敏感性分析趋势很有意思。碳价为0时系统完全追求经济性谷段大量从主网购电燃气轮机基本不开碳价升到0.08元/kg时系统减少谷段购电增加午间光伏外送和夜间风电利用成本略有上升但碳排放明显下降碳价继续升到0.15元/kg以上系统进一步压减主网购电在负荷高峰更多启用MG3燃气轮机。这说明“低碳经济运行”不只是多花钱换绿电碳排放价格信号会重新排列不同电源的优先级。实际做政策模拟或碳交易机制研究时这种敏感性曲线非常有用也能直接作为论文里的算例分析。4.4 影响范围从三微网扩展到园区级多微网三微网是最小可扩展单元。实际园区可能有十几个微网、几十个并网节点再多也只是把节点数和联络线条数增加目标函数和约束的数学结构完全一致。如果要推广有三个问题要提前想清楚联络线矩阵化。用邻接矩阵描述拓扑而不是每条线手写一个变量。三微网手写还能接受十几个微网再手写就非常容易出错。引入网损和电压约束后模型会从MILP变成非线性或二阶锥规划需要换求解器比如Gurobi能处理的MIQP或SCIP等。数据量增加后日前确定性调度只是起点最好做模型预测控制或随机规划。三微网代码里改进滚动优化的方式就是在每个滚动窗口里重复调用优化模型只是数据窗口移动而已。5. 常见问题与Matlab调试实录5.1 求解器配置类问题最常见报错是“No suitable solver for ...”。原因就是Yalmip找不到能处理当前模型的求解器对MILP需要Gurobi、CPLEX或intlinprog。如果你用Gurobi步骤是从官网下载安装Gurobi申请学术授权在Matlab中运行gurobi_setup运行yalmiptest看到Gurobi: OK说明识别成功在代码里设置solvergurobi。如果临时没有Gurobi把solver改成intlinprog也能算但变量多之后会明显变慢。还有同学连Yalmip都没装想用Matlab的optimproblem也可以但需要把所有决策变量手动拉长成一维向量索引映射很容易出错。5.2 结果出现同时充放、同买同卖怎么处理如果约束和惩罚成本不够优化结果确实可能出现同一时段储能又充又放、主网又买又卖。原因有两个目标函数对充放功率没有惩罚储能同时充放不影响SOC但也能形成退化解数据异常或电价异常导致“越充越赚”。解决办法是加布尔变量互斥u_ch binvar(N_MG, T, full); u_dis binvar(N_MG, T, full); C [C, u_ch u_dis 1]; C [C, Pch 1e3 * u_ch]; C [C, Pdis 1e3 * u_dis];同时给充放电加上很小的老化成本也能避免零成本退化解。购售电互斥同理可以加一个布尔变量或依赖电价差。但最终还是要检查输入数据确保负荷和电价数组没有异常负数。5.3 模型不可行的排查技巧模型一旦报infeasible不要急着删约束。我的排查顺序是先把功率平衡等式拆开加入非负松弛变量看哪个节点、哪个时段的松弛量最大把所有上限约束放宽包括联络线、购电、SOC然后逐条恢复定位是哪条约束导致无界重点检查SOC初值和终值约束是不是和容量不匹配很多不可行都是初值、终值和库容约束叠得太紧检查新能源可用出力数据如果某时段光伏预测为0模型却要求光伏出力为正那自然不可行。这种逐个隔离的调试方法比乱试快得多也更能理解模型结构。5.4 求解速度慢怎么办24小时三微网MILP变量其实不算多Gurobi通常几秒内能解完。如果慢常见原因有三点。第一模型里用了非线性函数比如abs()或sdpvar相乘Yalmip可能会把问题变成非凸问题或引入额外整数变量。我的经验是尽量用辅助变量线性化避免二次项。第二二进制变量太多。三微网里燃气轮机启停变量就已经不少如果多个微网都有燃气轮机变量会成倍增加。可以按“日出力总量”或分段线性化机组发电成本减少整数变量。第三优化参数没调好。我一般会设置ops sdpsettings(solver, gurobi, gurobi.MIPGap, 0.01);允许1%的最优性间隙速度会快很多论文结果也够用。5.5 启发式算法对比时的注意事项如果论文里要把Gurobi结果和粒子群算法对比要特别注意公平性。粒子群或遗传算法需要把约束转成罚函数或修复机制否则大量粒子不满足功率平衡对比就失去了意义。我的建议是决策变量编码建议写成连续变量储能充放功率、购售电、联络线功率所有约束用罚函数处理多次运行取最好结果启发式算法每次结果不同对比时要记录计算时间和目标函数值不要直接写“PSO比Gurobi好”因为Gurobi是精确算法启发式只在非线性、大规模或求解时间受限时有讨论价值。我在做算法对比时通常先用MILP求出精确解再让启发式算法往这个精确解上靠这样能快速检验约束和罚函数是否写对。最后再分享一个我自己的小习惯无论模型多小先跑通确定性24小时算例把功率平衡、SOC轨迹、买售电曲线全部画出来逐条看有没有不符合物理直觉的尖峰再去做多场景或随机优化。优化调度这个方向模型和代码都能模仿但对物理规律和量纲的敏感度才是真正拉开差距的地方。希望这篇整理能让你少踩几个坑把更多时间留给算法创新和场景拓展。
返回列表