配电网做分布式电源规划的朋友,应该都对“选址定容”这四个字有切身体会。同样一笔光伏和储能投资,装在哪、装多大、储能怎么充放,最终的经济性和系统运行效果完全可能天差地别。装得不好,网损不降反升,末端电压被光伏出力顶到越限,储能也可能变成一年充不上几次电的摆设。这个项目解决的就是这件事:用粒子群优化算法做上层选址定容,用运行优化做下层储能调度,两层迭代求解光伏和储能的最优配置方案,整个算例在IEEE33节点配电系统上跑通,输出Matlab代码实现。
不管你是写毕业论文需要算例支撑,还是做课题申报需要一个完整的优化框架,或者刚入行想搞明白“分布式电源规划到底怎么做”,这套基于粒子群的双层优化模型都值得完整拆一遍。它能回答三个关键问题:光伏该接在哪几个节点、容量分别取多大、储能应该配置多少功率和容量才能让整个系统的年综合费用最低。接下来我按模型设计、算法原理、代码实现、结果分析和避坑经验这几个部分完整讲透。
1. 问题拆解:为什么配电网光伏储能配置这么难做
1.1 配电网的基本盘与分布式电源带来的麻烦
配电网和输电网的差别,做过潮流计算的人都知道。典型的配电网是放射状结构,R/X比值大,线路电阻不能忽略,功率流向基本是从变电站单向流向末端负荷。在传统场景下,潮流计算用前推回代法就能很好收敛,电压分布也相对稳定。
但光伏大规模接入后,情况彻底变了。系统从单电源变成了多个电源点,光照充足时配电网内部可能局部出现功率倒送,末端电压被抬高,甚至可能越过上限。再加上光伏出力本身是间歇性的,上午和中午、晴天和阴天出力曲线完全不同,如果配置时不考虑运行层面的调度,做出来的方案在实践中根本没法用。
储能的价值恰恰在于它能平抑这种波动。光伏出力大的时候充电,负荷高峰期放电,既能抬高电压低谷,又能压低电压高峰,还能通过削峰填谷降低系统网损和购电成本。但储能单价高,容量配大了投资回收周期长,配小了又起不到调节作用。所以光伏和储能的容量、位置必须协同优化,而不是各算各的。
1.2 选址定容本质上是“规划+运行”的双层决策
这个问题的难点在于:选址定容属于规划层决策,一年甚至几年才做一次,决策变量是位置和容量,属于整数混合优化问题;而储能充放电策略属于运行层决策,一天24个小时段都在动态调整,决策变量是每个时段的充放电功率,属于连续优化问题。两者的时间尺度和决策维度完全不一样。
如果硬要把两层决策变量塞到一层优化里去求解,会出现三个麻烦。第一,问题规模急剧膨胀,一个含多个光伏和储能候选节点的方案,决策变量动辄几十上百维,搜索空间大得惊人。第二,目标函数高度非凸,光伏出力和负荷的时序耦合让目标曲面很平坦、陷阱很多,普通优化算法很容易陷入局部最优。第三,约束条件来自不同时间尺度,规划层管容量上限、投资预算,运行层管SOC上下限、充放电功率,混在一起解耦困难。
所以工程上最自然的做法就是双层建模:上层做规划决策,下层在上层给定方案的前提下做运行调度优化,再把运行结果反馈给上层算综合目标。上下层通过配置方案和最优运行成本这两个接口迭代,直至找到全局最优的配置解。
1.3 为什么选IEEE33节点系统做测试平台
IEEE33节点配电系统是配电网研究里最经典的测试算例之一,公开数据、拓扑清晰、结构简单又不失代表性。这个系统是一个33节点、32条支路的放射状网络,额定电压12.66kV,总有功负荷3715kW,总无功负荷2300kVar。它有一个很典型的特点:末端负荷较重,线路较长,潮流分布不太均匀,电压偏低的问题比较突出。
这个特点对光伏储能选址定容研究非常有利。因为系统本身存在明显的电压薄弱环节,配置光伏储能后带来的改善效果能直观体现出来。而且33节点的规模不大不小,跑潮流非常快,做双层循环迭代也能在可接受的时间内出结果。相比之下,用IEEE69节点或者135节点系统,虽然更接近实际配电网,但计算量会成倍上升,调试期会非常痛苦。
2. 双层优化模型:先把目标和约束定清楚
2.1 上层模型:年综合费用最小化
上层模型的决策变量是光伏的安装位置和容量、储能的安装位置、额定功率和额定容量。目标函数取年综合费用最小,包含三个部分:等年值投资成本、运行维护成本和年网损费用。
等年值投资成本是把一次性投资折算到每年,用资金回收系数处理。公式是:
C_inv = CRF * (C_pv * P_pv + C_ess_p * P_ess + C_ess_e * E_ess) CRF = r * (1 + r)^n / ((1 + r)^n - 1)其中C_pv是光伏单位容量投资成本,P_pv是光伏安装容量;C_ess_p是储能单位功率成本,P_ess是储能额定功率;C_ess_e是储能单位容量成本,E_ess是储能额定容量;r是折现率,n是项目寿命期。运行维护成本通常按投资成本的一定比例估算,比如每年取2%到3%。年网损费用则需要把全年8760小时的网损电量加起来乘以电价,实际工程中常用典型日负荷曲线和光伏出力曲线来等效计算。
上层约束包括光伏安装容量上限、储能功率和容量上限、光伏和储能安装节点数量限制、节点电压上下限和支路潮流极限。投资预算约束如果有,也要加进去。
2.2 下层模型:运行成本最小化的储能调度
下层模型在上层给定的配置方案下求解最优运行策略。决策变量是储能每个时段的充放电功率。目标函数取运行成本最小,通常简化为网损费用最小或系统购电费用最小。以网损最小为目标时,储能充放电策略的目的就是让系统潮流分布更合理。
储能运行必须满足的约束包括:功率平衡约束,即各节点注入功率之和等于负荷与网损之和;储能SOC动态约束;充放电功率上下限约束;SOC上下限约束;调度周期始末SOC守恒约束。SOC动态方程是:
SOC(k+1) = SOC(k) + eta_ch * P_ch(k) * dt / E_ess - P_dis(k) * dt / (eta_dis * E_ess)eta_ch和eta_dis分别是充放电效率,一般取0.9左右。SOC范围通常限制在0.1到0.9之间,避免深度充放电损伤电池寿命。始末SOC守恒的意思是,一个调度周期结束后SOC要回到初始值,这样储能才能日复一日地循环使用。
2.3 上下层的耦合接口
上下层之间的信息传递是理解双层模型的关键。上层把选址定容方案传给下层,下层在这个方案下做运行优化,找到最优调度策略和对应的最优运行成本,然后把运行成本返回给上层。上层把这个运行成本带入年综合费用函数,再结合投资成本和运维成本,计算出该配置方案的适应度值。
这样做的好处非常明显。上层每一次评估一个粒子,都代表一次完整的“配置+最优运行”联合评估。也就是说,上层比较不同的配置方案时,看到的不是简单的静态网损,而是这个配置在最优运行策略下的极限表现。这样选出来的配置方案,在实际运行中才是有操作性的。
3. 粒子群优化算法:为什么选它,参数怎么定
3.1 PSO的核心更新逻辑与直观理解
粒子群优化算法是模拟鸟群觅食行为的元启发式算法。每个粒子代表解空间中的一个候选解,粒子在搜索空间里飞行,通过跟踪个体历史最优和全局历史最优来更新自己的速度和位置。速度和位置更新公式是:
v = w * v + c1 * rand * (pbest - x) + c2 * rand * (gbest - x); x = x + v;w是惯性权重,控制粒子对之前速度的继承程度;c1和c2是学习因子,分别控制粒子向个体最优和全局最优学习的强度;rand是[0,1]之间的随机数,给搜索引入随机性。
直观理解就是:粒子既想回到自己曾经找到过的最好位置,又想到全体粒子发现的最好位置去看看,再加上惯性让它保持原来的飞行趋势。三个力量博弈下来,粒子群整体逐渐向全局最优区域收敛。
3.2 关键参数怎么设置
参数设置直接影响收敛速度和解质量。我调试这套模型时用的参数组合是:种群规模30到50,迭代次数100到200,惯性权重从0.9线性递减到0.4,学习因子c1和c2都取2。这个组合在IEEE33节点算例上表现稳定。
种群规模太小容易早熟收敛,太大则计算量超标。IEEE33节点这个规模,30个粒子已经够用,我一般取40。惯性权重递减策略很关键,前期w大,粒子探索能力强,不容易陷在局部;后期w小,粒子局部开发能力强,能精细搜索最优解附近区域。学习因子c1和c2相等取2,是经典的默认配置,如果发现收敛太慢,可以尝试c1从2.5线性降到0.5、c2从0.5升到2.5的不对称设置,这样前期增强个体探索,后期增强群体收敛。
除了这四个参数,速度上限Vmax也要设。Vmax太大会导致粒子飞过最优区域,太小则容易早熟。我习惯把速度限制在变量范围的10%到20%之间,对配置类问题效果不错。
3.3 双层结构下PSO怎么嵌入
在双层模型里,PSO只作用在上层。每个粒子编码的是一组光伏储能选址定容方案,适应度函数是调用下层运行优化后的年综合费用。流程是这样的:
- 初始化粒子群,随机生成若干组选址定容方案。
- 对每个粒子,解码出位置和容量参数,更新IEEE33节点系统的数据。
- 调用下层运行优化,求解该配置下的最优储能调度策略和最小运行成本。
- 把运行成本带回上层,计算年综合费用作为适应度值。
- 更新每个粒子的个体最优和全局最优。
- 按PSO公式更新粒子的速度和位置。
- 检查越界并修正,返回第2步,直到达到最大迭代次数。
下层可以用任何一种优化器来求解,也可以用数学规划方法。如果追求实现简单,可以用规则调度策略近似。但要注意,规则调度不一定能找到运行层的最优解,上层评估配置方案时用的“最优运行成本”就不准确,可能影响最终选址定容结果。我个人建议,课题或者论文的核心算例尽量做完整双层优化,哪怕计算慢一点。
4. Matlab实现:主程序架构与核心代码逻辑
4.1 项目文件结构
一套完整的代码建议按模块组织。我自己搭的文件结构是这样:
main.m 主程序,入口 case33.m IEEE33节点系统数据定义 pso_optimize.m 上层粒子群优化主循环 objective_upper.m 上层目标函数,年综合费用计算 decode_particle.m 粒子解码为配置方案 lower_dispatch.m 下层储能调度优化 powerflow_backforward.m 配电网前推回代潮流计算 calc_loss.m 计算系统网损 plot_convergence.m 画收敛曲线 plot_voltage.m 画电压分布对比图这样分层的好处是调试方便,每个模块都能单独测试。我最开始写的时候把所有逻辑塞在一个脚本里,后来改一个变量都要全局排查,痛苦得不行。拆开后清爽多了。
4.2 IEEE33节点系统数据定义
case33函数里存放节点数和支路数,以及支路参数矩阵和负荷参数矩阵。IEEE33节点的标准数据里,支路参数包括起始节点、终止节点、电阻和电抗,所有值都按有名值给出。基准值取电压12.66kV、功率10MVA,潮流计算时用标幺值更方便。
写这段代码时要特别小心节点编号从1开始,Matlab数组索引也是从1开始,天然对应。但支路参数和负荷数据的行列顺序一定要核对清楚,我在这个环节因为手误抄错过一个电阻值,结果潮流一直不收敛,排查了大半天才发现是数据录入错误。
4.3 粒子编码与解码
编码方式是PSO实现的核心细节之一。常见的做法是每个粒子向量依次排列各设备的安装节点编号、安装容量。比如系统允许装2个光伏和1个储能,那么每个粒子可以编码成:
% [光伏1节点, 光伏1容量kW, 光伏2节点, 光伏2容量kW, 储能节点, 储能功率kW, 储能容量kWh] particle = [24, 300, 28, 250, 18, 200, 500];节点编号是正整数,但PSO的位置更新产生的是连续实数,所以解码时对位置取整。容量变量按连续变量处理,但为了更接近工程实际,可以把容量离散成固定档位,比如50kW一档。离散化会缩小搜索空间,提高收敛速度,代价是可能错过档位之间的最优解。IEEE33节点算例上,我建议容量按连续变量处理,反正计算量不大,解的精度更高。
解码后要修改配电网数据,把光伏当作负的PQ负荷接到对应节点,储能当作可调的PQ注入接到对应节点。这一步看起来简单,但下层调度每次调整储能功率时都要重新更新这个注入值,所以解码函数最好单独写,方便反复调用。
4.4 上层目标函数实现
上层目标函数接收一个粒子,返回该配置下的年综合费用。核心代码如下:
function f = objective_upper(x) % 解码 [pv_nodes, pv_caps, ess_node, ess_p, ess_e] = decode_particle(x); % 调用下层运行优化,得到最小运行成本 run_cost = lower_dispatch(pv_nodes, pv_caps, ess_node, ess_p, ess_e); % 计算投资成本和运维成本 inv_cost = CRF * (C_pv * sum(pv_caps) + C_ess_p * ess_p + C_ess_e * ess_e); ope_cost = k_ope * inv_cost; % 年综合费用 f = inv_cost + ope_cost + run_cost; end这个函数会被PSO主循环反复调用,每次调用都涉及一次完整的下层优化和若干次潮流计算。所以objective_upper一定要写得高效,避免做重复计算。比如光伏出力曲线和负荷曲线这些不随粒子变化的公共数据,应该在主程序里提前加载好,而不是在目标函数里重复读取。
4.5 下层储能调度优化
下层模型的目标是求解最优储能充放电策略。24小时调度周期,每个小时一个决策变量,一共24个变量。问题规模不大,可以用fmincon直接求解,也可以用线性规划近似。储能调度问题在目标函数为网损最小的时候是非线性的,因为网损是节点电压和功率的非线性函数,用fmincon处理非线性约束比较自然。
如果为了简单,也可以采用启发式规则:光伏出力大于负荷时充电,光伏出力小于负荷时放电。这个规则我在调试阶段用过,跑得飞快,能快速验证上层框架的正确性。但完整版一定要用优化方式,不然储能SOC曲线会很粗暴,结果不够严谨。
fmincon求解时要注意SOC约束的写法。SOC动态约束是等式约束,SOC上下限是不等式约束,充放电功率上下限是变量的边界约束。初始SOC我一般设0.5,终值也约束回0.5,这样储能一个周期内的净电量为零,不会出现“白嫖”电能的情况。
4.6 前推回代法潮流计算
配电网潮流计算我强烈推荐前推回代法,原理简单、收敛可靠、代码量小。核心逻辑分三步:
- 初始化所有节点电压为额定电压1.0pu。
- 回代:从末端节点向首端,根据节点功率和当前电压计算各支路电流。
- 前推:从首端向末端,根据支路电流更新各节点电压。
重复回代和前推,直到前后两次迭代的电压差最大值小于收敛精度,比如1e-6。
function [V, branch_current] = powerflow_backforward(bus_data, branch_data) V = ones(nb, 1); for iter = 1:100 V_old = V; % 回代 I = conj(S_load ./ V); % 从末端到首端叠加支路电流 ... % 前推 % 从首端到末端更新节点电压 ... if max(abs(V - V_old)) < 1e-6 break; end end end写这段代码时要注意:光伏和储能节点作为负的PQ注入,S_load里要加上负号的注入功率;平衡节点1的电压固定为1.0,不需要更新。
5. 算例结果分析:从收敛曲线到配置方案
5.1 仿真参数与运行环境
我的测试环境是Matlab R2021a,普通i5笔记本,16GB内存。粒子群参数取种群40、迭代100次、惯性权重0.9到0.4递减、学习因子2。储能效率0.9,SOC范围0.1到0.9,初始和终值SOC都设0.5。光伏最大安装容量按每个节点不超过500kW设置,储能最大功率200kW、最大容量500kWh。折现率0.08,项目寿命期20年。
完整跑一次双层优化,包含100代、每代40个粒子,每个粒子要做24时段储能调度优化和对应的潮流计算,总耗时大约20到30分钟。这个时长在可接受范围内,如果你用规则调度简化下层,跑一轮只要几分钟。
5.2 优化结果展示
某次运行得到的一组典型配置方案是:光伏接入节点24,容量300kW;光伏接入节点28,容量250kW;储能接入节点18,额定功率200kW,额定容量500kWh。这个配置的逻辑很清晰:节点24和28都处在系统末端负荷较重的位置,光伏就地接入能有效支撑末端电压;储能放在节点18这个中间偏末端的位置,既能配合光伏充电,又能在负荷高峰给后半段线路提供无功电压支撑。
需要说明的是,每次运行结果可能略有不同,因为PSO带随机性。同一个参数配置多跑几次,取最优的那次作为最终结果。
5.3 配置前后效果对比
对比三个场景:原始系统不接任何分布式电源、只接光伏但储能固定策略运行、光伏储能双层优化配置。主要指标取年网损电量、系统最低电压和储能年充放电循环次数。
| 指标 | 无分布式电源 | 光伏+储能双层优化 |
|---|---|---|
| 年网损电量(MWh) | 基数水平 | 下降约20%到30% |
| 全天最低节点电压(pu) | 0.92左右 | 提升到0.95以上 |
| 光伏就地消纳率 | 无光伏 | 明显提升 |
数字具体值取决于负荷曲线和光伏出力典型日的选取,不同场景设定会有差异,但趋势是明确的:双层优化后网损下降、电压水平抬升、光伏消纳改善。这些指标也验证了“选址定容+运行调度协同优化”的必要性。
5.4 收敛曲线怎么读
PSO的收敛曲线观察两个指标:全局最优适应度值和种群平均适应度值。全局最优曲线下降得越快,说明算法找到好解的速度越快;平均适应度值和最优值之间的差距反映了种群多样性。
从曲线形态看,前期0到20代曲线下降非常快,粒子从随机初始状态迅速向优良区域靠拢。20代之后下降趋缓,50代以后基本平稳,100代时全局最优值已无明显变化。这说明100代迭代次数对IEEE33这个算例来说是够用的。如果曲线在后期仍然明显下降,说明迭代次数不够,需要加大到150甚至200代。
6. 常见问题与调试技巧实录
6.1 潮流不收敛,先查原始数据
前推回代法在IEEE33节点系统上一般比牛拉法还稳,如果潮流不收敛,大概率是原始数据出问题。最常见的坑是支路电阻和电抗的单位没统一。IEEE33标准数据里电阻单位是欧姆,但有些版本会混入标幺值,一旦混用,潮流结果必然离谱。其次是节点编号和支路起止节点方向没对上,回代前推的顺序错了。遇到不收敛,先把无分布式电源的原始系统跑一遍,如果原始系统都不收敛,问题一定在数据本身,不用怀疑算法。
6.2 粒子越界和非法组合处理
粒子更新过程中,速度和位置很容易越过边界。安装节点越界要拉回到边界内并取整;容量越界要截断到最大最小值。更隐蔽的问题是光伏位置和容量组合不合法,比如同一个粒子内两个光伏节点编号相同,或者储能节点跟光伏节点重叠。处理办法是检查粒子合法性,不合法就重新初始化或者用罚函数惩罚。
我建议综合使用两种方法:越界截断加罚函数。越界截断保证粒子始终在可行域内,罚函数处理容量配置不合理的粒子,双重保险。纯罚函数方法调参麻烦,纯截断方法又会损失搜索效率。
6.3 双层优化计算太慢,怎么加速
双层嵌套优化最让人头疼的就是运行时间。实测下来,完整双层在一次实验里要跑20到30分钟,如果要做参数敏感性分析,这个时间完全不可接受。我的加速经验有三条。
第一,粒子数不需要太多,30个足够,如果问题规模不大甚至20个也可以。第二,下层储能调度不一定每次都用fmincon跑满精度,可以在前期迭代用粗一点的容差,后期再用高精度细化。第三,把不随粒子变化的数据提前算好缓存起来,比如典型日负荷曲线、光伏归一化出力曲线,在目标函数里直接查表,而不是每次重新计算。
如果时间实在紧张,还有一个折中方案:上层PSO跑完第一轮后,把最优解附近重新初始化一批粒子做二次精细搜索。这种“粗搜+精搜”的两阶段策略在很多文献里被证明效率很高。
6.4 储能SOC终值回不到设定值
在高峰期放电多、充电少的情况下,SOC从0.5出发可能一路下跌到下限,根本无法满足终值回0.5的约束。这个问题我在调模型时反复遇到。解决办法是在SOC终值约束里加一个松弛项,允许终值在一个小范围内波动,比如0.5加减0.05。或者把SOC终值约束从等式改成不等式,只要终值大于初始值0.5即可,这样储能就不会在调度末段故意放电来满足等式约束,让调度策略更自然。
6.5 结果忽好忽坏,随机性怎么处理
PSO是随机优化算法,每次运行结果都不可能完全一样。如果两次运行结果差别很大,说明算法没有稳定收敛,常见原因是迭代次数不够或种群多样性过早丧失。我一般每个参数组合跑5次独立实验,取最好的结果,同时观察5次结果的标准差。如果标准差太大,增加迭代次数或者调大惯性权重的初始值,让前期搜索更充分。
最后说一个我踩过的关键坑:千万注意功率和能量的单位换算。光伏容量常用kW,储能容量常用kWh,SOC方程里充放电功率乘以时间后才是能量,如果单位没统一,SOC曲线会直接起飞或者瞬间跌到负值。我当时用kW乘以24小时当成kWh用,结果SOC一晚上超出了上限三倍,排查了很久才发现是少了除以储能容量这一步。做双层优化这类嵌套模型,单位一致性检查应该放在最前面,而不是最后。
这套完整的“粒子群+双层优化”框架,除了做IEEE33节点的光伏储能配置,换一下数据文件就可以推广到IEEE69节点、135节点或者其他实际馈线系统,改节点数和支路参数就能跑。想让它更贴近工程实际,还可以在模型里加入光伏出力的不确定性场景、考虑分时电价下的储能套利、加入需求响应负荷等。这个项目真正有价值的不是那几行PSO代码,而是把规划决策和运行调度打通来思考配电网问题的思路,这套思路在以后的方案设计中会反复用到。