资讯动态

含冰蓄冷空调的冷热电联供微网多时间尺度优化调度建模与Matlab实现

发布时间:2026/10/20 23:59:36 来源:尧图企业网站定制
做微网调度优化这个方向也有好几年了。最近不少同行和研究生在问“含冰蓄冷空调的冷热电联供型微网多时间尺度优化调度”这个题目怎么做尤其是蓄冰槽怎么建模、怎么用Matlab落地。这个题目看似复杂但拆开来看其实就是“一个CCHP微网”加上“一台冰蓄冷空调”再套上“日前日内两阶段调度”的组合。难的不是单个环节而是怎么把冷、热、电三种能量流统一到同一个优化框架里还要让Ice Storage这种“隐性储能”真正发挥作用。这篇文章我就以自己做过的某园区冷热电联供微网项目为基础把物理结构、数学模型、多时间尺度调度逻辑以及Matlab代码实现的关键点完整拆一遍给想复现这个方向的同学一条可以直接走的路。1. 项目全貌与需求拆解1.1 这个项目到底在解决什么问题常规微网调度只考虑电功率平衡但冷热电联供型微网要同时处理三条能量母线电负荷、热负荷和冷负荷。燃气轮机发电时有大量余热排出这部分热可以回收用于供暖也可以驱动吸收式制冷机制冷。问题在于供电和供冷/供热并不是同步的——白天冷负荷拉满的时候电价通常也是最高的而夜里冷负荷低、谷电便宜燃气轮机却不可能为了“蓄冷”单独满负荷跑一晚上。这时候冰蓄冷空调就派上了用场。它本质上是一种“电转冷”的时间平移装置夜间用低谷电驱动制冷机组制冰把冷量以冰的形式存起来白天用电高峰时段融冰供冷少开或者不开电制冷机。这样一来微网里的冷负荷不再是刚性的而是变成了一个可以被调度安排的能量项。把这个思路放到整个CCHP系统里就不只是空调省钱的问题了而是能让燃气轮机的运行策略、蓄电池的充放策略、购售电策略全部跟着联动起来运行成本才能整体降下来。1.2 冰蓄冷空调在微网中的角色定位很多第一次接触冰蓄冷的人会把它当成“一个大冰箱”其实它的本质更像一个“冷量水库”。夜间蓄冰就相当于往水库里蓄水白天融冰供冷就相当于开闸放水。在优化模型里它的角色和蓄电池非常类似都有一个荷电状态SOC有储/放功率上下限有能量转换效率唯独不同的是它的“能量”是冷量而不是电量。但要注意冰蓄冷和蓄电池在建模上有一个关键差异蓄电池是双向的既可以充电也可以放电充放可以在同一时刻二选一而蓄冰槽的输入是“电制冷产生的冷量”输出是“融冰释放的冷量”输入和输出在物理上也是互斥的。蓄冰工况下COP约3左右也就是说消耗1份电可以存进3份冷量融冰工况下释放冷量的效率接近1基本没有太大损耗但融冰速率受冰槽结构和换热条件限制。我在第一次建模时犯过一个典型错误直接把蓄冰槽当成普通电池用充放电状态变量去表达结果优化结果特别离谱——白天一边用电制冷一边融冰晚上一边蓄冰一边放冷看着完全反逻辑。后来重构模型时才想明白蓄冰槽一定要在“冷功率平衡”里用冷量表达蓄冰是在冷负荷侧增加了一个冷量吸收项融冰是在冷负荷侧增加了一个冷量供应项二者之间只通过SOC状态变量建立联系。这一步想通了整个模型才顺起来。1.3 为什么非要“多时间尺度”调度如果只靠一个单阶段的日前调度预测误差会直接吃掉调度方案的可行性。光伏出力受天气影响大冷负荷受气温和人员活动影响大日前预测的偏差到20%是很常见的事情。例如某天下午实际冷负荷比预测高出一截日前计划里分配的吸收式制冷和融冰供冷就不够了这时候如果不做日内修正只能现场紧急购电开电制冷机成本一下子就上去了。多时间尺度调度的思路用大白话说就是“走一步看一步、看一步修正一步”。日前调度先根据未来24小时的预测数据制定一个全局性的运行计划确定燃气轮机启停组合、蓄冰槽蓄放冰框架、蓄电池充放框架日内滚动调度再根据超短期预测以15分钟为周期对未来的1~4小时重新求解在尽量不偏离日前框架的前提下修正各设备的出力。这个思想和模型预测控制MPC的滚动优化本质上是同一套逻辑。时间尺度划分的比较关系可以看下面这个表调度层级更新周期预测窗口决策内容主要作用日前调度每日一次未来24h机组启停、蓄冰/融冰计划、储能基准轨迹全局经济性最优日内滚动15min一次未来1~4h各设备出力修正、购售电调整应对预测偏差实时控制秒级瞬时就地频率/功率控制兜底功率平衡这篇文章后面重点讲的就是前两个尺度怎么建模、怎么在Matlab里实现以及两个尺度之间如何通过“基准轨迹偏差惩罚”协调起来。2. 系统建模与优化模型拆解2.1 物理系统结构与能量流建模之前先把系统的物理结构捋清楚。我采用的典型CCHP微网拓扑包含以下设备燃气轮机GT燃天然气发电同时产生可回收余热余热回收装置把燃气轮机排烟余热转换为热站可用热功率吸收式制冷机溴化锂机组利用余热制冷电制冷机常规压缩式制冷直接用电力制冷冰蓄冷装置包含蓄冰机组和蓄冰槽谷电时段蓄冰、峰电时段融冰蓄电池电储能平抑电功率波动光伏PV可再生能源发电燃气锅炉余热不足时补充供热与配电网的交换接口可购电售电整个系统的能量流是这样的。燃气轮机烧天然气发电发出的电并入微网母线和光伏、蓄电池、购电一起共同满足电负荷电负荷包括普通电负荷、电制冷机耗电、蓄冰机组耗电、蓄电池充电功率。燃气轮机排烟余热进入余热回收装置变成热功率一部分直接供给热负荷另一部分驱动吸收式制冷机。冷负荷则由吸收式制冷机、电制冷机、蓄冰槽融冰三方共同供给。如果某个时刻余热不足燃气锅炉补燃供热。这样一个系统的调度逻辑本质上是在每一小时日前或每15分钟日内里决定燃气轮机发多少电、余热怎么分配、电制冷与冰蓄冷怎么配合、蓄电池怎么充放、电网交互多少电量。每一次决策都要让成本最小同时保证所有能量平衡和设备运行在安全边界内。2.2 主要设备建模要点燃气轮机是系统的核心动力源。建模时我用两个关键参数发电效率η_gt和热电比r_chp。燃气轮机输入燃料功率F_gt发电功率P_gt η_gt * F_gt可回收余热功率Q_heat_rec r_chp * P_gt燃料成本按燃气耗量乘以气价计算。启停成本用0-1变量表达只要机组从停机转为运行就记一次启动费用。此外还要加爬坡约束防止前后时段出力变化过于剧烈。余热回收****装置的效率η_hrec一般在0.8左右它把排烟余热转换为热站可用热功率。吸收式制冷机再把这个热功率转换成冷功率制冷系数COP_ab可以取1.3左右。注意吸收式制冷机的COP大于1是因为它利用的是热驱动能量品位低但数量大这一点跟电制冷机有本质区别。电制冷机建模最简单消耗电功率P_ec输出冷功率Q_ec COP_ec * P_ecCOP_ec取4.5。电制冷机的启停也可以做成连续调节避免额外引入0-1变量增加求解复杂度。冰蓄冷装置需要单独建立SOC状态方程。蓄冰机组蓄冰时消耗电功率P_ice以蓄冰工况COP_ice约3.2转换为冷量存入蓄冰槽融冰时释放冷量Q_melt。SOC状态转移可以写成S_soc(t1) S_soc(t) - Q_melt(t) / η_melt η_ch * Q_ch_ice(t)其中Q_ch_ice COP_ice * P_ice表示蓄冰过程存入槽内的冷量η_melt和η_ch分别代表放冷和蓄冷过程的效率。蓄冰和融冰在同一个时段内不能同时进行这个互斥关系用两个0-1变量加上一个大M约束实现。最后再加一个调度周期末的SOC约束保证蓄冰槽跨日出清的一致性不允许第二天“白嫖”前一天剩下的冰。蓄电池的建模相对标准。SOC状态转移、充放功率上下限、充放互斥、初末SOC相等这些约束都要带上充放电效率我取0.92。注意蓄电池和蓄冰槽在功率平衡方程里的位置完全不同蓄电池直接进出电功率而蓄冰槽是“电功率-冷功率”的跨能转换这个区别在组装约束时千万别搞混。2.3 目标函数与约束条件目标函数是综合运行成本最小包括五部分燃气轮机和燃气锅炉的燃料成本、从电网购电的费用、设备启停成本、运行维护成本、弃光惩罚。用一个式子表达就是min Σ (C_fuel C_buy - C_sell C_start C_om)购电成本和售电收益按分时电价计算燃气成本按气价和热值折算。弃光惩罚项用于保证系统优先消纳光伏但惩罚系数不要设太大避免数值病态。约束条件分六类我在代码里也是按这个顺序组的电功率平衡燃气轮机出力光伏蓄电池放电购电 电负荷电制冷耗电蓄冰耗电蓄电池充电售电热功率平衡余热回收输出燃气锅炉供热 热负荷吸收式制冷机耗热冷功率平衡吸收式制冷电制冷融冰供冷 冷负荷蓄冰槽蓄冰冷量设备容量约束各类设备出力上下限储能状态约束SOC动态、容量上下限、充放互斥电网交互约束购售电功率上限以及购电和售电的互斥关系值得一提的是冷功率平衡式里“蓄冰槽蓄冰冷量”这一项它代表蓄冰机组把冷量“灌”进冰槽形式上跟冷负荷一样都是冷量的消耗方。把蓄冰看作冷负荷、把融冰看作冷源这个角度很重要直接决定了后面的代码怎么写。3. 多时间尺度调度策略与实现逻辑3.1 日前调度的决策内容日前调度在每天零点前运行一次以1小时为步长、24小时为优化区间输入是未来24小时的电负荷、冷负荷、热负荷、光伏出力、分时电价的预测曲线。它要输出的决策包括燃气轮机每小时启停状态和发电功率燃气锅炉的供热功率吸收式制冷机和电制冷机的制冷功率分配蓄冰槽每小时的蓄冰/融冰功率及SOC轨迹蓄电池每小时充放电功率每小时购电/售电功率日前调度的目标是把全局成本压到最低所以它会在谷电时段尽量多购电蓄冰、给蓄电池充电在峰电时段让燃气轮机多发、融冰供冷减少高价购电。从结果看蓄冰槽的SOC曲线会呈现典型的“夜间攀升、白天下降”的形态这个曲线就是日内滚动调度要跟踪的基准轨迹。这里有一个工程经验日前调度的步长不一定要设成1小时。如果冷负荷变化比较快或者你所在地区的分时电价时段边界比较复杂建议把步长缩短到30分钟甚至15分钟。代价是决策变量数量成倍增加但对目前的主流求解器来说几十个0-1变量的MILP问题依然很快。3.2 日内滚动修正的设计思路日内滚动调度是应对不确定性的关键环节。我自己做项目时用的是15分钟触发一次、滚动优化未来4个时段即1小时的窗口设置。为什么选15分钟而不是5分钟因为超短期预测的更新频率通常是15分钟一个周期而且5分钟粒度的优化会让求解次数翻倍实际执行时也没必要做到那么精细。日内滚动的决策变量跟日前调度基本一致区别在于它只关心窗口内的决策并且必须考虑“当前系统状态”作为初始条件。比如当前时刻蓄冰槽的SOC是多少、蓄电池SOC是多少、燃气轮机是否处于开机状态这些状态直接来自实时监测或日前计划的执行结果。窗口内第一时段的决策会被真正下发执行后面几个时段的决策只是为后续滚动做准备。日内优化与日前优化最大的区别在目标函数里多了一个偏差惩罚项。如果不加这个惩罚日内滚动会完全按照最新预测重新算一个“最优轨迹”很可能跟日前计划的机组启停、蓄冰策略完全拧着来反倒造成运行混乱。加了惩罚之后日内调度会尽量贴着日前计划走只有当预测偏差确实大到需要修正时它才会主动偏离基准轨迹。3.3 时间尺度之间的信息传递与协调两阶段调度之间传递的信息主要有三类燃气轮机的启停状态序列、蓄冰槽的基准SOC轨迹、蓄电池的基准充放电轨迹。我采用的惩罚系数是单位燃料成本的15%~20%。这个权重很关键小了日内就完全放飞自我日前等于白做大了日内就失去修正能力滚不滚动就没意义了。另外日内滚动求解时还可以加一个边界约束例如“燃气轮机出力与日前计划的偏差不超过±20%”。这类约束能从硬约束层面防止日内结果跑偏比单纯加软惩罚更可靠。实际项目中我是“软惩罚硬边界”一起用的软惩罚保证趋势一致硬边界保证可执行性。日内滚动执行完当前时段后结果会反馈给实时控制层。这一层我通常不放到优化模型里而是用简单的AGC逻辑或就地控制器处理秒级功率波动。换句话说多时间尺度调度解决的是“分钟/小时级的经济调度”问题秒级的功率平衡交给底层控制去兜底这样层次分明模型复杂度可控工程上也更合理。4. Matlab代码实现的核心环节4.1 求解工具与建模套路Matlab实现这类调度模型我推荐用YALMIP工具箱加商用MILP求解器比如Gurobi或Cplex的组合。YALMIP最大的好处是可以用符号化的方式写约束和目标函数不用自己去拼稀疏系数矩阵这对于约束多、耦合复杂的CCHP模型来说极其重要。Matlab自带的optimproblem框架也能做但遇到大M约束、SOC状态转移这种跨时段耦合约束时写起来远不如YALMIP顺手。代码整体框架分六步清空环境并定义参数 → 读取负荷、光伏、电价数据 → 定义决策变量和状态变量 → 组装约束 → 写目标函数 → 调用求解器并处理结果。为了调试方便我习惯把参数集中放到一个结构体里例如para.gt_up、para.gt_down这样不同算例之间切换只需要改动参数文件不需要碰模型主体。4.2 关键代码片段解析先看变量定义部分。这里用到sdpvar定义连续变量、binvar定义0-1变量。以日前调度为例假设T24T 24; P_gt sdpvar(1, T); % 燃气轮机出力 on_gt binvar(1, T); % 燃气轮机启停状态 P_ec sdpvar(1, T); % 电制冷机耗电功率 Q_ab sdpvar(1, T); % 吸收式制冷输出冷量 Q_melt sdpvar(1, T); % 融冰供冷量 P_ice sdpvar(1, T); % 蓄冰耗电功率 z_ch binvar(1, T); % 蓄冰状态1为蓄冰 z_melt binvar(1, T); % 融冰状态1为融冰 S_soc sdpvar(1, T1); % 蓄冰槽SOC含末状态 P_buy sdpvar(1, T); % 购电功率 P_sell sdpvar(1, T); % 售电功率 SOC_bat sdpvar(1, T1); % 蓄电池SOC P_ch sdpvar(1, T); % 蓄电池充电功率 P_dis sdpvar(1, T); % 蓄电池放电功率接下来是电功率平衡约束。蓄冰耗电P_ice、电制冷耗电P_ec、蓄电池充电P_ch都作为负荷项放到等式右边Constraints []; for t 1:T Constraints [Constraints, ... P_gt(t) P_pv(t) P_dis(t) P_buy(t) ... L_elec(t) P_ec(t) P_ice(t) P_ch(t) P_sell(t)]; end冷功率平衡约束里把蓄冰冷量Q_ch_ice作为冷负荷项把融冰Q_melt作为冷源项% 蓄冰冷量 COP_ice * P_ice Q_ch_ice para.cop_ice * P_ice; for t 1:T Constraints [Constraints, ... Q_ab(t) P_ec(t) * para.cop_ec Q_melt(t) ... L_cold(t) Q_ch_ice(t)]; end这里P_ec(t) * para.cop_ec就是电制冷机的输出冷量吸收式制冷输出Q_ab直接是冷量变量避免单位混乱。蓄冰槽的SOC状态转移和蓄放互斥约束是关键% SOC初值 Constraints [Constraints, S_soc(1) para.soc_ice_0]; for t 1:T % SOC状态转移 Constraints [Constraints, ... S_soc(t1) S_soc(t) * (1 - para.ice_loss) - Q_melt(t)/para.melt_eff para.ch_eff * Q_ch_ice(t)]; % 容量上下限 Constraints [Constraints, 0 S_soc(t1) para.ice_cap]; % 蓄冰与融冰互斥 Constraints [Constraints, Q_ch_ice(t) para.ice_ch_max * z_ch(t)]; Constraints [Constraints, Q_melt(t) para.ice_melt_max * z_melt(t)]; Constraints [Constraints, z_ch(t) z_melt(t) 1]; end % 日末SOC约束保证跨日一致 Constraints [Constraints, S_soc(T1) para.soc_ice_0];注意融冰功率Q_melt的取值上限不是固定值有些冰槽的融冰速率会随冰层厚度变化但工程上做线性近似完全够用。把互斥约束写成两个0-1变量的大M形式会比用单个三态变量方便得多YALMIP对这种写法非常友好。4.3 日内滚动循环的实现思路日内滚动调度的主循环是个经典的MPC结构。我的实现框架如下for k 1 : 96-3 % 当前时刻索引k滚动窗口长度H4 H 4; idx k : kH-1; % 读取超短期预测数据 L_pred load_pred(idx); P_pv_pred pv_pred(idx); price_pred price_pred(idx); % 初始化窗口问题 Constraints []; Objective 0; % 定义窗口内变量维度改成H % ... 变量定义与约束组装与日前模型基本一致 ... % 加入对日前计划的偏差惩罚项 beta para.beta * para.price_gas; for h 1:H Objective Objective beta * abs(P_gt_win(h) - P_gt_da(idx(h))); end % 求解并执行当前时段 optimize(Constraints, Objective, options); P_gt_execute(k) value(P_gt_win(1)); % 其余设备类似 end这里有一个实际操作中的坑每天都跑一次完整滚动循环求解次数非常多。如果每个窗口都从头构建YALMIP模型代码运行速度会慢得让人怀疑人生。我在项目里把“模型构建”部分封装成了一个函数输入是预测数据和基准轨迹输出为优化后的调度结果循环里只调用这个函数。实测下来96个滚动窗口全部跑完不到两分钟完全在可接受范围内。4.4 数据准备与算例设置没有好的数据模型再漂亮都是白搭。做算例时数据至少包含四部分负荷曲线电、冷、热、光伏出力曲线、分时电价曲线、设备参数表。负荷和光伏数据可以用历史数据加预测误差的方式生成。比如取某个夏季典型日的历史冷负荷曲线乘以一个0.9~1.1的随机扰动模拟预测偏差这样生成的算例既能体现日前/日内差异又不脱离实际。设备参数可以按我下面的典型值设置方便你快速复现设备/参数数值燃气轮机额定功率500 kW发电效率0.30热电比1.2余热回收效率0.85吸收式制冷COP1.3电制冷机COP4.5蓄冰工况COP3.2蓄冰槽容量1000 kWh最大蓄冰功率250 kW最大融冰功率250 kW蓄电池容量300 kWh蓄电池最大充放功率100 kW光伏装机300 kW分时电价如果手头没有真实数据可以用典型峰平谷电价谷段0.3元/kWh平时段0.7元/kWh峰段1.1元/kWh。天然气价格2.8元/m³低热值按9.7 kWh/m³折算。结果处理部分我习惯把燃气轮机出力、电制冷功率、蓄冰SOC、购售电功率这些关键曲线画在一起对比再用sum统计总成本。画图时注意把X轴时间对齐到真实时刻否则日出和日没位置都会错位看起来就别扭。5. 调试过程中的常见问题与避坑记录5.1 模型“死活算不出可行解”这个问题在前期建模阶段出现得最频繁。我刚把这个项目的约束全部组装完毕之后第一次求解YALMIP直接报无解。排查思路很简单先把目标函数全部置零只求可行解如果仍然无解再用松弛变量逐个平衡等式看松弛量落在哪条约束上。实际项目中最常见的原因有两个。一是冷负荷峰值超过了吸收式制冷、电制冷和融冰三者最大供冷能力之和。这种情况属于设备容量配置不足不是模型写错了。二是蓄冰槽的日末SOC约束设置不合理。如果前一天蓄冰量被大量消耗日末SOC小于初值强行要求SOC(T1)SOC_0就会导致傍晚时段无法满足冷负荷。处理办法是把日末约束改成SOC(T1) 0.7*SOC_0这类松弛形式或者干脆只在蓄冰策略本身就要求跨日平衡时用严格等式。5.2 蓄冰槽“蓄不满”或者“用不完”优化结果里蓄冰槽经常只用了不到一半容量这说明冰蓄冷的经济性没有被模型体现出来。原因通常是峰谷电价差太小导致谷电蓄冰省下的钱覆盖不了设备损耗和运维成本。如果算例里电价差确实小那就不是模型问题是商业模式问题。但如果你确信电价差足够大结果还是蓄不满就要检查蓄冰和融冰的互斥约束是不是误伤了。我踩过一次坑融冰工况下允许吸收式制冷和电制冷同时停运只靠融冰供冷但融冰功率上限设得太低导致白天能放出来的冷量有限冰槽自然用不彻底。调试时把Q_melt的上限调到蓄冰功率的1.5倍并用表格列出峰值冷负荷时各冷源供冷量一眼就能看出问题在哪。5.3 日前计划和日内计划偏差很大如果日内滚动结果跟日前计划差得很远说明偏差惩罚权重太小或者日内模型里没有继承日前关键决策。有一个检查技巧把燃气轮机的启停序列取出来对比日前和日内结果如果大部分时段的开/停机状态都对不上那就说明日内没有收到“启停状态必须继承日前结果”的信息。解决办法是在日内模型的目标函数中对启停状态加硬约束on_gt_win(h) on_gt_da(idx(h))。这样日内滚动只修正出力大小不改变启停组合运行逻辑就会稳定很多。只有在超短期预测显示负荷发生剧烈变化时才允许修改启停状态这部分可以通过松弛变量实现。5.4 求解器数值问题与性能优化MILP模型经常遇到数值条件差的问题。最常见的原因是SOC量纲跟功率量纲差的太大。比如蓄冰槽SOC上限设成10000 kWh而电功率是几百kW级别目标函数里又多了一个数量级的惩罚系数求解器跑起来矩阵条件数就难看了容易出现“Optimal但结果明显不合理”或者求解极慢的情况。我的建议是所有能量单位统一成kWh、功率统一成kWSOC做归一化处理上限直接写成1约束里SOC乘以容量再参与运算。另外大M系数不要盲目取1e5能取100就取100够约束生效就行。数值条件越好求解速度越快。现象可能原因排查与处理无可行解容量不足/日末SOC约束过严松弛等式约束、放宽容限蓄冰量利用率低融冰上限低/电价差小调大融冰上限、检查峰谷价差日前日内偏差大惩罚系数小/未继承启停加大偏差惩罚、硬约束启停状态求解很慢变量量纲混乱/M过大归一化SOC、缩小M系数此外如果用的求解器支持多线程参数记得在options里开起来日内滚动场景下每个窗口的问题规模不大但循环次数多单窗口求解时间每缩短0.1秒整体都能明显感知到。写到最后我最大的一个体会是这种调度模型猛一看是个数学优化问题做到后面才发现真正的门槛是工程理解。设备参数是你自己定的预测数据是你自己给的但结果能不能在现场落地全靠你对物理逻辑有没有想透。冰蓄冷这东西我在实际项目中把它的自损率从0改成每天1%之后整个SOC曲线立刻合理了这种参数你在论文附录里永远找不到但工程里天天遇到。如果你也在复现类似题目建议先别急着钻代码先把能量流图画明白把蓄冰槽是“冷量水库”这个直觉建立起来后面的一切都会顺很多。

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

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

免费获取报价 →
↑