2026/10/10 15:22:35

风-光-储互补调度建模与Matlab实现:含废弃矿井抽蓄

风-光-储互补调度建模与Matlab实现:含废弃矿井抽蓄 风电、光伏、储能这三个词近几年几乎成了新能源领域的标配。但把三者放到同一个优化框架里做“互补调度”尤其是把电池储能和废弃矿井改造的小型抽水蓄能电站放在一起联合运行这里面的建模细节和工程约束比想象中要多不少。我最近正好完成了这样一个课题用Matlab完整搭建了风-光-储含废弃矿井抽蓄互补调度模型跑了典型日和参数灵敏度分析整个过程踩了不少坑也沉淀了一些可以直接复用的经验。这篇文章就把整套思路、数学模型、代码落地方式和调试技巧一次讲清楚适合正在做新能源调度方向研究、或者准备用Matlab做优化模型的同学参考。1. 为什么要把风电、光伏和两种储能放到同一个调度框架里1.1 风光出力的时间错位与“反调峰”问题先说说这个课题的出发点。风电和光伏虽然都是清洁能源但它们的出力特性天然存在时间错位风电往往夜间出力大、白天出力小冬春季节整体偏强光伏则是中午达到峰值、傍晚快速跌落夜间完全为零。这种错位听起来像是“互补”但在实际电网运行中反而制造了麻烦。举个简单的例子一个100MW风电场在夜间出力可能达到80MW但此时负荷可能只有60MW到了白天光伏50MW在中午完全满发风速却普遍偏低风电可能只剩20MW。如果这两个电源直接并网电网调度员就得在短时间内频繁调整火电或购买调峰服务否则要么夜间多余的风电被弃掉要么白天光伏高峰时段需要大量向下调节。这就是所谓的“反调峰”特性——新能源出力曲线和负荷曲线并不吻合而且波动幅度大。解决思路也很直接引入储能把多余的电先存起来等负荷需要的时候再放出来。但储能的选择并不唯一这也引出了下一节的问题。1.2 电池与抽水蓄能快慢搭配、长短结合储能的类型很多但适合大规模新能源配建的主要还是电池储能BESS和抽水蓄能。这两类储能的特性差异非常明显可以这样理解电池储能的优势是响应速度快毫秒级到分钟级就能完成充放电切换而且能量转换效率高通常能达到85%到95%布置灵活、不受地形限制。缺点是单位容量成本高循环寿命有限磷酸铁锂一般在6000到8000次大规模配置时初始投资压力很大。抽水蓄能正好反过来启动速度以分钟计响应速度不如电池但单机容量可以做很大寿命长达40到50年单位千瓦时成本远低于电池。主要的制约是地理条件——要有合适的高低落差和水源常规抽蓄电站选址非常挑剔。所以在这个课题里我选择把两者搭配使用电池储能负责平抑快速波动、提供短时功率支撑抽水蓄能负责日内或数小时尺度的大容量能量搬移。类比一下电池像水杯抽蓄像水桶日常喝水用水杯但真要储水浇地得靠水桶。1.3 废弃矿井改造小型抽蓄的工程可行性常规抽蓄电站选址难废弃矿井这种“特殊资源”就很有意思了。国内很多矿区开采了几十年后资源枯竭留下了大量竖井、斜井和巷道。这些地下空间其实有很好的改造潜力把矿井巷道作为下水库在地面修建一个小型上水库利用矿井原有的垂直深度形成水头就构成了一座小型抽水蓄能电站。这么做的好处有几个一是废弃矿井本身已经具备地下空间省去了新建地下洞室的高昂成本二是井下结构相对封闭渗漏问题比地面水库更容易控制三是很多矿区靠近负荷中心或电网末端电力接入条件不错。能量规模也很好估算。假设可利用巷道容积为10万立方米有效落差80米综合转换效率0.7理论储能量就是E ρghVη ≈ 1000 × 9.8 × 80 × 100000 × 0.7 ≈ 5.5×10^10 J ≈ 152 MWh150MWh的储能容量已经相当于一个几十兆瓦时的电池储能站的规模但单位成本低得多。当然这只是理论值实际还要考虑巷道渗水、岩体稳定性、泥沙淤积等一系列工程问题但在调度建模层面把它当作一个容量和功率受限的储能单元来刻画是成立的。2. 各设备数学建模与关键参数2.1 风电与光伏出力的简化建模调度模型的精度取决于各设备模型的合理性但也没必要过度复杂。在小时级调度里风电可以用风速-功率曲线来描述。标准的风电功率曲线是分段函数P_w(v) 0, v v_cut_in 或 v ≥ v_cut_outP_w(v) P_r × (v - v_cut_in) / (v_r - v_cut_in), v_cut_in ≤ v v_rP_w(v) P_r, v_r ≤ v v_cut_out其中v_r是额定风速v_cut_in和v_cut_out分别是切入和切出风速。实际代码里可以用向量化计算把风速数据一次处理成出力序列速度很快。光伏出力模型相对更直接标准公式是P_pv P_stc × (G_t / G_stc) × [1 k × (T_cell - T_stc)]其中G_t是实际辐照度G_stc是标准测试条件辐照度1000W/m²T_cell是电池板温度T_stc是标准测试温度25°Ck是温度系数通常为负值约-0.004/°C。电池板温度可以由环境温度推算也可以直接用历史数据。为什么要用这么简化的模型因为调度模型的决策变量很多如果每个时刻的光伏出力都依赖复杂的物理方程求解时间会成倍增加。简化模型的误差在小时级调度可接受范围内重点是捕捉出力的时序特征。2.2 电池储能SOC与老化模型电池储能建模的核心是SOC荷电状态的递推关系。设电池额定容量为E_bat充电功率为P_ch(t)放电功率为P_dis(t)充放电效率分别为η_ch和η_dis时间步长为Δt则SOC(t1) SOC(t) (η_ch × P_ch(t) - P_dis(t) / η_dis) × Δt / E_bat这个公式体现了两个关键点充电时实际存入电量是输入功率乘以效率存进去比用掉的少放电时消耗的电量要除以效率放出来的功率折算成SOC的减少量要大一些。效率不对称是电池真实特性的反映建模时一定要区分。SOC的上下限要留余量频繁的过充过放对电池寿命损伤很大。我一般设置SOC下限0.1、上限0.9这样30MW/60MWh的电池实际可用容量是48MWh。另外一个容易忽略的问题是电池老化成本。在目标函数里如果不考虑电池循环损耗优化器会倾向于频繁充放电这不现实。做法很简单给每次充放电加一个单位折旧成本比如每MWh充放对应几十元的老化费用数值根据电池价格和循环寿命折算。2.3 矿井抽蓄的水量平衡与能量约束抽水蓄能的建模比电池复杂一些核心是水量平衡方程。设抽蓄储能量为S(t)与水库水量成正比发电功率为P_gen(t)抽水功率为P_pump(t)发电效率η_gen和抽水效率η_pump则S(t1) S(t) - P_gen(t) × Δt / η_gen η_pump × P_pump(t) × Δt功率和流量的关系通过水头连接P ρgQh实际建模时不需要直接处理流量把功率作为决策变量储能量作为状态变量就够用。矿井抽蓄有两个特殊约束需要注意。第一上水库和下水库的容量通常不对称——下水库利用巷道空间往往比上水库大。所以储能量上下限要分别设定我常用S_min和S_max表示其中S_max取决于上水库库容因为上水库通常是瓶颈。第二抽蓄需要维持日循环即每天调度周期结束时储能量要回到起始值否则第二天就没法继续循环运行了。这个约束在数学上直接写成S(24) S(0)即可。还有一个容易出问题的地方抽蓄机组的发电和抽水不能同时进行这是一个互斥约束。后面在3.2节里我会讲怎么用整数变量处理。3. Matlab调度模型实现目标、约束与求解器选型3.1 目标函数设计三个指标怎么组合调度模型的目标函数通常不是单一的常见的有三个维度系统运行成本最小化、可再生能源消纳最大化和负荷缺电率最小化。这三个目标在数学上可以通过加权组合成一个标量目标函数。我采用的目标函数形式是min Σ C_grid(t) × P_buy(t) C_bat_degrade × (P_ch(t) P_dis(t)) λ_curtail × Σ P_curtail(t) λ_loss × Σ P_loss(t)其中第一项是从电网购电的成本如果允许向电网售电则加上售电收益的负项第二项是电池老化成本第三项是弃风弃光惩罚第四项是失负荷惩罚。λ_curtail和λ_loss是惩罚系数取值不能太小否则优化器会优先弃电而不是调度储能也不能太大否则会导致数值问题。我习惯把弃电惩罚设为购电价格的2到3倍失负荷惩罚设为购电价格的10倍以上这样储能资源会被充分调用。这个目标函数已经覆盖了经济效益和消纳指标在实际课题里比较容易出结果。如果想做更精细的多目标分析可以用帕累托前沿的方法但入门阶段加权法更实用。3.2 关键约束条件的线性化处理调度模型是一个混合整数线性规划MILP问题原因在于充放电互斥、抽蓄两种工况互斥这类逻辑需要通过二进制变量来表达。这里重点讲几个典型约束的处理。功率平衡约束是模型的主约束表达式为P_w(t) P_pv(t) P_dis(t) P_gen(t) P_buy(t) P_load(t) P_ch(t) P_pump(t) P_sell(t)左侧是各类电源出力右侧是负荷和储能充电消耗。这里P_w(t)和P_pv(t)可以是预测值但实际调度中为了考虑弃风弃光我把它们拆分成“实际出力 弃电量”的形式即实际出力P_w_actual(t) P_w_forecast(t) - P_curtail(t)这样弃电量作为一个非负变量被引入目标函数。充放电互斥约束需要引入二进制变量典型做法是大M法P_ch(t) ≤ M × u_ch(t)P_dis(t) ≤ M × u_dis(t)u_ch(t) u_dis(t) ≤ 1其中u_ch和u_dis是二进制变量M是一个足够大的常数。这里有个实操经验M不宜过大取该设备最大功率的1.1倍即可否则会带来数值求解困难。抽蓄工况互斥约束完全类似只是把充放电换成了发电和抽水。此外还有SOC上下限、抽蓄储能量上下限、购售电功率上限、日循环水量平衡约束等这些直接写成不等式或者等式即可。3.3 Yalmip建模与求解器选择Matlab里做优化建模我首选Yalmip工具箱。Yalmip的语法非常简洁特别适合把大型优化问题快速原型化。下面是调度模型核心部分的建模框架示例%% 定义决策变量 P_ch sdpvar(T, 1); % 电池充电功率 P_dis sdpvar(T, 1); % 电池放电功率 u_ch binvar(T, 1); % 电池充电状态 u_dis binvar(T, 1); % 电池放电状态 S_bat sdpvar(T1, 1); % 电池SOC P_pump sdpvar(T, 1); % 抽蓄抽水功率 P_gen sdpvar(T, 1); % 抽蓄发电功率 u_pump binvar(T, 1); % 抽蓄抽水状态 u_gen binvar(T, 1); % 抽蓄发电状态 S_psh sdpvar(T1, 1); % 抽蓄储能量 P_buy sdpvar(T, 1); % 电网购电 P_curt sdpvar(T, 1); % 弃电功率 %% 约束条件 Constraints []; % 功率平衡 Constraints [Constraints, P_w P_pv - P_curt P_dis P_gen P_buy ... P_load P_ch P_pump]; % 电池SOC递推 Constraints [Constraints, S_bat(2:end) S_bat(1:end-1) ... (eta_ch * P_ch - P_dis / eta_dis) * dt / E_bat]; % 电池充放电互斥 M 30; % 电池最大功率 Constraints [Constraints, P_ch M * u_ch, P_dis M * u_dis, ... u_ch u_dis 1]; % 抽蓄工况互斥 Mp 10; % 抽蓄最大功率 Constraints [Constraints, P_pump Mp * u_pump, P_gen Mp * u_gen, ... u_pump u_gen 1]; % 日循环约束 Constraints [Constraints, S_psh(end) S_psh(1)]; %% 目标函数省略各变量定义细节 obj sum(P_buy) lambda_curt * sum(P_curt); %% 求解 ops sdpsettings(solver, gurobi, verbose, 0); optimize(Constraints, obj, ops);求解器方面Gurobi是学术界和工业界都非常认可的MILP求解器性能出色。学生或科研用户可以申请学术免费license。如果暂时没有GurobiMatlab自带的intlinprog也能处理中小规模问题只是求解速度会慢不少。我在课题里同时测试了两种方案小规模算例24小时、节点数不多两者差异不大但参数灵敏度分析时要做几十次求解Gurobi的速度优势就很明显了。4. 仿真算例一个典型日内的完整调度过程4.1 算例参数与数据准备为了让模型跑起来并验证效果我设计了一个小型算例系统。基本参数如下表设备参数数值风电场额定容量100 MW光伏电站额定容量50 MW电池储能功率/容量20 MW / 40 MWh矿井抽蓄功率/储能量10 MW / 150 MWh抽蓄水头—80 m负荷峰值/谷值120 MW / 60 MW调度周期时间分辨率24 h / 1 h风速数据我用了一组典型夏季日数据凌晨风速较高7-9m/s午后下降4-5m/s夜间回升。辐照度数据符合钟形曲线中午12点达到峰值约900W/m²傍晚18点降为0。负荷曲线早晚双峰中午有短暂的午休低谷。这些数据虽然简化但能体现风电、光伏和负荷错位的主要矛盾。数据准备阶段有一个常见问题风速、辐照度、负荷数据来自不同数据源时间戳往往不同步。我建议进入模型前统一转化为同样的时间序列格式缺失值用线性插值补齐异常值比如辐照度超过1200W/m²直接剔除或者限幅。4.2 典型日调度结果解读调度结果很能说明问题。我把一天分成四个时段来分析凌晨0点到6点负荷处于低谷60-80MW风电出力反而最高70-90MW。模型选择让电池从1点开始以20MW功率充电约2小时抽蓄从3点开始以10MW功率抽水约4小时把多余的风电储存起来。这个时段基本不需要从电网购电弃电率被压到很低。上午6点到12点负荷逐步攀升到110MW光伏出力从0逐渐升到45MW风电下降。电池在7-9点开始放电支撑早高峰抽蓄在上午保持蓄水状态等待下午的更大负荷。中午12点到18点光伏进入大发时段12-15点之间光伏出力接近满发负荷却因为午休出现小幅回落。此时模型选择给电池充电约13-15点同时抽蓄在16点后开始发电配合光伏余量和电池补足晚高峰的负荷缺口。傍晚18点到24点光伏快速下降负荷迎来晚高峰120MW。此时电池放电、抽蓄发电同时进行加上风电夜间的回升共同满足负荷。24点前后负荷回落到80MW抽蓄在泵工况下抽水回蓄为第二天做准备。从结果数据看无储能方案下弃电率约15%纯电池方案弃电率降到6%左右而混合储能方案弃电率可以压到3%以内。这验证了“多种储能配合”的优势——电池负责灵活快速响应抽蓄承担大容量搬移二者互补后系统调节能力明显增强。4.3 参数灵敏度电池容量和矿井水头的影响参数灵敏度分析是这个课题里比较有说服力的部分。我重点考察了两个参数。第一个是电池容量对系统性能的影响。把电池从20MW/40MWh增加到40MW/80MWh弃电率从3.1%降到2.4%继续增加到60MW/120MWh时弃电率只降到2.2%。也就是说电池容量翻倍带来的边际收益递减非常明显。这个结果提醒我们储能配比不是越大越好要结合弃电率、投资成本和运行效益综合确定。第二个是矿井抽蓄水头的影响。在储能量公式里E与h成正比所以水头从80米提高到100米同样的巷道容积储能量提升25%。但水头提高意味着机组需要的扬程增加水泵和发电机的选型成本也会上升。灵敏度分析的结果是水头每提升20米系统弃电率大约下降0.5-0.8个百分点效果存在但不算巨大。如果想继续提升消纳率更有效的手段是扩大上水库库容或者优化电池容量配比。5. Matlab编程中的常见坑与排查方法5.1 求解器调用与license问题Matlab里使用YalmipGurobi的组合最常见的坑就是Gurobi的license配置。安装完Gurobi后需要把gurobi的matlab接口路径添加到Matlab搜索路径中同时设置环境变量GRB_LICENSE_FILE指向license文件。很多人在第一步就卡住报错信息往往是“Unable to locate Gurobi library”或者“License not found”。我的建议是先运行gurobi_setup函数Gurobi自带脚本确认命令行能求解一个简单的lp模型再到Yalmip里测试。如果Yalmip报错提示找不到求解器可以用sdpsettings(solver,gurobi)强制指定并检查yalmiptest是否通过。如果没有Gurobi license也不要用盗版破解直接用intlinprog完全能跑。Yalmip只需把求解器参数改成sdpsettings(solver,intlinprog)即可模型代码不需要任何改动。实际测试中24小时、单节点的小算例intlinprog跑几十秒也能出结果完全够用。5.2 模型求解慢的优化技巧调度模型一旦加了二进制变量求解时间就可能指数级增长。我遇到的典型问题是做72小时长周期调度时变量量达到数千个Gurobi默认参数求解要一两分钟灵敏度分析做几十次就很痛苦。这里分享几个亲测有效的提速方法。第一合理设置MIPGap参数。Gurobi默认的MIPGap绝对值配置有时过于严格工程上1%的相对gap通常已经足够。用sdpsettings(solver,gurobi,gurobi.MIPGap,0.01)可以显著加快求解收敛。第二避免过大的Big-M。有些同学习惯用1e6这样的值结果不仅引入了数值病态还让求解器在分支定界时大量试探。M取设备最大功率的1.1倍既不影响可行性又能让LP松弛更紧。第三尽量聚合约束。比如SOC的上下限约束写成区间形式而不是拆成两个节点约束变量规模可以压缩。Yalmip支持约束向量化像0.1 S_bat 0.9这种写法就可以。我还有一个经验是先把模型在24小时尺度上调通确认约束无冲突、结果合理再扩展到更长时间尺度。直接一上来就跑72小时一旦约束写错很难定位。5.3 结果可视化与数据对齐经验Matlab做结果可视化其实很灵活但调度结果有一点需要特别注意堆叠图stacked area plot的显示顺序。功率平衡里各个电源有正有负如果直接用area函数容易出现负值覆盖正值的问题。我习惯把负荷和各个电源出力分别画再单独画储能SOC曲线这样信息更清晰。还有一个细节是时间轴对齐。很多数据源用的是UTC时间本地时间需要转换。气象数据尤其如此——风速和辐照度如果按照UTC导入而负荷数据是本地时间两者错位一两个小时就会导致调度结果失真。我建议在读取数据时统一转换为Matlab的datetime格式并显式指定时区。可视化输出方面导出EPS或PDF时要注意字体设置Matlab默认画图导出的中文字体经常乱码。简单方案是在绘图前统一设置字体set(groot, DefaultAxesFontName, Times New Roman); set(groot, DefaultTextFontName, Times New Roman);这样在学术论文里插图效果会好很多。6. 一些个人经验和后续扩展方向调度模型的输出质量很大程度上取决于输入数据的质量和约束设置的合理性。我建议各位拿到一个真实系统时先不要急着把所有设备都加进去先把风、光、负荷三条曲线画出来肉眼判断负荷缺电时段和新能源盈余时段再设计储能容量和调度策略——往往一眼就能看出储能该配多大、该怎么充放。做这个课题时我自己最大的体会是互补调度的核心价值不是“多发电”而是“在正确的时间用正确的储能资源去填正确的缺口”。电池和抽蓄的组合一个管灵活、一个管容量协调好了弃电率能压下去高峰供电可靠性也能提上来。后续想扩展的话可以考虑这些方向一是在模型里加入机组组合和火电备用做多能源系统的联合优化二是把风电和光伏的不确定性用场景法处理做两阶段随机规划三是引入强化学习做一个实时调度智能体让它在历史数据中学习优化策略。每一块都是很好的延展课题。如果这篇分享对你有帮助后面我可以再写一篇关于废弃矿井抽蓄经济性评估和容量优化配置的详细拆解欢迎继续交流。