做综合能源系统热电优化这块的朋友,应该都有过类似的经历:调度模型跑出来了,结果在评审会上一问,碳排放是怎么算的?碳价是固定一个值还是阶梯式递增?电解槽到底有没有在低谷真正跑起来?说实话,固定碳价和阶梯式碳交易机制,对优化结果的差异非常大。如果不把碳成本的结构做对,算出来的电价、热价、设备利用小时数全都带偏。
这篇内容围绕“考虑阶梯式碳交易机制与电制氢的综合能源系统热电优化”这个项目,把建模思路、阶梯碳价处理技巧、电制氢设备建模细节、Matlab+Yalmip代码实现和踩坑记录完整梳理一遍。适合正在做综合能源系统(IES)调度优化、需要搭建算例验证模型、或者想在Matlab里用Yalmip快速搭一个可扩展优化框架的朋友参考。我会尽量把每一步为什么这么做讲清楚,代码也给到可以直接跑的框架。
1. 项目要解决的真实痛点:热电耦合与碳约束下的两难
1.1 综合能源系统里“热”和“电”从来不是一回事
综合能源系统最典型的结构,是燃气轮机(CHP)、燃气锅炉(GB)、电解槽、燃料电池、储能装置共同给一片园区供电供热。听起来设备不少,但真正难处理的是热电联产机组的“以热定电”特性。
CHP机组的热出力和电出力是强耦合的。常见做法是给定一个热电比,比如热出力是电出力的1.5倍,那么热负荷一旦定了,电出力基本也被绑定在一个区间里。冬季夜间热负荷很大,CHP被迫满发,电出力也跟着上来,但深夜电负荷又低,多余的电只能往外送或者弃掉。如果再接入风电,夜间大风时段的风电被强制挤掉,这就出现了我们常说的“弃风”和“热电解耦困难”。
传统解决方案是加电锅炉,用多余的电力制热,但电锅炉只是把电能转化成热能,能解决部分消纳问题,对降低碳排放没太大帮助。而电制氢的思路不同:电解槽用谷电制氢,氢气可以存储、可以供给氢负荷,也可以通过燃料电池在高峰时段发电发热。等于是在CHP刚性热电耦合中间切了一刀,让系统在“热”的约束之外,多了一个“氢”的缓冲。
1.2 引入电制氢和碳交易机制,到底是在优化什么
这个项目不是单纯的多设备调度,而是把两个维度同时放进了优化模型里。
第一个维度是经济性。系统运行要考虑购电成本、购气成本、设备运维成本,电价和天然气价格的波动会直接影响设备的出力分配。第二个维度是低碳性。碳排放配额、实际排放量和碳交易价格构成了一个新的成本项,而且这个成本项随着排放量的增加不是线性增长,而是阶梯式跳涨。
电制氢的作用,恰恰能把这两个维度串起来。谷电时段电价低,风电可能被弃,电解槽此时买电制氢,既降低了购电成本,又因为替代了部分天然气供能而减少了碳排放。到了负荷高峰,燃料电池再把氢转成电和热,替代高碳价的CHP出力。所以这个优化问题的核心,就是在电、热、氢三种能源载体之间,找到让总成本最低的24小时调度计划,同时还要让阶梯碳交易成本控制在可接受范围。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 阶梯式碳交易机制的理解与建模
2.1 从固定碳价到阶梯碳价:为什么不能一刀切
固定碳价很好理解,每吨碳排放一个固定价格,排放多少成本就增加多少。但固定碳价有一个问题:企业只要核算下来排放超标,多排一吨和多排一百吨的边际成本一样,抑制效果有限。阶梯式碳交易机制是把这个边际成本做成递增的,排放量超过配额越多,超出部分的碳价越高。比如配额内免费或者低价,超出第一部分按80元/吨,再多按120元/吨,继续超按180元/吨。
这种机制在真实碳市场中非常普遍,但放到优化模型里就带来一个数学上的麻烦:目标函数里会出现一个分段线性函数,如果处理不好会把模型变成非凸甚至非线性问题,求解器直接罢工。
2.2 碳排放配额、实际排放与碳交易量的计算
先明确几个关键量。
初始碳排放配额,常用的有历史法和基准线法。基准线法可以写成:
E_base = λ × (P_load + H_load)
也就是根据系统承担的电负荷和热负荷,乘一个配额系数λ得到免费配额。P_load和H_load是负荷总量,单位需要统一到MWh。
实际碳排放要分三块算。天然气输入CHP产生的排放,天然气输入燃气锅炉产生的排放,以及外购电对应的间接排放。写出来就是:
E_actual = α_gas × (F_chp + F_gb) + α_grid × P_buy
其中F_chp和F_gb是CHP和燃气锅炉消耗的天然气量(按热值输入折算到MWh),α_gas是燃气的碳排放系数(吨CO₂/MWh),α_grid是电网购电的碳排放因子。这里有个新手容易踩的坑:燃气锅炉的热出力不等于燃料输入,必须先除以锅炉效率,CHP也要先除以发电效率得到燃料输入,再乘排放系数。单位不统一是这类模型最容易出问题的地方。
然后碳交易量就是:
E_trade = E_actual - E_base
如果E_trade为负,说明排放低于配额,配额富余,可以卖出获得收益。如果为正,就是需要购买配额,碳成本按照阶梯价格计算。
2.3 阶梯碳价的分段函数与线性化化简技巧
阶梯碳成本函数是一个分段线性函数。假设配额富余时出售价格为c_sell,超出配额的部分分三段,价格分别为c1、c2、c3,且c_sell < c1 < c2 < c3。每段长度设为L1、L2,整个函数写成:
cost(E_trade) =
- c_sell × E_trade, E_trade ≤ 0
- c1 × E_trade, 0 < E_trade ≤ L1
- c1 × L1 + c2 × (E_trade - L1), L1 < E_trade ≤ L1+L2
- c1 × L1 + c2 × L2 + c3 × (E_trade - L1-L2), E_trade > L1+L2
很多人第一反应是直接在Matlab里用if语句判断E_trade落在哪一段。这在标定参数时没问题,但一旦放进优化模型里,if判断会让模型变成不可导的非线性问题,Gurobi和Cplex都没法直接处理。
正确做法是利用分段凸函数的性质。因为c_sell < c1 < c2 < c3,这个函数是凸的,凸分段线性函数可以用“极大值表示法”线性化。也就是说,不需要引入任何0-1整数变量,只需要设一个碳成本变量C_carbon,然后让它同时大于等于四条直线的表达式:
C_carbon ≥ c_sell × E_trade
C_carbon ≥ c1 × E_trade
C_carbon ≥ c2 × E_trade + (c1 - c2) × L1
C_carbon ≥ c3 × E_trade + (c1 - c2) × L1 + (c2 - c3) × L2
因为C_carbon在目标函数里是被最小化的,它最终会贴着这些直线中最大的一条走,恰好就是原阶梯函数。这个技巧非常实用,而且不需要额外增加整数变量,模型规模小,求解速度快。
3. 电制氢环节的建模细节与耦合方式
3.1 电解槽和燃料电池的基础模型
电解槽的输入是电功率P_el,输出是氢气,简化模型可以写为:
V_h2_prod = η_el × P_el
η_el是电解槽制氢效率,按氢气低位热值折算到输入电能。比如η_el=0.6,意味着输入1 kWh电能可以产出0.6 kWh等效能量的氢气。工程上还会考虑电解槽的最小稳定运行功率,一般设一个P_el_min,低于这个值电解槽不适合长期运行,所以约束写成:
P_el_min ≤ P_el ≤ P_el_max
燃料电池是电解槽的逆过程,输入氢气H2_consumed,输出电功率P_fc和热功率H_fc。简化模型:
P_fc = η_fc × H2_consumed
H_fc = μ_fc × P_fc
η_fc是发电效率,μ_fc是热电比。氢储存罐作为缓冲,用能量平衡方程描述:
E_st(t+1) = E_st(t) + (V_h2_prod(t) - H2_consumed(t) - H2_load(t)) × Δt
同时约束储氢罐容量上下限,以及调度周期首末储氢量相等,保证日调度闭环。这里H2_load是固定的外部氢负荷,比如氢能公交加氢站的需求。
3.2 电制氢如何改变热电联产机组的运行边界
没有电制氢时,CHP的出力区间受热负荷约束非常窄。加入电解槽后,多了一个可控电负荷,可以在谷电时段主动增加用电量。这样做的效果是:即使CHP因为供热需要保持较高电出力,电解槽也能把这部分电力“吃掉”,转化成氢气存起来,而不是被迫外送或弃风。
更进一步,燃料电池在高峰时段放氢发电发热,替代了一部分CHP出力,使得CHP可以适当降低负荷,碳排放随之减少。这就把原来的纯热电耦合系统,变成了电-热-氢三能流耦合系统。建模的时候,不需要额外引入复杂的CHP可行域多边形,只需要在电平衡约束中把电解槽和燃料电池的功率项加进去即可,结构上非常自然。
3.3 氢负荷与系统整体能量流的平衡关系
整个系统的能量流平衡关系可以分成三条链路。电平衡:CHP电出力加风电加燃料电池电出力加外购电,等于电负荷加电解槽耗电。热平衡:CHP热出力加燃气锅炉热出力加燃料电池热出力,等于热负荷。氢平衡:电解槽产氢量加上储氢罐变化量,等于燃料电池耗氢量加外部氢负荷。
这些平衡关系在Matlab里就是一组线性等式约束,非常容易表达。关键是每个变量的单位要统一,我在代码里全部用kW和kWh,碳排放用吨,输入单位注意换算。
4. 优化模型的目标函数与约束体系全解
4.1 目标函数由哪些成本构成
整个优化目标是最小化系统日运行总成本,包括五个部分。
购电成本,逐时购电量乘分时电价求和。购气成本,CHP和燃气锅炉的天然气消耗量乘天然气价格。碳交易成本,就是前面构造的阶梯函数值C_carbon。设备运维成本,按每个设备的出力乘一个很小的单位运维系数。最后一项是售氢收益,如果模型允许氢气外售,可以在目标函数里减去收益项,形成盈利项。
目标函数写成:
min J = Σ (P_buy(t) × price_e(t)) + Σ (gas_usage(t) × price_gas) + C_carbon + Σ (k_i × P_i(t)) - Σ (V_h2_sell(t) × price_h2)
注意,碳交易成本如果是负的(配额富余获得收益),目标函数里应该减去。用前面的极大值表示法时不需要额外处理符号,C_carbon变量会自动反映收益。
4.2 约束体系的层次划分
约束体系可以分成四层。第一层是设备出力上下限约束,包括CHP电热出力、燃气锅炉热出力、电解槽输入功率、燃料电池电出力、储氢罐容量、风电出力上限。第二层是能量平衡约束,包括电平衡、热平衡、氢平衡。第三层是设备耦合关系,包括CHP热电比、燃料电池热电比、电解槽制氢效率、储氢罐动态方程。第四层是碳排放约束,包括配额计算公式、碳交易量计算公式、阶梯碳价的极大值约束。
调度周期一般取24小时,时间步长Δt=1小时。如果要做长时间尺度(比如168小时),设备数量不变,变量数会线性增加,LP求解器依然能比较快地求解。
4.3 模型求解适配性分析
这个模型的基础版本是线性规划(LP)问题,因为所有约束和优化目标都是线性的。变量全是sdpvar连续变量,没有任何0-1整数变量,所以Gurobi、Cplex、甚至开源的GLPK都能直接求解。我平时用Yalmip做建模,求解器用Gurobi,设置好solver参数后直接调用optimize。
如果以后要扩展单位启停状态约束,比如电解槽开停机不能太频繁,那就需要引入0-1变量,模型升级为MILP。MILP虽然也能求解,但计算时间会明显增加,而且整数变量多了之后,24小时调度问题也可能出现求解时间从几秒钟变成几分钟的情况。建议先把LP版本跑通,确认结果合理后再逐步加复杂度。
5. Matlab代码实现:从雏形到可复跑
5.1 基础数据与参数初始化
代码框架采用Yalmip建模,数据部分单独放在一个脚本里。下面是我在这个项目里用的参数,不一定是标准答案,但数值量级比较接近工程实际。CHP最大电出力250 kW,热电比1.5,发电效率0.35;燃气锅炉最大热出力400 kW,效率0.9;电解槽最大输入150 kW,最小输入10 kW,制氢效率0.6;燃料电池最大电出力100 kW,热电比1.0,发电效率0.5;储氢罐容量取200 kWh等效氢气能量。
负荷和风电数据需要手动构造,也可以从实测数据读入。我这段示例里用一个典型冬季日的数据,夜间热负荷高、电负荷低,夜间风电大,白天电负荷高、热负荷相对低。电价采用分时电价,谷段0.38元/kWh,峰段1.20元/kWh。天然气价格2.8元/m³,天然气低位热值9.7 kWh/m³。
碳排放系数方面,天然气按0.20吨CO₂/MWh(输入热值)计算,外购电按0.58吨CO₂/MWh计算。配额系数取负荷总量的0.35倍。阶梯碳价参数设为:c_sell=50元/吨,c1=80元/吨,c2=120元/吨,c3=180元/吨,L1=1吨,L2=2吨,因为24小时园区级系统的日排放量一般就在3到6吨的量级。
5.2 核心约束与目标函数的Yalmip写法
第一步用sdpvar定义决策变量。每个设备24小时的出力都是一个24×1的向量,Yalmip可以直接处理向量变量,比写循环更简洁。
第二步写约束。电平衡、热平衡直接用等式约束,设备上下限用不等式约束。储能罐的动态方程涉及相邻时刻的状态变量,用Yalmip的表达式写法可以方便地实现:
matlab复制E_st = sdpvar(T, 1); % 储氢罐各时段的储氢量
Constraints = [Constraints, H_st > 0, H_st < H_st_max];
Constraints = [Constraints, H_st(2:T) == H_st(1:T-1) + (V_h2_prod(1:T-1) - H2_consumed(1:T-1) - H2_load(1:T-1)) * dt];
注意这里H2_load是外部氢负荷向量,值不为0时,储氢罐方程会强制电解槽产氢来满足这部分需求。
第三步处理碳交易成本。先计算实际排放量和配额,然后得到碳交易量x,再用极大值表示法给出碳成本变量C_carbon相关约束。这一步是整个代码里最值得反复核对的地方,因为碳交易量的符号决定了系统是购买配额还是出售配额,如果符号反了,优化结果会差很多。
目标函数直接写成一长串求和表达式。Yalmip会自动把它改为线性表达式,交给Gurobi求解。
5.3 完整示例代码框架
下面是一段可复跑的Matlab+Yalmip代码框架,注释写得比较详细。数据部分我给出示例向量,实际使用可以替换成自己的负荷曲线。
matlab复制%% 考虑阶梯式碳交易机制与电制氢的综合能源系统热电优化
%% 基础参数设置
clear; clc; close all;
yalmip('clear');
T = 24;
dt = 1; % 时间步长,小时
% 负荷曲线(kW),长度24
P_load = [220 200 190 180 175 180 200 230 260 290 310 320 315 310 300 295 280 270 260 250 260 270 280 290];
H_load = [420 400 380 360 350 360 380 390 360 320 300 280 270 275 290 300 320 340 370 390 410 430 440 430];
P_wt_forecast = [120 130 140 140 130 120 110 100 90 80 70 60 60 65 70 75 80 85 90 95 105 110 120 125]; % 风电预测出力
% 电价曲线(元/kWh)
price_e = [0.38 0.38 0.38 0.38 0.38 0.38 0.60 0.90 1.20 1.20 1.20 1.20 1.20 1.20 0.90 0.90 0.90 1.20 1.20 1.20 0.90 0.60 0.38 0.38];
% 能源价格
price_gas = 2.8; % 天然气价格(元/m3)
LHV_gas = 9.7; % 天然气低位热值(kWh/m3)
price_h2 = 1.2; % 氢气外售价格(元/kWh,按LHV)
% 设备参数
P_chp_max = 250; % CHP最大电出力(kW)
mu_CHP = 1.5; % CHP热电比
eta_chp_e = 0.35; % CHP发电效率
P_gb_max = 400; % 燃气锅炉最大热出力(kW)
eta_gb = 0.9; % 燃气锅炉效率
P_el_max = 150; % 电解槽最大输入电功率(kW)
P_el_min = 10; % 电解槽最小输入电功率(kW)
eta_el = 0.6; % 电解槽制氢效率(kWh H2/kWh电)
P_fc_max = 100; % 燃料电池最大电出力(kW)
mu_fc = 1.0; % 燃料电池热电比
eta_fc = 0.5; % 燃料电池发电效率
H_st_max = 200; % 储氢罐最大储氢量(kWh)
H_st_init = 50; % 初始储氢量(kWh)
% 碳排放参数
alpha_gas = 0.20; % 天然气碳排放系数(tCO2/MWh,按输入热值)
alpha_grid = 0.58; % 外购电碳排放系数(tCO2/MWh)
lambda_quota = 0.35; % 配额系数(tCO2/MWh负荷)
% 阶梯碳交易参数
c_sell = 50; % 配额富余售出价(元/t)
c1 = 80;
c2 = 120;
c3 = 180; % 阶梯碳价(元/t)
L1 = 1;
L2 = 2; % 阶梯区间长度(t)
%% 定义决策变量
P_chp = sdpvar(T, 1);
H_chp = sdpvar(T, 1);
P_gb = sdpvar(T, 1); % 燃气锅炉热出力,kW
P_wt = sdpvar(T, 1); % 实际风电出力,kW
P_el = sdpvar(T, 1); % 电解槽输入电功率,kW
P_fc = sdpvar(T, 1); % 燃料电池电出力,kW
H_fc = sdpvar(T, 1); % 燃料电池热出力,kW
V_h2_prod = sdpvar(T, 1); % 电解槽产氢量,kWh
H2_consumed = sdpvar(T,1);% 燃料电池耗氢量,kWh
P_buy = sdpvar(T, 1); % 外购电功率,kW
H_st = sdpvar(T, 1); % 储氢罐储氢量,kWh
%% 构建约束
Constraints = [];
% CHP约束
Constraints = [Constraints, 0 <= P_chp <= P_chp_max];
Constraints = [Constraints, H_chp == mu_CHP * P_chp];
% 燃气锅炉约束
Constraints = [Constraints, 0 <= P_gb <= P_gb_max];
% 电解槽与产氢约束
Constraints = [Constraints, P_el_min <= P_el <= P_el_max];
Constraints = [Constraints, V_h2_prod == eta_el * P_el];
% 燃料电池约束
Constraints = [Constraints, 0 <= P_fc <= P_fc_max];
Constraints = [Constraints, H_fc == mu_fc * P_fc];
Constraints = [Constraints, H2_consumed == P_fc / eta_fc];
% 风电出力约束
Constraints = [Constraints, 0 <= P_wt <= P_wt_forecast'];
% 储氢罐动态约束
Constraints = [Constraints, 0 <= H_st <= H_st_max];
Constraints = [Constraints, H_st(1) == H_st_init];
Constraints = [Constraints, H_st(2:T) == H_st(1:T-1) + (V_h2_prod(1:T-1) - H2_consumed(1:T-1) - 30) * dt];
Constraints = [Constraints, H_st(T) == H_st_init]; % 日调度闭环
% 电平衡
Constraints = [Constraints, P_chp + P_wt + P_fc + P_buy == P_load' + P_el];
% 热平衡
Constraints = [Constraints, H_chp + P_gb + H_fc == H_load'];
% 碳排放与碳交易约束
F_chp = P_chp / eta_chp_e; % CHP燃料输入,kWh
F_gb = P_gb / eta_gb; % 燃气锅炉燃料输入,kWh
E_actual = (alpha_gas * (sum(F_chp) + sum(F_gb)) + alpha_grid * sum(P_buy)) / 1000; % 吨
E_base = lambda_quota * (sum(P_load) + sum(H_load)) / 1000; % 吨
x_carbon = E_actual - E_base;
C_carbon = sdpvar(1, 1);
Constraints = [Constraints, C_carbon >= c_sell * x_carbon];
Constraints = [Constraints, C_carbon >= c1 * x_carbon];
Constraints = [Constraints, C_carbon >= c2 * x_carbon + (c1 - c2) * L1];
Constraints = [Constraints, C_carbon >= c3 * x_carbon + (c1 - c2) * L1 + (c2 - c3) * L2];
%% 目标函数
buy_cost = sum(P_buy .* price_e');
gas_cost = (sum(F_chp) + sum(F_gb)) / LHV_gas * price_gas;
maintain_cost = 0.01 * sum(P_chp + P_gb + P_el + P_fc);
h2_income = 0; % 无外售收益,可自行扩展
objective = buy_cost + gas_cost + C_carbon + maintain_cost - h2_income;
%% 求解
ops = sdpsettings('solver', 'gurobi', 'verbose', 2);
result = optimize(Constraints, objective, ops);
%% 结果输出
if result.problem == 0
disp('求解成功');
P_chp_opt = value(P_chp);
H_chp_opt = value(H_chp);
P_gb_opt = value(P_gb);
P_wt_opt = value(P_wt);
P_el_opt = value(P_el);
P_fc_opt = value(P_fc);
H_fc_opt = value(H_fc);
P_buy_opt = value(P_buy);
H_st_opt = value(H_st);
fprintf('总运行成本: %.2f 元\n', value(objective));
fprintf('碳交易成本: %.2f 元\n', value(C_carbon));
fprintf('实际碳排放: %.4f 吨\n', value(E_actual));
fprintf('碳配额: %.4f 吨\n', value(E_base));
fprintf('电解槽利用小时数: %.2f h\n', sum(value(P_el) > 1));
figure;
subplot(3,1,1);
stairs(1:T, [P_chp_opt, P_wt_opt, P_fc_opt, P_buy_opt], 'LineWidth', 1.5);
legend('CHP电出力','风电出力','燃料电池电出力','外购电');
title('电力调度结果');
xlabel('时刻/h'); ylabel('功率/kW');
grid on;
subplot(3,1,2);
stairs(1:T, [H_chp_opt, P_gb_opt, H_fc_opt], 'LineWidth', 1.5);
legend('CHP热出力','燃气锅炉热出力','燃料电池热出力');
title('热力调度结果');
xlabel('时刻/h'); ylabel('功率/kW');
grid on;
subplot(3,1,3);
stairs(1:T, [P_el_opt, H_st_opt], 'LineWidth', 1.5);
legend('电解槽输入功率','储氢罐储氢量');
title('电制氢与储氢调度结果');
xlabel('时刻/h'); ylabel('功率/kW 或 储氢量/kWh');
grid on;
else
disp('求解失败,请检查约束和参数设置');
end
5.4 结果解读:峰谷联动与碳价敏感性
把代码跑通之后,第一件事不是急着改参数,而是看几张图。正常情况下应该能看到:风电出力曲线在夜间保持在较高水平,而电解槽输入功率也在夜间达到高峰,这说明模型成功利用了谷电制氢。储氢罐在夜间缓慢上升,白天燃料电池放氢发电时缓慢下降。CHP在夜间热负荷大的时候维持较高热出力,白天负荷高峰时,燃料电池开始分担一部分电出力。
碳交易成本的值可以直接从fprintf打印出来。如果C_carbon是正值,说明实际排放超过了配额,系统在购买配额。如果出现负值,说明配额有富余,系统有碳收益。这时可以重点观察:加入电制氢前后,C_carbon有没有明显变化。我做过对比,在一个典型冬季日数据下,加入电解槽并让燃料电池参与高峰发电,碳交易成本大约下降15%到25%,具体幅度取决于碳价参数和储氢罐容量。
灵敏度分析也是这个项目里很有价值的部分。分别把c1、c2、c3同时放大1.5倍、2倍,观察CHP出力和电解槽利用率的变化。碳价越高,CHP在高峰时段的出力会越低,电解槽的利用小时数会上升。如果结果里碳价翻倍后电解槽依然纹丝不动,大概率是约束设置有问题,常见原因是储氢罐容量被限制死了,或者氢负荷常数设置得太大导致没有调度空间。
6. 常见问题与排查技巧实录
6.1 Infeasible Problem:先别急着调参
Gurobi报“Infeasible problem”是新手最常遇到的情况,而且这个报错信息很让人头大,因为它不会直接告诉你哪条约束出了问题。
我的排查习惯是先做二分法测试。第一步,把碳排放相关约束整套注释掉,看模型是否可解。如果可解,说明可行域的问题出在碳排放约束里,重点检查碳交易量的符号和阶梯区间参数。第二步,如果去掉碳排放约束后依然不可解,再注释电制氢相关约束,把电解槽和燃料电池的变量从平衡方程里去掉。这两步基本能定位到具体的约束模块。
实际上最常见的原因有两个。一是热平衡和CHP热电比耦合太紧,热负荷设置不切实际,导致电平衡也跟着无法满足。比如热负荷是450 kW,CHP最大热出力是250×1.5=375 kW,燃气锅炉最大400 kW,叠加后热上限是775 kW,看起来够用,但对某个时段,如果CHP热出力设成375 kW,电出力就是250 kW,电平衡中电负荷只有180 kW,而电解槽最小出力10 kW,风电是120 kW,外购电可以为负吗?不行,P_buy有隐含下限0。这样电就过剩了,模型无解。这种时候不是压缩风电,就是让CHP降低热出力,或者让电解槽多吃电。调整的方向是放宽P_buy的下限,或者给多余电设置一个明确的“弃电”变量。
6.2 求解结果“不符合预期”的排查顺序
很多人代码跑通后发现结果不合理,比如电解槽整天不开机,或者燃气锅炉热出力为零但热负荷全靠CHP扛。这时候我建议按这个顺序排查。
先看单位。检查目标函数里所有成本项的单位是否一致。我犯过一次错误是碳排放系数用吨/MWh,但负荷数据用的是kW,算出来的E_actual差了1000倍,阶梯碳价区间变得毫无意义,碳成本基本上恒为0。这是这类模型里最常见的隐性bug。
再看目标函数各项的量级。购电成本一般每天几千元,购气成本几千元,碳交易成本几百到上千元。如果碳交易成本只占不到1%,说明碳价或者配额设置有问题,碳约束对模型几乎没有约束力,结果当然不合理。
还要看风机预测曲线和负荷曲线的关系。如果全天风电都小于电负荷很多,电解槽的消纳意义就不大,需要在场景数据上做调整,而不是硬调参数。
6.3 碳交易和电制氢参数灵敏度分析的实操建议
做这个项目时,灵敏度分析是最能体现模型价值的部分。建议至少做三组对比:第一组是阶梯碳价系数从0.5倍变化到2倍,观察系统总成本和碳排放量的变化;第二组是储氢罐容量从50 kWh变化到500 kWh,观察电解槽利用小时数和风电消纳率的变化;第三组是氢负荷从0变化到100 kW,观察电解槽被“强制开启”的程度。
每组跑完之后,把结果汇总成表格。一个典型结果可能是:碳价提高后,碳排放量下降,但总成本上升,说明碳约束有效但是有经济代价;储氢罐容量扩大后,电解槽利用率上升,但容量超过某个值后改善效果明显变缓,这说明存在一个经济最优的储氢容量区间。这个结论放到论文里或者项目报告里,说服力比单纯贴出调度曲线强得多。
6.4 工具链和版本相关的避坑提示
Matlab版本建议R2021b以上,Yalmip用最新版就行。求解器我推荐Gurobi,因为它的LP求解速度比开源求解器快很多,而且对大规模MILP的支持也最成熟。如果你没有Gurobi授权,也可以先用Yalmip内置的sedumi或开源的GLPK跑小规模算例,验证模型正确性,然后再
