ARTICLE DETAIL

资讯详情

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

基于广义多项式混沌法的电力系统随机潮流计算与电压稳定分析

基于广义多项式混沌法的电力系统随机潮流计算与电压稳定分析 简介本资源面向具备电力系统与概率论基础的研究人员、工程师及高校教师聚焦广义多项式混沌法gPC在电力系统随机潮流中的应用解决风光并网带来的不确定性问题。内容涵盖gPC理论基础、正交多项式逼近、随机Galerkin法转化确定性方程组、统计特征提取及蒙特卡洛验证并针对风电场相关性建模Cholesky分解与光伏Beta分布建模给出实现思路还讨论了不连续场景下的收敛性与基函数选择策略。资源包为1个docx文档约48KB内含详细理论推导与Python代码实现及中文注释便于读者对照复现核心步骤。目前已有73人学习。通过多个IEEE标准系统算例读者可掌握gPC法在保证精度的同时提升计算效率的完整方案并评估其与蒙特卡洛、点估计法的优劣适用于高比例可再生能源接入下的随机潮流分析与工程实践。1. 风光并网后电压为什么忽高忽低随机潮流要算的到底是什么光伏电站中午满发、傍晚骤降风电场凌晨大发、白天切出这种分钟级的功率波动让配电网电压像坐过山车。传统确定性潮流只给一个断面算出来的电压幅值要么偏乐观要么偏保守调度员拿它做决策心里没底。电力系统随机潮流要解决的就是这个问题把风光出力、负荷波动当成随机变量算出节点电压的概率分布——均值、标准差、越限概率而不是一个孤零零的数字。广义多项式混沌法generalized Polynomial ChaosgPC是目前处理这类问题性价比很高的方案它用正交多项式基函数把随机响应展开成谱形式配合稀疏网格或配点法几十次确定性潮流就能得到完整的统计特征比蒙特卡洛快两到三个数量级。这套方法适合做新能源接入评估、无功电压优化、储能选址定容的工程师前提是你得接受一点数学门槛——但代码写出来之后调参和排错才是真正花时间的地方。2. 广义多项式混沌法为什么能替代蒙特卡洛从谱展开到配点采样2.1 gPC 的核心思想与 Wiener-Askey 框架gPC 的出发点很朴素如果一个随机输出 $Y$ 是输入随机变量 $\xi$ 的光滑函数那它就可以用一组关于 $\xi$ 的正交多项式展开。写成谱形式就是 $Y(\xi) \sum_{k0}^{P} c_k \Phi_k(\xi)$其中 $\Phi_k$ 是与输入分布匹配的正交多项式基$c_k$ 是待定系数。Wiener-Askey 框架给出了匹配规则高斯输入配 Hermite 多项式均匀输入配 Legendre 多项式Beta 分布配 Jacobi 多项式。风光出力通常用 Beta 分布描述光伏和 Weibull 分布描述风速严格来说 Weibull 不在经典 Askey 框架里工程上常见做法是先做等概率变换把 Weibull 映射到标准正态或均匀空间再用对应的 Hermite 或 Legendre 基。这一步变换的精度直接决定后面统计矩的准确度我一般会先画一张 Q-Q 图确认变换后的样本确实服从目标分布。展开阶数 $p$ 和随机变量维数 $d$ 决定了基函数个数 $P1 \binom{pd}{p}$。举个例子$d6$3 个风电场有功 3 个光伏有功$p3$基函数个数是 $\binom{9}{3}84$。如果直接做全张量积配点每个维度取 4 个配点就是 $4^64096$ 次潮流计算对上千节点系统来说不可接受。所以实际工程里必须用稀疏网格或 Smolyak 配点把次数压下来。2.2 稀疏网格配点与系数求解从 4096 次降到 85 次Smolyak 稀疏网格的思路是只保留张量积中“权重高”的配点组合丢弃那些对积分贡献极小的高阶交叉项。以一维 Gauss-Legendre 配点为基础构造多维稀疏网格的 Python 实现如下import numpy as np from itertools import product def smolyak_grid(d, level): 构造 d 维、level 阶的 Smolyak 稀疏网格配点与权重。 基于一维 Gauss-Legendre 配点适用于均匀分布输入。 from numpy.polynomial.legendre import leggauss # 一维配点每个 level 对应不同点数 def univariate_rule(l): n 2**l 1 if l 0 else 1 x, w leggauss(n) return x, w grid_points [] grid_weights [] # Smolyak 求和|i| level d - 1 的组合 def index_set(d, level): idx [] for combo in product(range(level 1), repeatd): if sum(combo) level d - 1: idx.append(combo) return idx for combo in index_set(d, level): # 每个维度取对应的一维规则 rules [univariate_rule(l) for l in combo] points_1d [r[0] for r in rules] weights_1d [r[1] for r in rules] # 张量积组合 for pt in product(*points_1d): grid_points.append(pt) for wt in product(*weights_1d): w_prod np.prod(wt) # Smolyak 系数符号 sign (-1)**(level d - 1 - sum(combo)) from math import comb coeff sign * comb(d - 1, level d - 1 - sum(combo)) grid_weights.append(coeff * w_prod) return np.array(grid_points), np.array(grid_weights) # 示例6 维level2 pts, wts smolyak_grid(6, 2) print(f配点数: {len(pts)}, 权重和: {wts.sum():.6f})这段代码的关键在index_set函数它只保留各维度阶数之和不超过level d - 1的组合这正是 Smolyak 公式的约束条件。level参数控制精度——level 每加 1配点数大约增加一个多项式因子但远小于全张量积的指数增长。对于 $d6$、level2 的情况配点数通常在 85 左右意味着只需 85 次确定性潮流就能完成展开。权重里的sign和comb是 Smolyak 构造的符号修正项少了它积分结果会偏。配点确定后系数 $c_k$ 通过伪谱投影或回归求解。伪谱投影用数值积分$c_k \frac{1}{\gamma_k} \sum_{i1}^{Q} w_i Y(\xi_i) \Phi_k(\xi_i)$其中 $\gamma_k$ 是基函数的归一化常数。回归法则是解一个最小二乘问题 $\mathbf{Y} \mathbf{\Phi} \mathbf{c}$当配点数大于基函数个数时用最小二乘小于时用稀疏回归如 LARS。我一般用伪谱投影因为权重已经算好了直接矩阵乘法就行不用调正则化参数。2.3 从 gPC 系数到电压统计特征均值、方差、越限概率拿到系数 $c_k$ 之后统计矩几乎是白送的。由于基函数正交均值就是 $c_0$方差是 $\sum_{k1}^{P} c_k^2 |\Phi_k|^2$。电压越限概率则需要从展开式重构样本生成大量 $\xi$ 样本代入 $Y(\xi) \sum c_k \Phi_k(\xi)$ 得到电压样本再统计超过上限或低于下限的比例。这一步的计算量可以忽略不计因为只是多项式求值。def voltage_statistics(coeffs, basis_funcs, n_samples100000): 从 gPC 系数计算电压均值、标准差和越限概率。 coeffs: gPC 系数数组coeffs[0] 为均值项 basis_funcs: 基函数列表每个元素可调用 # 生成标准正态样本假设已做等概率变换 xi np.random.randn(n_samples, len(basis_funcs[0].dim) if hasattr(basis_funcs[0], dim) else 1) # 重构电压样本 Y_samples np.zeros(n_samples) for k, c in enumerate(coeffs): Y_samples c * basis_funcs[k](xi) mean_v Y_samples.mean() std_v Y_samples.std() # 假设电压上限 1.05 p.u.下限 0.95 p.u. p_over (Y_samples 1.05).mean() p_under (Y_samples 0.95).mean() return mean_v, std_v, p_over, p_under这里basis_funcs需要根据实际输入分布构造如果是 Hermite 基可以用numpy.polynomial.hermite.hermval配合多指标索引生成。n_samples取 10 万足够稳定再大对精度提升有限。越限概率的阈值 1.05 和 0.95 是标幺值实际工程中要根据电压等级和导则调整。3. 风光并网场景怎么建模输入随机变量的选取与相关性处理3.1 光伏与风电出力的概率分布拟合光伏有功出力在白天时段通常用 Beta 分布拟合形状参数 $\alpha$ 和 $\beta$ 由历史出力数据的均值和方差反推。风速用 Weibull 分布形状参数 $k$ 一般在 1.8 到 2.5 之间尺度参数 $\lambda$ 由平均风速决定。风机出力还要经过功率曲线转换这部分是非线性的但 gPC 处理非线性映射没问题只要映射后的输出仍然是输入的“光滑”函数——功率曲线的死区和额定区会导致分段光滑展开阶数需要适当提高。import numpy as np from scipy.stats import beta, weibull_min def fit_pv_beta(mean_pu, std_pu): 由光伏出力均值和标准差反推 Beta 分布参数 # 矩估计alpha mean * (mean*(1-mean)/std^2 - 1) common mean_pu * (1 - mean_pu) / std_pu**2 - 1 alpha mean_pu * common beta_param (1 - mean_pu) * common return alpha, beta_param def wind_power_curve(v, v_in3, v_rated12, v_out25, p_rated1.0): 简化风机功率曲线输出标幺值 if v v_in or v v_out: return 0.0 elif v v_rated: # 三次方段 return p_rated * (v**3 - v_in**3) / (v_rated**3 - v_in**3) else: return p_rated # 示例拟合光伏 Beta 参数 alpha, beta_p fit_pv_beta(0.45, 0.15) print(fBeta 参数: alpha{alpha:.3f}, beta{beta_p:.3f})fit_pv_beta用的是矩估计比最大似然快对于工程精度足够。wind_power_curve里的切入风速 3 m/s、额定 12 m/s、切出 25 m/s 是陆上风电的典型值海上风电切入风速可以降到 2.5 m/s。这些参数要根据实际风场数据标定不能直接抄。3.2 空间相关性Copula 与 Nataf 变换的工程取舍同一风带里的多个风电场出力高度相关光伏电站之间也有云层移动带来的相关性。忽略相关性会低估电压波动的方差导致越限概率算偏小。工程上有两条路Nataf 变换和 Copula。Nataf 假设各变量边缘分布已知通过相关系数矩阵做高斯 Copula 映射实现简单适合线性相关较强的情况。Copula 更灵活可以选 t-Copula 捕捉尾部相关但参数估计需要更多数据。我一般先用 Nataf因为 gPC 的输入要求是独立随机变量Nataf 变换后正好得到独立标准正态空间直接接 Hermite 基。如果残差检验发现尾部拟合差再换 t-Copula 并配合 Rosenblatt 变换。Nataf 的核心是解一个隐式方程修正相关系数$\rho_{ij}^Z \rho_{ij}^X \cdot \frac{E[\xi_i \xi_j]}{\sigma_i \sigma_j}$其中 $\xi$ 是标准正态变量。这个修正因子有解析近似公式不用迭代。def nataf_transform(samples_corr, marginal_inv_cdfs): Nataf 逆变换从相关标准正态样本生成相关非正态样本。 samples_corr: 相关系数矩阵对应的标准正态样本 (n, d) marginal_inv_cdfs: 各维边缘分布的逆 CDF 函数列表 n, d samples_corr.shape # 对每维做标准正态 CDF 变换到均匀分布 from scipy.stats import norm uniform_samples norm.cdf(samples_corr) # 再用各维逆 CDF 变换到目标分布 result np.zeros_like(uniform_samples) for j in range(d): result[:, j] marginal_inv_cdfs[j](uniform_samples[:, j]) return resultmarginal_inv_cdfs里放 Beta 和 Weibull 的逆 CDFsamples_corr的相关系数矩阵要先用 Cholesky 分解生成。注意 Nataf 变换后的样本相关系数不等于原始设定值需要迭代修正但工程上差个 5% 以内可以接受。4. 代码落地从 IEEE 33 节点算例到 gPC 随机潮流完整流程4.1 确定性潮流内核前推回代与雅可比矩阵配电网通常是辐射状前推回代比牛顿-拉夫逊更稳。核心循环是从末端节点往前推电流再从根节点往后推电压反复直到收敛。对于 gPC 配点法每个配点都要跑一次确定性潮流所以内核必须快。用 numpy 向量化支路计算33 节点系统单次潮流在 1 ms 以内。import numpy as np def backward_forward_sweep(net, S_load, V_slack1.0, tol1e-6, max_iter50): 前推回代潮流。net 包含支路和节点拓扑。 S_load: 节点注入功率 (n,)标幺值正为负荷。 返回节点电压幅值。 n len(net[bus]) V np.ones(n, dtypecomplex) * V_slack V[0] V_slack # 根节点 for it in range(max_iter): V_old V.copy() # 前推从末端到根节点计算支路电流 I_branch np.zeros(len(net[branch]), dtypecomplex) for k in range(len(net[branch]) - 1, -1, -1): br net[branch][k] j br[to] # 节点电流 负荷电流 子支路电流之和 I_node np.conj(S_load[j] / V[j]) if abs(V[j]) 1e-8 else 0 I_branch[k] I_node sum(I_branch[m] for m in br[children]) # 回代从根节点到末端更新电压 for k in range(len(net[branch])): br net[branch][k] i, j br[from], br[to] V[j] V[i] - br[Z] * I_branch[k] if np.max(np.abs(V - V_old)) tol: break return np.abs(V)net[branch]里每个支路要存from、to、Z和children下游支路索引列表。S_load是节点注入功率光伏和风电按负负荷处理。收敛判据用电压变化的最大值tol1e-6对标幺值足够。4.2 gPC 配点循环与系数计算把稀疏网格配点映射到实际随机变量空间逐点跑潮流收集电压响应再投影求系数。def gpc_random_power_flow(net, base_load, pv_params, wind_params, level2): gPC 随机潮流主流程。 base_load: 基础负荷 (n,) pv_params: 光伏 Beta 分布参数列表 [(alpha, beta), ...] wind_params: 风电 Weibull 参数列表 [(k, lambda), ...] d len(pv_params) len(wind_params) pts, wts smolyak_grid(d, level) # 将 [-1,1] 配点映射到各随机变量的分位点 from scipy.stats import beta as beta_dist, weibull_min voltage_samples [] for pt in pts: # 映射到均匀分布再转目标分布 u (pt 1) / 2 # [-1,1] - [0,1] pv_powers [] for j, (a, b) in enumerate(pv_params): pv_powers.append(beta_dist.ppf(u[j], a, b)) wind_powers [] for j, (k, lam) in enumerate(wind_params): v weibull_min.ppf(u[len(pv_params) j], k, scalelam) wind_powers.append(wind_power_curve(v)) # 构造节点注入基础负荷 - 新能源出力 S base_load.copy() # 假设新能源接在特定节点这里简化处理 for idx, p in enumerate(pv_powers wind_powers): S[net[renew_bus][idx]] - p V backward_forward_sweep(net, S) voltage_samples.append(V) voltage_samples np.array(voltage_samples) # (Q, n) # 伪谱投影求系数以第一个节点电压为例 # 需要构造 Hermite 基函数此处省略基函数生成细节 # coeffs project_to_gpc(voltage_samples[:, 0], pts, wts) return voltage_samples, pts, wtsnet[renew_bus]是新能源接入节点列表。beta_dist.ppf和weibull_min.ppf把均匀分位点转成实际出力。注意配点pt是在 $[-1,1]$ 上的 Legendre 节点映射到 $[0,1]$ 均匀分布后再做逆变换。voltage_samples的每一行是一个配点下的全节点电压后续用投影公式求系数。4.3 结果验证与 10000 次蒙特卡洛的对比验证 gPC 结果最直接的方法就是跑蒙特卡洛。10000 次前推回代在 33 节点系统上大约几十秒可以接受。对比均值和标准差如果 gPC 的误差在 2% 以内说明展开阶数和配点 level 够了。def monte_carlo_validation(net, base_load, pv_params, wind_params, n_mc10000): 蒙特卡洛基准用于验证 gPC 精度 from scipy.stats import beta as beta_dist, weibull_min voltage_mc [] for _ in range(n_mc): S base_load.copy() for j, (a, b) in enumerate(pv_params): p beta_dist.rvs(a, b) S[net[renew_bus][j]] - p for j, (k, lam) in enumerate(wind_params): v weibull_min.rvs(k, scalelam) p wind_power_curve(v) S[net[renew_bus][len(pv_params) j]] - p V backward_forward_sweep(net, S) voltage_mc.append(V) voltage_mc np.array(voltage_mc) return voltage_mc.mean(axis0), voltage_mc.std(axis0)对比时重点看电压最低节点的均值和标准差以及越限概率。如果 gPC 的均值偏差大通常是展开阶数不够如果标准差偏小可能是配点 level 太低或者相关性没处理好。5. 避坑与排查gPC 随机潮流翻车实录5.1 配点 level 选低了方差算出来偏小现象gPC 算出的电压标准差只有蒙特卡洛的 60%越限概率几乎为零但实际运行中确实出现过电压越限。原因Smolyak 配点的 level 决定了能精确积分的多项式阶数。level1 只能精确到 3 阶而风光出力经过功率曲线后可能产生 5 阶以上的非线性。高阶项被截断方差自然偏小。解决逐步提高 level观察标准差是否收敛。33 节点系统、6 维输入level2 通常够用level3 更稳但配点数翻倍。我一般从 level2 开始如果与蒙特卡洛偏差超过 5% 就升到 level3。5.2 Weibull 分布直接套 Hermite 基系数全乱现象风速用 Weibull 分布但没做等概率变换直接拿 Hermite 多项式展开算出来的风速均值都对不上。原因Hermite 基关于标准正态分布正交Weibull 分布的概率测度不匹配投影公式里的内积算出来不是正交的系数没有意义。解决先做等概率变换 $u F_{\text{Weibull}}(v)$再 $z \Phi^{-1}(u)$把 Weibull 样本映射到标准正态空间然后用 Hermite 基。或者直接用 Legendre 基配均匀分布把 Weibull 的逆 CDF 作用在均匀分位点上。两种做法等价选顺手的。5.3 相关性矩阵非正定Cholesky 分解报错现象多个风电场的历史数据算出来的相关系数矩阵对角线是 1但特征值有负数np.linalg.cholesky直接抛异常。原因样本量不足或者数据里有缺失值导致相关系数矩阵不满足正定性。这是小样本下的常见问题。解决用最近正定矩阵修正把负特征值截断到一个小正数再重构矩阵。或者改用 Ledoit-Wolf 收缩估计把样本协方差向对角矩阵收缩。工程上后者更省事sklearn.covariance.LedoitWolf一行搞定。5.4 功率曲线死区导致展开震荡Gibbs 现象现象风机功率曲线在切入风速附近有死区gPC 展开在死区边界出现剧烈震荡电压统计量的尾部概率算不准。原因死区是分段函数的不连续点多项式展开在不连续点附近必然出现 Gibbs 震荡阶数越高震荡越剧烈但不会消失。解决要么把死区平滑化用 Sigmoid 过渡要么在死区附近加密配点。我一般用平滑化把切入和切出风速处的阶跃换成 0.5 m/s 宽的线性过渡对统计特征影响很小但展开稳定得多。5.5 节点电压越限概率对阈值敏感算之前先确认基准现象同一组 gPC 系数用 1.05 p.u. 算越限概率是 0.3%用 1.06 p.u. 算变成 0.05%差了一个数量级。原因电压分布尾部近似指数衰减阈值稍微一动概率变化很大。如果基准值本身没对齐比如标幺值基准电压取错结果完全不可信。解决算之前先确认标幺值基准配电网通常是 10 kV 或 0.4 kV 基准。越限阈值按导则取不要自己拍。报告结果时同时给出均值和标准差让读者自己判断尾部风险。6. 进阶技巧用 gPC 系数直接做电压无功优化gPC 展开的系数不只是用来算统计量的它们本身就是电压对随机输入的灵敏度谱。$c_1$ 对应一阶灵敏度$c_2$ 对应二阶高阶系数反映非线性交互。这意味着你可以把随机优化问题转化成关于系数的确定性优化目标函数用 $c_0$均值和 $\sum c_k^2$方差的加权和约束用越限概率的 gPC 近似。这样就不用每次优化迭代都跑随机潮流计算量降一个数量级。具体做法是把无功补偿容量、变压器抽头这些控制变量也纳入优化但它们是确定性的不增加随机维数。gPC 系数对控制变量的依赖可以通过链式法则求导或者直接用有限差分。我一般用有限差分因为潮流内核已经很快了控制变量个数通常不超过 10 个差分次数可控。def gpc_based_voltage_optimization(net, base_load, pv_params, wind_params, control_buses, control_range, level2): 基于 gPC 系数的电压无功优化。 control_buses: 可控无功补偿节点列表 control_range: 每个控制变量的上下限 [(min, max), ...] from scipy.optimize import minimize def objective(controls): # 把控制变量注入网络参数 net_modified apply_controls(net, control_buses, controls) # 跑 gPC 随机潮流返回系数 voltage_samples, pts, wts gpc_random_power_flow( net_modified, base_load, pv_params, wind_params, level) # 计算均值和方差 mean_v voltage_samples.mean(axis0) var_v voltage_samples.var(axis0) # 目标最小化电压偏差 方差惩罚 return np.sum((mean_v - 1.0)**2) 0.5 * np.sum(var_v) # 优化 x0 [(lo hi) / 2 for lo, hi in control_range] bounds control_range result minimize(objective, x0, boundsbounds, methodL-BFGS-B) return result.x, result.funapply_controls把无功补偿容量转成节点注入的虚部objective里的权重 0.5 是方差惩罚系数调大让优化更保守。L-BFGS-B适合有界优化控制变量少的时候收敛很快。这个框架可以直接扩展到储能充放电优化只要把储能功率当成控制变量加进去就行。验证优化效果时别只看目标函数降了多少要拿优化后的控制变量跑一遍蒙特卡洛确认越限概率确实降了。我吃过亏gPC 系数优化出来的方案在蒙特卡洛下越限概率反而升了原因是高阶系数被截断优化器钻了空子。后来养成习惯任何 gPC 优化结果都用 5000 次蒙特卡洛复核一遍多花几十秒省得后悔。希望帮到你。本文还有配套的精品资源点击获取
返回列表