1. 微电网电池容量配置到底在优化什么做微电网的人可能都有这种感觉光伏和风电天生不听话中午太阳好、风又大的时候发电量蹭蹭往上涨负荷却可能正在低谷到了晚上灯火通明光伏却下了班。储能电池就是用来“搬家”的——把多余的电存起来缺电的时候再放出来。但电池贵啊磷酸铁锂电芯加PCS、BMS、温控和安装一整套下来每千瓦时容量少说上千块。装少了光伏弃光、负荷限电钱没省多少装多了一大笔初始投资趴在电池上每天充放电循环可能都做不满收益率算下来还不如不装。所以“装多大才划算”这个事本质上是在算一笔经济账。这笔账难在哪难在它不是一个简单的“用最大负荷减去光伏出力”的加减法。电池的充放电行为是动态的一天24小时的电价、负荷、光伏出力都在变还要考虑电池寿命衰减、充放电效率、功率约束、SOC上下限。你拍脑袋定一个容量顶多能算出“够不够用”但算不出“划不划算”。要想让电池既能削峰填谷、又能提升光伏自用率同时总投资回收期最短就得把问题抛给优化算法——让计算机在满足所有物理和运行约束的前提下找一个全年总成本最低的容量配置方案。这也是混合整数规划在微电网里最典型的应用场景。2. 为什么选混合整数规划而不是穷举或启发式有些朋友一上来就想到遗传算法或者粒子群觉得这些算法“智能”搜一搜就能找到答案。但如果你真正做过优化就知道启发式算法最大的问题是不稳定——同样的参数跑十次十次结果可能都不一样而且它没法给你一个严格的全局最优证明。当然工程上很多时候不需要严格最优差不多就行。可电池容量这种投资决策差10%可能就是上百万的差别你总得知道当前方案离最优有多远吧。混合整数规划的优势在于它把问题拆成“连续决策”和“整数决策”两大类。电池的SOC是连续的充放电功率是连续的但“某个时刻电池是否在充电”这是个0-1变量——因为电池不能同时充电和放电这个逻辑关系不是线性约束能自然表达的必须引入整数变量。还有设备是否投建比如要不要多配一台PCS这也是0-1变量。这些问题恰好是混合整数规划的标准形态可以直接用MATLAB的intlinprog或YALMIPGurobi求解。求解器用的是分支定界加割平面理论上能收敛到全局最优而且解是确定性的——你给它同样的数据它输出的结果永远一样这对工程决策来说太重要了。再说混合整数规划的建模过程本身就是对系统逻辑的梳理。你为了写好那些约束必须把每一条物理规律、每一种运行策略都思考清楚。这个过程本身就是一种收益哪怕最后你不跑优化光是建完模你对微电网的理解都会上一个台阶。3. MATLAB建模的完整思路与实操步骤我这儿以一个小型工商业微电网为例假设园区光伏装机300 kW峰谷电价差很大想配一套磷酸铁锂储能要算电池容量和功率各取多少。先说明一下这个案例我简化了一些细节比如不考虑储能参与需求响应、不考虑系统备用但核心框架是完整的你后续可以在此基础上扩展。3.1 首先把决策变量定义清楚我们让优化器决定电池的额定容量EkWh和额定功率PkW这两个是连续变量但不是随便取的得从市场可选型号中选。实际操作中容量往往是集装箱式储能的标准规格比如100 kWh、200 kWh、500 kWh所以更准确的做法是把容量定义成整数变量取标准档位。功率也一样PCS单机功率通常是100 kW、250 kW这样。此外对每个调度时段t取1小时一个点一天24个点全年8760个小时我们要定义电池的充电功率P_ch(t)、放电功率P_dis(t)以及对应的两个0-1变量u_ch(t)、u_dis(t)用来互斥约束。这些都是决策变量。3.2 目标函数全生命周期净现值最小化把“划算”翻译成数学语言就是全生命周期总成本最低。总成本包括初始投资、运维成本、购电费用再减去光伏上网卖电收入和储能“低储高放”套利省下的电费。因为钱有时间价值未来每年的收益要折现到现在公式是[ C_{total} C_{cap} \cdot (E \cdot k_E P \cdot k_P) \sum_{y1}^{N} \frac{C_{om,y} C_{buy,y} - C_{sell,y} - C_{save,y}}{(1r)^y} ]这里k_E是单位容量成本元/kWhk_P是单位功率成本元/kWN是项目寿命取10年r是贴现率取6%。购电成本是电网分时电价乘以购电量卖电收入是光伏上网电价乘以多余电量储能套利节省的电费我放在C_save里含义是装了储能之后原本要在高峰高价时段买电的钱改为在低谷低价时段充、高峰时段放之后节省下来的购电费用。这个目标函数看着复杂但intlinprog要求的是线性目标所以要把非线性项比如“max()”拆开用辅助变量和约束去逼近。好在分时电价是固定分段购电量乘以电价就是线性项不需要额外处理。3.3 约束条件这是建模的重头戏第一组是功率平衡约束。每个时刻光伏出力加上电池放电加上电网购电要等于负荷加上电池充电加上卖给电网的电。考虑到光伏优先自发自用卖电只在光伏功率大于负荷和充电需求时才发生这个约束可以写成[ P_{PV}(t) P_{dis}(t) P_{grid,buy}(t) P_{load}(t) P_{ch}(t) P_{sell}(t) ]第二组是电池本身的约束。充电功率和放电功率不能超过额定功率同时充电和放电不能同时发生所以引入两个0-1变量u_ch和u_dis[ P_{ch}(t) \le P \cdot u_{ch}(t) ][ P_{dis}(t) \le P \cdot u_{dis}(t) ][ u_{ch}(t) u_{dis}(t) \le 1 ]第三组是SOC递推约束。SOC(t1)等于SOC(t)加上充电量乘以效率减去放电量除以效率。这里注意充电和放电效率不一样我通常取充电效率95%放电效率95%往返效率90%左右。SOC还有一个范围比如0.1到0.9防止过度放电损伤电池[ SOC(t1) SOC(t) \frac{P_{ch}(t)\cdot\eta_{ch}}{E} - \frac{P_{dis}(t)}{E\cdot\eta_{dis}} ][ 0.1 \le SOC(t) \le 0.9 ]注意SOC递推公式里容量E在分母上导致约束变成非线性。这个恰恰是混合整数规划模型里最需要小心处理的地方。怎么处理把“P_ch(t)/E”看成一个整体引入新的连续变量表示单位容量下的充电倍率然后乘以E就线性化了。具体做法是令Q_ch(t) P_ch(t)/EQ_dis(t)P_dis(t)/E那么SOC递推变成[ SOC(t1) SOC(t) Q_{ch}(t)\cdot\eta_{ch} - \frac{Q_{dis}(t)}{\eta_{dis}} ]约束变成[ 0 \le Q_{ch}(t) \le C_{rate} \cdot u_{ch}(t) ][ 0 \le Q_{dis}(t) \le C_{rate} \cdot u_{dis}(t) ]C_rate就是电池的倍率比如0.5C表示最大充放电功率是容量的0.5倍。这样一来SOC和Q变量都是线性的E只在目标函数里出现一次整列模型就线性化了。第四组是电网交互约束。购电功率不能超过变压器容量卖电功率不能超过并网逆变器限值。这些约束比较直接。第五组是储能寿命约束也可以叫充放电次数约束。为了延长电池寿命一天内充电循环次数不能太多等效满充循环次数不能超过某个值。这个约束通常写成基于放电量的累计表达式比较复杂我在后面常见问题里会详细说说。3.4 分时电价与负荷/光伏数据准备分时电价是决定储能套利空间的关键不同省份差异很大。我以某中部省份工商业峰谷电价为模板峰时电价1.1元/kWh平时电价0.7元/kWh谷时电价0.35元/kWh。峰时一般是8:00到11:00、18:00到23:00谷时是23:00到次日7:00。你要是拿自己的实际数据直接替换load_PV.mat里的向量就行。光伏出力和负荷数据我建议用典型日的24点数据而不是全年8760小时直接丢进去跑因为全年8760个时段再加上8760个0-1变量intlinprog不一定啃得动而且工程上也不需要精确到每个小时。更实际的思路是选四个典型日夏季晴天、夏季阴天、冬季晴天、冬季阴天每个典型日给予权重权重比如各占四分之一或按天数折算把四个典型日拼接成大矩阵这样精度够了计算量也降下来了。3.5 用MATLAB代码实现核心模型我贴一段精简但可直接运行的核心代码用的是MATLAB自带的intlinprog不需要额外装Gurobi虽然Gurobi算大模型更快但一般规模的微电网优化自带求解器已经够用了。% 基础参数 load(typical_day_data.mat); % 包含 P_load, P_pv, price_peak, price_flat, price_valley T length(P_load); % 一个典型日24点如果拼接多个典型日T取总时长 dt 1; % 1小时 % 经济参数 k_E 1200; % 电池容量单价元/kWh k_P 800; % 储能功率单价PCS等元/kW r 0.06; % 贴现率 N_years 10; % 项目寿命 eta_ch 0.95; eta_dis 0.95; SOC_min 0.1; SOC_max 0.9; C_rate 0.5; % 0.5C倍率 % 决策变量顺序E, P, 每个时刻 P_ch, P_dis, u_ch, u_dis, Q_ch, Q_dis, P_buy, P_sell % 实际建模中建议用 YALMIP 工具箱变量管理更简单。这里用 intlinprog 原始格式示意 % 为了可读性不写满所有索引只展示关键约束的构造思路 nvars 2 8*T; % 假定E、P为连续变量或整数变量加上8个逐时变量 lb zeros(nvars,1); ub ones(nvars,1); % 定义整数变量索引u_ch 和 u_dis 对应的索引列表 intcon [2 (2*T1:4*T)]; % 示意 % 目标函数 f: 初始投资 运维 购电 - 卖电 - 套利收益 % 省略具体构造核心是 f 与 E, P, P_buy, P_sell 的线性系数相关 % 等式约束功率平衡 % Aeq*x beqPV P_dis P_buy P_load P_ch P_sell % 不等式约束P_ch C_rate*E*u_ch? 实际上用Q变量线性化 % ... % 最终调用 % options optimoptions(intlinprog,Display,iter,MaxTime,600); % [x, fval, exitflag] intlinprog(f, intcon, A, b, Aeq, beq, lb, ub, options);如果你不习惯用intlinprog的矩阵格式强烈推荐在MATLAB里装YALMIP写约束像写公式一样E sdpvar(1,1); P sdpvar(1,1); % 额定容量和功率 P_ch sdpvar(T,1); P_dis sdpvar(T,1); u_ch binvar(T,1); u_dis binvar(T,1); SOC sdpvar(T1,1); P_buy sdpvar(T,1); P_sell sdpvar(T,1); % 约束 Constraints []; for t1:T Constraints [Constraints, P_pv(t)P_dis(t)P_buy(t) P_load(t)P_ch(t)P_sell(t)]; Constraints [Constraints, P_ch(t) C_rate*E, P_dis(t) C_rate*E]; Constraints [Constraints, P_ch(t) P, P_dis(t) P]; Constraints [Constraints, P_ch(t) 0, P_dis(t) 0]; Constraints [Constraints, P_ch(t) u_ch(t)*1e6, P_dis(t) u_dis(t)*1e6]; Constraints [Constraints, u_ch(t)u_dis(t) 1]; Constraints [Constraints, P_buy(t) 500, P_sell(t) 500]; % 变压器上限 Constraints [Constraints, SOC(t1) SOC(t) P_ch(t)*eta_ch/E - P_dis(t)/(E*eta_dis)]; end Constraints [Constraints, SOC(1)0.2, SOC_min SOC(2:end), SOC(2:end) SOC_max]; % 目标函数这里做了线性化处理避免E在分母造成非线性 Cost_invest k_E*E k_P*P; Cost_buy dt*sum(price.*P_buy); Revenue_sell dt*sum(sell_price.*P_sell); Objective Cost_invest Cost_buy - Revenue_sell; ops sdpsettings(solver,gurobi,verbose,2); optimize(Constraints, Objective, ops);注意上面代码里SOC递推分母有E这是非线性的不能直接丢给求解器。YALMIP虽然支持PNL但混合整数非线性规划求解难度大很容易无解。所以我前面推荐用Q变量线性化。在这个简化代码里如果E作为自由变量那么P_ch/E就是非凸的。实际建模时要么固定几档候选容量去跑整数选择要么用Q变量替代。3.6 线性化处理的三种常用套路在做容量优化时最常碰到的非线性源有三个SOC递推里有E在分母、目标函数里可能出现E和P_ch相乘、还有一个是P_ch和u_ch相乘表示“只有电池投建了才能充电”。这三个都有对应的线性化技巧。第一个分母E的问题定义等效充电倍率变量Q_ch P_ch/E约束改为0 ≤ Q_ch ≤ C_rateSOC递推式里用Q_ch目标函数里不出现Q_ch就能避开非线性。代价是多了一组变量但求解速度快很多。第二个E和P_ch相乘这种项一般出现在“容量越大充电功率越大”的耦合关系里。其实可以直接用P_ch ≤ P这个约束替代因为P本身就是额定功率额定功率约束已经保证了功率不超过额定值不需要再乘E。第三个0-1变量与连续变量相乘用大M法。比如“只有容量档位选了k才能在该档位容量下充电”引入0-1变量z_k表示第k档是否被选中那么E sum(z_k * E_k)同时P_ch ≤ M * z_k这个M取一个够大的数就行。我一般取1000既能保证松弛又不会让数值条件恶化。4. 一个算例跑下来看结果怎么解读我用前面说的典型日数据设光伏300 kW、峰值负荷350 kW、变压器容量400 kW分时电价按峰1.1元、平0.7元、谷0.35元光伏上网电价0.4元。储能候选容量从0开始每隔50 kWh取一档最大到600 kWh功率候选从0到200 kW间隔25 kW。4.1 优化结果容量150 kWh、功率75 kW这是典型的“小容量、低倍率”配置因为光伏装机只有300 kW负荷也不算大储能的主要功能是峰谷套利和稍微提升光伏自用率。150 kWh配75 kW倍率是0.5C能覆盖早上8点到11点两个高峰段的部分放电需求晚上低谷时段充电套利空间在每度电0.75元左右的峰谷差价一年省的电费大概9万元。初始投资按1200元/kWh的电池加上800元/kW的PCS算储能系统投资24万元左右加上并网改造和安装总共差不多28万元。静态回收期3年左右全生命周期净现值大概是正13万元内部收益率IRR在15%上下这个项目就算划算。如果把电池容量加到300 kWh呢结果依然可行但净现值反而低了因为多出来的150 kWh在绝大多数日子用不满每天循环深度只有不到50%容量利用率太低。这就回答了标题里的问题——电池不是越大越好多出来的钱躺在电池里睡大觉收益率是被摊薄的。4.2 灵敏度分析帮你理解边界条件我拿同一个模型分别跑了峰谷差价0.4元、0.6元、0.75元、1.0元四组结果非常直观峰谷差价低于0.4元时最优容量直接归零储能完全不具备经济性。这是很多项目投资方容易忽略的一点——不是在任何一个地方装储能都赚钱电费结构决定了商业模式。另外光伏上网电价从0.45元降到0.3元时最优容量从100 kWh涨到200 kWh原因在于光伏自用价值变高弃光成本变高储能帮光伏“挡弃光”的价值变大。这给我的实际感受是微电网的电池容量不是一个孤立的数字它是电价、光伏渗透率、负荷特性的函数。你跑一次优化只是拿到一个点多做几次灵敏度分析才知道这个项目到底靠什么赚钱。4.3 功率和容量为什么要解耦去看很多非专业的人会有个误解觉得电池容量定了功率就自然跟着定了。实际上磷酸铁锂电池的容量和功率可以灵活组合同一个电池舱配不同功率的PCS。优化模型里E和P是两个独立变量但它们通过倍率约束耦合在一起P ≤ C_rate × E。如果你觉得0.5C不合理可以改成1C功率往上提适合做调频或需量管理的场景。如果想要放电时间长的应用比如夜间的削峰可能要0.33C功率配小一点放电时间更长。这就是为什么我们不能只看容量必须同时看功率的原因。我个人的做法是先把倍率固定成0.5C或1C跑一版然后单独改变C_rate做敏感性分析。这样既能得到合理的电池舱选型又能知道如果换更贵的“高功率型”电池是否划算。5. 实际建模中踩过的坑和排查技巧5.1 intlinprog求解时间太长或者干脆卡死模型里0-1变量太多是主因。如果你的时间颗粒度是1小时跑全年8760小时那光u_ch、u_dis就有17520个0-1变量一般笔记本的intlinprog可能一个多小时都出不来。解决办法是降时间分辨率或者用典型日聚类的思路。我通常把全年数据K-means聚成4到6类典型日再乘上天数的权重。这样模型规模缩小到原来的几十分之一精度损失一般在5%以内对于工程决策完全够用。另外还可以把时间步长从1小时改成15分钟但那是为了刻画需量管理会加剧求解难度。实际做容量配置1小时步长足够了功率曲线里面的尖峰可以通过限制PCS功率和变压器容量间接考虑。5.2 约束写多了结果变成无解混合整数规划最容易出现的情况是约束之间互相矛盾。比如你既要求SOC每天同一时刻回到初始值又要求晚上必须充电但谷时电价和充电时间不够就解不出来。排查方法很简单先把电池功率和容量设成定值只优化运行策略看有没有可行解。如果运行策略都无解说明约束写错了或者数据有冲突如果运行策略有解但容量优化无解再看是不是整数变量范围设置太窄。还有一个我个人的小习惯所有不等式约束都用带松弛变量的方式先跑一遍。比如在约束右边加一个很小的负偏差epsilon比如1e-6配合罚函数能帮你定位是哪条约束太硬导致无解。实际项目里因为数据采集误差导致的约束违反非常常见尤其是功率平衡约束差个0.5 kW再正常不过所以我会把功率平衡写成绝对值小于0.5 kW的软约束。5.3 SOC递推公式的分母E处理不当就会非线性爆炸这个我已经强调过。很多人在YALMIP里写SOC(t1) SOC(t) P_ch(t)*eta_ch / E然后报错“nonlinear expression”。你不是非要引入Q变量也可以把E设成固定值然后循环枚举E跑多个整数线性规划选目标值最小的。比如E取100、150、200、250、300每个值下跑一次intlinprog比较总成本。这个方法简单粗暴而且工程上因为可选容量档位本来就有限枚举完全可行。我甚至建议初学者先这样做跑通了再优化模型性能。5.4 电池寿命衰减没有体现在模型里前文提到的充放电次数约束我没展开这里补充。电池寿命和等效循环次数强相关一般厂商给的是“5000次循环衰减到80%”也就是每完成一次满充满放寿命折掉一点点。如果不加约束优化器会让电池每天拼命充放电表面上看套利收入很高但实际上电池用不了五年就得换。项目周期10年中途换电池成本很高。所以我会加一个一天内累计放电量约束[ \sum_{t1}^{24} P_{dis}(t) \le E \cdot N_{cyc,max} ]N_cyc_max取0.8也就是一天最多等效0.8个满充满放循环。这样既保护了电池又限制了过度的套利行为模型也更贴近现实。5.5 别忘了功率平衡里的卖电项有些模型只写了“光伏储能电网 负荷”没有考虑光伏过剩时的上网。实际光伏出力一旦高于负荷多余电量有两种选择进电池或者卖电网。如果你不设卖电项这些电量就只能被抛弃优化器会夸大储能需求。我一开始也漏过这个结果算出来的容量严重偏大。加一条“P_sell ≤ min(P_PV, P_load)的差值”逻辑或者干脆用max函数处理结果就正常了。6. 从模型到决策还有一段路模型跑出“150 kWh、75 kW”这个数并不等于马上可以下单买设备。设备选型还有标准规格的问题——有的厂商只做100 kWh和200 kWh的储能舱150 kWh需要定制成本可能反而高。这种情况下更合理的做法是让优化器在候选容量档位里选整数而不是用连续变量。这就是为什么我之前强调如果你已经知道自己要买哪家厂商的产品直接把档位作为整数变量丢进混合整数规划算出来的才是可落地的方案。另外容量配置只是第一步。实际运行中电池的SOH衰减、温度对效率的影响以及电价政策调整都会让“最优”变“次优”。我通常会给决策报告附一个三年滚动收益率区间把最乐观和最悲观的边界都画出来。项目方看到这个心里才有底。7. 最后聊几句我的个人体会做微电网容量优化这行也有几年了最大的体会是问题模型的准确性,永远比求解算法的高级程度更重要。你用遗传算法跑一个简化模型还不如用混合整数规划跑一个精确模型得出的结论靠谱。MATLAB里的intlinprog虽然不如专业商业求解器那么快但胜在随手可得而且配合YALMIP写约束非常顺手学生和一线工程师都能快速上手。再分享一个实用的小技巧跑完优化别急着汇报结果画一张全年曲线图看看电池SOC在典型日的走势是否合理。如果SOC经常掉到下限还继续放电说明约束有漏洞或者数据里负荷和光伏对不上。如果SOC整天都在0.5附近小幅波动说明参数给得太保守储能几乎没有出力得查查目标函数系数是不是写错了。这些基于直观判断的经验比任何理论推导都更能帮你发现模型问题。说到底电池容量配置没有一劳永逸的答案。今天是峰谷差价0.75元最优是150 kWh明年政策性大用户电价改了可能就变成250 kWh。咱们做技术的能把账算清楚能跟投资团队解释清楚不同方案背后的逻辑这就已经很有价值了。希望这篇笔记能帮到正在跟微电网储能容量较劲的朋友。