很多做配网优化的人一听到“气电综合能源”就头疼,因为电网、气网、负荷响应全搅在一起。这套协调优化运行代码的功能说明,核心解决一件事:在电力与天然气互联的配网系统中,如何通过气电联合需求响应,让电网削峰和气网调压在同一个优化框子里完成,而不是各调各的。适用对象是正在做配网侧综合能源仿真、需求响应策略验证或者毕业设计的同学,也适合想快速了解多能耦合优化代码结构的工程师。
1. 项目整体设计与建模思路
1.1 气电耦合系统为什么需要“协调”
很多人对综合能源的第一印象是“把电、气、热统一规划”,但真正落实到配网层面,逻辑要比主网复杂得多。配电网里分布式电源、储能、充电桩已经够让人头疼了,再加上配气网,问题的维度会瞬间翻倍。气电联合的关键在于:天然气系统与电力系统在中低压侧存在两条明显的耦合通道——燃气轮机和电转气(P2G)。燃气轮机消耗天然气发电,电转气则反过来消耗电能产生天然气。这两个设备一上一下,相当于在两个网络之间开了两个双向调节阀。
如果只做电力需求响应,系统中会出现这样的情况:电负荷高峰时,用户削减了用电,但燃气轮机还在满发,配气网的天然气需求一点没少,甚至可能因为电网削峰导致电价下降,电转气设备集中启动,气网负荷突然攀升。结果是电网削了峰,气网却憋了压。反之,如果只在气网侧做需求响应,也可能出现用户少用天然气后,燃气轮机因缺气降出力,电网不得不从上级购电,甚至拉闸限电。所以气电联合需求响应的本质,是让两个网络的负荷和可调资源在时间和空间上互相配合,用整体成本最小的方式去满足终端用能需求。
这套代码功能说明里,“协调”体现得最直接的地方就是目标函数和耦合约束的设计。目标函数不是简单的购电成本加购气成本,而是要同步考虑需求响应补偿、设备运行成本、网架安全惩罚。耦合约束也不是把电网方程和气网方程简单拼在一起,而是通过燃气轮机和P2G的输入输出关系,建立跨网络的能量流平衡。只有把这些都写进同一套优化模型里,才算真正做到了气电联合。
1.2 模型框架与代码模块划分
我在整理这套代码功能说明时,第一感觉是它的框架非常清楚,大致分为四层:数据层、模型层、求解层、后处理层。
数据层负责读入配电网拓扑、配气网拓扑、设备参数、负荷曲线、电价、天然气价格以及需求响应参数。配网侧通常采用节点支路模型,气网侧则采用天然气管道节点模型。数据层输出的不是简单的Excel表读取结果,而是一套统一结构的数据对象,方便后续模型层直接调用。
模型层是最核心的部分。代码会把电网约束、气网约束、需求响应约束、耦合设备约束分别封装成函数,再统一拼接到一个大优化问题上。这样做的好处是调试的时候可以单独检查某一块约束是否写错,而不需要每次都要跑完整模型。比如想看看需求响应参数对结果的影响,只要调整需求响应模型模块里的参数,不需要动网架约束的代码。
求解层负责调用优化求解器。代码里内置了一个求解器接口,既可以选择开源求解器,也可以切换商业求解器,只需要修改一行配置。针对气网约束中常见的非线性管道方程,代码默认采用分段线性化处理,避免直接使用非线性求解器带来的收敛问题。
后处理层输出各时段购电功率、购气量、节点电压、气网压力、DR削减量、设备出力等关键结果,并自动生成对比报表。比如可以一键对比“无需求响应”“仅电力需求响应”“气电联合需求响应”三种场景下的总成本和负荷峰谷差,这在做方案论证时非常有用。
2. 核心功能模块拆解
2.1 数据输入与场景生成
这套代码的第一个功能模块是数据输入。它不是简单读数组,而是做了一套比较规范的场景化输入。主要包含四类数据:
第一类,电网数据。包括配电网线路阻抗、节点负荷基准值、分布式光伏和风电的时序出力、上级电网购电通道容量、节点电压上下限。这些数据通常来自标准配网算例或者实际台账,需要转换成节点导纳矩阵或者功率注入模型。代码里统一使用标幺值处理电压和功率,避免因数量级差异导致优化模型病态。
第二类,气网数据。包括管道长度、直径、粗糙度、节点气负荷、气源供气能力上限、节点压力上下限、压缩机参数。这里容易踩坑的是,气网数据单位通常是立方米每小时(m³/h)或者千克每秒,而电网数据是兆瓦(MW),两者量纲不同,必须通过天然气热值换算成统一能量单位。代码里专门写了一个单位换算函数,默认以兆瓦为统一能量基准。
第三类,时空负荷曲线。对每个电网节点和每个气网节点分别设置24小时或者更长周期的负荷序列。为了模拟实际场景,代码支持在基准负荷上叠加随机波动,形成多个预测场景。比如可以生成十组等概率的场景,每个场景代表一种可能的风电、光伏和负荷状态。
第四类,需求响应参数。包括电负荷中可削减比例、可转移比例、气负荷中可削减比例、可替代比例,以及对应的单位补偿成本。这些参数决定了弹性负荷在整个系统中的“可调度容量”。代码里有一个场景生成器,可以按正态分布或者三角分布生成多种DR潜力组合,方便做鲁棒性分析。
2.2 气电联合需求响应建模
需求响应在纯电网里通常被建模成可削减负荷或可转移负荷,但在气电联合系统中要复杂得多。因为用户有可能做出“跨网替代”行为,比如电价过高时,用户把一部分电炊具换成燃气灶;反过来,天然气价格过高时,用户又可能把燃气供暖改成电采暖。这种“电气替代”行为,需要在需求响应模型中显式表达。
代码里把负荷响应分成三类:
第一类是可削减负荷。无论是电力负荷还是气负荷,用户都可以在高峰时段减少一部分用能,代价是系统需要支付补偿费用。模型中对每一类可削减负荷设置最大削减比例和削减次数限制,避免同一节点在多个时段被反复削减。
第二类是可转移负荷。比如用户的洗衣机、消毒柜这类电负荷,可以从晚高峰转到低谷时段。可转移负荷的特征是“总量不变,时段平移”,因此代码里添加了一个关键约束:所有时段转移量的累加和必须为零,也就是正转移加负转移互相抵消。气网侧的工业用气也存在类似可转移负荷,比如某些天然气锅炉可以在允许的时间窗口内调整开工时段。
第三类是可替代负荷。这是气电联合需求响应最大的亮点。代码通过一个耦合矩阵建立电负荷减少量与气负荷增加量之间的对应关系,或者反过来。替代关系不是简单的一比一转换,而是需要考虑能源转换效率。比如电转热与气转热的热值差异、用电效率和用气效率的不同,代码里会设置等效转换系数。这样在优化模型里,变量ΔP_elec和ΔP_gas就可以同时变化,但必须落在一条能量守恒的直线附近。
2.3 优化目标与运行约束
优化目标在代码中体现为多时段累计成本最小化。具体来说,总成本包括上级电网购电成本、天然气购买成本、需求响应补偿成本、设备运行维护成本,还可以加入网损成本。目标函数被封装成一个独立的函数对象,外部只需要传递决策变量和系统参数,就可以算出当前方案的总成本。求解器每迭代一次,就会调用一次这个目标函数。
运行约束分四大块:电网安全约束、气网安全约束、耦合设备约束、需求响应约束。
电网安全约束包括各时段节点功率平衡、节点电压幅值上下限、线路功率传输极限、上级电网购电通道容量。这些约束在代码里是逐时段逐节点展开的,一般写成矩阵不等式形式,提高求解速度。
气网安全约束包括各节点天然气流量平衡、气源出力上下限、管道流量上限、节点压力上下限。气网与电网最大的区别是气网有“惯性”,天然气在管道中的流动速度远小于电的传播速度,因此短期调度中常对管道流量做大时间常数近似。代码采用稳态气网模型,按每个时段内的平均流量来处理,对于小时级调度已经足够。
耦合设备约束包括燃气轮机的出力上下限、爬坡约束、气耗特性曲线,以及P2G设备的输入电功率范围、转换效率、产气流量范围。这些设备一端连着电网,一端连着气网,它们的运行状态直接影响两个网络的平衡。所以代码中会把耦合设备的输入功率同时作为电网负荷和气体供应项来处理,保证两个网络各自平衡。
需求响应约束包括削减时段限制、削减量上下限、转移量守恒约束、替代量守恒约束,以及用户参与响应后的用能满意度约束。这一大组约束用离散变量和连续变量混合描述,所以整体模型是一个混合整数规划问题。
2.4 求解器与输出
求解器模块的设计比较实用。代码没有把求解过程绑死在某个软件上,而是在外层做了一个统一抽象接口。默认可以用免费求解器处理线性连续变量,遇到整数变量时再切换到混合整数规划模式。在求解之前,代码会自动检查模型是否存在非线性的管道流量约束;如果存在,就调用内置的分段线性化函数,把非线性项转化为若干线性段,再接回原来的MP模型。
代码的输出模块也做得比较细致。主输出文件是CSV表格,包含每个时间段的上级购电功率、购气量、各类机组出力、DR削减量、节点压力、节点电压等。同时还有一个汇总文件,统计总成本、网损、燃气消耗量、需求响应补偿费用、削减率等指标。为了快速定位问题,输出模块还会生成一个约束违反度报告,如果某个约束在最优解处仍然越界,报告里会标红对应的节点号和时段。
3. 关键数学表达式与代码对照
3.1 目标函数怎么写
在实际代码中,目标函数会写成类似下面的形式:
def objective(x): cost_buy = sum(price_elec[t] * x['p_buy'][t] for t in range(T)) cost_gas = sum(price_gas[t] * x['q_gas'][t] for t in range(T)) cost_dr = sum(price_dr_elec[t] * abs(x['dr_elec'][t]) + price_dr_gas[t] * abs(x['dr_gas'][t]) for t in range(T)) return cost_buy + cost_gas + cost_dr对应的数学表达式为:
min F = sum_t [ C_e(t)·P_buy(t) + C_g(t)·Q_gas(t) + C_DR,e(t)·|ΔP_DR(t)| + C_DR,g(t)·|ΔQ_DR(t)| ]
其中,t是调度时段,C_e(t)是t时段购电价格,P_buy(t)是t时段上级电网购电量,C_g(t)是天然气购买价格,Q_gas(t)是t时段总购气量,C_DR,e(t)和C_DR,g(t)分别是对电负荷和气负荷的响应补偿单价,ΔP_DR(t)和ΔQ_DR(t)是电负荷和气负荷的总响应量。
有一点需要特别注意:代码里绝对值符号的实现。绝对值在数学上方便,但在优化模型里会引入非光滑项。代码采用变量分解法,把正向响应量和负向响应量分别定义成两个非负变量,再通过约束两者乘积为零来等效绝对值。实际编写时由于整数变量的存在,通常用大M法或者直接设置互补约束。
3.2 电网约束与气网约束如何衔接
电网侧的功率平衡约束可以写成:
P_buy(t) + P_PV(t) + P_GT(t) - P_P2G(t) = P_load(t) - ΔP_DR(t) + P_loss(t)
这里P_GT(t)是燃气轮机的电出力,P_P2G(t)是电转气设备的耗电功率,P_load(t)是原始电负荷,ΔP_DR(t)是需求响应后的负荷削减量,P_loss是网损。这组约束在每个节点和每个时段都要成立。
气网侧的流量平衡约束写成:
Q_source(t) + Q_P2G(t) - Q_GT(t) = Q_load(t) - ΔQ_DR(t)
其中Q_source是天然气气源注入流量,Q_P2G是P2G产气流量,Q_GT是燃气轮机消耗气量,Q_load是原始气负荷,ΔQ_DR是气负荷响应量。
代码里实现“衔接”的关键就是P_GT、Q_GT、P_P2G、Q_P2G这四个变量。燃气轮机内部满足Q_GT(t) = a·P_GT(t) + b,即耗气量是出力的线性函数;P2G内部满足Q_P2G(t) = η·P_P2G(t),η是转换效率。只要把这两个关系写入模型,电网方程和气网方程就已经通过设备变量耦合在一起了。
气网管道流量约束原本是Weymouth方程,形式为流量平方等于压力平方差乘以管道常数。这种非线性关系不能直接进线性优化模型。代码里的处理办法是把管道流量范围分成若干小段,每段用一条切线或者割线近似,最后转成分段线性函数。分段数越多精度越高,但求解时间也越长。经验上取8到12段就足够满足工程误差要求。
3.3 需求响应约束及耦合变量
需求响应约束里最核心的量守恒公式是:
sum_t ΔP_transfer(t) = 0
这表示可转移电负荷的总量不变,只是在不同时段间重新分配。同样的道理也适用于可转移气负荷。
针对可替代负荷,代码用下面的耦合关系式维持能量守恒:
ΔP_sub(t) · η_elec + ΔQ_sub(t) · η_gas = 0
ΔP_sub和ΔQ_sub是同一组用户的电负荷替代量和气负荷替代量,η_elec和η_gas是等效转换效率。负号表示一个增加,另一个减少。比如用户把电采暖换成燃气采暖,ΔP_sub为负,则ΔQ_sub为正。
代码实现时,需要额外加入一个逻辑约束,防止同一个用户在同一个时段既“电转气”又“气转电”。这种逻辑一般通过二进制变量处理。比如定义状态变量u_sub(t),当u_sub(t)=1时允许电气替代,当u_sub(t)=0时允许气替代,再通过一系列带M的约束把它们限制在同一方向。
4. 代码运行流程与实操步骤
4.1 环境准备与目录结构
运行这套代码前,需要准备一个支持科学计算的脚本环境,并安装数组处理和数据处理相关的常用库。求解器方面,先用适合教学和调试的场景跑通代码,再切换到商用求解器处理大规模算例。
推荐的目录结构如下:
project/ ├── data/ │ ├── grid_case.xlsx │ ├── gas_case.xlsx │ └── dr_params.xlsx ├── model/ │ ├── grid_model.py │ ├── gas_model.py │ └── coupling_model.py ├── case/ │ └── run_case.py ├── result/ │ ├── summary.csv │ └── detail.csv └── main.pymain.py是程序入口,负责读取配置文件、构建模型、求解和输出结果。model目录下三个文件分别实现电网约束、气网约束和耦合约束,这样改任何一类约束都不会影响其他部分。data目录存原始数据,result目录放输出结果。
4.2 参数设置与算例配置
以我个人使用过的某模拟项目X为例,最基础的算例配置是电网33节点、气网20节点、调度周期24小时,时间分辨率取1小时。电网侧包括分布式光伏和风电,气网侧包括两个气源和一台压缩机。耦合设备包括一台燃气轮机和一台P2G设备。
参数设置时需要注意几个地方。电网的基准容量建议统一取为100 MVA,气网的基准流量也按热值转换到100 MW基准下。需求响应补偿单价需要根据当地电价水平确定,如果补偿单价设置过低,优化结果会倾向于不用需求响应资源;设置过高,则可能让系统不购买任何电能,全部靠削减负荷满足平衡,不符合实际。
算例里还可以设置三种对比场景。场景一,关闭所有DR功能,只做基础优化;场景二,只开放电负荷的需求响应,气负荷响应量为零;场景三,开放气电联合需求响应。这样一下子就可以看出联合DR相对于单独DR在成本和负荷曲线形态上的差异。
4.3 运行结果解读
运行结束后,result目录下会出现两个文件。summary.csv记录总成本和各项分成本,detail.csv记录每个时段各节点的详细运行数据。以模拟项目X的结果为例,无DR场景下总成本最高,因为系统只能硬扛用电高峰;单独电DR场景下,电负荷峰谷差明显下降,但气网压力在晚高峰仍有越限风险;气电联合DR场景下,部分晚高峰电负荷被转移到气电转换设备更多的低谷时段,同时气负荷高峰也被平抑,总成本进一步下降。
看结果的时候,我一般先关注下面几个指标:总成本是多少,比无DR场景下降了多少;电负荷峰谷差和最大净负荷是否下降;气网节点最低压力是否保持在允许范围内;需求响应补偿费用占总支出的比例是否合理。这四个指标一起看,才能判断模型是否真的实现了“协调”,而不是单方面牺牲某一侧的利益。
5. 常见问题与排查技巧
5.1 模型不收敛怎么办
这是调优化模型最容易碰到的问题。气电联合模型中带有二进制变量、分段线性化约束和多时段耦合约束,求解器经常提示“infeasible”或者干脆一直找不到最优解。
我的排查顺序是:先跑一个简单的小算例,把气网约束和需求响应约束全部关掉,只保留电网约束,看能不能求解。如果可以,再逐步打开气网约束,打开耦合设备,最后打开DR约束。哪一步导致不收敛,问题就出在哪一步。
如果是infeasible,大概率是某组约束写得过紧。比如气网节点压力下限设置过高、气源出力上限过低、可削减比例设得太大,都有可能导致没有可行解。可以把约束上限扩大一个数量级,先找到可行域,再逐步收紧。
如果是长时间不收敛,多半是分段线性化段数太多,或者MIP的gap阈值设得太严格。把分段数从20段降到8段,求解速度会明显提升,解的质量损失通常不到1%。另外务必将压力和功率变量做标幺化处理,否则数值差异过大会让求解器内部迭代非常痛苦。
5.2 数据维度对不上
气电联合模型中,最隐蔽的问题之一就是维度不统一。电网节点数是33个,气网节点数是20个,并不代表第5个电网节点和第5个气网节点有对应关系。耦合设备的位置必须通过设备参数表单独定义:某台燃气轮机接在电网节点10和气网节点6,某台P2G接在电网节点15和气网节点9。
另一种维度问题是时间尺度的匹配。电网调度按15分钟一个时段,气网数据却是按小时统计的,这两种数据放在同一个模型里就会产生系数错位。解决办法是建立统一的时间轴,所有曲线在进入模型前都做线性插值,确保每个时段都有完整的一套数据。
5.3 气网压力越限与需求响应的关系
如果我跑完算例后发现气网节点压力低于下限,第一反应不是去改压力约束,而是看这个节点的气负荷来源。如果某个薄弱节点同时接入了大容量P2G设备,在夜间电价低谷时P2G大量启动,虽然产生了天然气,但如果P2G的产气压力不足,可能反而拉低节点压力。
这种情况下,气电联合需求响应能起到的作用是调整P2G设备所在地的电力负荷。如果让P2G附近的电力负荷在夜间多用电,抬高节点电压,但对气网压力没有帮助;如果让气网薄弱节点附近的气负荷适当削减或转移到非低谷时段,压力越限问题一般能缓解。这就是为什么需求响应需要按照节点位置差异化设计,而不是整个系统一刀切。
5.4 调试建议清单
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 模型无可行解 | 约束过紧,变量上下限矛盾 | 先扩大气源上限和购电上限,逐步收窄 |
| 求解时间过长 | 分段数太多,MIP gap过严 | 降低分段数到8段,适当放宽gap |
| DR响应量为零 | 补偿单价过低,DR潜力未激活 | 提高补偿单价到电价的1.2~1.5倍 |
| DR削减量异常大 | 补偿单价过高,DR潜力参数过大 | 检查可削减比例是否超过实际范围 |
| 气网压力越限 | 耦合设备位置不当,负荷波动太大 | 改接P2G位置,或对薄弱节点增加DR约束 |
| 电网节点电压越限 | DR削减负荷集中在一个节点 | 为节点削减量添加最多连续削减时段限制 |
如果把这些检查清单从头到尾过一遍,大多数“玄学”问题都能定位到具体模块上。
我实际调试这套代码时体会最深的一点是,气电联合需求响应不是把需求响应量做得越大越好,真正有价值的是让气、电两种能量在时间和空间上互相补位。比如说,把一部分电负荷高峰需求转移到天然气供应相对宽裕的时段,看起来只是负荷迁移,结果却能同时缓解电网变压器过载和气网管道压力风险。后续如果想继续扩展,还可以把碳排放流约束加入目标,做成气电联合低碳调度,也可以把配电网三相不平衡约束细化进去,这套代码的框架完全能支撑这些研究方向。