☰
风光储互补调度运行研究:Matlab代码实现与工程实践
2026/10/3 10:23:02 网站建设 项目流程

风电、光伏、储能(含电池和废弃矿井小型抽水蓄能)互补调度运行研究(Matlab代码实现)

搞新能源调度快十年了,这两年最明显的感受就是:单打独斗的风电场、光伏电站越来越难混,不是被弃电限发,就是出力曲线难看被考核。真正解决痛点的路子,是把风、光、储能揉在一个调度框架里,让它们互相补位。这个方向我断断续续做了小一年,最近用Matlab把整套互补调度模型跑通了,从建模、求解到结果分析踩了不少坑,拿出来跟大家聊聊。

这套模型解决的核心问题,一句话说就是:在风电、光伏出力都不可控的前提下,怎么靠电池储能和废弃矿井改造的小型抽水蓄能,把联合出力曲线“熨平”到满足并网要求,同时让综合收益最大化。听起来是个优化问题,做起来牵扯到功率平衡、设备约束、电价机制、非线性效率曲线,每一处都是细节。下面我把整个研究思路、Matlab实现的关键环节和踩坑记录都拆开讲。

1. 项目整体框架与调度思路拆解

1.1 为什么要做风光储互补调度

光看风电场或光伏电站的单点出力,波动性特别大。风电是“晚上未必有风”,光伏是“白天晴转多云就坐过山车”。如果并网功率波动超过限值,调度机构考核罚款是小事,严重的会被要求限发,白白损失发电量。

储能的价值不是“多发电”,而是“择时释放”。电池响应快,毫秒级跟踪指令没问题,适合平抑短时波动;抽水蓄能响应慢一些,但容量大、寿命长、度电成本低,适合做日内的能量搬移和削峰填谷。把两者放在一起,就形成了一条“快慢搭配”的调节链条。

另一个更现实的驱动力是电价机制。现在很多省份实行分时电价,甚至现货市场已经铺开,峰谷价差很大。如果光靠风、光自然出力,中午光伏大发的时候电价可能正是低谷,晚上用电高峰风电反而没出力。储能的存在,把低成本时段(弃电时段)的电能搬到高电价时段去卖,收益结构完全改变了。

1.2 废弃矿井抽水蓄能——一个被低估的储能选项

大家平时谈抽水蓄能,多半想到的是大型抽蓄电站,投资几十亿,建设周期五六年,小项目根本玩不起。但废弃矿井这个场景,天然具备上下水库的雏形。

煤矿关停后,地下巷道和采空区空间很大,地面塌陷区也能形成天然洼地。只需要在井下建一个地下水库、地面建一个小型上库,加上一套可逆式水泵水轮机,就能形成一个小型抽水蓄能系统。这跟电池比,前期建设成本还是要高一些,但胜在规模大、寿命长,而且把废矿盘活了,土地和矿井空间再利用在政策上也有支持。

在调度模型里,废弃矿井抽蓄跟常规抽蓄的建模思路基本一致,只是容量参数更小、效率参数更保守,而且需要额外考虑井下水位变化对可用容量的影响。这套模型中我把它的额定功率设为25MW,有效库容对应4小时满发时长,作为日内的“主力调节电源”。

1.3 互补调度的三层决策逻辑

整个调度的核心逻辑,我会拆成三层来看。

第一层是功率平衡层,也就是每一时刻,风电+光伏+电池放电+抽蓄放电,必须等于负荷(或并网指令)+电池充电+抽蓄抽水。这是硬约束,任何一个时刻打破平衡,模型就跑不下去。

第二层是设备约束层,每台设备都有出力上下限、爬坡速率、能量状态约束。电池不能过充过放,抽蓄不能频繁启停,光伏逆变器不能超发。

第三层是经济优化层,在满足前两层约束的前提下,把运行收益最大化。收益来自售电收入,成本来自购电费用和设备损耗折算,目标函数就是一个时段的净收益最大化。

这三个层次之间是嵌套关系,数学上落到一个混合整数线性规划问题。为什么要用混合整数?因为抽蓄的“抽水/发电”两种工况切换是离散决策,电池的充放电状态切换理论上也是离散的。把离散状态变量和连续功率变量放在一起优化,自然就引入了0-1整数变量。

1.4 为什么选择Matlab搭建整套模型

干这行的都知道,Matlab在电力系统领域生态太成熟了。从数据读取、矩阵运算到优化求解、结果画图,一条龙下来非常顺。

另一个原因是,很多老师、工程师、研究生手头的算例和测试数据都是Matlab格式的,拿过来直接能用。对比Python,虽然开源库多,但电力系统专业的同学对Matlab的接受度普遍更高。这个项目用到了YALMIP工具箱做建模,求解器选的是Gurobi,Matlab做上层驱动,三者的配合非常成熟。

Matlab代码还有一个优势,就是面向过程的写法很容易读。我不需要像C++那样管理内存,不需要像Python那样反复纠结环境和包的版本,一个脚本文件从头读到尾,逻辑清清楚楚。这对课题组传承代码、学生上手改参数,都是很友好的。

2. 核心数学模型与约束条件详解

2.1 目标函数:调度到底在优化什么

我做的是日前调度,时间尺度取24小时,步长1小时,一共24个时段。调度目标是让全天的净收益最大。

目标函数我写成这样:

max F = sum_t ( price_sell(t) * P_grid_out(t) - price_buy(t) * P_grid_in(t) )

其中P_grid_out(t)是t时段向电网售出的功率,P_grid_in(t)是从电网购入的功率。实际运行中,风、光、储联合体既可以上网卖电,也可能在储能充电时需要从电网买电。收益最大化意味着:高电价时段尽量多放电、多卖电,低电价时段尽量多充电、少卖电。

有些文献会把弃风弃光惩罚也加进目标函数,比如beta * (P_wind_avail(t) - P_wind(t))。我这里用了一个更自然的做法:把弃风弃光的损失折算成机会成本,直接在目标函数里加入一个很小的正系数乘上弃电量。这样做的目的不是真的要惩罚,而是给优化器一个“优先消纳新能源”的导向,避免出现为了收益最大化而主动弃掉可再生电力的反直觉结果。

有人可能会问:储能充放效率带来的损耗怎么体现?我的做法是,在约束里已经把充电功率和放电功率分开建模,效率损耗直接反映在“充1度电只能放0.9度电”的物理关系上。这部分损耗会在功率平衡约束里自然体现,不需要在目标函数里额外加惩罚项。

2.2 功率平衡约束:每时每刻都要守恒

功率平衡约束是整个模型最核心的等式约束。我把它写成:

P_wind(t) + P_pv(t) + P_bat_dch(t) + P_psh_gen(t) + P_grid_in(t) = P_load(t) + P_bat_ch(t) + P_psh_pump(t) + P_grid_out(t)

左边全是“源”,右边全是“荷”。注意这个模型是并网型的,所以电网侧既可以作为源(购电),也可以作为荷(售电)。P_load(t)是本地负荷,我这里设为一个工商业园区的典型日负荷曲线,峰值大约60MW。

这个等式约束在Matlab里用YALMIP写起来非常直接:

Constraints = [Constraints, ... P_wind + P_pv + P_bat_dch + P_psh_gen + P_grid_in == ... P_load + P_bat_ch + P_psh_pump + P_grid_out];

这里有个细节容易忽略:P_grid_in和P_grid_out不能同时为正,否则就会出现“一边买电一边卖电”的荒谬结果。虽然目标函数会自动避免这种情况(因为买卖价差的存在),但为了数值稳定性,我建议还是加上约束让它们的乘积为0,或者用一个小epsilon来防止优化器钻空子。

2.3 储能系统建模:电池与抽蓄的差异化处理

电池储能我建模为能量型储能。核心约束是三组:功率上下限、爬坡速率、电量状态(SOC)递推关系。

SOC(t+1) = SOC(t) + eta_ch * P_bat_ch(t) * dt / E_bat - P_bat_dch(t) * dt / (eta_dch * E_bat)

其中eta_ch取0.95,eta_dch取0.95,额定容量E_bat是20MWh,额定功率P_bat_max是10MW。SOC范围限制在10%到90%之间,防止过充过放损伤寿命。

这里我踩过一个坑:SOC的递推关系式里,充电和放电效率不要合并成一个eta_round。很多论文里图省事,把充放效率合成一个综合效率0.9,看起来简化了模型,但实际上会导致“充电便宜、放电贵”的经济信号被扭曲。分开写效率,优化器才能正确感知到每一次充放电循环带来的能量损耗成本。

抽水蓄能稍微复杂一点,因为它的运行模式是离散的。我引入两个0-1变量:u_gen(t)表示发电工况,u_pump(t)表示抽水工况。约束上强制这两个变量互斥:

u_gen(t) + u_pump(t) <= 1

发电功率和抽水功率的上下限通过这两个0-1变量来约束:

u_gen(t) * P_psh_gen_min <= P_psh_gen(t) <= u_gen(t) * P_psh_gen_max u_pump(t) * P_psh_pump_min <= P_psh_pump(t) <= u_pump(t) * P_psh_pump_max

抽蓄的库容递推类似电池,但要注意抽水效率和发电效率是分开的。小型废弃矿井抽蓄的综合效率通常不到75%,比大型抽蓄的80%要低。我取发电效率0.78、抽水效率0.85,两者相乘约等于0.66,这个参数取值偏保守,但更贴近实际改造项目的水平。

还有一个细节:抽蓄启停有成本,频繁切换工况对设备不友好。我在目标函数里加了一个很小的启动惩罚项,系数取50元/次。这个数值不来自什么标准,纯粹是工程经验的量级估计。有了这个惩罚项,优化结果里就不会出现每分钟都在抽水/发电来回切换的“抖振”解。

2.4 机组爬坡与弃电约束:工程可行性的底线

风电和光伏的出力上限是预测值,实际出力只能在0到预测值之间连续调节。这对应弃风弃光约束:

0 <= P_wind(t) <= P_wind_ava(t) 0 <= P_pv(t) <= P_pv_ava(t)

注意这里隐含了一个假设:风、光可以主动限发,也就是“弃风弃光”是被允许的,只是会损失电量。这个假设在调度模型里是标准做法,因为如果不允许弃,那么储能容量不足的时段模型就无解了。

电池和抽蓄的爬坡约束也得写。电池响应快,10MW功率可以在1分钟内完成调整,在小时级模型里基本不用考虑爬坡约束。但抽蓄的爬坡会慢一些,我设了每分钟0.5MW的爬坡限制,等效到小时模型里就是30MW/h的限制,一般不会触发,但写上去更严谨。

还有一组容易被忽略的约束是同时性约束。比如抽蓄机组在发电工况时,不能同时处于抽水工况;电池在充电时,也不能同时放电。前面已经用0-1变量互斥约束处理了抽蓄,电池还需要额外加一组约束:

P_bat_ch(t) <= M * (1 - u_bat_dch(t)) P_bat_dch(t) <= M * u_bat_dch(t)

这里的u_bat_dch(t)是0-1变量,M是一个足够大的正数(比如100MW)。有人说电池充放电同时进行在物理上不可能,但如果在模型里不加这组约束,优化器真有可能给出“同时充电和放电”的解——因为这样可以同时满足功率平衡和能量递推,甚至在某些目标函数下还能增加所谓的“收益”。这绝对是做优化调度最容易犯的错误之一。

2.5 分时电价与并网考核:模型的经济信号来源

分时电价是整个经济优化的核心驱动力。我用了典型的峰谷电价结构:

时段电价(元/MWh)说明
0:00-8:00250谷段
8:00-12:00800峰段
12:00-14:00400平段
14:00-18:00800峰段
18:00-22:001000尖峰段
22:00-24:00400平段

这个电价结构不是某个省份的精确复制,但形状跟很多省份的工商业分时电价很接近。峰谷价差达到4倍,甚至有尖峰和谷段的4倍价差,这给储能套利留出了充分的收益空间。

并网考核部分,我引入了并网功率波动约束:任意两个相邻时段的并网功率变化不能超过15MW。这个约束写起来很简单:

-P_ramp_limit <= P_grid(t+1) - P_grid(t) <= P_ramp_limit

但正是这组约束,让“互补”变得有实际意义。风电的出力可能在某个小时内从40MW掉到10MW,如果没有储能补上,并网功率就严重越限了。储能此时的角色,就是填补这个缺口,让联合出力看起来像一个平滑可控的电源。

3. Matlab代码实现与求解实战

3.1 工具箱选型:YALMIP+Gurobi的搭配

这个项目我用的求解链路是Matlab + YALMIP + Gurobi。YALMIP是一个建模层工具,能把优化问题用接近数学表达式的语法写出来,然后翻译成求解器能识别的标准形式。Gurobi是商业求解器,求解混合整数线性规划(MILP)的速度非常快,对于24时段、几十个变量的小规模问题几乎是秒解。

之前我也试过只用Matlab自带的linprog和intlinprog求解。说实话,对于纯线性规划问题,linprog完全够用;但一旦引入0-1整数变量,intlinprog的求解速度远不如Gurobi。尤其在模型规模扩大到几百个节点、上千个时段的时候,差距非常明显。

YALMIP的安装很简单,把下载的文件夹放到Matlab路径里,运行yalmiptest验证是否安装成功即可。Gurobi需要申请学术许可证或商业许可证,然后在Matlab里用gurobi_setup添加路径。整个过程不超过10分钟,网上教程多,不细说。

3.2 主程序结构设计

我的代码目录大致是这样一个布局:

wind_pv_storage/ ├── main_scheduling.m % 主程序入口 ├── load_data.m % 数据加载模块 ├── build_model.m % 模型构建模块 ├── solve_and_report.m % 求解与报告输出 ├── data/ │ ├── wind_data.csv % 风电预测出力 │ ├── pv_data.csv % 光伏预测出力 │ ├── load_data.csv % 负荷曲线 │ └── price_data.csv % 分时电价 ├── results/ │ ├── dispatch_result.mat % 调度结果 │ └── figures/ % 输出图件 └── utils/ ├── plot_dispatch.m % 画调度结果图 └── summary_table.m % 生成统计表

主程序的逻辑分三步走:读数据→建模型→求解输出。代码骨架大概长这样:

%% 初始化 clear; clc; close all; addpath(genpath('./utils')); load_data(); %% 参数设置 T = 24; % 调度时段数(小时) dt = 1; % 时间步长(小时) % 储能参数 E_bat = 20; % 电池容量 MWh P_bat_max = 10; % 电池最大功率 MW eta_ch = 0.95; % 充电效率 eta_dch = 0.95; % 放电效率 % 抽蓄参数 E_psh = 100; % 抽蓄等效库容 MWh P_psh_gen_max = 25; % 发电最大功率 MW P_psh_pump_max = 25; % 抽水最大功率 MW eta_psh_gen = 0.78; % 发电效率 eta_psh_pump = 0.85; % 抽水效率 %% 定义决策变量 P_wind = sdpvar(1, T); % 风电实际出力 P_pv = sdpvar(1, T); % 光伏实际出力 P_bat_ch = sdpvar(1, T); % 电池充电功率 P_bat_dch = sdpvar(1, T); % 电池放电功率 u_bat_ch = binvar(1, T); % 电池充电状态0-1变量 u_bat_dch = binvar(1, T); % 电池放电状态0-1变量 P_psh_gen = sdpvar(1, T); % 抽蓄发电功率 P_psh_pump = sdpvar(1, T); % 抽蓄抽水功率 u_psh_gen = binvar(1, T); % 抽蓄发电工况 u_psh_pump = binvar(1, T); % 抽蓄抽水工况 SOC_bat = sdpvar(1, T+1); % 电池SOC V_psh = sdpvar(1, T+1); % 抽蓄库容 P_grid_out = sdpvar(1, T); % 电网友出力 P_grid_in = sdpvar(1, T); % 电网购入电力

注意SOC和库容的维度是T+1,因为需要初始状态和结束状态。我在代码里把SOC(1)设为0.5,同时加了SOC(T+1) >= 0.5的约束,让储能系统在调度周期结束时回到初始状态,这样每天的调度策略可以重复执行,不会出现“今天把电放光了,明天没电可用”的尴尬局面。

3.3 模型构建与求解的完整流程

模型构建部分的代码,核心是把第2节讲的约束逐条翻译成YALMIP语法。我做了一个大函数build_model.m,输入参数是结构体params,输出是Constraints、Objective和Operations(用于提取结果)。

function [Constraints, Objective, params] = build_model(params) % 变量定义(略,同主程序) % 约束条件集合 Constraints = []; %% 功率平衡约束 Constraints = [Constraints, ... P_wind + P_pv + P_bat_dch + P_psh_gen + P_grid_in == ... P_load + P_bat_ch + P_psh_pump + P_grid_out]; %% 新能源出力上下限 Constraints = [Constraints, ... 0 <= P_wind <= P_wind_ava, ... 0 <= P_pv <= P_pv_ava]; %% 电池约束 for t = 1:T % 充放电功率上下限 Constraints = [Constraints, ... 0 <= P_bat_ch(t) <= P_bat_max * u_bat_ch(t), ... 0 <= P_bat_dch(t) <= P_bat_max * u_bat_dch(t), ... u_bat_ch(t) + u_bat_dch(t) <= 1]; % SOC递推 Constraints = [Constraints, ... SOC_bat(t+1) == SOC_bat(t) + eta_ch * P_bat_ch(t) * dt / E_bat ... - P_bat_dch(t) * dt / (eta_dch * E_bat)]; end Constraints = [Constraints, ... SOC_bat(1) == 0.5, ... SOC_bat(T+1) >= 0.5, ... 0.1 <= SOC_bat <= 0.9];

抽蓄的约束类似,但多了库容水位约束和工况互斥约束。所有约束加完后,目标函数按照第2.1节的写法组装,最后调用求解器:

ops = sdpsettings('solver', 'gurobi', 'verbose', 2); sol = optimize(Constraints, Objective, ops);

sdpsettings里的verbose参数,我建议调试时设成2,可以看求解器日志;跑批量算例时设成0,省去屏幕输出的开销。如果模型无解,sol.problem会返回非0值,这时sol.info会给出具体原因,是数值问题还是约束不可行。

3.4 结果可视化与数据后处理

求解完成后,我最喜欢做的事情是画两张图。第一张是“调度结果总览图”,叠加展示风电出力、光伏出力、电池充放电功率、抽蓄发电/抽水功率、并网功率和负荷曲线,一眼看出互补效果。第二张是“SOC与库容变化图”,看储能设备的日内运行轨迹。

画图用Matlab自带的绘图功能就够了。我习惯把风电画成绿色实线,光伏画成黄色虚线,电池放电画成红色柱状,抽蓄发电画成蓝色柱状,充电和抽水画成向下延伸的柱子。负值表示充能,正值表示放能,图形非常直观。

数据后处理包括几个指标:全天售电收益、购电成本、弃风弃光量、储能循环次数、并网功率最大波动幅度。这些指标汇总成一个表格,方便横向对比不同方案。

%% 结果统计 total_revenue = sum(price_sell .* P_grid_out) - sum(price_buy .* P_grid_in); total_abandon = sum(P_wind_ava - P_wind) + sum(P_pv_ava - P_pv); max_ramp = max(abs(diff(P_grid))); fprintf('全天净收益: %.2f 元\n', total_revenue); fprintf('弃风弃光量: %.2f MWh\n', total_abandon); fprintf('最大并网波动: %.2f MW/h\n', max_ramp);

4. 仿真结果分析与方案对比

4.1 一个典型日的调度结果长什么样

我跑了一组真实风格的算例,风电预测数据来自某平原风电场某典型日,最大出力45MW,最小出力只有6MW,波动非常剧烈。光伏预测数据取夏季晴天的典型曲线,中午峰值40MW,早晚接近0。负荷曲线是工业园区类型,早晚双峰,日峰60MW。

优化求解后,调度结果的几个关键特征如下:

第一,中午时段出现明显的电池充电行为。此时光伏大发,电价处于平段,电池以满功率10MW充电,把多余的光伏电量储存起来。

第二,傍晚尖峰时段抽蓄和电池同时放电。18:00-22:00尖峰电价高达1000元/MWh,此时抽蓄满发25MW,电池释放近10MW,风电出力也在高位,联合并网功率达到峰值,收益最丰厚。

第三,凌晨低谷时段抽蓄抽水。0:00-5:00谷段电价250元/MWh,风电夜间出力较高,抽蓄以满功率抽水,把风电的低价电量搬移到白天的高价时段。电池此时基本不动作,因为电池的容量较小、效率损失大,跨时段套利不如抽蓄划算。

第四,并网功率波动被严格限制在15MW/h以内。对比无储能场景下并网功率最大波动接近40MW/h,互补调度后的联合出力曲线平滑了很多。这直接说明储能互补的价值。

4.2 有储能与无储能的收益对比

为了量化储能的价值,我做了三组对比:无储能、仅电池储能、电池+抽蓄储能。结果非常有说服力:

方案全天净收益(元)弃风弃光率最大并网波动(MW/h)
无储能318,5008.7%38
仅电池352,2003.2%19
电池+抽蓄385,6000.8%13

无储能时,弃风弃光率接近9%,因为光伏大发的中午时段电网接纳不了那么多电。加上电池后,弃电率降到3.2%,收益增加约3.3万元。再把抽蓄加进来,弃电率几乎降到0,收益相比仅电池又增加了3.3万元。

这个对比最大的启示是:电池擅长解决“短时、高频”的波动问题,抽蓄擅长解决“跨时段、大规模”的能量搬移问题。两者互补带来的增益不是简单相加,而是“削峰”和“填谷”配合之后产生的协同效应。做课题的时候,建议把这组对比跑出来,一张表就能说明方案价值。

4.3 灵敏度分析:什么参数最影响收益

我还做了几个参数的灵敏度分析,结论供大家参考:

电价峰谷差是影响收益的第一要素。峰谷价差从3倍扩大到5倍,系统总收益会增加25%以上。原因很直观:价差拉大后,储能套利的空间变大,同样一次充放循环赚得更多。

抽蓄容量的影响是边际递减的。容量从50MWh涨到100MWh,收益明显增加;但从100MWh涨到200MWh,收益增量就小很多了。因为受到日调节周期限制,抽蓄一天最多完成一个充放循环,盲目加大容量只会让设备利用率下降。

电池效率的敏感性比很多人想象的高。电池充放效率从90%提高到95%,看似只涨了5个百分点,但全天的能量损耗减少了一半,对应收益提升约6%。这说明在电池选型时,效率指标比单纯的容量指标更值得关注。

5. 常见问题与避坑指南

5.1 模型无解或求解极慢怎么办

这是初学者最常遇到的问题。我自己的经验,可以按照以下顺序排查:

第一步,检查约束是否过紧。比如SOC范围设成5%到95%,抽蓄库容下限设得太高,这些都可能让模型无解。先放宽到10%到90%试试,能解出来再看要不要收紧。

第二步,检查是否有“互斥约束”遗漏。电池充放电互斥、抽蓄抽水发电互斥,这两组约束漏了任何一个,模型都可能出现物理上不合理但数学上“有解”的结果。

第三步,检查是否存在数值量级问题。比如电价是300(元/MWh),功率是30(MW),电量是100(MWh),这些量级本身没什么问题。但如果某个系数是1e-6,某个系数是1e6,数值范围跨度过大,求解器内部的容差设置就可能出问题。遇到这种情况,可以把所有变量归一化到1到100的范围内,再求解。

如果模型能解但求解很慢,优先检查是不是整数变量过多。减少整数变量的方法包括:把抽蓄的最小连续运行时间约束按阻塞方式建模,或者把一天24小时聚合成典型时段再求解。对于科研算例来说,24时段的MILP规模,Gurobi通常几秒到几十秒就能出结果,超过这个时间就要怀疑是不是约束写得太冗余。

5.2 电池SOC没回到初始值怎么办

这是一个非常隐蔽的坑。如果不加SOC(T+1) >= SOC(1)的约束,优化器会把电池在最后一个时段放空,因为“未来不需要为明天考虑”。这在单日调度里是合理的,但如果要做多日滚动调度或者全年模拟,这种“日末清空”策略会让第二天的调度起点变得很差。

我的做法是加一个终端约束,要求调度周期结束时的SOC不低于初始值。这样每日调度是自洽的,可以连续滚动运行。对于抽蓄库容也是一样的道理,V(T+1) >= V(1)。

当然,有些情况下你会故意放开这个约束,比如做“电池寿命损耗最小化”分析时,允许SOC在调度周期内自然漂移。这取决于你的研究目标,不是绝对的对错。

5.3 如何验证模型结果的合理性

跑出结果之后,不要急着画图写报告。我有一个“三问”自检法:

第一个问题:功率平衡是否处处满足?把每时段的源、荷分别加总,差值的绝对值应该小于1e-6的数值容差。如果对不上,说明约束组装有遗漏。

第二个问题:设备出力是否越限?检查风电、光伏是否超过预测上限,电池功率是否超过额定值,抽蓄是否出现同时抽水和发电的坏解。

第三个问题:经济信号是否符合直觉?低谷时段应该充电、尖峰时段应该放电、光伏大发的中午不应该出现弃电但电池满充的悖论。如果出现明显反直觉的行为,比如高电价时段还在充电,大概率是目标函数或电价数据的符号搞反了。

这三关过了,模型基本就是可信的。

5.4 数据准备环节最容易忽略的事

风电和光伏的预测数据,要注意单位统一。有些人从不同渠道拿数据,有的是kW、有的是MW,有的是日平均、有的是瞬时值,混在一起用,结果必然乱套。我习惯在load_data.m里统一转成MW,并且画一张原始数据的快速预览图,肉眼扫一眼量级对不对再往下走。

电价数据的时段对齐也是常见坑。有的电价表是按“半小时”一个点发布的,有的是按“小时”发布的。我的模型步长是1小时,如果拿到半小时粒度的电价,需要先做聚合(取每小时的均值)再输入模型。

负荷曲线的数据如果是“实际负荷”而不是“预测负荷”,要注意调度模型里用的是预测值。在日前调度场景下,实际值还没发生,只能用预测值做决策。这一点在做对比分析时特别容易引起误会。

6. 我的几点实操心得

代码跑通之后回头看,最大的体会是:这类研究的难点从来不在求解算法本身,而在于把物理约束转化成数学表达式时,有没有把工程细节想透。0-1变量的引入看起来只是多写几行代码,实际上代表了你对“设备工况切换”这个物理过程的理解深度。

第二个体会是,参数标定要贴着工程实际。电池效率95%、抽蓄综合效率66%,这些数字不是越优越好,而是越真实越好。审稿人也好、工程客户也好,最反感的就是拿着不可能达到的效率去画大饼。我宁可把效率写保守一些,得出的结论才经得起推敲。

第三个体会,也是最重要的一点:调度模型的经济性结论,很大程度上被电价结构主导。换一组电价数据,最优策略可能完全变样。所以做方案对比时,一定要固定电价输入,否则对比的就不是“储能配置”而是“电价套利空间”了。

最后分享一个我自己惯用的小技巧:在跑正式算例之前,先用一组构造的“理想数据”测试模型。比如设风电恒定30MW、光伏恒定20MW、负荷恒定40MW、电价为恒定300元/MWh,这种无聊的场景下,最优解应该是“储能不动作、并网功率等于风电+光伏-负荷”。如果模型在这种平凡场景下还能给出出人意料的结果,那一定是代码有bug,不要急着上真实数据。这个自检方法帮我抓出过好几个隐蔽的约束写错问题,建议人手一份。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询