尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

虚拟储能赋能的楼宇微网优化调度:Matlab实现与效益分析

虚拟储能赋能的楼宇微网优化调度:Matlab实现与效益分析 1. 楼宇微网为什么要打“虚拟储能”这张牌1.1 传统楼宇微网调度的三个老毛病我在电力系统优化调度这块做了不少年头接触过的楼宇微网项目少说也有十几个。坦白讲早期大部分项目的调度策略都很粗放光伏出力大就多用点电价高就少买点蓄电池到了低谷电价就充、高峰电价就放。这套逻辑看着合理实际跑起来问题不少。第一个棘手的问题是负荷刚性太强。楼宇里的空调、照明、插座负荷跟着人的作息走早晨上班、午间午休、下午办公负荷曲线几乎是模板刻出来的。你要是调度员面对这种“动不了”的负荷手里真正能调的牌只有蓄电池和光伏自由度非常有限。第二个问题是蓄电池承担了太多不该它承担的活。很多楼宇微网项目为了削峰填谷把电池的充放电次数排得非常满结果电池寿命衰减得很快。我见过一个项目磷酸铁锂电芯用了一年多容量就掉了将近15%运维成本直接吃掉了一半的峰谷套利收益。电池不当钱用调度策略做得再漂亮也是纸面富贵。第三个问题也是很多人忽略的——负荷并不是完全不可调的。空调设定温度往上抬1℃电热水器温度下限从60℃降到50℃整栋楼在1小时内能腾出的容量非常可观。但这些潜力传统调度模型根本看不见因为它们把负荷当成一个固定数字塞进等式没有把负荷背后的物理过程制冷、制热、蓄能建模进系统。1.2 虚拟储能不是电池却干着电池的活这里就要引出“虚拟储能”的概念了。虚拟储能的核心思路很简单建筑物本身的热质量、空调系统的蓄冷能力、热水器的蓄热能力本质上就是一个天然的“储能池”。你把室内温度从26℃预冷到22℃跟把蓄电池从20%充到80%在数学上是同构的——都是在某个时间段内把能量“存”起来在需要的时候再“放”出来。区别在于蓄电池存的是电虚拟储能存的是热/冷量蓄电池有明确的SOC荷电状态虚拟储能也有自己的等效SOC蓄电池有充放电功率上限虚拟储能受限于制冷/制热功率和温度舒适度边界。把这种物理过程抽象成储能模型之后楼宇微网调度的自由度一下子就上来了。以前只有一块电池能调度现在空调是一块“虚拟电池”热水器是另一块“虚拟电池”楼宇的墙体地板是第三块“虚拟电池”。调度员手里有三四块储能可用削峰填谷和光伏消纳的难度会大幅下降。1.3 本文要解决的具体问题这篇文章要做的就是把“需求侧虚拟储能”这套思路落到楼宇微网的优化调度模型里并且给出完整的Matlab实现方案。我会从虚拟储能的物理建模讲起逐步推到数学优化模型的建立再到YALMIP工具箱下的求解代码最后一并给出典型场景下的调度结果分析。整个链路走完你应该能自己搭出一套可以跑的楼宇微网优化调度程序。有一点先说明白这套实现我走的是“确定性混合整数线性规划MILP 日前调度”的路线这也是工程落地里最常用、最稳妥的方案。光伏出力和负荷曲线用预测值给做24小时滚动优化。至于更复杂的随机优化、鲁棒优化属于后续扩展方向文末我会提一下思路。2. 虚拟储能建模从热力学物理量到等效储能状态2.1 楼宇热容模型把墙体变成“蓄水池”要建模虚拟储能第一步是把楼宇热动态过程写成能放进优化模型的状态方程。这里我用的是楼宇热容等效模型也叫一阶RC等效热参数模型工程上应用最广精度足够又不会把模型复杂度撑爆。模型的核心关系式是这样的[ C_{b}\frac{dT_{in}}{dt} \frac{T_{out} - T_{in}}{R_{b}} Q_{load} \eta_{HVAC}P_{HVAC} ]用大白话解释一下(C_b) 是整栋楼宇的等效热容相当于楼宇这个“热池子”能装多少热量的能力单位是kWh/℃(R_b) 是墙体围护结构的等效热阻表示室内外热量交换的阻力单位是℃/kW(T_{in})、(T_{out}) 分别是室内外温度(Q_{load}) 是室内人员、设备、照明等散热量(P_{HVAC}) 是空调的耗电功率(\eta_{HVAC}) 是空调的制冷能效系数你可以理解为每消耗1kWh电能从室内搬走多少kWh热量。离散化之后这个方程变成[ T_{in}(t1) T_{in}(t) \frac{\Delta t}{C_{b}R_{b}}(T_{out}(t) - T_{in}(t)) \frac{\Delta t}{C_{b}}Q_{load}(t) - \frac{\eta_{HVAC}\Delta t}{C_{b}}P_{HVAC}(t) ]注意最后一项前面的符号制冷工况下空调运行是给室内“减热量”所以是负号。如果做的是采暖场景符号要反过来。很多初写这个模型的同学容易在正负号上栽跟头我后面会再强调。这个式子做一次简单的移项就能看见虚拟储能的本质空调功率 (P_{HVAC}) 的变化会直接影响室内温度 (T_{in}) 的升降而室内温度允许在一个舒适区间内波动比如22℃~26℃这个温度波动的范围就是可调节的热容量也就是“虚拟储能”的容量边界。2.2 空调负荷的虚拟储能SOC推导有了热动态方程下面正式定义虚拟储能的SOC。参考电池SOC的定义方式我们先把热量形式的储能折算为电量形式。我习惯用这样一个思路给定一个室内参考温度 (T_{ref})通常取舒适区间中点比如24℃把虚拟储能的等效能量定义为[ E_{v}(t) \frac{C_{b}}{\eta_{HVAC}}(T_{in}(t) - T_{ref}) ]这里 (\eta_{HVAC}) 把热量折算回电量因为空调消耗的是电我们关心的是电量的腾挪空间。(T_{in} T_{ref}) 时 (E_{v} 0)表示室内温度高于参考点有“多余的热量”在室内对制冷场景而言这相当于储能“多存了一些冷量”。严格从调度角度看更直观的做法是用相对量定义虚拟储能SOC[ SOC_{v}(t) \frac{T_{max} - T_{in}(t)}{T_{max} - T_{min}} \times 100% ]温度下限 (T_{min}) 对应SOC100%室内最冷冷量存满温度上限 (T_{max}) 对应SOC0%室内最热冷量放空。这样定义的好处是和电池SOC的语义完全一致约束条件写起来直观结果分析也方便。空调虚拟储能的充放电功率可以定义为[ P_{v,ch}(t) \max(0, \eta_{HVAC}P_{HVAC}(t) - \eta_{HVAC}P_{HVAC,base}(t)) ] [ P_{v,dis}(t) \max(0, \eta_{HVAC}P_{HVAC,base}(t) - \eta_{HVAC}P_{HVAC}(t)) ]其中 (P_{HVAC,base}) 是维持参考温度所需的基准空调功率。空调功率大于基准功率就是在给虚拟储能“充电”——比如午后电价高之前提前把室内预冷到低温空调功率小于基准功率就是在“放电”——比如电价尖峰时段少开空调让室内温度在舒适区间内缓慢回升。2.3 热水器负荷第二块“蓄热池”楼宇里除了空调电热水器是另一大类可调温控负荷也是虚拟储能的重要来源。热水器的热动态模型和空调类似只是热源从空气变成了水箱里的水[ C_{w}\frac{dT_{w}}{dt} \eta_{w}P_{w} - k_{w}A_{w}(T_{w} - T_{amb}) - \dot{m}{w}c{p}(T_{w} - T_{in}) ]等号右边第一项是电加热功率第二项是水箱表面散热损失第三项是热水使用带走的热量热水出水、冷水补入造成的热损失。(C_{w}) 是水箱等效热容(T_{w}) 是水箱温度(T_{amb}) 是环境温度(\dot{m}_{w}) 是热水流量。热水器虚拟储能的SOC定义为[ SOC_{w}(t) \frac{T_{w}(t) - T_{w,min}}{T_{w,max} - T_{w,min}} \times 100% ]热水温度上限 (T_{w,max}) 由安全和设备限制决定一般不超过65℃下限 (T_{w,min}) 由用户舒适度决定比如45℃低于这个温度洗澡体验会很差。热水器的调度逻辑很有意思在电价低谷或光伏出力高峰时把水箱加热到较高温度——“充电”在电价高峰时段水箱自然散热供热水加热棒少开甚至不开——“放电”。由于水箱保温性能好这种操作的效率损耗往往很低比电池的充放电损耗还小。2.4 三种虚拟储能资源的聚合与调度边界真实楼宇的虚拟储能资源通常不止空调和热水器两种。建筑围护结构本身的蓄热能力、蓄冷空调系统的冰蓄冷能力、电动车充电桩的智能充电策略都算虚拟储能的组成部分。把这些资源聚合到统一框架下的关键是给每类资源定义一套标准参数等效容量上限 (E_{max})、等效容量下限 (E_{min})、最大充放电功率 (P_{max})、充放电效率 (\eta)、SOC递推公式。有了这套参数虚拟储能在优化模型里和真实电池的处理方式几乎一致这也是“虚拟”二字的含义所在——它的调度语义和电池相同只是物理载体不同。调度边界需要注意以下几点空调虚拟储能不能把室内温度长期顶在舒适区间边界上否则用户体感会很差。实际工程中往往会在舒适区间内部再设一个“调度死区”比如22℃~26℃是硬边界23℃~25℃是软边界调度尽量在软边界内运行。热水器虚拟储能的放能过程受热水使用规律影响很大工作日早高峰用水量大、午后小、晚间中等这些规律要提前从历史数据里提取。楼宇围护结构蓄热的时间常数非常长常常是6~12小时这意味着今天下午预存的热量要到后半夜才完全释放。跨日调度问题需要在滚动优化中重点处理否则容易在日边界处出现SOC错位。3. 优化调度数学模型目标函数与约束怎么落3.1 决策变量与时间粒度的选择建模之前先明确调度尺度。我做的楼宇微网调度项目时间粒度基本都用1小时优化时域24小时这是日前调度的标配。如果楼宇规模不大、负荷波动平缓15分钟粒度更精细但求解时间和数据要求都会上升前期调试阶段不建议一上来就上小粒度。决策变量分两组。连续变量包括从电网购电功率 (P_{buy}(t))、光伏上网功率 (P_{sell}(t))、蓄电池充放电功率 (P_{ess,c}(t)/P_{ess,d}(t))、蓄电池SOC (SOC_{ess}(t))、空调功率 (P_{HVAC}(t))、室内温度 (T_{in}(t))、热水器功率 (P_{w}(t))、热水温度 (T_{w}(t))。0-1整数变量包括蓄电池充电状态标志 (u_{c}(t)) 和放电状态标志 (u_{d}(t))用于防止电池同时充放电。只要模型里出现这种互斥状态0-1变量就躲不掉这也是问题最终是MILP而非纯LP的直接原因。3.2 目标函数四类成本怎么权衡目标函数设计上我倾向于在基础购电成本之上叠加多个成本项让模型能自行权衡每种手段的代价。典型的目标函数长这样[ \min \sum_{t1}^{24} \left[ c_{buy}(t)P_{buy}(t)\Delta t - c_{sell}(t)P_{sell}(t)\Delta t \right] ] [\sum_{t1}^{24} c_{deg}\left(P_{ess,c}(t) P_{ess,d}(t)\right)\Delta t ] [\sum_{t1}^{24} \left( \alpha_{v}(T_{in}(t) - T_{set})^{2} \beta_{v}(T_{w}(t) - T_{w,set})^{2} \right) ]第一项是购电成本减去售电收益这是最基础的运行成本第二项是电池充放电循环损耗成本 (c_{deg}) 是单位电量损耗折算成本需要根据电池型号和循环寿命曲线标定第三项是舒适度惩罚项目的是防止模型为了省钱把室内温度顶到舒适区边界。注意温度惩罚是二次型但如果想把问题保持为线性可以把它分段线性化——我在Matlab里用的是分段线性逼近因为YALMIP处理线性约束更稳定求解速度也快不少。有人会问为什么不把虚拟储能的“充放电损耗”也放进去因为空调和热水器的效率已经在热动态方程里了能源转换关系天然会体现在物理约束中不需要额外加成本项。这也是虚拟储能相对真实电池的一个优势——系统不会因为“舍不得充放损耗”而闲置这块储能。3.3 约束条件功率平衡、设备约束与舒适度优化模型的约束条件可以分成四块来看缺一不可。第一块是功率平衡约束这一条是微网模型的脊梁骨[ P_{buy}(t) P_{pv}(t) P_{ess,d}(t) P_{load}(t) P_{ess,c}(t) P_{HVAC}(t) P_{w}(t) P_{sell}(t) ]注意我把空调和热水器从常规负荷里单拎出来了因为它们现在是可调变量而不是固定参数。(P_{load}(t)) 只包含照明、插座等刚性负荷。这里有个小经验光伏出力预测值 (P_{pv}(t)) 可以先按“优先消纳”处理即 (P_{pv}(t)) 要么自用要么上网不作为优化变量简化模型的同时也贴近光伏优先消纳的实际运行习惯。第二块是蓄电池建模这一块看着简单坑最多[ SOC_{ess}(t1) SOC_{ess}(t) \frac{\eta_{c}P_{ess,c}(t)\Delta t}{E_{ess}} - \frac{P_{ess,d}(t)\Delta t}{\eta_{d}E_{ess}} ] [ SOC_{ess,min} \le SOC_{ess}(t) \le SOC_{ess,max} ] [ 0 \le P_{ess,c}(t) \le u_{c}(t)P_{ess,c,max}, \quad 0 \le P_{ess,d}(t) \le u_{d}(t)P_{ess,d,max} ] [ u_{c}(t) u_{d}(t) \le 1 ]最后这个互斥约束非常重要。如果不加很多求解器会给出一个在数学上成立但物理上荒谬的结果同一时刻电池既充电又放电两部分功率抵消表面上SOC不变但目标函数里的损耗成本和约束条件可能反而“受益”。加了 (u_{c} u_{d} \le 1) 之后两个状态被物理隔离这才是有效的电池模型。另外SOC的初值和终值要注意。日优调度里我习惯设置 (SOC_{ess}(24) SOC_{ess}(0))也就是终值等于初值。这是为了保证当天调度没有“透支”电池结果对比起来才公平。实际工程中如果第二天有明确的调度计划可以适当放开这个等式。第三块是虚拟储能约束也就是空调热动态、热水器热动态、温度舒适度区间。这部分在上一节已经写了核心公式这里只补充一条热水器SOC和空调SOC的终端约束也建议加上避免日内调度把热量“吃光”后不还——第二天没法正常运行。如果做的是滚动优化终端约束在一定程度上可以放宽因为每个滚动窗口会不断校正。第四块是并网交互约束。楼宇微网和电网的交换功率通常有上限变压器容量就是天然的限制[ 0 \le P_{buy}(t) \le P_{buy,max}, \quad 0 \le P_{sell}(t) \le P_{sell,max} ]售电功率上限再补充说明一下很多地方分布式光伏接入有容量限制超过限制的功率不允许上网这就逼着微网内部想办法消纳。这时候虚拟储能的价值就非常明显了——光伏大发时段空调启动预冷把电量“变成”室内冷量存起来等光伏出力下降后再释放一个简单的操作就能把原本可能被限电的清洁能源用起来。3.4 从确定性模型到滚动优化的扩展思路上面这套模型是典型的确定性日前优化它的局限性在于把光伏出力和负荷都当成已知量。实际光伏出力的预测误差往往在10%~20%之间这对调度结果的可靠性影响不小。工程上最常用的改进方案是模型预测控制MPC滚动优化不用一步把24小时全部定死而是每1小时滚动一次每次只优化未来4~6小时的调度计划只执行第一个时段的决策到下一个时段用最新的光伏和负荷实测数据重新优化。代码实现上MPC的核心就是把上面的模型包在一个for循环里每个循环更新预测数据、前移时间窗口、重新求解。滚动优化的好处是抗扰动能力强代价是计算时间增加。好在这类MILP模型规模不大用CPLEX或Gurobi求解单次通常只需要几秒到几十秒完全满足1小时滚动周期的要求。4. Matlab代码实现YALMIP建模与求解全过程4.1 代码整体结构与文件职责Matlab实现部分我强烈建议不要把代码全堆在一个脚本里。调度模型涉及的参数、数据、建模、求解、绘图环节太多拆分成模块化的文件才是可维护的正路。我的代码结构长这样main.m % 主入口装配参数、建模、求解、绘图 load_data.m % 加载典型日负荷/光伏/电价数据 init_params.m % 初始化设备参数、温度参数、求解器设置 build_model.m % 构建优化模型变量、目标、约束 solve_model.m % 调用YALMIP求解MILP plot_results.m % 绘图功率平衡图、SOC曲线、温度曲线只要保证数据文件里的变量名和建模文件里的变量名一致这套结构可以很自然地扩展到不同楼宇场景——民用楼宇、商业综合体、数据中心、学校换数据就能跑。4.2 基础数据初始化初始化参数部分我把关键参数按类别列出来实际代码里就是一个巨大的struct方便管理% 设备容量 param.ess_cap 100; % 蓄电池容量 kWh param.ess_pmax 25; % 蓄电池最大充放电功率 kW param.ess_eta_c 0.95; % 充电效率 param.ess_eta_d 0.95; % 放电效率 param.ess_soc_min 0.2; % 电池SOC下限 param.ess_soc_max 0.9; % 电池SOC上限 % 楼宇热参数 param.R_b 0.5; % 等效热阻 ℃/kW param.C_b 15; % 等效热容 kWh/℃ param.eta_hvac 3.2; % 空调制冷能效比 EER param.T_min 22; % 室内温度下限 ℃ param.T_max 26; % 室内温度上限 ℃ param.T_ref 24; % 参考室内温度 ℃ % 热水器参数 param.C_w 4.8; % 水箱等效热容 kWh/℃ param.eta_w 0.95; % 电热转换效率 param.T_w_min 45; % 热水温度下限 ℃ param.T_w_max 60; % 热水温度上限 ℃ % 电价(分时电价CNY/kWh) param.price_buy [0.56*ones(1,8), 1.16*ones(1,6), 0.86*ones(1,6), 1.16*ones(1,2), 0.56*ones(1,2)]; param.price_sell 0.35; % 上网电价这几组参数要着重检查热容的单位。很多初建的模型结果异常最后查下来都是 (C_b) 数量级错了。住宅楼宇等效热容通常在每平米0.02~0.05 kWh/(℃·m²)一个5000平米的楼 (C_b) 大致在100~250 kWh/℃我代码里给了个偏小的15是模拟小型单体建筑实际接入真实数据时务必按建筑参数重新标定。4.3 用YALMIP定义变量、目标与约束YALMIP是Matlab下最主流的优化建模工具箱语法近似数学公式写起来非常顺手。决策变量的定义是这样的% 时间轴 T 24; dt 1; % 连续决策变量 P_buy sdpvar(1, T); % 购电功率 P_sell sdpvar(1, T); % 售电功率 P_ess_c sdpvar(1, T); % 电池充电功率 P_ess_d sdpvar(1, T); % 电池放电功率 SOC_ess sdpvar(1, T1); % 电池SOC (T1个时刻) P_hvac sdpvar(1, T); % 空调功率 T_in sdpvar(1, T1); % 室内温度 (T1个时刻) P_w sdpvar(1, T); % 热水器功率 T_w sdpvar(1, T1); % 热水温度 (T1个时刻) % 0-1变量 u_c binvar(1, T); % 电池充电状态 u_d binvar(1, T); % 电池放电状态这里有个关键细节温度和SOC的状态变量维度是T1而不是T。因为递推关系式里 (x(t1) x(t) ...) 需要T1个时刻的状态来承接T个时段的控制量。这个错位如果没处理好YALMIP会直接报维度不匹配或者更隐蔽地约束里漏掉最后一个时刻的边界条件。目标函数的定义% 购电成本 - 售电收益 objective sum(param.price_buy .* P_buy) * dt ... - sum(param.price_sell .* P_sell) * dt; % 电池损耗成本 c_deg 0.02; % 单位电量损耗成本 CNY/kWh objective objective c_deg * sum(P_ess_c P_ess_d) * dt; % 舒适度惩罚分段线性化 comfort_penalty 0.2 * (sum(T_in(1:T) - param.T_ref) sum(T_w(1:T) - param.T_w_ref)); objective objective comfort_penalty;说明一下室温和水温的舒适度惩罚项我按线性化处理了和前面数学模型里的二次型不完全等价但工程上够用。追求严格二次型的同学可以在YALMIP里用quadratic对象不过求解时间会有明显增加。约束的建模把数学式子直接翻译成代码Constraints []; % 功率平衡约束 for t 1:T Constraints [Constraints, P_buy(t) P_pv(t) P_ess_d(t) ... P_load(t) P_ess_c(t) P_hvac(t) P_w(t) P_sell(t)]; end % 电池SOC递推 for t 1:T Constraints [Constraints, SOC_ess(t1) SOC_ess(t) ... param.ess_eta_c * P_ess_c(t) * dt / param.ess_cap ... - P_ess_d(t) * dt / (param.ess_eta_d * param.ess_cap)]; end % 电池SOC上下限 Constraints [Constraints, param.ess_soc_min SOC_ess param.ess_soc_max]; % 电池充放电互斥 for t 1:T Constraints [Constraints, 0 P_ess_c(t) u_c(t) * param.ess_pmax]; Constraints [Constraints, 0 P_ess_d(t) u_d(t) * param.ess_pmax]; Constraints [Constraints, u_c(t) u_d(t) 1]; end % 空调热动态约束 for t 1:T Constraints [Constraints, T_in(t1) T_in(t) ... (dt / (param.C_b * param.R_b)) * (T_out(t) - T_in(t)) ... (dt / param.C_b) * Q_load(t) ... - (param.eta_hvac * dt / param.C_b) * P_hvac(t)]; Constraints [Constraints, param.T_min T_in(t1) param.T_max]; end % 热水器热动态约束 for t 1:T Constraints [Constraints, T_w(t1) T_w(t) ... (param.eta_w * dt / param.C_w) * P_w(t) ... - (param.k_w * param.A_w * dt / param.C_w) * (T_w(t) - param.T_amb) ... - (m_dot_w(t) * param.cp * dt / param.C_w) * (T_w(t) - param.T_in_water)]; Constraints [Constraints, param.T_w_min T_w(t1) param.T_w_max]; end % 边界条件 Constraints [Constraints, SOC_ess(1) param.ess_soc_init]; Constraints [Constraints, SOC_ess(T1) param.ess_soc_init]; Constraints [Constraints, T_in(1) param.T_ref]; Constraints [Constraints, T_in(T1) param.T_ref]; Constraints [Constraints, T_w(1) param.T_w_ref]; Constraints [Constraints, T_w(T1) param.T_w_ref];注意代码里for循环写约束的方式比较直观初学者容易看懂。楼宇规模不大时循环没问题如果时域扩展到96点或模型更大建议改用矩阵化约束写法求解性能会有质的提升。4.4 求解器选型与求解参数模型建好了求解这步相对简单% 求解器设置 options sdpsettings(solver, cplex, verbose, 1, ... showprogress, 1, cplex.mip.tolerances.mipgap, 0.001); % 求解 sol optimize(Constraints, objective, options); % 结果检查 if sol.problem 0 disp(求解成功); else disp([求解失败: , sol.info]); end求解器方面YALMIP支持CPLEX、Gurobi、MOSEK、甚至免费的SCIP和CBC。楼宇微网MILP模型规模不大免费求解器通常也能扛住但如果你要做滚动优化或蒙特卡洛分析CPLEX和Gurobi的速度优势会非常明显。没有商业许可证的同学我可以推荐一个折中方案先在笔记本电脑上用免费求解器把模型调通正式跑仿真时再换商业求解器。关于MIP调参mipgap是最值得关注的一个参数。默认值往往是0.01%也就是0.0001对这种日调度模型来说太苛刻了求解时间会白白翻倍。设成0.1%即0.001结果几乎不变速度能快不少。这个经验是我反复对比过的建议直接照抄。5. 典型楼宇场景算例优化结果与收益分析5.1 算例参数与典型日数据为了展示模型效果我搭了一个典型商业楼宇微网算例。楼宇面积6000平方米屋顶光伏装机80kW蓄电池容量100kWh最大功率25kW。空调系统额定功率120kWEER取3.2。电价采用典型的分时电价结构尖峰时段1.16元/kWh平段0.86元/kWh谷段0.56元/kWh。天气数据方面夏季典型日室外最高温36℃最低温25℃太阳辐射强的结果是光伏出力在午间12:00~14:00达到峰值70kW左右。楼宇基础负荷照明、插座、电梯呈明显双峰特性早峰出现在9:00~11:00午峰出现在14:00~16:00晚高峰出现在19:00~21:00。5.2 优化前后对比购电成本、峰谷转移、电池损耗我把这个算例跑了两组一组是基准场景空调和热水器按固定设定运行只有电池参与调度称作“无虚拟储能”另一组是完整模型空调和热水器作为虚拟储能参与调度称作“融合虚拟储能”。结果对比见下表指标无虚拟储能融合虚拟储能日购电成本元2683.52217.2日购电量kWh3128.42815.6峰值购电功率kW214.5178.2电池日循环次数等效1.1次0.7次空调日耗电量kWh456.7483.9光伏日消纳率%91.398.6单看这个结果有几个值得注意的信号成本下降了约17.4%这个幅度的提升在真实微网项目里非常可观。省钱的主要来源不是单纯少用电而是把用电时间挪到了谷时段——空调午后预冷、热水提前加热相当于把峰值负荷“平移”到了电价低的时段。峰值购电功率下降了36kW这对需量电费敏感的工商业用户来说好处是双份的。电池循环次数下降了这是虚拟储能另一个隐藏价值。空调和热水器分担了一部分削峰填谷的任务电池不用那么频繁地充放电寿命自然变长了。这块收益虽然没有直接体现在日运行成本里但从资产折旧角度看每个月的维护成本能省不少。空调日耗电量反而增加了27kWh这个现象可能让不少人疑惑虚拟储能不是节能技术是移能技术。空调预冷过程中会有少量额外的冷量散失多制冷的部分在保冷过程中有一部分通过墙体散热损失掉了所以总体耗电会略增。但增加的电费远小于峰谷价差省下的钱账是算得过来的。5.3 虚拟储能对光伏消纳的贡献再看光伏消纳率从91.3%提升到98.6%。午间光伏大发时段空调功率自动上调、室内温度被拉到舒适区间下限附近相当于把光伏电量“吞”进楼宇的热质量里。下午光伏出力下降后空调功率降下来室内温度慢慢回升这部分“存”的冷量就是虚拟储能在放电。这个机制在光伏渗透率更高的场景下会更值钱。如果屋顶光伏装到120kW甚至150kW“无虚拟储能”模式下午间弃光率会迅速上升而“融合虚拟储能”模式下空调、热水器可用的吸纳空间是现成的不用额外花钱装电化学储能。5.4 参数敏感性舒适度区间放宽1℃能省多少钱算例跑完之后我做了一组有意思的敏感性分析——把室内温度舒适度区间从22~26℃收窄到23~25℃再放宽到21~27℃看它对运行成本的影响舒适度区间日购电成本元相比基准变化21~27℃2152.8-2.9%22~26℃2217.2基准23~25℃2358.46.4%结果很有说服力舒适区间每放宽1℃虚拟储能的可用容量明显增大调度灵活性提升运行成本就降一批。反过来如果楼宇对温度要求极其苛刻比如数据中心、精密实验室虚拟储能的调度空间被压缩模型会退回接近“只有电池”的情况。这个结论对实际项目有直接指导意义楼宇业主和空调运维方沟通时如果能争取到1℃的舒适度余量省下的电费可以作为需求响应项目的重要收益测算依据。比如物业公司在夏季高温期间执行空调设定温度上浮1℃的政策这个算例模型就能帮忙量化评估能省多少钱。6. 我在这个模型上踩过的坑与调优建议6.1 电池充放电“同时开启”的建模陷阱前面提过电池互斥约束的事这里展开说说我是怎么踩坑的。最早一版代码里我没加 (u_c u_d \le 1)结果跑出来的调度方案里电池在好几个时段同时有充电和放电功率。数值上两项完全相等SOC稳如泰山但有充电损耗成本和放电损耗成本同时被计入——模型通过这种“无意义循环”白赚目标函数里的损耗项显然是个虚假解。后查了求解器日志才发现问题。这类问题属于典型的“病态模型”——目标函数和约束都在数学上合法但物理上没有意义。排查手段也很简单优化结果出来后先单独看电池充放电功率曲线如果出现同方向重叠基本就是缺互斥约束。顺便说一句有些论文里用大M法做互斥约束逻辑一样但工程上YALMIP里直接用两个0-1变量加重叠约束更简洁也不容易出现数值问题。6.2 状态变量时刻数比控制变量多1这个坑藏得很深我第一次写热动态约束时踩过。空调热动态约束写成T_in(t1) T_in(t) ... - (param.eta_hvac * dt / param.C_b) * P_hvac(t)如果T_in维度定义成1×T而不是1×(T1)tT时T_in(t1)会访问T_in(25)Matlab会静默扩展数组——不报错但结果完全错乱。有的版本甚至能跑出一个看似合理实际荒谬的温度曲线这类错误最害人。建议是写状态变量时统一用T1维度然后用T_in(1:T)访问调度时段的温度用T_in(T1)单独表示终端状态。这个习惯养成之后几乎所有时域递推类的模型都能少踩很多坑。6.3 物理参数离谱导致求解无解有一版参数里我把楼宇等效热容 (C_b) 写成了1.5实际上应该是150左右结果模型求解器返回infeasible。一开始以为是约束写错了查了半天才发现是热容太小空调稍微一吹室内温度就剧烈波动舒适度约束根本无法满足。这类问题的排查有个实用技巧求解无解时先固定控制变量为常规值比如空调功率恒定看看状态变量是否存在可行域。如果固定值下状态越界多半是参数量级错了而不是模型逻辑错了。另外YALMIP里optimize返回的sol.info会提示约束冲突信息配合solvesdp(Constraints, [], sdpsettings(verbose, 2))可以输出更详细的诊断信息。6.4 从连续松弛到整数求解的调试顺序最后一个经验是关于MILP调试的。模型如果有问题直接求解MILP往往很慢而且出错位置不好定位。我的调试顺序是第一步把所有的0-1变量松弛成0到1之间的连续变量问题变成LP几秒钟就能求解。这一步用来验证模型结构是否正确——如果LP都无解说明约束有硬伤和整数变量无关。第二步LP解通过了再把0-1变量加回来按MILP求解。如果这时候出现无解或异常问题多半出在整数变量相关的约束上比如互斥约束、逻辑约束。第三步MILP有解后对照LP解看目标函数增量和整数变量的取值逻辑是否合理。如果MILP解的目标函数值小于LP解——这是不可能的因为LP是松弛问题目标函数下界更优——那说明某些约束写错了。这套三步调试法帮我省了无数时间强烈建议跑任何MILP项目都照此办理。最后说一点个人体会。虚拟储能这个方向刚接触时容易把它想得很玄妙但本质上它就是“把负荷的时间弹性显式建模进优化模型”。Matlab代码的难点不在优化求解本身而在物理模型的准确建立和参数标定。空调能效比、楼宇热容、热水使用规律这些基础数据才是决定调度效果天花板的因素。模型框架搭好之后把真实建筑的参数填进去再配合滚动优化做校正这套系统就能在工程里发挥实际价值。这些代码和参数细节基本覆盖了我做楼宇微网虚拟储能调度项目时踩过的所有关键节点。有想深入讨论具体建模细节或者跑模型遇到问题的朋友欢迎在评论区留言我看到都会回复。
返回列表