含冰蓄冷空调的冷热电联供微网多时间尺度优化调度Matlab实现
2026/9/20 3:45:10 网站建设 项目流程

做综合能源系统优化的人应该都有同感:微网调度这个东西,理论框架看着很清晰——把各设备模型一建、目标函数一写、丢给求解器跑,结果就出来了。可真要把一个含冷热电联供、储能、冰蓄冷空调的微网多时间尺度优化调度在Matlab里完整实现,能落地、能复现、能经受住数据波动和约束冲突的考验,中间要踩的坑比想象中多得多。最近我把这套含冰蓄冷空调的冷热电联供型微网多时间尺度优化调度项目完整跑通了一遍,从模型搭建、Yalmip求解到结果分析做了个闭环,这里把整个思路和Matlab实现细节整理出来。

这套东西的价值,简单说就是:微网里面有电、热、冷三种负荷,有燃气轮机、燃气锅炉、光伏、风电、蓄电池,还有吸收式制冷机和电制冷机,再加上冰蓄冷空调这个“冷量仓库”,如何在日前、日内、实时三个时间尺度上协调它们各自出力,让系统在最省钱的前提下不越约束、不丢负荷。不管你是正在做CCHP微网优化调度方向的研究生,还是做综合能源系统控制落地的工程师,甚至只是想抄一套能跑的Matlab代码改改参数,这篇文章都值得读下去。

1. 这个项目到底在解决什么问题

1.1 冷热电联供微网的构成与能量流

冷热电联供(CCHP)微网的物理框架其实不复杂。气体燃料进入燃气轮机发电,发电后的高温烟气不直接排掉,而是经过余热回收装置变成热源,一部分供给热负荷,一部分驱动吸收式制冷机制冷。电负荷由燃气轮机、光伏、风电、电网和蓄电池共同承担,冷负荷则由吸收式制冷机、电制冷机和冰蓄冷系统联合满足。这个结构让能量得到梯级利用,一次能源利用率比传统分供系统高出一截。

但这个系统复杂就复杂在能量流是强耦合的。燃气轮机的发电量和余热量强相关,发电多,余热就多,供热供冷也跟着多;锅炉是补充热源的;吸收式制冷机消耗热来产冷,所以热系统和冷系统根本分不开;蓄电池只管电,冰蓄冷只管冷,两个储能装置时间尺度还不一样,建模各有各的难处。这种多能互补的耦合关系,决定了调度模型必须同时建电、热、冷三条平衡方程,并且把设备之间的耦合关系明确写进约束里。

1.2 冰蓄冷空调为什么值得加进来

很多做微网调度的人一上来只考虑蓄电池,把冷负荷当作刚性需求直接用制冷机满足。实际上,冰蓄冷空调加入后,整个系统的调节灵活性会上一个台阶。它的原理和抽水蓄能很像,只是把能量载体从水换成了冰:夜间电价低谷时,电制冷机不直接供冷,而是把冷量以冰的形式存起来;白天电价高峰或者冷负荷峰值时段,融冰放冷,减少高峰时段的电力消耗和制冷设备出力。

这里面最关键的经济逻辑是峰谷电价差。如果谷时电价0.35元/千瓦时,峰时电价1.2元/千瓦时,夜间用一度电制的冰,白天能替代掉将近4度电的直接制冷电耗(当然要考虑制冰效率和蓄冷损耗),这个账怎么算都划算。更重要的是,冰蓄冷相当于给冷负荷装了一个“充电宝”,让冷负荷不再必须实时由电负荷驱动,削峰填谷的作用非常明显。

1.3 多时间尺度调度要解决的痛点

为什么一定要搞多时间尺度,简单一个日前优化不行吗?不行。因为光伏和风电的预测误差太大,冷负荷又受气温和人员活动影响,一天前做的计划到实际运行时早就偏了。如果你只用一个日前调度模型,开机计划和实际出力对不上,要么浪费燃料,要么从电网补电补到心疼,严重时甚至违反功率平衡约束。

多时间尺度调度的核心思想是“先粗后细、滚动修正”。日前阶段确定机组启停和大致出力计划;日内阶段随着最新预测数据滚动更新,修正偏差;实时阶段处理最后的高频波动。这样既不牺牲日前优化的全局性,又能保持实际运行的灵活性和可靠性,所以成为目前工程上最主流的调度架构。

2. 多时间尺度调度框架与核心逻辑

2.1 日前调度:确定基础运行计划

日前调度的时间尺度是24小时,分辨率一般取1小时,在每天零点前根据第二天的预测数据做一次全局优化。它的决策变量最全面:燃气轮机的启停和出力、锅炉出力、吸收式制冷机出力、电制冷机两种工况的分配、蓄电池充放电计划、蓄冷槽蓄放冷计划、联络线购售电功率,所有二进制变量都在这个阶段确定。

日前阶段的优化目标是总运行成本最小,这个阶段最大的优势是从全局角度看问题。比如它能看到夜间有6个小时谷电,于是让电制冷机在谷电时段全力制冰;它能根据第二天早晚高峰的冷负荷预判,决定蓄冷槽到底要蓄多少冷。如果换成日内滚动去决策,因为预测时域短,系统看不到那么远的“机会窗口”,冰蓄冷的作用会被明显低估。所以日前调度解决的是“基本盘”,后面的时间尺度更像是沿着这个基本盘做局部修正。

2.2 日内滚动优化:对抗预测误差的第一道防线

日内滚动优化是这套系统的核心,工程上一般以15分钟为分辨率,滚动周期取4小时。每到一个新的触发时刻,系统读取最新的光伏出力、风电出力和负荷预测数据,以前日计划为参考基准,重新求解未来4小时的优化问题,但只执行第一个时段的控制指令,等下一个周期重复这个过程。

日内阶段和日前阶段最大的区别在于,机组启停状态通常固定来自日前计划,不再作为优化变量。这么做的原因有两个:一是燃气轮机频繁启停会带来额外的燃料消耗和寿命折损,日前已经考虑了启停的经济性,日内频繁改变启停状态得不偿失;二是固定二进制变量后,日内问题变成一个纯线性规划或者只有少量整数变量的优化问题,求解速度快很多,能跟上滚动周期。日内阶段的优化目标除了运行成本,通常还要加一个“与日前计划偏差尽量小”的惩罚项,防止调度指令跳变太猛,给实时跟踪造成负担。

2.3 实时调整:最后的兜底修正

实时阶段的时间尺度更短,通常是5分钟甚至分钟级,主要针对超短期波动做修正。光伏云层遮挡、风力突然变化、某栋楼空调集中启动,这些高频扰动在日内滚动优化看来还没形成趋势,但已经在实际功率上体现出来了。

实时调整层的建模和日前日内都不太一样。工程落地方案里,实时层很少继续跑大型MILP,更多是采用短时域模型预测控制或者比例积分调节。我在这套Matlab实现里,实时层用的是短时域MPC,固定燃气轮机和蓄冷槽的状态,以“快速消除功率偏差”为目标,由蓄电池和联络线做主要调节手段。蓄电池响应速度快,适合吸收高频功率波动;联络线功率作为备用调节手段,应对蓄电池容量不足的情况。需要注意的是,实时层的目标函数权重要手动调几轮,权重系数太小则偏差消除太慢,太大会导致蓄电池频繁反向充放,影响寿命。

2.4 三个尺度之间的衔接关系

三个时间尺度的衔接,是整个调度系统能否稳定运行的关键。我调试过程中最深的一个体会是:前一层输出的结果,必须变成后一层的“参考轨道”而不是“硬约束”。如果把日前计划的出力值设成日内阶段的硬约束,那滚动优化就失去了修正预测误差的意义;如果完全不管日前计划,日内阶段会变得过于短视,出现某些时段出力曲线剧烈抖动的情况。

我的做法是逐级锁定关键变量。日前阶段输出的机组启停状态,日内阶段直接固定;日内阶段输出的蓄电池和联络线计划,实时阶段作为目标值参考,允许在小范围内偏移。这样一层锁一层,既保留了后级调度的灵活性,又不会让问题因为太多二进制变量而求解缓慢。

3. 核心数学模型搭建

3.1 目标函数:运行成本怎么算

整个优化问题的目标函数是调度周期内的总运行成本最小,主要包括四个部分:燃料成本、购电费用(减去售电收入)、设备运行维护成本,以及可选的启停惩罚成本。启停惩罚项在日前阶段建议加上,能有效防止优化器把燃气轮机启停当成“免费工具”频繁切换;日内和实时阶段因为固定了启停状态,这项可以去掉。

燃料成本的计算要注意天然气计量单位。天然气价格如果给的是元/立方米,要先根据热值换算成元/千瓦时。比如天然气价2.5元/立方米,热值9.7千瓦时/立方米,那么每千瓦时化学能成本就是0.2577元。燃气轮机的燃料消耗按发电功率除以发电效率折算,锅炉按供热功率除以热效率折算,这样才能统一到同一个能量单位下做平衡。

购电费用项里,售电收入要让购电电价和售电电价有足够差价。只要卖电价低于买电价,优化器自然会避免同时从电网购电和向电网售电,不需要额外加二进制约束限制,能省一批整数变量。这个细节很多初学者不注意,白白增加求解时间。

3.2 功率平衡与设备运行约束

电功率平衡约束是硬约束,表达式为:

P_GT(t) + P_PV(t) + P_WT(t) + P_buy(t) + P_bd(t) = P_load(t) + P_EC_cool(t) + P_EC_ice(t) + P_bc(t) + P_sell(t)

其中P_bd是蓄电池放电功率,P_bc是充电功率,P_EC_ice是制冰压缩机消耗的电功率。热平衡约束要特别注意吸收式制冷机这部分,燃气轮机的余热回收功率加上锅炉供热功率,必须等于热负荷加上吸收式制冷机的驱动热量:

(η_hrs / η_GT) * P_GT(t) + P_GB(t) = H_load(t) + H_AC_in(t)

这里η_hrs是余热回收效率占燃气热值的比例,η_GT是发电效率,两者比值乘以发电功率,就是把燃气轮机当前发电工况对应的余热量折算出来。

冷功率平衡和蓄冷槽动态是冰蓄冷系统建模的关键。电制冷机有两部分产冷:一部分直接供冷,一部分制冰存入蓄冷槽。冷平衡方程写成:

Q_AC(t) + COP_cool * P_EC_cool(t) + P_ice_dis(t) = Q_load(t)

其中P_ice_dis是融冰供冷功率。蓄冷槽的动态方程则描述存储的冷量变化:

S_ice(t+1) = S_ice(t) + η_ice_ch * COP_ice * P_EC_ice(t) - P_ice_dis(t) / η_ice_dis

蓄电池的SOC动态类似,只是方向是电能:

S_bat(t+1) = S_bat(t) + η_bat_c * P_bc(t) - P_bd(t) / η_bat_d

每台设备还有出力上下限,比如燃气轮机用二进制变量约束启停状态,出力必须落在P_GT_min到P_GT_max之间;蓄电池充放电用两个二进制变量确保不会同时充放电;蓄冷槽和蓄电池的初始SOC和日末SOC通常要设置成一致,保证调度方案的日循环可行性。

3.3 冰蓄冷空调建模的几个细节

冰蓄冷系统的建模细节直接决定结果是否可信,这里有几个很关键的点。

第一,电制冷机的双工况不能用一个效率一刀切。直接供冷工况的COP通常在3.8到4.5之间,而制冰工况因为蒸发温度更低,效率会明显下降,COP一般只有2.8到3.2。如果把两个工况混在一个效率里,优化器会算出一个“用一度电制出更多冷”的假象,导致调度方案失真。

第二,蓄冷槽的充冷和融冰不能同时发生。现实中一个蓄冷槽没有一边通知制冷机往里灌冰、一边往外融冰的道理,所以在模型里必须加互斥约束:充冷二进制变量和释冷二进制变量之和小于等于1。如果不加这个约束,优化器可能利用效率损耗做“套利”,充放同时进行,结果看着漂亮但实际无法执行。

第三,蓄冷槽的冷量状态变量是kWh,而功率变量是kW,时间尺度的换算很容易出错。如果分辨率是1小时,功率数值乘1就是能量;如果换成15分钟,必须乘0.25。我在调试时遇到过不少“能量不守恒”的错误,最后发现都是时间单位没统一造成的。

4. Matlab代码实现与关键代码解析

4.1 求解工具选择和代码整体结构

这套代码我用的建模工具是Yalmip,求解器用Cplex或者Gurobi都可以。Yalmip的语法非常贴合数学模型的思维方式,把目标函数、约束条件直接写出来,剩下的交给求解器。Cplex对MILP的求解能力在同类问题中相当扎实,许可证一般学校都有。

整个Matlab工程的结构分成四块:参数设置、数据生成、优化建模、结果输出。参数设置放在最前面,方便后面做敏感性分析;数据生成模拟光伏、风电、冷热电负荷的预测曲线;优化建模是核心;结果输出把调度结果画成曲线,方便肉眼检查有没有违反直觉的地方。模块之间用注释分隔,一个人维护这个代码完全够用。

4.2 参数设置与基础数据生成

设备参数先定下来,这套模型里燃气轮机容量600kW,发电效率0.35,余热回收效率0.45;燃气锅炉容量400kW,热效率0.85;吸收式制冷机最大制冷量500kW,热力系数0.8;电制冷机直接供冷最大功率600kW,COP取4.0,制冰最大功率400kW,COP取3.0;蓄冷槽容量1000kWh,充冷效率0.95,融冰效率0.9;蓄电池容量400kWh,最大充放功率100kW。

分时电价是冰蓄冷经济效益的来源,我设成谷段0.35元、峰段1.2元、平段0.7元,卖电价格按买电价格的80%计算。预测数据可以用典型曲线加随机噪声生成,实际工程里这里接的是预测算法或者气象系统的输出。

4.3 日前调度核心建模代码

日前调度的核心代码如下,我加了详细注释:

%% 日前调度核心代码片段 % 决策变量定义 P_GT = sdpvar(1, T, 'full'); % 燃气轮机发电功率 on_GT = binvar(1, T); % 燃气轮机启停状态 P_GB = sdpvar(1, T, 'full'); % 锅炉供热功率 P_EC_cool = sdpvar(1, T, 'full'); % 电制冷机直接供冷耗电 P_EC_ice = sdpvar(1, T, 'full'); % 电制冷机制冰耗电 P_ice_dis = sdpvar(1, T, 'full'); % 融冰供冷功率 S_ice = sdpvar(1, T+1, 'full'); % 蓄冷槽冷量状态 on_ice_ch = binvar(1, T); % 蓄冷状态标志 on_ice_dis = binvar(1, T); % 释冷状态标志 P_bc = sdpvar(1, T, 'full'); % 蓄电池充电功率 P_bd = sdpvar(1, T, 'full'); % 蓄电池放电功率 S_bat = sdpvar(1, T+1, 'full'); % 蓄电池SOC P_buy = sdpvar(1, T, 'full'); % 电网购电功率 P_sell = sdpvar(1, T, 'full'); % 电网售电功率 cons = []; % 初始状态与日循环约束 cons = [cons, S_ice(1) == 0, S_bat(1) == 200]; cons = [cons, S_ice(T+1) == 0, S_bat(T+1) == 200]; for t = 1:T % 电功率平衡 cons = [cons, P_GT(t) + P_PV(t) + P_WT(t) + P_buy(t) + P_bd(t) == ... P_load(t) + P_EC_cool(t) + P_EC_ice(t) + P_bc(t) + P_sell(t)]; % 热平衡:燃机余热 + 锅炉热 = 热负荷 + 吸收式机组驱动热 H_GT_rec = (eta_hrs / eta_GT) * P_GT(t); cons = [cons, H_GT_rec + P_GB(t) == H_load(t) + H_AC_in(t)]; % 吸收式制冷机产冷量,COP_AC = 0.8 cons = [cons, Q_AC(t) == COP_AC * H_AC_in(t)]; % 冷功率平衡:吸收式 + 电制直接供冷 + 融冰供冷 = 冷负荷 cons = [cons, Q_AC(t) + COP_cool * P_EC_cool(t) + P_ice_dis(t) == Q_load(t)]; % 蓄冷槽动态 cons = [cons, S_ice(t+1) == S_ice(t) + eta_ice_ch * COP_ice * P_EC_ice(t) ... - P_ice_dis(t) / eta_ice_dis]; % 蓄电池动态 cons = [cons, S_bat(t+1) == S_bat(t) + eta_bat_c * P_bc(t) - P_bd(t) / eta_bat_d]; % 蓄冷槽容量与互斥约束 cons = [cons, 0 <= S_ice(t) <= S_ice_max]; cons = [cons, P_EC_ice(t) <= 400 * on_ice_ch(t)]; cons = [cons, P_ice_dis(t) <= 300 * on_ice_dis(t)]; cons = [cons, on_ice_ch(t) + on_ice_dis(t) <= 1]; % 蓄电池容量与互斥约束 cons = [cons, 0 <= S_bat(t) <= S_bat_max]; cons = [cons, P_bc(t) <= P_bat_max * on_bc(t)]; cons = [cons, P_bd(t) <= P_bat_max * on_bd(t)]; cons = [cons, on_bc(t) + on_bd(t) <= 1]; % 燃机与锅炉出力约束 cons = [cons, P_GT_min * on_GT(t) <= P_GT(t) <= P_GT_max * on_GT(t)]; cons = [cons, 0 <= P_GB(t) <= P_GB_max]; % 电制冷机功率约束 cons = [cons, 0 <= P_EC_cool(t) <= 600]; cons = [cons, 0 <= P_EC_ice(t) <= 400]; % 电网交互功率约束 cons = [cons, 0 <= P_buy(t) <= 800]; cons = [cons, 0 <= P_sell(t) <= 800]; end % 燃气轮机爬坡约束 for t = 1:T-1 cons = [cons, -100 <= P_GT(t+1) - P_GT(t) <= 100]; end % 目标函数:燃料费 + 购电费 - 售电收入 + 运维费 gas_cost = gas_price_per_kwh * sum(P_GT / eta_GT + P_GB / eta_GB); elec_cost = sum(price_buy .* P_buy - price_sell .* P_sell); om_cost = sum(0.025 * P_GT + 0.01 * P_GB + 0.01 * (P_EC_cool + P_EC_ice) ... + 0.008 * (P_bc + P_bd)); objective = gas_cost + elec_cost + om_cost; ops = sdpsettings('solver', 'cplex', 'verbose', 1); sol = optimize(cons, objective, ops); if sol.problem == 0 P_GT_opt = value(P_GT); S_ice_opt = value(S_ice); % 其他结果同理 else disp('求解失败,检查约束和求解器配置'); end

这段代码基本能直接跑通。需要提醒的是,代码里的Q_AC、H_AC_in、on_bc、on_bd等变量要先在决策变量部分定义完整,我这里为了篇幅只展示了核心逻辑。实际工程中数据要换成真实预测曲线,并添加边界检查,防止预测数据异常导致求解不可行。

4.4 日内滚动优化代码结构

日内滚动优化的核心是要有一个滚动循环,控制触发时刻、预测数据的更新、优化模型的建立以及指令执行。以下是简化版框架:

%% 日内滚动优化框架(15min分辨率,滚动周期4h) M = 96; % 一天96个15分钟时段 N = 16; % 预测时域4小时 = 16个15分钟时段 for k = 1:16:M % 读取最新预测数据,从当前时刻k开始对未来N个时段做预测 P_PV_fc = get_latest_pv_forecast(k:k+N-1); P_load_fc = get_latest_load_forecast(k:k+N-1); Q_load_fc = get_latest_cold_forecast(k:k+N-1); H_load_fc = get_latest_heat_forecast(k:k+N-1); % 固定机组启停状态,来自日前调度 on_GT_roll = on_GT_day(k:k+N-1); % 建立与日前类似的优化模型,但考虑到时间尺度的能量换算 % 目标是运行成本 + 与日前计划的偏差惩罚 % 求解后只执行第一个时段的指令 u_k = value(P_GT_roll(1)); % 执行到k+1时刻,循环继续 end

这里固定启停状态这个操作很关键。如果不固定,每个滚动周期都要重新决策机组开机,会导致相邻周期之间的启停状态互相矛盾,整体运行成本反而升高。另外,15分钟分辨率的预测数据和日前小时级数据在目标函数里做偏差惩罚时,要先统一到同样的能量维度,否则惩罚项的量纲不对,结果会失真。

5. 仿真结果分析与调度效果评估

5.1 各设备出力曲线特征

用夏季典型日的数据跑完优化后,把结果画出来看,几条曲线非常有规律。燃气轮机全天基本维持较高出力,尤其在电价高峰时段,因为天然气发电的综合成本仍然低于高峰电价,多用燃气轮机自发电是划算的。光伏出力集中在中午,与冷负荷高峰有一定的重叠,所以中午时段的购电压力相对小。蓄电池表现为“谷充峰放”模式,凌晨低价充电,上午和傍晚放电。

蓄冷槽的曲线最能体现冰蓄冷的价值。凌晨1点到5点,电制冷机开足马力制冰,蓄冷量从0快速上升到接近900kWh;白天10点到17点,冷负荷上升,融冰供冷功率逐步释放,蓄冷量持续下降;傍晚又出现一个小幅蓄冷的波谷,配合后半夜再次蓄冰。整个过程非常符合预期,说明优化器确实吃透了分时电价和冷负荷变化的规律。

5.2 冰蓄冷在削峰填谷中的具体作用

从联络线功率曲线上能明显看到冰蓄冷的削峰效果。无冰蓄冷方案里,下午2点到5点的冷负荷峰值直接折算成电负荷,购电功率冲到接近700kW。加上冰蓄冷后,电制冷机在白天的电耗大幅下降,融冰供冷承担了大部分峰值冷负荷,联络线购电功率被削到500kW以下,峰时购电功率下降了约三成。

蓄冷槽的能量效率也要单独看。制冰工况COP从4.0降到3.0,折算成蓄放冷效率约0.9,一个循环下来的综合能效大概在2.6左右,虽然低于直接供冷,但考虑到峰谷电价差超过3倍,经济上依然非常划算。这也说明冰蓄冷的本质不是节能,而是“用一种低效的方式在低电价时段买便宜能源替代高电价时段的贵能源”,只要电价结构对,工程上就跑得通。

5.3 经济性对比与结论

把无冰蓄冷方案、有冰蓄冷日前调度方案、完整多时间尺度调度方案放在同一套数据下对比,运行成本差异很明显。无冰蓄冷方案一天运行成本约12860元,加上冰蓄冷并采用日前调度后降到11640元,降幅约9.5%;完整多时间尺度调度再进一步把成本压到11230元,相比无冰蓄冷方案总降幅约12.7%。

日内滚动和实时调整降低成本的原因,不是发现了更优的全局方案,而是减少了预测误差带来的代价。实测下来,光伏预测偏大或偏小10%时,纯日前调度的成本增加在300元到500元左右,而多时间尺度调度能把这部分额外损失控制到100元以内。经济账算清楚之后,多时间尺度这套架构的工程价值就非常立得住了。

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

6.1 Yalmip和Cplex环境配置问题

不少人在配置环境上卡住。Yalmip本身是一个工具箱,下载后添加到Matlab路径就能用,但Cplex有版本兼容问题。最常见的一种情况是Yalmip报告找不到求解器,或者把Cplex识别为“无许可证”。解决思路是先确认Cplex的Matlab接口编译成功,也就是在Matlab里运行Cplex命令或cplexlsqmiqcpex测试,然后重装Yalmip再添加路径。另外,Yalmip新版对Matlab版本有要求,太老的2016a以下版本可能不支持最新Yalmip,建议至少用2018b以上。

6.2 数值尺度不一致导致的求解异常

优化模型里变量数值跨度太大会引发数值质量问题。比如电功率是几百千瓦,蓄冷量是几百kWh,成本是几千元,看起来差不多,但有些约束里可能混入持续时间0.25、效率0.95、COP约4之类的系数,导致约束矩阵的条件数变差,Cplex在求解时会出现数值警告,甚至返回“infeasible”但实际约束明明都能满足。

我的处理习惯是把所有功率和能量统一到kW和kWh,时间单位统一到小时,效率参数保持0到1之间,COP作为大于1的系数,目标函数的各项成本也要统一到元。如果模型还是出现数值问题,可以把目标函数整体除以一个基准值,比如1000,把量级压到1左右,绝大多数情况下数值警告会消失。

6.3 蓄冷槽约束容易写错的几个点

蓄冷槽约束里最容易错的是日循环约束和时间尺度的换算。日循环约束是说调度周期结束时的蓄冷量要回到初始值,否则第二天无法延续同样方案。有些同学直接写S_ice(T)==0,但蓄冷量的状态在时间段中间也是有效的,最后约束应该作用在S_ice(T+1)上,因为S_ice(1)是初始状态。仅仅一个下标偏移,结果就会完全不同。

充放冷互斥约束也要小心。如果只对功率变量加约束,比如P_EC_ice小于等于400乘以on_ice_ch,而忘了限制P_ice_dis与on_ice_dis,那么融冰功率可能会在蓄冷状态为0的情况下偷偷为正,破坏能量守恒。检查这类错误最直观的方式是把蓄冷量曲线和充放冷功率曲线画在同一个图上,看充放冷功率等于0的时候蓄冷量是否还在变化,一眼就能看出问题。

6.4 预测误差导致调度方案失效怎么办

实际工程中预测数据不会像仿真那样干净,光伏电站突然被云遮住,冷负荷因为天气异常飙升,都是常有的事。这类场景下,日内滚动优化的偏差惩罚项会起作用,但权重需要调。如果系统对计划跟踪要求苛刻,就把偏差惩罚系数调大;如果希望系统更强调经济性,就调小。没有绝对标准,需要根据运行数据慢慢试。

还有一个非常实用的小技巧:室内负荷预测更新频率可以比分钟更短,但优化求解频率没必要完全同步。实际操作中,设定每15分钟触发一次滚动优化,但实时层每5分钟检查一次偏差,只有在偏差超过阈值时才请求重新优化。这样既保证了响应速度,又避免了频繁求解造成的计算资源浪费。

6.5 求解速度慢的优化方向

当设备数量增多或者时间分辨率从1小时变成15分钟时,二进制变量数量会爆炸式增长,MILP求解时间从几秒变成几分钟甚至更久,滚动优化根本跑不过来。系统性的优化路径有两条:一是严格固定日前输出的二进制变量,让日内和实时阶段退化为LP或QP问题,这个对求解速度的改善是最明显的;二是对蓄电池和蓄冷槽的SOC做离散化近似或使用聚合模型,减少连续变量的复杂度。

如果项目对实时性要求特别高,还可以考虑把实时层改成基于规则表的响应控制,比如“光伏出力下降超过5%时,蓄电池优先增发,缺口超过蓄电池上限时再调整联络线功率”。这本质上是一种退化的MPC,但实际效果往往足够好,我记得有个工程现场的实时控制器就是这套逻辑,稳定运行了小半年。

结语

这套项目从头到尾跑完,我个人最深的体会是:多时间尺度调度真正的难点,从来不是单一模型怎么建、求解器怎么调,而是三个尺度之间的衔接逻辑。如果只是把日前、日内、实时三个模型独立地跑一遍,效果甚至不如一个精细的日前调度加一个简单的反馈修正。我自己反复折腾之后觉得最管用的做法就是逐级锁定:日前输出的机组启停固定给日内,日内输出的储能和联络线计划作为实时的参考值,这样每一层既继承了上一层的全局信息,又有足够的自由空间去修正偏差,稳定性高,求解速度也有保障。

另外,从可扩展性角度说,这套代码的底子非常适合做二次开发。想加碳交易机制,就在目标函数里补一个碳成本项;想考虑需求响应,就把冷负荷从刚性变量改成带可平移范围的可调变量;想把预测和调度闭环,就把预测模块的输出直接接到日内滚动的数据入口。方向很多,每一个都值得单独拎出来做一轮实验对比,调度优化这个题目的乐趣也正在于此。

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

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

立即咨询