
配电网里做分布式能源规划光伏和储能的选址定容是个绕不开的硬骨头。很多人手头有Matlab代码能跑通潮流、能做优化但一旦把光伏和储能同时放进配电网问“装在哪个节点、装多大容量”时就卡住了。这个问题的本质是投资决策与运行调度互相耦合规划方案定了储能该放哪运行策略又决定了规划方案到底省不省钱、电压合不合规。这篇内容我想把这套“光伏、储能双层优化配置接入配电网”的完整思路讲清楚包括模型怎么搭、Matlab代码怎么落、调试中哪些坑我替你先踩了适合正在做配电网规划课题的研究生以及准备用优化方法解决实际并网问题的工程人员参考。1. 配电网里装光伏和储能难的是回答“装哪、装多大”1.1 为什么选址定容不能靠经验拍脑袋先聊一个很多项目里真实发生过的场景。某个台区变压器容量有限设计人员在末端节点“凭经验”装了几百千瓦光伏结果午间光伏大发时线路末端电压直接冲到1.08 p.u.以上逆变器被迫限功率发电量反而受损。这就是典型的光伏集中接入引发功率倒送和过电压问题。储能虽然能吸收多余功率但如果容量配置不合理投资回收周期会被拉得很长甚至出现“装储能比不装还亏”的尴尬局面。选址定容本质上是一个离散与连续变量混合的组合优化问题。安装位置要选节点编号这是离散变量每个节点的光伏、储能容量是连续变量还需要同时考虑一年8760小时的负荷与光伏出力时序、网络拓扑和潮流约束。靠人工试算是完全不可能遍历所有组合的靠启发式经验又容易踩局部极端情况。这也是为什么这个方向的研究热度一直很高从单目标优化到多目标优化从确定性模型到不确定性模型本质都是在回答“装在哪、装多大才能综合效益最优”这一个核心问题。1.2 双层优化在这个问题里的角色定位为什么这类问题特别适合用双层优化框架关键在于投资决策与运行调度之间存在天然的时间尺度差异。选址定容是规划层面的决策一年甚至几年才做一次决策后设备装在那里就基本固定了而储能怎么充放电、光伏怎么出力、主网购电多少是运行层面的决策以小时甚至分钟为周期滚动调整。把这两类决策放在同一个单层模型里要么因非线性潮流变成难以求解的非凸问题要么让算法分不清投资变量和运行变量的主从关系结果往往不理想。双层模型恰好把这种主从递阶关系刻画得很清楚上层做规划决定光伏和储能的选址定容方案下层做运行在上层给定的方案下优化典型日的调度策略并把运行成本或网损指标反馈给上层。上层再根据反馈修正方案反复迭代直到找到综合最优。我在实际项目里体会最深的一点是这种结构让模型的可解释性变得非常好——哪一部分是投资成本、哪一部分是运行成本、上下层之间是怎么耦合的都能清楚地拆开出问题的时候也容易定位。2. 双层模型的两层职责规划层拍板方案运行层核算代价2.1 上层规划模型总投资与运行费用的权衡上层规划层要做的事情是在所有候选节点中选出光伏和储能的最优安装位置同时给出最优容量。它的目标函数通常写为年综合费用最小即[ \min ; C_{\text{total}} C_{\text{inv}} C_{\text{om}} C_{\text{oper}} ]其中 (C_{\text{inv}}) 是光伏和储能投资成本的等年值(C_{\text{om}}) 是年运行维护费用(C_{\text{oper}}) 是下层返回的年运行费用典型日运行成本的年度加权。投资成本要折算成等年值依靠的是资金回收系数Capital Recovery Factor, CRF[ CRF \frac{r(1r)^n}{(1r)^n - 1} ](r) 为贴现率(n) 为设备寿命。把总投资额乘以 (CRF)就得到每年平均分摊的投资成本。这里的难点在于光伏和储能的寿命不同——光伏通常按20-25年计算锂电池储能受循环次数限制一般按10-15年计不能简单用同一个 (n) 一刀切。上层约束条件包括投资预算上限、单个节点最大安装容量、全系统总安装容量约束以及每个候选节点是否安装的0-1变量约束。实际建模时节点电压和支路潮流约束通常不直接写入上层而是交给下层处理通过下层返回的约束违反度反馈给上层这样建模逻辑更清晰上层算法的收敛性也更好控制。2.2 下层运行模型在方案给定前提下做最优调度下层接收上层给定的光伏、储能选址定容方案后在一个典型日通常取96时段15分钟一个点内做运行调度优化。下层的决策变量包括储能各时段充放电功率、光伏有功出力、主网购电功率有时还包括储能的无功支撑。目标函数是典型日运行费用最小[ \min ; \sum_{t1}^{T} \left( c_t P_{\text{buy},t} \Delta t c_{\text{loss}} P_{\text{loss},t} \Delta t c_{\text{curtail}} P_{\text{curtail},t} \Delta t \right) ]分别对应购电费用、网损费用和弃光惩罚。约束条件包含配电网潮流平衡常用DistFlow辐射状配电网潮流方程、节点电压上下限通常取0.95~1.05 p.u.、支路电流上限、储能SOC递推关系、充放电功率限制、购电功率上限等。储能SOC的递推关系是下层模型的核心[ SOC_{t1} SOC_t \left( \eta_{ch} P_{ch,t} - \frac{P_{dis,t}}{\eta_{dis}} \right) \Delta t / E_{rated} ](\eta_{ch})、(\eta_{dis}) 分别为充放电效率(E_{rated}) 为储能额定容量。这个约束的正确建模直接影响优化结果的可信度。另外还需要令 (SOC_1 SOC_{T1})保证储能以日循环方式运行不能让模型在优化结束时把电池电量放空从而虚增经济收益。2.3 上下层之间如何耦合KKT条件与启发式嵌套的取舍双层规划的求解路径大致有两类。第一类是KKT条件法把下层问题的Karush-Kuhn-Tucker最优性条件推导出来作为上层模型的附加约束从而把双层问题转化为单层问题。这个方法的优点是数学上严谨求解效率高但前提是下层问题必须是线性的或凸二次规划否则KKT条件无法等价转换。配电网潮流本身是非线性的虽然可以用线性化DistFlow近似但近似误差需要评估建模工作量也不小。第二类是启发式嵌套上层用元启发式算法粒子群、遗传算法、灰狼优化等搜索选址定容方案每评估一个方案就调用一次下层求解器做运行优化下层的精确解作为上层的适应度值。这种方法逻辑简单、模块清晰、容易扩展缺点是计算量大。我在实际项目中更倾向于后者尤其是用PSO嵌套YALMIP时代码架构非常直观后续要增加约束或换求解器都很方便不需要动上层算法框架。对比维度KKT条件法启发式嵌套数学严谨性高全局最优性有保障依赖算法性能一般得到近似最优建模复杂度推导KKT条件繁琐易出错模块化建模主从关系清晰求解速度快单次求解慢需反复调用下层对下层凸性要求要求线性或凸二次无要求扩展难度每加一个下层约束都要重新推导直接追加约束即可这两种方法都在论文里大量见到但实验环境不同选择也不同。做工程验证或代码实现教学我推荐启发式嵌套好调试、好理解追求严格最优解且下层模型不复杂时KKT法是值得投入精力去推导的路线。3. Matlab实现的两条关键链路建模、编码与上下层数据交互3.1 工具链选型YALMIP、求解器与潮流计算的分工Matlab环境下做这类优化我的标准配置是“YALMIP Gurobi/CPLEX Matpower可选”。YALMIP是一个建模语言工具包它的价值在于把优化问题的目标函数和约束条件用非常接近数学表达式的语法写出来然后统一派发给底层求解器。Gurobi和CPLEX是商用的数学优化求解器对线性规划、混合整数规划、二次规划的求解性能非常出色高校用户申请学术许可证很方便。如果下层的运行优化是线性化潮流模型直接用YALMIP建模并调用Gurobi是最顺畅的路径。如果要做精确潮流校核可以用Matpower对优化结果做后验验证。需要注意Matpower自带的是常规潮流计算不直接参与YALMIP的优化建模所以我一般把Matpower当作“裁判”而不是“球员”。当然如果你对配电网潮流非常熟悉也可以自己在Matlab里写DistFlow方程并交给YALMIP处理只是在处理非线性约束时要注意初值敏感性。3.2 上层PSO的编码方式与参数设计粒子群算法的编码决定了搜索空间的维度和语义。在我常用的编码方案里一个粒子包含四段基因光伏候选节点的容量向量、储能候选节点的额定功率向量、储能容量向量以及一组0-1变量表示是否安装。相邻的实数值互相配合解码时就能得到完整的选址定容方案。以IEEE 33节点系统为例如果设了10个候选节点粒子的长度大概是10光伏容量 10是否装光伏 10储能功率 10储能容量一共40维。这个规模对PSO来说非常轻松。参数设置上种群数取30-50迭代次数取50-100惯性权重从0.9线性递减到0.4学习因子 (c_12.0, c_22.0)。这些参数是经过大量文献和实践验证的经验值不用刻意调整就能得到不错的结果。粒子越界处理是我在上层代码里特别注意的地方。很多初学者直接对越界维度做裁剪把值拉回边界这会让粒子群过早聚集在可行域边缘失去探索能力。实测下来反弹边界处理的效果往往更好超出上限就从上限往回弹超出多少弹多少能有效维持种群多样性。3.3 下层运行优化的YALMIP建模要点下层模型用YALMIP建模时要把所有时段的决策变量声明成向量或矩阵。以96时段为例核心代码骨架大致是T 96; dt 0.25; % 15分钟一个点 P_buy sdpvar(1, T); % 主网购电功率 P_ch sdpvar(1, T); % 储能充电功率 P_dis sdpvar(1, T); % 储能放电功率 SOC sdpvar(1, T 1); % 荷电状态 u_ch binvar(1, T); % 充电状态标志 u_dis binvar(1, T); % 放电状态标志 Constraints []; % 储能SOC递推 Constraints [Constraints, SOC(1) SOC0]; Constraints [Constraints, SOC(2:end) SOC(1:end-1) ... (eta_ch * P_ch - P_dis / eta_dis) * dt / E_rated]; % 不同时充放电 Constraints [Constraints, P_ch M * u_ch]; Constraints [Constraints, P_dis M * u_dis]; Constraints [Constraints, u_ch u_dis 1]; % 节点电压约束以线性化DistFlow为例 % 这里需要根据网络参数和光伏、储能接入位置动态生成约束矩阵 Objective sum(price .* P_buy) * dt ... sum(c_loss * P_loss) * dt ... c_curtail * sum(P_curtail) * dt; ops sdpsettings(solver, gurobi, verbose, 0); optimize(Constraints, Objective, ops);不同时充放电的约束需要引入0-1变量 (u_{ch}, u_{dis}) 和足够大的常数 (M)这让下层问题变成混合整数规划。好在Gurobi对这类MIP的求解速度很快96时段的储能调度通常一两秒内能解完。不过如果网络节点数多、约束复杂MIP求解时间会明显上升这时候就要考虑把不同时充放电约束松弛用很小的惩罚项引导模型避免同时充放电大幅提升求解速度。3.4 上下层代码骨架从粒子解码到适应度计算整个双层优化代码的主循环非常清晰用伪代码表示为for iter 1:MaxIter for i 1:Np % 粒子解码得到光伏和储能的节点、容量 [pv_node, pv_cap, es_node, es_power, es_cap] decode(pop(i, :)); % 更新配电系统参数 net update_network(net, pv_node, pv_cap, es_node, es_power, es_cap); % 调用下层运行优化返回运行成本与约束违反度 [oper_cost, violation] run_lower(net, load_curve, pv_curve, price); % 上层适应度 投资等年值 运维费用 运行成本 惩罚项 fitness(i) annual_invest(pv_cap, es_power, es_cap) ... annual_om(pv_cap, es_power, es_cap) ... oper_cost * 365 penalty(violation); end % 更新粒子速度和位置 [pop, velocity] update_pso(pop, velocity, fitness, iter); end解码、网络参数更新、下层求解、适应度计算这四步构成了上层和下层之间的数据交互闭环。最容易出的问题集中在update_network这一步——如果光伏或储能节点编号与网络数据中的节点索引不匹配下层潮流就会出错。编码时我习惯把候选节点列表定义成全局变量解码时通过索引映射到实际节点避免硬编码节点编号带来的低级错误。4. 实测中反复踩过的三个坑求解器、SOC约束与迭代收敛4.1 求解器调用失败与结果精度不稳定初学阶段最让人崩溃的就是YALMIP报“No suitable solver found”。通常情况下这个报错有三个原因求解器没有正确安装、Matlab路径没添加、许可证没有生效。Gurobi在Windows下要通过系统环境变量设置GRB_LICENSE_FILEMatlab中调用时有时候会因为环境变量没有刷新而找不到许可证重启Matlab往往能解决一半问题。更隐蔽的问题藏在求解精度里。Gurobi默认的MIP gap是万分之一级别对于一般的储能调度问题已经足够但双层迭代几百次之后微小的求解误差会在PSO适应度评估中累积导致迭代收敛曲线出现高频毛刺。如果是做严格对比实验建议设置固定的随机种子并把求解器的MIP gap参数固定保证每次调用下层求解器的数值行为一致。我自己在实验时会记录每次下层调用的目标函数值定期检查有没有异常波动这是排查“程序莫名其妙不收敛”问题的第一道防线。4.2 储能同时充放电与SOC初末值约束如果下层模型不加以约束优化器可能给出储能同时充电和放电的荒谬结果——一边花钱买电给电池充电一边放电卖给配电网中间套利的假象直接扭曲了目标函数。这通常发生在目标函数中加入了一些与储能充放电不直接相关的惩罚项时。解决办法是引入二进制变量强制不同时充放电代价是下层从LP变成MILP求解时间上升。一种更快的替代方案是在目标函数里给充电和放电同时加上极小的非负正则项例如 (10^{-6} \times (P_{ch}P_{dis}))利用线性规划的最优解对目标函数的细微变化足够敏感这一特性诱导优化器避开同时充放电的奇异解。这个方法在实际求解中很有效且不引入整数变量求解速度几乎不受影响。SOC初末值约束是我反复强调的点。如果不强制 (SOC_1 SOC_{T1})优化器会在最后一个时段把储能电量全部放光制造出“赚了最后一笔电费”的假象。对于配电网日调度来说储能每天回到初始SOC状态才是符合实际运行逻辑的。处理方式有两种直接写等式约束或者在目标函数里给SOC末端值与初值的偏差加一个大的惩罚系数。等式约束更严格也推荐优先使用。4.3 上下层迭代不收敛怎么判断是模型错还是算法错当PSO迭代了二三十代适应度曲线一直震荡不下降时不要急着怀疑粒子群算法参数没调好先排查模型是不是写错了。常见的一个问题出现在下层运行优化的可行域判定上如果上层给出的光伏容量过大或储能位置导致潮流约束无解下层返回的约束违反度会是一个很大的惩罚值此时不同粒子之间的适应度差距会被惩罚项淹没PSO就像在平地上走路完全失去寻优方向。我的调试经验是先用一个手工构造的合理方案比如只在末端节点装固定容量的光伏和储能跑通下层确认下层返回的数值在合理范围内再把这个方案作为PSO初始种群的一个粒子观察PSO是否会在迭代初期保留这个优质解。如果连这个都留不住说明代码的可行解标记或惩罚项设置有问题而不是算法参数的问题。确定模型没问题之后再调整PSO的种群规模和惯性权重。另一个高发问题是粒子解码后的网络参数更新不一致。例如光伏容量更新了但储能容量没有同步更新或者节点索引发生偏移下层求解器接到的还是旧网络参数。这类“潜藏bug”通常不会导致程序崩溃但会让适应度评估结果完全错误。排查方式是把某一次迭代的粒子解码结果和下层网络数据分别打印出来比对确认信息传递链路没有断裂。5. 结果怎么解读算例对比要展现出双层优化的真实价值5.1 算例设计IEEE 33节点系统与典型日场景我搭建验证算例时用的是IEEE 33节点配网系统基准电压12.66 kV总负荷约3715 kW加2300 kvar。这个系统规模适中节点数量足够展现优化效果差异计算开销又在个人电脑可承受范围内是配电网优化研究的事实标准。负荷曲线和光伏出力曲线都按典型日处理取96时段。分时电价采用峰平谷三段峰时1.0元/kWh平时0.6元/kWh谷时0.3元/kWh。储能参数按锂电池考虑单位容量成本取2000元/kWh单位功率成本取2500元/kW充放电效率0.95SOC运行范围0.1~0.9。光伏候选节点一般放在负荷较重、电压偏低的末端区域比如部分重载节点和末端节点但注意这只是候选集合最终装在哪、装多少要由优化算法决定。这样设计符合实际工程中“哪里需要就优先考虑哪里”的选点思路。5.2 关键指标对比网损、电压与综合成本运行双层优化后至少要和两个基准方案对比才有力。第一是无分布式电源的原始配网第二是只优化光伏、不配置储能的方案第三才是光伏储能双层优化方案。对比维度包括年网损、节点最低电压、光伏利用率、综合费用等。一个典型的对比结果如下方案光伏装机/kW储能配置/kW·kWh年网损/MWh最低电压/p.u.年综合费用/万元无分布式电源00约11000.913约420仅光伏优化18000约7800.941约390光伏储能双层优化1500400/1200约6200.978约350从结果能明显看出单纯加光伏虽然能降低网损和费用但末端电压改善有限加入储能并优化配置后电压质量提升显著网损进一步下降。储能的价值除了峰谷价差套利还有效消纳了光伏大发时的反送功率缓解了电压越限问题这正是双层优化“112”的核心体现。5.3 从运行曲线反推模型合理性算例跑完后一定要把典型日的运行曲线画出来看这是验证模型是否正确的最直观手段。正常情况下光伏出力中午最大储能应该在中午到下午时段充电晚高峰时段放电。如果优化结果出现“白天放电、晚上充电”千万不要以为发现了什么高级策略这大概率是电价或时序数据写反了。我还会重点看储能SOC曲线是否在一天内平滑波动并且首末值相等。SOC曲线如果出现频繁的剧烈震荡说明充放电切换过密对电池寿命非常不利可以在下层目标函数里加入充放电切换次数的惩罚项来抑制。这个细节在论文里往往不被强调但工程实践中直接关系到储能系统的实际寿命和经济性。电压曲线方面应该对比中午光伏大发时刻和晚高峰时刻的节点电压剖面。优化前末端节点在某个时段的电压可能跌破0.95 p.u.优化后应该恢复到安全范围。把这两个时刻的电压曲线画在同一张图里是最有说服力的展示方式也方便在答辩或报告中解释方案的实际效果。6. 这类项目的延伸方向多目标、不确定性与多元资源协同做过一轮双层优化之后很容易发现这个框架的可扩展空间非常大。最直接的方向是多目标化把年综合费用和系统电压偏差作为两个优化目标用NSGA-II等算法求解Pareto前沿。这样决策者就能在投资成本和电能质量之间做权衡而不是被单一的加权系数捆住手脚。我见过很多项目把目标函数线性加权成一个值虽然简单但权重的选择本身很主观评审时容易被挑战。不确定性建模也是当前研究的热点。光伏出力本身有很强的随机性用确定性典型日曲线求解得到的方案在实际运行中可能偏乐观。场景法随机规划、两阶段鲁棒优化都是主流的处理思路。双层框架天然适配两阶段随机规划第一阶段是选址定容第二阶段是各个场景下的运行调度期望值。不过要注意场景数量增大后计算量会急剧上升场景削减技术如K-means聚类选典型场景几乎是必须的。再往后推一步可以考虑更多分布式资源的协同配置。比如把电动汽车充电站、可控负荷、需求响应、电容器组都纳入优化框架用电网改造的方式降低配电网对传统扩容的依赖。热词里提到的“构网型储能系统配置规范”“三相光伏逆变”这类话题说明工程界已经在关注储能逆变器对配电网的支撑能力而不仅仅是削峰填谷。如果把逆变器的无功调压能力也建模进下层运行层双层优化的结果会更贴近实际工程需求。还有一个被很多代码实现忽略的问题规划是多年的。配电网负荷逐年增长光伏和储能也不是一次装完就一劳永逸多阶段动态规划才能反映真实投资时序。这部分计算复杂度更高但做出来的成果无论从学术创新还是工程实用角度看价值都上一个台阶。最后分享一个我反复试验后的建议不要一上来就写上层算法和下层求解的耦合代码先把单个下层运行优化彻底跑通用固定方案验证储能SOC曲线和费用结构是否合理。这一步通过了再加上层PSO很多莫名其妙的报错都能避免。做这类项目80%的时间会花在调试、验证、调参数上模型框架反而是最容易定下来的部分。