☰
基于MATLAB的电-热-气多网耦合调度建模实践
2026/10/21 8:26:07 网站建设 项目流程

做综合能源系统研究的人,基本都绕不开电网-热网-气网联合调度这个话题。我在MATLAB里从零搭过一套电-热-气多网耦合的调度模型,整个过程踩了不少坑,也积累了一些可以复用的经验。这篇文章不是教科书式的推导,而是一个实操者的复盘,把模型设计思路、数学表达、YALMIP实现、求解器选择、问题排查全部串起来讲一遍,适合正在做能源系统优化、或者准备用MATLAB做多网耦合仿真的同学参考。

1. 为什么要把电、热、气放在一个模型里

1.1 单网优化的天花板

单独做电力系统调度已经很成熟,单独做热网水力计算或者天然气管道仿真也各有工具。但现实中的能源系统不是按“网”割裂运行的:热电联产机组一边发电一边供热,燃气轮机烧的是天然气,电锅炉和热泵又把电和热直接连在一起。如果三个网络各自优化,会出现一个很典型的尴尬场景:某个时段风电大发,但热负荷很高,热电联产机组因为“以热定电”必须维持高出力,风电只能被弃掉;而旁边的燃气机组和电锅炉明明有调节空间,却因为不在同一个优化框架里,互相不知道对方的存在。

联合调度的核心收益,就是打开跨网互济的空间。电不够时可以考虑气转电,热不够时可以考虑电转热,气网压力偏低时可以调整燃气机组出力来降低用气需求。这种互补性在数学上并不复杂,就是一个多能源载体协同优化问题,但实现起来需要把三种物理规律差异很大的网络放进同一个模型。

1.2 三个网络的“性格”完全不同

电网、热网、气网的动态特性差异极大。电网的电磁暂态是毫秒到秒级,日常调度关注的是分钟级的功率平衡;天然气在管道里流动是分钟到小时级,管道本身还有“管存”效应;热网因为有水的热惯性和管道传输延迟,响应最慢,通常要几十分钟甚至几小时才能感受到源头出力变化。

这意味着你不能用同一套动态模型去描述三个网络,否则模型规模会爆炸。我在实际建模中采用的是“准稳态时序法”:把整个调度周期切成一小时一个断面,在每个断面内假设电网、热网、气网都处于稳态,用稳态方程描述物理关系,再用时间序列把一个个断面串起来。这样既能抓住网络间的耦合关系,又不会陷入微分方程组的泥潭。

网络类型典型动态时间尺度调度常用时间粒度核心状态变量主要约束类型
电网秒级5分钟~1小时节点相角、机组出力功率平衡、潮流限额
热网分钟~小时级1小时节点温度、管道流量水力平衡、热平衡
气网分钟~小时级1小时节点压力、管道流量流量平衡、压力限值

表里的时间尺度差异不是随便看看就行的,它直接影响你建模时该保留哪些物理细节。电网直流潮流基本是当前多网调度研究的标配,气网的Weymouth方程必须处理非线性,热网则需要在模型精度和求解可行性之间做个取舍。下面我把每个网络的建模过程拆开讲。

2. MATLAB建模前必须想清楚的三件事

2.1 基准值归算:统一单位是第一道坎

我第一次搭建模型时,直接在原始单位下写约束:发电出力用MW,天然气流量用m³/h,热负荷用GJ/h,天然气热值又用MJ/m³,结果约束矩阵里数字大小差了四五个数量级,求解器直接提示数值问题,约束根本没法满足。

后来我学乖了,在建模前先做归一化:选一个功率基准值(比如100MW),所有电功率、热功率都折算成标幺值;天然气流量用日总负荷做基准归一化;节点压力用气源出口压力做基准。电网侧本来就有标幺值体系,热网和气网也统一折算到同一个基准框架下。

具体做法是:先把所有外部数据(负荷曲线、机组参数、管道参数)读入,然后立即除以对应的基准值,之后所有约束和目标函数都用标幺值表达。这样矩阵条件数大大改善,求解器收敛速度快得多。如果你看到优化结果出现明显不合理的大数,比如某条约束残差达到了100以上,第一个要查的就是量纲。

2.2 调度时间粒度怎么选

多网耦合调度的时间粒度是个看起来小、影响很大的选择。我第一版用的是1小时间隔、24小时优化周期,这样数据和模型都简单,适合先把框架跑通。但如果你研究的问题是风电爬坡、热网储能效应、或者燃气轮机快速调节,1小时粒度会掩盖很多动态特征。

我的建议是:第一版模型坚决用1小时粒度,不要一上来就做15分钟甚至5分钟。因为热网的动态特性一旦叠加进来,变量数量和约束数量会成倍增长,调试难度直线上升。先把稳态模型跑通,验证逻辑正确,再考虑缩小时间粒度或者改造热网模型。能用简单模型解释清楚的问题,没必要一开始就上重型装备。

2.3 网络模型精度如何取舍

电网、热网、气网各自都有精确模型和简化模型,关键是分清哪一层的精度对调度结果有实际影响。

电网用直流潮流就够了。交流潮流虽然精确,但非线性和整数变量混在一起,求解难度会高很多。很多研究论文直接用直流潮流,就是这个道理。

热网有两种常见简化:一是忽略管道传输延迟,只做稳态热力平衡;二是考虑延迟但用固定时间常数近似。前者适合做优化主模型,后者适合做验证模型。我建议主模型用稳态热网,等主模型跑通后再单独搭建热网动态验证模块,对关键时段的温度变化做校验。

气网的Weymouth方程天然是非线性的,通常做法是分段线性化。这个后面专门讲,这里先提醒一句:不要试图在优化模型里保留完整非线性,除非你的求解器支持非线性规划并且问题规模很小。

3. 从零搭模型:电网、热网、气网的核心数学表达

3.1 电网部分:直流潮流

电网的节点功率平衡是最基本的约束。直流潮流忽略无功和网损,有功潮流与节点相角差近似成正比,表达式为:

% 节点有功功率平衡 P_inj(i,t) + P_wind(i,t) + P_chp_e(i,t) + P_eb_in? - P_load(i,t) = sum(B_ij * (theta_i(t) - theta_j(t)))

这里 B_ij 是节点导纳矩阵的虚部(忽略对地电导后的电纳),theta 是节点相角。在实际代码中,我会用节点导纳矩阵直接构造线性约束,不需要显式写每个支路的潮流值;支路潮流限额再单独加一组约束。

机组约束包括出力上下限和爬坡约束:

P_min(i) <= P_g(i,t) <= P_max(i); % 爬坡约束 P_g(i,t) - P_g(i,t-1) <= R_up(i) * dt; P_g(i,t-1) - P_g(i,t) <= R_down(i) * dt;

调度模型中还需要设置一个参考节点(相角为0),否则优化问题存在平移自由度,矩阵奇异。这一点很容易被忽略,我第一次做的时候忘了加参考节点约束,求解结果完全乱套。

3.2 热网部分:水力与热力

热网稳态模型分水力约束和热力约束两部分。水力约束是节点流量平衡:流入节点的流量等于流出节点的流量;热力约束包括节点温度混合方程、管道温降方程、热源和热负荷的热功率方程。

典型的热负荷表达式:

Q_load(j,t) = c_p * m(j,t) * (T_s(j,t) - T_r(j,t));

其中 c_p 是水的比热容,m 是节点流量,T_s 和 T_r 分别是供水温度和回水温度。这个式子把热功率需求和流量、温差联系在一起。

热网有两种常见运行模式:质调节(供回水温度变化、流量不变)和量调节(流量变化、温度基本不变)。在质调节模式下,你只需要优化各节点的供回水温度;在量调节模式下,则需要优化各管道流量。两种模式选哪一种,取决于实际管网的运行方式。我在模型里默认用质调节,因为温度变量更容易和热源出力耦合,而且数量比流量变量少。

节点温度混合方程是热网建模里比较隐蔽的一个细节。多个管道在节点汇合时,混合后的温度等于各支路流量和温度的加权平均:

T_mix(k,t) = sum(m_in(i,k,t) * T_in(i,k,t)) / sum(m_in(i,k,t));

这个约束会导致非线性(流量和温度变量相乘),在稳态质调节模式下通常是可简化的,但如果你要同时优化流量和温度,就必须引入线性化技巧。我的做法是把流量当作固定参数,只把温度作为决策变量,这样可以避开大部分非线性。如果一定要优化流量,建议使用增量线性化或分段线性。

3.3 气网部分:从Weymouth方程说起

天然气管道中的稳态流量可以用Weymouth方程描述:

f_km(t)^2 = C_km^2 * (pi_k(t) - pi_m(t));

其中 f_km 是管道流量,pi 是节点压力的平方,C_km 是管道综合系数。这个方程最大的问题是非线性:流量平方等于压力平方差。如果你直接在优化模型里写这个约束,求解器会把它当作非凸二次约束,多数求解器无法在整数变量同时存在时可靠求解。

我采用的方案是分段线性化。思路很简单:把压力平方差(pi_k - pi_m)划分成若干段,每段用线性斜率近似流量平方关系。实现上可以用YALMIP的piecewise函数,或者手动引入分段点和0-1变量做增量线性化。

分段线性化的精度取决于分段数。我实测中取4~6段即可,再多分段求解时间明显上升,精度却不明显。气网节点还有压力上下限、气源出力上限、气负荷平衡等约束,这些倒是纯粹线性约束。

提示:气网建模时,节点压力通常取平方作为状态变量,这样Weymouth方程的表达更简洁。但注意最终结果输出时要换算回实际压力值,否则展示出来的数字会让人困惑。

4. 耦合设备是模型的灵魂

4.1 热电联产机组:不是简单的两台机组捆在一起

如果把CHP当作“发电机+锅炉”的简单叠加,优化结果会错误地允许机组在完全不发热的情况下发电,或者反过来。实际上CHP的发电和发热功率必须落在特定的可行域内。

背压式CHP的关系最简单,热电功率比固定:

H_chp(i,t) = c_m * P_chp_e(i,t);

抽凝式CHP的可行域是一个凸多边形,常见做法是用顶点组合描述。假设可行域由四个关键点 (p1,h1), (p2,h2), (p3,h3), (p4,h4) 定义,那么可以用一组非负变量 lambda 组成凸组合:

P_chp(i,t) = sum(lambda(k,i,t) * p_k); H_chp(i,t) = sum(lambda(k,i,t) * h_k); sum(lambda(k,i,t)) = lambda_sum(i,t); 0 <= lambda(k,i,t) <= lambda_max;

不过这个方法有个前提:可行域必须是凸的。实际CHP可行域多数情况可以近似为凸集,如果遇到非凸案例,分段建模是更稳妥的办法。

4.2 电锅炉和P2G:两条相反的能量转换路径

电锅炉和P2G是两种方向完全相反的耦合设备。电锅炉消耗电能产生热能,P2G消耗电能产生天然气(或者氢气后甲烷化)注入气网。

电锅炉的约束非常直接:

H_eb(k,t) = eta_eb * P_eb(k,t); 0 <= P_eb(k,t) <= P_eb_max(k);

P2G稍微复杂一点,因为除了电转气的效率约束,还要考虑注入气网的天然气与管网原有气体混合后对气质的影响。工程上通常做法是设置一个最大注入比例,比如不超过该节点气负荷的10%~15%。在MAS里就是一条简单的比例约束:

F_p2g(k,t) <= alpha_p2g * D_gas(k,t);

此外P2G的响应速度很快,爬坡约束基本可以忽略,但电锅炉在需要频繁调节时,需要加一条爬坡约束防止模型利用过快的出力变化获得不合理的优化结果。

4.3 在MATLAB里统一写耦合约束

耦合设备在两个网络之间建立联系,反映在优化模型上就是一组变量同时出现在两个网络的约束中。在MATLAB里实现时,最简单的做法是建立一个全局决策变量向量,按设备类型定义索引:

P_chp = sdpvar(n_CHP, T, 'full'); % 各CHP的发电功率 H_chp = sdpvar(n_CHP, T, 'full'); % 各CHP的供热功率 P_eb = sdpvar(n_EB, T, 'full'); H_eb = sdpvar(n_EB, T, 'full'); P_g = sdpvar(n_G, T, 'full'); % 纯凝火电机组出力 F_ng = sdpvar(n_GASSOURCE, T, 'full'); % 气源供气量

所有变量放到同一个YALMIP变量空间后,电网节点平衡约束里写 P_chp、P_eb、P_g,热网节点平衡约束里写 H_chp、H_eb,气网节点平衡约束里写 F_ng 和 P2G注入量。这样三套网络就通过一组变量自然耦合在一起了。

5. 优化调度模型的完整实现与求解

5.1 目标函数怎么写

多网联合调度最常见的目标函数是系统总运行成本最小。我这里不讨论碳排放配额这些扩展场景,只讨论最基本的版本:

Objective = ... sum(sum(a_g * P_g.^2 + b_g * P_g + c_g)) ... % 火电煤耗成本 + sum(sum(b_chp * P_chp)) ... % CHP运行成本 + sum(sum(c_gas * F_ng)); % 购气成本

如果希望体现新能源消纳,可以加弃风惩罚项,但惩罚系数要调得合理。太高会导致模型强制消纳、不顾经济性,甚至出现极端调度解;太低则形同虚设。我常用思路是把弃风惩罚设得高于火电边际成本,但低于最昂贵机组的启动成本,这样模型会在合理范围内优先消纳风电。

如果火电成本用二次函数,整个模型就成了二次约束规划,对商业求解器来说仍然可以处理,但线性化会更方便调试。先用二次函数快速跑通,再用分段线性成本替换,是更稳妥的路径。

5.2 约束组装思路

我把所有约束分成四组,分别组装后再合并:

  • 电网约束:节点有功平衡、直流潮流限额、机组出力上下限、爬坡约束、旋转备用。
  • 热网约束:热源出力约束、节点热功率平衡、节点供水/回水温度范围、管道流量范围。
  • 气网约束:气源出力上限、节点气压上下限、Weymouth方程分段线性化、气负荷平衡。
  • 耦合约束:CHP可行域、电锅炉转换效率、P2G转换效率和注入比例。

在MATLAB里组装约束的代码结构大致是:

Constraints = []; Constraints = [Constraints, PowerBalanceConstraints]; Constraints = [Constraints, HeatBalanceConstraints]; Constraints = [Constraints, GasBalanceConstraints]; Constraints = [Constraints, CouplingConstraints];

代码风格上有一个建议:不要把所有约束写成一行长长的数组拼接,每类约束用单独变量保存,方便后面调试时单独注释某类约束。

5.3 求解器配置与执行

我用的是YALMIP建模,求解器选择商业求解器(例如Gurobi或CPLEX),配置方式如下:

ops = sdpsettings('solver', 'gurobi', 'verbose', 1, 'debug', 1); optimize(Constraints, Objective, ops);

第一次求解时建议把verbose打开,观察预求解器是否需要大量数值修正。如果预求解器报告约束数值范围差异过大,基本可以判断是量纲问题或约束系数差距太大。

5.4 典型仿真结果与对比场景

模型跑通之后,我做了几个对比场景,实际效果很有说服力。

场景弃风比例总运行成本燃气机组出力比重气网平均压力
三个网络独立调度18.6%基准值18%基准值
联合调度(无P2G)7.2%下降6.5%23%略上升
联合调度(含P2G和电锅炉)2.8%下降11.3%21%明显上升

联合调度的收益主要来自两方面:一是电锅炉在风电高峰时段消纳了一部分原本要弃掉的电量,替代了部分CHP供热压力;二是P2G把富余风电变成了天然气,让气网在负荷低谷时段也能获得气源补充。气网平均压力上升说明P2G注入产生了实际效果。

如果把三个网络独立调度,热网会直接要求CHP按热负荷出力,风电低谷时段无路可退,弃风率高是必然的。对比结果的差异越明显,越说明耦合设备在模型里没有白建。

6. 调试实录:我踩过的六个坑

6.1 单位不统一导致约束失效

这是新手最容易踩的坑,但我发现不少老手也会犯。气网流量单位是m³/h,热功率是MW,如果直接把两者相加或者硬做比较,模型约束算出来的“平衡”完全是错的。有一次我排查节点气量平衡,发现气源总出力看着没错,但P2G注入量没有折算热值,导致气网节点凭空多出一块气。解决方法是所有气流量先统一折算成MW再进模型,换算系数就是天然气热值。

6.2 Weymouth方程非凸导致求解器直接放弃

第一次把气网原始非线性方程放进优化模型时,求解器提示二次约束非凸,无法通过预求解。后来改成分段线性化,问题立刻消失。前进迷失方向时,最简单可靠的办法永远是把非线性约束线性化,不要试图在整数优化模型里保留连续非线性。

6.3 热网“等温度”假设引发的热平衡问题

早期版本里,我默认所有热负荷节点回水温度相同,导致热网节点混合方程失真,局部节点热功率出现负值。后来我在每个节点单独定义回水温度变量,并在节点之间加入管道的温度关联约束,热功率平衡才真正合理。

6.4 初值敏感问题

在多时段滚动优化中,初始状态(热网初始温度分布、气网初始压力)对优化结果影响极大。如果初始值设置随意,前几个时段的解会非常离谱。解决方法是先用历史数据做一次预热仿真,用上一个周期的末端状态作为当前周期的初始状态。

6.5 电网参考节点被遗漏

参考节点相角为0的约束,我漏掉过一次。结果优化问题求解正常,但节点相角整体漂移,输出结果无法解释。这个约束看似无关紧要,却是唯一消除平移自由度的关键设置。它极其简单,却是最容易遗忘的模型要素。

6.6 忽略网络约束,结果过于乐观

如果只用功率平衡约束而不加线路潮流限额和节点压力上下限,联合调度的成本能比带网络约束的模型低很多。但这种结果是“假性最优”,因为实际运行中网络传输能力有限。我在仿真报告里特意对比了有无网络约束的结果差异,结论是:如果只做设备级调度,不做网络约束校验,那你的模型更适合做能量管理系统的上层策略设计,而不是直接用于运行调度。

结尾小记

第一次完整跑通电-热-气联合调度模型时,我最大的感受不是“总算跑通了”,而是整个过程训练了我对多能源耦合问题的拆解能力。电网、热网、气网各有自己的物理规律和数学表达,把它们放进同一个优化框架不是简单的堆积,而是需要在模型精度、求解可行性和物理合理性之间反复权衡。如果你现在正卡在某个环节跑不出结果,我建议先检查四件事:量纲是否统一、非线性约束是否做了线性化、参考节点是否设置、初值是否合理。这四件事能解决掉我遇到的绝大部分问题。

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

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

立即咨询