ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

多微电网电能交互调度:计及碳排放的ADMM分布式优化Matlab实现

多微电网电能交互调度:计及碳排放的ADMM分布式优化Matlab实现 做多微电网调度的项目也有三年了最深的感受是单微网运行优化是“自己管好自己的账”多微电网电能交互却是“几本账之间还要来回对账”。最近我把一套计及碳排放的ADMM分布式运行策略完整在Matlab里跑通了从模型搭建、算法推导到算例验证前前后后踩了不少坑。这篇文章把完整的技术思路和实现细节都摊开讲清楚适合正在研究多微电网优化调度、分布式优化或者准备用Matlab做ADMM仿真的同学参考。先说这套策略解决了什么问题。多微电网系统里每个微网都有自己的光伏、风机、储能和负荷靠联络线连在一起。每个微网的用电成本、发电成本、碳排放配额都不一样如果只靠自己内部平衡有的微网光伏大发用不完有的微网夜间缺电只能靠高成本机组顶上。通过合理的电能交互可以让富余电量在微网之间流动整体削峰填谷、降本减排。但这里有一个关键前提参与交互的每个微网往往是独立运营主体不愿意把自己的负荷曲线、储能SOC、机组成本系数全部交给一个中央调度中心。这时候分布式优化就比集中式优化更贴近实际ADMM就是其中非常成熟的工具。整个项目里我把碳排放以碳配额加碳交易的方式纳入每个微网的目标函数再用ADMM把联络线交互功率作为耦合变量拆开让每个微网只交换交互功率信息就能收敛到与集中式几乎一致的结果。下面按从模型到代码、再到算例结果和调试经验的顺序完整讲一遍。1. 项目要解决的问题与整体设计思路1.1 多微电网电能交互为什么难做多微电网和单微网优化最大的区别就是多了一个“主体自治”的维度。单微网内部的所有设备归属同一个运营主体想怎么调度都行集中式求解很自然。但多微电网不一样每个微网可以是独立的售电公司、园区、居民社区它们之间是合作博弈关系而不是上下级关系。这种情况下如果做集中式优化需要把所有微网的内部信息汇总到同一个优化器里。问题很直接谁来当这个中心各微网凭什么把真实成本、负荷、储能状态交出去就算是一个集团内部的微网群跨部门的数据共享也可能遇到权限和合规问题。所以一个可以落地的方法是把全局优化拆成多个本地子问题每个微网自己解自己的优化只通过联络线交互功率这个公共变量做协调。ADMM的价值正在于此它只需要相邻微网交换少量边界信息就能在数学上保证收敛到全局最优解。1.2 为什么选ADMM而不是集中式求解集中式求解其实也有优点实现简单、结果稳定、没有收敛问题。如果多微网属于同一个主体比如同一个园区的几个微网我个人推荐直接做集中式没必要为了分布式而分布式。但如果是独立的多个主体ADMM是更合适的选择主要原因是它有三个特性。第一ADMM对目标函数形式要求低。每个微网内部的优化问题不管是二次规划还是线性规划只要子问题能解外层迭代就能跑。第二ADMM天然支持并行计算每个微网的子问题在迭代中互不影响可以各自在本地算也可以在Matlab里用parfor并行加速。第三ADMM收敛性理论上比一般对偶分解方法好实际调试时只要惩罚参数选得合理通常几十步迭代就能达到10^-4量级的残差。当然ADMM不是万能的。非凸问题、离散整数变量会让收敛性变得敏感。所以这套策略把微网内部机组建模为连续可调变量储能、交互功率等也都是连续变量整个问题保持凸性ADMM的收敛性有保障。1.3 碳排放怎么进入优化目标碳排放进入优化模型常见有三种思路硬约束法、碳税法和碳交易法。硬约束法最简单直接把碳排放设成上限但问题在于碳限额如果设置得太紧可行域可能为空模型跑不出来。碳税法是在目标函数中对每千瓦时碳排放加一个固定碳价本质上是把碳成本内部化但缺乏总量控制逻辑。碳交易法更符合当前主流的碳市场机制每个微网获得一个碳排放配额实际排放低于配额时有盈余可以卖出获得收益实际排放高于配额时需要购入配额成本增加。这套策略采用碳交易法因为它在工程上更好解释配额多、排放少的微网等于多了一笔收益配额少、负荷重的微网就要为超额排放支付成本。这个机制天然就能引导微网之间通过电能交互来降低整体碳排放而不是各自闷头烧高价燃料发电。2. 计及碳排放的多微电网运行模型搭建2.1 微电网元件建模与变量定义先定义微网编号为i 1,2,...,N每个微网内部的典型元件包括光伏、风电、常规燃气机组、储能、负荷以及与其他微网相连的联络线。为了便于用Matlab的quadprog求解所有变量都定义为连续变量并统一为一组向量x_i。光伏出力和风力出力在短期调度中可以视为给定的预测值所以不把它们设为决策变量而是作为已知参数放入功率平衡约束。常规机组出力P_g是一个连续决策变量发电成本采用二次函数C_g(P_g) a * P_g^2 b * P_g c。储能方面定义充放电功率P_ch和P_dis以及SOC状态变量SOC的递推关系是SOC(t1) SOC(t) (eta_ch * P_ch - P_dis / eta_dis) * dt / Cap其中eta_ch和eta_dis是充放电效率Cap是储能容量dt是调度步长。联络线方面假设微网i和微网j之间存在一条交互线路定义从i流向j的功率为P_tie(i,j)正方向从i到j负方向反之。这样定义之后两个微网之间同一个物理功率变量会出现两个视角ADMM就是要让这两个视角的数值收敛一致。2.2 目标函数运行成本与碳交易成本每个微网i的目标函数f_i由三部分组成常规机组发电成本、储能退化成本、碳交易成本。常规机组发电成本是二次函数在目标函数里对应H矩阵中的二次项和f向量中的一次项。储能退化成本通常简化成与充放电功率成正比的线性项也可以进一步拆成充、放电两个方向的系数反映电池循环寿命损耗。碳交易成本的形式为lambda_carbon * (E_total - E_alloc)其中E_alloc是碳配额E_total e_co2 * P_g * dt是常规机组发电产生的实际碳排放量lambda_carbon是碳市场交易价格。这个目标函数有几个值得注意的地方。第一可再生能源自身的碳排放按零处理所以在目标函数中没有直接体现光伏和风电的碳成本。第二如果微网从外部买电买电的碳排放按对方的边际排放来算比较复杂这里简化为主网或相邻微网的电力互济不额外计算配额只在物理功率平衡中体现。第三碳价lambda_carbon一旦设定整个系统会自然把碳排放转化成经济信号碳价越高燃气机组越倾向于减少出力微网间交互功率越活跃。2.3 约束条件功率平衡、储能与交互线每个微网内部需要满足功率平衡约束 P_pv P_wt P_g P_dis - P_ch - P_L - P_tie_export 0。 其中P_tie_export是微网i通过所有互联线路向外送出的净功率如果为负就表示从其他微网购电。储能约束包括上下限、充放电功率限值和SOC递推方程。特别要注意SOC的初值和末值约束在实际算例中通常要求一个调度周期结束时SOC回到初始值避免日积月累的偏心充放电。燃气机组有出力上下限和爬坡约束爬坡约束对时间序列调度很重要如果只做单时段优化可以忽略。联络线有传输容量约束即|P_tie(i,j)| P_tie_max(i,j)这个约束在分布式求解时需要放到子问题中确保本地解不会超出线路物理极限。在多时段场景下约束会变得比较多。比如一天24个时段每个微网就有24个功率平衡约束、24个SOC递推方程和若干不等式约束。好在这些约束都是线性约束用Matlab的quadprog可以一次性把矩阵Aineq、Aeq、bineq、beq构造出来。2.4 耦合关系与全局优化问题形式整个多微网系统的问题是minimize Σ f_i(x_i)其中不同微网之间唯一耦合的就是联络线功率P_tie(i,j)。为了让问题可分离引入公共变量z(i,j)表示微网i和微网j之间联络线的公共交互功率值。每个微网的本地变量中包含它自己视角的交互功率两个视角需要满足一致性约束 x_tie(i,j) z(i,j)x_tie(j,i) -z(i,j)。 这里的第二个条件本质上定义了方向如果z(i,j)为正表示从i流向j那么从j视角看就是负值。把这个耦合关系写成全局问题形式就是一个带等式约束的优化问题。ADMM处理这种结构非常自然本地子问题更新x_i协调层更新公共变量z再更新拉格朗日乘子lambda。后面这一整套迭代就是把原问题完全拆开的关键。3. 从ADMM公式推导到Matlab代码3.1 把全局问题写成ADMM标准型ADMM的标准形式是min f(x) g(z)约束条件是Ax Bz c。多微网问题天然满足这个形式f(x)就是所有微网本地运行成本之和g(z)可以设为零因为公共变量z本身没有成本。当然如果希望限制交互功率的偏好也可以在g(z)中加惩罚项但这套策略里不需要。定义每个微网i的本地变量x_i包括P_g、P_ch、P_dis、SOC以及它看到的各条交互线功率。公共变量z表示所有联络线的公共功率。约束条件就是x_i中记录的交互功率减去公共变量z等于零。这样增广拉格朗日函数写成L Σ f_i(x_i) Σ lambda_i_k * (x_{i,k} - z_k) Σ (rho/2) * (x_{i,k} - z_k)^2。所有交互线k遍历一遍rho是惩罚参数。3.2 三步迭代更新与收敛判据ADMM每一步迭代分三步执行。第一步固定公共变量z和乘子lambda每个微网独立求解min_x L也就是求解带增广项的本地优化问题。这一步完全是并行化的不同微网之间没有信息交换。第二步更新公共变量z。因为g(z)0所以z_k的解析式是z_k_new mean(x_{i,k})这里mean是参与该条交互线的两个微网视角的平均值。更准确地说如果两个微网分别上报x_{i,k}和x_{j,k}则z_k_new (x_{i,k} - x_{j,k}) / 2。有路线容量约束时再做一次投影到容量区间内。这一步非常轻量协调层只需要做一个平均操作。第三步更新拉格朗日乘子lambda。对每个微网和每条交互线lambda lambda rho * (x_{i,k} - z_k_new)。这个更新式的含义很直观如果微网i的交互功率角度大于当前公共值说明它倾向于多送电乘子就往正方向调整在下一轮迭代中惩罚它偏离公共值。收敛判据方面原始残差r_prim sqrt(sum((x_{i,k} - z_k)^2))对偶残差s_dual sqrt(sum((-rho * (z_k_new - z_k_old))^2))。当两个残差同时小于容差时可以认为收敛。实际调试中我习惯同时打印目标函数值和残差如果目标函数稳定但残差还在小幅波动说明收敛精度已经足够工程使用。3.3 Matlab主程序框架Matlab主程序流程比较固定先设置参数初始化变量然后进入主迭代循环最后输出结果。核心代码如下。% 初始化 z_new zeros(E, T); % 公共变量E条交互线T个时段 z_old z_new; lambda zeros(2*E, T); % 每个微网视角的乘子 x_all cell(N, 1); % 每个微网的本地解 for iter 1:MaxIter % 第一步各微网独立求解本地问题 for i 1:N x_all{i} solve_subproblem(i, z_new, lambda, rho, SysParam); end z_old z_new; % 第二步更新公共变量 for e 1:E z_new(e, :) 0.5 * (x_all{from(e)}.tie(e, :) - x_all{to(e)}.tie(e, :)); z_new(e, :) min(max(z_new(e, :), -TieMax(e)), TieMax(e)); end % 第三步更新乘子 for e 1:E i from(e); j to(e); lambda(2*i-1, e, :) lambda(2*i-1, e, :) rho * (x_all{i}.tie(e, :) - z_new(e, :)); lambda(2*j-1, e, :) lambda(2*j-1, e, :) rho * (x_all{j}.tie(e, :) z_new(e, :)); end % 计算残差 r_prim 0; for e 1:E r_prim r_prim sum((x_all{from(e)}.tie(e, :) - z_new(e, :)).^2); r_prim r_prim sum((x_all{to(e)}.tie(e, :) z_new(e, :)).^2); end r_prim sqrt(r_prim); if r_prim tol iter 5 break; end end这个框架里需要注意两点。第一子问题求解函数solve_subproblem是整个程序最核心的部分它内部要根据微网i的本地参数构建H、f、A、b等矩阵并调用quadprog。第二乘子lambda维度要和变量维度严格对齐否则在更新时非常容易报维度不匹配的错。我一开始就在这个地方栽过跟头后面在5.2里细说。3.4 微网子问题的quadprog实现每个微网的子问题其实就是一个带ADMM增广项的二次规划形式是min 0.5 * x * H * x f * x满足线性等式和不等式约束。在Matlab里先定义变量顺序比如[P_g; P_ch; P_dis; SOC; P_tie1; P_tie2; ...]然后按顺序填充H矩阵和f向量。常规机组二次成本a * P_g^2对应H矩阵对角元素加2a因为quadprog的形式是0.5 * x * H * x一次成本b * P_g对应f向量加b碳交易成本e_co2 * lambda_carbon * P_g对应f向量再加lambda_carbon * e_co2。ADMM增广项0.5 * rho * (P_tie - z)^2 lambda * (P_tie - z)展开后H矩阵中对应P_tie的对角元素加rhof向量对应位置加(-rho * z - lambda)。关键代码如下。H sparse(nvar, nvar); f zeros(nvar, 1); % 常规机组成本项0.5 * a * P^2 b * P idx_g var_index.g; H(idx_g, idx_g) H(idx_g, idx_g) 2 * a_g; f(idx_g) f(idx_g) b_g; % 碳交易成本项 f(idx_g) f(idx_g) lambda_carbon * e_co2 * dt; % 储能退化成本 idx_ch var_index.ch; idx_dis var_index.dis; f(idx_ch) f(idx_ch) alpha_ch; f(idx_dis) f(idx_dis) alpha_dis; % ADMM增广项 idx_tie var_index.tie; H(idx_tie, idx_tie) H(idx_tie, idx_tie) rho; f(idx_tie) f(idx_tie) - rho * z_local - lambda_local; % 求解 options optimoptions(quadprog, Display, off); x_opt quadprog(H, f, Aineq, bineq, Aeq, beq, lb, ub, x0, options);这里最容易被忽略的是SOC递推方程要写成等式约束Aeq * x beq并且每一时段之间要耦合起来。比如一天96个时段如果变量按时段堆叠Aeq矩阵是一个大的块状矩阵需要用循环逐时段填充。4. 算例场景与结果分析4.1 算例参数设置我设计了一个三微网互联的算例拓扑结构是微网1和微网2互联微网2和微网3互联微网1和微网3不直接相连。三个微网的风光负荷特性刻意设置成互补结构微网1光伏充足但负荷较小白天有明显的富余电力微网2风电较多且夜间出力大微网3负荷最重且自有风光少是明显的“购电方”。参数上三个微网各带一台常规燃机成本系数不同。微网1的燃机容量小但成本高微网3燃机容量大但成本相对低。碳配额设置成微网1富余、微网2基本平衡、微网3紧缺的状态这样碳交易机制才能真正发挥作用。碳价基准取80元/t调度周期为24小时步长1小时储能容量统一为200 kWhSOC范围0.1到0.9初始SOC设为0.5。在ADMM参数上惩罚参数rho先取50最大迭代次数设500收敛容差tol设为1e-4。这个设置对大多数二次规划子问题都能在一个可接受的时间内收敛。4.2 分布式迭代收敛过程从实际运行结果看前20次迭代原始残差下降得很快从初始的10^2量级快速降到1以下后面40到100次迭代进入缓慢下降阶段最终在大约130次迭代后达到1e-4的收敛标准。这里有一个现象值得注意目标函数值在第10次迭代左右就已经基本稳定但交互功率的一致性残差还没有收敛。如果只看目标函数判断收敛很容易过早终止迭代导致最终微网间上报的交互功率对不上账。所以看收敛一定要同时看原始残差和对偶残差这条经验在调试中非常管用。rho对收敛速度的影响也很明显。rho取20时迭代次数增加到300次以上rho取200时前30次迭代残差下降更快但后期出现轻微震荡最终收敛到同样精度所需的总体迭代次数反而增加了。这符合ADMM的经典规律rho过小收敛慢rho过大惩罚过重导致来回波动。4.3 电能交互与碳排放结果收敛后微网1在白天光伏大发时段通过联络线向微网2送电微网2再向微网3转送一部分同时微网2在夜间风电大发时向微网1反向送电。全天下来微网3的净购电量为约420 kWh这相当于它减少了自己高成本燃机约420 kWh的发电量按微网3燃机的单位碳排放水平折算大约减少碳排放90 kg左右。碳排放配额的分配结果更贴近实际市场逻辑。微网1由于光伏出力大、燃机出力小实际排放低于配额产生了盈余微网3排放超额需要从碳市场购买配额。碳交易成本对三个微网的净收益都有影响微网1因为售出配额获得额外收入微网3因为购买配额增加了运行成本。这个结果说明碳交易机制确实会在经济信号层面引导电能交互而不是单纯靠调度指令。4.4 碳价对运行策略的影响我还专门做了碳价敏感性分析把lambda_carbon从0逐步升到200元/t观察系统整体运行策略的变化。碳价为0时所有微网只按经济成本优化微网3会倾向多用自己的燃机发电因为它的燃机成本比从微网1购电总成本更低。碳价上升到80元/t时微网3减少燃机出力增加从微网1和微网2的购电量因为购电对应的碳排放算在卖方配额里对买方的直接碳成本不敏感。碳价到150元/t以上时系统总碳排放量明显下降但总运行成本也上升了约8%到12%。这个结果揭示了一个重要权衡高碳价能推动减排但会增加用能成本。如果项目目标是研究碳市场机制对多微电网协同运行的影响这种敏感性曲线正是最有说服力的输出结果。在Matlab里只需要在主程序外加一层for循环逐个碳价运行整个ADMM迭代再把结果汇总成曲线即可。4.5 与集中式优化对比为了验证ADMM分布式求解的正确性我把同一算例的全局信息汇总起来用集中式quadprog直接求解然后把两种方式得到的系统总成本、各微网出力、交互功率做对比。结果显示ADMM收敛后的目标函数值与集中式最优值的相对偏差小于0.5%交互功率曲线也几乎重合。这个偏差主要来自收敛容差的数值精度如果进一步收紧容差到1e-6两者差异会进一步缩小。实际工程中0.5%以内的偏差完全可以接受何况集中式方案在现实中还面临信息隐私和主体自治的障碍。从工程效率上看集中式求解一个24时段的三微网问题大概需要几秒ADMM则需要迭代一百多次每次求解三个子问题总耗时约20到30秒。在算例规模较小时ADMM没有速度优势但扩展到几十个微网时ADMM的并行特性就能体现出来。我在Matlab里用parfor包住子问题求解循环后三微网算例在4核机器上明显变快微网数量越多收益越明显。5. 实际调试中的常见问题与避坑经验5.1 ADMM不收敛惩罚参数与自适应调整最常见的ADMM调试问题就是不收敛或收敛极慢。如果你发现残差曲线长时间走平先别急着怀疑算法优先检查rho的取值。rho太小原始残差下降慢需要几十上百次迭代才能进入收敛区间。rho太大局部看增广项主导目标函数残差下降快但后期振荡明显收敛精度反而难保证。一个实用的经验是先固定其他参数把rho从很小到很大做一遍扫描观察迭代次数和最终残差的变化找到中间较为稳定的区间。也可以采用自适应rho策略每若干次迭代根据原始残差和对偶残差的比例调整rho。Matlab实现起来很简单加一个判断即可。另一个容易被忽略的点是残差归一化。如果变量数量级相差很大比如功率变量是10^3量级乘子变量是10^-2量级直接比较原始残差和对偶残差会被大数量级的项主导。我通常会在计算残差前先按各自变量的典型量级做归一化处理。5.2 模型常见错误与方向定义问题多微网建模里方向定义问题是最容易出错的。联络线功率的正负方向不同微网代码库里的约定可能完全不同。我建议在项目一开始就统一用“从微网i流向邻居j为正”并且每个微网维护一个本地映射表记录自己所有交互线路的邻居编号和本地符号。公共变量z统一采用这个约定每次更新时严格按照映射表取正负号。SOC的单位也经常搞混。储能容量若以kWh为单位而调度步长内功率乘以时间得到的是kWh两边统一后没问题。但如果你用的功率单位是kW时间单位是h那么SOC递推方程里必须乘以dt1h不要漏掉。我在调试时遇到过SOC曲线突变的情况排查到最后就是递推方程里漏乘了dt。约束冗余也不能忽视。SOC上下限和充放电功率限值在物理上应同时满足但有些场景下SOC上限与充电功率限值会发生冲突导致子问题无解。如果quadprog返回空解先检查是不是某个时间步的SOC初值、功率限值和容量参数之间不满足可行条件。5.3 Matlab实现层面的性能问题子问题求解是ADMM循环里最耗时的部分。如果每个微网都重新构造Aeq、Aineq矩阵在循环里反复分配内存几百次迭代下来性能会很差。我的做法是把每个微网的等式约束矩阵、不等式约束矩阵、上下界数组全部在循环外预先构造好子问题函数里只改动H矩阵和f向量中的ADMM相关项然后调用quadprog。另一个性能优化点是用sparse矩阵。多时段问题的Aeq矩阵很大但非常稀疏直接用full矩阵会占用大量内存。改成sparse后三微网96时段问题的内存占用可以降到原来的十分之一以下。如果微网数量多把子问题求解循环改成parfor可以明显提速。但要注意parfor里不能有global变量子问题函数需要的参数必须显式传入。另外第一次跑parfor有进程池启动开销微网数量少于5个时parfor反而不如普通for循环快。5.4 常见问题速查表现象可能原因排查与解决办法残差下降极慢rho取值过小增大rho或做rho扫描测试残差振荡不收敛rho取值过大减小rho或采用自适应rho目标函数稳定但交互功率对不上过早按目标函数判收敛同时监控原始残差以残差为准子问题无解变量约束冲突检查SOC初值、功率限值、联络线容量交互功率方向反了联络线正方向约定不一致统一本地映射表符号检查z更新公式代码越跑越慢每轮重新构造大矩阵循环外预分配矩阵使用sparse并行后反而更慢微网数量少进程池开销大微网数超过5个再用parfor碳交易项没有效果碳配额设置过宽松调整配额使部分微网超额、部分盈余5.3 关于“分布式”的几个认知误区最后补充一个特别想说的点ADMM分布式并不等于完全没有协调者。公共变量z的更新需要有一个协调者或点对点通信机制只是这个协调者不需要知道每个微网的内部模型参数只需要收集交互功率的目标值并做平均。这一点经常被误解。有些人认为ADMM之后每个微网就完全自治、没有任何中心了其实严格来说它消除的是对“集中式全局模型”的依赖而不是对“消息传递”的依赖。在Matlab仿真中这个协调者就是一个简单的主进程负责汇总各子问题的交互功率并更新z和lambda。在真实系统中它可以是轻量级的边缘服务器也可以是相邻微网之间的点对点通信协议。另一个误区是ADMM一定比集中式结果更好。实际上从数学角度ADMM收敛到的最优解和集中式求解的是同一个凸问题的最优解不存在ADMM结果更优的说法。ADMM的优势在于求解架构的分布式特性而不是解的质量。在写论文或项目报告时把这一点表述清楚非常重要否则评审容易追问“你的ADMM凭什么比集中式总成本更低”。这个项目做完后我最大的体会是ADMM本身是一个清晰的三步迭代真正的复杂度全在模型建模和代码细节里。把微网内部约束建准确、把交互方向约定统一、把rho调合适剩下的算法落地反而水到渠成。如果你正在做多微电网相关的分布式优化不用被一堆公式吓住先在Matlab里搭一个三微网小算例跑通闭环再逐步扩大规模是最快的路径。
返回列表