ARTICLE DETAIL

资讯详情

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

含风光发电的概率潮流计算:Matlab蒙特卡洛实现与避坑指南

含风光发电的概率潮流计算:Matlab蒙特卡洛实现与避坑指南 做含风光发电的概率潮流计算时我踩过的那些坑Matlab一步步复现给你看。先交代背景。前段时间帮一个做微电网规划的朋友跑了一批仿真核心就是标题里这个事含风光发电的概率潮流计算。他那边前期方案已经定了风光渗透率大概在30%左右但电网调度那边一直有个疑问——光伏和风电出力是波动的你按一个固定值算潮流算出来的电压和支路功率到底靠不靠谱这个问题单靠确定性潮流算不出来所以才需要概率潮流。概率潮流听着唬人本质就是把输入从一个确定值变成一组概率分布然后通过大量采样或解析方法让输出也变成概率分布。最终你告诉调度这条母线电压在0.95到1.05之间的概率是97.3%而不是干巴巴一句电压是1.02。这种信息在规划和调度里非常实用。这篇文章我用Matlab完整走一遍风速怎么抽样、光照怎么建模、风电光伏出力怎么折算、潮流怎么反复求解、结果怎么统计。中间会穿插我实际踩过的坑和调整思路代码基于Matlab R2023a编写需要的工具箱是Matpower和Statistics and Machine Learning Toolbox。Matlab版本建议用R2021b以上太老的版本对某些概率分布函数支持不全。1. 整体设计思路为什么选蒙特卡洛而不是其它方法1.1 概率潮流到底在解决什么问题传统潮流计算也就是我们熟悉的牛拉法或PQ分解法所有输入都是确定值负荷是1000kW就是1000kW发电机出力是500kW就是500kW。但实际电网里风电场出力一会儿300kW一会儿800kW光伏中午冲到峰值、傍晚骤降这些都是随机变量。你拿一个固定值去算算出某条线路潮流是450kW但实际可能一会儿350一会儿550调度按哪个值决策概率潮流的思路是既然输入是随机变量那就让输出也成为随机变量。通过对风光出力和负荷的概率分布进行采样跑几百上千次潮流最后统计出每个节点电压幅值、每支路潮流的均值、标准差、概率分布曲线甚至算出越限概率。这样调度看到的不再是一个点而是一个区间相应概率决策依据就完整得多。1.2 蒙特卡洛模拟法为什么适合做这件事概率潮流主流方法分三类蒙特卡洛模拟法、解析法如两点估计法、Gram-Charlier级数展开、近似法如无迹变换。我最终选了蒙特卡洛原因很实际。蒙特卡洛的逻辑最简单对每个随机输入按照它的概率分布抽一个值组成一组完整的潮流输入跑一次确定性潮流得到一组输出重复几千次得到的输出集合就是输出的概率分布。这个方法的优点是完全不依赖潮流方程是否线性——牛拉法本身处理非线性方程蒙特卡洛只是把潮流方程当黑箱反复调用因此兼容性极强。缺点也直观要跑几千次潮流计算量大。解析法里比较有代表性的两点估计法PEM只用2n1次潮流计算就能得到各阶矩速度快得多。但PEM的前提是能通过输入的前几阶矩近似输出的分布遇到强非线性、重尾分布时会失真。实际项目里我不太愿意冒险去做这种隐性假设。所以我的建议很明确如果你是一次性离线分析场景数量几十到上百个蒙特卡洛完全够用如果你要做在线实时评估、对单次计算速度有硬性要求再去考虑PEM或半不变量法。这篇文章全部基于蒙特卡洛展开。1.3 算例系统的选择与准备我用的是Matpower自带的case33bw一个33节点配电网系统基准电压12.66kV。选它的原因结构经典、节点多、结果便于验证很多论文和开源项目都用它做概率潮流测试。如果你的研究对象是输电网比如IEEE 30节点或118节点系统方法一模一样只是数据文件换一下。具体改造方案在原来33节点系统基础上接入两类分布式电源——风电机组接在节点18光伏阵列接在节点22。同时把原来固定的负荷改成服从正态分布的随机负荷均值取原case数据标准差取均值的5%到10%。这样整个系统里就有三类随机源风电、光伏、负荷基本覆盖了配电网概率潮流的主要场景。2. 风光出力的概率建模这是整个仿真的地基2.1 风速与风电出力模型别把分布函数搞混了风速的长期统计特性在工程界普遍用双参数Weibull分布描述。这个分布的概率密度函数是f(v) (k/c) * (v/c)^(k-1) * exp(-(v/c)^k)其中v是风速k是形状参数无量纲一般在1.5到3之间决定分布形状c是尺度参数单位m/s和平均风速相关。实际工程里沿海风电场k取2.0左右内陆风电场取2.2到2.6的更多。我仿真时取了比较典型的k2.0、c8.5对应平均风速约7.5m/s属于中等等级风资源。风速抽到之后要折算成风电出力。这个环节我第一次做的时候踩了坑差点直接把风速作为功率用。风电出力有一个标准的分段函数关系风速低于切入风速(v_in通常3m/s)时风机不出力风速在切入风速和额定风速(v_r通常12m/s左右)之间出力近似线性上升风速达到额定风速到切出风速(v_out通常25m/s)之间出力恒定为额定功率风速超过切出风速保护停机出力为0代码里我把这个关系写成了一个独立函数方便反复调用function P_wt windPower(v, v_in, v_r, v_out, P_r) % v: 风速样本 (m/s) % P_r: 额定功率 (kW) P_wt zeros(size(v)); % 线性段 idx (v v_in) (v v_r); P_wt(idx) P_r .* (v(idx) - v_in) / (v_r - v_in); % 额定段 idx (v v_r) (v v_out); P_wt(idx) P_r; % 低于切入或高于切出出力为0 end注意几个工程细节。额定风速的选取直接影响曲线形状我见过有人图省事直接把切入风速设成0算出来明显偏乐观。另外风机功率曲线存在最大功率追踪区域并非严格线性但普通潮流分析用线性近似已经足够没必要搬精确功率曲线进来增加复杂度。2.2 光照强度与光伏出力模型光伏出力和光照强度直接相关。归一化后的光照强度(实际辐照度/标准辐照度1000W/m²)在工程上常用Beta分布描述。Beta分布有两个形状参数a和b典型取值范围在0.5到4之间。a和b的取值可以按式(ab)μ、aμ²*(1-μ)/σ²-μ来标定其中μ是平均归一化辐照度σ是标准差。我用的是μ0.5、σ0.2反解出a和b实测效果还行。光伏出力的计算式P_pv η * S * r * 1000其中η是光伏板综合效率含逆变器效率一般取0.85到0.9S是光伏阵列总面积(m²)r是归一化辐照度。如果面板朝向固定、不考虑温度效应这个线性表达式完全够用。我写成了向量化代码一次计算一整批样本的功率function P_pv pvPower(r, eta, S) % r: 归一化辐照度样本 % eta: 综合效率 % S: 光伏阵列总面积 (m^2) P_pv eta * S * r * 1000; % kW end这里有个关键坑Beta分布的随机数生成Matlab里是betarnd(a, b, n, 1)我当时用的是betarnd(2, 3, 10000, 1)后来发现均值偏了原因是参数设错了。正确做法是先算好均值对应关系再取参数。另外光伏逆变器在低辐照度下效率会明显下降但概率潮流一般忽略这个细节误差在可接受范围内。2.3 随机变量之间的相关性怎么处理风光出力不独立这是做概率潮流最容易忽略的问题。比如同一区域的风电场风速相关性很强风和光在某些地区还有负相关性——白天光照强但风速往往较小夜间反过来。如果不处理相关性仿真结果会高估系统波动范围给出偏保守但失真的结论。处理相关性我用了Cholesky分解法原理不复杂、实现方便。假设你有一个相关系数矩阵C比如风-光相关系数设为0.3风-风相关系数设为0.7先求C的Cholesky分解C LL然后对独立标准正态样本Z做变换Y LZ得到的Y就带有所需相关性。关键在于从任意分布抽样出的样本不是正态的需要先用逆正态变换把样本映射到标准正态空间处理完相关性后再映射回来。这一步在Copula理论里叫Nataf变换。我在项目里简化了风速样本先通过norminv变成标准正态光伏的Beta样本也做同样处理再施加Cholesky分解最后用normcdf映射回均匀分布最后反变换得到带相关性的风速和辐照度序列。如果只想快速验证可以先不做相关性但结果要注明假设独立不然后续分析会出错。3. Matlab实操全流程从采样到统计一次走通3.1 程序框架与初始化整个程序结构分四块初始化参数、生成随机样本、潮流循环计算、结果统计与画图。先看初始化部分% 初始化 clear; clc; close all; addpath(path/to/matpower); % 换成你的matpower路径 % 加载系统数据 mpc loadcase(case33bw); baseMVA mpc.baseMVA; % 随机源参数 % 风电 k_w 2.0; % Weibull形状参数 c_w 8.5; % Weibull尺度参数 v_in 3; v_r 12; v_out 25; % 切入、额定、切出风速 P_wt_r 500; % 风机额定功率 kW % 光伏 eta_pv 0.88; % 综合效率 S_pv 3000; % 光伏阵列面积 m^2 a_beta 2.5; b_beta 2.5; % Beta分布参数 % 负荷波动 mu_load 1.0; % 均值系数 sigma_load 0.08; % 标准差系数 % 蒙特卡洛采样次数 N_mc 5000;几个参数我说下理由。采样次数N_mc我取了5000这是精度和时间的折中。少到1000次分布曲线细节会毛糙算出的95%分位数不稳定多到20000次结果不会明显变好但算33节点系统要跑很久。对33节点配电网而言5000次牛拉法潮流大概一到三分钟可以接受。3.2 随机样本生成模块样本生成是核心我把风速、光照、负荷三个部分的代码分别列出来每个都写成向量化操作避免在循环里逐个抽随机数速度差好几倍。风速样本生成% 生成风速样本 (Weibull分布) v_samples wblrnd(c_w, k_w, N_mc, 1); % 折算成风电出力 P_wt windPower(v_samples, v_in, v_r, v_out, P_wt_r);光照样本生成% 生成归一化辐照度样本 (Beta分布) r_samples betarnd(a_beta, b_beta, N_mc, 1); % 折算成光伏出力 P_pv pvPower(r_samples, eta_pv, S_pv);负荷样本生成。每个节点的有功负荷乘一个随机系数% 负荷波动样本 (正态分布) load_factor 1 sigma_load * randn(N_mc, 1); % 注意这里是对所有节点用同一个系数代表系统整体负荷水平波动 % 如果想要每个节点独立波动需要对每个节点单独生成样本这里有个细节值得说负荷波动到底是整体波动还是各节点独立波动取决于场景。配电网里居民负荷、商业负荷往往有同步性我选了整体波动如果你要研究分布式负荷独立波动的影响就要对每个负荷节点单独抽样。两种做法的方差输出差别很大要根据实际场景选。3.3 潮流计算主循环这是最容易出错的地方主循环逻辑不复杂但有个细节非常关键每次计算前必须恢复mpc原始数据不然上一次修改的出力值会残留在结构体里造成累积误差。我一开始没注意跑了2000次发现结果漂移排查半天才找到问题。% 预分配结果存储 V_results zeros(N_mc, size(mpc.bus, 1)); % 电压幅值 P_branch_results zeros(N_mc, size(mpc.branch, 1)); % 支路有功 Q_branch_results zeros(N_mc, size(mpc.branch, 1)); % 支路无功 % 主循环 for i 1:N_mc % 每次重新加载原始系统 mpc_i loadcase(case33bw); % 修改节点18接入风电出力 (节点编号要看case33bw实际数据) % 找到节点18的索引 idx_wind find(mpc_i.bus(:, 1) 18); mpc_i.bus(idx_wind, 3) P_wt(i); % 有功出力 mpc_i.bus(idx_wind, 4) 0; % 无功出力简化设0 % 修改节点22接入光伏出力 idx_pv find(mpc_i.bus(:, 1) 22); mpc_i.bus(idx_pv, 3) P_pv(i); mpc_i.bus(idx_pv, 4) 0; % 修改负荷 (所有PQ节点) load_nodes find(mpc_i.bus(:, 2) 1); % PQ节点类型 mpc_i.bus(load_nodes, 3) mpc_i.bus(load_nodes, 3) .* load_factor(i); mpc_i.bus(load_nodes, 4) mpc_i.bus(load_nodes, 4) .* load_factor(i); % 运行潮流计算 results runpf(mpc_i, mpoption(verbose, 0)); % 检查收敛性 if results.success ~ 1 warning(第 %d 次潮流不收敛跳过本次样本, i); continue; end % 提取结果 V_results(i, :) results.bus(:, 8); % 电压幅值 P_branch_results(i, :) results.branch(:, 14); % 支路有功 Q_branch_results(i, :) results.branch(:, 15); % 支路无功 end这里有个简化处理要说明我把风光电源当作PQ节点处理也就是出力恒定、功率因数给定。严格来说风电和光伏如果采用恒电压控制应该建模成PV节点但这会涉及无功出力上限问题在配电网场景里分布式电源通常按恒功率因数运行所以PQ处理是合理的。如果你想模拟恒电压模式需要修改节点类型和无功出力上下限代码复杂度会上升。另外一个经验runpf里用mpoption(verbose, 0)关掉控制台输出不然5000次潮流会把命令窗口刷爆严重影响运行速度。3.4 结果统计与可视化计算完之后统计环节是概率潮流的临门一脚。我最常做的几件事电压幅值的均值、标准差、95%概率区间以及越限概率。以节点电压为例% 筛选收敛的样本 V_conv V_results(~isnan(V_results(:, 1)), :); % 计算每个节点的电压统计量 V_mean mean(V_conv, 1); V_std std(V_conv, 0, 1); V_p5 prctile(V_conv, 5, 1); % 5%分位数 V_p95 prctile(V_conv, 95, 1); % 95%分位数 % 电压越限概率 (以0.95到1.05为正常范围具体按标准) lower_lim 0.95; upper_lim 1.05; V_limit_prob sum(V_conv lower_lim | V_conv upper_lim, 1) / size(V_conv, 1);绘图部分我一般输出三张图各节点电压均值±标准差阴影带、某个关键节点比如18号节点电压幅值直方图、某条关键支路潮流的累积概率分布曲线。直方图用histogram函数累积概率曲线用ecdf函数。这些图在项目报告里比任何文字描述都有说服力。% 画节点18电压幅值直方图 figure; histogram(V_conv(:, idx_wind), 50, Normalization, pdf); xlabel(电压幅值 (p.u.)); ylabel(概率密度); title(节点18电压幅值概率分布); grid on;4. 常见问题与排查技巧实录4.1 问题速查表先给一个速查表后面逐个展开讲现象可能原因解决方案潮流频繁不收敛风光出力设置过猛导致系统无解检查出力是否超过系统承载能力适当降低出力或增加无功支撑电压波动区间异常大负荷标准差设太大sigma_load从8%降到3%-5%调试结果分布偏斜严重忽略了风光间相关性加入Cholesky分解处理相关性计算速度极慢循环里频繁打开数据文件改用mpc结构体深拷贝或一次性加载后复制随机样本均值偏移分布参数标定错误用mean(wblrnd(...))对照理论均值检校统计结果含NaN部分样本潮流不收敛收敛性判断后再统计NaN样本直接剔除4.2 详细排查经验第一个要重点讲的是收敛性问题。配电网接入大量分布式电源后系统有时会失去可解性尤其当风电出力在某次抽样中恰好撞上负荷低谷时会出现电压越限甚至潮流发散。我在调试初期设置了5000次采样结果有30多次不收敛差不多0.6%的不收敛率。这些不收敛样本如果直接计入统计会把均值拉偏标准差吹大。我的处理是每次潮流结束都检查results.success不收敛的样本标记为NaN最后统计前统一剔除。同时我会打印不收敛次数占比如果超过2%说明系统配置有问题需要返回检查电源接入容量。第二个值得说的是Matlab版本兼容性问题。cholesky分解函数是chol所有版本都有。但wblrnd、betarnd这些分布函数需要Statistics and Machine Learning Toolbox有些精简版Matlab没装会直接报错。建议做之前先跑一下exist(wblrnd, file)检查工具箱是否可用。第三个是关于mpc数据格式的坑。Matpower的mpc结构体中bus矩阵第3列是有功出力发电机节点但PQ负荷节点的有功是存在第3列的负值。我之前修改负荷时直接覆盖了第3列导致部分节点的负荷被误当成发电出力结果完全跑偏。正确做法是只修改属于负荷节点的行而且要和发电机节点区分。最后提一个容易被忽视但非常重要的点随机数种子。我在写程序时特意用rng(42)固定了随机源。这样做的原因是同样的随机数种子别人复现你的代码时能得到完全一样的结果。科学研究里可复现是底线如果你不加种子每次运行结果都不同后面调试和写报告都会抓瞎。这是个习惯问题但非常重要。5. 一些经验总结写到这里整个含风光的概率潮流Matlab实现就完整了。从我实际操作出的经验来看蒙特卡洛加Matpower的组合适合绝大多数配电网概率潮流分析场景胜在简单直接、方便改造。但有几个边界条件要说清楚一是采样次数和精度之间存在对数关系5000次和10000次的差别往往没有想象中那么大不用盲目加大二是概率潮流只刻画了输入随机性带来的输出不确定性并没有考虑拓扑变化、故障等离散事件那是另一个范畴的可靠性评估要做的事三是风光出力的概率建模是整条链路里误差最大的环节与其花大量时间优化潮流求解器不如多花心思收集真实风速和辐照度数据把Weibull和Beta的参数标定准——这才是整个概率潮流精度的瓶颈所在。如果你要在自己的项目里直接用这套代码建议从case33bw跑通整个流程后再换你自己的网络数据。网络拓扑变了电源接入节点的位置和容量都要跟着改尤其要注意修改节点编号。另外如果后续想把模型升级到考虑时序相关性、多风电场之间空间相关性可以在现有框架上叠加Copula或者时间序列模型这个方向完全可以继续深挖。
返回列表