十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

微电网多时间尺度联合调度:PSO与MPC协同优化实现

微电网多时间尺度联合调度:PSO与MPC协同优化实现 最近把微电网多时间尺度联合调度优化这个项目重新完整实现了一遍正好借这篇博客把整个方案摊开聊一聊。核心思路用一句话说就是日前用粒子群算法PSO做全局寻优日内和超短期用模型预测控制MPC做滚动优化三个时间尺度各自带不同的目标函数再通过多目标加权把经济性、跟踪精度和功率平稳性串到一起。整套东西用Matlab实现从建模到出图大概一千行代码左右没有依赖商业求解器纯脚本就能跑通。这篇文章不打算端着讲理论而是按我实际做项目的顺序来怎么从问题出发定技术路线三级目标函数和约束怎么设计粒子群怎么编码MPC滚动循环在Matlab里怎么写以及运行过程中会踩到的各种坑。无论你是刚接触调度优化的研究生还是在做综合能源系统集成的工程师应该都能从里面找到可以直接“抄作业”的部分。1. 多时间尺度调度在做什么三个层级的分工与关键技术选型1.1 为什么单时间尺度调度行不通在接入高比例光伏、风电之后调度最头疼的问题就是预测精度。光伏功率的日前预测误差经常能到20%左右但超短期预测未来15分钟到1小时误差通常能控制在5%以内。如果我们只在日前做一次调度把未来24小时的机组出力和储能计划全部定死那第二天实际光伏或风电一波动计划就跟实际严重偏离要么削负荷要么产生大量弃风弃光。反过来如果只做实时控制也就是所谓“单步优化不回头看”又会因为没有全局眼光让微燃机、储能长期运行在局部最优状态甚至可能出现电价高峰期储能没电可用这种尴尬局面。所以工程上更成熟的做法是“分层分段逐步细化”日前先做一个全局的经济规划日内根据更新的预测去修正超短期再根据实时量测做精细调节。这就是多时间尺度联合调度的出发点本质上是把不确定性按时间尺度逐步消解掉。1.2 为什么选PSO加MPC这个组合先说日前层。日前调度的优化问题里目标函数往往是二次函数组合微燃机发电成本通常写成aP²bPc加上储能SOC前后时段的强耦合约束、分时电价的阶梯边界问题本身是非线性的甚至如果你加上机组启停的0/1变量就变成混合整数非线性规划。对这种问题传统数学规划方法要么需要线性化处理要么必须依赖Gurobi、CPLEX这类商业求解器。但很多课题和工程场景下我们没有商业求解器可用这时候粒子群算法PSO就非常合适它不要求问题可导、不要求凸性只要有适应度函数就能找优Matlab实现也方便。再说日内和超短期层。这两个时间尺度共同的特点是需要“边执行边修正”必须应对不断更新出来的预测数据。模型预测控制MPC的核心思想正好就是滚动优化加反馈校正每一时刻都去优化未来有限时域内的控制序列但只执行当前这一步下一时刻重新优化。这种策略天然适合日内和超短期的调度修正。我在这套方案里做的一个关键设计是日内层和超短期层的MPC滚动优化核心求解器也用PSO。一方面MPC如果写成标准二次规划理论上可以用quadprog求解但在储能充放电效率非线性、约束需要灵活调整的场景下用PSO可以少做很多推导和简化代码风格也统一另一方面因为滚动优化的决策变量维度小、预测时域短PSO在Matlab里求解速度足够快完全能满足日内甚至超短期的实时性要求。2. 调度模型怎么建三级目标函数与多目标加权的建模细节2.1 系统结构与变量定义我搭建的测试系统是一个典型微电网主要包含四类设备微燃机MT、储能系统BESS、光伏PV、风电WT微电网通过联络线PCC与配电网交互既可以向电网购电也可以反送多余电量。每条母线上有一个公共负荷假设负荷、光伏和风电的预测数据在仿真中是已知的可以通过历史数据加噪声模拟。调度的核心任务是决定每个时段微燃机出力P_mt(t)、储能充放电功率P_bat(t)、联络线交换功率P_pcc(t)从而在满足功率平衡和各类设备约束的前提下让经济性和跟踪性能等指标最优。功率平衡是最基本的约束P_mt(t) P_pv(t) P_wind(t) P_bat(t) P_pcc(t) P_load(t)储能模型采用一阶SOC递推SOC(t1) SOC(t) - P_bat(t) * Δt / Cap其中P_bat(t)0表示放电P_bat(t)0表示充电。充放电效率可以分别设置但为了在PSO和MPC中处理方便我通常采用一个统一的等效效率系数并且对充放电功率加限幅约束。约束还包括微燃机出力上下限和爬坡约束、储能功率限幅、SOC上下限、联络线功率限幅。三层优化均包含这些约束但处理方式不同日前和日内我用罚函数把不可行解压低超短期因为滚动频率高我加了松弛变量来避免无解。2.2 三级时间尺度各自的目标函数三层目标函数的设计是整个项目的灵魂。标题里强调“三级时间尺度采用不同目标函数”这一点千万不能理解成“把权重换个数字就行”而应该是三个层级的优化目标本身有本质区别。日前层Day-Ahead时间尺度24小时步长15分钟共96个点的目标函数以经济性为主导J_day Σ [ C_mt(P_mt(t)) C_pcc(P_pcc(t)) C_bat(P_bat(t)) C_curtail(t) ]其中C_mt是微燃机燃料成本C_pcc根据分时电价计算购电或售电费用C_bat是储能的充放电折旧成本C_curtail是弃风弃光惩罚项。日前层的任务是在预测数据基础上给出一个24小时的经济运行基准计划包括联络线功率参考值P_pcc_ref(t)和储能SOC参考轨迹SOC_ref(t)。日内层Intraday时间尺度未来4小时步长15分钟预测时域16步每15分钟滚动一次的目标函数则在经济性和跟踪日前计划之间做平衡J_intra Σ [ λ1 · (P_pcc(t)-P_pcc_ref(t))² λ2 · C_oper(t) λ3 · (ΔP_pcc(t))² ]其中第一项是让联络线功率尽量贴近日前计划不能太偏离第二项是短时间内的运行成本第三项是联络线功率变化惩罚防止功率前后抖动。可以看到日内层的核心是“修正”不是“重规划”。超短期层Ultra-short term时间尺度未来30分钟步长5分钟预测时域6步的目标函数继续收窄聚焦点J_ultra Σ [ μ1 · (P_pcc(t)-P_intra_ref(t))² μ2 · (ΔP(t))² μ3 · (SOC(t)-SOC_ref(t))² ]这里的P_intra_ref是日内层刚给出的最新参考轨迹所以超短期的主要目标是高频跟踪和平抑波动经济性已经不是最直接的关注项。2.3 多目标加权为什么不能把所有目标直接相加做过多目标优化的人都知道量纲不同会导致加权权重失去意义。如果你把“功率偏差的平方”单位是MW²直接和“运行成本”单位是元相加权重λ1很可能被无量纲的数值掩盖掉怎么调都调不出合适的结果。我在项目中用的办法是先做无量纲化再赋权最后统一折算成一个综合目标。具体来说每个子目标都除以一个基准值比如日前计划的最大允许偏差、日内平均运行成本得到0到1左右的归一化数值然后再加权求和J_total w1 · (偏差/偏差基准) w2 · (成本/成本基准) w3 · (波动/波动基准)这样做的好处是权重w1、w2、w3可以在0到1范围内直接按“重要度”语义去调节而不受量级影响。权重初值我建议按“从单目标到多目标”的步骤确定先跑三次纯单目标优化分别只考虑经济性、只考虑跟踪、只考虑平抑记录各目标的最优值作为基准再按“想让哪个目标越接近最优值权重就越大”的原则设置初值。最后根据仿真曲线微调。这是我在多个项目里验证过比较省力的做法。3. 粒子群算法求解日前层原理、编码与Matlab实现3.1 PSO的核心更新方程与参数选择粒子群算法的思想从鸟群觅食行为中来把每一个候选解看成一只有速度的鸟飞行过程中记住自己找到的最好位置个体极值pbest同时所有鸟共享整个群体找到的最好位置全局极值gbest。每次迭代每个粒子根据这两个信息更新自己的速度再更新位置v(i) w · v(i) c1 · rand1 · (pbest(i) - x(i)) c2 · rand2 · (gbest - x(i))x(i) x(i) v(i)其中w是惯性权重c1、c2是学习因子。我用的参数组合是种群100个粒子迭代300代惯性权重w从0.9线性递减到0.4c1c22速度和位置的边界都做限幅处理。为什么惯性权重要线性递减因为迭代初期权重较大粒子有较强的全局探索能力不容易被局部极值困住后期权重减小粒子在最优解附近精细搜索收敛更稳定。这是粒子群算法里最经典的参数调节策略实测下来比固定权重效果好很多。3.2 日前调度问题的编码方式与适应度函数日前层的决策变量是96个时段的微燃机出力和储能功率所以粒子位置向量是192维实数向量x [P_mt(1), ..., P_mt(96), P_bat(1), ..., P_bat(96)]粒子位置x的维度是192维这个规模对PSO来说不算大100个粒子完全能处理。如果你还要考虑机组启停的0/1变量可以扩展成混合编码在连续PSO外层再套一层二进制PSO但在我的方案里先假定微燃机一直处于开机状态重点做功率优化。适应度函数的设计是PSO成败的关键。我写了一个统一的函数输入粒子位置输出综合目标值并在里面完成约束检查function J dayAhead_Fitness(x, data, param) nT param.nT; % 96 P_mt x(1:nT); P_bat x(nT1:2*nT); % 通过功率平衡求得联络线功率 P_pcc data.P_load - P_mt - data.P_pv - data.P_wind - P_bat; % 目标微燃机成本 购电成本 储能折损 弃风弃光惩罚 C_mt sum(param.a_mt * P_mt.^2 param.b_mt * P_mt param.c_mt); C_pcc sum((P_pcc 0) .* P_pcc .* data.price_buy ... (P_pcc 0) .* (-P_pcc) .* data.price_sell); C_bat param.k_bat * sum(abs(P_bat)); C_cur param.k_cur * sum(max(0, data.P_avail - (data.P_pv data.P_wind P_mt P_bat P_pcc))); % 约束惩罚项 Pen param.penalty * ( ... sum(max(0, param.P_mt_max - P_mt).^2) sum(max(0, P_mt - param.P_mt_min).^2) ... sum(max(0, param.P_bat_max - P_bat).^2) sum(max(0, P_bat param.P_bat_max).^2) ... sum(max(0, abs(P_pcc) - param.P_pcc_max).^2) ... sum(max(0, param.SOC_max - SOC).^2) sum(max(0, SOC - param.SOC_min).^2) ... ); J C_mt C_pcc C_bat C_cur Pen; end这里最值得注意的是约束处理方式。我没有在PSO内部去显式修复不可行解而是用平方罚函数把越界量放大后加到目标函数里。惩罚系数param.penalty要取得足够大我通常取1e6到1e8否则粒子会“钻空子”选择越界但目标值更低的解。平方形式比一次绝对值形式收敛更好因为越界越多惩罚越大梯度方向也更明确。3.3 PSO主循环代码PSO主循环的框架比较固定我直接贴出经过简化的版本for iter 1:param.iterMax w 0.9 - (0.9 - 0.4) * iter / param.iterMax; % 惯性权重线性递减 for i 1:param.nPop % 更新速度 v(i,:) w * v(i,:) c1*rand(1, dim).*(pbest_pos(i,:)-x(i,:)) ... c2*rand(1, dim).*(gbest_pos - x(i,:)); % 速度限幅 v(i,:) max(min(v(i,:), param.vMax), -param.vMax); % 更新位置 x(i,:) x(i,:) v(i,:); % 位置限幅 x(i,:) max(min(x(i,:), ub), lb); % 适应度 J(i) dayAhead_Fitness(x(i,:), data, param); % 更新个体极值 if J(i) pbest_val(i) pbest_val(i) J(i); pbest_pos(i,:) x(i,:); end end % 更新全局极值 [bestVal, idx] min(pbest_val); if bestVal gbest_val gbest_val bestVal; gbest_pos pbest_pos(idx,:); end history(iter) gbest_val; end这段代码看起来简单但有三个地方容易出错。第一个是速度限幅的时机一定要在更新位置之前做限幅否则速度过大直接导致位置越界第二个是rand函数每次调用都会生成不同随机数如果不加rng设置PSO结果每次都不一样复现性很差建议在每个场景前用rng(2024)固定种子第三个是边界重置策略我采用简单的截断也就是越界就拉回边界并清零对应速度分量这样比直接截断效果更好可以避免粒子反复越过边界又弹回来的振荡。3.4 日前调度的结果怎么用日前优化跑完之后得到的是96个时段的P_mt_ref(t)、P_bat_ref(t)、P_pcc_ref(t)以及由P_bat递推得到的SOC_ref轨迹。这些参考轨迹并不会直接作为控制指令下发而是传给日内MPC作为跟踪目标。所以从设计逻辑上看日前层的作用更像“给全天定一个经济运行的基调”而不是“拍板每个时刻的精确值”。这一点在代码架构里要理清楚你后续写MPC时才会明白为什么目标函数里是“偏差平方”而不是“绝对值最小”。4. 模型预测控制滚动优化日内与超短期的Matlab实现4.1 MPC三要素在电力调度中的对应MPC有三件事预测模型、滚动优化、反馈校正。很多人刚开始接触MPC会觉得它只是个“高级PID”但放在调度场景里它的优势非常具体。预测模型对应的是负荷、光伏、风电在未来预测时域内的变化趋势我直接用预测序列当作已知输入不需要复杂的动态模型辨识滚动优化对应的是每一时刻求解一个有限时域优化问题得到未来几步的控制序列反馈校正对应的是求解完之后只执行第一步然后下一时刻用最新量测值比如储能SOC、联络线实际功率更新状态重新开始优化。这三个环节在Matlab里的实现其实很直观外层是一个for循环相当于时间推进内层调用一个优化函数优化函数返回当前时刻应该执行的功率值然后更新状态变量。理解了这个结构所有MPC相关的调度代码都是一个套路。4.2 日内MPC的建模与滚动时域设计日内层MPC我设置的时间尺度是步长15分钟预测时域16步也就是滚动优化未来4小时每15分钟执行一次优化。日内决策变量维度是16×232因为要在这16步内同时决定P_mt和P_bat。联络线功率P_pcc由功率平衡推出。这个维度用PSO求解非常快50个粒子、100代迭代在普通笔记本上实测约0.1至0.2秒完成一次优化完全可以接受。日内MPC的目标函数设计为J λ1 · Σ(P_pcc(t)-P_pcc_ref(t))² λ2 · Σ(成本项) λ3 · Σ(P_pcc(t)-P_pcc(t-1))²这里有一个小细节λ3对应的功率变化惩罚项既能平抑功率波动又能防止储能频繁充放电切换。我经常看到有人只写前两项结果日内优化出来的联络线功率一会儿正一会儿负现场设备根本没法执行储能也跟着来回切换寿命损耗很大。4.3 超短期MPC有什么不同超短期层我把时间尺度缩到步长5分钟预测时域6步也就是滚动优化未来30分钟每5分钟执行一次。超短期MPC与日内MPC的差异不只是时间尺度缩短目标函数的优先级也变了。超短期的目标函数里跟踪日内参考轨迹的权重μ1是最高的其次是功率平滑项μ2经济性项在这个层级基本可以忽略。因为超短期存在的意义就是“应对快波动尽量贴近日内计划”如果在第五分钟还在考虑“省几分钱电费”很可能导致大范围偏离计划反而让日内层白优化了。这种“不同层级、不同目标侧重”的设计是这套多时间尺度调度方案里最值得仔细琢磨的部分。4.4 滚动优化的Matlab主循环结构我把日内MPC的滚动循环简化成下面这样超短期只是预测序列和步长不同框架完全一样for k 1:96 % 日内96个15分钟点 % 获取当前预测序列模拟滚动更新 load_pred data.load_pred_full(k : k16); % 未来16步负荷预测 pv_pred data.pv_pred_full(k : k16); wind_pred data.wind_pred_full(k : k16); % 提取日前计划中当前时刻的参考值 pcc_ref_seq plan_day.pcc_ref(k : k16); % 调用MPC优化函数内部用PSO求解 u_opt mpc_rolling_optimizer(load_pred, pv_pred, wind_pred, ... pcc_ref_seq, soc_now, param); % 只执行第一步 P_mt_exec(k) u_opt(1); P_bat_exec(k) u_opt(2); % 状态更新仿真模型 soc_now soc_now - P_bat_exec(k) / param.Cap * param.dt_intra; % 加入量测噪声模拟反馈校正 soc_now soc_now 0.001 * randn; end这里最关键的工程决策是“只执行第一步”。很多初学MPC的人会在这一步犯错把优化出来的未来16步全部执行完到了下一时刻又重新开始优化这不叫MPC这叫开环优化完全失去了反馈校正的意义。真正的MPC必须每次只执行当前时刻的控制量然后通过量测更新状态再滚动到下一个时刻。4.5 MPC滚动优化用PSO求解的代码怎么写mpc_rolling_optimizer这个函数其实就是一个轻量级PSO决策变量维度为2×HH是预测时域由于维度低求解速度很快。可以直接复用第3章的PSO核心函数只需要替换适应度函数。为了进一步提高速度我在热启动上做了点优化每次滚动优化把上一次得到的最优控制序列作为当前粒子群的一个初始粒子其余粒子在这个解附近随机生成。这样做有两个好处一是温度启动让PSO收敛速度快很多二是MPC相邻滚动时刻的最优解本来就很接近从上一个解附近开始搜得到的最优解也更平滑。function u_opt mpc_rolling_optimizer(load_seq, pv_seq, wind_seq, ref_seq, soc0, param) H length(load_seq) - 1; % 决策变量P_mt(1:H), P_bat(1:H) dim 2 * H; % 热启动初始粒子 x0 [param.P_mt_last, param.P_bat_last]; % 上次最优解 x0 ensure_bounds(x0, param.lb, param.ub); % 粒子群初始化时把x0放进去 x_init(1,:) x0; for i 2:nPop x_init(i,:) x0 0.05 * param.ub .* randn(1, dim); end % 然后执行标准PSO迭代... % 返回当前时刻控制量 u_opt [gbest_pos(1), gbest_pos(H1)]; end注意这个热启动策略在超短期MPC中效果特别明显因为超短期步长5分钟前后两个滚动时刻的实际运行状态变化更小热启动能让PSO在20代以内就收敛到高质量解。5. 三级时间尺度如何协调联动5.1 通过参考轨迹逐级传递实现“分工不分家”三级时间尺度能够协调起来靠的是参考轨迹的逐级传递日前层给日内层下发P_pcc_ref和SOC_ref日内层修正后给超短期层下发新的P_intra_ref超短期层最终输出执行功率。这个链条看起来简单但里面有一个经常被忽略的问题当日内层发现预测与实际偏差太大它到底应不应该严格跟踪日前计划我的做法是给日内层设定一个“允许偏离带宽”。如果负荷、光伏的实际预测和日前预测偏差在某个阈值以内比如2%日内层就在目标函数里加大λ1让联络线功率尽量贴近日前计划如果偏差超过阈值就适当减小λ1允许日内层为了安全和经济重新调整功率分配。这个阈值不需要很精细我用仿真扫一遍就能确定。5.2 权重协调的联动调节技巧多目标加权在三个不同层级之间的联动本质上是给每个层级定“任务”和“边界”。我在项目里是这样定的日前层w1经济性0.7w2弃风弃光0.3主要让成本低日内层λ1跟踪日前0.5λ2经济性0.3λ3平滑0.2超短期层μ1跟踪日内0.6μ2平滑0.3μ3SOC恢复0.1。这套初值不是拍脑袋拍出来的而是先用归一化方法把量纲统一再根据“哪个目标在这个层级最应该被保证”去定优先级。例如超短期层里SOC恢复权重μ3虽然只有0.1但它的作用非常关键它保证储能SOC在一天结束时能回到初始值附近不至于因为逐级跟踪导致“电量漂移”第二天没有储备可用。5.3 防止功率频繁调节的工程化技巧多时间尺度调度在实际工程中很容易出现“因为预测更新所以每次都让设备动作一次”的问题。如果超短期层每5分钟就改变微燃机工况那么微燃机爬坡磨损和储能循环寿命都会受到严重影响。我的解决办法有两个。第一在超短期MPC目标函数里加入了“动作惩罚项”也就是前面代码里的ΔP项第二在滚动循环中加了一个简单的死区逻辑如果本次优化结果与当前执行值的偏差小于额定功率的1%就直接沿用上一时刻的设定值不执行新的调节。这个死区逻辑在代码里就两行if abs(P_mt_exec(k) - P_mt_exec(k-1)) 0.01 * param.P_mt_rated P_mt_exec(k) P_mt_exec(k-1); end别小看这一步它能把设备动作次数减少30%以上对工程落地非常重要。6. 完整Matlab代码架构与运行流程6.1 文件组织与目录规划很多人做Matlab项目容易把所有函数堆在一个脚本里跑通一次后再改就非常痛苦。这个项目我强烈建议按功能拆文件我的目录结构供参考Main.m主程序负责加载参数、调用三层优化、保存结果data_init.m定义系统参数生成负荷/光伏/风电数据设置电价pso_solver.m通用PSO函数接收适应度函数句柄和边界输出最优解day_ahead_opt.m日前层优化调用pso_solver返回日前计划mpc_roll_opt.m日内/超短期MPC滚动优化负责时间循环和结果存储fitness_day.m / fitness_mpc.m分别为两个层级提供适应度函数plot_results.m结果可视化。这样一个文件一个职责排查问题的时候不用翻几百行代码。特别是通用PSO函数和适应度函数分离后续换目标函数、换约束条件都能减少改动量。6.2 主程序流程先日前、再日内、最后超短期主程序的逻辑非常简单就是一个顺序执行的三层结构% 1. 日前层得到全天96点计划 plan_day day_ahead_opt(data, param); % 2. 日内层按15分钟滚动修正 plan_intra mpc_roll_opt(plan_day, data, param, intraday); % 3. 超短期层按5分钟滚动精细执行 plan_ultra mpc_roll_opt(plan_intra, data, param, ultra);在实际跑数据的时候日内层和超短期层并不是做完全独立的两轮循环而是一天内日内层执行了每15分钟一次优化而每次日内优化完成后在执行这15分钟内的三个5分钟超短期点时会调用超短期MPC。更严谨的主循环是嵌套的但拆成两步跑可以更快验证各层逻辑我建议新手先按顺序执行调试通过后再改嵌套版本。6.3 结果评价指标与可视化只跑出一堆数据还不够你得有评价指标来回答“三级协调到底比单层调度好在哪里”。我常用的三个指标是总运行成本衡量经济性单位元联络线功率跟踪偏差RMSE衡量对日前计划的执行程度设备动作次数/功率波动率衡量可执行性和设备寿命影响。可视化方面我一般画三张图第一张是96点联络线功率对比把日前计划、日内修正、超短期最终执行三条曲线放一起第二张是储能SOC曲线看有没有漂移和越界第三张是成本收敛曲线看PSO迭代过程是否正常。这三个指标加上三张图基本就能判断方案是否合理。7. 常见问题与实战避坑速查7.1 PSO每次跑出来的结果都不一样这是PSO类随机算法的通病原因很简单初始粒子群是随机生成的。解决办法一是用rng固定随机种子保证复现性二是增大种群数量和迭代次数让算法稳定收敛到相近结果三是可以跑多次取最优值。我习惯在代码里写两个开关一个是“调试模式”nPop30, iterMax50跑得快一个是“正式模式”nPop100, iterMax300结果稳定避免每次都跑完整参数浪费时间。7.2 滚动优化速度不够超短期卡顿超短期层每5分钟就要调用一次优化如果你的PSO每次要跑好几秒肯定不行。我实际调优的做法有三个一是把预测时域从6步缩短到4步决策变量从12个降到8个求解速度提升接近一半二是用4.5节的热启动策略显著减少迭代次数三是在适应度函数里减少不必要的重复计算比如电价序列、预测序列在滚动过程中不变的部分可以提前缓存。7.3 约束不满足导致MPC无解在滚动优化中如果未来时段功率需求极端可能出现即使设备和联络线都满出力也无法满足功率平衡的情况这时候MPC优化问题无解。我采用的工程解决办法是加入松弛变量在功率平衡约束中加一个可控的虚拟负荷项目标函数里对这个虚拟负荷加一个很大的权重让它在一段有限的时段内允许少量失负荷但尽量把失负荷量控制在极小范围。这个处理在调度工程里非常常见比直接让优化器报错强太多。7.4 权重不好调改一个权重另一个目标就爆炸这是因为子目标之间本身存在矛盾经济性最好意味着储能尽可能在低价时充、高价时放但这会导致联络线功率偏离日前计划较大。我的体会是不要“直接调权重”而是先把每个目标都归一化到同一数量级再用“优先级分层”的思路高优先级的子目标用加权平方项低优先级的子目标用惩罚项或软约束。例如超短期层里“SOC恢复”优先级最低我就把它写成软约束让MPC在无法满足时通过罚函数自行权衡而不是硬碰硬地加进目标函数。7.5 储能SOC一直漂移每天结束回不到初值这个问题如果只在日前层做优化通常不太明显但在MPC逐级跟踪后会放大。原因是日内层和超短期层只关心未来几个小时的SOC变化完全没有意识要把SOC保持在一个合理范围。解决办法是给每层MPC的目标函数中加入“SOC末端恢复项”也就是把预测时域末端的SOC与初始SOC或日前SOC计划的偏差加入目标函数权重不大但能起到“拉住”SOC的作用。7.6 日前计划与日内实际执行之间出现明显跳变出现这个现象通常是日前层忽略了爬坡约束或者日内层λ3平滑权重设得太小。我处理这类问题时会先检查日前层约束里有没有加入微燃机爬坡限制如果加了还是跳变就加大日内目标函数中λ3让日内在靠近日前计划的同时尽量保持功率平滑过渡。跳变还可能是储能SOC在日前计划里已经接近边界导致日内层被迫改变运行方式这种情况下要回溯日前储能SOC轨迹是否留了足够的充放电裕度。我把上面这些问题整理成一个速查表格方便你拷贝下来对照排查现象可能原因排查顺序PSO结果不稳定随机种子未固定、种群数太小先固定rng再加大nPop超短期MPC卡顿预测时域太长、PSO迭代太多缩短时域启用热启动MPC报无解功率平衡无法满足增加松弛变量某个目标完全失控未做归一化就加权先除以基准值再合成目标SOC持续漂移MPC缺SOC恢复项加入末端SOC软约束日前和日内跳变日前漏爬坡约束或λ3太小补爬坡约束加大平滑权重这张表里的问题基本覆盖了我重写这个项目过程中遇到的大部分“疑难杂症”。最后再分享一个实际体会这个项目跑通不难真正耗时的是让结果“符合物理直觉”。我调试时最常用的一招是把所有子目标先折算成“等效经济成本”比如跟踪偏差每偏离1MW约等于损失多少元功率波动每变化1MW/min等于消耗多少次储能循环寿命。折算完之后所有权重都可以用“价格”来理解调参就从一个玄学问题变成一个经济优化问题。另外整套代码里所有时间步长、预测时域、权重参数我都集中放在data_init.m顶部的结构体里改参数不需要翻主程序。你复现这个项目时先跑通默认参数再按自己的系统改数据最后根据上面的速查表调优会顺利得多。
返回列表