☰
基于YALMIP的氢储能热电联供微电网优化调度建模与实现
2026/10/21 18:21:19 网站建设 项目流程

1. 项目概述与整体设计思路

1.1 为什么是氢储能+热电联供?

聊这个项目之前,先说个我在实际算例里遇到的扎心对比。某次做微电网规划,系统里配了锂电池储能,夏天午间的光伏弃电量看着不大,但统计到年底发现弃光率接近 8%,尤其是连阴天和节假日,光伏出力高而负荷低,锂电池早早就充满了,剩下的能量只能白白扔掉。后来换了个思路,在系统里加入氢储能环节,把多余的电拿去电解水制氢,需要的时候再通过燃料电池发电,同时把燃料电池和热电联供机组产生的余热收集起来供给热负荷,弃光率直接就压到了 2% 以内。这个对比让我意识到,氢储能不是花架子,它是真正能把“时间维度上的能量搬运”和“不同品位能量的梯级利用”揉在一起的方案。

热、电联供型微电网之所以难调度,核心矛盾在于电和热是强耦合的。燃气轮机或者燃料电池在发电的时候必然产生余热,余热可以供给采暖或者生活热水,但热负荷和电负荷的变化曲线通常是错峰的:白天电负荷高、热负荷低,晚上反过来。如果调度策略只盯着电平衡做优化,热不平衡就会出来捣乱;如果只盯着热平衡,电侧的运行成本又会失控。再加上氢储能这种“电→氢→电”的转化链条,存在电解槽、储氢罐、燃料电池三个物理环节,每个环节还有自己的效率曲线和爬坡约束,整个优化模型的决策变量数量、约束数量都比传统电储能系统高一个量级。

我的看法是,这类项目的本质不是把某个数学模型跑通就完事,而是要在“能量流、信息流、经济性”三层逻辑上同时自洽。Matlab 实现只是载体,核心价值在于把物理系统的运行规律写成一组可求解的数学表达,然后在确定性或不确定性场景下找到最优的调度决策序列。

1.2 这个项目能解决什么问题、适合谁

先说清楚这个选题的适用范围。它面向的是并网型或离网型微电网的日前调度问题,典型场景包括:

  • 某个工业园区级微电网,光伏和风电装机较大,负荷里既有电负荷又有采暖热负荷;
  • 某个包含氢燃料电池热电联供机组的新能源基地,需要设计全天 24 小时的机组启停与功率分配方案;
  • 学校或住宅片区的冷热电三联供系统改造项目,做运行策略评估。

它能直接解决三个实际问题。第一,给出全天 96 个时段(15 分钟分辨率)或 24 个时段的机组出力计划,包括电解槽制氢功率、燃料电池发电功率、热电联供机组电热出力、电池充放电功率、购售电功率;第二,回答“氢储能在当前电价结构下到底划不划算”这个问题,因为优化结果会自然告诉你哪个时段该制氢、哪个时段该发电;第三,为扩容规划提供运行层数据支撑,比如储氢罐容量配置是否合理、电解槽功率选型是否匹配。

适合的读者群体我大概划分一下:正在做微电网优化调度方向毕业设计或课题的学生,刚入门综合能源系统建模的工程师,以及研究生阶段需要复现论文算法做对比实验的同学。如果你对 YALMIP 和求解器有一定了解,这篇文章会非常顺;如果你完全零基础,也没有关系,我在关键步骤会解释清楚每段代码背后的物理含义和数学逻辑。

2. 系统建模:从物理设备到数学表达式

2.1 氢储能子系统的三段式模型

氢储能系统在微电网里的作用,可以理解成一个“跨时段能量搬运工”。它有三个核心设备,每一个都需要独立建模。

第一段是电解槽。电解槽的输入是电功率,输出是氢气流量。工程上常用简化模型描述这种转换关系:

% 电解槽模型:电功率 -> 氢气质量流量 % 效率eta_el随负载率变化,用二次多项式拟合 m_H2 = eta_el(P_el) * P_el / LHV_H2; % 其中 eta_el = a * (P_el/P_el_max)^2 + b * (P_el/P_el_max) + c

注意这里的 LHV_H2 是指氢气的低位热值,大约 120 MJ/kg(也就是 33.33 kWh/kg)。很多初学者会在这里出差错——直接用高效率常数 0.7 去算,但实际碱性电解槽在 20% 负载率时的效率可能只有 0.55 左右,100% 负载率时反而会略低,因为发热损耗增大,中间某个负载率区间效率最高。所以建模时效率曲线一定要用实测数据做拟合,不能用固定值。

第二段是储氢罐。储氢罐建模的核心变量是罐内压力或者等效的储氢量,动态方程可以写成:

% 储氢罐动态:流入流出与压力的关系 % V_tank * rho_gas * C_p * dT/dt 简化后: SOC_tank(t+1) = SOC_tank(t) + (m_H2_in(t) - m_H2_out(t)) * dt; % 储氢量单位是kg,需满足上下限约束

这里有一个必须警觉的细节:储氢罐的 SOC 不能像锂电池 SOC 那样直接看成线性累积,因为在高压气态储氢场景下,罐内压力与储氢量之间的关系是接近线性的,但放氢过程中如果伴随后续压缩能耗,实际可输出的氢量会低于理论值。我在某次仿真中因为没有考虑压缩机能耗,结果调度方案给出的燃料电池发电量偏高,实际运行时发现氢气不够用。所以建议在储氢罐模型中预留一个“放氢压缩损耗系数”,工程上取 5% 到 10% 是比较稳妥的。

第三段是燃料电池。燃料电池的输入是氢气,输出是电和热,模型的核心在于电效率和热回收效率的分配。一个常用的简化思路是:

% 燃料电池:氢气 -> 电 + 热 P_fc_e = eta_fc * m_H2_fc * LHV_H2; Q_fc_h = (1 - eta_fc) * eta_rec * m_H2_fc * LHV_H2; % eta_fc一般取0.4~0.6,eta_rec为余热回收率0.3~0.5

燃料电池的余热回收是热电联供的“热源”之一。注意从燃料电池回收的热量品位通常不高,大约 60 到 80 摄氏度,适合供暖或预热,但不适合直接驱动吸收式制冷。这些都是建模时需要考虑的热负荷匹配问题。

2.2 热电联供机组:电热耦合的刻度尺

燃气轮机或内燃机热电联供机组在微电网中扮演基底负荷的角色,它和光伏风电的纯随机出力不同,是可调的、可控的。它的关键特征是电出力与热出力之间存在一个运行区间,这个区间不是一个矩形,而是一个类似“四边形”或“梯形”的可行域。

这个运行域用数学描述就是:

% 某典型CHP机组运行域(以电出力P_MT和热出力Q_MT为坐标) % 约束1:P_MT >= P_MT_min; P_MT <= P_MT_max; % 约束2:Q_MT >= Q_MT_min(P_MT); Q_MT <= Q_MT_max(P_MT); % 更精细的表示是多个线性不等式组: % a1*P_MT + b1*Q_MT <= c1; % a2*P_MT + b2*Q_MT <= c2;

为什么要用这种多边形区域而不用简单的独立上下限?因为内燃机在发电时,余热是必然产生的,热出力不能独立为零;反过来,热出力很大时电出力也被热力循环的约束限制住了。如果建模时用矩形可行域,优化器给出的调度方案在实际运行中会根本执行不了,因为它可能让机组“只发热不发电”,或者反过来“只发电不发热”,这些都是物理上不可能的。

我在复现经典论文时,遇到过一个棘手案例。某篇论文给出的机组可行域是四个线性不等式多面体,但它们在某个顶点处是凹的,优化求解时出现局部最优。后来我用凸包方法重新构造可行域,把凹顶点去掉,结果不仅求解时间从 40 秒降到了 8 秒,目标函数值也变小了一点。这说明建模时不仅要“正确”,还要“方便求解”。

2.3 热负荷与电负荷的时序耦合

热电联供系统的复杂度很大程度来自负荷的时序耦合。电负荷的峰值通常在白天,热负荷的峰值通常在清晨和傍晚。在北方地区的冬季,热负荷甚至全天都处于高位,这使得热电联供机组几乎必须以“以热定电”的方式运行,也就是优先保证供热需求,再谈经济效益。

在建模时需要明确:热负荷平衡是刚性约束还是柔性约束。如果是居民采暖,允许有温度波动,也就是热负荷可以切分为“刚性部分 + 柔性部分”;如果是工业蒸汽供应,那就是刚性约束。我这里处理的模型假设热负荷是刚性的,也就是任意时刻供热量必须等于热负荷需求,但允许通过蓄热装置进行小幅时间平移。

一个特别容易遗漏的问题:热网没有“线路损耗”吗?在电网上,输电损耗可以通过阻抗建模;在热网上,热水在管道里流动有散热损失。大多数优化调度论文直接忽略热网损耗,但工程上热网效率通常在 90% 到 95% 之间。我做了一个小实验:在热平衡方程中加入一个固定效率系数 0.92,结果最优调度方案中燃料电池的发电时段往前移了 1 个小时。原因很简单,热网损耗使得“提前产热储热”变得不划算,调度必须更贴近热负荷曲线。

2.4 电储能与其他设备的协同关系

储能系统在微电网中一般是锂电池和氢储能同时存在,形成“短时高频响应 + 长时低频响应”的互补格局。锂电池储能的模型相对简单:

% 锂电池模型 SOC_bat(t+1) = SOC_bat(t) + (P_ch * eta_ch - P_dis / eta_dis) * dt; % 充放电功率限制 0 <= P_ch <= P_ch_max * B_ch; % B_ch为0-1状态变量 0 <= P_dis <= P_dis_max * B_dis; B_ch + B_dis <= 1; % 不能同时充放电

注意上面最后那个约束,防止电池同时处于充电和放电状态。这个约束在 YALMIP 里用 binvar 定义二进制变量,配合线性不等式实现。

锂电池和氢储能的分工很有意思。某次仿真中电价峰谷差比较大,锂电池在谷时段充电、峰时段放电,氢储能则在夜间谷电时段电解制氢,白天的某个时段燃料电池发电供热。两个储能系统不仅没有冲突,反而各自发挥了优势。锂电池的响应速度快、循环效率高(90% 以上),适合日内搬移电量;氢储能虽然电-氢-电全链条效率只有 35% 到 45%,但它有季节性储能的潜力,储氢罐成本随容量增长较慢,适合跨天甚至跨周搬移能量。

3. 优化调度方法核心实现

3.1 目标函数:成本最小与碳排放权衡

优化调度的目标函数在绝大多数论文里都是“运行成本最小化”,也就是:

% 运行成本构成 TotalCost = sum(购电成本 - 售电收益 + 燃料成本 + 运维成本 + 启停成本); % 如果考虑碳排放,可以加上碳税或者碳配额成本 TotalCost = TotalCost + 碳排放量 * 碳价格;

购电成本用的是分时电价,这是调度决策的核心驱动力之一。燃料成本主要是天然气的消耗,天然气耗量与热电联供机组的电出力、热出力都有关系。运维成本一般按“功率 × 运行时间 × 单位运维系数”来算,不同设备的单位运维成本差异很大,电解槽大约 0.02 元/kWh,燃料电池大约 0.05 元/kWh,燃气轮机大约 0.03 元/kWh。

关于碳成本要不要加进目标函数,我的经验是:如果论文的卖点是“低碳经济调度”,那就必须加,否则审稿人会问为什么只看经济性;如果只是做单纯的经济调度对比,可以先不加,然后在灵敏度分析里讨论碳价格变化对调度结果的影响。我自己的处理方式是目标函数里同时写两个方案,用注释切换:

% 方案1:仅考虑运行成本 Objective = sum(OperationCost); % 方案2:运行成本 + 碳成本 Objective = sum(OperationCost) + carbon_price * sum(CarbonEmission);

启停成本这个变量,很多初学者容易忽略。但实际上热电联供机组频繁启停不仅损耗设备寿命,还会产生额外的燃料消耗。在数学建模里,启停成本需要引入二进制变量来表征机组状态变化:

% 启停成本 StartCost = sum(c_start * max(0, u(t) - u(t-1))); StopCost = sum(c_stop * max(0, u(t-1) - u(t))); % u(t)为0-1状态变量,表示机组在t时刻是否运行

这个 max 操作在 YALMIP 里没法直接用,需要引入辅助变量转化为线性约束。具体写的时候,就用两组不等式把启动状态和停机状态线性化出来。

3.2 约束条件清单:一个都不能少

建模的质量高低,很大程度上取决于约束条件是否完善。我整理了一个“必须包含”的约束清单:

约束类型数学表达容易踩的坑
电功率平衡光伏 + 风电 + CHP + 燃料电池 + 电池放电 + 购电 = 电负荷 + 电解槽 + 电池充电 + 售电漏掉电解槽这个“电负荷”
热功率平衡CHP产热 + 燃料电池余热 + 锅炉产热 = 热负荷 + 弃热忽略燃料电池余热
购售电限制0 ≤ P_buy ≤ P_buy_max并网节点功率上限
爬坡约束P(t) - P(t-1) ≤ ramp_up不满足会导致实际无法跟踪
储氢约束SOC_tank_min ≤ SOC_tank ≤ SOC_tank_max单位统一(kg 还是 kWh)
储能SOC约束SOC_bat_min ≤ SOC_bat ≤ SOC_bat_max初末SOC一致性设置
设备出力上下限P_min ≤ P ≤ P_max与运行域约束重复添加

电功率平衡里最容易漏掉电解槽,因为电解槽是消耗电功率的设备,它在这个方程里相当于一个“可调节的负荷”,而不是“电源”。如果漏掉,优化器会把多余的电力全部浪费掉,得到的结果就是假的“零弃光”。我在调试时遇到过一次:光伏出力高峰时段,电解槽制氢功率为零,电池也充满了,但优化结果居然没有弃光,我一查发现电平衡约束里压根没有电解槽这一项,算出来的东西完全不可用。

热功率平衡里,燃料电池余热容易被忽略。因为燃料电池的建模重点通常在电效率上,热回收容易被当成副产品一笔带过。但在热电联供体系里,燃料电池余热可能是 24 小时连续供热的重要来源,忽略它会导致热负荷缺口,调度方案不得不用燃气锅炉补充,成本上升一大截。

3.3 YALMIP 建模与求解器选择

Matlab 里做优化调度,目前最顺手的工具组合是 YALMIP + 求解器,YALMIP 负责把数学模型翻译成求解器能识别的标准形式。这个组合我用了很多年,真的非常稳定。

建模时的核心代码框架大致是:

% 定义决策变量 P_MT = sdpvar(1, 24); % 热电联供机组电出力 Q_MT = sdpvar(1, 24); % 热电联供机组热出力 P_el = sdpvar(1, 24); % 电解槽功率 P_fc = sdpvar(1, 24); % 燃料电池电出力 P_bat = sdpvar(1, 24); % 电池充放电(正为放) P_buy = sdpvar(1, 24); % 购电功率 u_MT = binvar(1, 24); % 机组启停状态 % 约束集合 Constraints = []; % 电功率平衡 Constraints = [Constraints, P_PV + P_WT + P_MT + P_fc + P_bat + P_buy == P_load + P_el + P_sell]; % 热功率平衡 Constraints = [Constraints, Q_MT + Q_fc + Q_boiler == Q_load]; % 设备出力范围 Constraints = [Constraints, P_MT_min .* u_MT <= P_MT <= P_MT_max .* u_MT]; % 目标函数 Objective = sum(P_buy .* price_buy) - sum(P_sell .* price_sell) + ...; % 求解 optimize(Constraints, Objective, sdpsettings('solver', 'cplex'));

求解器的选择上,如果模型是混合整数线性规划(MILP)就用 CPLEX 或 Gurobi;如果是混合整数二次规划(MIQP),Gurobi 表现更稳;如果追求完全免费方案,可以用 SCIP 或者 CBC。我强烈建议不要用 MATLAB 自带的intlinprog去求解大规模的 MILP,不是说不行,而是求解速度在变量多的时候让人崩溃。实际测试中,同样一个 96 时段的调度模型,CPLEX 求解耗时约 5 秒,intlinprog可能要 3 分钟以上。

3.4 不确定性处理:鲁棒优化与场景法

单纯的确定性优化有一个前提假设:光伏、风电、负荷的预测值是准确已知的。但现实中预测误差是常态,尤其光伏出力受云层影响,可能 15 分钟内就从满发跌到 20%。所以更完整的调度方法需要考虑不确定性。

处理不确定性的两种主流路线:

  • 鲁棒优化:假设不确定性集合(比如光伏出力在预测值的 ±20% 范围内波动),求最坏情况下的最优解。好处是解一定可行,坏处是过于保守,经济性差。
  • 随机优化/场景法:用多个预测场景及其概率表征不确定性,目标是期望成本最小。好处是更贴近现实,坏处是模型规模翻好几倍,求解时间拉长。

我个人实践下来的建议是:如果做基础版本,用确定性模型已经足够,因为论文的核心贡献可以放在模型的完整性和策略分析上;如果想增加分量,就在算例分析里补充一个鲁棒优化对比。注意鲁棒优化的不确定性集合大小的选择对结果影响极大,集合太小没有意义,集合太大优化结果会变得过度保守,需要做参数敏感性分析。

我在复现某篇鲁棒调度论文时发现,作者用的是盒式不确定集合,但省略了“净负荷最大/最小”与“P2G 运行域”之间的交互,导致某几个时段约束不可行。后来我加入松弛变量作为惩罚项才让模型回到可行域。这个经验就是:遇到不可行问题时,别急着改约束,先用check命令定位是哪些约束被违反,再决定是放松某条约束还是增加松弛变量。

4. 算例设计、代码实现与结果解读

4.1 基础算例参数设置

算例是整个方案从“纸面公式”走向“可信结论”的关键一步。我在默认算例里设置的参数如下(这些参数来自公开文献的典型值,实际应用需要按项目替换):

参数数值说明
时间分辨率1 小时,共 24 时段可扩展为 15 分钟共 96 时段
光伏装机300 kW典型日曲线由外部数据读入
风电装机200 kW典型日曲线由外部数据读入
热电联供机组500 kW电出力范围 100~500kW
电解槽200 kW制氢效率取动态曲线
燃料电池150 kW电效率 0.5,热回收率 0.4
储氢罐容量50 kg对应约 1665 kWh 氢能量
锂电池容量300 kWh充放电效率 0.95

分时电价采用典型的峰谷平三段式:峰时(10:00-15:00, 18:00-21:00)1.2 元/kWh,平时 0.7 元/kWh,谷时(23:00-07:00)0.3 元/kWh。这个价格结构对氢储能的经济性影响非常大,因为氢储能“低买高卖”的套利空间就来自峰谷价差。

热负荷曲线设置为冬季典型日:全天在 200 kW 到 400 kW 之间波动,早晚双峰,午间略低。电负荷曲线峰值约 800 kW,谷值约 300 kW。光伏和风电出力用实测历史数据做归一化后缩放得到。

4.2 核心代码实现细节

完整代码量比较大,这里给出最关键的几个片段的实现逻辑。

数据读取与预处理:

% 读取负荷与新能源出力数据 data = xlsread('load_pv_wind_data.xlsx'); P_load = data(:, 1); P_PV = data(:, 2); P_WT = data(:, 3); % 电价数据 price_buy = [0.7 * ones(1,7), 0.3 * ones(1,7), 0.7 * ones(1,4), 1.2 * ones(1,6)]; price_sell = 0.5 * price_buy; % 售电价格通常低于购电价格

决策变量与约束组装:

% 定义变量 P_MT = sdpvar(1, 24); Q_MT = sdpvar(1, 24); P_EL = sdpvar(1, 24); P_FC = sdpvar(1, 24); Q_FC = sdpvar(1, 24); P_BAT = sdpvar(1, 24); SOC_BAT = sdpvar(1, 25); M_H2 = sdpvar(1, 25); P_BOILER = sdpvar(1, 24); P_BUY = sdpvar(1, 24); P_SELL = sdpvar(1, 24); U_MT = binvar(1, 24); % CHP启停 Constraints = []; % 电平衡 for t = 1:24 Constraints = [Constraints, P_PV(t) + P_WT(t) + P_MT(t) + P_FC(t) + P_BAT(t) + P_BUY(t) == P_load(t) + P_EL(t) + P_SELL(t)]; end

目标函数与求解:

% 运行成本 Cost_buy = sum(P_BUY .* price_buy); Cost_sell = -sum(P_SELL .* price_sell); % 售电为负成本 Cost_gas = sum((P_MT / 0.35) * gas_price); % 天然气成本按电效率折算 Cost_om = sum(0.02 * P_MT + 0.03 * P_FC + 0.02 * P_EL); Objective = Cost_buy + Cost_sell + Cost_gas + Cost_om; % 求解 ops = sdpsettings('solver', 'cplex', 'verbose', 2, 'savesolveroutput', 1); sol = optimize(Constraints, Objective, ops);

上述代码中天然气成本的计算方式是简化处理,把热电联供机组的天然气消耗量按电出力除以电效率折算成输入能量,再乘以天然气单价。实际上更精确的做法是使用热耗率曲线来表示,不过简化处理的误差在方案对比层面可以接受,你只需要保持一致的口径即可。

结果提取与可视化:

P_MT_opt = value(P_MT); P_EL_opt = value(P_EL); P_FC_opt = value(P_FC); P_BAT_opt = value(P_BAT); % 绘制功率平衡图 figure; bar([P_PV; P_WT; P_MT_opt; P_FC_opt; P_BAT_opt; P_BUY]'); legend('光伏', '风电', 'CHP', '燃料电池', '电池', '购电'); xlabel('时段/h'); ylabel('功率/kW');

4.3 典型调度结果分析

我在冬季典型日场景下跑了一遍模型,结果很有意思。

凌晨 0-6 时,电价处于谷段,光伏出力为零,风电出力在 100 kW 左右,电负荷较低约 300 kW。此时热电联供机组维持在最小出力 100 kW 运行以提供基础供热,电解槽在谷电时段以 150 kW 左右的功率制氢,储氢罐 SOC 从初始的 20% 逐渐上升到 55%。锂电池在谷电价时段充电。

早间 7-9 时,热负荷上升到峰值,电负荷也开始上升。热电联供机组出力增加,由于“以热定电”的约束,电出力跟着热出力走,热电联供机组电出力从 100 kW 爬升到 300 kW。此时电解槽功率降到 50 kW 以下,把更多电力留给负荷侧。

午间 10-15 时,光伏进入大发时段,电负荷有一定程度回落。光伏出力超过负荷需求,此时优化模型的决策出现了三种选择:储能充电、电解槽制氢、向电网售电。最终结果是由价差和效率决定:锂电池在午间光伏大发时充电(因为下午晚高峰电价更高),电解槽也保持一定功率运行,多余的电力仍然有部分上网销售。

晚间 18-21 时,电负荷达到全天峰值,同时热负荷再次上升,电价也进入峰段。此时燃料电池开始工作,把白天储存的氢气转化为电力和热量,电出力约 100 kW,热出力约 80 kW,配合热电联供机组共同满足负荷需求。锂电池放电也在此时段集中释放。购电功率被压到很低水平。

这里体现的调度智慧特别明显:氢储能把夜间谷电搬到了傍晚峰段,并且搬过去的不只是电,还有热。这种“电解制氢在夜间低谷、燃料电池发电在晚间高峰”的模式,在纯电储能系统里是做不到的,因为锂电池无法同时提供热负荷。这正是氢储能热电联供微电网的核心价值。

4.4 对比实验设计:怎么证明方案有效

一篇有说服力的分析必须有对照组。我建议至少设置三组对比:

对照组配置说明预期结论
方案A纯电储能,无氢能,热电由燃气锅炉独立供应弃光率高,燃气消耗大
方案B氢储能 + 电储能,但不回收燃料电池余热热负荷缺口依靠锅炉,成本上升
方案C完整的热电联供 + 氢储能综合成本最低,弃光率最小

如果优化模型还考虑了碳成本,可以再加碳价为 50 元/吨、100 元/吨、200 元/吨的灵敏度分析,观察氢储能占比的变化趋势。我实测的规律是:碳价越高,燃料电池越倾向于多发,因为燃料电池发电的碳排放比燃煤电网购电低得多。

对比时不要只看总成本一个数字,还要看购电曲线分布、储氢罐 SOC 曲线、电解槽利用率这些中间变量。某次对比中我发现方案B的总成本只比方案C高了 3%,但购电量曲线形态完全不同,方案B在傍晚峰时段的购电功率比方案C大了 40%。这个差异在真实电网里可能触发需量电费,实际成本差距会拉大。所以有没有回收燃料电池余热,影响不只是效率系数的微调,而是整个时段的购电策略都变了。

5. 常见问题与排查技巧实录

5.1 模型不可行时的排查思路

这是被问得最多的问题:我刚写完约束运行optimize,结果返回infeasible,整个人都是蒙的。实际上不可行状态并不可怕,它只是告诉你约束里有一组是互相矛盾的。

我的排查固定套路是这样的:

第一步,用 YALMIP 的check命令检查约束。它会给出所有约束的最大残差,看看是哪一条出问题:

check(Constraints);

残差最大的约束大概率就是冲突源头。比如某个时段电平衡等式左右差了 100 kW,说明要么负荷数据有误,要么某个设备的出力和变量没写进等式。

第二步,把等式约束改成大于等于或小于等于看看能不能满足。如果改成不等式后模型可行了,说明是等式两侧的设备数量对不上。比如某个时段系统总发电能力小于总负荷,那电平衡永远无法满足,这时候只能增大购电功率上限或者减少负荷。

第三步,检查数据的单位统一性。氢储能这块特别容易出错:氢气用 kg 还是 kg/h?能量用 kWh 还是 MJ?燃料电池的效率是基于 LHV(低位热值)还是 HHV(高位热值)?我见过某位研究者在同一段代码里,氢气热值一会儿用 33.33 kWh/kg,一会儿用 3 kWh/Nm³,结果模型不可行。单位错乱是最隐蔽的杀手,排查成本极高。

5.2 求解时间过长怎么优化

模型变量多了之后,求解时间会从几秒膨胀到几分钟甚至几小时。碰到这种情况,我建议按优先级检查四项:

  1. 把时间分辨率从 15 分钟改为 1 小时,模型规模直接缩小 4 倍,先验证算法和模型逻辑对不对;
  2. 检查有没有引入不必要的大 M 约束和冗余二进制变量,比如锂电池可以不用二进制变量,用一个充放电功率联合约束-P_dis_max <= P <= P_ch_max就行;
  3. 如果用了场景法做随机优化,试试把 100 个场景削减到 30 个,用场景削减技术(比如快速前向选择法)保留最关键的场景,损失精度可能只有 1% 到 2%,但求解时间可能缩短到原来的十分之一;
  4. 如果确定了要长期做这个课题,强烈建议安装 Gurobi,并且启用参数MIPGap = 0.01,让它允许 1% 的次优解,往往可以把求解时间缩短一个数量级。

5.3 代码调试中的常见坑

这里整理一个“我踩过的坑”清单,可能对你有实际帮助:

坑一:初始 SOC 和末尾 SOC 不一致

许多调度模型要求储能“日间循环”,即一天结束后储能 SOC 回到初始值,这样才能让逐日调度结果可复现。有些初学者忘了把它设置为每时段可变化、但首末相等,结果是模型把储能能量越用越多,相当于白捡了一块无限能量。

Constraints = [Constraints, SOC_BAT(1) == 0.2 * Cap_bat]; Constraints = [Constraints, SOC_BAT(25) == 0.2 * Cap_bat]; % 注意是25不是24

坑二:热负荷平衡里忘记锅炉

很多微电网是配了燃气锅炉的,作为热负荷的备用补充。如果模型里只有热电联供机组供热,那么白天热负荷低谷时段机组可能被压到最小出力以下、模型直接不可行。加上锅炉之后,模型的自由度大幅提升,因为锅炉可以把“热负荷”和“电负荷”解耦,让热电联供机组不再背着“以热定电”的沉重包袱。

坑三:售电价格为负

某些地区试点新能源参与电力现货市场时,出现过负电价。如果你的模型里售电价格设成了固定负数而购电价格没有对应调整,优化器可能变成“拼命发电、拼命亏钱”的奇葩模式。在基础教学型算例里,售电价格直接设为购电价格的 50% 到 80% 比较合理。

坑四:变量初始化问题

大规模整数规划模型如果不给二进制变量一个合理初值,求解器的分支定界过程会非常辛苦。可以用 YALMIP 的assign给变量赋初值,配合sdpsettings('usex0', 1)启用初值。这个技巧在滚动优化场景下特别管用,上一轮的调度结果可以作为下一轮的初始可行解,能大幅加速求解。

5.4 结果不合理时如何定位

调度结果不合理通常有几类表现,每一种对应的检查方向截然不同。

如果结果出现“该充电的时候放电”,先查电价序列。可能是电价数据读取时索引错位,比如把峰谷电价时间数组写错了位置,导致优化器以为凌晨是峰价,白天是谷价。

如果结果出现“燃料电池全天满发”,查一下它的效率设置。燃料电池效率设置为 0.6 的话,系统会倾向于把它当主力电源,但如果氢来自电解制氢且全链条效率只有 40%,那么燃料电池“满发”从系统角度反而不经济。优化器会综合原料成本和效率自己判断,如果结果偏了,检查氢气热值、电解效率、燃料电池效率三者的乘积是否合理。

如果结果出现“购电量为零但负荷还没满足”,查电平衡约束里的变量是否写全。最常见的情况是光伏和风电的变量在目标函数里出现,但在电平衡约束里漏掉,导致优化器使用这些“免费”出力来满足负荷但不计入平衡,结果变成无源之水。

6. 一些实操体会与扩展方向

6.1 参数敏感性分析怎么做才有说服力

我特别建议在完成基础调度后,补做一组参数敏感性分析。这个部分有时候比调度结果本身更能体现你的工作深度。

氢储能在模型中最关键的经济参数是“电解槽单位投资成本”和“储氢罐单位容量成本”。我的做法是,把电解槽投资成本从 3000 元/kW 逐步增加到 10000 元/kW,看最优调度方案中电解槽的利用率变化。你会发现存在一个临界点:低于这个成本,系统一定会在谷电时段全力制氢;高于这个成本,电解槽可能只在某些特殊时段开启。这个临界点的数值对实际项目投资决策非常有用。

同时可以做“碳价”的敏感性分析。碳价为零时系统考虑的是纯经济目标,碳价升高到一定程度时,氢储能的利用率会显著上升,因为这个系统用氢能替代了燃煤购电,减少了间接碳排放。某次计算中,碳价从 0 提升到 300 元/吨时,储氢罐容量利用率从 48% 提升到 83%,这个拐点数据说服力很强。

6.2 从确定性调度扩展到滚动优化

固定的日前调度有一个天然缺陷:它假设全天的新能源出力和负荷数据是已知的。真实系统里,预测误差随时在累积,日前方案执行到下午往往已经偏离最优很远。

一个性价比很高的扩展方向是“模型预测控制的滚动优化”,思路是:在每个滚动窗口(比如每 4 小时一次)重新求解未来 24 小时的调度问题,但只执行下一个时段的结果,然后滚动推进。Matlab 实现时,核心在于把实时数据读取、模型重建、求解三步封装成一个循环函数。

我实践下来的体会是:滚动优化比日前固定调度在总成本上能降低 5% 到 8%,但求解时间限制比较紧,因为要在 15 分钟内完成一次求解。如果求解耗时超过窗口长度,就需要牺牲模型精度,比如把时间分辨率从 15 分钟降到 30 分钟,或者采用多阶段简化策略。

6.3 扩展方向:考虑需求响应与多微电网协同

这个模型还可以往两个方向扩展。一是加入需求响应机制,让部分电负荷和热负荷变成可平移、可削减的柔性负荷,目标函数里加入用户舒适度损失成本。这种情况下,调度系统不再是被动匹配负荷曲线,而是主动引导负荷曲线跟随新能源出力。二是做多微电网之间的功率交互,把问题从单微电网优化扩展为多主体博弈,涉及到纳什均衡和分布式优化算法,生成的研究点就更多了。

不过基础没打牢之前,不建议直接跳到这些高级方向。先把确定性调度模型的物理正确性、代码实现稳定性、算例对比的说服力做好,后续的扩展都是水到渠成的事情。

我个人在实际操作中最大的体会是:这个课题的技术栈并不复杂,核心难点在于把“物理设备行为”翻译成“数学表达式”时必须足够精确,任何偷懒的简化后期都会在结果分析中反咬一口。建议初入门的朋友动手跑通一个完整算例,再逐步把氢储能、电储能、热平衡、分时电价这些模块加进去,你会看到系统行为的变化,这个过程对理解综合能源系统运作逻辑的帮助,比看十篇论文都大。

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

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

立即咨询