光伏储能双层优化配置配电网选址定容的Matlab实现
2026/9/13 13:44:32 网站建设 项目流程

分布式能源选址与定容这事儿,我这两年用Matlab做了不少算例,从最初的盲试到后来能一小时跑完一套完整方案,中间踩过的坑比代码行数还多。今天就把这套光伏、储能双层优化配置接入配电网的研究思路和Matlab实现经验完整拆开聊,从模型怎么搭、代码怎么写到结果怎么解读,一次性讲透。

这套东西解决的核心问题就是两个:光伏和储能装在哪、装多大。别小看这两个问题,装错了位置,光伏午间出力高峰可能直接把节点电压顶到越限;储能容量选大了,投资收不回来,选小了,削峰填谷根本不起作用。我在实际算例里见过不少方案,网损确实降了,但电压越限问题反而更严重,典型的捡了芝麻丢西瓜。

所以做选址定容,不能只看单一指标。这套研究用双层优化把规划层的投资决策和运行层的调度策略解耦开,上层决定装什么,下层负责算清楚装完之后系统怎么运行、成本是多少,再把运行结果反馈回上层作为方案评价依据。这种结构非常贴合电力系统里"先规划、后运行"的实际决策流程,也是目前这个方向用得最多的建模方式。

无论你是刚接触分布式能源规划的研究生,还是在做配电网项目的工程师,这篇文章都会把从建模到落地的关键环节讲清楚。模型目标函数怎么设、约束条件容易漏掉哪些、粒子群参数怎么调、内层求解器报错怎么处理,这些常规论文里不会写细的东西,我在下文里都给你交代明白。

1. 为什么选址定容这么关键:光伏储能在配电网里会惹什么麻烦

1.1 光伏接入带来的电压抬升与消纳难题

光伏发电有一个天然特性,就是它的出力曲线和负荷曲线往往错位。午间光伏出力达到峰值的时候,恰恰是居民和商用负荷的低谷期,工厂还没到换班高峰,空调负荷也还没起来。这时候多余的电只能顺着馈线往回送,也就是业内常说的反向潮流。

反向潮流一出现,节点电压就会被抬高。这个抬升幅度在接入点附近最明显,因为电流往回走,线路压降的极性反转了。分布式光伏渗透率高的馈线,末端节点电压在午间时段容易逼近甚至超过上限,这在光伏资源好的地区尤其常见。电压越限的后果不只是电能质量不合格,严重了会导致用户设备损坏、逆变器保护动作频繁启停,甚至是馈线保护误动。

光伏的另一个问题就是出力波动。云层飘过,出力可能在半分钟内掉一半,这种短时功率波动对配电网的调压和无功控制设备是很大考验。我做仿真的时候看到过一条馈线,一分钟内电压波动超过3%,这已经超过国标对电压变动的限值了。如果这些问题不在规划阶段就考虑进去,等到实际运行出问题再来补救,成本要高得多。

1.2 储能的价值与选址定容的决策困境

储能在配电网里的角色,简单说就是搬运工加缓冲池。光伏出力高峰时把电存起来,负荷高峰时再放出去,既避免了午间电压抬升,又能在晚高峰提供支撑。同时储能还能平抑出力波动,让光伏并网点的功率曲线平滑很多。理论上讲,储能是光伏接入配电网的最佳搭档。

但储能的成本摆在那,电池本体、PCS变流器、土地、运维加起来,一套MWh级的储能系统投资不小。这就带来了决策困境:储能不是装得越多越好,装多了利用率上不去,投资回收周期长得吓人;也不是哪儿都能装,装在不合适的位置,线损降低效果差,削峰填谷作用也发挥不出来。

光伏的选址也是类似的逻辑,光照资源好但设备老旧、容量紧张的馈线段,未必比光照稍差但网架结构合理的节点更适合。这类问题看起来是选几个坐标、定几个容量,本质上是在投资成本、系统安全、运行经济性三者之间找平衡点。纯靠经验拍脑袋选节点,跑几个潮流算例看看结果,很难保证方案是全局最优的。

1.3 双层优化为什么比单层更贴合这个问题

选址定容问题最直观的做法是搭一个混合整数非线性规划模型,把所有投资决策变量和运行决策变量放一起求解。理论上没问题,但这个模型里既有0-1整数变量(装不装)、连续变量(容量多少、功率多少),又有潮流方程这种强非线性约束,再加上储能的时间耦合约束(SOC的时序递推),求解难度非常大。我用商业求解器试过直接求解单层模型,中等规模算例跑几个小时还经常找不到可行解,工程上根本没法用。

双层优化把问题拆成了两层:上层做投资决策,下层做运行模拟。上层每次确定一组选址定容方案后,下层就在这个方案下求解最优运行策略,再把运行指标反馈给上层。这样每一层的问题规模都小了很多,下层潮流和调度问题用成熟求解器就能快速求解,上层用智能算法去搜索方案空间。更重要的一点是,这种结构非常贴近实际决策流程——先定规划方案,再做运行调度,决策逻辑清晰,也方便工程人员理解每个方案为什么优、为什么劣。

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

2.1 上层规划模型的目标函数与决策变量

上层模型回答的问题是"在哪些节点装、装多大容量"。决策变量包括光伏的安装节点和装机容量,以及储能的安装节点、额定功率和额定容量。这里有一个实际问题:光伏和储能是否必须绑定安装在同一节点?

从我做的算例经验来看,光伏和储能同点位安装的方案实施起来更简单,征地、并网、运维都方便,但未必是运行最优的。允许光伏和储能分别在适合的节点安装,会给上层优化更大的搜索空间,最终方案的综合经济性往往更好。不过要注意,解绑后问题的组合爆炸特性会更明显,对上层搜索算法的要求也更高。

上层目标函数我通常设定为年综合费用最小,或者年净收益最大。年综合费用包含几个部分,一是光伏和储能的年化投资成本,把总投资按寿命周期折成等年值;二是年运行维护费用,按装机容量的比例估算;三是系统年运行费用,这部分来自下层反馈,包括向上级电网购电的费用和网损费用。如果算例设置了分时电价,购电费用就要按峰平谷三个时段分别计算,这也更符合实际。

约束条件方面,第一是投资预算约束,总投资的现值不能超过给定预算上限。第二是各节点安装容量上下限约束,比如单个光伏接入点的容量不能超过该节点变压器容量的某个比例。第三是安装节点数约束,很多工程案例中会对分布式电源的总接入点数有限制,因为每增加一个接入点就多一套并网设备。第四是渗透率约束,分布式电源总装机容量占系统峰值负荷的比例不能超过设定值,这个约束在消纳能力不足的地区尤其重要。

2.2 下层运行调度模型的核心约束

下层模型在每个上层方案下求解典型日的运行策略。目标函数是系统日运行成本最小化,主要构成是向上级电网的购电成本,加上网损成本。如果是夏季和冬季多个典型日分别计算,就把每个典型日的运行成本加权汇总后反馈给上层。

下层决策变量是每个时段的光伏实际出力和储能充放电功率。光伏出力在光照充足时通常全额消纳,但如果出现电压越限风险,也可以做弃光处理,弃光惩罚系数设置得比较高就行。储能运行策略是典型的时间耦合问题,需要满足前后时段的SOC递推关系,充电效率、放电效率和自放电率都要考虑进去。

潮流约束是下层模型的核心。在配电网计算中,我一般用DistFlow分支潮流方程,这个模型在处理辐射状配电网时精度足够且求解速度快。节点电压需要维持在允许范围内,IEEE 33节点算例中我习惯设为0.95到1.05pu。线路传输功率不能超过载流量限制,购买电力的联络线功率也要有限制。

储能运行约束要特别注意,除了SOC递推外,还要保证一个调度周期结束后SOC回到初始值,不然储能就在一个周期内偷偷"赚"能量,结果没有实际意义。充放电功率不能同时为正值和负值,如果有0-1变量能处理就直接处理,如果没有,通过大M法或者二进制变量方式也能解决。我在YALMIP里实现时习惯用二进制变量把充放电状态显式建模,清晰不易出错,代价是求解时间略长。

2.3 上下层迭代求解的实现逻辑

上下层求解的衔接方式,常见的有两种路线。第一种是把下层模型通过KKT条件转换为上层模型的约束,形成单层数学规划问题再求解。好处是用数学优化方法处理,有最优性保证;坏处是KKT转换要求下层是凸问题,而且补松弛条件会引入大量非线性项,最后模型复杂度依然很高。

第二种是我更常用的方法,上层用启发式算法比如粒子群,下层用数值求解器精确求解,上下层通过迭代实现嵌套。每次上层生成一组粒子的位置,也就是一组选址定容方案,然后逐一送入下层求解器计算运行成本,把结果返回给上层更新粒子的适应度值。虽然计算量相比单层模型大不少,但每一层的求解器都很成熟,稳定性好,出了问题也好排查。

这里有个实操细节,上下层之间的数据传递要定义好接口和单位。上层传给下层的是光伏安装节点序号、光伏容量、储能安装节点序号、储能功率和容量这些静态参数。下层返回的是典型日总运行成本、网损电量、弃光电量、最大电压偏移这些运行指标。如果单位不一致,比如上层用kW,下层用MW,计算出来的数据可能就是天文数字或者接近零,这个坑我在初版代码里踩过,调试了半天才发现是单位问题。

3. Matlab代码实现:从IEEE 33节点算例到可复用框架

3.1 算例系统与基础数据准备

我用的测试系统是标准的IEEE 33节点配电网,基准电压12.66kV,系统总负荷大约3.7MW加2.3Mvar。这个系统的拓扑结构很规范,节点和支路参数在很多论文里都能查到,方便结果对比验证。关键是这个网络有33个节点、32条支路,规模不大不小,既能体现电压分布问题的复杂性,又不会让内层求解器算得太慢。想研究更大规模的系统,比如IEEE 69节点或123节点,代码逻辑完全不用改,只换数据文件就行。

基础数据要准备这么几类。第一是线路参数,每条支路的电阻电抗和最大载流量;第二是节点负荷参数,典型日的负荷曲线我在算例里取的是24个时段的标幺值曲线,峰谷比大约1.5到2.0之间;第三是光伏出力曲线,夏季典型日取早6点到晚7点有出力,午间12点到14点达到峰值,峰值利用小时数我按全年1200小时倒推;第四是分时电价数据,我这里设定峰时段1.2元/kWh、平时段0.75元/kWh、谷时段0.4元/kWh,储能就是在谷时充电、峰时放电来套利的。

一种常见的做法是把光伏和储能的物理参数做在独立文件中。光伏逆变器功率因数设定为0.95,储能系统充放电效率设为0.95,SOC运行范围取10%到90%,储能寿命按10年计,光伏寿命按20年计。投资单价方面,光伏按每千瓦3500元估算,储能电池按每千瓦时1200元,PCS按每千瓦500元,这些参数可以根据自己所在地区的市场情况调整,模型结构不用动。

3.2 Matlab代码结构怎么组织才算顺手

写这个代码初期我走过弯路,把所有功能堆在几个大脚本里,结果改一个参数要翻半天,出了问题也不知道是建模错误还是求解器设置不对。后来重构之后,我按功能拆成了三个模块:数据模块、模型模块、求解模块。数据模块负责读取系统参数和规划参数,模型模块负责构建上层和下层的目标函数及约束,求解模块负责粒子群搜索和调用内层求解器。

数据模块用结构体把参数组织起来,比如sysData存线路和负荷数据,planData存光伏储能成本及约束参数,priceData存分时电价。这样在模型模块里引用参数就不用全局变量,函数传参传入结构体就可以,代码清晰很多。模型模块我拆成了两个函数,buildUpperModel.m负责生成上层优化所需的适应度函数,buildLowerModel.m负责构建内层YALMIP模型并求解。

上下层迭代的主循环放在主程序main_double_layer.m里,流程是初始化粒子群参数、生成初始粒子群、循环计算每个粒子的适应度(调用下层求解器)、更新粒子速度和位置、判断收敛条件、输出最优解。整个流程行数不长,但逻辑一定要理清楚,特别是粒子群的边界处理,光伏容量和储能容量如果超出边界,要拉回到边界内并重新计算适应度,不然搜出来的结果可能是不可行的。

3.3 上层粒子群的参数设置与实现细节

粒子群算法在这个问题里的表现很大程度上取决于参数设置。我第一次跑的时候直接用了个默认参数组合,种群规模30,迭代次数100,惯性权重0.8,学习因子都是2.0,结果收敛很慢,而且多次运行结果差异大,稳定性不好。

调参之后我固定下来一套效果不错的参数。种群规模50,迭代次数150,惯性权重从0.9线性递减到0.4,这个策略的好处是前期探索能力强,后期限于局部搜索,不容易错过最优区域。学习因子c1和c2都取2.0,但速度上限设为变量范围的一半,防止粒子飞出去太远导致适应度计算畸形。

粒子编码方式我选择的是混合编码。前段是光伏安装节点编号,后段是光伏容量值,再后段是储能安装节点编号,最后是储能功率和容量。节点编号用整数编码,容量用实数编码。速度更新的时候,整数部分用取整的方式处理,实数部分用标准PSO公式。这种处理方式在实现时稍显麻烦,但比把所有变量都变成实数的效果要好,因为节点编号就是离散的整数,硬用连续变量去逼近反而会引入无意义的中间值。

有个容易踩的坑是粒子群初始化。节点编号不能随机生成重复值,不然一个节点被选了两次,实际上就是少了一个可用节点。我初始化时用randperm从可选节点集合里无放回抽取,容量变量则用均匀分布随机生成。另外,初始种群生成后建议做一次可行性检查,把不满足投资预算约束的粒子直接重新生成,比在迭代过程中靠惩罚函数去拉回要好得多。

3.4 内层YALMIP模型的构建与求解器配置

下层模型用YALMIP建模,求解器我推荐用gurobi,对混合整数二阶锥规划的支持非常好,求解速度快。如果没有gurobi的license,用cplexmosek效果也不错。如果这些商业求解器都没有,退而求其次用开源的cbcipopt也能算,但在混合整数变量的处理上速度会慢很多。我不建议在YALMIP默认求解器状态下直接跑,很多时候求解器选不对,模型规模稍大就卡死。

YALMIP建模的下层模型核心代码逻辑大概是这样:定义优化变量,包括各节点电压幅值、支路功率、光伏出力、储能充放电功率、SOC状态,以及充放电状态的二进制变量。然后按刚才说的约束逐条添加,用optimize命令求解。这里我强烈建议把求解器细节打开,optimize的第三个参数设成solvesdp设置,或者直接用options = sdpsettings('solver','gurobi','verbose',0)把冗余输出关掉。我在调试阶段会把verbose打开看求解状态,但批量跑粒子群时一定关掉,不然终端刷屏刷到你怀疑人生。

内层模型还有一个细节是时段间耦合。储能SOC是跨时段的变量,不能把24个时段拆开单独求解,必须整体建模。这意味着内层模型的变量数量是24倍的单时段变量规模,对求解器来说压力还是有的。我在33节点算例上,单次内层求解时间大约在0.5到1.5秒之间,粒子群50个粒子150次迭代,理论上总计算量不小。实际跑的时候可以并行化处理,用parfor把每个粒子的适应度计算分散到多核上,整体耗时可以从两个多小时压缩到半小时以内,这个优化非常值得做。

内层模型构建时的潮流约束我建议用二阶锥松弛处理。DistFlow方程本身有凸性,配电网辐射状的特性让二阶锥松弛在很多标准算例下是紧的,也就是说松弛后的解和原问题解误差很小。用二阶锥的好处是模型是凸的,求解器可以在多项式时间内求解,稳定性大大提高。做结果验证时,可以检查松弛间隙来判断松弛是否紧,如果间隙大,需要增加约束来收紧模型。

4. 结果分析怎么看:方案评价的关键指标与典型结果

4.1 选址定容结果与经济性判断

跑完程序后,最关心的自然是结果。我在33节点算例里得到的一个典型方案是:光伏安装在第18节点(线路末端附近)和第25节点,容量分别为500kW和300kW;储能安装在第18节点和第30节点,功率容量分别是200kW/400kWh和300kW/600kWh。这个规律其实符合配电网规划的基本逻辑——电压偏低的末端节点,恰恰是光伏和储能最能发挥作用的位置,因为就地支撑能直接改善电压分布。

判定经济性要看几个关键指标。第一是年化总投资成本,假设光伏总投资280万元,储能总投资216万元,寿命期内折算到每年的成本大约是34万元和33万元左右。第二是年运行费用的变化,如果没有光伏储能,系统年购电费用大约在520万元,网损折算约30万元;加了分布式光伏储能之后,购电费用降到450万元,网损降到20万元左右,加上储能的峰谷套利收益大约10万元。综合起来,年净收益大约70万元左右,投资回收期能控制到6到7年。

但要注意,不同光伏和储能容量配比下,经济性差异很大。我做过一组对比实验,储能容量从200kWh增加到800kWh时,投资成本快速上升,而运行收益的边际增加在600kWh之后就明显变缓。这说明储能的最佳容量范围有个"甜点区",容量超出某个阈值后边际效益下降,不单纯是越大越好。这也是为什么选址定容问题不能简化成经验估计,必须做优化搜索的原因。

4.2 电压分布与网损改善效果验证

方案效果验证最直观的方法是画出24小时的节点电压分布图。我在对比实验里的数据很典型:未接入光伏储能前,18号节点晚高峰时段电压低到0.938pu,已经低于0.95pu的下限;午间时段因为光伏出力反送,25号节点电压又能抬到1.06pu左右,属于"一头低一头高"的双重越限状态。

接入优化方案后,情况明显改善了。午间光伏出力就地消纳,剩余部分充入储能,25号节点电压稳定在1.03pu以内;晚高峰时段储能放电,18号节点电压回升到0.96pu以上。全天各节点电压都保持在0.95到1.05pu的安全范围内,电压合格率从优化前的78%提升到接近100%。网损方面,系统日网损电量从原来的1320kWh降到约880kWh,降幅超过30%,损耗改善效果非常明显。

这些数据也可以用表格固化下来,作为论文里的结果支撑。一般我会整理一个对比表,分别列出无分布式电源、光伏单独接入、光伏储能接入三种情况下的电压极值、网损率、购电费用、DG渗透率等指标,这样评审老师看起来一目了然,自己核对结果时也方便。

5. 常见问题与排查技巧实录

5.1 内层求解器报"不可行"怎么查

这是我在调试阶段最常遇到的情况。内层模型报infeasible problem,说明给定方案下运行约束无法满足。最常见的触发原因是电压约束设得太紧,特别是线路末端节点,在某些恶劣的运行方式下电压已经不可能回到安全区间。排查方法是先把电压约束放松到0.90到1.10pu范围跑一遍,如果这样能求解成功,基本可以确定问题出在约束范围上。

第二个常见原因是储能SOC约束矛盾。比如SOC范围设置成了10%到90%,但调度周期结束又要求SOC回到初始值,如果初始值设置得太高或充放电效率太低,储能在一天内放不完也充不满,就可能出现无解。这时把SOC初值设成50%,或调整结束SOC的允许偏差范围,通常问题就解决了。

第三个原因是求解器数值问题。DistFlow方程里如果电阻值太小或导纳值太大,数值矩阵会出现病态,也会导致求解器误判不可行。排查办法是检查数据文件里有没有异常值,线路阻抗如果是标幺值系统,看看基准值是不是设置对了。我在处理一个69节点算例数据时发现,有一条支路的电阻被人为填成了0.00001欧姆,显然不对,修正后模型就正常了。

5.2 粒子群收敛太慢或者陷入局部最优

粒子群在这个问题里最典型的症状是:迭代到四五十代后适应度就不再下降,但你知道这个结果并不是全局最优,因为稍微改变几个安装节点,成本就能降不少。这种问题通常是粒子多样性不足造成的。解决思路有两个方向。

第一是调大惯性权重的初始值,让粒子在前期有更强的探索能力,减少过早收敛到局部最优的概率。我原来用的是0.8到0.4线性递减,改成0.95到0.35线性递减之后,虽然收敛速度慢了十几代,但最终结果明显更优。第二是引入变异操作。每次迭代结束后,随机选一小部分粒子对节点编号做重新随机化,相当于强制注入新信息,防止整个种群陷入同一个局部区域。

还有一种情况是适应度函数计算有误导致伪最优。我遇到过一次,适应度计算时把储能投资成本的单位弄错了,导致算法永远在往储能容量偏小的方向搜索。排查这类问题的方法很直接:取一个已知可行方案,手算一遍适应度值和程序算出来的对比,如果对不上就逐步排查目标函数里每一项的单位和符号。

5.3 运行时间太长怎么办

粒子群嵌套潮流计算天然耗时,我在早期的串行版本算过,50个粒子150次迭代跑了近三个小时,调试体验非常差。优化方向有三个层次。

第一层是选择更快的潮流求解方式。如果只是需要计算电压分布和网损,可以不用YALMIP搭完整的优化模型,直接用Matpower或者手写牛顿拉夫逊法算潮流,这样单次计算耗时能降到几十毫秒。但这种方式没法显式模拟储能的最优调度策略,储能充放电曲线只能按固定规则比如"谷充峰放"来给定,精度会打折扣。

第二层是并行化。用parfor替换for循环,让每个粒子的适应度计算分配到不同的工作线程上。我实测下来,六核机器能提速四倍多。需要注意的是,parfor循环内不要共享数据,每个粒子的适应度计算必须完全独立,结果保存用单元格数组或者按索引写入。

第三层是减少不必要的计算。粒子群每次更新位置后,只有部分粒子发生了变化,但早期版本我每次都对所有粒子重新计算适应度,浪费了大量算力。优化后可以只重算变化过的粒子,对未变化的粒子沿用历史适应度值。这个方法在问题规模大的时候效果尤其显著。

5.4 YALMIP求解器设置和数值稳定性细节

最后提几个YALMIP使用上的小坑。一个是全局默认精度设置,sdpsettings('gurobi', struct('MIPGap', 1e-4)),求解器类型中的MIPGap参数要设置好。如果不设,求解器可能默认追求精确解,收敛很慢;设成1e-3甚至5e-3对分布式能源规划问题来说精度足够,速度能快不少。

另一个是模型导出和调试技巧。如果内层模型经常报错,可以用save函数把YALMIP模型保存成文件,再用export命令导出成LP或MPS格式,放到求解器官方工具里进一步分析。这个办法排查约束错误非常管用,能直接看到求解器视角下的模型长什么样,比自己对着代码猜快得多。

数值稳定性方面,建议统一用标幺值而不是有名值。有名值下线路阻抗、电压、功率的数量级差太多,求解器在迭代过程中容易出现数值问题。用标幺值后所有变量量纲统一,求解稳定,而且后面换成更大的系统也方便比较。这是我吃过亏之后才养成的习惯,现在建模都会先做归算。


最后再分享一个小经验。做这个课题最忌讳一上来就把模型加得很复杂,什么三相不平衡、各种时序场景全塞进去,最后根本跑不动。我的建议是先跑通一个最简单的版本——单典型日、光伏储能同点位、粒子群50代——哪怕是结果差强人意,至少整条链路是通的。确认无误了再逐步增加细节:从单日扩展为四季典型日,从同点位扩展到独立选址,从固定电价升级成分时电价,每一步都验证一次结果的合理性。这种迭代方式看着慢,实际上是最快的路子。做完了之后回头看,整个框架很干净,加约束、换数据、迁移到别的系统都不费劲。

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

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

立即咨询