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

资讯详情

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

风光储微电网优化调度:粒子群算法与需求侧响应建模实践

风光储微电网优化调度:粒子群算法与需求侧响应建模实践 接手这个园区微电网调度模块之前我一直用规则表做功率分配白天光伏功率大就给储能充电晚上负荷涨上来就让储能放电跟电网的关口功率直接按“峰段少买、谷段多买”来框。这套逻辑在小规模、预测稳定时还凑合可一旦把需求侧响应加进来规则表就完全不够用了——用户侧的可平移负荷、可削减负荷是动态变量电价又是分时的风光出力还有明显的反调峰特性所有因素耦合在一起靠人工经验根本排不出24小时的最优出力计划。后来我把问题重新建模成考虑电源侧与负荷侧运行成本的优化调度问题再用粒子群算法去求解事情才真正走到正轨上。这篇文章就是我完整梳理一遍风光储微电网优化调度的模型怎么建需求侧响应怎么数学化粒子群算法怎么跟调度模型结合以及我在MATLAB上实现时踩过的那些坑。适合正在做微电网能量管理、正在学智能优化算法在电力系统应用的同学参考。1. 问题的第一性风光储微电网为什么要做“跟电网讨价还价”的调度1.1 微电网调度在调度什么先卸掉一个常见的误解微电网调度不是“有风光就优先用风光”这么简单。风光虽然边际成本趋近于零但它的出力曲线由天气决定根本不受调度指令控制。储能倒是可控但它有容量限制、充放电效率损耗、循环寿命磨损频繁深充深放会显著缩短电池寿命这部分也要换算成成本。可调负荷同样可控但让用户挪用电时段不能白挪必须给激励补偿。所以微电网优化调度的本质是在一段时间内一般取24小时步长1小时决定每个时段储能充多少放多少、和电网买多少电或卖多少电、哪些负荷需要平移或削减、是否要弃风弃光。目标函数是让电源侧运行成本加上负荷侧需求响应成本的总和最低约束条件是发电侧与负荷侧的实时功率平衡以及储能、可调负荷、电网交互功率各自的物理限制。这一步如果直接用枚举法24个时段、6到8个决策变量序列组合空间是天文数字所以必须用智能化化算法。1.2 需求侧响应为什么让问题从“线性”变成“非线性”如果只有固定负荷和储能微电网调度本质是一个线性规划问题用cplex或者linprog就能求全局最优。但一旦引入需求侧响应事情就不一样了。可平移负荷有一个“总用电量固定、运行时间可以挪动”的特性比如工厂的一台300kW设备必须在10点到15点之间运行满3小时不能拆开。这种约束在数学上是整数和逻辑组合关系等价于一个混合整数规划。可削减负荷虽然连续但补偿费用函数往往带阶梯价格目标函数又变成分段线性。加上储能SOC更新方程里充放电效率不一样充电时SOC往上走要乘效率放电时SOC往下要除效率这个分段效率函数又是一个强非线性源。三类非线性叠加在一起传统的梯度类算法非常容易陷入局部最优甚至因为目标函数在边界处不可导直接发散。这时候粒子群这类无梯度智能算法就有了用武之地它不依赖导数信息只靠目标函数的函数值比较来搜索处理非凸、不连续、黑箱形式的调度模型非常合适。2. 优化模型怎么落地目标函数、DR建模与约束条件的工程取舍2.1 目标函数电源侧成本与负荷侧成本怎么量化模型里我选取1小时为调度步长一天24个时段。目标函数共四个部分全部折算成一天的运行费用成本项表达式说明与大电网交换功率成本C_grid sum(Price_t * P_grid_t)Price_t为分时电价P_grid_t为购入功率正值表示购电负值表示售电风光运维成本C_om sum(k_pv * P_pv_t k_wt * P_wt_t)k_pv、k_wt为光伏、风电单位发电的运维系数储能损耗成本C_bat sum(k_bat * abs(P_bat_t))把充放电造成的寿命折损按电量折算为成本k_bat一般为0.02~0.05元/kWh需求侧响应成本C_dr sum(k_shift * P_shift_t k_cut * P_cut_t)k_shift为可平移负荷补偿单价k_cut为可削减负荷补偿单价这里有一个工程上的关键点电网交换功率成本要区分购电和售电。实际园区往往“峰段购电、谷段不上送”即便允许余电上网售电电价也远低于购电电价不能直接用同一个Price_t计算。我的做法是限制P_grid_t只能为正即不允许倒送这样成本函数就保持线性且单调粒子群搜索时目标函数也更平滑。储能损耗成本是很多人容易漏掉的一项。如果把电池的充放电总电量直接累进SOC而不计损耗算法会倾向于让储能持续循环做无意义的能量搬运——反正不花钱。实际模型中我会按每1kWh的吞吐量折算一个很小的损耗系数让算法在“削峰填谷带来的收益”和“电池损耗”之间做权衡。这个系数不要设得太大否则储能根本不会动作从我的测试经验来看0.03到0.05元/kWh是一个比较稳的区间。2.2 需求侧响应负荷的两种建模方式对可平移负荷我采用“总电量恒定 功率序列连续化”的处理。假设该负荷额定功率是P_rated允许运行区间为[T_start_window, T_end_window]必须在窗口内运行L小时那么约束写成sum(P_shift_t * dt) P_rated * L P_shift_t P_rated * z_t # z_t是该时段是否允许运行 sum(z_t) L # 只能连续运行L个时段工程简化粒子群无法直接处理0/1变量z_t我的妥协方案是用功率序列P_shift_t本身作为决策变量额外加一条“非窗口时段必须为0”的约束。这样粒子向量里每一维都可能被置0可行域变成一个带矩形约束的连续空间粒子越界时直接用边界值钳制。对可削减负荷建模就简单很多每个时段的削减量不能超过该时段原始负荷的某一比例比如15%或20%同时要设一个全天累计削减上限防止调过头引起用户不满。可削减负荷的补偿单价通常高于可平移负荷因为削减直接牺牲了用户的用电体验激励必须给足。这个比例系数我一般取0.15超过这个值算法就倾向于用平移负荷而不是削减负荷来响应。2.3 储能约束与功率平衡的细节处理储能模型的更新方程是调度的核心写出来不能错SOC(t1) SOC(t) - dt / E_bat * (P_dis_t / eta_dis - P_ch_t * eta_ch)其中P_dis_t和P_ch_t要分开定义不能直接用一个可正可负的P_bat_t代入。我的处理是定义P_bat_t 0表示充电P_bat_t 0表示放电在代码里用逻辑判断分开计算效率保证SOC更新准确。这种方法虽然不是纯数学的友好形式但用粒子群求解时完全没有问题因为算法只需要目标函数值和约束越界量不需要梯度。功率平衡约束是等式约束处理方式很关键。我选择把电网交互功率P_grid_t作为松弛变量从功率平衡方程直接反解出来P_grid_t P_load_base_t P_shift_t - P_cut_t - P_pv_t - P_wt_t - P_bat_t这样等式约束被精确满足不用进惩罚函数。剩下要检查的只是P_grid_t是否在关口允许范围内如果越界就把越界量送入惩罚项抬高目标函数值。这样做的好处是粒子群搜索时所有个体天然满足功率平衡惩罚项只需要关注不等式约束收敛速度明显比把等式约束也塞进惩罚函数要快一大截。3. 粒子群算法接入调度模型编码、解空间收缩与惩罚参数怎么配3.1 粒子向量怎么编码我用了最直接的方案把调度决策量按时间序列拼接成一维向量维度是3 * TT24共72维。第1段是储能功率序列P_bat(1:24)取值范围[-100, 100]kW负值充电、正值放电。第2段是可平移负荷功率序列P_shift(1:24)取值范围[0,300]非窗口时段通过初始化和边界钳制强制置0。第3段是可削减负荷比例序列ratio_cut(1:24)取值范围[0,0.15]实际削减量是ratio_cut乘以基础负荷。这段编码的核心技巧是所有决策变量都限定为连续变量避免混合整数规划带来的求解复杂性。可平移负荷的0/1状态我没有显式建模而是通过“在允许窗口内才给非零初值”和“其余时段钳制为0”来间接保证。这种简化会损失一点点最优性但换来的是粒子群可以直接上手工程收益远大于数学最优性损失。3.2 迭代框架与速度钳制标准粒子群的速度和位置更新公式如下v(i1) w * v(i) c1 * r1 * (pbest - x(i)) c2 * r2 * (gbest - x(i)) x(i1) x(i) v(i1)但在微电网调度问题里我强烈建议加一个速度钳制步骤经验公式是v_max 0.2 * (x_max - x_min)。比如说储能功率范围是[-100,100]那么储能维度上的速度上限就是0.2 * 200 40。如果不钳制粒子可能一步就从可行域飞到不可行域远端再靠惩罚函数拽回来收敛曲线会剧烈震荡。惯性权重w我采用线性递减策略迭代初期w0.9搜索范围大、全局探索强迭代后期w0.4收敛性好、局部精细搜索强。公式是w w_max - (w_max - w_min) * iter / iter_max学习因子c1和c2我取1.5比经典的2/2略小一点实测在24时段储能调度问题中更稳定。我再加了一个小技巧对每个粒子在更新后做一个局部随机微调即x x 0.01 * randn(size(x))防止粒子群早熟收敛到同一个局部极小点。3.3 约束惩罚系数怎么设不能一套参数打天下惩罚函数的通用形式是F(x) f(x) lambda1 * sum(ineq_violation1.^2) lambda2 * sum(ineq_violation2.^2)第一次实现时我用了固定惩罚系数lambda1000结果发现储能SOC经常贴着边界来回穿越P_grid越界量虽然在最后收敛到接近0但前50代粒子群几乎全在不可行域里打转。后来换成自适应惩罚系数才解决每次迭代统计当前种群的平均越界量越界量大时提高惩罚权重越界量接近0时就降低防止惩罚项过大把目标函数的真实梯度淹没。具体做法是把惩罚系数分两套SOC越界用lambda_soc10关口功率越界用lambda_grid1000。因为SOC越界0.05影响不大而关口功率越界10kW直接违反并网协议必须严惩。这样分层设计的思路比一个统一惩罚系数要合理得多。另外粒子群对惩罚项非常敏感惩罚系数过大会让目标函数失去原有的成本指引算法变成“只找满足约束的解”而忽视经济性惩罚系数过小又会返回一个明显越界的方案。需要多跑几次对比越界量与成本之间的平衡。4. 典型日仿真三个场景的成本结果与调度策略解读4.1 算例参数与基础数据我用一个典型园区微电网做测试基础参数如下配置项数值光伏装机600kW风电装机300kW储能容量600kWh储能额定功率100kW储能SOC范围[0.1, 0.95]基础负荷峰值800kW可平移负荷额定300kW连续运行3小时可削减比例上限15%关口交换功率上限200kW分时电价取工业电价典型结构峰段8-11点、18-21点1.20元/kWh平段11-18点、6-8点0.80元/kWh谷段0-6点、22-24点0.35元/kWh。光伏出力在12-14点达到峰值风电出力在夜间22点后升高基础负荷呈早晚双峰特性——中午光伏大但负荷低晚上负荷高但光伏完全消失这就是调度最矛盾的时段。粒子群参数粒子数30最大迭代次数200。每个场景独立运行10次取最优解避免随机性误导。4.2 场景对比无需求响应 vs 有需求响应的成本构成为了验证需求侧响应对总成本的影响我设计了三个场景做对比场景A无需求响应。可平移负荷固定在早上10点启动储能按“谷充峰放”运行可削减负荷为0。场景B有价格型需求响应。可平移负荷可以在允许窗口内自由选择启动时间可削减负荷仍为0。场景C完整模型。可平移负荷和可削减负荷同时参与优化储能联合调度。结果如下场景购电成本(元)需求响应补偿(元)储能损耗(元)总成本(元)A 无需求响应756202127774B 平移负荷参与69351862387359C 平移削减参与62803742616915可以看到从场景A到场景C总成本下降约11%。成本下降主要来自购电成本的减少可平移负荷从上午10点平段偏峰挪到凌晨谷段可削减负荷在晚间高峰时段削减了一部分储能腾出的容量更多用在尖峰时段放电而不是在平段和峰段之间来回搬运。这个结果说明了需求侧响应在微电网里的真实价值它不是单纯让用户“少用电”而是让用户侧的弹性成为系统调度的可调资源用最低的补偿成本撬动最大的购电成本降幅。场景C里374元的需求响应补偿换来了1282元的购电成本下降投入产出比非常可观。4.3 储能SOC曲线和负荷转移的细节解读看场景C的调度结果最典型的特征有两个。第一个是储能SOC曲线在谷段先充电到0.8以上平段小幅放电晚高峰来临前再充电到满晚高峰集中放电到0.15左右最终在仿真结束时段回到0.5初始值附近。这个“谷充-平放-峰前补充-峰段猛放”的模式正是算法对储能经济性的正确判断谷段电价低充电成本低峰段电价高放电收益高。第二个特征是可平移负荷被安排到凌晨1点到3点之间运行这段时间是典型的风电大、负荷低、电价极低的“三低谷”时段整体算下来最划算。有些朋友可能会疑惑既然谷段电价那么低为什么不把储能SOC全部充满再放原因是储能容量有限、功率有限而且SOC到0.95以上时充电效率因内阻增大而降低模型里虽然没显式写内阻曲线但惩罚函数会通过SOC越界风险间接限制过充。储能损耗成本也让“充满再放”的边际收益被逐步吃掉算法自己找到了最优折中。4.4 收敛性与算法稳定性验证粒子群的收敛曲线方面场景C在40代左右成本已经下降到7000元附近到80代基本稳定在6915元左右后有微小波动属于正常现象。我每次运行都会保存gbest的历史变化如果超过50代gbest都没有下降就判为早熟收敛。测试中还有一个有意思的现象随机数种子不同最后结果波动在1%以内说明粒子数30、迭代200对于72维的解空间已经足够。如果维数再扩大比如把可平移负荷拆成多个独立负荷粒子数建议加到50迭代次数加到300否则容易因为解空间维度上涨导致收敛不足。5. 从MATLAB实现到代码稳定运行我踩过的坑和排查方法5.1 SOC更新方向错了充电效率和放电效率写反第一次跑通模型时SOC曲线出现了“放着放着电量自己涨回去”的诡异现象查了半天才发现是SOC更新方程里的效率项方向写反了。充电时SOC增加但输入的电能有一部分变成热量损失所以有效增加量要乘以充电效率放电时SOC减少但电池输出到外部的电量小于内部减少的能量所以减少量要除以放电效率。正确写法是if P_bat 0 % 放电 SOC(t1) SOC(t) - (P_bat / eta_dis) * dt / E_bat; elseif P_bat 0 % 充电 SOC(t1) SOC(t) - (P_bat * eta_ch) * dt / E_bat; % P_bat为负 end这种低级错误在公式推演时很容易漏掉偏偏它对调度结果影响巨大。我建议在仿真主程序跑之前先写一个最小测试固定P_bat序列为恒定放电功率看SOC是否线性下降再恒定充电看是否按正确速率上升。十分钟就能验证的事别等到整个模型跑完再怀疑人生。5.2 惩罚系数导致“假收敛”目标函数卡在不可行域另一个坑是惩罚系数设得太大粒子群前期所有粒子几乎都处于不可行域函数值完全由惩罚项主导pbest和gbest的实际成本曲线看不出任何下降趋势。这种现象特别容易出现在SOC越界惩罚上因为SOC是一个累积量粒子初始化稍有不慎后面几十个时段全部越界越界量相对巨大。我的排查方法是打印每一代的平均罚函数占比如果占比长期超过50%说明可行域被惩罚淹没了。解决办法是减小相应惩罚系数同时把粒子初始化策略改成储能功率先按“谷充峰放”的经验设定初值再叠加小幅度随机扰动。这样初始种群就基本落在可行域附近后面的搜索效率完全不一样。5.3 初始种群太随机导致前100代都在“探路”粒子群算法对初始种群质量非常敏感。我最初用完全均匀随机初始化结果前60代gbest基本没有改善原因是粒子全在解空间乱飞没有利用储能“谷充峰放”这个天然的物理经验。后来我改成“启发式初始化”% 80%的粒子在随机初始基础上加入价格方向偏置 for i 1:round(N*0.8) P_bat_init -0.3 * (price 0.8) 0.5 * (price 0.4); % 叠加随机扰动 P_bat_init P_bat_init 0.2 * randn(1, 24); end这样初始种群天然携带了价差信息前20代就有明显的成本下降趋势。这个技巧在文献里不常写但实际加速效果非常明显尤其是把粒子数控制在25到40的中等规模时。5.4 多峰问题的稳定性单次最优解未必可信微电网调度目标函数虽然不是严格凸函数但也不是特别恶劣的多峰函数粒子群大概率能找到接近全局最优的解。但“大概率”不等于“绝对”我会把同一参数配置跑10次记录最优值、平均值和最差值。如果最优值和平均值差距超过3%说明种群多样性不足需要增大惯性权重或者增加粒子数如果最差值和平均值差距过大说明有粒子反复掉进SOC越界惩罚的陷阱需要调整惩罚系数。调试时我还会人为构造一个已知最优的小规模测试只取6个时段手动计算最优调度然后对比粒子群的结果。如果这个小规模测试都不对那大概率是模型或代码问题而不是算法问题。这是我个人的一个经验先小规模验证模型正确性再放大到24时段去跑优化。做这个项目下来我最大的体会是粒子群算法本身不难难的是把微电网的物理约束、需求侧响应的商业逻辑、储能的经济损耗这三件事同时放进一个数学框架里。很多人一上来就调算法参数忽略了约束建模和决策变量编码这些更底层的环节最后算法换了好几个结果还是不对。如果你也在做类似的题目我建议先从第2章的目标函数和第5章的坑入手把模型结构焊死了再回头调粒子群参数速度会快得多。
返回列表