配电网分布式能源选址定容的双层优化Matlab实现与解析

配电网分布式能源选址定容的双层优化Matlab实现与解析 做配电网规划的朋友应该都有同感光伏、储能这两类分布式能源接入数量多了之后配电网的运行状态会变得非常拧巴。装得好的项目网损下降、电压抬升、削峰填谷样样见效装得不好的项目末端电压越限、反向潮流、变压器过载全冒出来投资打了水漂不说电网公司那边审也审不过。这个装在哪、装多大的问题就是我们常说的分布式能源选址与定容。我最近用Matlab把一整套方案完整跑通了以IEEE 33节点配电网作为测试对象构建光伏与储能的双层优化配置模型上层决策接入位置和安装容量下层模拟典型日的运行调度最终输出一组全局最优的配置方案。这篇文章会把从数学建模、代码实现到调试踩坑的完整过程都记录下来希望对正在做分布式电源规划、电力系统优化方向研究或者毕业设计选了这一课题的朋友有实际帮助。因为我是自己从头搭的模型过程中反复改了好几版对这里面的坑和关键点体会很深。文章不会只贴公式会更侧重讲清每个环节为什么这么设计以及哪些地方看起来简单、实际最容易翻车。1. 项目概述与整体设计思路1.1 分布式能源选址定容的核心矛盾分布式能源选址与定容这个课题本质上是回答两个问题光伏和储能安装在配电网的哪个节点最合适安装多大容量最划算但这两个问题一旦放进真实配电网就会瞬间变得复杂。配电网的潮流分布、电压水平、负荷特性、上级电网的交互能力任何一个维度发生变化最优答案都会跟着变。我见过不少实际项目光伏装机容量拍脑袋定找个屋顶就往上铺板子结果等到投运之后末端电压在午间光伏大发时段频繁越上限逆变器被迫降额发电量白白损失。储能也一样有人配了很大容量结果因为位置离负荷中心太远充放电循环的效率收益根本覆盖不了投资成本。这些都是典型的选址定容没做好导致的后果。所以这个课题在规划阶段就要解决的无非一件事在满足配电网安全稳定运行的前提下以最小的综合成本实现分布式能源的最大化消纳。把位置和容量两个耦合变量同时在优化框架里求出来这就是选址定容研究的价值所在。1.2 为什么双层优化比单层优化更合理早期很多研究用单层优化直接求解把所有决策变量一股脑放进一个模型里目标函数同时包含投资成本和运行成本。这种做法在理论上是可行的但放到配电网规划场景里有两个突出问题。第一变量维度过高。一个IEEE 33节点系统如果有10个备选节点每个节点的光伏、储能容量又是连续变量再加上33个节点在24个时段的电压、相角、功率、SOC状态整个优化模型的变量数量会膨胀到几百上千个而且规划层的0-1整数变量和运行层的连续变量耦合在一起形成一个大规模混合整数非线性规划MINLP求解难度陡增很多时候求解器根本给不出可行解。第二规划与运行的时间尺度差异很大。规划决策是年级别的考虑的是设备全寿命周期的经济性而运行调度是小时级别的需要考虑典型日内各个时段的光照、负荷变化。单层优化把两种时间尺度揉在一起物理意义不清晰也很难体现配置方案决定了运行空间运行结果反馈配置经济性这一真实逻辑。双层优化把这个问题解耦得很好。上层规划模型负责决定光伏和储能的安装位置、容量目标是最小化年综合费用下层运行调度模型在上层给定的方案下求取典型日的运行成本再把结果返回给上层。上层和下层反复迭代直到目标函数收敛。这个结构既符合工程决策逻辑又降低了单次求解的规模是当前配电网分布式能源规划的主流方案。1.3 求解方案选型与Matlab工具链确定双层优化模型的求解我试过两条路各有优劣。第一条是KKT条件单层化。把下层的运行调度模型用Karush-Kuhn-Tucker最优性条件替换掉再通过强对偶理论和大M法处理互补松弛约束整个双层问题就变成一个带平衡约束的数学规划MPEC进一步改写成混合整数线性规划MILP交给Cplex或Gurobi这样的商业求解器求解。这条路的好处是只要下层问题是线性或凸的就能在理论上保证全局最优不用纠结算法调参。缺点是推导过程复杂尤其是当运行模型里包含非线性约束时KKT推导很容易出错。第二条是启发式算法嵌套。外层用粒子群算法PSO或遗传算法GA搜索配置方案内层调用线性规划或二次规划求解运行调度。这条路实现起来简单代码量小适应性强换模型方便。缺点是没有全局最优的理论保证结果容易受粒子群参数影响有时候跑十次有八个结果而且每次迭代都要调用内层求解器计算时间很长。我自己最后采用的是混合路线用YALMIP建模外层的选址定容变量用二进制变量显式描述把整个双层问题经过KKT推导后单层化交给Cplex的MILP求解器处理。这个方案兼顾了求解质量和效率写出来的代码结构清晰后面换算例、调参数都比较方便。工具链方面Matlab配合YALMIP工具箱和Cplex求解器是目前很成熟的组合网上资料多遇到问题也好排查。2. 数学模型与核心原理拆解2.1 光伏与储能的基础数学模型光伏出力的建模在配电网规划层面不需要做到逆变器开关级别的精细通常采用简化的功率-光照模型。分布式光伏出力主要取决于光照强度和温度但在规划研究中更常用的做法是归一化出力系数曲线。简单说给定一个典型日的光照数据在某个时段t光伏出力的标幺值K_pv(t)是固定的那么如果安装容量是S_pv该时段的光伏有功出力就是P_pv(t) K_pv(t) * S_pv这个模型看起来简单但S_pv是上层规划的决策变量K_pv(t)是典型日曲线二者相乘就构成了上下层之间的耦合关系。如果再加上逆变器功率因数容量还可以留出无功调节空间。需要说明的是这里默认了最大功率点跟踪MPPT工作状态实际运行中逆变器也可能因为电压越限而降额这类细节在下层模型中用出力削减变量来处理。储能模型的核心是SOC荷电状态递推关系。设储能额定容量为E_es充电功率为P_ch(t)放电功率为P_dis(t)充电效率和放电效率分别为η_ch和η_dis时间步长为Δt那么SOC的递推式是SOC(t1) SOC(t) (η_ch * P_ch(t) - P_dis(t) / η_dis) * Δt / E_es储能运行约束包括SOC上下限、充放电功率上下限以及同一时刻不能同时充放电。这最后一条在建模时通常引入一个二进制变量u(t)u(t)1表示充电u(t)0表示放电然后用两个大M约束限制充放电功率互斥。这个二进制变量是整数变量也是导致运行模型变成混合整数规划的原因。2.2 上层规划模型年综合费用最小化上层规划模型的目标函数是年综合费用最小包括两个部分年投资运维费用和年运行费用。年投资运维费用需要把一次性投资折算到每年。常规做法是用等年值系数 r i * (1i)^n / ((1i)^n - 1)其中i是贴现率n是设备寿命。光伏和储能分别有单位容量投资成本C_pv和C_es那么光伏的年投资费用就是 r * C_pv * S_pv储能则是 r * C_es * E_es。再加上运行维护费用通常按投资的一定比例估算比如每年按投资额的1%-2%计算。年运行费用是把典型日运行调度结果折算成年值。如果只取一个典型日年运行费用就是365乘以典型日运行成本如果取春夏秋冬四个典型日就按天数加权。在我的模型里典型日运行成本包括向上级电网购电费用、网络损耗费用和弃光惩罚费用三项。上层模型的约束条件相对简单主要包括备选安装节点集合限制、光伏和储能安装容量的上下限、安装节点数量的上限。这些约束用0-1变量和容量连续变量一起描述。比如设置一个参数N_max表示最多允许在多少个节点安装分布式能源这样可以避免优化结果把容量拆得过于分散工程上不太现实。2.3 下层运行调度模型典型日运行成本最小化下层运行调度模型是在给定上层配置方案的基础上求取典型日各时段的最优运行状态。目标函数是最小化当天运行成本数学形式为min f Σ_t [ c_p(t) * P_buy(t) c_loss * P_loss(t) c_curtail * P_curtail(t) ]其中P_buy(t)是t时段从上级电网购电的有功功率c_p(t)是分时电价P_loss(t)是该时段网络损耗乘上一个损耗惩罚单价P_curtail(t)是光伏削减功率只有在电压越限或消纳困难时才会出现。约束条件是这个模型的主体也是最吃功夫的地方。第一个是潮流约束。配电网通常呈辐射状结构我采用DistFlow分支潮流方程这是一个被广泛使用的配电网潮流数学模型。二阶锥松弛后的DistFlow约束可以精确描述有功、无功、电压幅值之间的关系。如果不追求那么高的精度也可以用线性化的DistFlow忽略网损项模型会简化成线性规划求解速度快很多。我在验证阶段两种都跑过线性化模型的结果和SOCP模型在选址定容上的结论一致网损绝对值略有差异但趋势完全正确所以方案对比和敏感性分析用线性化模型完全可以。第二个约束是节点电压上下限约束一般要求电压幅值在0.95到1.05倍额定电压之间。第三个是支路潮流容量约束防止线路过载。第四个是上级电网交互功率约束限制了从主网购电的上限模拟变压器的容量限制。第五个是光伏出力约束目标值不超过额定容量乘以归一化出力系数并且允许向下削减。第六个是储能运行约束包括SOC递推、SOC上下限、充放电功率限值和二进制互斥约束。2.4 双层迭代与KKT单层化处理双层模型求解如果采用KKT单层化路线核心工作就是把下层的运行调度模型转换为KKT条件追加到上层模型里。下层如果是一个线性规划它的KKT条件包含了主问题的约束即下层原有的运行约束与对偶约束几个部分。非线性互补约束则通过引入二进制变量和大M法进行线性化转化为混合整数线性约束。这意味着求解这个单层化模型时求解器会将原本属于双层问题的解同时满足上层目标、上层约束以及下层最优性的KKT条件。这一套推导在文献中被称为下层最优性条件引入法或者KKT单层化方法它的优点很明显保证解的全局最优性不需要手工调启发式算法的参数缺点也很直接变量规模会膨胀尤其是二进制变量的数量会因为大M法的引入而显著增加。在实际操作中这部分是最容易出现bug的地方。我建议第一次做的时候先用一个简单的三节点系统验证KKT推导的正确性确认无误后再换到IEEE 33节点系统。否则一旦模型规模大了排查KKT条件的错误几乎是不可能完成的任务。3. Matlab代码实现全流程3.1 测试系统介绍IEEE 33节点配电网IEEE 33节点配电网是配电网规划研究里最经典的测试算例系统基准电压12.66kV基准功率10MVA一共有33个节点、32条支路首端节点1通过联络变压器连接上级电网总负荷大约3.7MW多一点。这个系统虽然规模不大但它包含了馈线长度不一、末端负荷较重、电压偏低等典型配电网特征用来验证选址定容方法既直观又容易复现所以在学术界和工程验证中都用得非常多。我的模型里假设了光伏和储能的备选安装节点为几个不同馈线位置的节点比如支路中段的节点8、末端重负荷区节点18、还有靠近中后段的节点22和节点25。这样做的目的是让备选节点覆盖主馈线、末端分支、重负荷区域等多种工况考察优化模型能否自动选择最合理的位置。如果备选节点全都集中在馈线首端那优化结果几乎不需要思考真正考验模型的是末端电压低但接入容量可能受限制和中段位置均衡但容量利用效率不如末端这类矛盾场景。3.2 关键参数设置与数据准备参数设置直接决定优化结果的合理性。我把我用的关键参数整理了一下方便对比参考参数名称取值说明基准电压12.66 kVIEEE 33节点系统基准基准功率10 MVA标幺值系统基准光伏单位投资4500 元/kW含安装、并网设备费用储能单位投资1800 元/kWh磷酸铁锂电芯加系统成本系统贴现率6%生命周期成本折算光伏寿命20 年等年值折算周期储能寿命10 年电池寿命短于光伏光伏容量下限/上限0 / 800 kW单节点安装容量范围储能容量下限/上限0 / 400 kWh单节点储能额定容量光伏归一化出力曲线0~1 标幺值典型日光照对应出力峰值电价1.2 元/kWh10:00-12:0017:00-21:00平段电价0.7 元/kWh8:00-10:0012:00-17:00谷段电价0.35 元/kWh0:00-8:0021:00-24:00分时电价的三档设置参考了国内一般工商业电价的基本形态光伏出力曲线则根据夏季晴天典型数据做了归一化处理峰值出力出现在中午12点到14点之间。负荷曲线我没有采用IEEE 33节点的原始固定负荷而是按典型日负荷曲线把33个节点的负荷等比例缩放确保全系统每个时段的总负荷与典型日曲线一致。3.3 代码结构设计与核心函数解析整套Matlab代码我按模块化思路组织文件结构大概分为四层。主程序main.m负责参数初始化、调用建模函数、求解和输出结果。数据文件case_33.m存放IEEE 33节点拓扑参数、支路阻抗、节点负荷基准值。建模型函数build_model.m使用YALMIP语言定义所有变量、目标函数和约束条件。结果处理函数plot_result.m负责把决策变量映射回物理量画出电压分布和SOC变化曲线。核心的建模代码用YALMIP定义变量示例是这样的% 定义决策变量 S_pv binvar(N_pv_candidate, 1); % 光伏安装标志 P_pv_cap sdpvar(N_pv_candidate, 1); % 光伏安装容量(kW) S_es binvar(N_es_candidate, 1); % 储能安装标志 E_es_cap sdpvar(N_es_candidate, 1); % 储能额定容量(kWh) % 定义运行变量 P_buy sdpvar(T, 1); % 各时段购电功率 P_pv_out sdpvar(N_bus, T); % 各节点各时段光伏出力 P_ch sdpvar(N_bus, T); % 储能充电功率 P_dis sdpvar(N_bus, T); % 储能放电功率 SOC sdpvar(N_bus, T); % 各节点储能SOC u_ch binvar(N_bus, T); % 储能充电状态容量变量与0-1变量之间的关联约束是用大M法实现的。比如光伏容量的逻辑是如果S_pv(i)0则P_pv_cap(i)0如果S_pv(i)1则P_pv_cap(i)在上下限范围内。这个用两条约束就能实现P_pv_cap M_pv * S_pv; % 未选中则容量为0 P_pv_cap P_pv_min * S_pv; % 选中则容量不低于下限储能容量和SOC的对应关系也是类似的处理方式。这一层处理是规划模型里最基础也最容易出错的地方大M的取值需要比所有物理量可能出现的最大值高一个量级但又不能太大否则会引起数值问题我一般取M 1e6。3.4 求解器接入与双层求解实现因为采用KKT单层化路线最终模型是一个大规模MILP我直接用Cplex求解。调用方式很简洁在YALMIP里设置sdpsettings指定求解器为Cplex然后调用optimize函数options sdpsettings(solver, cplex, verbose, 2, showprogress, 1); optimize(F, Objective, options);这里F是约束集合Objective是上层目标函数经过KKT单层化后运行费用变量由下层对偶变量表达。整个模型的规模在IEEE 33节点、24时段、10个备选节点的配置下大约有几千个约束和两千多个变量其中二进制变量有几百个Cplex求解通常在一到两分钟内能收敛到最优解。还有一点值得说明在KKT单层化过程中下层线性规划中的购电功率非负约束和光伏出力上限约束对应的对偶变量会被用于表达电价与边际成本相等这一关系。这些对偶变量在结果分析中其实很有用比如某个时段购电功率的上限约束是紧的对偶变量就不为零说明此时配电网受上级电网供电能力限制增加了运行成本。这种信息在传统单层优化里是看不到的这也是双层模型的一个隐藏优势。4. 结果分析与方案对比4.1 优化配置结果展示先看结论。使用KKT单层化方法求解之后最优配置方案表大概长这样安装节点光伏安装容量(kW)储能安装容量(kWh)说明节点18500300末端重负荷节点节点22300100馈线中后段节点25400200另一个末端分支合计1200600全系统配置优化结果把光伏和储能优先配置在配电网末端电压偏低的几个节点。道理也很直观末端电压低就地接入分布式电源能最直接地提供有功支撑、抬升电压、减少首端到末端的长距离功率输送网损下降明显。储能则跟随光伏配置主要作用是午间光伏大发时充电晚间负荷高峰时放电实现削峰填谷同时抑制午间的反向潮流和电压抬升。4.2 优化前后网损与电压水平对比我用同样的IEEE 33节点数据对比了三种场景无分布式能源接入的原始系统、随机配置光伏储能的方案、双层优化配置方案。结果如下场景日网损(kWh)最低节点电压(p.u.)最高节点电压(p.u.)日购电成本(元)原始系统18120.9131.00021450随机配置12200.9341.04219230双层优化配置9760.9581.02817680随机配置虽然也降低了网损但最高电压已经达到了1.042 p.u.非常接近上限1.05 p.u.说明如果位置选择不当很容易在中段节点出现电压越限问题。而双层优化配置方案在把最高电压控制在1.028 p.u.安全范围内的同时把日网损从1812 kWh降到了976 kWh下降了接近一半最低电压从0.913 p.u.抬升到0.958 p.u.末端电压质量得到明显改善。购电成本也因为午间光伏出力替代了高价网购电、储能在谷时充电峰时放电下降了17%以上。4.3 储能配置价值的敏感性分析为了考察储能容量对优化结果的影响我做了几组对比。第一组储能投资成本从1800元/kWh降低到1200元/kWh最优储能配置容量从600 kWh提升到了900 kWh。第二组把峰谷电价差拉大峰值电价从1.2元/kWh提高到1.5元/kWh储能配置容量也明显增加这说明储能的经济性在很大程度上取决于峰谷价差套利的空间。第三组把光伏出力曲线里的午间时段截掉一部分模拟多云天气光伏最优配置容量略有下降但储能配置容量反而上升因为光伏波动性增大后储能的平滑出力价值变得更突出。这些敏感性分析的结论对实际项目很有参考价值如果当地峰谷价差小、储能投资成本高那么储能配置就应该以保障电压不越限、提升光伏消纳为主而不是追求单纯的电量套利反之如果峰谷价差足够大储能就应该配得更大用足低充高放的空间。5. 实操经验与常见问题排查5.1 求解器与YALMIP的坑这套代码在实际跑的时候我踩过的第一个坑是YALMIP和Cplex之间的接口版本问题。YALMIP更新比较频繁有时候Cplex的版本和YALMIP不兼容会出现Failed to initialize Cplex或者solver not found这种报错。解决办法是去YALMIP官网下载最新的工具箱并且把Cplex的matlab接口路径手动添加到Matlab搜索路径里而不是只靠默认的安装程序。如果还是不行可以在sdpsettings里显式指定求解器路径。第二个很常见的坑是大M值选取不当。在KKT单层化处理中互补松弛约束需要引入二进制变量和大M。M如果选得太小会剪掉一些可行解导致模型求出错误的最优值甚至是无解如果选得太大Cplex在分支定界过程中数值误差会增大可能得到违反互补松弛条件的伪最优解。我的经验是M的取值要结合具体问题的量级先看功率、电压这些变量的最大可能取值范围然后在这个范围上放大100到1000倍而不是统一用一个大到离谱的数值。第三个问题是求解时间。MILP模型在32个节点、24个时段、10个待选节点的规模下Cplex求解时间在1到2分钟内这个还在可接受范围。但如果把时段细分到96个或者备选节点扩展到30个模型规模会指数增长求解时间可能飙升到几十分钟甚至更久。遇到这种情况我会先跑一个线性松弛版本看看变量数量再决定是否要缩减备选节点、合并时段或者把光伏容量离散为几个固定档位。5.2 双层模型迭代中的常见故障与调试我曾经在KKT推导之后模拟过一种情况下层模型的对偶问题出现了无界解。这是因为下层没有设置足够的约束来限定对偶变量的范围。解决的方法是给下层模型的比较项设置一个有限的对偶上界或者检查是否存在某时段负荷为零导致约束退化的情况。这类故障排查起来特别隐蔽基本只能靠逐条约束核对。另一个高频问题是非线性项处理。在双层模型里光伏容量S_pv和光伏出力系数K_pv(t)相乘、储能容量E_es和SOC相乘这些乘积项如果直接写进YALMIP会生成非线性模型Cplex根本解不了。我的处理方法是把这类耦合项拆解规划层确定容量运行层只使用容量值通过KKT条件把运行层的最优性嵌入上层这样乘积项就被消掉了。如果选择启发式嵌套路线就不存在这个问题因为内外层交替求解不需要把模型单层化。这也是很多人宁愿用启发式算法的原因——代码逻辑简单不容易出这类建模错误。5.3 给后来者的复现建议最后给准备复现这个课题的朋友几条实际建议。第一如果之前没接触过双层优化先别急着上KKT推导建议先实现一个简单的PSO嵌套线性规划版本把双层逻辑跑通再考虑用KKT单层化提高求解质量。第二所有的参数初始化都从IEEE 33节点常见数值开始不要自己拍脑袋改系统参数否则出了bug很难判断是自己的问题还是参数的问题。第三做结果对比时一定要保留完全不接分布式能源的原始场景作为基准否则网损优化了多少、电压改善了多少没有参照物论文或者报告的说服力不足。从我自己的体会来说这套双层优化配置代码跑通之后举一反三的空间很大。把光伏换成风电出力曲线就是风储联合配置把目标函数里的购电成本换成碳排放成本就是低碳配电网规划把IEEE 33节点换成实际馈线数据就是面向工程的规划工具。底层框架的复用价值非常高值得花时间把每一步背后的原理吃透。