“融合需求侧虚拟储能系统的楼宇微网优化调度”这个项目听起来像是又一篇把关键词堆在一起的论文标题但真正把它落到Matlab代码里跑通之后我才意识到这里面其实藏着一个很值得展开的工程命题。这个项目做的事情通俗说就是把楼宇里原本“只会耗电”的空调、充电桩、热水设备等柔性负荷通过调度变成一个“看不见的电池”和物理储能一起参与到微网的功率调节里并且用一套完整的Matlab代码把整个优化问题求解出来。对于正在做微网调度相关课题的研究生或者想在企业微网平台上尝试需求侧资源聚合的工程师这套思路都有直接的参考价值。它不是停留在概念层面的科普而是把模型怎么建、约束怎么设、代码怎么组织、结果怎么分析这些实操细节都串在了一起。下面我就从项目拆解、建模思路、代码实现到调试经验一层层把这份工作讲清楚。1. 楼宇微网里的“虚拟储能”到底值多少钱1.1 楼宇微网的基本盘楼宇微网的物理组成说穿了就四块分布式电源最常见的是屋顶光伏、储能装置铅酸、锂电等、可控和不可控负荷以及和外部配电网的联络线。调度中心的任务就是在满足楼宇用能需求的前提下动态决定每一台设备的出力或功率让整个系统在某个目标上最优通常就是经济性最优。但这里面有个很现实的问题物理储能是靠真金白银堆出来的。电池本体、变流器、电池舱、消防、监控哪一样都不便宜。而且电池寿命有限循环次数受制于充放电深度平时调得越猛衰减越快。在楼宇场景下很多项目初期根本舍不得配大容量电池或者配了之后又发现白天光伏大发时电池很快充满了到了晚上却无电可放利用率很低。这个痛点恰恰是需求侧虚拟储能能介入的地方。1.2 虚拟储能为什么“香”虚拟储能的核心思想是把末端用电设备本身具备的调节能力当成一种储能资源来用。空调房间的设定温度可以在舒适区间里浮动相当于有一个“热容量”缓冲充电桩可以错峰充电电热水器可以提前蓄热这些都是时间尺度上的能量搬移。如果把它们的功率灵活性统一聚合并且在优化模型里显式表达成“可充可放的等效SOC”那么调度中心看到的就多了一台不需要花钱买的电池。我一开始做这个方向的时候也很怀疑空调温度稍微浮动几度能有多少调节量后来算了一笔账一个两万平方米左右的办公建筑空调负荷峰值可能在600到1000千瓦如果允许室内温度在一定范围内浮动等效储能容量可以达到几百千瓦时、持续时间1到2小时。这个量级对平抑光伏波动、降低高峰购电很有意义。所以“需求侧虚拟储能”不是一个概念上的噱头而是可以量化参与调度的实际资源。1.3 楼宇里到底有哪些“虚拟储能源”做建模之前先把楼宇里面能利用的资源盘点一下。按调节方式不同我一般分成三类。第一类是温控类负荷包括中央空调、多联机、地源热泵、电采暖等。它们的特点是有热惯性和蓄热介质室内温度不会因为功率突变而立刻变化。给空调功率加一点限制室内温度依然可以维持一段时间这就是“充放电”的空间。第二类是可平移负荷典型代表是充电桩、洗衣机、消毒柜、蓄冷装置。它们的特点是总用电量固定但可以在某个时间窗口内整体挪动只要最终完成就行。这类负荷更像一个“时间可控的功率块”可以把高峰时段的用电量移到光伏多、电价低的时段。第三类是可中断负荷例如部分照明、非关键通风设备。这类负荷在紧急时刻可以被削减一部分功率通常要付出舒适度或服务质量的代价调度中一般作为紧急备选或者合同约定容量来建模。三类资源在调度模型里的表达方式并不一样后面建模章节会详细展开。这里想强调的一点是虚拟储能不是把某一台设备单独建模而是以“聚合资源”的方式纳入优化。这样模型规模可控求解效率高也符合实际上调度系统“只下发总功率指令”的工程习惯。1.4 优化调度要管的几件事楼宇微网优化调度本质上是一个“多时段耦合”的决策问题。因为能量是跨时段转移的今天15点的决策会影响16点甚至晚上的状态。虚拟储能的引入又把原本只关心电池SOC的耦合扩展到空调温度、热水温度、电瓶车充电进度等具有内在时间记忆的状态变量。决策变量包括联络线交换功率、光伏实际出力、储能充放电功率、各虚拟储能单元的充放电功率、可平移负荷的启停时间等。约束包括功率平衡、各设备的功率上下限、SOC转移方程、网络或变压器容量约束、用户舒适度约束等。求解结果就是一份“未来24小时或未来若干小时的设备运行计划表”。那为什么很多项目最终选择在Matlab里实现而不是直接用商业调度软件我的体会是Matlab的优势在于快速搭建和验证算法。你可以把目标函数、约束、求解器调用都写在脚本里随时改参数、换场景、前处理数据。尤其是做科研或者方案对比的小伙伴Matlab几乎是标配。这也就是这个项目标题里专门强调“Matlab代码实现”的原因。2. 融合虚拟储能的优化建模从物理量到数学约束2.1 目标函数怎么设首先要明确目标函数决定了优化会“朝哪个方向跑”。绝大多数楼宇微网项目以运行成本最小为目标成本项包括向电网购电的电费、光伏余电上网的收入负成本、物理储能的损耗折算、需求侧资源调用带来的舒适度损失。写成一个紧凑的数学形式就是min Σ_t [ price_net(t) * P_net(t) - price_sell(t) * P_sell(t) λ_comfort * Σ_i D_i(t) battery_cost(t) ]其中第一部分是购电成本第二部分是售电收益第三部分是各类虚拟储能资源调用产生的舒适度惩罚第四部分是电池寿命损耗项。注意P_net为正代表从电网购电为负代表倒送到电网。在实际项目里我喜欢把目标函数分成两个层次第一层是经济成本最小第二层是在多个可行解之间进一步考虑设备磨损和用户舒适度。这里用“分时电价”来驱动虚拟储能充放是最直接的做法峰时段让虚拟储能“放电”比如降低空调功率或延迟充电谷时段让虚拟储能“充电”把温度提前降下来或预冷。2.2 虚拟储能的等效SOC模型把需求侧资源抽象成虚拟储能需要定义一组和物理储能几乎一样的参数容量上限、功率上限、自损率、初始能量、末态能量。对于温控负荷一个典型的等效SOC可以表示为房间与用户设定温度之间的偏差或蓄热量。这里我给一个温控负荷聚合模型示例。设定房间室内温度为T_in设定温度范围为[T_min, T_max]等效SOC定义为SOC_v(t) (T_in(t) - T_min) / (T_max - T_min)。这样当温度处于下限时SOC为0处于上限时SOC为1。空调功率P_HVAC和热平衡之间的关系用一个一阶RC等效热参数模型表示T_in(t1) T_in(t) * e^(-Δt/τ) (T_out(t) Q_gain(t) * R P_HVAC(t) * R) * (1 - e^(-Δt/τ))其中τ R * C是房间时间常数R是热阻C是热容Q_gain是内部得热。从工程角度可以直接把上面的非线性指数项在一个调度周期内近似为常系数写成线性化状态方程。这样就把“空调功率影响温度变化”的耦合转换成类似储能的线性转移约束在Matlab中用矩阵迭代即可表达清楚。2.3 温度舒适度的边界与惩罚虚拟储能最有意思的地方在于它的容量大小并不是固定值而取决于用户愿意把舒适度让出多少。温度边界越宽等效储能容量越大调节能力越强但用户体感变差。所以在模型里我不建议把温度上下限设成一个绝对硬约束而是做成“硬边界约束软惩罚”。具体做法是引入松弛变量eps_lo和eps_hi让室内温度可以在极端情况下稍微越界同时在目标函数中惩罚越界量。这样无论调度场景多极端求解器都能给出结果不会因为某一天冷空气来袭直接无解。这个细节在很多代码里容易省略但实际运行起来非常关键。2.4 调度周期与步长选择的工程考量调度周期和步长直接决定矩阵维数和计算速度。楼宇微网中光伏出力和用户负荷的波动通常以分钟级为主为了捕捉峰谷变化我推荐使用15分钟步长调度周期24小时即T 96个时段。有人会为了省时间用1小时步长但这样会把温度变化和虚拟储能充放电过程估得太粗糙可能高估储能能力。举个例子一台空调在1小时内可以有较大功率调节但如果只按整点建模可能就忽略了15分钟尺度的削峰潜力。相反如果步长缩到5分钟计算规模扩大3倍而且对预测数据精度的要求也大幅提高实际收益有限。所以“96时段”通常是精度和计算量之间的平衡点。3. Matlab代码实现从搭架到求解手把手拆解3.1 代码结构怎么搭这套代码我在组织时完全按照“数据—参数—模型—求解—分析”五段式组织原因很简单优化调度代码最容易犯错的地方不是算法而是数据口径不一致。代码结构建议如下数据生成与输入定义日负荷曲线、光伏出力曲线、分时电价、室外温度、设备参数。基础参数设置设置步长、总时段数、电池容量或功率、虚拟储能参数。约束矩阵构建用矩阵形式表达功率平衡、SOC递推、温度递推等约束组装成标准形。求解器调用调用Matlab优化工具箱或者外部求解器设置求解选项。结果输出把解还原成功率、SOC、温度等物理量绘图并保存表格。这样的好处是以后换一栋楼的数据只需要改第一步和第二步后面模型和求解代码基本不用动。项目中期我甚至把这套模块化的脚本封装成了几个函数每个函数只负责一个小环节调试起来一头雾水的时候能快速定位到是哪个矩阵不对、哪个参数没传对。3.2 建模方式与求解器选择的建议Matlab下面做优化建模无非几种路线。最简单的是直接用优化工具箱的linprog或者quadprog把问题写成标准形式。缺点是约束多、变量多的时候手工拼接矩阵很痛苦尤其是有0-1变量时需要混合整数线性规划如果用intlinprog矩阵必须拼得极其仔细。更舒服的方式是利用CVX或Yalmip这类建模框架用接近数学表达式的语法直接描述目标函数和约束然后让建模框架调用底层求解器。如果本地只有Matlab我一般先用quadprog或者intlinprog跑通再考虑是否需要引第三方求解器。项目展示或者课程作业用开源求解器就够了如果要做大规模算例对比可以接更专业的求解器但那些主要是性能上的差异模型本身不变。需要注意的一点是调度模型如果含有0-1变量比如可平移负荷的启停问题会变成MILP。MILP的求解时间对整型变量个数非常敏感我通常会把同一类型的设备先聚合宁可多建一个“聚合变量”也不让20个充电桩各自出现20组0-1变量。这一步能省下大量求解时间而且结果差距非常小。3.3 核心约束的Matlab实现细节下面给一段核心约束的示意代码。为方便展示这里假设已经用变量向量化方式定义了各时段的决策变量代码是伪代码风格实际操作中需要配合索引转映射。% 假设T为时段数P_pv、P_load、P_net等均为T维变量 % P_net为正购电P_sell为正上网两者不能同时为正 % 功率平衡P_net P_pv P_bat_d - P_bat_c P_virtual P_load % 写成一组线性约束配合矩阵Aeq_beq Aeq []; beq []; % 1) 节点功率平衡约束 % 这里仅示意单时段实际需扩展到T维每一时段一行 Aeq [Aeq; 1 1 1 -1 1]; % 对应变量 [P_net, P_pv, P_bat_d, P_bat_c, P_virtual] beq [beq; P_load_total]; % 2) 虚拟储能SOC递推 % SOC_v(t1) SOC_v(t) - P_virtual(t)/(E_v_max) * dt eta_self * SOC_v(t) % P_virtual为正表示放电为负表示充电 for t 1:T-1 % 构造对应的转移关系这里按矩阵形式追加 % 行向量在对应变量位置填系数右侧为0 Aeq [Aeq; ...]; beq [beq; 0]; end % 3) 室内温度递推 % T_room(t1) A_te * T_room(t) B_te * (P_HVAC(t) Q_gain) % 通过线性化得到T维的等式约束这里最容易被忽略的点是功率平衡约束里的下标对齐。不同调度时段之间必须严格对应尤其是在把变量拼接成一个大向量时索引错一位就会导致全盘错误。我调试时常用的技巧是先固定所有变量为一个已知可行解然后把这组值代入约束矩阵检查Aeq*x是否等于beq如果不等马上能判断是哪一行错了。3.4 参数设置与场景设计实例为了让代码跑起来有可比性我设计了一个基准场景某典型办公建筑屋顶光伏容量200千瓦锂电池容量300千瓦时、功率100千瓦空调峰值负荷500千瓦楼宇非空调基础负荷为200到300千瓦采用峰平谷分时电价调度步长15分钟全天96个时段。光伏出力曲线我采用典型晴天的形状峰值出现在12点30分左右峰值功率约160千瓦。负荷曲线分为两部分固定负荷和空调负荷。固定负荷工作时间内维持高位空调负荷则与室外温度正相关。室外温度数据就直接用前一天的温度曲线用一阶RC模型计算室内温度。关键参数可以用下面这个表格来整理参数名称数值说明光伏容量200 kW屋顶分布式光伏电池容量300 kWh磷酸铁锂物理储能电池功率上限100 kW单时段充放电功率约束空调峰值功率500 kW楼宇空调负荷峰值基础负荷范围200~300 kW非空调负荷温度舒适区间20~26 ℃白天办公时段强制范围调度步长15 min全天96个时段分时电价峰1.2 / 平0.8 / 谷0.4 元/kWh典型工商业电价虚拟储能参数这里要重点说明一下空调聚合等效容量可以理解为室内温度从T_min移到T_max所对应的蓄热量如果温差为4℃空气体积约6万立方米等效热容C约为60000 m³ * 1.2 kg/m³ * 1.005 kJ/(kg·K) ≈ 72.36 MJ折合约20 kWh。这个值看起来不是特别大但注意它是“每度温差”的能量如果允许4℃浮动对应80 kWh已经很可观了。3.5 结果输出与可视化的几个关键图调度结果的呈现方式直接决定了方案能不能说服别人。常规画图包括以下几张第一张是功率平衡曲线堆叠图把光伏出力、负荷、储能充放电、虚拟储能充放电、电网交换功率按时间堆叠在一张图上可以直观看到削峰填谷的效果第二张是电池和虚拟储能的SOC曲线能看出两者协同充放电的时序第三张是室内温度曲线验证温度边界约束是否被突破。我在做对比分析时通常会跑三个场景场景A是无虚拟储能、只有电池场景B是有虚拟储能、无电池场景C是电池加虚拟储能联合。这样就能把“虚拟储能单独的价值”和“两者协同的价值”都量化出来。实测下来只靠虚拟储能也能把高峰时段购电功率压低大约10%到15%配合电池一起调度整个系统的峰谷差能进一步降低经济效益比单独配电池更平滑。4. 常见问题与避坑经验4.1 虚拟储能的SOC为什么会越界这是我自己踩过的第一个坑。刚开始用温度模型替换虚拟储能SOC时没设置末态约束结果优化算法为了让下午的电费最小把虚拟储能的SOC在周期末压到最低值下一轮调度又得从0开始导致前后两个调度周期之间出现能量“断点”。解决办法有两个一是加末态约束强制SOC_v(T)等于SOC_v(0)二是在目标函数里增加末态SOC的惩罚让算法自动选择一个更可持续的收尾状态。4.2 室内温度约束过紧导致无解有段时间我为了追求用户舒适度把全天温度都设在20到26℃之间结果冬季典型日光伏出力不足温度约束无论如何也满足不了求解器直接报infeasible。后来加了温度松弛变量把硬约束改成“尽量在舒适区间”并在目标函数里加入松弛惩罚问题立刻解决。经验是舒适度约束要有时段性比如夜间非工作时段允许更宽的温度范围白天办公时段才严格限温。4.3 时间步长不一致导致的数据错位因为光伏数据、负荷数据、电价数据可能来自不同渠道在时间分辨率上经常不统一有的人直接一整行数据读进来也不检查时间轴结果曲线对不上。我建议把所有输入数据统一插值到同一个时间轴再通过时间戳对齐而不是靠行号硬拼。这个看似小的问题在实际中能耗费大量调试时间。4.4 求解时间过长怎么办如果模型里逐台设备建模几十台空调和几十个充电桩的0-1变量会让你等很久。我的做法是聚合分组按类型、按楼层、按朝向把热特性相近的房间聚合为几个虚拟储能组每组只占一个变量。这样计算时间可以从几十秒降到几秒而调度结果差异通常不超过2%。对于楼宇微网来说这种误差完全在可接受范围内。4.5 验证模型正确性的一些技巧最后分享一个我觉得特别有用的验证方法先把所有虚拟储能相关约束的上下界放到无限宽让模型退化成“纯电池基础负荷”的传统微网调度跑通后再逐步缩紧虚拟储能的边界观察调度结果是否按预期变化。这样可以把问题拆解成一个个小步骤排错。另外强烈建议用一组已知的最优解数据做回归测试每次改代码后跑一遍防止自己把之前的正确逻辑改坏。做这个项目前我一直觉得“虚拟储能”是个广告词真正把它写进优化模型、跑出有说服力的曲线之后才意识到这件事的含金量。它本质上是在重新定义负荷以前负荷是必须满足的“变量”现在负荷变成了可以调节的“资源”。这种思维转变对搞微网调度的人特别重要。最后再分享一个小技巧虚拟储能的等效参数会随室外温度和建筑使用强度变化不要一劳永逸地用一个固定值。我建议在调度程序里每隔几个时段根据实测温度、实测功率重新校准一次等效SOC和容量做“滚动修正”。这样模型在一天内始终贴近实际比单纯依靠开环预测要稳妥得多。