
先说一个结论在微电网经济调度里把空调集群“当成储能”来用不是比喻而是可以严格建模的工程方法。你可以把一整栋写字楼的空调看成一块挂在微电网母线上的隐形电池——它有容量房间的蓄冷量、有功率上限压缩机的可调范围、有SOC室内温度到舒适度边界的距离甚至还有“自放电率”房间漏热导致的冷量散失。我最近用Matlab完整实现了这套“基于等效储能聚合模型的含空调集群微电网经济调度”跑了典型日96个时段的日前优化算下来运行成本比不参与调度时降低了11%左右。这篇文章把从单台空调建模、集群聚合、调度建模到Matlab求解的完整链路拆开写适合正在做微电网优化、需求响应、虚拟电厂方向的研究生和工程师参考。1. 为什么非要把空调集群“打包”成储能设备1.1 微电网调度的调节资源荒搞过微电网的人都有个共同感受光伏和风电的出力曲线看着漂亮真要做经济调度时手里的调节资源永远不够。光伏中午大发下午断崖式下跌傍晚负荷高峰偏偏撞上风电小发。这时候储能电池是最理想的调节手段但容量贵一块100kW/200kWh的磷酸铁锂储能光电池成本就够买好几台小型燃气轮机。微型燃气轮机和柴油发电机响应慢频繁调节还有寿命损耗动不动就给调度员脸色看。现实里还有一种被长期忽视的调节资源——空调负荷。城市配电网夏季高峰负荷里空调能占到30%~50%。单体空调功率不大一两千瓦但它数量极其庞大且天然具备热惯性。房间就是一个蓄能体你让空调停机20分钟室温从24℃慢慢爬到26℃人体基本无感反过来提前半小时把房间过冷到23℃后面半小时压缩机休息也能维持舒适。这种“短时间内允许功率波动但不牺牲舒适度”的特性跟储能电池的充放电行为在数学上是同构的。把大量空调聚合成一个整体让它在微电网调度里扮演一台可控的虚拟储能这就是等效储能聚合模型的出发点。相比电池它几乎零成本而且容量随空调数量线性增长。要知道一个中型园区的空调总功率可以轻松过兆瓦这个量级对微电网调度完全有实际意义。1.2 空调的热惯性就是天然的储能空间理解等效储能模型最关键的一步是把“温度”翻译成“电量”。电池储能的本质是电化学能量SOC表示剩余电量占比。空调集群的“储能”本质是热力学势能——室内空气和建筑围护结构里存储的“冷量”。室内温度越低储冷量越大。给定一个舒适度区间比如制冷工况下24℃~26℃那么从26℃降到24℃的过程中空调每多移出一份热量房间就多储存一份“冷量”。这就是虚拟储能的充电过程温度从24℃回升到26℃冷量释放就是放电过程。所以虚拟储能跟电池储能面对的问题完全一样充电功率多大压缩机满功率制冷能搬走多少热、放电功率多大停机后房间自然吸热有多少、容量多大温度从上限到下限之间能存多少冷量、什么时候充什么时候放追随分时电价和新能源出力。微电网调度员不需要关心每一台空调的启停细节只需要知道此刻这个空调集群整体能消耗多少电、能少消耗多少电、能持续多久以及温度会不会越过舒适度红线。把这几个数拿到优化模型里空调就从“被动负荷”变成了“主动调节资源”。这也是为什么这几年“虚拟电厂”和“需求响应”领域都在抢空调负荷——因为它不需要额外硬件投资只需要一套协调控制算法就能把用户侧散落的弹性空间变成电网侧的调节能力。1.3 等效储能模型的适用边界任何模型都有适用条件等效储能聚合模型不是万能的。我实际用下来它最舒服的场景是日前调度和日内滚动调度时间尺度在15分钟到1小时之间。在这个尺度上空调集群的聚合规律足够稳定温度变化过程可以用常微分方程描述线性化误差可以接受。但如果你要做秒级AGC调频这个模型就太粗糙了因为压缩机启停周期、制冷剂循环延迟这些因素都会凸显出来需要更精细的开关控制模型。另一个限制在于空调集群能提供的“储能”方向是单向的。电池可以充电也可以放电但空调集群无论怎么调它整体仍然是一个耗电负荷不可能倒送功率给电网。它的“放电”指的是相对基准功率降低用电量从而把原本要卖给它的电让出来给其他负荷而不是真正向母线注入电能。经济调度建模时要把这一点写清楚否则功率平衡方程的方向很容易搞反。2. 单台空调怎么变成“虚拟电池”ETP模型与状态映射2.1 一阶ETP热力学方程要聚合先拆解单台空调的模型是整个链条的地基。工程上最常用的是等效热参数模型英文叫Equivalent Thermal Parameters简称ETP。它的物理图景很直观把房间看成一个热容C墙体和窗户看成一个热阻R空调是一个可控冷源室外温度是外界扰动。一阶ETP模型的连续时间形式是C · dT_in/dt (T_out - T_in) / R - η · P_cool Q_gain其中T_in是室内温度T_out是室外温度C是房间热容kWh/℃R是等效热阻℃/kWη是空调能效比COPP_cool是压缩机消耗的电功率kWQ_gain是室内人员和设备的热增益kW。这个式子的物理含义很直白左边是室内温度的变化率右边第一项是室外通过墙体漏进来的热量第二项是空调搬走的热量第三项是室内热源产生的热量。温度升高还是降低取决于这三项谁占上风。离散化之后便于在Matlab里递推T_in(k1) T_in(k) Δt/(R·C) · [T_out(k) - T_in(k)] - (η·Δt/C) · P_cool(k) (Δt/C) · Q_gain我实际编程时把Δt设为0.25h15分钟因为电价和光伏出力曲线通常按15分钟一个点给数据。这里有一个细节Δt不能取得太大否则离散化误差会累积尤其夏季午后室外温度快速爬升时模拟出来的室温容易偏大但也不能太小否则96个时段的优化问题规模成倍增长。折中下来15分钟对日前调度完全够用。2.2 从室温到SOC状态变量的等价变换ETP模型描述的是温度储能模型描述的是SOC中间需要做一个变量代换。定义单台空调的虚拟储能量E(t) C · (T_max - T_in(t))这里T_max是舒适度区间的温度上限。当室温等于上限时E0意味着这台空调已经“没电了”一点冷量都挤不出来当室温等于下限T_min时E达到最大值E_max C · (T_max - T_min)把E(t)对时间求导再代入ETP方程可以得到虚拟储能的充放电方程dE/dt (T_in - T_out)/R - η · P_cool Q_gain整理一下就会发现这个方程和电池储能的动态方程结构完全一致等式左边是“电量”的变化率右边第一项是自放电项第二项是可控充电功率第三项是环境干扰。其中右侧第二项前面带负号说明空调耗电功率越大冷量蓄积越多。把E(t)归一化就得到单台空调的等效SOCSOC(t) E(t) / E_max (T_max - T_in(t)) / (T_max - T_min)这个式子太好用了。室温26℃时SOC0室温24℃时SOC1。调度运行时只要监测室内温度就能实时知道这台“虚拟电池”还剩多少能量。反过来调度指令下发一个SOC目标控制器也能反推出室温应该控制在什么位置。2.3 定频、变频空调的参数化差异真实世界的空调分定频和变频两大类建模时不能一概而论。定频空调压缩机只有启停两种状态功率不可连续调节在优化模型里需要引入0-1整数变量变频空调压缩机功率可以连续调节建模要平滑得多。我在这里建议针对不同的研究目标做不同的处理。如果你关心的是集群尺度的功率调节能力可以把变频空调近似为连续可调功率源只需约束功率上下限如果研究对象包含定频空调占比很高的情况比如居民小区那最好把单台定频空调建模为占空比控制用在一个控制周期内启停时间比例近似连续功率。这样既保留了功率连续的方便性又不会偏离实际太多。另一个容易出错的参数是COP。夏季制冷时空调COP一般在2.5到4之间老旧空调可能只有2新一级能效的变频机可以到5。很多人建模时直接把空调铭牌功率当成制冷量结果把虚拟储能容量算大了一倍。正确做法是铭牌功率×COP才是制冷功率ETP方程里的η·P_cool项用的是制冷功率所以要么把COP乘进去要么在代码里用制冷功率作为变量。这个细节如果错了后面聚合模型算出来的可调容量会严重虚高调度结果自然不可信。3. 从N台空调到一台“聚合储能”数学合并与潜力估算3.1 分组聚合法按参数一致性归并从单台模型到集群模型最朴素的做法是把每台空调都写进优化模型一栋楼500台空调对应500组温度状态变量。这个做法精度最高但优化问题规模会爆炸15分钟一个时段、24小时就是96个时段500台空调带来48000个状态变量和约束求解时间动辄几分钟甚至更久工程上很难接受。工程上更常用的是分组聚合法。思路很简单把参数相近的空调归到同一组每组当成一台“大空调”来建模。比如同一个园区里同样朝向、同样面积、同样空调品牌的用户它们的R和C分布通常是聚类的。先把每台空调的R、C、初始室温算出来然后用K-means聚类分3到5组组内参数取均值或加权平均。聚合后第j组的等效参数为C_agg,j Σ C_i组内所有房间热容之和 R_agg,j 1 / Σ(1/R_i)并联热阻 η_agg,j 按功率加权平均的COP这样做的好处非常明显原本500个状态变量压缩到3到5个但精度损失很小。因为优化调度关心的是集群整体的功率边界和能量边界组内个体差异会在求和过程中相互平均只要分组数不是太少聚合误差对总调度成本的影响通常在3%以内。我自己的代码里默认分4组实测效果不错。3.2 聚合后的功率边界、容量边界与SOC递推分组之后每一组空调就等效为一台虚拟机组它的参数和约束定义如下。等效容量kWhE_cap,j C_agg,j · (T_max - T_min)等效功率下限kWP_min,j Σ P_ac_min,i等效功率上限kWP_max,j Σ P_ac_max,i其中P_ac_min是单台空调的最小可调功率定频空调取0变频空调取额定功率的20%~30%P_ac_max是最大功率定频取额定功率变频取额定功率的100%~110%。聚合虚拟储能的SOC递推方程是SOC_j(k1) SOC_j(k) Δt / E_cap,j · [P_set,j(k) - P_base,j(k)]这里的P_set,j是调度指令给出的空调组总用电功率P_base,j是维持温度不变所需的基础功率可以理解为“追踪温度设定点所需的平均功率”。P_set比P_base大就是充电相当于让空调多耗电把房间再降低一点温度P_set比P_base小就是放电相当于让空调少耗电允许温度向上升。写到这里必须强调一个容易忽略的方向问题空调多用电动对应“充电”少用电动对应“放电”。这和电池的符号习惯刚好相反因为电池放电是对外输出功率而空调“放电”是减少自身的用电以把电让给别的负荷。建模时建议在代码注释里明确标记免得过两天自己再看的时候绕晕。3.3 一个算例1000台空调到底能挤出多少可调功率我经常被问到这个模型算出来空调集群到底能提供多大调节能力。这里给一个直观的估算算例参数按典型的商用写字楼变频多联机设置。1000台空调单台额定功率1.5kW变频最低功率20%即0.3kW。房间热容C取0.18kWh/℃舒适区24℃~26℃即T_max-T_min2℃。单台功率调节范围0.3~1.5kW聚合后总功率调节范围300~1500kW这意味着电力公司或者微电网调度中心能在这个范围内连续调节空调集群的用电功率。相比一台1000kW的储能PCS这个功率等级完全可用于削峰填谷。再看容量单台虚拟储能容量是0.18×20.36kWh1000台合计360kWh。相较于功率等级这个容量不算大支持满功率放电的时间约为360kWh除以平均可调功率600kW约36分钟。换句话说空调集群更适合做小时级以内的短时功率调节比如晚高峰前2小时的削峰或者配合光伏出力波动做跟踪。指望它像大型抽蓄那样连续调节6小时不现实这是物理规律决定的模型算出来也会是这个结论。4. 经济调度模型成本最小化目标与全约束清单4.1 微电网拓扑与运行成本构成搭建经济调度模型之前先明确微电网的拓扑结构。我采用的一个典型配置是光伏、风电、微型燃气轮机、储能电池、常规负荷和空调集群通过一条交流母线连接与上级配电网存在功率交换。这个系统里运行成本主要来自四个部分微型燃气轮机的燃料成本向上级电网购电的费用售电收益可以抵扣储能电池的充放电损耗成本空调集群参与调节可能带来的舒适度惩罚光伏和风电是零边际成本电源优先消纳不在目标函数里加成本项但可以通过弃风弃光惩罚来避免极端情况下强行消纳导致的不合理调度。空调集群的成本项不是真实货币支出而是为了量化舒适度损失——如果调度让空调长期工作在温度区间边界虽然约束没违反但用户体感会变差需要设置一个软惩罚来让优化结果“留有余地”。4.2 目标函数的建立燃料、购电与舒适度罚项日前经济调度的目标函数可以写成min Σ_t [ C_MT(P_MT(t)) C_grid(t)·P_grid_buy(t) - C_sell(t)·P_grid_sell(t) C_ESS·|P_ESS(t)| C_comfort·violation(t) ]这里逐项解释。微型燃气轮机成本采用二次函数拟合C_MT(P) a·P² b·P c实际计算时二次函数直接丢给Yalmip也能求解但如果用CPLEX求解器二次目标会走MIQP速度慢且可能数值不稳定。更稳妥的做法是分段线性近似把P的可行域切成2到3段每段用线性成本系数。我的经验是两段线性就够误差在1%以内。购售电价采用分时电价曲线峰时段1.2元/kWh平时段0.8元/kWh谷时段0.4元/kWh这组数据来自国内某省工商业电价政策的典型值。购电和售电不能同时发生通常用一组互补约束保证。储能电池成本按充放电功率的绝对值乘以一个很小的系数比如0.05元/kWh代表每一次充放电循环对应的电池衰减成本。这个系数虽然小但能让求解器避免无意义的来回充放电。最后一项是舒适度罚项当温度越界时按越界深度线性惩罚。加这一项的意义在于防止模型把空调功率压得太狠导致舒适度贴着约束边界持续运行。系数取几百元/℃跟购电成本放在一个数量级实际调参时可以试算。4.3 约束条件逐条拆解功率平衡、机组爬坡、虚拟储能约束条件分为几组每一组都不能漏。功率平衡约束P_PV(t)P_WT(t)P_MT(t)P_grid(t)P_ESS_dch(t) P_load(t)P_AC(t)P_ESS_ch(t)注意这里P_load是除空调外的常规负荷P_AC是空调集群总用电功率作为优化变量而不是固定负荷。符号约定P_grid购电为正、售电为负P_ESS_dch为正表示放电P_ESS_ch为正表示充电。微型燃气轮机约束包括出力上下限和爬坡速率P_MT_min ≤ P_MT(t) ≤ P_MT_max |P_MT(t) - P_MT(t-1)| ≤ Ramp_MT·Δt空调集群虚拟储能约束P_AC_min(t) ≤ P_AC(t) ≤ P_AC_max(t) SOC_AC(t1) SOC_AC(t) Δt/E_cap·[P_AC(t) - P_AC_base(t)] SOC_min ≤ SOC_AC(t1) ≤ SOC_max T_AC_min ≤ T_room(t) ≤ T_AC_max等价于SOC约束电网交互约束0 ≤ P_grid_buy(t) ≤ P_buy_max 0 ≤ P_grid_sell(t) ≤ P_sell_max储能电池约束类似包括SOC递推、充放电功率上下限和终值SOC设定。特别提醒一下电池储能放在模型里时SOC递推方程很容易出现符号写反的问题我每次写完都会手推一遍第一个时段的递推关系再往下走。5. Matlab代码实现变量定义、约束拼装与求解器选择5.1 求解工具对比linprog、YalmipCPLEX、还是自己写Matlab做优化求解工具选型直接影响开发效率。我对比过三种方案。第一种是直接用linprog或quadprog优点是无须额外安装工具箱缺点是约束拼装非常痛苦尤其是带时间耦合的SOC递推约束要手动构建大矩阵每加一个约束都要小心行索引对齐调试一晚上可能都查不出哪行写错了。第二种是Yalmip加外部求解器这是我推荐的主流方案。Yalmip本身不是一个求解器而是一个建模层你只需要用sdpvar声明变量、写约束和目标函数最后一行optimize调用求解器。Yalmip支持CPLEX、Gurobi、Mosek等商用求解器也支持内置的linprog切换只需改一个参数。缺点是需要额外安装Yalmip和对应求解器第一次配环境要花点时间。第三种是自己写交替迭代算法比如逐步动态规划、遗传算法或者差分进化。除非研究算法本身否则我不推荐。经济调度本质上是个结构化很强的优化问题商业求解器的凸优化算法远比通用启发式算法稳定高效而且Yalmip建模和修改约束都方便。我的完整项目里用的是YalmipR2025bCPLEX的组合调度周期设为96个时段每15分钟一个点决策变量大约1500个CPLEX求解时间在3到8秒之间完全满足离线仿真需求。5.2 核心代码虚拟储能约束的线性化写法代码里最关键的一段是空调集群虚拟储能约束的拼装。我直接贴简化版本删除了一些工程参数初始化的细节保留核心逻辑。%% 决策变量定义 T 96; % 调度时段数 P_AC sdpvar(1, T); % 空调集群总功率 SOC_AC sdpvar(1, T1); % 虚拟储能SOC多一个节点表示初始和末端 P_MT sdpvar(1, T); % 微型燃气轮机出力 P_grid sdpvar(1, T); % 与电网交换功率正买负卖 P_ESS sdpvar(1, T); % 储能电池功率正放负充 P_ESS_ch max(P_ESS, 0); % 充电功率非负 P_ESS_dch max(-P_ESS, 0); % 放电功率非负注意上面max函数在Yalmip里是支持自动线性化的它会引入辅助变量和不等式约束等效于两个线性约束P_ESS_ch ≥ P_ESS P_ESS_ch ≥ 0这种方法比手动写max表达式干净也不容易出错。接下来是虚拟储能的约束部分%% 空调集群虚拟储能约束 dt 0.25; % 时段长度小时 E_cap 360; % 聚合等效容量kWh P_base 600 * ones(1,T); % 基准功率由室温设定点处的热平衡计算得到 P_AC_max 1500 * ones(1,T); P_AC_min 300 * ones(1,T); SOC_AC_min 0.05; SOC_AC_max 0.95; Constraints []; Constraints [Constraints, SOC_AC(1) 0.5]; % 初始SOC for t 1:T Constraints [Constraints, SOC_AC(t1) SOC_AC(t) ... dt / E_cap * (P_AC(t) - P_base(t))]; Constraints [Constraints, P_AC_min(t) P_AC(t) P_AC_max(t)]; Constraints [Constraints, SOC_AC_min SOC_AC(t1) SOC_AC_max]; end这段代码对应的物理过程是如果P_AC大于P_base相当于空调多耗电给房间“充电”SOC升高P_AC小于P_base相当于少耗电房间温度回升SOC降低。约束SOC上下限等价于约束室内温度不要突破舒适度区间。5.3 数据准备负荷、风光出力、空调参数怎么造得像真的仿真输入质量直接决定调度结果是否可信。我的数据准备做法分三步。第一步生成常规负荷曲线。典型商用建筑日负荷曲线形状大致是晚上低、白天高、中午有一个小回落。可以用几个高斯函数叠加来拟合t 0.25*(0:95); % 小时数 P_load 300 150*exp(-(t-12).^2/8) 100*exp(-(t-15).^2/5);需要真实数据的话可以把公开数据集的负荷曲线插值到15分钟分辨率。第二步生成光伏和风电曲线。光伏用晴天模型即正午出力最大、早晚为零P_PV 400 * max(0, sin(pi*(t-6)/12)).^1.5; P_PV(t 6 | t 18) 0;风电用随机波动叠加日尺度分量。第三步生成空调集群的异质性参数。单台房间热容C按均值0.18、标准差0.03的正态分布抽样热阻R按均值2.0、标准差0.4抽样然后用kmeans聚类分成4组每组聚合后计算等效功率上下限和容量。这里不要用全同参数否则聚合模型过于理想调度结果缺乏说服力。5.4 结果可视化调度曲线与温度曲线怎么画调度做出来之后可视化是必须的。我习惯用四个子图展示结果左上各电源出力与负荷平衡堆叠图右上空调集群用电功率与基准功率对比左下虚拟储能SOC随时间变化右下代表性房间的室内温度曲线绘图代码核心如下figure(Position, [100, 100, 1200, 800]); subplot(2,2,1); area(t, [P_PV; P_WT; P_MT; P_grid_buy], LineWidth, 0.5); hold on; plot(t, P_load P_AC_opt, k-, LineWidth, 1.5); legend(PV, WT, MT, Grid, Total Load); subplot(2,2,2); stairs(t, P_AC_opt, r-, LineWidth, 1.2); hold on; stairs(t, P_AC_base, b--, LineWidth, 1.2); legend(AC Power, Base Power); subplot(2,2,3); stairs(t, SOC_AC_opt(1:end-1), g-, LineWidth, 1.2); ylim([0, 1]); subplot(2,2,4); stairs(t, T_room_opt, m-, LineWidth, 1.2); yline(24, k--); yline(26, k--);画图时别急着展示先检查温度和SOC是否真的在边界内。有一次我画完温度曲线才发现SOC约束生效了但温度越界回头一查是SOC初始值跟实际室温对不上白白浪费了一个晚上。6. 典型日仿真结果空调集群是如何“削峰填谷”的6.1 各机组出力与购电曲线变化我用一个典型夏季日的仿真参数跑完优化调度结果有几个明显特征。光伏中午12点到14点出力最大这时候微电网会出现功率富余优化结果把多余功率用于给空调集群“充电”——即让空调提前深冷把室温压到24℃左右SOC推到0.85以上相当于把午间光伏发电量转化成“冷量”存起来。傍晚18点到21点负荷达到晚高峰光伏出力已经降到很低燃气轮机和购电成本都很高。此时优化结果会主动下调空调集群功率允许室温从24℃回升到25.5℃SOC从0.85下降到0.2左右。空调集群减少的用电量让渡给了其他负荷微电网从电网购电的尖峰被明显削掉。对比不参与调度的基准场景燃气轮机的出力波动明显减小高峰时段购电功率下降了约180kW这对微电网运营商来说意味着基本电费容量的降低——即便忽略电量电费差异仅需量电费一项就相当可观。6.2 空调功率曲线和虚拟储能SOC的变化逻辑把空调功率曲线和SOC曲线放在一起看能很明显地看到虚拟储能的“充放电”节奏。凌晨0点到6点电价处于谷时段优化结果让空调略微高于基准功率运行SOC从0.5缓慢爬升到0.65。这段时间空调多消耗的电来自低价电网电成本很低相当于低价“充电”。上午9点到11点电价进入平段光伏出力逐渐上升调度策略趋于中性SOC基本维持不变或小幅波动。午后光伏大发时段空调功率出现一个明显的上凸峰对应SOC快速爬升到全天最高点。这个动作的实质是“把电能转化为冷能”等到光伏出力衰减后空调集群进入“放电模式”功率明显低于基准线SOC一路下滑。整个过程看起来就是一块储能电池在电价和新能源出力的双重信号下进行的低买高卖只不过交易的商品是冷量。一个值得注意的细节是SOC轨迹在绝大部分时段没有触及0.05的下限而是保持在0.2以上。这是因为舒适度惩罚项在起作用——如果调度策略把空调集群压到极限室温逼近27℃甚至更高虽然还在约束内但惩罚项的边际成本会超过购电成本所以优化结果主动留了余量。这符合实际需求调度员不希望用户因为空调不凉而投诉。6.3 经济性对比参与调度前后成本差多少为了评估空调集群参与调度的经济价值我设置了对照组基准场景中空调功率固定为用户自行设定温度对应的自然功率曲线不参与优化对比场景中空调集群按等效储能模型参与日前调度。两个场景使用完全相同的电价、风光出力、负荷和燃气轮机参数唯一区别是空调功率是固定值还是优化变量。仿真结果汇总如下指标基准场景参与调度变化幅度燃气轮机燃料成本元48604315-11.2%电网购电成本元65205930-9.1%总运行成本元1138010245-9.97%空调高峰用电功率kW14201210-14.8%最大购电功率kW980800-18.4%需要说明的是这个成本降幅是在分时电价峰谷差较大的场景下得到的。如果电价峰谷差很小空调集群参与调度的收益空间会被压缩。实际项目中空调负荷聚合的主要收益来源不一定是电量费用节省更可能是容量电费降低和需求响应补贴这两块在模型里没有直接体现。7. 调试过程中的五个坑与三个处理技巧7.1 只约束功率、不约束SOC模型“白嫖”空调能量我第一次搭建模型时只加了空调功率的上下限约束觉得功率不越界就没问题结果优化结果非常离谱空调集群在电价高峰时段长时间运行在最低功率室温一路升高越界模型却没有任何机制阻止这种行为。原因很简单因为我把虚拟储能的SOC递推约束漏掉了。这个坑的本质是功率上下限只刻画了“此刻能调多少”却没有刻画“能持续多久”。如果不约束SOC模型就默认空调集群拥有无限能量储备可以无限期地少用电。加上SOC上下限约束后模型才会在“少用电省下的购电费”和“温度越界带来的惩罚”之间做合理的权衡。这是等效储能聚合模型最重要的一个约束千万不能漏。7.2 初始SOC取值不当导致无解另一个常见问题是初始SOC设得太极端比如直接设成1或0导致优化问题从一开始就不可行。这是因为如果初始SOC等于1意味着初始室温已经在舒适区下限此时如果调度还想继续“充电”温度进一步降低就会违反下限约束但没有可行方向求解器直接报infeasible。我的解决办法是先用一个简单的负荷追踪策略跑一遍基线场景得到自然的室温分布再用这个室温对应的SOC作为初始值。通常初始SOC设定在0.4到0.6之间比较稳妥既留有充电空间也留有放电空间。如果发现无解优先检查初始SOC和SOC终值约束的搭配而不是怀疑模型本身。7.3 舒适度硬约束太紧引入松弛变量和惩罚费用在真实项目里如果空调数量不够、室外温度又极高把温度严格限制在24℃~26℃的硬约束下调度问题很可能无解——因为物理上确实做不到。这时候需要把硬约束软化成带惩罚的软约束。具体做法是引入非负松弛变量ε_1、ε_2改造约束T_room(t) ≤ T_max ε_1(t) T_room(t) ≥ T_min - ε_2(t)然后在目标函数里加惩罚项C_penalty · Σ(ε_1(t) ε_2(t))这样求解器宁可付出少量惩罚费用也不至于整个问题崩溃而且惩罚系数调得越高结果越接近硬约束。我一般把惩罚系数设在购电最高价的1.5到2倍这样一般不会出现温度越界除非极端场景下物理条件真的不允许。7.4 定频空调大功率阶跃带来的振荡如果集群里定频空调占比较高优化出的功率指令如果步进变化太大实际执行时会出现振荡——一批空调同时启停功率曲线抖动房间温度也跟着波浪式波动。这个现象在仿真里不明显但落地时会非常头疼。处理技巧是给聚合功率的变化率加限制|P_AC(t) - P_AC(t-1)| ≤ P_ramp_max·Δt我通常会加这个约束哪怕模型是纯线性规划也能处理。定频空调的功率虽然非连续但加上爬坡约束后等效于在时间尺度上做了平滑既能保证优化可解又让控制指令更贴近实体空调的可执行性。7.5 容量单位错误这类低级但致命的错误调参过程中我踩过最无语的坑是单位搞混。把房间热容C的单位写成W·h/℃计算虚拟储能容量时按kWh使用结果数值差了1000倍导致SOC递推方程每天都在剧烈震荡看起来像代码写错了。在ETP模型里C常用的单位是kWh/℃R常用单位是℃/kW计算出的功率乘以时间才是能量。我在代码里统一把所有参数转换成标幺值或者统一成kWh和kW然后在关键位置加了assert检查assert(abs(E_cap - sum(C_agg) * (T_max - T_min)) 1e-6, Capacity unit mismatch!);这种断言检查在写模型时是很好的护身符能帮你在参数文件被改乱的时候第一时间发现问题。7.6 几个让模型更稳定的实际技巧最后分享三个实测有用的技巧。第一个是给SOC递推方程加一个很小的衰减项。因为房间不可能完全绝热E_cap在长时间尺度上会存在能量泄漏不加衰减会让模型在48小时以上调度中出现SOC漂移。加一个0.001量级的泄漏系数就能很好地抑制这个问题。第二个是求解后用温度约束反查一遍结果。SOC约束本质上等价于温度约束但数值计算误差可能导致SOC在边界上但温度略微越界。我会在求解后把SOC曲线反推成温度曲线画出来跟约束线对比确认物理量是一致的。第三个是手动设定求解器精度参数。Yalmip调用CPLEX时把mipgap设置为0.001就能显著加快求解速度。对于纯线性规划问题CPLEX默认容差往往过于严格适当放松不会影响调度方案的工程可接受度但能把求解时间从十几秒压缩到几秒。这套等效储能聚合模型拿来做微电网经济调度的研究Matlab加Yalmip加商用求解器的组合已经很成熟了。如果你只是复现一个典型日场景按照上面的建模逻辑一步步搭两三天就能跑通如果想往上做滚动优化和实时控制需要把状态更新的接口从离线脚本改成函数化调用再把求解器初始化部分抽出来复用。从我个人经验来看最大的价值并不在代码本身而在于把“空调负荷”从一个固定负荷改写成“动态储能资源”的思维转变——这个模型一旦搭好不只是空调电动汽车、电热水器、冷水机组这些温控负荷都可以沿用同一套框架去建模。遇到具体问题可以沿着这个思路自己扩展比每次都从零开始要快得多。