ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

风电光伏与废弃矿井抽蓄互补调度:Matlab建模与仿真

风电光伏与废弃矿井抽蓄互补调度:Matlab建模与仿真 风电、光伏与储能含废弃矿井小型抽水蓄能互补调度运行研究这个方向近几年在新型电力系统领域讨论度一直很高。原因不复杂风电光伏装机上得飞快但出力不稳定这个老问题始终绕不开单纯靠电网调度去平衡越来越吃力储能就成了调节的刚需。而把电池储能和废弃矿井抽水蓄能放在同一个框架里研究互补调度关键是想解决一个实际问题——不同储能介质的响应速度、容量规模、成本特性差异很大怎么配合风电光伏的出力波动让系统整体运行最经济、最可靠。这篇内容我结合自己做过的Matlab仿真经验把这个研究方向涉及的建模思路、调度框架、代码实现和常见坑完整拆一遍希望能帮到正在做相关课题的同行。1. 项目整体设计与思路拆解1.1 互补调度的本质是什么先说清楚“互补调度”这四个字到底在调什么。风电和光伏的出力都有明显的间歇性和随机性但在时间尺度上恰好存在一定互补关系——白天光伏出力强夜间风电往往更充沛晴天风小阴雨天风反而常来。这种天然的资源互补是第一个层面的“互补”。但光靠风光的自然互补远远不够因为负荷曲线不配合比如傍晚光伏骤降、风电还没起来、负荷却处在晚高峰这时候就需要储能介入。所以第二个层面的“互补”是风光出力和储能调节能力的互补让储能去弥补风光预测误差和负荷偏差实现系统功率平衡。这个研究把储能又进一步拆成电池储能和废弃矿井小型抽水蓄能两类这就有了第三个层面的互补。电池储能响应速度快毫秒到秒级、布置灵活但容量成本高、循环寿命有限抽水蓄能响应速度慢一些分钟级、功率密度低但单次循环成本极低、寿命长适合大容量长时间尺度的能量搬移。把两者放在一个调度模型里互补使用本质上是在做时间尺度上的分工抽蓄负责削峰填谷、大能量吞吐电池负责快速跟踪、平滑短时波动。这个设计思路在实际工程项目里非常常见比如一些风光基地配套的“新能源储能”项目中混合储能方案正在成为主流。1.2 为什么选择Matlab做这个研究做这个方向的研究工具选择其实比较固定。Matlab在电力系统领域的使用率仍然是最高的原因有三点第一Matlab的矩阵运算天然适合电力系统的潮流计算和优化求解第二Optimization Toolbox和Global Optimization Toolbox提供了一整套现成的优化算法接口从线性规划、整数规划到粒子群、遗传算法都有成熟实现第三Simulink可以搭物理模型验证控制策略做风光储联合系统的动态仿真很方便。对于以算法研究和调度策略验证为主要目标的课题Matlab是最稳妥的选择。我通常建议代码结构上分成四个模块数据输入模块风光出力曲线、负荷曲线、储能参数、模型构建模块目标函数、约束条件、求解模块优化算法、结果分析模块出图、指标统计。这样分层的好处是后期换算法、改参数都只需要动对应模块不需要重写整套代码。1.3 废弃矿井抽水蓄能的建模特殊性废弃矿井小型抽水蓄能是这两年比较受关注的新概念。原理不复杂煤矿关闭后会留下大量的巷道和采空区如果能利用上下两个水平巷道或者矿井之间的落差构成上水库和下水库就具备修建小型抽水蓄能电站的地理条件。这个方案的现实价值在于废弃矿井的巷道系统已经存在改造成本比新建常规抽蓄电站低很多同时还能解决矿区废弃设施的再利用问题推动资源枯竭型地区的转型。但在调度建模层面废弃矿井抽蓄和常规抽蓄有几点重要差异。首先是容量限制——巷道可用的储水空间有限单站容量通常只有几十兆瓦级别属于小型抽蓄所以调度模型中不需要像常规大型抽蓄那样做复杂的库容分区但必须精确计算巷道可用容积对应的储能上限。第二是水头变化——矿井巷道的水头变化范围较大抽水和发电工况的效率会随水头改变如果想精细建模需要把效率写成水头的函数这对粒子群这类启发式算法的求解负担会明显增加。第三是运行约束——抽蓄机组的启停次数、工况转换时间约束在矿井条件下可能更严格因为巷道的水流通道切换有机械限制。这些细节决定了废弃矿井抽蓄在调度模型里不能简单地用一个标准抽蓄模型替代需要单独建一个子模块来处理它的特有限制。2. 核心模型构建与技术细节解析2.1 风电和光伏出力曲线的建模方法在这个研究里风电和光伏出力曲线可以分两种方式获取。一种是用实际数据——比如从NWP数值天气预报系统获得的历史风速和辐照度数据再通过功率曲线换算成出力。另一种是合成数据——如果没有实测数据可以用概率分布模型模拟风速常用双参数Weibull分布辐照度则用Beta分布或者基于晴空模型的确定性分量加随机扰动。做调度策略研究时我建议至少准备三组典型日场景大风光日、弱风光日、常规波动日。因为调度策略在不同场景下的表现差异很大只跑一组数据说服力不够。风电出力换算时要注意功率曲线的非线性特征。常见的做法是分段函数近似风速低于切入风速时出力为0风速在切入风速和额定风速之间时出力近似按三次方关系增长风速达到额定风速后出力保持额定值风速超过切出风速时保护性停机光伏出力模型则要考虑辐照度和温度两个因素。标准模型是P_pv P_stc × (G/G_stc) × [1 - β × (T_cell - T_stc)]其中G是实际辐照度β是温度系数T_cell是电池板温度。现实中电池板温度往往需要用NOCT模型从环境温度推算不能直接用环境温度代替否则夏季正午的光伏出力会被明显高估。2.2 电池储能模型的SOC递推与寿命损耗电池储能模块的建模核心是SOC荷电状态的递推方程。离散时间步长下第t时段的SOC由上一时段SOC和本时段的充放电功率共同决定SOC(t1) SOC(t) - P_bat(t) × Δt / E_cap其中P_bat为正值时表示放电负值为充电。这个递推关系看起来简单但实际写代码时有几个容易踩的坑。第一充放电效率要分别处理充电时实际消耗的电量要除以充电效率放电时实际发出的电量要乘以放电效率如果混用一个效率值SOC的累计误差会越来越大。第二SOC的限幅约束必须放在每个时段的迭代里不能让求解器把SOC算到0到1之外否则电池寿命评估就失真了。另一个值得关注的问题是电池寿命损耗。单纯的SOC递推只解决了“能量从哪来、到哪去”的问题没有考虑电池老化成本。电池循环寿命取决于放电深度DOD深度放电会显著加速容量衰减。在实际调度模型里我建议在目标函数中加入电池寿命损耗项用等效循环成本近似。一个实用的简化方法是已知电池全寿命周期内的总循环次数N和单位容量成本把每次等效满充循环EFC的成本折算进目标函数让求解器自动权衡“多用电池”和“少用电池”的经济性。这个改动会让调度结果更贴近工程实际。2.3 废弃矿井抽水蓄能模型的约束集废弃矿井抽水蓄能模块的建模比电池储能稍微复杂一些。除了常规的功率上下限约束还需要考虑库容约束上水库或高位巷道的水量变化由抽水和发电的流量决定而巷道容积有限所以蓄水量的上、下限是硬约束。以小时为调度步长时蓄水量的变化可以表示为V(t1) V(t) Q_pump(t) × Δt × η_pump - Q_gen(t) × Δt / η_gen功率耦合约束抽水工况和发电工况不能同时进行这是一个0-1整数变量控制的互补约束。在Matlab中用intlinprog或遗传算法处理时通常引入二进制变量抽水时该变量为0或1发电时相反。水量-功率转换这个约束往往被忽略但它很重要。矿井巷道的水头范围比较大不同水头下同样的流量对应的功率是不同的反过来同样功率对应的流量也不同。简化建模时可以取平均水头下的线性关系但如果想做精确一点的调度建议至少分段线性化处理。最小运行时间约束抽蓄机组频繁切换工况会加速设备磨损实际调度中通常要求机组在某工况下至少持续运行一定时间。这个约束在数学上是复杂的非线性约束处理时需要引入额外的二进制变量和逻辑约束。2.4 目标函数与约束体系的完整数学表达这个研究的标准目标函数是系统总运行成本最小化包括几个部分min F Σ [C_grid(t) × P_grid(t) C_bat_degrad(t) C_psh_start(t)] × Δt其中C_grid是购电成本从主网购电P_grid是购电功率C_bat_degrad是电池老化折算成本C_psh_start是抽蓄机组启停惩罚成本。如果研究还关注碳排放可以在目标函数里加一个碳成本项把火电购电量和碳排放关联起来但这会引入额外的约束和参数需要课题支持才行。约束条件体系包括以下各类。功率平衡约束是所有调度模型的基础系统内所有电源出力加储能充放电要时刻等于负荷需求这是硬约束写代码时通常作为等式约束处理。风电光伏出力上下限约束是保证优化结果不超出物理可行域的必要条件。储能SOC约束与充放电功率约束构成储能运行的可行域。抽蓄库容约束与工况互补约束是抽蓄模块的专属限制。联络线功率约束则是考虑并网通道的传输能力上限。3. 实操过程与Matlab代码实现3.1 数据准备与典型场景设计我先说数据准备。有些同学做这个课题时习惯直接下载公开数据集但公开数据集的格式和质量千差万别花在清洗上的时间往往比建模还多。我更推荐用合成数据先跑通整个流程后续再替换成实测数据。合成数据生成的方式很简单用Matlab的随机数生成器加上你设定的典型日特征曲线。比如设计一个“大风光日”场景光伏出力用0到1之间的Beta分布随机数乘以峰值功率峰值时刻设在正午12点风力出力用Weibull分布随机数乘以额定功率再叠加一个白噪声扰动模拟预测误差。这样生成的曲线虽然不如实测数据真实但用来验证调度模型逻辑是足够的。实际案例参考参数风电场额定容量200MW光伏电站额定容量100MW电池储能额定容量50MW/200MWh2C倍率废弃矿井抽蓄机组两台5MW机组上巷道可用库容对应满发4小时的发电量负荷曲线用典型工业负荷形状。时间步长取1小时调度周期24小时。这个配置的好处是电池和抽蓄的容量规模在一个数量级能明显看出不同时间尺度上的互补效果。3.2 目标函数与约束条件的代码实现Matlab代码实现时我通常把所有参数定义在一个结构体里这样传参方便也方便统一修改。核心代码逻辑可以拆成下面几个段落。参数定义部分主要设置风光容量、储能参数、抽蓄参数、负荷曲线数据、分时电价表、预测误差范围等。求解器选择部分如果约束全是线性的直接用intlinprog混合整数线性规划最稳妥Matlab自带的linprog和intlinprog性能虽然不算顶级但胜在开箱即用。如果约束里有非线性项可以用遗传算法ga或粒子群算法particleswarm。我之前做过一个方案是把非线性的水头-效率曲线做分段线性近似然后用intlinprog求解求解速度明显优于启发式算法而且结果更稳定。写代码时目标函数的形式很关键。intlinprog要求所有表达式是线性的所以电池寿命成本不能用二次形式必须做线性化处理——把DOD分成若干档每档对应一个线性成本系数。抽蓄启停惩罚则通过二进制变量实现启停一次固定加一个成本项。下面是目标函数的一个简写示例实际代码里用矩阵形式% 变量顺序: [P_bat; SOC; P_psh_pump; P_psh_gen; V_psh; P_grid; u_pump; u_gen] % 目标函数系数 f [C_bat_degrad; 0; C_psh_op; C_psh_op; ...; C_grid; C_start_pump; C_start_gen] f [bat_degrad_cost*ones(N,1); zeros(N,1); ... psh_om_cost*ones(N,1); psh_om_cost*ones(N,1); ... zeros(N,1); grid_price(:); pump_start_cost*ones(N,1); gen_start_cost*ones(N,1)];约束矩阵部分需要仔细核对每一行的索引对应关系。最容易出错的地方是SOC递推约束对应的那小段矩阵——SOC(t1)同时关联了SOC(t)和P_bat(t)写的时候要特别小心索引错一位整个结果就全乱了。3.3 求解流程与结果验证求解流程标准化之后大概是这样的读取数据、构建参数结构体、构造决策变量索引表、逐条添加约束、调用求解器、解析结果、做功率平衡校验、输出图表。结果验证部分强烈建议做三件事。第一平衡校验把每个时段的各类功率加起来看是否严格等于负荷如果有偏差优先检查等式约束的矩阵行是否写对。第二边界检查把SOC、库容、功率等变量的结果逐项对照上下限看有没有贴着边界跑的情况贴边说明约束在起作用但如果连续多个时段都贴边要警惕约束放得太紧。第三场景对比把大风光日、弱风光日、常规日的结果放在一起对比看弃风弃光率、购电成本、储能利用率的差异是否合理。一个可靠的运行结果是大风光日弃风弃光率控制在5%以内弱风光日购电成本显著上升但负荷保证率100%正常日电池负责小时级波动调节、抽蓄负责4小时以上的能量搬移。如果结果符合这个规律调度模型的逻辑基本就是对的。4. 常见问题与排查技巧实录4.1 求解器报“No feasible solution”怎么办这个问题我在实际调试中遇到过很多次而且绝大多数情况下不是模型本身错了而是约束之间互相矛盾。常见的矛盾来源有三个我分别说一下。SOC初始值设置不当是最常见的错误。如果SOC(1)设得过高后续时段无论如何充电都会越界。建议SOC(1)设为50%并给SOC终值加一个柔性约束——比如强制SOC(24)不低于初始值保证日循环的持续性。抽蓄库容初值同理不要把库容初值设在接近上限的位置。功率平衡约束和联络线约束冲突也经常出现。比如某个时段负荷很低、风光出力很大但储能和抽蓄都已经在满发充电无法再多消纳而此时联络线的购电功率又强制为0这个约束组合就会导致无解。处理办法是放宽联络线约束允许极端时段少量购电或售电在目标函数里用较高的电价惩罚来引导求解器自动避免这种情况。最后一个常见原因是抽蓄工况二进制变量的互补约束写法不对导致抽水和发电的变量同时为0时被硬性排除。这类约束要用“u_pump u_gen 1”的形式而不是等号。4.2 粒子群算法收敛慢或结果重复性差如果你选择用粒子群或遗传算法求解可能遇到收敛慢、每次运行结果差异大的问题。经验处理办法有三个一是把种群规模和迭代次数从默认值往上调这直接增加搜索的充分性二是给决策变量设置合理的上下界把搜索空间收紧到可行域附近三是把已知的可行解作为初始种群的一部分植入。比较实用的技巧是先用线性规划版本算出最优目标值然后把这个解的目标值作为启发式算法的参考上界把超过该上界的个体直接淘汰收敛速度会明显提升。如果你发现结果波动严重影响结论还有一个更彻底的方案改用Yalmip工具箱配合外部求解器如Gurobi、CPLEX。Yalmip的建模语法比直接写intlinprog的矩阵要直观得多尤其是处理复杂的约束逻辑时开发效率高一个量级。学术论文要求结果可复现的话用商业求解器是更稳妥的选择。4.3 储能SOC“锯齿形”波动的处理调度结果的SOC曲线经常出现高频锯齿形波动看起来像是在频繁充放电。这个现象的本质是电价波动驱动套利行为——每个时段电价高低不同求解器发现低买高卖有利润就会让电池频繁切换充放电状态。但从工程角度看电池不能这样跑每次切换都有寿命损耗。处理方式有两种。一种是在目标函数里加大充放电切换惩罚项这个需要引入二进制变量记录充放电状态的变化会让模型变复杂。另一种更简单的方式是设置充放电死区——功率绝对值小于某个阈值的操作忽略不计并将该时段的充放电功率强制归零。这个方法实现简单实测效果不错缺点是可能损失少量经济性但对工程而言可以接受。4.4 热门词“matlab 2026b”相关环境问题的快速排查这几年Matlab版本更新频繁很多人习惯用新版“matlab 2026b”跑仿真但新版在优化工具箱上有时会有默认求解器的行为变化导致老代码跑出不一样的结果。我的建议是学术研究以可复现性优先锁定一个稳定版本比如R2022b之后任何版本均可并在代码开头加一段版本检查% 版本检查确保优化工具箱可用 assert(license(test, Optimization_Toolbox) 1, 需要 Optimization Toolbox 许可证);另外如果你要在Linux服务器上跑长时间仿真注意Matlab的并行计算工具箱在多核环境下要显式开启并行池parpool否则大量循环会浪费宝贵的计算资源。首次启动parpool的时间往往很长建议放到仿真循环外初始化。5. 结果分析方法与论文级图表绘制5.1 功率平衡曲线与储能充放电时序做结果分析时最有说服力的图第一张是系统功率平衡图。横轴为小时序列纵轴为功率用堆叠面积图展示风电出力、光伏出力、放电功率正值、充电功率负值和购电功率之间的关系负荷曲线用黑线叠加。这张图最大价值在于直观检验所有时段的功率平衡是否严格满足也能看出储能的调节作用是否合理。第二张是储能SOC和抽蓄库容的时序图。重点关注SOC曲线是否保持在合理区间库容曲线是否体现了“低谷蓄水-高峰放水”的日循环规律。如果库容曲线长时间不动说明抽蓄没有被合理利用可能是容量设置过大或者电价激励不足。第三张是不同场景下各项经济指标和运行指标的对比表。建议汇总成表包括弃风弃光率、平均购电电价、储能等效循环次数、抽蓄启停次数等方便做敏感性分析。5.2 灵敏度分析的关键参数选择调度研究的深度很大程度上体现在灵敏度分析。建议优先做三个参数的敏感性分析。负荷峰谷差加大的时候看看储能配置容量对总成本的影响是不是非线性上升以此评估最优配置。分时电价峰谷价差收窄时储能套利空间缩小这时候电池和抽蓄的利用率会下降系统是否还能维持经济运行要看结构调整的余量。风电渗透率提升时弃风率和辅助服务需求的增长情况可以用来论证储能建设的必要性。做灵敏度分析时有个小技巧不要单独改变某一个参数而是把两个关键参数同时扫描画二维的等值线图或三维曲面图。比如横轴是风光配比纵轴是储能容量倍率颜色是系统总成本这样一张图就能看出最优方案是否存在以及是否敏感。这种图在论文里很容易打动审稿人也能给工程决策提供更丰富的信息。5.3 从仿真到论文的图表处理习惯投稿或写报告时图的字体、线宽、颜色这些细节经常被忽略。我的经验是Matlab导出图之前先把字体统一设置为Times New Roman或Arial字号控制在8到10磅之间线条加粗到1.5磅以上坐标轴要有完整的单位标注。图片导出用 exportgraphics 函数设置300dpi分辨率输出为PNG或PDF格式。这些细节虽然小但能省掉很多改稿时间。6. 实际运行效果与个人经验分享6.1 一组典型算例的结果呈现用前面说的配置跑一组实际算例结果大致符合预期。大风光日200MW风电加100MW光伏满发叠加的时候弃风弃光率如果不加储能大约在12%到18%之间。加入电池和抽蓄联合调蓄之后弃风弃光率降到5%以下系统购电成本也显著下降因为储能把多余的绿电搬移到了晚高峰时段。电池和抽蓄的分工也很清晰电池的SOC曲线波动频率高但每次幅度不大负责的是小时级波动抽蓄的库容曲线则是平滑的“V”形——白天光伏高峰抽水蓄能傍晚到夜间放水发电负责的是跨时段能量搬移。这种时间尺度上的分工正是混合储能互补的价值所在。6.2 我在实际调试中踩过的几个坑第一个坑是抽蓄模块的效率参数。最初我用固定的效率值仿真跑了三轮发现库容曲线有不自然的突跳排查到最后是抽水流量和发电功率的换算关系没写对。后来我把效率参数改成水头的函数并加了一个效率插值表问题才彻底解决。具体的做法是预先算好不同水头下的效率数据形成一个二维查找表用Matlab的interp1做插值这样既不会拖慢求解速度又能保证精度。第二个坑是电池寿命成本模型。最开始我用线性电池老化成本替代时调度结果里电池几乎每个时段都在充放电SOC频繁大幅波动。后来我意识到这是因为线性成本函数没有体现DOD越深损耗越大的非线性关系求解器当然会倾向“浅充浅放、频繁操作”因为每次操作的成本一样。换成分段线性化成本函数之后结果才变得合理——电池更愿意做深度充放而不是高频小幅操作。第三个坑是初值灵敏度。粒子群算法初始种群如果随机分布不当很容易让抽蓄机组一上来就处于不合理的工况导致大量个体在早期被罚掉。解决办法是植入了几个已知可行解作为初始种群个体这样种群一开始就在“正确的方向上”收敛快得多。6.3 这个项目还能怎么扩展如果你读完这份内容想往下做我建议几个扩展方向。把确定性优化升级为鲁棒优化或随机优化考虑风光预测误差的不确定性研究鲁棒调度策略的保守度与经济性权衡。在现有基础上加入常规火电机组的启停和爬坡约束把模型扩展为含传统电源的多能源互补系统。利用Matlab的Simulink搭建电池和抽蓄的电磁暂态模型把调度层给出的功率指令在物理层做验证研究跨层协同。把调度方法从集中式优化扩展到分布式优化参考多智能体一致性算法研究多园区独立微电网的协同调度问题。这些方向都有成熟的工具支持在Matlab环境下可以逐步演进。我做这个课题最大的体会是调度模型的价值不在数学复杂度而在于模型假设是否贴合工程实际、约束体系是否真实反映设备物理极限以及结果是否能指导实际运行。很多初次接触的同学容易把精力放在花哨的算法上却忽略了风光预测数据的质量、储能寿命模型的准确性这些基础环节最后仿真结果看起来很漂亮实际却很难落地。希望这份内容能帮你少走几条弯路把时间花在真正重要的地方。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进