融合风电与集群电动汽车的微电网需求响应优化调度实现
微电网、风电、集群电动汽车、需求侧响应这几个词放在一起最近几乎快成了电力系统优化调度方向的标准套餐。风电并网带来的随机性和波动性让微电网的调度难度直线上升而集群电动汽车又天然是个“移动储能池”调度得好能削峰填谷调度不好就是一群无序接入的“随机负荷”。我前阵子刚好把一个相关课题完整跑通了一遍从数学建模到Matlab仿真中间踩了不少坑也整理出一些能直接用上的经验。这篇就把整个思路、模型细节、代码实现和调试过程都摊开讲清楚给正在做同类课题的研究生或者入行不久的工程师一个能“抄作业”的参考文档。先说清楚它能解决什么问题。传统微电网调度往往只考虑常规机组、储能和固定负荷风电一接入就需要处理出力的不确定性而集群电动汽车的加入则把“源—荷—储”三个环节全打通了。需求侧响应又在用户侧增加了一个可调节维度让调度策略从单纯“追着负荷跑”变成“让负荷跟着系统跑”。这篇文章要讲的就是怎么把这几个东西统一放进一个优化模型里用Matlab求解并给出可以直接落地的代码实现思路。如果你正在写微电网相关的毕业论文、做需求响应项目或者刚接触智能调度想找一个能跑的起点这篇应该能帮你省下不少检索文献和试错的时间。下面按我的实际推进顺序来写。1. 整体设计思路为什么非要把风电、微电网、集群EV和DR放一起1.1 风电并网给微电网调度带来的本质难题风电出力由自然风速决定具有明显的间歇性、随机性和反调峰特性。白天负荷高峰时风速可能很小深夜负荷低谷时反而可能满发这在调度里是最棘手的问题。微电网本身容量小、惯量低不像大电网有那么强的调节裕度风电一波动频率和电压都会受影响。我在模型里首先做的事就是把风电处理成“不可精确预测但有一定分布规律”的随机变量。常见做法是用蒙特卡洛抽样生成风速场景再按风机功率曲线转换成出力场景。这里有个容易犯的错误直接把风电出力当成确定性常量代入模型结果算出来的调度方案在真实场景下完全不可用因为忽略了预测误差需要其他机组去平衡。所以在整体设计里风电场景集是所有后续约束的基础。调度方案必须在多个风电场景下都可行或者至少保证在大多数场景下可行这其实就引入了鲁棒优化或随机优化的思想。后面我在3.3节详细讲解法时还会提到。1.2 集群电动汽车的双重身份电动汽车EV在微电网里很特殊。它既是负荷充电时又是潜在电源放电时也就是V2G。单辆EV的电池容量不大但集群之后的总容量就非常可观了完全可以当作一个移动储能系统来用。不过集群EV的调度难度在于用户行为的不确定性什么时候接入、什么时候开走、需要充多少电这些都是随机事件。我把集群EV的调度变量分解成三部分充电功率、放电功率、以及充电/放电状态。充放电状态是一个0-1整数变量这就让模型从纯线性规划变成了混合整数线性规划MILP或者混合整数二次规划MIQP。很多新手在这块翻车就是忽略了整数变量直接把充放电功率设为连续变量并允许同时为正结果模型给出“一边充一边放”的荒唐方案。集群EV的价值在于通过需求侧响应信号可以引导它们在风电大发、负荷低谷时充电在负荷尖峰或风电出力低时放电。这个“时间平移”能力本质上是把原本刚性的充电需求变成了弹性可调的调度资源。1.3 需求侧响应把“死负荷”变“活资源”需求侧响应Demand ResponseDR在微电网中扮演的角色是给调度中心多一个调节手段。一般来说DR分两种价格型DR和激励型DR。价格型DR通过分时电价引导用户自主改变用电行为激励型DR则是调度中心直接与用户签约在特定时段削减或转移负荷并给用户补偿。在建模时我喜欢把DR处理成可转移负荷和可削减负荷两类。可转移负荷指的是洗衣机、洗碗机这类可以在时间上平移的用电设备可削减负荷则是空调、照明这类可以在短时内降低功率的设备。两种负荷的约束不同可转移负荷要满足“总用电量不变”只是时间偏移所以有累计电量约束可削减负荷则要限制削减时间和削减量不能把用户的电全断了。把DR和集群EV放一起实际上是把“源荷互动”做到了更细的颗粒度。在我的模型里需求侧响应不是单独一块而是融入到功率平衡约束中——负荷的大小本身是可以变化的这就让系统调度有了更大的可行域。2. 数学建模与关键公式拆解2.1 微电网拓扑与设备模型我采用的微电网典型结构包括双馈异步风机DFIG、光伏阵列可选、柴油机或燃气轮机作为可控机组、储能电池BESS、集群电动汽车、以及常规负荷和可响应负荷。所有设备都连接在同一个公共母线上不考虑网络潮流和电压约束这种单母线模型在目前很多研究里仍然在用也是从调度策略角度出发最常见的简化方式。可控机组的模型通常使用二次发电成本函数C_gen(t) a * P_gen(t)^2 b * P_gen(t) c其中P_gen(t)是机组在t时段的出力a、b、c为成本系数。为了用线性规划求解我会把这个二次函数分段线性化把非线性项变成多段线性近似这一步对MILP求解器来说很重要。储能电池模型比较直接用荷电状态SOC递推SOC(t1) SOC(t) (P_ch(t) * eta_ch - P_dis(t) / eta_dis) * delta_t / E_bat这里P_ch和P_dis分别是充放电功率eta_ch和eta_dis是充放电效率E_bat是电池容量。需要同时约束SOC上下限和充放电功率上下限以及充放电状态互斥约束。2.2 风电出力场景生成风电出力的随机性我采用了场景法来描述。最简单的场景生成方法是假设风速服从Weibull分布然后通过蒙特卡洛抽样得到风速样本再代入风机功率曲线得到出力序列。风机功率曲线表达式可以写成P_w(v) 0, v v_in 或 v v_out P_w(v) P_rated * (v - v_in)/(v_rated - v_in), v_in ≤ v ≤ v_rated P_w(v) P_rated, v_rated ≤ v ≤ v_out其中v_in、v_out是切入和切出风速v_rated是额定风速。抽样得到的原始场景数量往往很大直接放进优化模型会导致约束过多、求解变慢所以还需要做场景削减。同步回代消除法也叫快速前向选择是一个常用技巧把相似的场景合并成一个代表场景并重新分配概率。我在模型里取了20个场景做基础验证后来为了平衡计算时间削减到5个典型场景结果在最优解和计算速度上都能接受。这个“场景数量”的取舍在5.3节还会细化。2.3 集群电动汽车聚合模型集群EV的建模有两种思路一种是把每辆车都作为独立主体建模精度高但维度爆炸另一种是用聚合模型把一群EV当成一个大储能系统来近似。聚合模型在日前调度中足够用而且计算效率高。聚合模型的核心参数包括集群的总电池容量、总充放电功率上限、初始总SOC、以及必须满足的总电量需求。我用的约束如下SOC_ev_agg(t1) SOC_ev_agg(t) (P_ev_ch(t) * eta_ev_ch - P_ev_dis(t) / eta_ev_dis) * delta_t / E_ev_total同时要满足总充电需求约束sum(P_ev_ch(t) * delta_t) - sum(P_ev_dis(t) * delta_t) E_demand_total这里的E_demand_total是集群在调度周期结束时需要达到的总电量代表用户行驶消耗的总能量。这个约束能防止模型“只放电不充电”来省钱因为那样到时间结束EV就没电了不符合用户出行需求。集群EV的充放电效率我们通常取0.92到0.95之间实际如果考虑充电桩转换效率综合效率会更低一些我在仿真中取0.9。另外还要加入充放电功率互斥约束确保同一时段不能同时充放电。2.4 需求侧响应模型可转移负荷我用一个简单的延时模型来表达。假设某类可转移负荷的总额定功率为P_shift_total最大转移时段为L那么在t时段的实际负荷为P_shift_actual(t) P_shift_base(t) Delta_shift(t)其中Delta_shift(t)是转移变化量有上下限约束且在整个调度周期内所有Delta_shift之和为0也就是说转移前和转移后的总用电量相等sum(Delta_shift(t)) 0可削减负荷则使用削减比例约束P_cut(t) alpha_cut(t) * P_load_base(t)其中alpha_cut(t)在0到1之间代表该时段允许的削减比例。削减负荷会给用户带来不舒适感所以目标函数里要加入对应的补偿成本我用线性成本函数表示C_dr(t) c_cut * (P_load_base(t) - P_cut(t))价格型DR则通过分时电价引导不直接在约束中体现而是通过目标函数中的购电成本项影响优化结果。我这里主要做的是激励型DR因为可转移负荷和可削减负荷的约束更容易量化。3. 优化调度模型与求解方法3.1 目标函数设计调度目标常见的有经济性最优、碳排放最小、用户满意度最大、或者三者的加权组合。我的核心目标函数是让微电网总运行成本最低包括可控机组燃料成本、启停成本、从主网购电的成本、EV充放电的电池损耗成本以及需求侧响应成本。目标函数可以写为min F sum_t [ C_gen(t) C_onoff(t) C_buy(t) - C_sell(t) C_ev_loss(t) C_dr(t) ]其中从主网购电成本C_buy(t)用分时电价乘以购电功率计算向主网购电的功率不能超过联络线容量。卖电功率一般限制得比较小或者直接不考虑卖电因为微电网想在配电网里卖电涉及到电价机制问题我在基础模型里只允许购电。EV电池损耗成本是很多人忽略的一项。如果允许V2G放电实际上是在消耗电池循环寿命。这个成本为C_ev_loss(t) beta_ev * P_ev_dis(t)beta_ev是单位放电功率的电池退化成本。不加这一项时优化模型会倾向于让EV频繁放电来省购电费但在实际中用户和运营商都不乐意。加了损耗成本后模型会自发地仅在电价差足够大的时段使用V2G这更贴近真实决策。3.2 约束条件梳理我把约束分成了四类功率平衡约束、设备运行约束、EV集群约束、DR约束。功率平衡约束是硬性的P_wind(t) P_gen(t) P_buy(t) P_ev_dis(t) P_bat_dis(t) P_load(t) P_ev_ch(t) P_bat_ch(t)注意这里把充电功率和放电功率都列在等式两边因为它们的效率不同。实测中很多人把充放电功率合并成一个净功率变量虽然能简化模型但无法准确反映效率损失所以我不建议那么干。设备运行约束包括机组出力上下限、爬坡速率约束、最小启停时间约束储能SOC上下限、充放电功率上限、充放电状态互斥等。这些约束在Matlab中用Yalmip表达非常直观比如constraints [constraints, 0 Pgen Pgen_max]; constraints [constraints, SOC_min SOC SOC_max];EV集群约束已经在上面提过这里不再重复。DR约束需要注意的是可转移负荷的累计零和约束以及可削减负荷的比例限制。可转移负荷如果建模不合理容易导致“转移后负荷在某个时段超过负荷上限”的问题所以要补充逐时段的负荷上下限约束。3.3 求解方法与工具选型这个模型在Matlab里最主流的解法是Yalmip工具箱配合外部求解器比如Cplex、Gurobi。Yalmip本身不是求解器它是一个建模层让你用类似数学表达式的语法写优化问题然后再传给底层求解器求解。对于我已经把二次成本分段线性化、并且引入0-1变量的模型本质上是一个MILP问题。Gurobi或Cplex都能高效求解。如果手头没有商业求解器可以用开源的CBC求解器但性能会差一些场景多时可能很慢。我实际用的是Gurobi许可证可以通过学术许可免费申请速度确实给力。求解过程就是ops sdpsettings(solver, gurobi, verbose, 2); result optimize(constraints, objective, ops);对于一个24时段、20个风电场景、50个EV聚合体的模型Gurobi一般几十秒就能收敛到0.1%的gap以内。如果换成CBC可能要跑几分钟甚至更久。如果你要批量跑参数仿真建议优先用Gurobi或Cplex。另外如果不想用Yalmip也可以直接用MATLAB自带的intlinprog函数只是约束矩阵的构建会繁琐很多。我建议新手还是先用Yalmip把模型快速跑通再考虑优化代码效率。4. Matlab代码实现详细拆解4.1 代码整体架构我把整个仿真代码分成六个模块main.m主程序负责参数设置、数据生成、建模型、求解、出图。data_generation.m生成风电出力场景、负荷曲线、EV参数、电价数据。ev_aggregation.m把单辆EV的参数聚合成集群EV模型。build_model.m用Yalmip定义变量、目标函数和约束。solve_model.m调用求解器求解并返回结果。plot_results.m绘制各类时序曲线图比如功率平衡图、SOC曲线图、DR负荷调整图。这个模块化划分的好处是当你要改某个设备参数或换一种DR策略时只需要修改对应模块其他部分不需要动。我一般把参数全部集中放在一个struct里便于批量仿真。4.2 核心变量定义与参数设置在build_model.m里最关键的是变量维度。每个变量都要定义成“时间段×场景数”的矩阵因为我们要让方案在所有风电场景下都可行。可控机组出力和储能功率是针对每个场景的因为它们需要根据风电实际出力进行调整而EV充放电和DR负荷属于决策变量也需要分场景。注意如果采用“前瞻”调度那么第一阶段的决策比如机组启停对所有场景是相同的这需要额外加非预期约束不过在基础模型中我暂时忽略直接用场景全局优化。下面是变量的定义示例T 24; % 时段数 S 5; % 削减后的风电场景数 Pgen sdpvar(1, T, full); % 可控机组出力 Pbuy sdpvar(1, T, full); % 购电功率 Pbat_ch sdpvar(1, T, full); % 储能充电功率 Pbat_dis sdpvar(1, T, full); % 储能放电功率 u_bat binvar(1, T, full); % 储能充电状态1表示充电 Pev_ch sdpvar(1, T, full); % EV集群充电功率 Pev_dis sdpvar(1, T, full); % EV集群放电功率 u_ev binvar(1, T, full); % EV放电状态1表示放电 SOC_bat sdpvar(1, T1, full); % 储能SOC SOC_ev sdpvar(1, T1, full); % EV集群SOC需要注意的是sdpvar默认变量是连续非负的实际上sdpvar不预设非负性非负约束需要显式加constraints [constraints, Pgen 0];。我见过不少同学在这漏掉非负约束导致出现负数出力这种没物理意义的结果而且求解器也不报错最后画图才发现异常。4.3 关键约束的Yalmip表达功率平衡约束可以写成constraints [constraints, Pwind(t,s) Pgen(t) Pbuy(t) Pev_dis(t) Pbat_dis(t) ... Pload(t) Pev_ch(t) Pbat_ch(t) Pdr_cut(t)];在实际代码中因为Pwind是按场景s变化的所以需要写成循环或者用repmat扩展。处理这个细节时要注意可控机组、储能、EV的变量如果不依赖场景就必须让它们在所有场景下满足平衡也就是说这些变量其实是“场景无关”的同一组变量。但这样会导致模型过于保守因为储能可以随场景变化调整。为了平衡鲁棒性和经济性我通常让储能和EV的调度决策依赖场景可控机组出力也场景相关只有机组启停变量对所有场景相同。这样模型表达能力更强计算量增加也有限。EV聚合约束用Yalmip写出来大致就是constraints [constraints, SOC_ev(:,t1) SOC_ev(:,t) (Pev_ch(:,t)*eta_ev_ch - Pev_dis(:,t)/eta_ev_dis) * delta_t / E_ev_total]; constraints [constraints, Pev_ch(:,t) Pev_ch_max * (1 - u_ev(:,t))]; constraints [constraints, Pev_dis(:,t) Pev_dis_max * u_ev(:,t)]; constraints [constraints, sum(Pev_ch - Pev_dis) * delta_t E_demand_total];注意最后一行是总电量约束用大于等于而不是等于因为模型可以让EV多充电但绝对不能少充——如果U型约束设置不当小于等于是完全错误的会让EV在满足不了行驶需求时也给出“最优解”。实际工程中我会设置一个很小的松弛让等式两边允许有微小偏差防止数值问题导致无解。4.4 求解与结果可视化求解完成后我习惯保存结果到.mat文件然后用plot画四张图第一张各电源出力高亮叠加的堆叠面积图能直观看到调度结果中各类机组的出力占比。第二张储能和EV集群的SOC曲线。第三张负荷侧调整前后的对比包括原始负荷、可转移负荷、可削减负荷。第四张分时电价和购电功率的柱状图用来验证DR削减尖峰的效果。绘制功率平衡图时我要确保“发电放电”和“负荷充电”两条线完全重合否则说明约束写错了。有一次我发现两条线之间差了一个常数查了半天发现是储能效率的delta_t写成了1而时间是0.5小时导致能量计算差了一倍。这种问题画图一对比就能看出来。5. 实战中常见问题与调试经验5.1 求解结果为NaN或infeasible怎么办这是最常遇到的情况。infeasible说明约束集合里存在矛盾。排查思路先把所有等式约束打印出来检查边界是否一致。特别是储能SOC的初始值和最终值如果你的约束要求SOC初始0.2最终0.2但充放电功率范围和容量设置不当导致无论如何都转不回0.2就会无解。还有一个隐蔽问题可转移负荷的零和约束。如果你设定了“转移总量不变”同时又对每个时段的负荷设置了严格上下限很可能两个约束互相打架。比如负荷高峰时段你强制转移上限但其他时段容量不够接收那么多转移就无解了。遇到这种情况要么放宽上下限要么引入松弛变量并根据需要惩罚松弛量。5.2 模型求解特别慢慢的原因往往是整数变量太多。例如如果你对每辆EV都建一个0-1变量1000辆车就1000×24个变量这会让问题规模爆炸。聚合模型能把EV数量从“辆”降到“群”极大减少整数变量。另外如果启停变量和EV充放电变量都很精细模型的MIP gap收敛缓慢可以适当调大MIPGap到0.01或0.02工程上完全够用。还有一种加速技巧给0-1变量提供初始可行解。我一般先用松弛LP求解把整数变量的连续解四舍五入作为初始点然后交给MIP求解器有时能省一半时间。5.3 风电场景数量怎么选我跑过20、10、5、3个场景的对比。场景越多得到的调度方案越“对症”具体的概率分布但求解时间和内存都涨得厉害。20个场景在我的机器上要跑3分钟5个场景只要20秒而优化结果的目标函数值只差1.2%。所以如果你的研究重点不是随机优化方法本身而是DR或EV策略的对比用5个典型场景就足够支撑结论。如果要写高档次论文建议做场景数敏感性分析把5、10、20个场景的结果都列出来证明你的策略在不同场景数下都有效。5.4 如何验证模型正确性很多同学跑出结果后不知道对不对。我的习惯是做三组“退化测试”第一把风电场景全设成同一场景看结果是否和单场景模型一致第二把EV充放电效率都设为1损耗成本设为0看是否退化成普通储能模型第三把弃电成本设为无穷大看系统是否还会出现弃风。如果这些退化测试出现了预期之外的偏差那必然是模型或代码有问题。做灵敏度分析也是一种验证方式。比如增加DR用户比例总运行成本应当下降提高风电预测精度波动减小系统成本也应当下降。如果趋势不符合逻辑赶紧回头查约束。6. 这个课题还能往哪个方向延伸6.1 从确定性调度走向不确定优化本文的模型虽然用场景来刻画风电随机性但本质是“场景内确定性”的每个场景对应一套调度方案。如果你想让调度方案在风电实际出力与预测值有偏差时依然安全可以引入鲁棒优化用盒式不确定集或者椭球不确定集来描述风电预测误差然后优化最恶劣情况下的成本。好处是鲁棒性强代价是结果更保守、成本更高。做这个方向时Yalmip支持鲁棒优化建模但要仔细设置不确定集不然容易出错。6.2 多微电网协同调度我这里只考虑单个微电网但实际配电网往往是多个微电网互联。多微电网之间可以共享备用容量、交换功率整体效率高于各微电网独立运行。优化模型需要引入微网之间联络线功率变量并用交替方向乘子法ADMM分解求解或者用纳什谈判方法处理利益分配。这部分在Matlab里的实现比单微网复杂得多通常要写迭代循环但思路还是建立在单体模型之上。6.3 引入碳排放与多目标优化如果课题强调“双碳”可以在目标函数中加入碳排放项比如C_co2 sum_t [ gamma * (Pgen(t) Pbuy(t)) ]其中gamma是单位电量的碳排放因子从主网购的电算作间接排放。多目标优化可以用加权和法也可以使用NSGA-II这类启发式算法但纯MILP的精确方法在维度大时有优势而多目标进化算法能一次性得到Pareto前沿。我建议先把单目标模型跑通再改成多目标否则调试起来问题叠加根本分不清是建模错还是优化错。最后再分享一个我在代码调试上的小技巧给所有约束命名比如constraints [constraints, pow_balance: PwindPgen... ...];。Yalmip支持这种带tag的约束写法当模型无解时可以使用diagnostics optimize(...)然后查看diagnostics的详细信息Yalmip会提示哪个约束导致了冲突配合约束命名能精确定位问题。这个方法帮我省下了无数个排查无解的夜晚。这个跨“源—荷—储”的调度课题越深入越发现它是把电力系统、运筹优化、用户体验串在一起的综合体。你要是正卡在建模或者代码某一步可以按我上面的顺序把模型按设备拆开逐块验证再合到一起多半能顺利跑通。祝你们早日出图、早日写出漂亮的论文。

相关新闻

最新新闻

日新闻

周新闻

月新闻