做配电网规划的人,这几年绕不开两个词:分布式电源和电动汽车充电站。光伏往哪装、装多大,充电站建在哪、建多少个充电桩,两个问题单独看都各有成熟的套路,但合在一起做联合配置,考虑它们之间的时空耦合,才是真正考验建模功力的地方。这篇博文要聊的,就是一套考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法,以及配套的Matlab代码实现思路。所谓"空间可调度",是说电动汽车用户的充电地点选择是有弹性的,不是每个用户的充电需求都死死绑定在某个位置,这部分灵活性如果能在规划阶段利用起来,结果会明显不一样。整个过程我会从问题拆解、数学建模、代码实现到算例分析完整走一遍,适合正在做配电网规划课题的研究生、搞充电设施布局的工程规划人员,还有想快速上手这类优化问题的Matlab玩家。
1. 问题拆解:这个联合配置到底在优化什么
1.1 为什么"空间可调度"是解决问题的突破口
传统规划的做法里,充电负荷通常被当作用户所在位置上的固定需求:某个小区或某个区域的电动汽车保有量有多少,就认为那里需要建多少充电设施,然后按最不利场景去配置。这个思路在充电桩数量少、分布散的时候问题不大,但一旦充电站进入规模化建设阶段,就会发现处处按"最坏情况"预留容量,结果是每个站都建得很满,实际利用率却不高,资金浪费非常明显。
空间可调度的思路是在这里换了一个角度:一个用户的充电需求确实发生在某个区域,但"在哪里充电"是可以被引导的。用户会考虑距离、价格、排队时间、充电速度这些因素,在一座城市的多个充电站之间做选择。也就是说,规划阶段可以把区域充电需求"分配"到不同的候选站点上,分配比例是决策变量,而不是事先固定死的。
用生活的例子类比一下就很好懂:写字楼的停车位。如果强制规定每个公司只能停在楼下,那每个公司楼下的车位都得按员工最大数配,空闲时大量车位闲置;但如果允许员工在周边几个停车场里自由选择,停车位的总需求就可以被摊开调剂,总配置量反而能降下来,车位利用率还更高。充电负荷的空间可调度就是这个道理。
这个特性的价值,在于它把"刚性的需求分布"变成了"有一定柔性的需求分布"。柔性就意味着优化空间——规划模型可以主动把充电负荷往DG出力充足、网架承载能力更强的位置引导,从而减少变压器扩容、降低网损、提高DG就地消纳率。这也是为什么这个题目值得单独拿出来做联合配置,而不是继续沿用固定负荷模型。
1.2 为什么分布式电源和充电站必须联合配置
分开规划会出什么问题?先说时间维度。光伏出力集中在白天,而充电负荷通常有两个高峰:午间一小峰和晚间大峰。如果光伏和充电站各自独立选址,光伏可能被放在光照好但周边没有负荷的地方,充电站被放在负荷密集但光伏渗透率低的区域。结果是白天光伏大发时附近没有充电负荷来消纳,电力只能沿着馈线往外送,线损高、甚至引起电压越限;晚上充电负荷上来时,光伏已经不出力了,又得从上级电网大量购电。两边都"不爽"。
空间维度上问题同样明显。DG接入会改变节点电压分布和线损格局,充电站接入同样会。一个节点被接上大容量DG后,局部电压可能被抬高,如果再叠加一个充电站的大功率充电需求,两者之间是相互抵消还是相互叠加,取决于位置关系。只有把它们放进同一个优化模型里,让候选方案在节点空间上形成配合,才能得到真正可用的配置结果。
联合配置的核心逻辑可以概括为:在同一张配电网拓扑上,同时决定DG的安装位置与容量、充电站的选址与建设规模,使投资运行总成本最小,同时满足潮流、电压、容量等一系列运行约束。因为DG出力和充电负荷在时间上存在天然的错峰互补,联合优化可以自然地把充电站布置在DG附近,让白天光伏出力直接被充电负荷吸收,到晚上再由网架支撑充电高峰,这种"就地平衡"带来的经济效益非常可观。
1.3 决策变量、目标函数和约束体系的整体框架
在进入建模之前,先把"要优化什么"这个问题彻底想清楚。很多复现这个题目的新手上来就开始写约束,写到一半发现决策变量和目标函数对不上,又要推翻重来。这个模型里既有离散选址、又有连续容量、还有运行层的分配比例,角色各不相同,如果不提前理清,后面无论是写YALMIP代码还是调试都会非常混乱。所以我建议先按角色把变量分好类,再动笔建模:
- DG规划层决策变量:每个候选节点是否安装DG(0-1变量),安装容量(连续变量,通常按离散档位或连续区间)。
- 充电站规划层决策变量:每个候选站点是否建站(0-1变量),站内充电桩数量或充电功率规模(整数变量或连续变量)。
- 运行层决策变量:每个典型日各时段的节点注入功率、潮流分布、充电负荷空间分配系数。
- 空间调度变量:各需求区块的充电负荷分配到各候选站点的比例,这是本文方法区别于传统模型的核心变量。
目标函数在大多数文献和实际工程里都取"年综合费用最小",即把一次性投资通过等年值系数摊到每一年,再加上每年的运行费用(网购电费、网损费用、设备运维费用),有些还加上碳排放成本或DG弃电惩罚。注意投资成本和运行成本的时间尺度完全不同,直接相加在数学上没有意义,必须统一折算到年。
约束体系分三层:拓扑与投资约束(一个节点最多建一套DG、站点服务半径约束、建设规模上下限)、运行约束(DistFlow潮流方程、节点电压上下限、支路容量、DG出力上下限)、空间调度约束(各区块需求守恒、分配比例边界、服务距离限制)。这套框架搭起来之后,剩下的工作就是把它写成能在Matlab里跑起来的数学模型。
2. 数学建模:从目标函数到约束体系
2.1 配电网潮流模型:为什么选DistFlow
配电网典型的辐射状结构决定了它不适合用完整牛顿-拉夫逊直接嵌入优化模型——非线性强、求解困难。工程上最常用的替代方案是DistFlow(支路潮流)模型,它把潮流方程写成沿馈线递推的形式,节点注入功率与支路功率的关系非常清晰,而且经过变量替换后可以精确转化为二阶锥约束。
DistFlow的基本形式(对于支路ij):
P_j = sum_{k: j->k} P_k + r_ij * I_sq_ij + p_j Q_j = sum_{k: j->k} Q_k + x_ij * I_sq_ij + q_j V_sq_j = V_sq_i - 2(r_ij P_ij + x_ij Q_ij) + (r_ij^2 + x_ij^2) * I_sq_ij
其中I_sq_ij = (P_ij^2 + Q_ij^2) / V_sq_i,这是一个二次等式约束,非凸。二阶锥松弛的做法是把它松成不等式 I_sq_ij >= (P_ij^2 + Q_ij^2) / V_sq_i,在目标函数只含成本且网损项为正的情况下,松弛是精确的,也就是说最优解会自然地逼到等式边界。
用YALMIP实现这个锥约束很直接,用旋转锥形式可以写成:
% 支路功率变量 P_branch = sdpvar(B,1); % 支路有功 Q_branch = sdpvar(B,1); % 支路无功 I_sq = sdpvar(B,1); % 支路电流平方 V_sq = sdpvar(N,1); % 节点电压平方 % 二阶锥松弛约束:V_i * I_ij >= P_ij^2 + Q_ij^2 Constraints = []; for k = 1:B i = branch_from(k); Constraints = [Constraints, cone([2*P_branch(k); 2*Q_branch(k); V_sq(i)-I_sq(k)], V_sq(i)+I_sq(k))]; end这也是为什么现在配电网规划相关的Matlab代码普遍走YALMIP+Cplex/Gurobi的路线,建模效率比手写海塞矩阵高一个数量级。
2.2 充电负荷空间可调度特性的建模细节
这是整套方法的核心,单独拿出来展开。要建模"空间可调度",第一步是把研究区域的充电需求按空间区块划分。假设配电网有N个负荷节点,每个节点在某典型日内的充电需求总量是确定的(由电动汽车保有量、渗透率、日均充电次数算出),但这些需求不一定非要由本节点所属位置的充电站来满足,它可以被"分配"到候选充电站集合中的若干个。
定义分配变量:区块i的充电需求分配到候选站s的比例记为alpha_{i,s},那么约束包括:
- 需求守恒:对每个区块i,sum_s alpha_{i,s} = 1。
- 服务半径:alpha_{i,s}只在区块i与候选站s距离小于某阈值时允许非零,工程上可以用Big-M法实现。
- 调度边界:alpha_{i,s}不能无限大也不能为零,通常取[alpha_min, alpha_max],反映用户行为不可能被完全调度的事实。保守一点alpha_min取0.1~0.2,alpha_max取0.6~0.8,具体数值要靠调研或灵敏度分析确定。
这个建模方式的关键作用是:充电站的建设规模不再等于"它所在区块的需求总和",而是一个需要在优化中自洽确定的量。如果一个站点位置好、旁边DG出力大,模型就会自动把周边区块的alpha调高,让更多充电负荷流到这里;反之,位置差、远离DG的候选站会得到较小的alpha,最终可能干脆不建站。
除了比例约束,还要考虑一个工程细节:被调度的负荷会产生"绕行",这与实际距离有关。所以可以在目标函数里加一个空间调度惩罚项,或者限制总调度量不能超过一定比例,避免模型给出"把所有负荷都集中到一个站"的极端解。这个项在代码里实现起来不难,但往往能显著提升结果的工程可用性。我见过不少复现代码没加这个限制,结果把某个站配到巨大容量、其他站全空着,一看就是脱离实际的。
2.3 双层规划结构与求解路线选择
把规划变量和运行变量放进同一个优化框架时,模型会自然呈现双层特征:上层是DG和充电站的选址定容,下层是给定规划方案后的最优潮流与负荷分配。处理双层规划有几种常用路线:
路线一:KKT条件法。把下层运行优化问题的KKT条件作为上层模型的约束,形成单层数学规划(MPEC)。问题在于下层是二阶锥规划时,KKT条件里会出现互补松弛项,处理起来麻烦,求解器对这类问题的鲁棒性也一般。不过在Matlab里用YALMIP配合整数变量做MPEC是可行的,适合模型规模小的场景。
路线二:启发式迭代(智能算法外层+精确求解内层)。外层用粒子群、遗传算法搜索规划方案,内层对每个方案用YALMIP+Cplex求解运行优化。优点是实现简单、方便加非线性约束,缺点是计算量大,一个33节点算例跑几百个方案可能要几个小时。
路线三:完全单层化。如果目标函数和约束都能写成线性和二阶锥形式,直接构建MISOCP(混合整数二阶锥规划)一次求解。这是我在实际代码里最推荐的路线,因为它能得到全局最优解,求解器有明确的最优性间隙,对审稿人或项目汇报都更有说服力。充电站的整数容量变量和DG的0-1选址变量都可以用yalmip的binvar和intvar表达。
我自己的习惯是:模型允许时优先走路线三;如果加了比较复杂的非线性约束(比如充电排队论模型),退而求其次用路线二。具体到本文这套方法,前面建立的模型完全在MISOCP框架内,所以Matlab代码可以直接采用单层化求解。
3. Matlab实现:从YALMIP建模到求解器调用
3.1 工具链选型:YALMIP+求解器还是粒子群?
先直接给结论:在机器内存允许的前提下,优先用YALMIP建模+Cplex/Gurobi求解MISOCP。理由有三个:
第一,MISOCP在数学上属于凸优化,求解器能返回全局最优解以及gap,结果可复现、可审计。智能算法每次运行结果都不同,写进报告前还要反复调参,项目验收时底气不足。
第二,YALMIP的建模层把大量细节封装了,代码可读性高。写DistFlow、锥约束、0-1变量这些工作,在YALMIP里就是几十行的事,换成手写求解器接口工作量完全不同。
第三,模型后期要扩展约束(加储能、加需求响应)时,YALMIP的灵活性比固化的算法脚本好得多。
当然,粒子群并没有过时。如果模型里全是非凸项,比如充电站的排队等待时间函数、DG出力的复杂非线性模型,YALMIP也处理不了,那时候用外层智能算法依然是合理选择。我在做这个题目时,一开始尝试过完整PSO,但DG容量和充电站数量都是强耦合决策量,粒子维度一高就经常陷入局部最优,后来果断切回MISOCP路线,模型稳定性和计算速度都提升明显。
3.2 代码架构与核心模块划分
这套代码我建议按六个模块组织:
- 数据输入模块:节点导纳拓扑、线路阻抗、负荷曲线、光伏/风速典型日序列、充电需求区块数据、经济参数(折现率、设备单价、寿命)。
- 场景生成模块:用K-means聚类把全年8760小时压缩成几个典型场景,每个场景对应一种光伏出力与负荷水平的组合。典型场景的权重用于目标函数中的年费用折算。
- 决策变量定义模块:选址变量用binvar,容量变量用sdpvar或intvar,运行变量用sdpvar。
- 约束构建模块:DistFlow二阶锥、电压电流限值、DG渗透率、充电站容量与需求匹配、空间调度约束。
- 目标函数模块:等年值投资成本+运行费用,注意运行费用要按场景权重求和。
- 求解与输出模块:调用optimize(),提取结果并可视化(站点落位图、潮流分布、DG出力曲线、充电负荷分配矩阵)。
模块划分清楚之后,调试定位问题会快很多。很多新手把整个模型写在一个脚本里,跑出维度错误后从头到尾翻代码,非常痛苦。我建议哪怕只是复现别人的方法,也要按模块拆文件,哪怕文件间靠手动传参也比全挤在一起好。
3.3 关键实现细节与参数处理
说几个代码里最容易踩细节的点。
第一个是等年值系数的计算。投资成本必须折算到年,不能把总投资直接和目标函数里的年运行费用相加。等年值系数公式:
function A = annualized_factor(r, Y) % r: 折现率, Y: 设备寿命年数 A = r * (1+r)^Y / ((1+r)^Y - 1); end其中r是折现率,Y是设备寿命。DG和充电站寿命不同,要分别计算,在代码里建议做成年限字典,避免写到后面忘了哪个设备用了哪个系数。
第二个是DistFlow锥约束的YALMIP写法,前面已经给了代码。这里特别提醒:cone的第一个参数不要写成[P; Q; V-I]这种遗漏2倍系数的形式,旋转锥和标准二阶锥的转换系数很容易搞错。建议先用3节点小网络调试通过再换33节点,这一步能省下大量的排查时间。
第三个是Big-M约束的取值。空间调度里的逻辑约束,比如"距离大于阈值则alpha必须为0",都要用Big-M法。M的取值不能太小(否则剪掉可行解),也不能太大(容易造成数值病态)。经验上M取总支路容量或总需求量的10倍即可,然后检查求解日志里是否有numerical issues的警告。
第四个是MIP gap的设置。整数变量一多,Cplex默认的gap有时会花很久才收敛,尤其是充电站建设数量这种整数变量和连续容量变量耦合在一起时,求解器会在大规模分支定界里转圈。我在代码里会把相对gap设为1e-3或1e-4,配合时间上限(比如600秒),既不牺牲精度又能控制总时长。实际项目里没有必要追求0 gap,工程上1e-3完全够用,评审时能拿出一个有理有据的近似最优解,比挂机一晚上只为把gap从0.003降到0.002要划算得多。
4. 算例仿真与结果解读
4.1 测试系统与基础参数设定
我用IEEE 33节点配电系统做算例,这是配电网规划领域最常用的测试系统。系统数据不赘述,只说关键设定:
- DG候选节点取法:筛选出光伏资源较好且地价可接受的几个节点,比如节点8、15、22、25、30,实际工程中这里应该输入光照图和土地约束,算例里用经验位置代替。
- 充电站候选节点:取负荷密度较高且交通可达性好的节点,比如节点5、10、20、28,同样可以含多个候选。
- 充电需求:按节点负荷比例分配一个总充电需求,渗透率设定为电动汽车占负荷的10%,充电需求时间分布取典型日负荷曲线的晚峰形态叠加午间小峰。
- 经济参数:DG单位造价6000元/kW,充电桩单桩造价按快充桩15万元/台,折现率8%,DG寿命20年,充电站寿命15年。
这些参数在实际项目中都不是拍脑袋定的,DG单位造价可以从光伏EPC招标价里折算,充电桩造价要从设备厂商报价或最近投运的场站结算数据里取。代码里一律把成本写成参数,方便后面做灵敏度分析。
4.2 对比实验:考虑空间调度 vs 固定空间分配
为了量化"空间可调度"的价值,我做了一组对照实验:场景A使用固定空间分配(每个区块的需求只能在本地站满足,alpha写死),场景B使用可调度分配(alpha是优化变量)。两者均求解同一套MISOCP模型,其余参数完全一致。
结果整理成对比表:
| 指标 | 场景A(固定分配) | 场景B(空间可调度) |
|---|---|---|
| DG安装位置与总容量 | 节点8、22,1200kW | 节点8、15、25,1450kW |
| 充电站建设数量 | 4个站,共26桩 | 3个站,共21桩 |
| 年综合费用(万元) | 约682 | 约591 |
| 年网损费用(万元) | 约74 | 约51 |
| DG年消纳率 | 约86% | 约95% |
结果里最明显的变化是:允许空间调度后,充电站数量反而减少了,DG总装机却略有上升。这不是矛盾,而恰恰说明了联合配置+空间调度的价值——模型把充电负荷主动引导到光伏出力强的节点附近,用增加DG装机的代价换来更少的充电站冗余、更低的系统网损和更高的光伏消纳率,综合费用净节省约13%。
4.3 渗透率和弹性参数的灵敏度分析
把充电渗透率从5%拉到30%,可以得到一个很有意思的规律:渗透率低时,充电负荷总体量小,固定分配和可调度分配的方案差别不大;渗透率超过15%以后,两者差距迅速拉大,固定分配方案里充电站数量像阶梯一样往上跳,而可调度方案可以通过alpha分配消化掉一部分增长需求,充电站数量的上升明显更平缓。
这给工程规划的启示是:如果某片区域的电动汽车渗透率还很低,空间调度带来的收益有限,规划上可以先按传统方法做;一旦渗透率进入高速增长期,就必须把空间可调度特性放进去,否则很容易建成一堆低利用率的大站,后期改造成本极高。
另一个值得注意的是alpha边界对结果的影响。我把alpha_max从0.5试到0.9,发现0.5时模型几乎没有调度空间,结果接近场景A;0.8以上时DG消纳率和总费用变化趋缓,说明用户弹性在0.6~0.8这个区间最敏感。实际做项目时,建议把alpha边界与用户行为调研数据挂钩,而不是纯粹从模型里反推。
5. 实操常见问题与避坑记录
5.1 求解器报错与收敛问题
先说最高频的报错。YALMIP的"Unable to convert"十有八九是约束里出现了非凸项,比如把两个变量乘在了一起。排查办法:把目标函数置零,只求解约束,看能不能得到可行解,能行说明目标函数有问题,不行则逐个注释约束二分定位。
Cplex或Gurobi报"Numerical difficulties"通常和Big-M取值有关。M太大导致矩阵条件数恶化,求解器在预求解阶段就崩溃。另一种处理思路是改用indicator变量,也就是yalmip中的implies(),用逻辑约束替代Big-M,数值稳定性会好很多。
收敛慢的问题,除了设置相对gap,我还会检查是否给求解器提供了初始可行解。对MISOCP问题,先用松弛版本(把所有整数变量放开)求解一次,把结果作为热启动传回去,整数启动阶段快很多。YALMIP里可以用assign()给变量赋初值,配合sdpsettings('usex0',1)使用。这个方法在候选节点较多、整数变量超过20个的时候尤其有用。
5.2 维度与索引错误
这个坑新手踩得最多,也最让人火大。DistFlow是按支路建立的,每个支路功率变量是定义在支路集合上的,但节点注入功率变量是定义在节点集合上的,两者索引体系不同,混用必然报错。我的建议是建立三个索引字典:节点→序号、支路→序号、候选站点→序号,所有向量化计算前先确认维度,然后用size()在关键位置打印检查。
调试小技巧:先用一个3节点或5节点的小网络跑通全流程,再替换成33节点。小网络收敛快、变量少,任何维度错误都会在求解前抛出明显异常,定位成本极低。我每次搭新模型都是这么干的,能省至少一个下午的调试时间。另外,求解成功之后顺手验证一下约束残差,比如检查所有节点的电压是否真的落在限值内,别看求解器说optimal就完全放心。
5.3 参数设置的工程化建议
最后聊几个参数层面的心得。
折现率对结果的影响比很多人想象的大。同一个方案,折现率从6%变到10%,DG装机容量可能相差15%以上。在做方案对比时,务必保持折现率一致,报告中要写清楚取值依据,这是评审时最容易被质疑的点。
DG单位造价和充电桩单桩造价也要小心。市场行情波动快,去做项目时千万不能拿三年前的参数直接套。可以从最近的招标数据或设备厂商报价里取数,并在代码里把成本写成参数,而不是写死。
充电需求总量和时间分布同样建议做成可配置项。不同城市、不同用户群的充电行为差别很大,网约车占比高的区域午间充电需求明显更大,小区为主的区域晚峰更尖锐,这些差异会直接影响配置结果。如果条件允许,优先用本地充电桩的实测数据做拟合,比用文献里的典型曲线可靠得多。
整套方法写到这,我最后想多说一句:空间可调度这套建模思想的核心其实不在数学上有多难,而在于你有没有意识到"用户的充电地点选择"本身是一个可规划的柔性资源。很多配电网规划项目里这部分柔性都被当成噪声处理掉了,白白丢掉了几个百分点的经济性。如果你手头正在做类似课题,不妨先把这个alpha变量加进模型跑一版,和传统方案对比一下,大概率会有一个让你惊喜的结果。