首页 / 资讯中心 / 文章详情

微电网日前经济调度实战:风光储与需求响应Matlab建模

微电网日前经济调度实战:风光储与需求响应Matlab建模 ★ FEATURED ARTICLE
最近好几个做微电网方向的同学都在问同一件事怎么看懂别人分享的“基于风光储能和需求响应的微电网日前经济调度”Matlab代码以及怎么把它改成自己能跑、能复现、能写进论文里的版本。这个方向确实火风、光、储能、需求响应DR、日前调度几个关键词拆开都不算生僻但一旦组合到一起建模逻辑、约束条件、求解器配置就全是细节。我自己从最早拿着别人源码做替换到后来能独立搭一套完整的日前调度模型中间踩了不少坑。这篇就把我实际跑通的经验完整梳理一遍从为什么需要日前调度到数学模型怎么建再到Matlab代码怎么组织、结果怎么看、哪些地方最容易翻车一次性讲清楚。1. 为什么微电网必须做“日前”调度风光储与需求响应同台的经济性逻辑1.1 微电网调度的核心矛盾风光出力看天吃饭负荷却要稳定供电微电网这个概念听起来高大上说白了就是一个可以独立运行的小型发配电系统里面有分布式光伏、小型风机、储能、柴油发电机或者燃气轮机再加上本地负荷。微电网的调度难题根源在于电源侧和负荷侧的天然不对称。光伏出力夜间为零白天跟着光照走遇到阴天直接腰斩风电则看风速白天晚上都可能有但波动大。这跟传统的火电机组完全不同——火电是“想发多少发多少”只要燃料跟上光伏风电是“能发多少发多少”完全看天吃饭。而负荷侧的用电需求又有自己的规律早晚高峰、午休低谷基本不跟风光出力同步。比如夏天傍晚太阳落山后光伏骤降空调负荷却还在高位这时候如果没有储能和外部电网支撑微电网的电压和频率都会很难看。所以微电网调度要回答的核心问题就一个在风光出力不确定、负荷波动、电价分时的前提下怎么安排储能充放电、柴油机开停机、从大电网买电或卖电、以及调动需求侧资源使得整个微电网的运行成本最低。1.2 日前调度的时间尺度与滚动策略提前一天定好每小时的发用电计划“日前”这两个字指的是调度的时间尺度。微电网调度可以分为日前调度day-ahead scheduling、日内滚动调度intra-day dispatch和实时控制real-time control三个层次。日前调度是其中最上游的决策环节提前24小时以1小时为间隔也常用15分钟根据风光出力预测、负荷预测、电价信息制定次日0点到24点每小时各设备的运行计划。为什么需要提前一天做这个事因为微电网里的很多设备存在启停约束和爬坡约束。柴油机不能瞬间从0跳到满功率储能充放电切换也不能太频繁。如果完全依赖实时控制设备响应不过来而且实时市场的电价通常比日前波动更大临时调整成本很高。所以行业惯例是先把日前计划算出来把大方向的运行基点定好然后再用日内滚动和实时控制去做偏差修正。这个思路其实特别像我们安排一天的行程——前一天晚上把重要事项排好第二天再根据突发情况微调而不是第二天早上睁眼才开始想今天要干什么。在Matlab里实现日前调度本质就是求解一个以24小时为周期的优化问题决策变量覆盖全天各个时段。1.3 需求响应如何在这里“化被动为主动”把负荷侧变成可调资源需求响应Demand ResponseDR的意思是让用户侧的负荷不再是固定值而是可以根据电网状态主动调节的资源。微电网中的DR常见有两种类型可削减负荷和可转移负荷。可削减负荷就是用户允许调度中心在特定时段削减掉一部分用电比如提前把空调温度上调几度、关停一些非关键设备用户因此获得经济补偿。可转移负荷则是不削减总用电量只是把用电时段平移比如电动汽车充电、洗衣机、蓄热式热水器等把下午的用电挪到凌晨低谷期。在日前经济调度模型里DR被建模成一种“虚拟机组”——它不像光伏风电那样受自然条件约束但也需要消耗成本补偿费用并且有调用上限和时段限制。它的作用是在电价尖峰时段“削减”负荷帮助微电网减少高价购电相当于给调度员多了一个灵活性手段。可以把DR理解为电梯高峰期安排的分流疏导——大家都在同一时间挤电梯的话效率极低调度中心通过错峰引导把一部分人流挪到空闲时段整体出行体验反而更好。DR参与日前调度后系统不用为了20分钟的尖峰负荷去启停一台昂贵的柴油机也不用在电价最高的时候从外部买电经济性改善非常明显这也是它在各种微电网调度方案里都在被积极引入的原因。2. 数学模型的完整推演目标函数、决策变量与每一类约束的来龙去脉2.1 目标函数四项成本购电、售电、发电、储能与DR补偿怎么组合微电网日前经济调度的目标函数第一眼看上去有点长但拆开就是几笔账。第一笔是跟大电网交互的成本从电网买电要花钱向电网卖电有收入所以购电成本减去售电收益。第二笔是本地发电机组的燃料成本通常用二次函数表示——发电功率越高边际成本越大。第三笔是储能的运行损耗成本电池充放电是消耗寿命的按充放电功率乘一个单位损耗成本折算。第四笔是需求响应的补偿费用调用多少可削减负荷就要付给用户多少钱。目标就是让这四笔费用的总和最小。目标函数写成公式就是min C Σ[P_buy(t) * price_buy(t)] - Σ[P_sell(t) * price_sell(t)] Σ[F(P_dg(t))] Σ[P_ch(t)*c_ess P_dis(t)*c_ess] Σ[P_dr(t) * c_dr]其中P_buy(t)是第t小时从电网购电功率price_buy(t)是购电价P_sell(t)是售电功率price_sell(t)是上网电价F(P_dg(t))是柴油机的燃料成本函数典型形式是aP²bPcP_ch(t)、P_dis(t)是储能充电、放电功率c_ess是单位充放电损耗成本P_dr(t)是DR调用量c_dr是DR补偿单价。注意P_dg(t)是决策变量F里面有二次项所以这个问题天然是二次规划QP或者混合整数二次规划MIQP。如果不想处理非线性项也可以用分段线性化把二次函数拆成几段直线让问题变成MILP求解更稳定。2.2 功率平衡约束一天24小时每一小时都必须“发用”微电网运行最基本的原则是每一时刻系统的功率必须平衡。这个平衡不是说光伏风电柴油机储能发出的电刚好等于负荷就行还得考虑和大电网的交互以及DR削减掉的负荷。功率平衡约束可以写成P_pv(t) P_wt(t) P_dg(t) P_dis(t) P_buy(t) P_dr(t) P_load(t) P_ch(t) P_sell(t)这个等式是日前调度模型里最重要的约束。左边是“可用电源”右边是“负荷需求”。注意P_dr(t)放在左边是因为调用需求响应相当于减少了负荷等价于增加了供给而储能充电P_ch(t)是消耗功率的所以放在右边储能放电P_dis(t)是提供功率的放在左边。把这个等式理解为日常家庭的用电管理就很直观夏天晚上全家用电3000W光伏停了那就得决定是从电网买电、让电池放电、还是暂时关掉空调削减负荷来补上缺口。所有可用的“来源”加起来必须刚好等于“去处”一分不多一分不少。这个等式如果写错整个调度结果就会完全失控。2.3 储能的SOC递推与充放电互斥能量守恒是调度模型的灵魂储能是微电网灵活性的关键但它不乱用。电池的荷电状态SOCState of Charge直接决定了后续时段还能充多少放多少所以模型里必须描述SOC随时间变化的关系这就是SOC递推方程。SOC(t1) SOC(t) (P_ch(t) * η_ch - P_dis(t) / η_dis) * Δt / Cap其中η_ch是充电效率η_dis是放电效率Cap是储能容量kWhΔt是调度的时段间隔1小时。充电时电网输入的电能要乘以效率才能存入电池放电时电池释放的电能要除以效率才能得到实际输出的功率。效率损失就是热损耗建模时必须体现否则求解结果会高估储能的价值。除了SOC递推还有几类约束缺一不可。首先是储能充放电功率上下限充电功率不能超过充电机最大功率放电功率同理。其次是SOC上下限一般不会允许电池完全放空通常限制在10%~90%之间保护电池寿命。第三是充放电互斥约束——同一时刻储能不能同时充电和放电否则模型会“投机”一边低价充电一边高价放电账面上赚差价实际物理上不可能实现。这个互斥约束在Matlab里通过两个二进制变量来实现u_ch(t) u_dis(t) 1当u_ch(t)1时允许充电u_dis(t)0u_dis(t)1时允许放电u_ch(t)0两个都为0时储能处于空闲状态。还有一类容易被忽略的是SOC的初始值和末端值约束。SOC(1)要设置为已知初值比如0.5末端SOC(T1)一般也要约束回到初始值目的是让储能的调度计划日复一日可持续运行——如果每天结束时电池都是满的第二天就没地方充电了如果每天结束时电池是空的第二天的灵活性就大打折扣。2.4 需求响应资源的约束建模可削减量与调用次数的上限DR并不是想调多少就调多少。用户参与需求响应是有条件的单时段削减量不能超过该时段总负荷的一个比例通常10%~20%一天内允许被调用的总时长或次数也有限制不能让用户全天被拉闸。在Matlab模型里单时段DR约束很简单0 P_dr(t) dr_max * P_load(t)dr_max是最大削减比例。这个约束限定了每个小时能调用多少DR。但实际工程中还要考虑DR的累计使用次数这是初学最容易漏掉的。如果只加了单时段上限求解器可能会让DR在一天24小时每小时都卡在最大削减量上——对于某些用户场景这并不合理也不符合合同约定。要建模“一天最多调用N小时”需要引入二进制辅助变量d(t)d(t)1表示第t小时调用DR然后加约束P_dr(t) dr_max * P_load(t) * d(t) Σ d(t) N这组约束的含义是只有d(t)1的时段才允许调用DR且全天调用时段总数不超过N。把DR的使用频次限制住调度结果才真正具备可操作性不会在仿真里好看、实际用户根本不配合。3. Matlab实现链路Yalmip建模、Cplex求解与数据准备的完整代码框架3.1 用Yalmip还是手写矩阵中小规模模型直接上建模语言做Matlab微电网调度第一步要决定用什么方式建模。手写约束矩阵调用linprog或intlinprog是一种方式但24时段、每个时段十来个变量和几十条约束手写系数矩阵极其痛苦改一个参数要跟着改一堆索引调试效率太低。我的做法是用Yalmip工具箱做建模把优化问题写成接近数学公式的代码再调用Cplex或Gurobi做底层求解。Yalmip是一个Matlab建模层它允许用sdpvar定义变量用等式不等式表达约束用optimize函数一键求解。这样做的好处是约束写出来跟论文公式几乎一一对应代码可读性高也更不容易出错。当然用Yalmip需要额外安装工具箱很多人卡在这一步。安装其实不复杂去Yalmip官方GitHub仓库下载压缩包解压后把Yalmip文件夹放到了Matlab路径里在MATLAB中右键路径设置添加即可再安装一个求解器。Cplex和Gurobi都有学术免费授权学生申请很方便我最早用的是Cplex因为IBM的授权申请流程相对简单在校园邮箱注册就能拿到许可证。3.2 核心代码模块拆解变量定义、约束生成、目标函数与求解调用完整的代码框架分为五个部分。第一部分是参数初始化把所有固定参数装在结构体里比如储能容量、效率、SOC上下界、柴油机爬坡率、分时电价等。第二部分是定义决策变量第三部分是构建约束第四部分是写目标函数第五部分是调用求解器并解析结果。决策变量定义的核心代码如下% 基础参数 T 24; % 调度时段数 dt 1; % 时段间隔小时 % 决策变量 P_dg sdpvar(1, T); % 柴油机出力 P_buy sdpvar(1, T); % 购电功率 P_sell sdpvar(1, T); % 售电功率 P_ch sdpvar(1, T); % 储能充电功率 P_dis sdpvar(1, T); % 储能放电功率 u_ch binvar(1, T); % 充电状态 u_dis binvar(1, T); % 放电状态 SOC sdpvar(1, T1); % 荷电状态 P_dr sdpvar(1, T); % 需求响应调用量约束构建部分功率平衡直接写成Constraints []; % 功率平衡 for t 1:T Constraints [Constraints, P_pv(t) P_wt(t) P_dg(t) P_dis(t) P_buy(t) P_dr(t) P_load(t) P_ch(t) P_sell(t)]; end储能SOC递推和充放电互斥% 储能启停互斥与功率上下限 Constraints [Constraints, 0 P_ch(t) P_ch_max * u_ch(t)]; Constraints [Constraints, 0 P_dis(t) P_dis_max * u_dis(t)]; Constraints [Constraints, u_ch(t) u_dis(t) 1]; % SOC递推约束 for t 1:T Constraints [Constraints, SOC(1) SOC_init]; Constraints [Constraints, SOC(t1) SOC(t) (P_ch(t) * eta_ch - P_dis(t) / eta_dis) * dt / Cap_ess]; end Constraints [Constraints, SOC_min SOC(2:end) SOC_max]; Constraints [Constraints, SOC(T1) SOC_init];需求响应约束加上累计次数限制% 引入DR调用标志变量 d binvar(1, T); for t 1:T Constraints [Constraints, P_dr(t) 0]; Constraints [Constraints, P_dr(t) dr_max * P_load(t) * d(t)]; end % 全天DR调用次数不超过N_dr_max Constraints [Constraints, sum(d) N_dr_max];目标函数Objective sum(P_buy .* Price_buy * dt) - sum(P_sell .* Price_sell * dt) ... sum(a * P_dg.^2 b * P_dg c_0) ... sum((P_ch P_dis) * c_ess * dt) ... sum(P_dr .* Price_dr * dt);求解调用ops sdpsettings(solver, cplex, verbose, 2, cplex.mip.tolerances.mipgap, 0.01); result optimize(Constraints, Objective, ops); % 解析结果 P_dg_opt value(P_dg); P_buy_opt value(P_buy); P_sell_opt value(P_sell); P_ch_opt value(P_ch); P_dis_opt value(P_dis); SOC_opt value(SOC); P_dr_opt value(P_dr);求解器中mipgap设的1%是有讲究的。MILP含0-1整数变量的混合整数线性规划要找到严格最优解往往耗时指数级增长但允许1%的相对间隙求解时间能缩短一个数量级而成本偏差只有1%工程上完全可接受。如果打印的求解结果是“Optimal solution found”说明已经收敛到了最优或接近最优的解。3.3 输前数据准备典型日风光出力、分时电价与DR合同参数的处理模型跑之前数据准备决定了仿真结果的合理性。风光出力数据必须是“预测值”这和历史实测是两个概念。日前调度基于预测所以预测值一般会带一点保守调整比如光伏预测打9折、风电预测打8折避免实际运行时出力不足导致电量缺口。我自己喜欢构造一个典型日场景来调试模型定义一条光伏出力曲线峰值150kW出现在13点左右夜间为零风电出力在30~80kW之间随机波动负荷曲线早上8点开始爬升11点到13点出现午高峰18点到21点出现晚高峰峰值350kW左右。分时电价按谷、平、峰三档设定谷段23:00~07:00售价0.25元/kWh平段0.5元/kWh峰段0.9元/kWh峰段覆盖11:00~12:00和16:00~21:00。DR参数方面最大削减比例设为15%每日最多调用4小时补偿单价0.8元/kWh——这个值很有讲究它低于峰段电价0.9元但高于平段电价0.5元这样求解器只会在电价高的时候调用DR低谷时调用对降低成本没有帮助自然不会被选中。如果DR补偿设得比峰段电价还高系统会更愿意削减负荷而不是买电这虽然不算错误但在现实里用户补偿不可能高于电网购电价经济逻辑上不成立。这些数据在代码里直接写成向量或结构体调试时先用典型日数据跑通再替换成实际的全年预测数据。我见过不少同学上来就把8760小时全年数据灌进去结果模型跑不动或者报错排查半天也不知道问题出在数据还是代码——正确做法是先调通一个典型日把逻辑理顺了再扩展效率高得多。4. 调度结果怎么看功率平衡图、SOC曲线与需求响应前后的成本对比4.1 从求解结果还原每小时的电量流向检验模型是否合理模型算完第一件事不是看成本降低了多少而是看调度曲线物理上是否合理。很多初学者直接跳到最后成本数字却忽略了中间的功率曲线是否符合常识——这是最危险的因为模型可能会在错误约束下给出一个“数学上最优、物理上荒谬”的结果。画图的做法是把每个小时的P_pv、P_wt、P_dg、P_dis、P_buy当成堆叠面积图的下层负荷叠加上方这样一眼就能看到每个时段电量怎么来的。同时把SOC曲线画在右侧坐标轴上看储能是否遵循“低谷充电、高峰放电”的基本逻辑。合理的调度结果有几个特征。储能SOC在夜间低谷时段上升充电在白天高峰时段下降放电日末回到初始值。柴油机一般只在负荷高峰或者光伏低谷时段启动不会整天开着。购电多发生在平段和谷段而峰段主要靠储能放电和DR削减负荷支撑。如果SOC曲线出现频繁的“锯齿状”——一个小时内充电突增下一小时放电突增——往往说明模型缺少对储能切换次数的惩罚虽然代价不大但现实中会极大加速电池老化。此时需要在目标函数里增加一点切换惩罚项或者加一个约束限制充放电状态的切换次数。4.2 有无需求响应的经济性对比成本下降来自哪里验证DR价值的标准做法是跑两个场景场景A不启用DRP_dr强制为0场景B启用DR对比总成本和各类费用的变化。在我的典型日参数下启用DR后期总成本大约下降6%~10%而下降的金额主要来自峰段购电费用的减少。峰段电价0.9元/kWhDR补偿0.8元/kWh每削减1kWh负荷系统节省0.1元购电费用还要少买高价电。更关键的是削减晚高峰负荷后柴油机的峰值出力需求变小机组可以在更低功率区间运行燃料成本下降。有时候DR还能延迟柴油机的启动时间——本来19点就需要启机有了DR可以拖到20点机组少运行1小时启停成本直接省掉一大块。画对比图时用柱状图把“无DR”和“有DR”场景下的购电成本、燃料成本、储能损耗成本、DR补偿费用并列对比成本下降一目了然。写论文时这是最直观的一张图。4.3 储能容量和DR可调用量对调度结果的灵敏度影响除了基础场景我一般会额外做两个灵敏度分析它们对工程规划特别有用。第一个是储能容量变化对总成本的影响从200kWh到1000kWh步长100kWh看总成本是否单调下降、下降幅度是否递减。结果通常是边际效益递减的——储能越大单位容量带来的成本下降越小等到某个点之后收益可以忽略这就是经济上最优储能容量的参考依据。第二个是DR最大可调用量比例的变化从5%到20%。DR潜力增加时成本下降也非常明显但要注意DR占比过高意味着用户舒适度损失大实际可行性不足。这些灵敏度分析在Matlab里只需要一个for循环批量跑不同参数场景输出成本矩阵再画成折线图即可。这两个分析最大的作用是证明模型不是“只在一个参数下能用”而是可以支撑光伏配储容量规划、DR合同设计等实际决策问题。很多审稿人关心的就是模型有没有这个泛化能力。5. 实战中没踩过坑的人写不出这套排错清单求解慢、SOC飞、DR滥用5.1 二进制变量让MILP求解变慢的加速经验我第一次跑带储能的日前调度时求解器大概要半分多钟才出结果当时以为是自己模型规模太大后来发现完全是可优化的。核心问题在于我用了两种方式引入了不必要的二进制变量一是没有简化DR调用标志二是对每个时段都用两个二进制变量控制充放电状态。优化思路有三条。第一条是给求解器一个合理的初始可行解用assign函数给部分变量赋初值让Cplex从更好的起点开始搜索。第二条是合理设置求解器参数把mipgap从默认的1e-4放宽到0.01求解时间通常能缩短80%以上成本偏差却几乎没有。第三条是缩减不必要的整数变量范围——比如如果储能额定功率很小充电功率上限P_ch_max已经是固定值那么u_ch和u_dis实际上只有0或1两种取值这已经是精简的了但如果有两台完全相同的储能可以合并成一台等效储能来建模变量数直接减半。还有一个小技巧是不要一开始就把所有约束都加上先跑一个去掉DR累计次数约束的LP松弛版本确认连续变量部分没问题再加上整数变量和MILP求解。这样分步排错出问题能快速定位。5.2 SOC初始值、终端约束与效率方向错误的典型症状SOC相关的错误是排错重灾区而且症状非常迷惑。我记得有一次跑出来的调度结果里储能每到傍晚就“用光”日末SOC竟然变成负值而求解器还提示“Optimal solution found”——这说明我根本没有给SOC加下界约束或者下界约束写错了地方。正确写法是SOC_min SOC(2:end) SOC_max这个约束必须作用在整条SOC曲线上不能漏掉末端SOC(25)也包含在里面。有些同学只写了SOC_min SOC但SOC在Yalmip里是1x25向量写少了等于没约束。效率方向的错误就更隐蔽。有人把SOC递推写成SOC(t1)SOC(t) P_ch(t)/η_ch - P_dis(t)*η_dis看似合理实则方向反了结果是储能充的越多亏的越多调度结果会倾向于完全不充电。正确定位方法很简单单独给一个强制充电场景跑测试比如设置负荷很低、光伏很高看SOC是否在上升再设一个强制放电场景看SOC是否在下降。如果方向相反把效率放在对侧再试一次就好。还有一个必须检查的细节是SOC的量纲。如果储能容量Cap的单位是kWh那么递推公式右边要乘Δt小时如果Cap单位是kW·h而Δt1小时乘不乘都不影响数值但在15分钟调度间隔的模型里不乘就错了。务必确认时间基准和容量单位统一。5.3 需求响应被“无脑调用”的根因与约束收紧方法DR滥用这个坑我在看过别人代码时见到过不止一次。症状非常明显最优调度结果里P_dr每一小时都顶在dr_max*P_load的上限上成本比不启用DR时低得离谱一看就是模型有问题。根因有两类。第一类是DR的累计调用次数约束没加导致求解器把DR当成免费资源在每个时段都大量使用。补救方法是引入二进制标志变量d(t)加sum(d)N_dr_max的约束把全天调用次数锁死。第二类是DR补偿单价设置得不合理高于峰段购电价于是削减负荷比买电还要“划算”系统当然无脑削减。排错时先检查DR补偿参数和峰平谷电价做对比。如果补偿低于峰段电价但高于谷段电价那么DR在峰段被短时调用是正常的在谷段被调用就非常可疑。如果出现谷段也调用DR优先检查功率平衡方程是否有误——P_dr(t)减错了方向会让系统误以为削减负荷等于额外发电白赚补偿。最后再说一个容易被忽视的问题当负荷水平本身很低时DR可调用量dr_max*P_load(t)也很小此时DR对调度结果几乎没影响。所以验证DR效果时要用高峰负荷日的典型场景做对比不然DR的价值根本体现不出来很多文章的仿真结果看起来DR没啥用其实就是数据场景没选对。写在最后我先跑通无DR版本再逐步加复杂度的调试顺序建议这套日前经济调度模型我个人建议从简单到复杂分四步走第一步只放开风光储能电网交互不启动柴油机也不启动DR用纯LP模型把功率平衡逻辑跑通第二步加入柴油机把二次成本函数和爬坡约束加上此时变成MIQP先跑通再说提速第三步加入需求响应分别验证单时段上限和累计次数约束对比有无DR的成本差第四步再做灵敏度分析把储能容量、DR比例、电价这些参数扫一遍。每一步都对应一组可视化检查功率平衡图、SOC曲线、各成本项比例。任何一步结果不符合物理直觉先别急着调求解器参数回去检查约束本身。把这一步作为标准流程执行下来你会发现“基于风光储能和需求响应的微电网日前经济调度”这套Matlab代码不仅是能跑的东西更是理解微电网运行逻辑的完整工具。
阅读完成 · 觉得有帮助?
咨询建站