ARTICLE DETAIL

资讯详情

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

综合能源系统优化调度:需求响应与阶梯碳交易建模详解

综合能源系统优化调度:需求响应与阶梯碳交易建模详解 1. 项目到底在算什么综合能源系统调度模型的设计思路1.1 电-热-气三网怎么耦合先把这个项目从“标题翻译成人话”考虑综合需求响应和阶梯型碳交易机制的综合能源系统优化调度核心是在 MATLAB 里搭建一个电、热、气多能互补的园区级能源系统并求出未来 24 小时的最优运行方案。这里的“最优”不是拍脑袋而是以一个总成本最小化的目标函数为基准同时满足能量平衡、设备出力范围、储能约束等条件最终输出各机组的启停、出力、储能充放、与外网购电、甚至需求侧负荷调整的具体数值。我复现时通常会把系统拓扑固定为下面这张图论文里八成也是这个结构外部电网作为电力来源之一天然气网供燃气轮机和燃气锅炉使用系统中配有光伏、风机、电锅炉、燃气轮机CHP、燃气锅炉、蓄电池和热储能。电负荷由光伏、风机、燃气轮机、外网购电和蓄电池共同满足热负荷由燃气轮机余热、燃气锅炉、电锅炉和热储能满足。天然气负荷直接来自气网如果论文里有“气负荷”则在地理管网络中混入。这个结构对应的就是“能源集线器”思想多种能源在输入端经过转换、存储、分配最后以统一的电、热、气负荷输出。为什么要用集线器而不是完整电网建模因为大部分复现论文根本不考虑拓扑网络约束它们关心的是跨能源品种的调度决策而不是潮流计算。如果你非要把支路潮流、节点电压、天然气管道压力全部加进去模型会从 MILP 变成复杂得多的 MINLP求解时间会从几秒变成几小时论文复现的性价比极低。另一个关键点是时段粒度。多数综合能源系统优化调度论文用 24 个时段步长 1 小时。少数会用到 96 时段、15 分钟粒度那主要是为了刻画储能和需求响应的实时性。MATLAB 复现时我建议先用 24h 跑通再改 96 时段。直接在 96 时段起步一旦约束条件写错排查成本会非常高。1.2 调度策略的复现目标与建模路径选择要弄清楚这个项目到底输出什么每个时段设备出力、储能充放功率、电网交互功率、需求侧响应量、碳交易成本和总运行成本。因此本质上是一个多时段最优决策问题。从建模路径看几乎全部这类论文都是“先列目标函数再写约束最后丢给求解器”。目标函数是运行成本最小化运行成本包括购电购气费用、设备运行维护费用、需求响应补偿费用、碳交易费用如果系统中有启停状态变量还要加上启停成本。约束条件则分为四组能量平衡约束、设备特性约束、储能动态约束、需求响应约束。在 MATLAB 平台上有两条技术路线。一条是使用 YALMIP 工具箱建模后端调用 Gurobi 或 Cplex 求解另一条是直接用 MATLAB Optimization Toolbox 的optimproblem和intlinprog。我在复现这类论文时强烈推荐 YALMIP原因在后文会展开。核心在于模型里会大量出现 0-1 变量比如储能不能同时充放、需求响应动作的时序约束等YALMIP 对二进制变量的表达更自然代码可读性好后期修改约束条件也更方便。复现论文前的“假设清单”很重要。比如光伏出力是否取预测值、电负荷是否刚性、热负荷是否允许削减、天然气价格是否是分段阶梯价、外网购电是否存在上限。这些看似细节的东西直接决定了你的模型可不可解。2. 综合需求响应建模的两个层次2.1 价格型需求响应弹性矩阵与负荷转移很多人把需求响应简单理解成“削峰填谷”这个理解太浅了。综合需求响应的第一个层次是价格型需求响应它建立在“用户会随着电价变化调整用电行为”这个经济学假设上。用户不会因为某时段电价高了就完全不用电而是在可容忍范围内把一部分负荷从高峰挪到低谷。建模时最常用的是弹性矩阵法。设用户原始电负荷为 (L_0(t))经过需求响应后的负荷为 (L(t))电价变化率为 (\Delta p^e(t)/p_0^e(t))则 [ L(t)L_0(t)\left[1\sum_{s} e(t,s)\frac{\Delta p^e(s)}{p_0^e(s)}\right] ] 其中 (e(t,s)) 是弹性系数。(ts) 时是自弹性通常为负值表示涨价会抑制用电(t\ne s) 时是交叉弹性表示其他时段电价变化对本时段负荷的影响这在峰谷电价转移中非常关键。实际复现时线性化的方式是把上式变成一组线性等式约束引入一个“负荷调整量” (\Delta L(t))并且对调整量加上限制。比如某园区原始电负荷为 1000 kW峰时段电价从 1.2 元/kWh 涨到 1.5 元/kWh自弹性取 -0.3那么这个时段大约会有 7.5% 的负荷被移走。但建模时你真按这个公式算会发现一个很现实的问题交叉弹性矩阵如果设置不合理很容易导致某些时段负荷变成负数这明显不可能。所以我建议给调整后的负荷加上上下限约束比如 (0.5L_0(t) \le L(t) \le 1.2L_0(t))同时让所有时段的总负荷保持一个合理范围。价格型需求响应解决了“用户主动避峰”但它假设用户很理性且全部按价格信号行动。现实中用户往往需要额外激励才愿意调整于是就有了激励型需求响应。2.2 激励型需求响应与 IDR 的跨能源替代激励型需求响应跟价格型本质区别在于前者靠价格引导后者靠补偿合约。在模型里价格型需求响应不直接进目标函数花钱只是通过价格弹性改变负荷曲线而激励型需求响应会在目标函数里加入一笔补偿成本。典型场景是“可削减负荷”和“可转移负荷”。可削减负荷意味着用户允许系统在某些时段将其负荷切掉一部分但每削减 1 千瓦时要给用户补偿。建模时需要一个削减量上限 [ 0 \le \Delta L_{cut}(t) \le \Delta L_{cut}^{max}(t) ] 可转移负荷更复杂它往往是一个确定的工作周期比如工业电解槽、污水处理装置必须连续运行若干小时但可以提前或推迟启动。这类负荷通常用 0-1 变量去约束启动状态表示“这台设备在第 3 小时启动连续运行 4 小时后关闭只能整体平移不能拆分”。到这里只是传统需求响应。所谓综合需求响应还包含一个“跨能源替代”的维度用户不仅削减电负荷还可以在电、热、气之间互相转换。比如一个工厂既有电锅炉又有燃气锅炉电价很高时把一部分热量需求由燃气锅炉承担气价高时再切回电锅炉。这等于把原来独立的电负荷、热负荷响应统一成一个综合决策。我在建模时会把终端负荷拆成刚性负荷、可转移负荷、可削减负荷、可替代负荷四类然后分别写约束。刚性负荷必须满足可转移负荷满足调峰约束和总量不变约束可削减负荷满足上限约束可替代负荷在能量等值条件下参与电热气联调。这样做的好处是需求响应不再只是“把负荷曲线改一下”而是真正参与了设备出力决策这也是标题里“综合”二字的由来。3. 阶梯型碳交易机制如何线性化3.1 配额、实际排放和交易量三步走碳交易机制的建模有三步先算碳配额再算实际碳排放量最后根据差值在碳市场购买或出售配额。这三个概念如果没理清后面很容易把符号搞反。免费碳配额通常按产出基准法分配最常用的形式是 [ E_{free} \alpha \cdot D_{load} ] 其中 (D_{load}) 是系统总负荷或总发电量(\alpha) 是单位电量或单位负荷对应的免费配额系数。不同论文的配额基准差异很大有的按发电量给配额有的按负荷侧给配额还有的按历史排放值给配额。复现前你先看摘要和 3.2 模型构建部分确定用的是哪种别看到公式就抄。实际排放量要逐设备算。燃气轮机燃烧天然气排放二氧化碳燃气锅炉也排外购电通常算作间接排放因为发电侧上游已经排了碳。表达式可以写成 [ E_{actual} \sum_t \left[ \mu_{gt} P_{gt}(t) \mu_{gb} H_{gb}(t) \mu_{grid} P_{buy}(t) \right] \cdot \Delta t ] 这里的排放系数要统一量纲。我复现时最头疼的是单位混用有的论文给 (t/(MWh))有的给 (kg/(kWh))稍不注意就差了 1000 倍。然后碳交易量为 [ E_{trade} E_{actual} - E_{free} ] 当 (E_{trade} 0) 时系统配额不够用需要购买当 (E_{trade} 0) 时配额有富余理论上可以出售获利。注意模型里若允许出售配额目标函数的碳交易成本会变成负值这相当于给减排行为发了补贴。如果论文里不考虑卖出就把负值直接清零。3.2 阶梯价格的分段函数与 MILP 建模阶梯型碳交易机制的关键在于碳价不是一刀切的常数而是随着购买量增加逐级抬高。这个设计非常符合实际碳市场逻辑——排放越多超额部分越贵倒逼企业减排。我复现时常用一个三段或五段的阶梯价格表。举个例子碳交易量区间区间上限碳价第 1 段0 ~ a1λ₀第 2 段a1 ~ a2λ₀ δ第 3 段a2 ~ a3λ₀ 2δ其中 λ₀ 是基础碳价δ 是阶梯增量。如果交易量为 (E_{trade})则成本不是简单的 (\lambda E_{trade})而必须分段累加。这个函数是分段线性的但存在不连续折点直接放进线性规划会出问题。正确的做法是引入分段变量 (x_1, x_2, x_3)满足 [ E_{trade} x_1 x_2 x_3 ] 并且 [ 0 \le x_1 \le a_1, \quad 0 \le x_2 \le a_2 - a_1, \quad 0 \le x_3 \le a_3 - a_2 ] 成本 [ C_{co2} \lambda_0 x_1 (\lambda_0\delta) x_2 (\lambda_02\delta) x_3 ]但这里藏着一个大坑如果不加限制求解器会把交易量全塞到第 1 段因为第 1 段碳价最低。你必须用二进制变量强制“装满前面的段才能用后面的段”。典型写法是引入两个二进制标志位 (z_1, z_2)并用大 M 法约束若 (x_2 0)则 (x_1 a_1)若 (x_3 0)则 (x_2 a_2 - a_1)用大 M 公式表达 [ x_2 \le M z_1,\quad x_1 \ge a_1 - M(1 - z_1) ] [ x_3 \le M z_2,\quad x_2 \ge (a_2-a_1) - M(1 - z_2) ] 其中 (z_11) 表示第 1 段已经装满(z_21) 表示第 2 段已经装满。这套约束写进 YALMIP 后模型就变成标准的 MILP 问题Gurobi 可以直接求解。注意大 M 不能取太小否则数值不稳定也不能取太大否则求解器会浪费大量分支。我一般取系统最大可能排放量的 5~10 倍。4. 目标函数与约束条件的代码化装配4.1 目标函数把成本项和碳交易成本写进一个表达式综合能源系统优化调度的目标函数一般可以写成下面这个形式目标函数 购电成本 购气成本 运行维护成本 需求响应补偿成本 碳交易成本其中购电成本是每个时段的外购电功率乘以该时段电价再按时长累加。购气成本是燃气轮机和燃气锅炉消耗的天然气量乘以气价。运行维护成本通常简化成机组出力的线性函数比如某台设备每发一度电运维成本 0.02 元。需求响应补偿成本是最容易被忽略的它让模型愿意在碳价高、电价高的时候去削减负荷而不是一味硬扛。碳交易成本我单独强调如果你用第 3 节的分段线性模型那么 (C_{co2}) 本身也是分段累加结果而不是一次性项。写进 YALMIP 时目标函数就是一个sdpvar表达式。比如Objective sum(price_buy .* P_grid) * dt ... price_gas * (P_chp/eta_chp H_gb/eta_gb) * dt ... c_om * (P_chp H_chp H_eb P_dis) * dt ... c_dr * sum(DR_cut DR_shift) * dt ... C_co2;这里有一个经验最好把全部成本统一到同一个单位再代入。比如时间步长 ( \Delta t1) 小时电价如果是元/kWh功率用 kW则购电成本单位是元刚好对齐。如果你用 MW电价用元/MWh那也算能对齐。最怕的是功率用 kW电价却用元/MWh算出来会差 1000 倍。4.2 核心约束平衡、设备出力、储能与爬坡约束条件是整个复现最容易翻车的地方也是论文“看着简单、写着一堆 bug”的重灾区。第一组是电能平衡约束。每一时刻所有电源出力等于所有负荷需求 [ P_{grid}(t) P_{chp}(t) P_{pv}(t) P_{dis}(t) P_{load,afterDR}(t) P_{eb}(t) P_{chg}(t) ] 这里的 (P_{dis}) 是蓄电池放电(P_{chg}) 是充电功率。很多人会忘记电锅炉也是一个电负荷如果直接写成 (电源总电负荷)那电锅炉消耗的电就没地方去了。第二组是热能平衡约束 [ H_{chp}(t) H_{gb}(t) H_{eb} H_{dis,thermal} H_{load,afterDR}(t) H_{chg,thermal} ] 第三组是机组特性约束比如燃气轮机的热电比约束 [ H_{chp}(t) R_{chp} P_{chp}(t) ] 也可以写成一个可运行域包含最小出力、爬坡速率和热电耦合。最简单实用的写法是给 (P_{chp}) 和 (H_{chp}) 分别设上下限再加一个线性耦合约束。第四组是储能约束包括SOC(t1) SOC(t) (eta_chg * P_chg(t) - P_dis(t) / eta_dis) / Cap_storage; 0 P_chg(t) b_chg(t) * P_chg_max; 0 P_dis(t) b_dis(t) * P_dis_max; b_chg(t) b_dis(t) 1;最后这个约束非常重要它保证电池不会同时充放电。如果不加这一条模型就会出现“用一个设备同时充放电来薅羊毛”的无厘头结果。第五组是爬坡约束 [ P_{chp}(t) - P_{chp}(t-1) \le Ramp_{up} ] [ P_{chp}(t-1) - P_{chp}(t) \le Ramp_{down} ] 爬坡约束经常被新手漏掉漏掉之后模型会给出一个非常“生猛”的调度曲线机组出力从 800 kW 瞬间跳到 200 kW。这在现实中根本做不到但求解器完全不觉得有问题。5. MATLAB 实操从数学符号到可运行程序5.1 工具选型YALMIP 求解器为什么是默认组合这个复现用 MATLAB 自带的优化工具箱也能做但我不推荐。原因有三点。第一optimproblem的变量定义方式偏“矩阵化”遇到循环索引非常别扭第二约束横跨平衡式、不等式、二进制变量、分段线性函数YALMIP 的表达更接近数学符号第三YALMIP 可以无缝切换 Gurobi、Cplex、Mosek 等求解器论文里如果要求对比不同求解器你只需要改一行sdpsettings。整个环境建议这样配MATLAB 版本不要太老我建议 R2021 以上。YALMIP 装最新版直接从 GitHub 仓库下载并addpath就能用。求解器优先 Gurobi如果学校没有 Gurobi 授权可以用 Cplex再不行就用 MATLAB 自带的intlinprog但求解时长会增加。在sdpsettings里设置solver, gurobi并打开求解日志。我踩过最明显的坑是求解器版本和 YALMIP 对不上导致调用时提示gurobi: solver not found。这个问题十有八九是gurobi.m这个文件没被 MATLAB 找到不一定是安装失败。解决方法是把 Gurobi 安装目录下的 MATLAB 路径手动addpath(genpath(...))然后运行yalmiptest检查是否成功识别。5.2 参数模板直接照抄的基准参数表复现论文最怕的设置不一致。下面这张表是我自己跑这类综合能源系统优化调度常用的基准参数可以作为起步模板但具体数值一定要随论文原文修正。参数数值单位说明调度时段数24h步长 1h电负荷峰值1200kW峰谷分布需自行设置热负荷峰值700kW供暖季典型值光伏装机300kW出力曲线取典型日燃气轮机容量500kW电出力上限燃气轮机热电比1.2-余热产出与电出力比例燃气锅炉效率0.9-热效率电锅炉效率0.95-电转热效率蓄电池容量600kWh蓄电池充放效率0.95-充放对称外购电上限800kW受上级变压器容量限制天然气价格2.5元/m³可折算为 0.35 元/kWh碳配额系数 α0.45tCO2/MWh负荷侧配额基准基础碳价 λ₀65元/tCO2碳价阶梯增量 δ15元/tCO2这张表有一个细节碳配额系数如果按负荷电量给单位是 tCO2/MWh那么计算时要把所有电量都折算到 MWh不能一边用 kW 一边用 MWh。我在第一次复现时就是因为这里单位乱掉导致碳配额计算出来比碳排放还大结果模型疯狂卖配额目标函数变成负无穷。5.3 核心代码骨架与求解器调用下面是一个可以直接跑通的 MATLAB YALMIP 核心骨架先看整体结构。n 24; dt 1; % 小时 P_load0 [3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 8, 7, 7, 8, 9, 10, 9, 6, 4] * 100; % kW H_load0 [4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 6, 6, 7, 7, 6, 5, 5, 5] * 100; % 决策变量 P_grid sdpvar(n, 1); P_chp sdpvar(n, 1); H_chp sdpvar(n, 1); H_gb sdpvar(n, 1); H_eb sdpvar(n, 1); P_eb sdpvar(n, 1); P_dis sdpvar(n, 1); P_chg sdpvar(n, 1); b_chg binvar(n, 1); b_dis binvar(n, 1); SOC sdpvar(n1, 1); DR_el sdpvar(n, 1); % 电负荷削减量 DR_ht sdpvar(n, 1); % 热负荷削减量 % 设备参数 eta_chp 0.35; eta_gb 0.9; eta_eb 0.95; R_chp 1.2; Cap_bat 600; Constraints []; % 电能平衡 Constraints [Constraints, P_grid P_chp 30 P_dis ... P_load0 - DR_el P_eb P_chg]; % 热能平衡 Constraints [Constraints, H_chp H_gb H_eb H_load0 - DR_ht]; % 热电耦合 Constraints [Constraints, H_chp R_chp * P_chp]; Constraints [Constraints, P_eb H_eb / eta_eb]; % 设备上下限 Constraints [Constraints, 0 P_chp 500]; Constraints [Constraints, 0 H_chp 700]; Constraints [Constraints, 0 H_gb 800]; Constraints [Constraints, 0 H_eb 600]; % 电池约束 Constraints [Constraints, SOC(1) 300]; Constraints [Constraints, 0 P_chg b_chg * 200]; Constraints [Constraints, 0 P_dis b_dis * 200]; Constraints [Constraints, b_chg b_dis 1]; Constraints [Constraints, SOC(t1) SOC(t) (0.95*P_chg - P_dis/0.95)/Cap_bat]; % 需求响应上限 Constraints [Constraints, 0 DR_el 0.2 * P_load0]; Constraints [Constraints, 0 DR_ht 0.2 * H_load0]; % 目标函数 price_buy [4,4,4,4,4,4,5,6,7,8,8,9,10,9,8,8,7,7,8,9,10,9,6,4] * 0.1; % 元/kWh Objective sum(price_buy .* P_grid) * dt ... 0.35 * (P_chp / eta_chp H_gb / eta_gb) * dt ... 0.02 * (P_chp H_chp H_eb P_dis) * dt ... 2 * sum(DR_el DR_ht) * dt ... C_co2; ops sdpsettings(solver, gurobi, verbose, 1); sol optimize(Constraints, Objective, ops); if sol.problem 0 P_grid_opt value(P_grid); P_chp_opt value(P_chp); % .... 后续画图 else disp(sol.info); end这段代码能跑但它只是骨架。真实复现时还要加上碳交易分段约束、爬坡约束、可转移负荷的二进制约束。如果你把碳交易分段约束直接粘进去必须先把 (C_{co2}) 按第 3.2 节的方法定义成分段变量表达式。还有一个细节电能平衡我写成了而不是这在初期调试时比较友好因为模型有富余空间就不会那么脆。但正式复现时如果论文是“保证供需平衡”通常要改回否则系统可能无成本地弃掉多余出力。如果你要允许弃风弃光和切负荷那就加松弛变量并在目标函数里加惩罚项而不是简单用糊弄过去。6. 复现过程中的高频问题与排查方法6.1 无解和“可解但不可行”的排查路径我在复现这类模型时遇到的第一大坑是模型直接报infeasible。Gurobi 会给你一个提示Model is infeasible但不会告诉你哪条约束错。这时候最蠢的办法是一条条猜最有效的办法是先从变量范围查起。第一步查设备容量和负荷量级。举个例子某段时间热负荷是 1200 kW但所有热源设备加起来最大热出力只有 900 kW那热平衡必然无解。这种问题在电热耦合系统里尤其常见因为燃气轮机的热电比是固定的热出力跟着电出力走可能出现“电平衡刚好满足但热出力不够用”的矛盾情况。第二步查 SOC 约束。很多论文会要求储能首末时段电量相等也就是 (SOC(1)SOC(25)SOC_0)。如果你把 SOC 的初值设成 300 kWh期末也要求回到 300 kWh而在夜间充放电能力不足就会出现无解。我的建议是先用松弛版本跑通只设 SOC(1)不设 SOC(n1)确认系统本身可行再逐步收紧约束。第三步用 YALMIP 自带命令排查比如sol.info、sol.problem更有用的是checkset(Constraints)它会逐条显示约束的最大违反量。哪条约束 violate 得离谱问题就在哪。这个方法我到现在都在用。6.2 碳交易阶梯约束的经典“便宜段”错误碳交易分段约束如果只写了变量范围没写装满顺序就会出现一个经典错误系统把大量碳配额需求全部塞进第一段低价区间导致碳交易成本被严重低估最后求解器给出一个“特别环保”但其实不符合机制的调度结果。更隐蔽的问题是使用了大 M 法但 M 取得不合适。M 太小会把可行域卡死M 太大又会让求解器花费大量时间处理数值病态。我复现时经常看到有人写M 1e6然后整个模型求解不动最后换M 5000就能秒出结果。针对这个模型大 M 取最大碳交易量的 3~5 倍就够。如果你手头的 YALMIP 版本支持pw函数还可以用自带的分段线性表达。但我个人建议新手还是老老实实写二进制变量和线性约束因为pw的工业代码在用户不懂细节时反而更容易产生隐藏 bug一旦算错排查成本比手写还高。6.3 量纲与数值缩放问题这个坑我要单独拉出来说因为十个人复现至少有八个人在这里出问题。综合能源系统模型里的物理量跨度极大设备功率是几百 kW碳排放配额是几十吨碳价是几十元每吨需求响应补偿是几元每千瓦时。如果你把所有成本直接相加目标函数可能是一个 (10^8) 级别的数这让求解器在数值上非常难受。我的习惯是统一用“元”做成本单位功率用“kW”能量用“kWh”碳配额用“tCO2”然后观察目标函数量级。如果总成本达到 (10^7) 以上我就把目标函数除以一个基准数比如 (10^6)相当于用“万元”作为目标单位。这样 Gurobi 的默认容差设置会工作得很好求解速度明显提升。另一个常见单位坑是天然气热值。很多论文里天然气价格给的是“元/m³”但燃气轮机效率是以热值计算的。你要先把天然气价格换算成“元/kWh”换算公式是 [ c_{gas_kWh} \frac{c_{gas_m3}}{天然气低位热值(kWh/m^3)} ] 天然气低位热值一般取 9.5 kWh/m³ 左右。如果忽略了这一步购气成本会高出十倍结果自然是燃气机组一点不敢用全系统都靠电网买东西出力曲线变得非常畸形。7. 结果怎么验证才算复现成功7.1 关键输出曲线怎么读代码跑通只是第一步结果合理才算复现成功。我一般从五张图开始看。第一张图是电平衡堆叠图横轴是 24 个时段纵轴是功率把光伏出力、风电出力、燃气轮机出力、外网购电、蓄电池放电叠成堆叠柱状图。堆叠图如果出现负数说明平衡约束或变量符号有问题。第二张图是热平衡堆叠图方法与电平衡类似但要特别注意燃气轮机余热出力必须和电出力同步变化。如果看到燃气轮机在某个时段电出力很低但热出力很高那就违反了热电比约束。第三张图是需求响应前后的负荷曲线对比。原始负荷是一条高峰在白天、低谷在凌晨的曲线响应后的曲线应该出现“峰削谷填”的效果。如果两曲线几乎完全重合说明需求响应补偿价格设得不够高或者响应量上限设得太低约束被“闲置”了。第四张图是蓄电池 SOC 曲线正常应该是一条连续平滑变化的曲线不会频繁跳变。如果 SOC 在每个时段都在剧烈波动说明储能的充放成本权重太低储能在那里单纯做套利而且效果差。第五张图是碳交易量和碳交易成本的曲线。碳交易量应该和燃气机组、外购电的使用强相关且阶梯成本在跨过段点时会有跳变。如果碳交易成本是一条完美直线大概率是分段约束没生效。7.2 对比实验与灵敏度分析怎么设计论文复现还有一步不能省把“考虑综合需求响应”和“考虑阶梯型碳交易机制”的贡献分别拆出来。一般设置四个场景场景一都不考虑只做基础经济调度。场景二只考虑综合需求响应。场景三只考虑阶梯型碳交易机制。场景四两者都考虑。然后对比总成本、碳排放量和设备出力结构。如果场景四的总成本比场景三还高不一定说明模型错了可能只是需求响应补偿成本高于它节省的燃料成本但如果场景四的碳排放和场景三完全一样那就是需求响应约束根本没有激活需要检查补偿价格或负荷弹性系数。灵敏度分析也很重要比如扫描基础碳价 (\lambda_0) 从 50 元/吨到 120 元/吨观察燃气轮机出力和外购电量的变化。如果碳价升高后外购电反而减少那基本上就说明模型有 bug因为更高碳价应该让系统少用碳排高的能源多用碳排低的能源。用这一条就能快速判断结果是否符合机理。我在实际复现这类论文时最大的体会是所谓“复现成功”不一定是和原文结果一模一样而是你的模型在机理上与论文传达的核心逻辑一致。碳交易阶梯机制必须真的让碳价随排放量上升需求响应必须真的改变负荷曲线储能必须真的在低谷充电、高峰放电。这三个“必须”满足了哪怕你用的参数跟论文略有差异结果也大概率在可接受范围内。做这种复现项目最忌讳的是代码跑出一个漂亮图但图里的数据和物理机理完全对不上。先保证每一个变量都有明确的物理含义再谈算法优化和模型扩展。
返回列表