配电网规划这个方向这两年绕不开的一个话题就是“分布式电源和充电站到底怎么一起配”。很多项目方案书里写着“协调发展”实际做模型时却还是DG归DG、充电站归充电站各算各的最后网损、电压、投资三本账合不到一起。我前后做了两个配电网规划课题把“考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法”在Matlab里完整实现并跑通了IEEE 33节点算例从数学建模、粒子群求解到结果后处理都踩过不少坑。今天把整套逻辑和代码思路摊开聊希望对正在做研究生课题、课程设计或者规划可研的人有点参考价值。1. 项目起源这个联合配置问题到底在算什么1.1 一句话说清题目这个题目可以拆成三个关键词分布式电源、电动汽车充电站、充电负荷空间可调度特性。分布式电源一般指光伏、风电、燃气轮机这类直接接在配电网上的中小容量电源它的接入位置和容量会改变节点注入功率直接影响电压分布和网损。电动汽车充电站则是纯粹的大功率负荷一个快充站几十根桩同时充电局部负荷密度可能比一个小型工业园还高。这两类设备如果分开规划容易出现DG选址在末端、充电站也堆在末端的情况结果末端电压要么被顶高、要么被拉低网损越算越难看。所谓联合配置就是把分布式电源和充电站放进同一个优化模型同时决策它们的位置和容量让二者在电气和经济学上互相配合。这个模型里的目标函数通常是年总费用最小约束条件包括潮流约束、电压约束、DG渗透率约束、充电站服务能力约束等。把两类设备“绑”在一起解才能避免规划方案内部互相打架。1.2 “空间可调度”四个字的分量传统规划模型里各节点的充电负荷是一堆固定的PQ负荷算完潮流就完事。但现实中电动汽车用户不会老老实实只在家门口充电。用户可以在一定空间范围内选择充电站规划者也可以通过充电价格、充电桩指引等手段把一部分充电需求引导到不同位置的站点。这种“充电需求不完全绑定在某个固定节点可在空间上重新分配”的特性就是充电负荷空间可调度特性。把它放进模型之后充电负荷不再是一成不变的输入而是一部分决策变量每个需求点的充电量可以按用户意愿和服务半径分配到周围的候选充电站。这样一来充电站的选址定容就和真实用户行为挂上了钩规划出来站点位置更接近实际需求分布。更重要的是这个柔性让模型有了一部分“需求侧响应”的味道能在不增加任何硬件投资的情况下通过调整负荷空间分布来改善电压和降低网损。1.3 面向人群与典型使用场景这套方法最适合三类人一是电气工程研究生做配电网规划、电动汽车接入方向课题时需要一套能讲清楚原理又能出结果的模型二是做电网规划或充电基础设施规划的工程师尤其是做可研阶段的方案比选需要量化评估“要不要引导用户去别处充电”三是做Matlab课程设计或竞赛的学生需要一个结构完整、能跑出图的优化模型。2. 模型搭建把“空间可调度”写进数学公式2.1 目标函数钱的问题要统一量纲联合配置的优化目标我建议直接用年总费用最小这是工程上最好解释、也最容易和投资方沟通的指标。目标函数可以写成min F C_DG_inv C_DG_om C_CS_inv C_CS_om C_loss C_purchase各项含义分别是分布式电源的年化投资费用、年运维费用、充电站年化投资费用、年运维费用、配电网年网损费用、向上级电网购电费用。这里有一个关键细节设备和工程投资是一次性投入而运行费用是逐年发生的不能直接相加。处理方法是把一次性投资按贴现率和运行年限折算成年值也就是等年值法。对于一个设备全寿命周期为Y年、贴现率为r的项目年化系数为 r(1r)^Y / ((1r)^Y - 1)然后用这个系数去乘初始投资。算例里我通常取Y20年贴现率取6%这样DG、充电桩、变压器等设备都能统一到“每年花多少钱”的口径上加出来才有实际意义不然就是拿苹果加香蕉。需要提醒的是如果模型里同时有网损费用和购电费用要小心重复计算。网损费用是从潮流结果算出的网络损耗电量乘以电价而购电费用是上级电网注入的功率乘以电价。在不通DG场景下购电费其实包含了网损费的一部分我一般只保留网损费用和DG相关的费用购电成本可以在报告中单独说明避免模型里出现同一笔钱算两次。2.2 充电负荷空间可调度特性的建模方式可调度特性在数学上有多种建模方式我用的是一套“需求点-候选站”分配模型操作起来最直观。假设规划区域内有M个充电需求点每个需求点i对应当地电动汽车的数量产生一个充电负荷需求D_i。你有一组候选充电站节点集合为S不是每个候选站都会建。可调度部分的比例用α表示意思是总需求中α比例可以由规划者根据距离和用户选择规律自由分配剩余1-α属于“死负荷”只能就近充电。引入分配变量x_ij表示需求点i的充电负荷分配到候选站j的比例。那么实际落到候选站j上的总充电负荷就是L_j sum_i (x_ij × D_i)约束条件主要有三个每个需求点的负荷分配比例之和等于1即sum_j x_ij 1只有处于服务半径R以内的需求点和站点之间才允许x_ij非零如果某个候选站没有建设即y_j 0则该站点接到的所有分配必须为零也就是x_ij ≤ y_j。除了硬性半径约束我还会加一个距离衰减因子。用户选择充电站不是完全均匀分配的距离越远的站吸引力越小。我常用指数衰减形式w_ij exp(-d_ij / d0)d0是经验距离参数比如500米。然后在满足约束的前提下让粒子群自动向“总费用更小”的分配方式搜索而不是人为规定每个点去哪个站。这样既保留可调度特性的柔性又不至于做出脱离实际的均匀分配。2.3 分布式电源与配电网约束配电网潮流约束是整个模型的底层所有配置方案都必须满足物理定律。配电网通常是辐射状结构我采用Distflow支路潮流方程。对每条支路从根节点向末端递推节点j的电压满足U_j² U_i² - 2(R_ij P_ij X_ij Q_ij) (R_ij² X_ij²) × I_ij²其中i是j的父节点P_ij和Q_ij是流过支路ij的有功和无功功率R_ij、X_ij是支路阻抗。这个方程可以精确反映DG和充电负荷对节点电压的影响DG出力大会抬高末端电压充电负荷大会压低末端电压联合配置的关键就是让这两股力量在空间上错开平衡。其他约束包括节点电压幅值限制在0.95~1.05 pu之间支路电流不超过额定值DG单点安装容量不超过上限DG总渗透率不超过系统峰值负荷的30%左右具体按当地电网管理规定充电站总充电桩数要满足整个区域内充电需求的覆盖率要求两个已建充电站之间的距离不能太近避免重复建设。这里要特别强调耦合约束。DG和充电站的联合效应不是简单相加而是要通过潮流方程共同影响电压和网损。比如DG末端出力导致电压越上限时可以在附近配置充电站把多余的有功就地消耗掉这就是联合配置相比分开配置最核心的优势。这个耦合关系是我在做模型时反复向课题组同学解释的东西。2.4 决策变量与优化难度分析这个模型的决策变量一共三类分布式电源的接入位置整数和接入容量连续充电站的建设位置0-1变量和充电桩数量整数充电负荷分配比例x_ij连续变量取值0到1三类变量混在一起目标函数高度非线性潮流方程本身也是非线性方程组。这是一个典型的混合整数非线性规划MINLP问题。理论上可以用商业求解器Yalmip加Cplex或Gurobi处理但配电网算例稍大一点、场景数加多之后求解器内存和时间消耗非常可观而且模型如果写了数字扰动的函数求解器还容易报数值警告。所以我在这套代码里选用粒子群优化算法PSO做求解框架。PSO对非线性约束问题的处理很灵活离散整数变量可以通过取整映射处理连续变量直接迭代可调度分配变量也能在边界范围内自由搜索。虽然在数学上没有最优性证明但工程上用来做方案比较和敏感性分析完全够用。加上Matlab代码实现简单迭代过程可视化强非常适合这类规划课题。3. Matlab实现编码、潮流、罚函数一整套代码思路3.1 程序结构与运行流程整套代码我按功能拆成了几个文件跑起来逻辑非常清楚main.m——主程序初始化参数、循环迭代、调用各个函数case33.m——IEEE 33节点系统的节点、支路、负荷数据定义init_pso.m——粒子群参数和粒子种群初始化loadflow.m——基于Distflow的前推回代潮流计算evaluate.m——适应度评估包括目标函数计算和罚函数施加plot_results.m——收敛曲线、单线图、电压分布图绘制主循环的伪逻辑是每一代先解码粒子得到DG位置容量、充电站位置容量、负荷分配方案调用潮流计算得到各节点电压和网损然后算适应度更新个体最优和全局最优更新粒子速度和位置循环至最大迭代次数最后输出最优配置方案。整个流程看起来简单但编码设计是决定求解效率和结果质量的关键下面重点讲。3.2 粒子编码与边界处理粒子编码直接影响搜索空间的利用效率。我采用分段编码的方式一个粒子同时包含所有决策变量。假设系统有N个DG候选节点、M个充电站候选节点、K个需求点编码形式如下[dg_idx(1:N)] [dg_cap(1:N)] [cs_idx(1:M)] [cs_pile(1:M)] [alloc(1:K)]其中dg_idx用连续值表示取值后在候选节点集合中取最近整数得到DG安装位置dg_cap是对应容量cs_idx表示候选站是否建设取整后大于0.5表示建站否则不建cs_pile是建桩数alloc是每个需求点向各候选站的分配向量需要归一化保证sum_j x_ij 1。这样编码有一个显而易见的好处粒子群的连续搜索机制不需要做大的改动离散变量在评估时才取整省去了反熵离散化的麻烦。代价是取整操作会让搜索空间出现一些“重复粒子”不过对PSO来说影响很小换来的是代码简洁。边界处理上容量和分配比例这类连续变量我采用反射边界即超出上界就折回超出下界同理避免粒子飞出可行空间。位置类整数变量取整后如果超出候选表范围就直接映射到最近的合法节点。这里的经验是不要让位置变量在边界处吸附太久否则粒子会聚集在边界附近局部搜索能力下降。3.3 潮流计算选用与实现细节33节点这类辐射状配电网用前推回代法做潮流计算是最快的也最不容易出错。前推回代的思路是先假设各节点电压为额定值从末端向根节点逐段计算支路功率得到全网功率分布再从根节点向末端逐段计算电压降落更新各节点电压反复迭代直到前后两次电压差值小于收敛精度。Distflow潮流的核心递推关系可以写为节点j的注入功率 S_j S_load_j - S_DG_j - 已分配充电负荷S_CS_j支路ij上的功率可以表示为P_ij sum(节点j及其下游节点所有注入有功之和)无功同理。电压更新时直接用前面提到的电压递推公式但为了加速收敛我做了一个小的简化把I_ij²项先用上一轮的功率估计值算出来而不是每轮重新联立求解。下面是loadflow.m里面核心部分的简化代码function [V, Ploss] loadflow(bus, branch, P_DG, Q_DG, P_charge) % 输入: bus为节点负荷矩阵, branch为支路矩阵 % P_DG/Q_DG为DG注入功率, P_charge为充电负荷 V ones(size(bus,1),1); % 初始电压标幺值 iter 0; while iter 50 % 回代: 从末端往根节点求支路功率 P_branch zeros(size(branch,1),1); Q_branch zeros(size(branch,1),1); for k size(branch,1):-1:1 i branch(k,1); j branch(k,2); P_flow P_DG(j) - bus(j,3) - P_charge(j) sum(P_branch(branch(:,2)j)); Q_flow Q_DG(j) - bus(j,4) sum(Q_branch(branch(:,2)j)); P_branch(k) P_flow; Q_branch(k) Q_flow; end % 前推: 从根节点往末端求电压 V_new V; for k 1:size(branch,1) i branch(k,1); j branch(k,2); R branch(k,3); X branch(k,4); V_new(j) sqrt(V(i)^2 - 2*(R*P_branch(k) X*Q_branch(k)) ... (R^2X^2)*(P_branch(k)^2Q_branch(k)^2)/V(i)^2); end if max(abs(V_new - V)) 1e-6 V V_new; break; end V V_new; iter iter 1; end Ploss sum(branch(:,3) .* (P_branch.^2 Q_branch.^2) ./ V(branch(:,1)).^2); end这段代码没有做太多优化但结构很清楚适合作为框架修改。在实际算例中33节点系统通常只需要5到8轮就能收敛。如果你的系统包含环网或需要通过变压器连接就要用Matpower或者Newton-Raphson方法不能硬套前推回代。3.4 罚函数与可行性处理PSO本身不处理约束所以我把所有约束统一放到适应度函数里用罚函数处理。罚函数的基本思路是一旦某个粒子对应的方案越限就在目标函数上加一个很大的惩罚项让这个粒子的适应度变差从而在进化过程中被逐步淘汰。惩罚项我分三类电压越限惩罚、支路功率越限惩罚、充电站覆盖不足惩罚。总适应度可以写成F_obj F_cost λ_V × sum(max(0, V_min - V, V - V_max)²) λ_S × sum(max(0, I/I_max - 1)²) λ_cov × (D_unserved / D_total)其中λ_V、λ_S、λ_cov是罚系数。我的经验是罚系数至少要达到目标费用典型值的10到100倍比如目标费用量级在几百万时罚系数可以设到千万级别。太小了越限方案可能被选进来太大了又会导致粒子过早聚集到可行域边缘搜索多样性下降。还有一个小技巧把罚函数里的平方项单位对齐。如果电压是标幺值量级在0.01左右平方之后就非常小必须放大系数才能起作用。我在代码里用了一个归一化处理把电压偏差除以基准偏差1e-3然后平方这样罚函数数值和费用项在同一量级调试起来直观很多。4. 算例验证33节点系统下跑出来的真实结果4.1 算例参数与实际接线我用经典的IEEE 33节点配电系统做验证。该系统基准电压12.66 kV基准功率取10 MVA总负荷约3715 kW加2300 kvar是一个标准的辐射状配电系统末端节点长、电压问题明显非常适合测试充电站和DG接入后的影响。DG候选节点选择末端和线路中段我取了节点10、16、24、31四处类型设定为光伏和分散式风电单点容量上限500 kW总渗透率上限取系统峰值负荷的25%。充电站候选节点取节点2、9、19、25、32单个充电站最大建桩数设为20根桩单桩额定功率60 kW也就是说单个站点最大充电负荷1200 kW。充电需求点按节点负荷权重折算设定总充电需求为800 kW可调度比例α分别取0、0.4、0.7做对比实验。服务半径设为3个节点距离换算到实际距离约为1.2公里左右。这个参数不是拍脑袋定的我参考了城市充电基础设施规划中“用户步行或驾车5分钟内可达”的经验值。d0距离衰减系数取500 m。4.2 算法参数与运行环境PSO参数我用了工程上最常用的组合种群规模40最大迭代次数100惯性权重w线性递减从0.9到0.4学习因子c1c22.0速度上限取变量范围宽度的20%运行环境是Windows 11下面的Matlab R2023aCPU是普通的酷睿i7单次跑100代大约耗时2到3分钟。这个时间量级对方案比选来说完全能接受。如果需要做多场景蒙特卡洛分析建议把循环改用parfor并行计算能再把时间压缩一半以上。4.3 结果展示与方案对比下面是我在三个可调度比例下得到的典型结果。场景年总费用万元网损MWh/年最低节点电压pu建站方案α0无可调度486.3152.80.915节点2、9、25α0.4451.2139.60.932节点2、19、32α0.7423.5127.40.946节点9、19、32从表格可以看到随着可调度比例从0提高到0.7年总费用下降了约13%网损减少了接近17%最低节点电压也从0.915提升到0.946改善效果非常直观。我一开始做这个实验时以为可调度比例只会影响充电站布局没想到对电压和网损影响这么大后来想通了因为充电负荷空间上重新分配后末端的高负荷区域可以“卸载”一部分DG出力和充电负荷形成更合理的互补关系整个系统的潮流分布自然就变好了。建站方案的变化也很有意思α0时建站位置偏向负荷中心附近的节点2和25而α0.7时站点向节点9、19、32靠方案更分散这是因为可调度能力允许部分负荷跨越一定距离去更合适的站充电末端节点不再需要硬扛所有本地的充电压力。4.4 结果图怎么看我习惯画三张图第一张是粒子群收敛曲线横轴为迭代次数、纵轴为全局最优适应度用来判断算法是否收敛、有没有早熟第二张是IEEE 33节点单线图把DG接入位置、充电站位置用不同颜色节点标出来可以直接看到配置方案的空间分布第三张是优化前后各节点电压分布对比图能非常直观地展示末端电压的改善效果。看收敛曲线时有一个经验如果40代以前曲线就完全水平不动说明大概率早熟需要调整粒子数或惯性权重如果到100代还在缓慢下降说明迭代次数不够可以延长到150代。标准的曲线形态是前30代快速下降后面基本平直偶有小幅波动。如果出现波浪形反复说明惯性权重过大或罚函数设置不当需要回头检查。5. 避坑经验从报错到收敛的实用排查清单5.1 潮流不收敛的排查顺序如果loadflow.m不收敛百分之八十是数据问题不是算法问题。我踩过的坑主要有三个。第一是节点编号从1开始但需求点索引从0开始导致支路矩阵里取错行电压越界直接发散。我的经验是写代码前先打印一遍节点和支路个数的核对信息把bus矩阵和branch矩阵的第一行输出来看一眼确认格式和编号关系。第二是单位换算混乱。Matpower类数据通常以标幺值输入但充电功率和DG容量往往以kW为单位一旦忘了除以基准功率节点注入功率会大几万倍潮流必然坏。我习惯在参数初始化文件里统一做一次换算所有数据的单位都转成标幺值后面代码里就再也不用管单位问题。第三是末端节点电压初始值给得太低。前推回代法在重负荷下容易出现电压过低导致迭代公式中根号内出现负值。我的处理是给V初始全部为1.0标幺值并且如果某轮迭代出现平方根内负值就取绝对值后继续迭代保证程序不中断最终由罚函数去淘汰那些电压崩掉的方案。这个方法不算严谨但做优化搜索非常实用比直接报错终止体验好太多。5.2 粒子群早熟与振荡调整技巧PSO最让人头疼的问题就是陷入局部最优。我调整过几轮参数分享几条实际有效的经验。第一个技巧是惯性权重线性递减这比固定值效果好得多。前期w大粒子速度快全局搜索能力强后期w小粒子精细搜优。0.9到0.4的递减区间是经典经验值我试过0.95到0.2全局搜索强但收尾速度太慢也试过静态0.6后期很容易早熟。总体上0.9到0.4是最省心的组合。第二个技巧是如果连续20代全局最优没有更新就对当前全局最优粒子做一个随机扰动比如容量变量乘以0.8到1.2之间的随机数位置变量随机跳到另一个候选节点重新给它一次探索机会。这种方法叫“重新初始化”或“跳跃扰动”代码只要十行却能让算法从局部最优里逃出来。第三个技巧是种群规模并非越大越好。规模从20加到40时结果改善明显从40加到80提升很小但计算时间翻倍。规划问题计算量不大我建议控制在40到60之间即可。5.3 罚函数系数选择与结果合理性检验罚函数系数的选择直接影响最终方案是否可行。系数太小算法会把越限节点当成“低费用方案”保留结果里出现电压0.88这种硬伤系数太大粒子一旦越限就几乎不可能返回可行域导致搜索严重偏向保守区域错过边界上的最优解。我调试时有一个笨办法先跑一次不含约束的纯费用优化记录当前目标费用的量级然后把罚系数设为目标费用量级的100倍左右跑完之后检查电压和支路功率的最大越限量。如果越限量超过1%就把系数乘以3再跑如果粒子全部聚集且结果很差就把系数除以2。通过两三轮试验基本能找到一个稳定可行的区间。结果合理性检验也很重要。跑完最优方案之后要检查充电站总容量和总充电需求是否匹配如果总充电站容量只有总需求的50%说明覆盖约束写松了模型钻了空子。还要看DG总安装容量是否满足渗透率约束以及是否有某个粒子输出“负费用”的荒唐结果。任何反常识的结果九成都是模型逻辑写错了而不是算法找到了新世界。5.4 工程落地中的几点提醒模型跑通只是第一步真要拿去做规划决策还需要注意三个工程问题。第一空间可调度比例α不是一个能自由设定的技术参数它本质上反映的是用户选择行为。做实际项目时需要通过问卷调查、充电App数据分析或者区域交通仿真来标定不能直接拍脑袋设成0.7。模型的价值在于让你知道“如果能把可调度比例从0.3引导到0.5年费用能省多少”这本身就是对运营方的建议。第二一定要注意充电站的空间分布不能只看电气节点还要结合城市路网和实际地块属性。有些节点电气上非常适合建站但现实中是个公园或基本农田保护区这种候选节点要提前删掉。我一般会把可用地块清单先做出来再映射到电网节点上避免模型跑半天出来一个落在河中央的方案。第三做方案比选时不要只看单目标结果建议多跑几次敏感分析。比如把可调度比例从0到0.8每隔0.1取一次把服务半径从2公里到5公里扫一遍看配置方案是否发生大的跳变。如果稍微改参数就明显改变建站位置说明模型对参数过于敏感落地时需要更加保守。我在实际项目里还留了个习惯每次跑完结果都会把收敛曲线、电压分布和配置图存成一个带时间戳的文件夹方便复盘。这套代码从最初只能跑固定负荷到现在支持多典型日场景、负荷时空分布和多种可调度策略前前后后改了十几版。做这类规划研究最大的坑往往不是算法本身而是对配电网物理特性理解不到位用再高级的算法也救不回来。希望这篇文章能帮你少走几条弯路把你的配置方案真正跑到可信、可讲、可复现的程度。