资讯动态

多时间尺度优化调度:新能源制氢系统协同控制与建模

发布时间:2026/10/14 8:54:26 来源:尧图企业网站定制
简介面向新能源制氢系统优化调度方向的研究人员、工程师与相关学者这份PDF文档以可运行代码配合详细解释完整复现多时间尺度优化调度策略。内容覆盖孤岛与并网两种典型场景日前阶段分别采用改进雷达图模型和价格型、替代型需求响应日内阶段则通过模型预测控制MPC与激励型需求响应实现功率跟踪与源荷平抑。文档从风/光发电模型、储能设备、电解槽集群等系统建模入手逐步讲解优化算法、电-氢综合需求响应机制及MPC参数整定并给出多场景对比结果与实际应用建议。资源为单个PDF文件大小约792KB重点在于代码逐段解读与工程实现细节适合需要掌握新能源消纳、制氢调度策略或需求响应建模的读者。目前已有127人浏览学习可直接用于论文复现、课题设计或工程方案参考。1. 多时间尺度调度为什么是新能源制氢系统的刚需风电和光伏出力天生波动制氢负荷却又讲究稳定——电解槽有最小运行功率、爬坡速率甚至启停次数限制电网侧的峰谷电价又摆在那里。如果像传统工控那样只写一个固定控制策略风光大发的时段弃电、电价低谷时段又不敢多买电制氢整体经济性会差一大截。这个标题给出的解法是把调度问题拆到日前、日内、实时三个时间尺度上分层求解同时让制氢、储能电池、储氢罐和电网购售电坐在一起做联合优化再通过需求响应机制把电解槽变成电网眼里「可调度的柔性负荷」。这套策略适合正在做新能源制氢系统方案设计的工程师、搞微电网能量管理的研究生以及想从「单机控制」升级到「园区级优化调度」的从业者。2. 先搭框架日前-日内-实时三层调度各层到底管什么2.1 日前调度以 24 小时为窗口把「明天怎么跑」先定下来多时间尺度优化调度策略的第一层是日前调度Day-Ahead Scheduling时间颗粒度通常取 1 小时优化窗口为 24 小时。输入是风光出力预测曲线、次日分时电价、气象预报和固定的用氢交付计划输出是未来 24 小时每个时段的设备运行计划——电解槽功率、储能电池充放电、购电与售电功率、储氢罐的充放节奏。这一层的核心价值不是精确跟踪而是「排兵布阵」在电价低谷时段多安排电解槽出力在高峰时段少用电甚至反向售电风电光伏充足时优先消纳不足时再考虑购电。因为预测误差随提前时间放大日前调度的结果不需要执行到每一分钟但它决定了设备的启停安排和大致的运行区间是后续日内、实时调度必须遵守的「契约」。顺便说一句日前调度也是最容易用数学规划建模的一层一般的混合整数线性规划MILP就能覆盖大部分场景。2.2 日内滚动调度每 15 分钟重算一次修正预测偏差风光预测在 4 到 6 小时内的误差最容易翻车——明明预报有风实际却静风了。日内滚动调度把窗口压缩到 4 到 8 小时步长缩短到 15 分钟每隔一个周期比如每 4 小时用最新的超短期预测数据重新求解一次。这一层的目标是在不推翻日前计划大框架的前提下修正风光波动带来的偏差。有效做法是采用滚动时域控制Receding Horizon ControlRHC思路每次只执行第一个时段的指令执行完再滚动到下一个优化窗口。这类似于自动控制里的模型预测控制MPC区别在于它同时优化经济目标和功率平衡而不仅仅是跟踪一个设定值。在实现时日前层的启停状态变量会作为固定参数传给日内层日内层只调整功率连续变量这样既能降低求解规模又保留了调整空间。2.3 实时反馈层承接 AGC 信号与需求响应指令把短期偏差拉回来实时调度的颗粒度是分钟级甚至秒级负责处理两件事一是风光出力的瞬时抖动二是电网侧发来的需求响应指令。需求响应落到制氢系统里通常是调度机构或售电公司在高峰时段发出削峰指令要求电解槽在一定时间窗口内降低用电功率同时给予电费折扣或容量补偿。实时层不需要再跑大优化模型常见做法是查表或线性分配——根据日前/日内层给出的运行基点按照电解槽爬坡能力、电池 SOC 和储氢罐余量按比例分摊功率偏差。这一层的动作要快所以模型必须轻、约束必须简单否则算完指令窗口已经过了。有一点要提醒实时层不是越大越好它是给前面两层「兜底」的设计原则是能处理 5 分钟以内的短期偏差就够了。2.4 三层之间的时间颗粒度与信息传递层级优化窗口时间步长刷新频率主要输入输出用途日前调度24 小时1 小时每天 1 次日前预测、分时电价、氢交付计划设备启停、运行区间、购售电计划日内滚动4~8 小时15 分钟每 4 小时 1 次超短期预测、日前计划修正功率指令、需求响应预留实时反馈5~15 分钟1 分钟每 1~5 分钟 1 次实测出力、AGC 指令设备执行级指令、负荷调节三层之间信息是单向传递的日前给日内定边界日内给实时定基点实时只做偏差修正。反方向只反馈执行偏差和执行约束的越限情况不回改上层的开机决策。这样设计的工程原因是开停机决策涉及电解槽寿命和设备启停成本不适合在秒级频繁改动而功率连续量则可以在日内和实时层灵活调整。3. 把风光氢储协同调度写成约束目标函数与各环节建模要点3.1 目标函数购电成本、售电收益、需求响应补偿与弃电惩罚的取舍风光氢储协同调度模型的优化目标一般取系统日运行总成本最小也可以等价地写成收益最大。以成本最小为例目标函数包含以下几项向电网购电的费用、向电网售电的收益负成本、参与需求响应获得的调节补偿负成本、弃风弃光的惩罚成本以及储能电池循环损耗成本。数学形式大致是min Σ [ price_buy[t] × P_buy[t] − price_sell[t] × P_sell[t] − dr_price[t] × (dr_add[t] dr_cut[t]) curtail_penalty × P_curtail[t] battery_cost × P_dis[t] ]其中price_buy[t]是 t 时段的购电价price_sell[t]是售电价一般取购电价的 70%90%dr_add和dr_cut分别表示需求响应中主动增加和削减的负荷dr_price是电网给出的调节补偿单价P_curtail[t]是弃风弃光功率给它一个高于峰电价的惩罚系数才能让求解器「愿意」优先消纳风光。电池损耗battery_cost要设成一个小正数否则模型会为了省电费让电池频繁充放算出来的曲线现场根本执行不了。3.2 电解槽与储氢罐建模最小运行负荷、爬坡约束与储氢 SOC电解槽是最关键也最容易建模出错的环节。碱性电解槽ALK常见的最小运行负荷是额定功率的 20%40%低于这个值无法稳定运行可能造成气体纯度下降甚至安全联锁停机PEM 电解槽调节范围宽一些但也有爬坡速率限制。因此至少需要三类约束功率上、下限P_el_min ≤ P_el[t] ≤ P_el_max爬坡约束|P_el[t] − P_el[t−1]| ≤ R_el启停逻辑可选启动次数和最小运行时长约束储氢罐建模采用 SOCState of Charge方式储氢量按质量计算。产氢速率与电解槽功率之间近似线性关系H_prod[t] P_el[t] / η_el其中η_el的单位是 kWh/kg。储氢 SOC 递推关系为SOC_h2[t] SOC_h2[t−1] H_prod[t] − H_delivery[t]H_delivery[t]是每个时段对外交付的氢气量由合同或下游用氢需求决定通常设为恒定值。SOC 还需满足上下限约束比如常见设计取 20%90%避免储氢罐过充或放空。3.3 储能电池与需求响应负荷的耦合方式储能电池建模比储氢罐复杂一些因为要考虑充放电效率不对称和 SOC 边界。充电时SOC_bat[t] SOC_bat[t−1] η_ch × P_ch[t]放电时SOC_bat[t] SOC_bat[t−1] − P_dis[t] / η_dis。充放电功率需要分别设上限并加同一时段充放电互斥约束或让总功率约束P_ch[t] P_dis[t] ≤ P_bat_rate来兜底避免模型同时充放做无用功。需求响应在制氢场景里的自然载体是电解槽的功率平移。模型里引入可转移负荷量dr_add和dr_cut分别表示相对于基准计划的电负荷增加量和削减量并满足总量守恒约束Σ(dr_add[t]) Σ(dr_cut[t])——就是说把高峰时段的用电转移到低谷时段总用电量不变但电网高峰压力降下来了。每条时段上的转移量受合同约束比如不得超过电解槽额定功率的 15%20%。3.4 功率平衡风光、购售电、电池与制氢负荷的等式约束把所有环节串起来的是全时段的功率平衡等式这也是风光氢储协同调度的「宪法」P_re_used[t] P_buy[t] P_dis[t] P_load[t] P_el[t] P_ch[t] P_sell[t] dr_shift[t]左侧是电源侧右侧是负荷侧。P_re_used[t]表示实际消纳的风光功率需要满足0 ≤ P_re_used[t] ≤ P_re_forecast[t]没有被消纳的部分就是弃风弃光量。dr_shift[t] dr_add[t] − dr_cut[t]正值表示负荷增加负值表示负荷削减。这条等式每一时段都必须严格成立求解器才能给出物理上可行的结果。4. 用 Python 实现日前调度模型MILP 代码与逐段参数说明4.1 数据准备风光预测、分时电价与设备参数下面的代码用一个简化的中试规模系统演示完整建模过程。系统参数设置为电解槽额定功率 600 kW储能电池容量 300 kWh储氢罐容量 400 kg日制氢交付量 200 kg。先构造 24 小时的风光预测、分时电价等输入数据。import numpy as np import pandas as pd import pulp as lp # 时间参数 T 24 # 日前调度窗口单位小时 # 设备参数 P_el_max 600.0 # 电解槽额定功率kW P_el_min 200.0 # 电解槽最小运行功率kW约 33% R_el 120.0 # 电解槽爬坡速率上限kW/h eta_el 52.0 # 制氢电耗kWh/kg H2_delivery 200.0 / T # 每时段的固定交付量kg/h # 储能电池参数 E_bat_max 300.0 # 电池容量kWh P_bat_rate 100.0 # 电池最大充放电功率kW eta_ch 0.95 # 充电效率 eta_dis 0.92 # 放电效率 soc_min, soc_max 0.2, 0.9 # 电池 SOC 上下限 # 储氢罐参数 H2_tank_max 400.0 # 储氢罐容量kg h2_lo, h2_hi 0.2, 0.9 # 储氢 SOC 上下限 h2_init 0.4 # 储氢罐初始 SOC h2_end_min 0.5 # 日末储氢 SOC 下限保证次日可交付 # 电网与需求响应参数 P_grid_max 500.0 # 与电网交互功率上限kW price_sell_ratio 0.8 # 售电价 0.8 × 购电价 DR_cap 100.0 # 需求响应单时段最大调节量kW dr_price 0.3 # 需求响应补偿单价元/kWh curtail_penalty 2.0 # 弃风弃光惩罚系数元/kWh battery_cost 0.05 # 电池放电损耗成本系数元/kWh # 风光预测与分时电价示例数据实际工程中来自预测系统 np.random.seed(42) wind_fc 350 * (0.5 0.5 * np.sin(np.linspace(0, 2*np.pi, T)) 0.2 * np.random.randn(T)) wind_fc np.clip(wind_fc, 0, 450) pv_fc 300 * np.clip(np.sin(np.linspace(0, np.pi, T)), 0, 1) ** 2 P_re_forecast wind_fc pv_fc # 风光总可用功率 price_buy np.array([0.4]*6 [0.7]*6 [1.1]*6 [0.7]*6) # 谷-平-峰-平 P_load 50.0 # 站内固定负荷kWP_re_forecast是每个时段风光预测的可用总功率后面通过P_re_used变量决定实际消纳多少差值即为弃电。price_buy按「谷 6 小时、平 6 小时、峰 6 小时、平 6 小时」构造符合国内一般工商业的分时电价形状。所有设备参数都放在头部方便后面做敏感性分析。4.2 模型定义与核心约束实现这里用 PuLP 建立 MILP 模型。决策变量包括电解槽功率、电池充放电、购售电、储氢 SOC、需求响应调节量等。为了避免绝对值运算把模型变成非线性dr_add和dr_cut作为两个独立非负变量使用。# 创建模型 prob lp.LpProblem(Wind_Solar_Hydrogen_DayAhead, lp.LpMinimize) # 决策变量 P_el {t: lp.LpVariable(fP_el_{t}, lowBound0) for t in range(T)} P_buy {t: lp.LpVariable(fP_buy_{t}, lowBound0) for t in range(T)} P_sell {t: lp.LpVariable(fP_sell_{t}, lowBound0) for t in range(T)} P_ch {t: lp.LpVariable(fP_ch_{t}, lowBound0) for t in range(T)} P_dis {t: lp.LpVariable(fP_dis_{t}, lowBound0) for t in range(T)} P_re_used {t: lp.LpVariable(fP_re_{t}, lowBound0) for t in range(T)} soc_bat {t: lp.LpVariable(fsoc_bat_{t}, lowBoundsoc_min, upBoundsoc_max) for t in range(T)} soc_h2 {t: lp.LpVariable(fsoc_h2_{t}, lowBoundh2_lo, upBoundh2_hi) for t in range(T)} dr_add {t: lp.LpVariable(fdr_add_{t}, lowBound0, upBoundDR_cap) for t in range(T)} dr_cut {t: lp.LpVariable(fdr_cut_{t}, lowBound0, upBoundDR_cap) for t in range(T)} # 目标函数 prob lp.lpSum(price_buy[t] * P_buy[t] - price_buy[t]*price_sell_ratio * P_sell[t] - dr_price * (dr_add[t] dr_cut[t]) curtail_penalty * (P_re_forecast[t] - P_re_used[t]) battery_cost * P_dis[t] for t in range(T)) # 功率平衡约束风光 购电 放电 负荷 电解槽 充电 售电 需求响应偏移 for t in range(T): prob (P_re_used[t] P_buy[t] P_dis[t] P_load P_el[t] P_ch[t] P_sell[t] dr_add[t] - dr_cut[t]) # 风光消纳上限 for t in range(T): prob P_re_used[t] P_re_forecast[t] # 电解槽运行约束 for t in range(T): prob P_el[t] P_el_min * (P_el[t] 0) # 该式仅示意见下方说明 prob P_el[t] P_el_max for t in range(1, T): prob P_el[t] - P_el[t-1] R_el prob P_el[t-1] - P_el[t] R_el # 储氢罐 SOC 递推与边界 for t in range(T): if t 0: prob soc_h2[t] h2_init * H2_tank_max P_el[t]/eta_el - H2_delivery else: prob soc_h2[t] soc_h2[t-1] P_el[t]/eta_el - H2_delivery prob soc_h2[T-1] h2_end_min * H2_tank_max # 电池 SOC 递推与充放互斥 for t in range(T): if t 0: prob soc_bat[t] 0.5 * E_bat_max eta_ch * P_ch[t] - P_dis[t]/eta_dis else: prob soc_bat[t] soc_bat[t-1] eta_ch * P_ch[t] - P_dis[t]/eta_dis prob P_ch[t] P_dis[t] P_bat_rate # 同时段功率互斥 # 电网交互上限 for t in range(T): prob P_buy[t] P_grid_max prob P_sell[t] P_grid_max # 需求响应总量守恒增加的负荷总量等于削减的负荷总量 prob lp.lpSum(dr_add[t] for t in range(T)) lp.lpSum(dr_cut[t] for t in range(T))目标函数里− dr_price × (dr_add dr_cut)是负成本代表电网给制氢站的调峰补偿所以模型在满足总量守恒的前提下会倾向于把负荷从高电价时段转移到低电价时段从而既拿到补偿又节省电费。curtail_penalty设为 2.0 元/kWh高于峰电价 1.1 元/kWh确保求解器优先消纳风光而不是弃掉再买电。电解槽最小功率约束里写了一句注释提示的表达式实际工程中如果 P_el 可以为零停机最小功率约束需要引入 0/1 开停机变量。简化演示模型里我们把lowBound直接设为 0并约束开启时段不低于P_el_min这样既允许夜间停机又避免低负荷运行但要通过 0/1 变量才能严格表达。初学者容易在这里踩坑只把lowBound200会导致电解槽永远无法停机这在现实中是不合理的。4.3 求解与结果整理模型定义完成后调用 CBC 求解器求解然后把各时段的决策变量整理成 DataFrame 并计算关键经济指标。# 求解 solver lp.PULP_CBC_CMD(msgFalse) prob.solve(solver) print(求解状态:, lp.LpStatus[prob.status]) # 结果整理 df pd.DataFrame({ P_re_used: [P_re_used[t].value() for t in range(T)], P_el: [P_el[t].value() for t in range(T)], P_buy: [P_buy[t].value() for t in range(T)], P_sell: [P_sell[t].value() for t in range(T)], P_ch: [P_ch[t].value() for t in range(T)], P_dis: [P_dis[t].value() for t in range(T)], dr_shift: [dr_add[t].value() - dr_cut[t].value() for t in range(T)], soc_h2: [soc_h2[t].value() / H2_tank_max for t in range(T)], soc_bat: [soc_bat[t].value() / E_bat_max for t in range(T)], }) df[price_buy] price_buy # 关键指标 total_cost prob.objective.value() curtailment sum(P_re_forecast[t] - P_re_used[t].value() for t in range(T)) print(f总运行成本: {total_cost:.1f} 元) print(f弃风弃光总量: {curtailment:.1f} kWh) print(df.round(1))求解状态为 Optimal 表示找到了全局最优解。CBC 是 PuLP 自带的开源求解器对这个规模的 MILP约 200 个变量、300 个约束通常在几秒内收敛。dr_shift为正值代表该时段主动多用电为负值代表削减用电观察它的分布就能看出需求响应行为是否符合预期——正常情况下负值集中在高电价时段正值集中在低电价时段。整个代码演示的是日前调度层的求解过程。实际项目中只需要把输入数据替换成预测系统的输出、把设备参数替换成现场设备的铭牌参数再把电价模型换成当地电网的分时电价文件就可以作为一个最小可用版本跑起来。日内滚动层则把上述求解过程包进一个循环每 15 分钟重新调用一次滚动更新预测数据和初始 SOC。5. 参数整定与避坑指南5 个让调度结果「翻车」的高发点5.1 电解槽最小功率约束写错模型解出来现场执行不了现象调度结果里电解槽在低功率区间运行比如 10% 额定功率现场操作员反馈实际产氢量和模型对不上气体纯度偶尔报警。原因很多初版模型只用P_el_min ≤ P_el[t]作为约束没有引入 0/1 开停机变量。当模型需要停机时P_el 被硬压在 P_el_min 上实际上电解槽在低负荷段已经无法稳定运行或者反过来为了「省钱」模型频繁启停损坏电解槽。解决把开停机二元变量z[t]引入约束写成P_el[t] ≤ P_el_max × z[t]和P_el[t] ≥ P_el_min × z[t]并加最小运行/停机时长约束。如果嫌 MILP 变量太多也可以做近似把启停状态在日前层固定日内层只调功率连续量。5.2 日前和日内的时间颗粒度不一致数据拼接错位现象日内滚动调度的 SOC 递推在每 4 小时的窗口边界突然跳变储氢罐容量曲线出现「台阶」。原因日前层用 1 小时步长日内层用 15 分钟步长但两层之间传递的日前计划序列没有做插值对齐——日内层第 1 个 15 分钟拿到了日前整点计划后面 3 个 15 分钟却用了同样的值边界处产生重复或跳变。解决统一用一个基础时间序列建议 15 分钟存储所有调度结果日前层求解后按 1 小时分段写入日内层按 15 分钟读取再在日前和日内之间做一个线性插值接口。这个接口代码很简单但一定要在数据落地前设计好不然后面改起来全是血泪。5.3 储氢罐 SOC 递推忽略了温度与压力修正现象实际储氢量比模型计算值低 10% 左右日末 SOC 勉强达标但次日一早实测压力已经接近下限。原因储氢罐的储氢质量不是压力的线性函数。氢气在高压下的压缩因子随温度和压力变化如果直接用m PV/(RT)算高压段30 MPa 以上偏差非常明显。解决在模型外做一个修正表用真实气体状态方程如 SRK 方程把压力换算成质量调度模型里直接用「kg」为单位递推关系保持线性。储氢 SOC 上下限也留足安全裕度不要贴着 0% 和 100% 设。5.4 需求响应补偿价格设得太低模型「甩负荷」省钱现象优化结果里 dr_cut 在整个峰电时段都顶到上限电网侧反映你参与需求响应的实质成了「单方面少用电」制氢站的实际产量目标差点没完成。原因需求响应约束里只设了总量守恒和调节上限但补偿单价dr_price若低于峰平电价差模型发现削减高峰用电再在低谷补回来能净省钱就会「主动」把负荷大量转移。看起来是响应了电网实际是在套利偏离了需求响应「双向协商」的本意。解决给需求响应补偿设一个合理基线通常按电价的 20%40% 计同时加一个「与基准计划的偏差上限」约束比如每个时段允许的调节量不超过电解槽额定功率的 15%。更重要的是要在目标函数里把「未完成氢交付」的惩罚系数设得很高比如 10 元/kg迫使模型在响应电网和完成制氢生产之间做真实取舍。5.5 MILP 求解规模爆炸求解时间从秒级变成小时级现象把日内 15 分钟步长引入后变量数变成日前模型的 4 倍再加入 0/1 开停机变量CBC 求解时间从 3 秒涨到 20 分钟实时性完全不能满足。原因多时间尺度模型常常直接把日前、日内、实时三层写成一个超大规模 MILP一次性求解。层与层的目标函数权重混在一起求解器很难收敛。解决把三层拆开求解用「日前求离散、日内求连续、实时查表修正」的层级方案。日前层只保留开停机二进制变量日内层固定这些变量后只解 LP线性规划或 QP二次规划实时层不跑优化用比例分配规则。这是工程上最成熟的做法既保证了全局经济性又让求解时间回到秒级。6. 从开环到闭环滚动更新、反馈校正与效果验证技巧日前调度解出来的是一个开环计划风光预测不可能完全准确所以必须把日内滚动和偏差反馈闭环起来。常见做法是写一个循环每 15 分钟读取一次实测风光出力和储氢罐压力将实测 SOC 作为当前优化窗口的初始状态用未来 4 小时的超短期预测重新求解只执行第一个 15 分钟的指令然后进入下一轮。这个「执行-反馈-重算」的循环就是多时间尺度调度真正落地时的发动机。验证调度策略有没有效果我习惯用三组对照第一组是「只购电不售电、无需求响应」的固定功率基线第二组是只做日前不开日内滚动的开环方案第三组才是完整的多时间尺度协同方案。对比总运行成本、弃风弃光率、储氢罐 SOC 末端值和需求响应收益这四项指标。如果多时间尺度方案比基线的成本降低不到 5%说明约束或电价参数设置有问题需要回头检查是不是把弃电惩罚设低了或者需求响应容量根本没被利用起来。还要做一次蒙特卡洛扰动测试——把风光预测加上 ±20% 的随机误差看日内滚动能不能把末端储氢 SOC 稳定在安全区间这一步能提前暴露 SOC 下限设计不足的问题。我在做这类系统时踩过最大的坑是把储氢罐压力和 SOC 换算表做得太理想化结果现场压力曲线和模型对不上。后来改成用 kg 作为调度模型的统一单位压力和温度修正全部放在数据预处理里模型层面只保留线性递推整个系统才真正稳定下来。如果你刚开始做建议先把第 4 章的示例跑通再逐步加日内滚动和实时反馈每一步都保留一份能对比的基线结果。多时间尺度调度不是越复杂越好而是每一层解决一个明确的问题希望这套方案能帮你少走弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑