气电联合需求响应与配网优化协调模型详解
很多做配网优化的人一听到“气电综合能源”就头疼因为电网、气网、负荷响应全搅在一起。这套协调优化运行代码的功能说明核心解决一件事在电力与天然气互联的配网系统中如何通过气电联合需求响应让电网削峰和气网调压在同一个优化框子里完成而不是各调各的。适用对象是正在做配网侧综合能源仿真、需求响应策略验证或者毕业设计的同学也适合想快速了解多能耦合优化代码结构的工程师。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段适当放宽gapDR响应量为零补偿单价过低DR潜力未激活提高补偿单价到电价的1.2~1.5倍DR削减量异常大补偿单价过高DR潜力参数过大检查可削减比例是否超过实际范围气网压力越限耦合设备位置不当负荷波动太大改接P2G位置或对薄弱节点增加DR约束电网节点电压越限DR削减负荷集中在一个节点为节点削减量添加最多连续削减时段限制如果把这些检查清单从头到尾过一遍大多数“玄学”问题都能定位到具体模块上。我实际调试这套代码时体会最深的一点是气电联合需求响应不是把需求响应量做得越大越好真正有价值的是让气、电两种能量在时间和空间上互相补位。比如说把一部分电负荷高峰需求转移到天然气供应相对宽裕的时段看起来只是负荷迁移结果却能同时缓解电网变压器过载和气网管道压力风险。后续如果想继续扩展还可以把碳排放流约束加入目标做成气电联合低碳调度也可以把配电网三相不平衡约束细化进去这套代码的框架完全能支撑这些研究方向。