ARTICLE DETAIL

资讯详情

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

储能参与调峰的配置方案与经济性分析:Matlab建模复现全流程

储能参与调峰的配置方案与经济性分析:Matlab建模复现全流程 最近后台好多电力方向的同学在问一类题目参与调峰的储能系统配置方案及经济性分析。这类文章在EI期刊里非常常见标题看着也不复杂——给储能选功率、选容量、定运行策略最后算一笔经济账。但真正动手用Matlab完整复现一遍从模型搭建、约束处理到求解器调用、经济性核算卡人的地方一个接一个。我今年完整复现了一篇这篇博文就把全过程拆开讲先讲清楚这类问题到底在优化什么再给出可直接落地的数学模型和Matlab代码主干最后把我踩过的坑和排查思路整理出来。想复现论文、想用这套框架做自己课题的同学照着这个思路走能少走很多弯路。1. 这个选题到底在优化一个什么问题——先想清楚再动手1.1 调峰的本质与储能在其中的位置电力系统负荷一天之内有明显的高峰和低谷。传统上这个波动靠火电、水电等机组跟随负荷调节但火电深度调峰存在出力下限问题机组压得越低煤耗越高设备损耗也越大。新能源大规模接入后负荷峰谷差进一步拉大调峰压力更突出。储能这个角色之所以被反复提及核心逻辑就一句话它能充能放能在负荷低谷时把电存起来在负荷高峰时放出来等效于把高峰负荷“搬运”到低谷时段让净负荷曲线变得平坦。“参与调峰”在建模里的体现就是这个净负荷曲线。原始负荷减去储能放电功率、加上储能充电功率得到净负荷曲线调峰效果好不好就看净负荷的峰值降了多少、峰谷差压缩了多少。这个定义贯穿全文后面所有约束都围绕它展开。1.2 EI论文复现不等于抄代码复现的目标是还原完整决策逻辑很多人一拿到复现任务就上网找代码我的经验恰恰相反EI复现的正确打开方式是先不看代码把论文里的模型公式一个公式一个公式拆开搞清楚决策变量是什么、目标函数是什么、约束条件有哪些。代码只是最后一步验证手段。为什么这么说论文代码经常存在版本差异、数据缺失有些边界条件为了篇幅直接省略了。直接跑别人的代码经常是“跑通了但不知道为什么”一旦换个数据、换个参数就彻底懵掉。复现的本质是还原“决策逻辑”给定负荷曲线、电价、储能参数系统如何决定每时每刻充多少、放多少以及这个策略对应的经济账。把这条逻辑链想通写代码就是水到渠成的事。1.3 复现前的信息清单从论文摘要反推你要准备什么动手前我建议先列一张信息清单逐项打钩信息类别典型内容论文没说时的替代方案负荷数据典型日/典型周负荷曲线MW用IEEE RTS典型负荷或对某地区日负荷做归一化电价机制分时电价峰/平/谷时段与价格按一般工商业分时电价设定典型值储能参数充放电效率、SOC范围、循环寿命磷酸铁锂典型参数效率95%、SOC 10%~90%、循环6000次投资成本单位功率成本、单位容量成本按近年主流功率成本约600元/kW容量成本约1500元/kWh经济参数折现率、运行年限、运维费率折现率8%、年限12年、运维费率2%/年这张表看起来琐碎但90%的复现卡壳都卡在“论文没给数据”这一步。我的做法是先用一组典型参数把代码全部跑通再替换实际数据做敏感性分析。千万不要一开始就纠结精确数据先把逻辑链路打通更重要。2. 储能配置与运行的经济性数学模型怎么搭2.1 决策变量配置层与运行层分开定义储能配置问题的典型建模方式是把决策变量分成两层。配置层储能额定功率 P_essMW、额定容量 E_essMWh。这两个变量决定了储能系统的“大小”。运行层每个调度时段 t 的充电功率 P_ch(t)、放电功率 P_dis(t)、充放电状态0-1变量 u_ch(t)、u_dis(t)以及荷电状态 SOC(t)。为什么要分层因为配置层回答“装多大”运行层回答“怎么用”两者时间尺度不同配置决策是长期的、一次性的运行决策是短期的、周期性的。分层建模的好处是你可以先用一组给定配置求解运行优化得到最优收益再在配置空间里搜索避免把两类变量混在一个非线性模型里一锅炖。2.2 目标函数总成本最小还是净收益最大这类论文的目标函数一般有两大流派。第一种是“净收益最大”。典型形式为 max 运行收益 - 年化投资成本 - 年运维成本运行收益主要来自峰谷套利峰时段放电收益减谷时段充电成本。如果考虑新能源场站场景还可以加入减少弃风弃光带来的收益。投资成本通过等年值法折算成每年的费用量纲统一后可以直接做加减。第二种是“系统总成本最小”。这种视角把储能当作系统的一个元件目标函数写为系统运行成本加储能投资成本、加调峰惩罚成本。惩罚项通常用来描述净负荷峰谷差过大或火电深度调峰带来的额外代价。两者本质等价只是记账方式不同。复现时优先看原文用哪一种因为后续所有经济性结论的“口径”都跟目标函数绑定混着用会出大问题。2.3 关键约束组SOC、充放电、功率平衡、寿命相关约束怎么列一个完整的调峰储能模型至少有下面几组约束。功率平衡约束是调峰的本质净负荷(t) 原始负荷(t) - 储能放电功率(t) 储能充电功率(t)如果还有新能源原始负荷要先扣除新能源出力。削峰填谷的效果就体现在这条净负荷曲线的峰谷差是否被压缩。充放电功率上限约束0 ≤ P_ch(t) ≤ u_ch(t) × P_ess 0 ≤ P_dis(t) ≤ u_dis(t) × P_ess同时性约束防止又充又放白套利u_ch(t) u_dis(t) ≤ 1SOC递推约束SOC(t1) SOC(t) η_ch × P_ch(t) × Δt / E_ess - P_dis(t) × Δt / (E_ess × η_dis)SOC上下限约束SOC_min ≤ SOC(t) ≤ SOC_max首末SOC一致性约束配周期调度SOC(1) SOC(T)调峰效果约束这是“参与调峰”的灵魂净负荷峰值 ≤ 原始负荷峰值 × (1 - 削峰率要求)或者写成净负荷峰谷差小于设定阈值。有些人只做纯峰谷套利完全不约束调峰效果那复现出来的结果虽然收益漂亮但和标题里的“参与调峰”就对不上了。这一点我在复现时吃过亏后面专门细说。2.4 非线性项怎么处理从互补约束到混合整数线性化如果 P_ess 和 u_ch(t) 同时都是变量那约束 P_ch(t) ≤ u_ch(t)×P_ess 就是双线性项直接交给求解器会非常难处理。这是建模时最容易踩的第一个坑。我复现时采用的处理方式是“两阶段解耦”外层在 P_ess、E_ess 的二维网格上扫描比如功率从1 MW到10 MW容量从2 MWh到20 MWh内层固定一组配置把 P_ess、E_ess 变成常数求解包含0-1变量的混合整数线性规划MILP得到该配置下的最优运行策略和最大收益最后把所有配置下的收益全算出来叠加投资成本比一比哪组配置经济性最好。这个做法的好处是把双线性问题拆成了“线性规划MILP”的组合Matlab完全能hold住而且每一组配置之间天然可以并行计算。很多EI论文正篇里用的就是类似思路只是在公式层面写成了更紧凑的单层模型。3. 经济性分析指标体系与“值不值得装”的判断方法3.1 全生命周期视角投资成本、运维成本、收益项逐项拆储能经济性分析不能只看单年收益要把账算到全生命周期。我习惯把它拆成三类。初始投资单位容量成本 × E_ess加上单位功率成本 × P_ess再加上建设安装等一次性费用。逐年费用运维成本通常按初始投资的百分比计电池更换成本如果循环寿命期内需要更换。逐年收益峰谷套利收益、调峰服务补偿、减少弃电带来的增发收益、容量租赁收益等。复现时最容易混淆的是“收益口径”。有的论文把火电少发的煤耗节约也算作收益有的只算储能本身的峰谷价差。这个口径必须和原文一致否则最后的回收期完全对不上。我建议做一个收益构成表逐条把论文的收益项和代码里的现金流对应起来这项工作比调代码重要得多。3.2 净现值NPV与内部收益率IRR算回本周期不是拍脑袋判断储能配置方案经济性好坏最有用的三个指标是NPV、IRR和动态回收期。NPV净现值把未来每年的净现金流用折现率折算到现在减去初始投资。NPV大于0说明项目在财务上可行。IRR内部收益率令NPV等于0的反解折现率。IRR高于基准收益率时方案可接受。动态回收期累计折现现金流由负转正的年限。这个指标最直观论文里最爱放。等年值投资成本公式A P × r × (1r)^n / ((1r)^n - 1)其中 P 是初始投资r 是折现率n 是运行年限。把年化投资成本代入目标函数就可以在年度收益和一次性投资之间直接做加减。我在复现时习惯把这几项做成一个独立函数 economic_eval()输入配置、年收益、投资参数输出NPV、IRR、回收期表格。后面做敏感性分析时只改参数批量调用非常方便。3.3 敏感性分析与边界界定论文里那几张曲线的含义EI论文里几乎必画三张图容量-收益曲线、功率-容量等收益图、回收期随关键参数的变化曲线。这些图不是在堆数据而是在回答一个问题这套配置方案对哪些参数最敏感复现时至少要做以下参数的敏感性分析储能单位容量成本上下浮动20%峰谷电价差上下浮动20%年利用天数/循环次数上下浮动20%测试结果往往能发现调峰储能的收益由峰谷价差主导。价差一旦缩小到某条线以下NPV就转负了。论文里说的“经济性边界”就是这条线。复现时把这条边界算出来比只算一个最优配置更有说服力这也是审稿人最喜欢看的内容之一。4. Matlab代码实现的主干结构从数据到图表的完整链路4.1 整体代码框架与文件组织我推荐的代码组织方式是按“数据-模型-求解-后处理”四段式拆分main.m % 主脚本控制整个流程 data/ load_profile.m % 负荷数据读取或生成 price_profile.m % 分时电价定义 storage_params.m % 储能参数定义 model/ build_model.m % Yalmip建模目标约束 run_operation.m % 给定配置求解运行优化 economic_eval.m % 经济性指标计算 result/ plot_results.m % 画图净负荷曲线、SOC曲线 sensitivity_analysis.m % 敏感性分析这样组织的好处是换一组数据、换一个储能参数只需要改 data 文件不需要动模型代码。复现论文时这套结构可以和论文的章节一一对应方便检查哪里有遗漏。4.2 数据准备与参数设定论文不给数据时怎么搭算例如果论文没给原始数据我一般用这样的典型算例负荷曲线标准双峰曲线峰值出现在10:00-11:00和18:00-20:00低谷在23:00-6:00最大负荷100 MW。分时电价峰段1.0元/kWh平段0.6元/kWh谷段0.3元/kWh。储能参数充放电效率95%SOC范围[0.1, 0.9]周期初末SOC都设为0.5。投资参数容量成本1500元/kWh功率成本600元/kW折现率8%运行年限12年运维费率2%/年。第一轮先用这组参数跑通再替换实际数据。注意所有时间单位统一为小时Δt一般取1小时。如果数据是15分钟粒度Δt0.25小时SOC递推公式里要同步修改这是新手最容易漏掉的细节。4.3 Yalmip建模核心代码与求解器选择下面是给定配置P_fix, E_fix下的内层运行优化代码骨架我用的是 Yalmip 加 Gurobi。如果没有商业求解器Yalmip也能调用开源求解器但MILP问题规模一大建议还是用商业求解器速度和稳定性完全两回事。T 24; dt 1; % 单位小时 % 已知量 P_load load_profile(T); % 1xT 负荷曲线 price price_profile(T); % 1xT 分时电价 P_fix 10; % 给定额定功率 MW E_fix 20; % 给定额定容量 MWh eta_ch 0.95; eta_dis 0.95; SOC_min 0.1; SOC_max 0.9; % 决策变量运行层 P_ch sdpvar(1, T); P_dis sdpvar(1, T); u_ch binvar(1, T); u_dis binvar(1, T); E_soc sdpvar(1, T 1); % 各时段能量状态初始时刻也算一个点 % 约束 Constraints []; % 充放电功率上下限与同时性 for t 1:T Constraints [Constraints, 0 P_ch(t) u_ch(t) * P_fix]; Constraints [Constraints, 0 P_dis(t) u_dis(t) * P_fix]; Constraints [Constraints, u_ch(t) u_dis(t) 1]; end % SOC递推用能量状态避免除以容量 for t 1:T Constraints [Constraints, ... E_soc(t1) E_soc(t) eta_ch * P_ch(t) * dt - P_dis(t) * dt / eta_dis]; Constraints [Constraints, SOC_min * E_fix E_soc(t1) SOC_max * E_fix]; end % 首末SOC一致性周期调度 Constraints [Constraints, E_soc(1) 0.5 * E_fix]; Constraints [Constraints, E_soc(T1) 0.5 * E_fix]; % 目标峰谷套利年收益最大化单日收益再乘年运行天数 Revenue sum(price .* (P_dis - P_ch) * dt); Objective -Revenue; % Yalmip默认求解最小化 ops sdpsettings(solver, gurobi, verbose, 0); optimize(Constraints, Objective, ops); % 提取结果 P_ch_opt value(P_ch); P_dis_opt value(P_dis); E_soc_opt value(E_soc(1:T));这里有个值得说明的细节SOC递推我用 E_soc 这个能量状态变量而不是直接用 SOC(t)。因为能量状态乘以容量后可以避免出现“SOC(t)×E_fix”混合项。在给定 E_fix 的情况下直接用 SOC 也可以因为 E_fix 是常数不会产生双线性。我只是习惯性用能量状态后面扩展到容量也是变量的场景时这套写法可以直接复用。4.4 结果后处理调峰效果图与经济性表格跑完内层优化后通常画三张图原始负荷曲线对比净负荷曲线直观看出高峰被削、低谷被填储能充放电功率曲线和SOC曲线检查运行策略是否符合直觉高峰放电、低谷充电经济性表格NPV、IRR、回收期、年化收益。经济性计算的典型代码逻辑function [npv_val, irr_val, payback] economic_eval(P_ess, E_ess, annual_revenue, params) % 初始投资 inv_cost params.cost_p * P_ess params.cost_e * E_ess params.install_cost; % 年运维成本 opex params.opex_rate * inv_cost; % 年净现金流简化忽略电池更换 cf annual_revenue - opex; % 计算NPV years params.life; disc params.discount_rate; npv_val -inv_cost cf * (1 - (1 disc)^(-years)) / disc; % IRR数值求解 irr_val irr([-inv_cost, repmat(cf, 1, years)]); % 静态回收期 payback inv_cost / cf; endMATLAB自带的 irr 函数按年份顺序输入现金流向量即可。如果算出来的回收期大于运行年限这个配置在给定参数下就是不可行的。敏感性分析的意义正在于找出这个“可行边界”。5. 复现过程最容易翻车的四个环节实测排查记录5.1 数据维度与时间粒度不一致我第一次复现时用的是网上下载的某地区实测负荷数据15分钟一个点一天96个点。代码假设 T24、dt1SOC递推全乱了。排查时一直盯着SOC曲线看跑出来SOC一跳一跳的完全不符合物理规律。折腾了半天才发现是时间粒度不匹配。排查方法很简单第一步打印 P_load 的长度确认 T 和 dt 是否对应第二步检查 SOC 递推式里的 dt 是否与数据粒度一致第三步如果换了数据源价格序列的粒度和负荷也必须一致。这类问题往往不在建模而在数据管道。我建议从一开始就封装一个 load_case() 函数统一输出 T、dt、P_load、price避免后面每次手动改数据时埋雷。5.2 SOC约束和充放电状态耦合导致解不可行另一个高频问题是 Yalmip 报 infeasible。我遇到的典型原因是充放电同时性约束写了 u_ch(t) u_dis(t) ≤ 1但忘记给 P_ch 和 P_dis 分别乘上对应的0-1变量。结果求解器为了凑目标函数出现又充又放、白拿收益的情况加上其它约束后整体不可行。遇到不可行时的标准排查顺序先把 SOC 上下限约束注释掉看能否求解再检查首末 SOC 一致性约束是否过紧检查功率平衡约束中 P_ch 和 P_dis 的正负号是否写反打印约束和目标函数值逐条验证。能用20分钟内定位这类问题靠的就是这个固定排查顺序。建议把排查步骤直接写在代码注释里因为几周之后回来看代码你大概率已经忘了当初怎么排查的。5.3 求解器选择导致的结果差异同一套模型用 Gurobi 和用默认求解器结果可能差异明显。这不是代码写错了而是MILP问题本身可能有多个近优解不同求解器的分支定界策略不一样会收敛到不同解。如果复现的论文用的是粒子群PSO、遗传算法GA等智能算法那和用MILP精确求解的结果更不可能完全一致——智能算法大概率得到的是次优解。复现时如果发现自己的结果比原论文更优不用太惊讶这恰恰说明精确求解器的优势。写报告时建议注明求解器型号和版本比如Gurobi 10.0.2、CPLEX 12.10否则别人复现你的复现时会一头雾水。5.4 收益口径问题经济性结论对不上的隐蔽原因这是经济性分析中最隐蔽的坑。我第一次复现时看到论文里“年收益”数字很大但自己算出来总是差一截反复检查模型都没发现问题。后来仔细读原文才发现它把“减少火电深度调峰带来的煤耗节约”也算进了收益里而我做的只是储能自身的峰谷套利。所以复现前一定要把论文的收益项逐条列出和代码中的现金流逐条对应。我建议做一张收益构成表收益项论文是否计入代码是否计入备注峰谷套利是是收益主体减少弃风/弃光增发收益看场景看场景需要新能源出力数据调峰辅助服务补贴部分论文计视参数而定注意时效与适用条件火电煤耗节约个别论文计复现时建议单独列出口径必须与原文对齐只有逐项对齐经济性结论才有可比性。这一步不做后面算NPV、IRR全是空中楼阁。6. 从复现到创新这套框架还能扩展哪些方向6.1 把单目标扩展成多目标调峰率、新能源消纳、经济性原题只优化经济性但实际工程中电网更关心调峰效果和新能源消纳率。可以把单目标扩展成多目标优化一个目标是最小化净负荷峰谷差或最大化削峰率一个目标是最大化年净收益第三个可以是最大化新能源利用率。多目标问题常用NSGA-II这类启发式算法求解在Matlab里可以直接用 gamultiobj 函数。我的建议策略是先用本文的两阶段框架求出每个目标单独最优的配置再交给多目标算法搜索Pareto前沿这样得到的解集既有极端方案也有折中方案。写论文时Pareto前沿图比单点结果好讲得多。6.2 把确定性模型扩展成不确定性场景法与鲁棒优化确定性模型的输入是单条负荷曲线和单组电价但实际调度中负荷预测有误差、新能源出力有波动。复现论文后很自然的下一步是把模型改成两阶段随机规划第一阶段储能配置决策第二阶段对每个随机场景求解运行优化场景可以用蒙特卡洛抽样后用 kmeans 聚类缩减成几个典型场景目标改成期望收益最大或者条件风险价值CVaR约束下的收益最大。这个扩展方向专业性更强但如果确定性模型吃透了换成场景集合其实只是把单场景约束复制成多场景约束的事情代码改起来并不复杂。6.3 把独立储能扩展成共享储能或混合储能独立储能是单一主体自建自用。共享储能会引入多主体博弈多个新能源场站或用户共同租用一块储能涉及容量分配和费用分摊建模时通常用主从博弈或合作博弈。混合储能则是锂电池加超级电容组合超级电容响应快、循环寿命长适合吸收高频波动锂电池承担能量型调峰模型变成双时间尺度优化。这两条路都是目前研究热点而且都建立在这套“配置-运行-经济性”框架之上。我在复现完之后的最大体会是标题里的“储能系统配置方案”不是一个孤立的建模题而是一整套决策框架。把框架拆清楚后面换应用场景、换目标函数、换求解方法都是往框架里填细节的事。最后分享一个小习惯复现这类论文时我建议先动笔在纸上画一张“变量-约束-目标”三角关系图把哪些变量影响哪些约束、哪些约束影响目标用箭头标出来。这张图画清楚了写Matlab代码基本上不会迷路画不清楚就算代码跑通了换个数据、换个配置照样翻车。这套框架我在储能调峰、风储联合、光储充一体化的项目里反复用过每次都靠这张图快速定位问题。希望这篇东西能帮你少走几个弯路跑出属于你自己的那张调峰效果图。
返回列表