☰
基于双层优化的配电网光伏储能选址定容方案
2026/10/13 13:47:51 网站建设 项目流程

如果手头有一个配电网需要规划光伏和储能接入,最让人头疼的问题往往不是设备选型,而是三个字:装哪、装多少、怎么配合。光伏面板往哪条馈线接、储能柜放在哪个节点、容量定多大,直接决定了这块电源是帮电网减压还是添乱。这个“分布式能源选址与定容”的项目,本质上就是一套基于双层优化框架的Matlab计算工具,用来在给定配电网节点系统上自动搜索光伏与储能的最优接入位置和容量配置。

我做完这套程序最直观的感受是:选址定容不是拍脑袋,而是把“投资决策+运行模拟”打包成一个大优化问题,让机器替你在上千种组合里找最优解。它适合准备做配电网规划方向的科研人员、搞新能源接入设计的工程师,也适合刚接触双层优化想找个完整代码框架练手的研究生。这篇文章我把模型拆开、把代码骨架讲透、把调参和踩坑的经历全部分享出来,看完你完全可以照着复现一套属于自己的光储优化配置程序。

1. 项目背景:光伏储能接入后,配电网到底出了什么问题

1.1 光伏一多,电压就不是原来那个电压了

传统配电网的潮流是单向的,电从变电站流向负荷,网络结构像一棵树,电压沿馈线方向逐渐降低。但光伏接入后情况变了:分布式电源往节点注入功率,相当于在每个接入点附近多了一个“反向负荷”。馈线末端的电压可能不降反升,尤其是在中午光照最强、负荷却不高的时候,光伏出力达到峰值,节点电压被顶到上限附近。

用工程口语说,就是“末端电压倒灌”。如果不控制接入位置和容量,轻则电压越限增加线损,重则触发逆变器保护停机。这个问题的数学本质很清晰:节点电压大致取决于该节点下游的净功率,光伏接入改变了净功率分布,而净功率分布又和光伏建在哪、建多大强相关。所以选址定容首先要解决的,是一个电压分布问题。

1.2 选址定容的数学本质:混合整数非线性规划

把这个问题翻译成数学语言,大致是这样一个框架:决定“某节点是否安装光伏/储能”是0-1整数变量,决定“安装容量是多少”是连续变量,而配电网潮流方程是非线性等式约束,电压上下限和线路载流量是非线性不等式约束。类问题在运筹学里叫混合整数非线性规划,规模随候选节点数和容量档位数爆炸式增长。

这也是为什么不能靠穷举。假设候选节点有10个,每个节点的光伏容量有10个可选档位,储能再有10个档位,组合数就是10的20次方量级,服务器也扛不住。合理做法是用智能优化算法在解空间里搜索,同时用潮流计算去校验每组方案是否可行、运行成本是多少。这个项目选择双层优化的思路,就是把这个大问题拆成“上层找配置、下层算运行”的两个相互嵌套的问题,逐个击破。

1.3 光伏和储能为什么要一起配,而不是各配各的

很多人一开始会想:先单独优化光伏,再单独优化储能,最后把两个结果拼起来不就行了?实测下来会发现结果往往不理想。原因在于光伏出力和负荷曲线在时间上是错位的。

白天光伏大发的时候,工商业负荷还没到高峰,电网吸纳不了那么多绿电,电压还容易被抬高;傍晚负荷起来了,光伏出力却已经掉到零。储能的价值恰恰在于补上这段时差:光伏多的时候把电能存起来,负荷高峰再放出去。如果分开优化,光伏会倾向于选容量最大的节点,储能会倾向于选峰谷差最大的节点,两者在空间和时间上根本没有协同,算出来的方案可能整体网损更高,投资回报更差。

所以正确的做法是把光伏和储能放进同一个优化模型里,让算法同步搜索它们的安装位置和容量,同时考虑储能的充放电时序,才能得到真正意义上的全局最优方案。

2. 双层优化模型:上层定方案,下层算运行

2.1 为什么双层结构比单层更合适

单层优化最容易遇到的问题:决策变量维度太高。光伏的位置、容量,储能的位置、容量,再加上每个时段储能充放电功率,一天24个时段,一年就是8760个时段,全挤进一个决策向量里,搜索空间大得离谱,而且离散变量和连续变量混在一起,求解器很容易陷入局部最优。

双层结构的好处是把“规划层面的事”和“运行层面的事”分开。上层只负责找光伏和储能的安装位置以及容量配置,站在投资决策者的视角看问题;下层在拿到一组配置后,去模拟典型日运行,算潮流、算储能时序,反馈运行成本和安全性指标,站在调度运行者的视角看问题。上下层之间有明确的输入输出关系,每一层的目标函数和约束条件都比原来清晰得多,程序结构也更易维护。

2.2 上层投资决策模型:目标函数和决策变量

上层优化的目标函数,我设计成最小化年度综合费用,包含光伏储能投资折算到每年的成本、设备运行维护费、配电网网损折算费用,以及惩罚项(电压越限、潮流不收敛等)。

投资折算采用等年值法,核心是资金回收系数CRF:

CRF = r * (1 + r)^n / ((1 + r)^n - 1)

其中r是贴现率,n是设备寿命周期。光伏寿命可以做20年,储能按电池循环寿命折算成年限,通常在10年左右。把初始投资乘以CRF,得到平均到每一年的投资成本,这样才能和每年的运行费用、网损费用放在同一个口径下比较。

上层决策变量主要包括:

  • 光伏接入节点编号(从候选节点集合中选取)
  • 光伏装机容量(在连续区间内取值)
  • 储能接入节点编号
  • 储能额定容量和额定功率

约束条件包括光伏总装机上限、储能总投资上限,以及同一个节点不能同时接太多设备等工程限制。

2.3 下层运行优化模型:给定方案下的运行模拟

下层拿到上层传来的配置后,要做两件事:一是按典型日场景跑潮流,二是确定储能每个时段的充放电功率。

如果储能策略用固定规则(比如光伏大发时充电、负荷高峰时放电),下层就可以简化为时序潮流计算,逐时段求潮流,统计全天网损和节点电压。这种实现比较简单,适合第一个版本跑通。

更严谨的做法是把下层也建成一个优化问题:在给定光伏出力和负荷曲线的条件下,以网损最小或运行成本最小为目标,优化储能每小时充放电功率,约束条件包括:

SOC(t+1) = SOC(t) + (ηc * Pc(t) - Pd(t) / ηd) * Δt / E SOC_min <= SOC(t) <= SOC_max 0 <= Pc(t) <= Pc_max 0 <= Pd(t) <= Pd_max

其中SOC是荷电状态,ηc和ηd分别是充放电效率,Pc和Pd是充放电功率,E是储能额定容量。每个时段的储能功率改变潮流分布,潮流分布又反过来影响网损,所以下层本质上是一个带储能时序的最优潮流问题。

2.4 上下层交互逻辑:每一组方案都跑一遍全年

上下层的关系可以这样理解:上层每搜索到一组光伏储能配置,就把这组配置传给下层;下层在全部典型日场景上执行运行模拟,返回一个综合运行费用和惩罚值给上层;上层用这个回报值计算适应度,指导种群朝着更优方向进化。

这个嵌套结构计算量不小。上层种群规模50,迭代100次,意味着要评估5000组配置,而每组配置下层都要跑几十个时段的潮流计算。所以程序里的速度优化很关键,后面我会讲哪些地方可以加速。

3. 光伏出力与储能时序协同的建模细节

3.1 光伏出力曲线怎么生成

光伏出力特性本质上是太阳辐照度通过光电转换效率映射出的功率曲线。一个典型的晴好天气,日出后出力近似从零开始爬升,中午达到峰值,下午回落,夜间为零。简化建模可以用正弦函数拟合:

t = (0:23)'; Ppv_norm = max(0, sin(pi * (t - 6) / 12)) .^ 1.5; Ppv = Ppv_norm * Ppv_max;

这段代码的逻辑是:假设早6点日出、晚18点日落,正午12点出力最大。指数1.5用来让出力曲线在早晚两端更陡一些,更贴近真实光伏下午衰减略缓的特点。工程上更精确的做法是直接用当地典型日的实测辐照数据,或者从气象库取太阳辐照度序列再乘转换效率。

如果项目只有一套负荷曲线,光伏也就一个形状,两者逐时对应,那只需要把光伏额定容量乘以归一化出力系数,叠加到对应节点负荷上,即可得到净负荷曲线。

3.2 储能运行策略:规则和优化的取舍

我以前做第一个版本时,储能策略用的是固定规则:光伏出力大于负荷需求时充电,负荷大于光伏出力时放电。好处是逻辑简单,跑得快,而且不存在求解器收敛问题,适合先把整体框架跑通、验证选址定容算法方向是否正确。

但固定规则有个明显短板:它不会主动利用峰谷电价差,也不会为了降低网损而在特定时段调整出力。比如晚高峰前一小时电价已经走高了,规则却还在等负荷超过光伏那一刻才放电,白白浪费低充高放的机会。

所以在正式版本里,我建议把下层改成一个小规模优化模型,用成熟的开源求解器直接求解每个时段的储能充放电功率。这个模型小到什么程度呢?决策变量就是24个时段的充放电功率,线性约束加上SOC递推,规模很小,求解一次也就零点几秒,完全可以嵌在双层循环里用。

3.3 典型日选取:全年8760小时这样压缩

如果下层直接把全年8760个小时全部跑完,每组配置的评估时间就会变得不可接受。实践里常见的做法是做典型日聚类,春夏秋冬各取一个代表日,或者用模糊C均值聚类把全年的净负荷曲线聚成3到5类,每类对应一个权重系数。

拿典型日加权来折算全年指标是一个很实用的简化方法。假设全年365天可以聚成三个典型日:大晴天、多云天、阴雨天,权重分别是60%、25%、15%。下层只需要针对这三个典型日分别做时序模拟,然后把网损、弃光量等指标按权重累加,就可以近似得到全年运行费用。误差完全在规划阶段可以接受的范围内,计算速度却提升了上百倍。

4. Matlab代码架构与核心函数实现

4.1 程序文件组织:模块化是跑通双层优化的基石

这套程序我从一开始就按模块化来组织,避免把所有逻辑堆在一个脚本里。整个项目的文件清单如下:

文件名功能说明
main.m主入口,设置算法参数,调用优化循环,输出结果
loadCase.m加载配电网节点系统数据(线路参数、负荷数据)
genTimeSeries.m生成光伏出力曲线、负荷曲线、储能参数
initPop.m初始化上层种群
decodePop.m将个体编码解码为光伏储能配置方案
powerFlow.m前推回代潮流计算,返回节点电压和支路功率
lowerLevelSim.m下层运行模拟,计算典型日运行成本和惩罚项
calcFitness.m汇总下层结果,计算上层目标函数值
selectCrossoverMutation.m遗传算子:选择、交叉、变异

这样分的好处很明显:想换一个节点系统,只需要改loadCase.m中的数据文件;想把遗传算法换成粒子群,只需要改main.m里的循环部分和算子函数;想修改储能策略,只需要改lowerLevelSim.m,其他模块都不受影响。

4.2 编码方案:一个个体怎么表示光伏和储能的位置容量

编码是双层优化里比较考验经验的一环。我的做法是用一个行向量表示一个个体,前面部分是光伏相关编码,后面部分是储能相关编码。

对于光伏:如果候选节点编号是固定的集合(比如7个候选节点),就用7位编码表示每个候选节点的安装容量,0表示不装,非零容量在0.1到2MW之间连续编码。对于储能:同样用等长的编码段表示储能接入容量和额定功率,每个位置对应候选节点,0表示不装。

% 一个个体示例:前半段是光伏,后半段是储能 % [PV_7节点容量 ES_7节点容量] % 例如: [0.3 0 0.8 0 0.5 0 0 0 0 0.6 0 0.4 0 0]

解码时要额外定义一个约束:同一节点的光伏和储能编码不能同时为零但允许都为零,也允许同时有容量,算法靠带惩罚因子的适应度函数把超出总安装上限的个体淘汰掉。

4.3 前推回代潮流和下层模拟的实现示例

配电网潮流计算,我用的是前推回代法。它的原理很直观:先假定各节点电压为额定值,从末端往首端推支路功率,得到线路损耗和各节点注入功率;再从首端往末端推节点电压分布,反复迭代直到前后两次计算的功率差值满足精度要求。对于33节点这样的辐射状网络,前推回代法比牛顿法收敛更稳,实现也简单。

核心的潮流计算循环可以这样写:

function [V, Ploss] = powerFlow(branch, load, gen, V0) V = ones(1, 33) * V0; % 电压初始值 for iter = 1:50 % 前推:根据电压计算支路功率 % 回代:根据支路功率更新节点电压 % 检查收敛误差 if max(abs(V - V_old)) < 1e-6 break; end end Ploss = sum(branch.p_loss); % 累加所有支路损耗 end

这是示意性的结构,实际省去了支路节点编号映射、功率累计和电压更新的细节,但套路就是这个套路。潮流的输入要把光伏出力和储能功率作为发电机节点数据接入,储能充电时当成负荷,放电时当成电源。

下层模拟的总体流程是:逐时段读取光伏出力系数和储能充放电功率,修改对应节点注入功率,调用powerFlow,统计全天网损总量和电压越限次数,最后把这两个指标乘以对应权重,返回给上层作为适应度的组成部分。

4.4 整体优化循环的标准模板

上层如果选择遗传算法,整体循环框架是这样的:

for gen = 1:maxGen for i = 1:popSize [PV_capacity, ES_capacity] = decodePop(pop(i, :)); [cost, punish] = lowerLevelSim(PV_capacity, ES_capacity); fitness(i) = calcFitness(cost, punish); end [pop, bestFitness] = selectCrossoverMutation(pop, fitness); end

这个循环写得对不对,直接决定结果能不能收敛。我在做的时候遇到过两类麻烦:一是下层模拟偶尔因为储能SOC越界而报错,导致整个个体适应度为无穷大,种群很快就崩了;二是popSize太小导致早熟,所有个体都集中到同一个次优解附近。这些都要在下一部分讲清楚怎么处理。

5. 参数标定、收敛性调优与结果分析

5.1 关键参数怎么设:我的参考表

这套程序在经典33节点配电网算例上测试(基准电压12.66kV,基准容量1MVA,总负荷约3.72MW,2.3Mvar),我用的参数如下:

参数取值说明
候选光伏节点7个含首端、中段、末端节点
光伏容量范围0 ~ 2 MW连续变量
储能容量范围0 ~ 1 MWh连续变量,功率按0.5C配置
储能SOC范围0.1 ~ 0.9防止过充过放
种群规模50太小早熟,太慢
最大迭代次数100常规收敛所需
交叉率0.8保持种群多样性
变异率0.1避免局部最优
潮流收敛精度1e-6前推回代法常规要求

这些参数不是一次定死的,我前后改了好几轮。如果你发现程序跑得很慢,优先把迭代次数砍半,而不是减小种群规模;如果你发现结果每次运行波动很大,优先增大种群规模并固定随机种子。

5.2 收敛性调整的三个实战心得

第一,惩罚项的系数不要一次性拉太高。电压越限、潮流不收敛这类约束,如果惩罚系数设成天文数字,会让适应度函数变得不平滑,遗传算法的选择压力直接失衡,种群很容易在某代全部退化。正确做法是让惩罚值刚好比正常成本高一个数量级,既能淘汰违规个体,又不会让算法失去探索方向。

第二,精英保留必须做。每代把当前最优的1到2个个体原封不动复制到下一代,避免因为交叉变异把已经很优秀的方案破坏掉。不做精英保留的遗传算法,经常会出现“这代最优解是xx,下代又丢了”的反复振荡。

第三,电压越限的处理不一定要完全依赖惩罚函数。如果某个节点的电压在被测时段越限了,直接把它折算成网损等值惩罚。这样算法会自然趋向于避开那些容易电压越限的节点,相当于在选址阶段就融入了安全性考虑。

5.3 仿真结果分析:三个场景对比

我在33节点系统上做了三组对照:不装任何分布式电源、只装光伏、光伏储能联合优化配置,测试一个夏季典型日。结果汇总如下:

场景网损/kW最低电压/pu电压越限次数年度综合费用/万元
无分布式电源202.50.9130按购电计
光伏单独配置138.60.9411相对下降明显
光伏+储能联合配置121.30.9580最优

从结果能明显看出:只装光伏虽然能降网损,但中段节点在正午光伏大发时出现了电压越上限的隐患;加上储能之后,储能柜在光伏大发时段充电,把多出的功率吸收掉,电压被压在限值以内,同时晚高峰放电又进一步压低了网损。储能只占了总投资的一小部分比例,却把系统整体的安全裕度和经济性都提上来了。

这种三场景对比的结论,放在报告里非常有说服力,因为它不只展示了“算法找到的最佳配置”,还论证了“为什么光伏必须和储能联合配置”这个核心逻辑。

6. 高频问题排查与我的个人调试经验

6.1 常见报错和故障速查表

我在开发调试过程中整理了典型问题对照表,适合大家直接对照排查:

现象可能原因排查方向
程序报数组越界节点系统数据中负荷数组和支路数组维度不一致检查loadCase.m中的数据录入,逐行核对行列数
潮流计算不收敛光伏容量设得过大,导致节点电压异常降低容量上限或改用平启动初值;检查储能SOC初始值
适应度大部分为无穷大大量个体违反电压约束调大惩罚系数,或修正初始种群生成逻辑,让初始解更贴近可行域
结果每次运行不一致遗传算法随机性导致固定随机种子set(0),或增大种群规模、增加迭代次数
储能SOC一直卡在边界充放电策略没有考虑SOC约束检查SOC递推方程的顺序是否放对了,插值要落在上下限区间内
程序跑得很慢下层每个个体都做全时段优化先切换到固定规则策略验证效果;再用典型日聚类大幅度降开销

6.2 我的调试路径:从单步到整链

我自己的经验是,这种双层嵌套程序不要一上来就直接跑全流程。调试顺序应该是“先固定方案、后全局搜索”。

第一步,先给定一组手调的合理配置(比如光伏装在末端两个节点0.5MW,储能装在中段0.4MWh),单独调用powerFlow,确认潮流计算本身是收敛的。第二步,保持这个固定方案,调用lowerLevelSim,检查储能SOC是否在上下限内、网损数值是否合理。第三步,把lowerLevelSim的结果喂给calcFitness,核对成本组成是否符合预期。最后一步,才把main.m整个优化循环跑起来。

这个顺序能帮你把“潮流问题”“储能时序问题”“遗传算法问题”三个层次隔离开来。如果一上来就跑完整程序,报错了都不知道错误出在哪一层,排查效率特别低。

我做完这套程序后的最大体会是:双层优化的框架本身不复杂,真正花时间的往往是那些看似不起眼的细节。比如光伏出力曲线归一化系数写错一位小数,会导致优化结果集中在某个错误节点;储能SOC的初始值设成0.5还是0.8,会影响整个典型日的充放电空间;惩罚系数大了收敛性差,小了又不满足约束。这些坑坑洼洼趟过去之后,回头再看这个项目,其实就是一套很清晰的方法论:把复杂的配电网规划问题拆成投资层和运行层,用算法搜索位置和容量,用潮流验证每个方案的可行性。把这个骨架搭好,后续不管是换更大的节点系统,还是加进电动汽车充电桩、燃气轮机等更多分布式能源类型,都是往骨架上填肉的事。

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

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

立即咨询