简介:本资源是面向能源系统优化研究者与电力系统方向研究生的学术复现型代码包,聚焦微电网中新能源经济消纳与共享储能协同配置这一核心问题。针对储能投资成本与微网运行经济性双重目标,完整复现了文献《考虑微网新能源经济消纳的共享储能优化配置》提出的双层规划模型:外层优化储能容量/功率配置,内层基于KKT条件求解消纳率与微网经济调度,具备明确的工程建模逻辑与算法可解释性。压缩包共5个文件(3个核心MATLAB脚本实现主模型与嵌套求解、1份PDF代码说明文档详述变量定义与调用流程、1个Excel提供典型日风光负荷原始数据),总大小2.21MB,结构精炼、模块分工清晰,便于理解双层优化框架与MATLAB工程实现细节。目前已有1265人学习下载,读者可直接运行调试、修改参数开展敏感性分析,并结合PDF文档快速掌握KKT转化技巧与新能源消纳率量化方法。
1. 项目背景与核心价值
最近在做一个微网项目,客户的核心诉求很明确:怎么把光伏、风电这些出力不稳定的新能源,既经济又高效地用起来,同时还得解决弃风弃光的问题。这几乎是所有新能源微网项目都会遇到的经典难题。我们团队在方案阶段,反复讨论的一个焦点就是储能。自己建一套储能系统,初始投资大,利用率可能还不高,尤其是对于中小型微网或者工商业园区,经济账算不过来。这时候,“共享储能”这个概念就进入了我们的视野。
简单来说,共享储能可以理解为一个“储能云服务”。它不是为某个单一用户或单一微网单独配置的,而是作为一个独立的、集中式的储能电站,为区域内多个微网或用户提供灵活的充放电服务。对于单个微网而言,它不需要承担高昂的储能建设成本,而是通过租赁或购买服务的方式,按需使用共享储能的能力。这就像我们不一定要自己买发电机,而是从电网买电一样。这个模式的核心优势在于提升储能设备的整体利用率和经济性,从而摊薄成本,让新能源消纳更划算。
我们这个项目标题——“考虑微网新能源经济消纳的共享储能优化配置”,瞄准的正是这个痛点。它要解决的,不是一个简单的技术仿真,而是一个经济性驱动的优化决策问题。具体来说,我们需要用数学模型和优化算法,回答几个关键问题:对于一个接入共享储能的微网,在给定新能源(光伏、风电)出力预测和负荷需求的情况下,共享储能的最优功率和容量应该是多少?微网内部应该如何制定与共享储能的互动策略(何时充电、何时放电、充放多少)?最终的目标函数,是在满足微网自身运行安全约束的前提下,最小化系统的总成本,这个总成本通常包括:从上级电网购电的成本、向共享储能运营商支付的服务费(或租赁费)、以及新能源弃用的惩罚成本等。
用Matlab来实现这个优化模型,是工程和研究领域的常见选择。Matlab强大的优化工具箱(如fmincon,intlinprog)和建模语言(如YALMIP、CVX),能够相对高效地将这个复杂的、可能包含连续和离散变量的优化问题描述并求解出来。接下来,我将结合我们实际项目中的经验,拆解这个优化配置问题的建模思路、Matlab实现的关键步骤,以及那些在仿真中容易踩坑的细节。
2. 问题建模:从业务逻辑到数学方程
要把一个实际的工程经济问题变成Matlab能解的代码,第一步也是最关键的一步,就是建立准确的数学模型。这个模型需要清晰地定义决策变量、目标函数和约束条件。
2.1 系统结构与决策变量定义
我们考虑一个典型的并网型微网系统,其结构简化如下:微网内部包含光伏(PV)、风机(WT)、常规负荷,以及一个可调度的分布式发电机(如燃气轮机,作为备用)。微网通过公共连接点(PCC)与主网进行功率交换,同时,它还可以与一个外部的共享储能电站进行功率交互。
基于此,我们需要定义时间尺度上的决策变量。通常,我们会以1小时为时间间隔,对一个典型日(24小时)或更长时间尺度的运行进行优化。核心决策变量包括:
- 微网与主网的交互功率
P_grid(t): 正值表示从主网购电,负值表示向主网售电(如果允许)。 - 微网与共享储能的交互功率
P_shared_ess(t): 正值表示微网从共享储能充电(消耗功率),负值表示微网向共享储能放电(提供功率)。注意:这个功率的“方向”定义需要与共享储能服务商的计费模型对应,在建模初期必须统一。 - 共享储能的荷电状态
SOC_shared(t): 描述共享储能在每个时刻的剩余电量,是状态变量。 - 新能源弃用功率
P_curt_pv(t),P_curt_wt(t): 当新能源出力过剩,而微网无法消纳且共享储能也无法完全吸收时,被迫弃掉的部分。 - 分布式发电机出力
P_dg(t): 微网内部可控电源的出力。
对于共享储能配置问题,有时我们还需要将共享储能电站本身的额定功率容量P_ess_rated和额定能量容量E_ess_rated也作为优化变量(通常是长期规划变量)。但在一个给定共享储能参数的运行优化问题中,它们可能是已知参数。
2.2 目标函数:经济性为王
目标函数是引导优化方向的指挥棒。对于“经济消纳”,我们的目标是最小化微网系统在调度周期内的总运行成本。一个典型的目标函数构成如下:
Minimize: 总成本 = 购电成本 + 共享储能服务费 + 燃料成本 + 弃能惩罚成本
- 购电成本:
C_grid = sum_t ( price_buy(t) * max(P_grid(t), 0) - price_sell(t) * max(-P_grid(t), 0) )。这里price_buy和price_sell分别是分时电价下的购电和售电电价,通常售电电价低于购电电价。 - 共享储能服务费: 这是共享储能模式的核心。计费方式多样,常见的有两种:
- 功率租赁费+电量服务费:
C_ess = α * P_ess_rated + β * sum_t( abs(P_shared_ess(t)) )。其中α是单位功率的租赁费(元/kW/天),β是单位电量的服务费(元/kWh)。这种方式下,P_ess_rated可能是一个需要优化的配置变量。 - 单纯电量服务费:
C_ess = γ * sum_t( abs(P_shared_ess(t)) )。γ是综合服务费率。在我们的运行优化中,通常先假设费率已知。
- 功率租赁费+电量服务费:
- 燃料成本:
C_dg = sum_t ( a * P_dg(t)^2 + b * P_dg(t) + c )。对于燃气轮机等,其成本通常用二次函数或分段线性函数近似。 - 弃能惩罚成本:
C_curt = sum_t ( λ_pv * P_curt_pv(t) + λ_wt * P_curt_wt(t) )。λ是弃能惩罚系数,这不是实际发生的费用,而是为了在优化中优先消纳新能源而设置的一个“虚拟成本”。将其设得足够高,优化器就会尽量避免弃光弃风。
实操心得:目标函数中惩罚系数的设置非常关键。如果λ设置过低,优化器可能会认为弃掉便宜的新能源比购买昂贵的共享储能服务或启动燃机更“经济”,这违背了“充分消纳”的初衷。通常,我们会将λ设置为高于最高购电电价的一个值,例如1.5倍。这需要反复调试。
2.3 约束条件:确保运行安全与物理可行
没有约束的优化是空中楼阁。我们必须用等式和不等式约束来描述系统的物理规律和运行限制。
功率平衡约束(最核心):在任何时刻t,微网内部的发电、用电、储能交互必须平衡。
P_pv(t) - P_curt_pv(t) + P_wt(t) - P_curt_wt(t) + P_dg(t) + P_grid(t) + P_shared_ess(t) = P_load(t)这个等式约束确保了供需实时平衡。设备运行约束:
- 主网交互功率限值:
P_grid_min <= P_grid(t) <= P_grid_max。这可能是变压器容量或协议规定的限值。 - 分布式发电机出力上下限及爬坡率:
P_dg_min <= P_dg(t) <= P_dg_max-RD_dg <= P_dg(t) - P_dg(t-1) <= RU_dg(RD, RU为向下/向上爬坡速率) - 新能源弃能限制:
0 <= P_curt_pv(t) <= P_pv(t),0 <= P_curt_wt(t) <= P_wt(t)。弃能不能超过当前实际出力。
- 主网交互功率限值:
共享储能运行约束(重点与难点):
- 功率约束:
-P_ess_rated <= P_shared_ess(t) <= P_ess_rated。充放电功率不能超过其额定功率。注意符号,我们定义充电为正,放电为负。 - 能量状态(SOC)动态方程:
SOC_shared(t) = SOC_shared(t-1) + (η_ch * max(P_shared_ess(t), 0) - max(-P_shared_ess(t), 0)/η_dis) * Δt / E_ess_rated其中,η_ch和η_dis分别为充电和放电效率(0<η<1)。这个公式用max函数处理了充放电不同效率的问题,但它是一个非线性约束。为了在Matlab中利用线性或二次规划求解器(速度更快、更稳定),我们通常需要对其进行线性化处理。 - SOC上下限约束:
SOC_min <= SOC_shared(t) <= SOC_max。通常为0.1和0.9,以延长电池寿命。 - SOC循环约束:
SOC_shared(0) = SOC_shared(T)。要求调度周期结束时,共享储能的电量回到初始状态,确保其可持续为多个周期服务。这是一个非常重要的约束,否则优化器可能会在最后时刻“掏空”或“塞满”储能来套利,这不符实际运行情况。
- 功率约束:
踩坑记录:SOC动态方程的非线性是第一个坑。我们最初直接使用带
max函数的非线性形式,用fmincon求解,不仅速度慢,而且容易陷入局部最优。后来我们引入了一组0-1二进制变量u_ch(t)和u_dis(t)来表示充放电状态,并添加约束u_ch(t) + u_dis(t) <= 1来防止同时充放电。然后将功率分解为P_ch(t) = u_ch(t) * P_shared_ess(t)和P_dis(t) = -u_dis(t) * P_shared_ess(t),再利用大M法将乘积线性化。这样就把问题转化成了一个混合整数线性规划问题,虽然变量多了,但可以用intlinprog可靠求解。
3. Matlab实现:从模型到代码的跨越
模型建立后,用Matlab实现就变成了一个“翻译”工作。我们推荐使用YALMIP工具箱进行建模,它语法直观,能自动识别问题类型并调用合适的求解器(如Gurobi, Cplex, Mosek或Matlab自带的intlinprog)。
3.1 数据准备与参数定义
首先,我们需要准备输入数据。这通常是一个时间序列,包含24小时或更长时间的数据。
% 定义时间步长和时段数 T = 24; % 24小时调度 dt = 1; % 1小时 % 加载或生成预测数据(示例) P_pv = [0,0,0,0,0, 20, 80, 150, 200, 220, 200, 180, 150, 120, 80, 40, 10, 0,0,0,0,0,0,0]; % kW P_wt = [85, 90, 95, 100, 105, 100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10]; % kW P_load = [120, 110, 100, 95, 100, 130, 180, 220, 250, 260, 255, 240, 230, 220, 210, 200, 190, 210, 230, 240, 220, 180, 150, 130]; % kW % 电价 (元/kWh) price_buy = [0.3, 0.3, 0.3, 0.3, 0.3, 0.5, 0.8, 1.2, 1.2, 1.0, 1.0, 0.8, 0.8, 0.8, 0.8, 1.0, 1.2, 1.2, 1.0, 0.8, 0.5, 0.3, 0.3, 0.3]; price_sell = 0.2 * ones(1,T); % 假设固定售电价 % 共享储能参数(假设已知,如果是优化变量则不同) P_ess_rated = 100; % kW E_ess_rated = 400; % kWh eta_ch = 0.95; % 充电效率 eta_dis = 0.95; % 放电效率 SOC_min = 0.1; SOC_max = 0.9; SOC0 = 0.5; % 初始SOC % 共享储能服务费率 beta = 0.15; % 元/kWh, 按使用电量计费 % 其他设备参数 P_dg_max = 150; % kW P_dg_min = 30; % kW RD_dg = 60; % kW/h RU_dg = 60; % kW/h a = 0.002; b = 0.5; c = 10; % 燃机成本系数 % 惩罚系数 lambda_curt = 1.0; % 元/kWh, 高于最高购电价3.2 使用YALMIP构建优化模型
接下来是核心的建模部分。我们按照第2部分的模型,使用YALMIP定义变量、目标函数和约束。
% 初始化YALMIP yalmip('clear'); % 定义决策变量 P_grid = sdpvar(1, T); % 与主网交换功率 P_shared = sdpvar(1, T); % 与共享储能交换功率,充电为正 P_dg = sdpvar(1, T); % 分布式发电机出力 P_curt_pv = sdpvar(1, T); % 光伏弃电 P_curt_wt = sdpvar(1, T); % 风电弃电 SOC = sdpvar(1, T); % 共享储能SOC % 为了线性化SOC动态方程,引入二进制变量和大M法(简化示例,未完全展开) % 此处假设我们采用简化线性模型(效率近似为1或使用平均效率),以保持示例清晰。 % 实际工程中,必须处理充放电效率差异。这里用一个平均效率eta_avg近似。 eta_avg = sqrt(eta_ch * eta_dis); % 近似平均效率 Constraints = []; % 1. 功率平衡约束 for t = 1:T Constraints = [Constraints, ... (P_pv(t) - P_curt_pv(t)) + (P_wt(t) - P_curt_wt(t)) + P_dg(t) + P_grid(t) + P_shared(t) == P_load(t)]; end % 2. 设备运行约束 Constraints = [Constraints, -P_ess_rated <= P_shared <= P_ess_rated]; % 共享储能功率限值 Constraints = [Constraints, P_dg_min <= P_dg <= P_dg_max]; % DG出力限值 % DG爬坡约束 for t = 2:T Constraints = [Constraints, -RD_dg <= P_dg(t) - P_dg(t-1) <= RU_dg]; end Constraints = [Constraints, 0 <= P_curt_pv <= P_pv, 0 <= P_curt_wt <= P_wt]; % 弃能约束 % 3. 共享储能SOC动态与约束 Constraints = [Constraints, SOC(1) == SOC0 + (P_shared(1)*dt) / E_ess_rated]; % 第一时刻,忽略效率 for t = 2:T % 注意:此处为简化,未严格区分充放电效率。严谨模型需按2.3节所述线性化。 % 简化假设充放电效率均为eta_avg if P_shared(t) >= 0 delta_E = P_shared(t) * eta_avg * dt; % 充电 else delta_E = P_shared(t) / eta_avg * dt; % 放电 end Constraints = [Constraints, SOC(t) == SOC(t-1) + delta_E / E_ess_rated]; end Constraints = [Constraints, SOC_min <= SOC <= SOC_max]; % SOC限值 Constraints = [Constraints, SOC(T) == SOC0]; % SOC循环约束 % 4. 主网交互约束(假设只能购电,不能售电,且上限200kW) Constraints = [Constraints, 0 <= P_grid <= 200]; % 定义目标函数 Cost_grid = sum(price_buy .* P_grid); % 购电成本 Cost_ess = beta * sum(abs(P_shared)) * dt; % 共享储能服务费,按电量计 Cost_dg = sum(a * P_dg.^2 + b * P_dg + c); % 燃机燃料成本(二次) Cost_curt = lambda_curt * sum(P_curt_pv + P_curt_wt) * dt; % 弃能惩罚 TotalCost = Cost_grid + Cost_ess + Cost_dg + Cost_curt; % 设置求解器选项并求解 ops = sdpsettings('solver', 'gurobi', 'verbose', 1); % 推荐使用Gurobi或Cplex % 如果没有商业求解器,可以使用Matlab自带的 `intlinprog`,但需要将问题转化为线性/混合整数线性形式。 % ops = sdpsettings('solver', 'intlinprog', 'verbose', 1); sol = optimize(Constraints, TotalCost, ops); % 检查求解状态并输出结果 if sol.problem == 0 disp('求解成功!'); P_grid_opt = value(P_grid); P_shared_opt = value(P_shared); P_dg_opt = value(P_dg); P_curt_pv_opt = value(P_curt_pv); P_curt_wt_opt = value(P_curt_wt); SOC_opt = value(SOC); TotalCost_opt = value(TotalCost); % 计算各部分成本 Cost_grid_opt = value(Cost_grid); Cost_ess_opt = value(Cost_ess); Cost_dg_opt = value(Cost_dg); Cost_curt_opt = value(Cost_curt); fprintf('总运行成本: %.2f 元\n', TotalCost_opt); fprintf('购电成本: %.2f 元\n', Cost_grid_opt); fprintf('共享储能服务费: %.2f 元\n', Cost_ess_opt); fprintf('燃机燃料成本: %.2f 元\n', Cost_dg_opt); fprintf('弃能惩罚成本: %.2f 元\n', Cost_curt_opt); else disp('求解出错!'); yalmiperror(sol.problem); end关键技巧:在定义目标函数中的
abs(P_shared)时,YALMIP会自动引入辅助变量将其线性化。但对于SOC动态方程中的充放电效率非线性项,YALMIP无法自动处理,必须手动进行线性化建模(如使用二进制变量和大M法),否则fmincon求解非线性问题的性能和全局最优性无法保证。这是区分“玩具代码”和“工程代码”的关键点。
3.3 结果可视化与分析
求解成功后,我们需要通过图表来直观理解优化调度策略。
% 绘制功率平衡图 figure('Position', [100, 100, 1200, 600]); t = 1:T; subplot(2,2,1); area(t, [P_curt_pv_opt; P_pv - P_curt_pv_opt]', 'LineStyle', 'none'); hold on; area(t, [P_curt_wt_opt; P_wt - P_curt_wt_opt]', 'LineStyle', 'none'); plot(t, P_load, 'k-', 'LineWidth', 2); plot(t, P_dg_opt, 'm-', 'LineWidth', 1.5); plot(t, P_grid_opt, 'b-', 'LineWidth', 1.5); plot(t, P_shared_opt, 'r-', 'LineWidth', 1.5); hold off; legend('弃光', '光伏出力', '弃风', '风电出力', '负荷', '燃机出力', '网购电', '共享储能交互', 'Location', 'bestoutside'); xlabel('时间 (h)'); ylabel('功率 (kW)'); title('微网日内优化调度结果'); grid on; subplot(2,2,2); bar(t, P_shared_opt); xlabel('时间 (h)'); ylabel('功率 (kW)'); title('共享储能交互功率 (正为充电)'); grid on; yline(0, 'k--'); subplot(2,2,3); plot(t, SOC_opt, 'o-', 'LineWidth', 1.5); xlabel('时间 (h)'); ylabel('SOC'); title('共享储能荷电状态变化'); ylim([0, 1]); grid on; yline(SOC_min, 'r--'); yline(SOC_max, 'r--'); yline(SOC0, 'k--'); legend('SOC', '下限', '上限', '初始值', 'Location', 'best'); subplot(2,2,4); costs = [Cost_grid_opt, Cost_ess_opt, Cost_dg_opt, Cost_curt_opt]; labels = {'购电成本', '储能服务费', '燃机成本', '弃能惩罚'}; pie(costs, labels); title('总成本构成分析');通过分析这些图表,我们可以清晰地看到:
- 共享储能的“削峰填谷”作用:它通常在电价低谷(如夜间)或新能源过剩时充电,在电价高峰或负荷高峰时放电,从而降低购电成本。
- 新能源消纳情况:
P_curt是否为零或很小,是判断模型是否有效促进消纳的直接指标。 - 经济性分析:成本饼图直观展示了共享储能服务费在总成本中的占比,这是评估共享储能经济性的关键。
4. 进阶探讨:从运行优化到容量配置
上面的代码解决的是给定共享储能参数下的运行优化问题。而标题中的“优化配置”,更常指长期规划问题:共享储能的功率和容量(P_ess_rated, E_ess_rated)应该是多少?
这需要将容量变量也纳入优化,并考虑更长时间尺度(如一年)的数据,以及对应的投资成本。目标函数会变为:Minimize: 总投资等年值 + 年运行总成本
其中,总投资等年值可以通过将储能系统的初始投资成本(与功率、容量相关)乘以资本回收系数得到。约束条件中,P_ess_rated和E_ess_rated会成为优化变量,出现在功率约束和SOC动态方程的分母中,使得问题变为一个混合整数非线性规划问题,求解复杂度大大增加。
一种实用的工程方法是迭代搜索或分段线性化:
- 设定一组候选的
(P_ess_rated, E_ess_rated)值。 - 对每一组候选值,运行上述的日内运行优化模型,模拟一整年(选取典型日或全时序数据),计算年运行总成本。
- 将“该容量下的投资等年值”与“对应的年运行总成本”相加,得到该配置下的总等年成本。
- 遍历所有候选配置,选择总等年成本最低的
(P_ess_rated, E_ess_rated)作为最优配置。
这种方法虽然计算量大,但概念清晰,且可以利用并行计算加速。在Matlab中,可以用parfor循环并行处理不同容量场景的仿真。
5. 避坑指南与经验总结
在复现和拓展这类模型时,有几个地方特别容易出错:
功率方向定义混乱:这是最基础的错误。务必在建模之初就统一所有功率流的方向(例如,流入微网为正,流出为负),并在目标函数和约束中保持一致。一个简单的检查方法是:在电价高峰时段,优化后的
P_grid(购电)应该减少,而P_shared(若为放电)应为负值以提供功率。SOC动态方程线性化不严谨:直接使用非线性效率模型会导致求解困难。务必使用二进制变量和大M法进行严格的线性化,或者至少在学术研究中说明这种近似带来的误差。对于工程应用,线性化是保证求解速度和可靠性的前提。
忽略爬坡等动态约束:对于燃气轮机等设备,爬坡率约束至关重要,否则优化结果可能无法实际执行。同样,储能系统的充放电功率变化率有时也需要考虑。
惩罚系数设置不当:如之前所述,弃能惩罚系数
lambda_curt如果设置过低,优化结果会失去“促进消纳”的意义。需要通过敏感性分析,观察该系数变化对弃电量和总成本的影响,选择一个合理的值。数据质量与时间尺度:优化结果严重依赖于输入数据(新能源预测、负荷预测、电价)的准确性。对于配置问题,需要使用典型日或全年时序数据才有说服力。单日优化结果可能具有偶然性。
求解器选择与问题规模:对于包含整数变量的大规模问题(如全年8760小时),Matlab自带的
intlinprog可能会非常慢甚至内存不足。商业求解器如Gurobi、Cplex在求解速度和稳定性上有巨大优势。在代码中做好异常处理(try-catch)和求解状态检查是必要的。
从我个人的项目经验来看,这类共享储能优化配置模型,其价值不仅仅在于给出一个“最优解”的数字,更在于通过模型进行情景分析和敏感性分析。例如,我们可以分析:
- 电价波动对共享储能配置容量的影响有多大?
- 新能源渗透率提高到多少时,配置共享储能开始变得经济?
- 共享储能的服务费率在什么区间内,对微网业主才有吸引力?
这些分析能为投资决策和商业模式设计提供坚实的量化依据。把模型跑通只是第一步,更重要的是学会用它去回答实际的商业和技术问题。
本文还有配套的精品资源,点击获取