2026/10/9 8:56:34

楼宇微网虚拟储能建模与Matlab优化调度实战

楼宇微网虚拟储能建模与Matlab优化调度实战 前一阵我帮某商业楼宇做能源管理方案甲方开口就问“你这套系统到底要不要加电池加了电池多久能回本”这个问题其实很能代表行业现状——光伏组件越来越便宜但电池价格依然占大头楼宇微网调度模型做得再精细回本周期一拉长方案就很难往下推。后来我们换了个思路不着急上物理储能先把楼宇里空调、热水、电梯这类柔性负荷的调节能力用起来也就是把需求侧的可控资源当成“虚拟储能”来参与优化调度。这篇文章我想把整套做法的思路和Matlab实现完整讲一遍重点包括虚拟储能怎么建模、优化调度的目标函数和约束怎么设计、代码怎么组织、以及实际调试会遇到哪些坑。适合正在做毕业设计的电气/自动化专业学生、做园区能源管理的工程师以及想把仿真模型往工程落地推进的算法岗朋友。1. 楼宇微网优化调度里虚拟储能到底解决什么问题1.1 常规楼宇微网的组成与调度痛点一栋商业楼宇的微网通常由光伏、储能电池、柴油发电机或燃气轮机、市电联络线以及楼宇负荷组成。负荷又可以拆成两大类一类是照明、插座、电梯这类“刚性”负荷基本跟随人的行为走很难强行改变另一类是空调、新风、充电桩这类“柔性”负荷在一定范围内可以平移、削减或提前使用。调度层面的经典痛点非常明确白天光伏大发且电价高但楼宇自身负荷也高光储加在一起不一定够用需要高价买电夜间电价便宜、光伏为零负荷低谷时段却几乎没有可调空间。如果只靠电池就得按照“午间峰”和“夜间谷”来设计容量投资回报很吃力。而且多数商业楼宇并没有独立的大容量电池室改造空间、消防审批都是现实问题。1.2 实体储能的现实瓶颈实体电池的优势是响应快、调度直接、能量吞吐关系清晰但它有三个绕不开的瓶颈初投资高全生命周期度电成本在不少地区仍然高于峰谷套利收益。循环寿命与调度策略强相关频繁深度充放会加速衰减运维成本随之上升。电池容量固定一旦微网中光伏渗透率提高或负荷结构变化原始配置可能很快就过时了。我在做方案对比时经常说一句话实体储能是在“用钱买调节能力”而虚拟储能是在“用算法找调节能力”。后者没有电化学衰减问题前期投入几乎为零唯一的成本是舒适度的精细管理和控制系统的复杂度。1.3 虚拟储能的核心逻辑虚拟储能的概念其实不神秘。楼宇里的空调系统利用建筑围护结构的蓄热特性在电价较低时段提前预冷让室内温度先降下来再用建筑本身的热容量在电价高峰时段“扛住”休息时间而不开压缩机。这样一来空调的电功率曲线就从原来相对刚性的一张图变成了一条可以上下平移、左右挪动的柔性曲线。如果把“室内温度与舒适度上限之间的偏差”看成状态量把“空调功率相对基准功率的偏移量”看成充放电功率那么整栋楼的空调负荷在数学上就等价于一个虚拟电池制冷预冷相当于充电停机自然漂移相当于放电。这就是融合需求侧虚拟储能系统的基本出发点。2. 虚拟储能建模把建筑热惯量变成可计算的“等效电池”2.1 一阶热参数模型要做优化调度第一步必须把建筑热过程写成方便计算的代数方程。工程里用得最多的是一阶等效热参数模型Equivalent Thermal Parameters也就是把房间等效成一个热阻R加一个热容C的简单结构。连续时间下的一阶模型可以写为C * dTin/dt (Tout - Tin) / R - Qc其中C是房间等效热容单位 kWh/°C代表建筑能吸收或储存多少热量R是等效热阻单位 °C/kW代表墙体、窗户等阻止热量交换的能力Qc是空调的制冷量单位 kW制冷量越大室内温度下降越快Tout是室外温度Tin是室内温度。实际写进Matlab时需要对时间离散化。假设时间步长为dt单位为小时则Tin(t1) Tin(t) dt / (R*C) * (Tout(t) - Tin(t)) - dt / C * Qc(t)空调电功率P_ac(t)和制冷量Qc(t)之间通过能效比COP建立联系Qc(t) COP * P_ac(t)。这里要特别说明一阶模型虽然简单但对调度层已经足够。它抓的是“电价高峰期能不能少开空调”“低谷期提前预冷有没有意义”这种小时级决策问题不需要CFD级别的温度场细节。模型参数可以通过现场温降实验来标定停电后记录室内温度变化曲线拟合出R*C值。2.2 等效电量与充放电功率要把空调负荷变成“虚拟储能”最直观的等价方式是这样定义设空调在舒适区中点的基准电功率为P_ac_ref定义虚拟储能功率P_ves(t) P_ac_ref - P_ac(t)。当空调少开、P_ves 0时相当于虚拟储能释放冷量减少电网侧用电当空调多开预冷、P_ves 0时相当于虚拟储能充电把冷量提前存到建筑里。对应的“容量”则是温度允许波动范围内建筑能储存的净冷量E_ves C * (T_max - T_min)比如某会议室热容是 200 kWh/°C舒适度区间是 22~26°C那么虚拟储能容量就是200 * 4 800 kWh。这个量级往往和一组实际电池的容量相当甚至更大。正因为容量不小虚拟储能在削峰填谷问题上才有参与价值。与电池状态量SOC类似虚拟储能的状态量就是当前室内温度Tin(t)。温度越低相当于“SOC越高”后续允许自然漂移的时间越长温度越接近上限相当于“电量快放完”必须马上开启压缩机降温。2.3 和电池储能的关键差异虚拟储能虽然数学形式上像电池但它和电池有几个本质区别建模时必须区别对待电池的SOC可以规划在0.9到0.2之间大幅波动而虚拟储能的“SOC”就是室内温度必须全程约束在人能接受的舒适度区间内不能为了省电把楼层搞得像冰窖或桑拿房。电池放电功率上限基本恒定而空调的“放电”即停机自然漂移能力受室外温度、太阳辐射、室内人员数量影响很大。同样是停机一小时中午比早上温度漂移快得多。电池可以在凌晨自动充满而预冷只能在建筑有人之前做时间窗口有限。商业楼宇通常只在上班前半小时到一小时允许深度预冷下班后则更多是关机节能模式。所以一套能用的虚拟储能模型至少要包含温度动态方程、温度舒适范围、空调功率边界和运行时间窗口这四个要素。把这些约束写进优化问题调度器才能在不影响用户体验的前提下挖掘柔性。3. 优化调度模型目标函数、约束条件与求解框架3.1 目标函数怎么定楼宇微网优化调度的目标函数没有标准答案取决于你是“为了卖方案”还是“为了做研究”。我把常见的几种写法整理如下目标类型数学形式适用场景运行成本最小购电成本 燃料成本 设备运维成本商业楼宇最常用直接对应电费单碳排放最小购电等效碳排放 燃料燃烧排放低碳园区、绿色建筑认证项目自给率最大本地可再生能源消纳量最大化偏远微网、孤岛运行成本舒适度加权运行成本 舒适度偏离惩罚希望体现用户感受的精细化调度实际做项目时我基本都选择“运行成本最小同时用软约束处理舒适度”。因为楼宇投资方最关心的就是电费而舒适度问题可以通过约束温度边界来处理不需要把它写进目标函数再去调权重。一个典型的24小时调度目标函数如下min Σ [ Price_buy * P_buy - Price_sell * P_sell c_diesel * P_diesel c_es * |P_es| ] * dt其中P_buy是向电网购电功率Price_buy是对应电价P_sell是售电功率P_diesel是柴油发电机出力P_es是电池充放电功率负值充电、正值放电c_es可以理解为综合运维成本系数。3.2 约束条件逐条拆解调度模型最核心的约束是功率平衡任何时候都要满足“进等于出”P_pv P_diesel P_es P_buy P_base P_ac P_ev P_sell其中P_pv是光伏出力P_base是刚性基础负荷P_ev是充电桩负荷。然后是电池储能动态SOC(t1) SOC(t) - P_es(t) * dt / E_cap SOC_min SOC SOC_max -P_es_max P_es P_es_max再就是前文说的虚拟储能模型简写为Tin(t1) Tin(t) dt / (R*C) * (Tout(t) - Tin(t)) - dt * COP * P_ac(t) / C T_min Tin T_max 0 P_ac P_ac_max这个模型巧妙的地方在于调度器为了在高峰时段降低P_buy会自动想办法调整P_ac。而P_ac降低会推高Tin只要不顶到T_max优化算法就会把这部分调节能力用满。最后还要根据项目情况加入联络线功率限制、柴油机爬坡约束、购售电互斥约束等。购售电互斥这一步最容易忽略如果不加约束优化器会同时买电又卖电来套利结果在物理上不成立。3.3 模型类型与求解器选择上面的模型中电池充放电、购售电互斥如果直接建模会引入0-1整数变量整体是一个混合整数线性规划问题。YALMIP配合Gurobi或Cplex可以直接求解不需要自己写分支定界算法。如果你不想引入整数变量也可以用变通方式比如将电池功率拆成两个连续变量分别限制正负再用互补约束或惩罚项近似。但这样求解时间不一定更快还可能让问题变成非线性。我的建议是能用MILP就用MILPGurobi对这类问题的求解速度已经很快24小时内、15分钟一个时点变量规模在几千个完全在可控范围内。4. Matlab代码实现从数据准备到调度结果输出4.1 数据输入与参数初始化代码实现的第一步不是写约束而是把数据组织清楚。我的习惯是单独建一个参数区把所有曲线、成本系数、设备参数都集中放在一起方便后续替换真实数据。%% 基础参数 T 96; % 调度总时段数15分钟一个点共24小时 dt 15/60; % 时间步长单位 h %% 外部数据曲线示意数据实际替换为测量值 Tout 28 5 * sin(2*pi*(0:T-1)/T); % 室外温度 P_pv max(0, 150*sin(pi*(0:T-1)/T)); % 光伏出力单位 kW Price 0.6 * ones(1,T); % 分时电价单位 元/kWh Price(12:18) 1.1; % 高峰时段假设 Price(0:6) 0.3; % 低谷时段 P_base 180 * ones(1,T) 40 * sin(pi*(8:T-1)/T); % 刚性负荷近似 % 电池参数 Ecap 200; % 电池容量 kWh Pes_max 100; % 充放电功率上限 kW SOC_min 0.1; SOC_max 0.9; % 建筑/空调参数 R 0.5; % °C/kW C 100; % kWh/°C COP 3; Pac_max 120; % 空调电功率上限 kW Pref_ac 60; % 基准运行功率 kW Tmin 22; Tmax 26;设置数据时容易踩的坑是单位不一致。比如热容C的单位要统一到 kWh/°C而热阻R要统一到 °C/kW这样R*C得到的时间常数单位才是小时。否则离散化方程会出现量纲错误结果看起来正常但实际完全不对。4.2 决策变量与约束组装用YALMIP定义变量非常方便。电池功率、SOC、空调功率、室内温度都是连续变量如果考虑购售电互斥需要额外加二元变量我这里先把购电功率定义为非负变量并用范围约束替代互斥%% 决策变量 P_buy sdpvar(1, T, full); % 购电功率 P_es sdpvar(1, T, full); % 电池功率正放负充 SOC sdpvar(1, T, full); % 电池SOC P_ac sdpvar(1, T, full); % 空调电功率 Tin sdpvar(1, T, full); % 室内温度 %% 目标函数 c_diesel 0.9; % 柴油发电成本 元/kWh此处暂不使用柴发 Objective sum(Price .* P_buy * dt) ... 0.01 * sum(abs(P_es)) * dt; %% 约束 Constraints []; % 功率平衡 Constraints [Constraints, P_pv P_es P_buy P_base P_ac P_pv*0 0]; % 电池SOC递推 Constraints [Constraints, SOC(1) 0.5]; for t 1:T-1 Constraints [Constraints, SOC(t1) SOC(t) - P_es(t)*dt/Ecap]; end Constraints [Constraints, SOC_min SOC, SOC SOC_max]; Constraints [Constraints, -Pes_max P_es Pes_max]; % 虚拟储能室内温度动态 Constraints [Constraints, Tin(1) 24]; for t 1:T-1 Qc COP * P_ac(t); Constraints [Constraints, Tin(t1) Tin(t) dt/(R*C)*(Tout(t)-Tin(t)) - dt/C*Qc]; end Constraints [Constraints, Tmin Tin Tmax]; Constraints [Constraints, 0 P_ac Pac_max]; % 尚需注意P_pv 在功率平衡中重复出现实际项目要按拓扑关系修正代码里有一个写法问题值得指出如果在功率平衡方程中P_pv已经出现就不应该再用别的变量替它占位。实际建模中光伏出力在调度周期内一般作为已知参数直接写在等号左边不需要用P_pv*0这种占位写法。上面的代码只是为了展示约束拼接思路真正落地时要按照你的拓扑关系仔细核对功率流向。4.3 求解与结果提取约束和目标组装完成后就可以调用求解器%% 求解设置 options sdpsettings(solver,gurobi,verbose,1); sol optimize(Constraints, Objective, options); %% 结果提取 if sol.problem 0 P_buy_opt value(P_buy); P_ac_opt value(P_ac); Tin_opt value(Tin); SOC_opt value(SOC); fprintf(调度成功日运行费用 %.2f 元\n, value(Objective)); else disp(求解失败); disp(sol.info); endsol.problem 0表示求解成功。这里我习惯用sol.info来检查求解器给出的具体信息而不是只看sol.problem因为Gurobi有时会给出“子最优”“数值有问题”这类隐藏警告不细看容易漏掉。5. 一个典型算例虚拟储能介入前后的调度对比5.1 算例设置为了把虚拟储能的效果讲清楚我在这里给出一个示意算例数据来自与某商业楼宇项目模型量级相似的公开案例具体数值各项目会不同。场景设定一栋小型商业楼宇光伏装机300 kW蓄电池100 kW/200 kWh办公室空调额定功率120 kW室内舒适度区间22~26°C室外温度在28~35°C之间波动电价分三时段。对比三种策略策略A无优化空调全天按额定设定运行电池不参与。策略B有电池参与但空调不参与优化调度只做固定运行。策略C电池和虚拟储能同时参与优化调度。5.2 结果对比表指标策略A无优化策略B仅电池策略C电池虚拟储能日运行成本元512045803965峰值负荷kW430356281光伏消纳率%829496空调全天开机时长h10.510.58.2室内温度超限次数000从表里可以看到电池介入后日成本下降了约540元虚拟储能再叠加成本又下降了600多元。峰值负荷从430 kW降到281 kW削峰效果非常明显。空调开机时长减少约2.3小时相当于把两台空调的功率在高峰期完全“让”出去了。5.3 关键结论省的钱从哪里来很多人看到结果第一反应是虚拟储能是不是把空调关了很久其实不是。策略C里的空调全天开机8.2小时比不优化的10.5小时少但用户并没有明显感觉因为温度始终在舒适区间内。省钱的本质是三个动作低谷电价时段提前预冷把房间温度拉低到舒适区下边界附近相当于给“虚拟电池”充上电。高峰电价时段少开空调让温度自然漂移但仍不触碰26°C上限相当于“虚拟电池”放电。光伏大发时段空调适当加力提高本地光伏消纳率减少向电网倒送或弃光。同时要注意虚拟储能容量与室外温度强相关。夏季极端高温天房间自然漂移很快温度从22°C升到26°C可能只需要不到两小时所以虚拟储能的“容量”不是固定值。做项目方案时不能拿春秋天的数据来承诺夏季削峰效果这一点我在和甲方对赌效果时吃过亏。6. 实际调试中踩过的坑与处理经验6.1 求解器和建模接口的兼容问题YALMIP只是建模层真正求解MILP还需要Gurobi或Cplex。第一次搭建环境时经常碰到以下情况症状可能原因处理方式No suitable solver for KYP或Failed to find solver没安装求解器或YALMIP找不到路径安装Gurobi后在Matlab里运行yalmiptest确认求解器能被识别Gurobi报License expired学术许可过期或未配置环境变量重新申请学术License或检查GRB_LICENSE_FILE路径求解器返回NaN或Infeasible or unbounded约束中出现了Inf、NaN数据或目标函数有未定义变量先检查所有输入曲线是否存在NaN再用feasible()单独测约束开发过程中建议先用小规模测试比如只取前8个时段跑通逻辑后再放大到96个时段。这样能把数据问题和模型问题分开节约排查时间。6.2 虚拟储能模型“无解”的完整排查链路有一次我把虚拟储能模型加进原有调度代码直接遇到求解失败而且是整段代码都不可行。当时第一反应是找是不是空调功率上限写错了但排查之后发现是别的问题。我整理一下当时的排查步骤供读者参考先把虚拟储能相关约束全部注释掉保留电池和功率平衡。如果此时能求解说明问题出在虚拟储能约束部分。再把Tmin Tin Tmax放宽为15 Tin 35如果可解说明温度边界太紧。检查初始温度。Tin(1)我设成了24°C但当时室外温度曲线是早晨20°C、中午35°C优化器发现为了保持24°C空调功率必须超过上限于是无解。解决方式是把初值改到舒适区间更靠近上限的位置并增加前面几个时段空调功率的预热约束让模型有足够时间把温度拉回舒适区。这条排查链路基本可以覆盖大多数虚拟储能无解问题。说到底虚拟储能约束的“难”不在数学而在物理逻辑。它要求Tin的初值、室外温度扰动和空调功率边界三者协同任何一个不匹配都会直接不可行。6.3 从24小时静态调度走向日内滚动优化前文讲的是一次性求解24小时调度计划但实际工程落地时我更推荐日内滚动优化。原因很简单光伏出力预测会偏差室外温度预测也会偏差一次性算出来的空调预冷计划执行到下午可能就失效了。滚动优化的做法是每个控制周期比如15分钟更新一次最新的预测曲线重新求解未来4小时或6小时的调度计划只执行第一个时点的指令。这样虚拟储能时刻在根据实际温度修正状态鲁棒性比一次性开环调度强很多。在Matlab里做滚动优化不需要改模型主体只需要把代码包在一个循环里每次更新Tout、P_pv的预测值把当前Tin的实测值作为新的初始条件。要注意的是滚动优化必须给虚拟储能预留恢复空间不能让温度长期贴着上限否则下一个周期没有调节余地。关于参数校准我强烈建议在正式调度前做一次24小时实测记录空调功率、室内温度、室外温度然后用最小二乘去拟合R和C。很多论文里直接用一个固定热容跑全年这在工程里风险很高因为窗户开闭、人员密度、设备发热都会改变等效热容。用我上面的ETP模型公式Matlab里20行代码就能完成拟合值得花这个时间。最后再分享一个我自己的体会虚拟储能不是把空调一关了之而是在舒适度和经济性之间做实时权衡。我们在实际项目里先小范围试点只把一层楼的空调纳入调度运行一周确认用户投诉为零才敢全楼铺开。如果你也在做楼宇微网项目我建议第一步先别急着写复杂代码而是把楼宇的分项计量数据整理清楚——空调、照明、插座、充电桩各走各的表数据摸透了后面建模、调度、验证都会顺手得多。