简介:该压缩包面向电力系统从业人员与风电研究者,提供基于IEEE 14节点模型的风电潮流计算与安全分析实践。内含的MATLAB脚本可实现风电机组出力的灵活配置,模拟不同风速与注入功率下的系统电压、电流、功率分布;配套数据文件则保存了模型参数与计算结果,便于直接进行静态安全评估,观察风电波动对电压、频率及功角稳定性的影响。包体共2个文件,涵盖MATLAB源程序与mat数据文件,整体仅5KB,轻量精简,适合快速开展仿真验证。目前已有161人学习下载,适合希望掌握潮流计算流程、理解风电并网稳定性的工程师与研究人员,也可作为课程设计或科研入门的实用工具。
1. 拿到 WIND1.zip 先别建模:wind farm 安全分析的第一步是读懂数据包在说什么
做风电场并网接入的工程师,大概率都见过这类文件名:WIND1.zip。它看着像个普通算例包,实际作用是一整套 wind farm 电气参数——35kV 集电线路、箱变、主变、风机出力曲线和并网点母线,打包给你做风电潮流计算与安全分析用的。这类包的价值在于:风机还没并网时,就能把满发、低发、单机脱网等场景先在模型里跑一遍,回答集电线路会不会过载、并网点电压是否越限、主变 N-1 后潮流往哪走。适合刚接手风电场电气设计的人,也适合复核厂家接入报告的人。
一个反直觉的结论是:风电场安全分析里最容易出问题的通常不是 110kV 主变,而是 35kV 集电线路。它们 R/X 比值大、载流量裕度小,一遇到 N-1 就很容易超限。所以后面所有建模和扫描,我都会把重点放在集电网上,而不是只盯着升压站。
2. 先拆数据包:WIND1.zip 里的母线、线路与风机参数怎么读
2.1 数据包里通常有什么:文件类型与读卡脚本
行业里这类压缩包没有统一标准,常见做法是参考 IEEE 节点格式或 PSASP / BPA 的卡片格式,用 txt 或 csv 存放,字段顺序和编码都很随性。把 WIND1.zip 解压后当成黑匣子来体检,是最稳的心态——先别急着套用某个商业软件格式,先用一段不挑格式的脚本把所有文件读成 DataFrame,把原始字段拍平,再按电力系统习惯去识别 bus / branch / gen。
我一般会先写这个通用读卡函数,兼容逗号分隔、空格分隔和带注释行的文件:
import pandas as pd def read_card(filepath): rows = [] with open(filepath, 'r', encoding='gbk', errors='ignore') as f: for line in f: line = line.strip() if not line or line.startswith('#') or line.startswith('/'): continue rows.append([cell.strip() for cell in line.split(',')]) return pd.DataFrame(rows) bus = read_card('WIND1/bus.dat') branch = read_card('WIND1/branch.dat') gen = read_card('WIND1/gen.dat') print(bus.head()) print(branch.head())这段脚本的作用不是替你把数据读成标准电网模型,而是先把文件结构暴露出来。实际上 PSASP 的卡片经常用逗号分隔,而 BPA 用固定列宽,所以 read_card 里 split(',') 在遇到空格分隔文件时会失效。我在工程里的做法是再写一个按正则切分的版本,但第一步一定是先打印 head(),确认每列到底是什么。
读的时候有两个值得注意的参数:encoding 用 gbk 并加 errors='ignore',因为这类包常混着中文注释和乱码;跳过以 # 和 / 开头的行,因为注释里通常写着基准电压或风机型号。branch 表里最关键的字段是从母线编号到母线编号的首末端点,bus 表里最关键的是母线编号和基准电压,gen 表里最关键的是每台风机接在哪个母线上以及额定容量。
2.2 读入后的数据体检:先查基准容量、电压等级、控制模式三个数
数据读进来之后不要急着画图、跑潮流,先把三个数查清楚。第一是基准容量:数据包里的变压器阻抗、线路阻抗标幺值都是相对某个基准容量折算的,常见是 100 MVA,但也有按单台主变容量做的。如果基准容量不一致,后续所有标幺值都会失真。第二是电压等级:风电场内部通常是 35kV 集电,升压后是 110kV 或 220kV 并网,数据包里母线表会有 vn_kv 字段,要逐一核对,别把 35kV 母线当成 10kV 填进去。第三是风机控制模式:风机是 PQ 节点(给定有功和功率因数)还是 PV 节点(给定有功和电压),直接决定潮流计算里 Q 怎么处理。
这三个检查项可以落到一张核对表里:基准容量对应主变和线路阻抗的换算;电压等级对应母线表里的 vn_kv;控制模式对应 gen 表里是否给出无功上限或功率因数。我习惯在跑潮流前先打印 bus 表的 vn_kv 唯一值,和 branch 表里所有线路型号,扫一眼就知道数据包是否完整。很多新手拿到 WIND1.zip 后直接导入 MATLAB 或 pandapower,结果电压虚高、线损为负,回头查全是这里埋的雷。
3. 把风速折成功率的潮流模型:风机 PQ/PV 化与尾流修正
3.1 风速到出力:功率曲线插值的第一道折算
风电潮流计算与常规潮流最大的差异,在于发电机出力不是固定值,而是风速的函数。WIND1.zip 里如果直接给了每台风机的有功和无功,可以跳过这一步;但我见过不少版本只给风速时间序列和风机型号,需要自己按功率曲线折算。
常见的工程做法是用三段式功率曲线:风速低于切入风速或高于切出风速时机组出力为 0,额定风速以上按满发处理,切入到额定之间按三次方近似。虽然厂家会提供实测功率曲线,但在潮流计算里用三次方近似已经足够,因为集电线路过载与否主要看大风时段,而那段机组基本都在额定功率附近。
def wind_to_power(v, v_cut_in=3.0, v_rated=12.0, v_cut_out=25.0, p_rated=1.5): # 三段式风功率曲线:切入到额定之间按三次方近似,额定之后限功率,切出后停机 if v < v_cut_in or v >= v_cut_out: return 0.0 if v >= v_rated: return p_rated return p_rated * ((v - v_cut_in) / (v_rated - v_cut_in)) ** 3 for v in [3, 6, 9, 12, 25]: print(v, round(wind_to_power(v), 3))这段代码里 p_rated 的单位是 MW,代表单台风机额定容量,1.5 是常见的 1.5MW 机型,也可以换成数据包里的实际值。v_cut_in、v_rated、v_cut_out 分别对应切入风速、额定风速、切出风速,不同机型差异不小——有的 2MW 机型额定风速是 11.5m/s,有的是 12.5m/s,直接用默认值会低估大风段的出力。算出来的 P 在潮流模型里会作为风机的有功注入,Q 则根据功率因数折算,例如功率因数 0.95 时,Q = P * tan(acos(0.95)),约等于 P * 0.329。
3.2 尾流效应与集电线路损耗:什么时候必须建模
如果数据包给的是每台风机独立的风速,不需要自己算尾流;但如果只给测风塔数据,那就得考虑尾流效应。风电场内上下游机组之间,上游机组的尾流会让下游风速降低 5%~15%,集中体现在主导风向上的第一排和第二排机组之间。
工程上最常用的简化模型是 Jensen 尾流模型。它假设尾流区按线性扩张,下游风速由扫风面积和尾流扩张系数决定:
def jensen_wake(v0, rotor_d=80.0, distance=300.0, k=0.04): # Jensen 尾流模型:按尾流扩张系数折算下游风速 return max(v0 * (1 - 2 * k * distance / rotor_d), 0.3 * v0)这个函数里 rotor_d 是风轮直径,80 米对应 2MW 级机组,distance 是上下游机组的间距,k 是尾流扩张系数,平原风电场取 0.04 左右,复杂地形取 0.06~0.08。注意函数里对最低风速做 0.3 倍保护,避免尾流模型在某些极端参数下算出负风速。在潮流建模时,把修正后的风速代入 wind_to_power,再作为 P 注入风机节点。
什么时候必须建尾流模型?如果安全分析的任务是校验集电线路 N-1 过载,那么满发场景是核心工况,前排机组基本都满发,后排机组只要离得够远也接近满发,尾流影响有限。但如果是做低风速场景下的电压越限分析,尾流会让部分风机出力偏低,无功需求也跟着变,这时忽略尾流会得到偏乐观的电压结果。我在实际项目中通常会两种工况都算:满发场景用于线路过载校验,低发场景用于无功和电压校验。
4. 用 pandapower 复现风电场潮流与 N-1 安全分析:一份最小可跑模型
4.1 搭建最小风电场潮流模型:母线、主变、集电线路与风机节点
WIND1.zip 这类数据包里的模型不算大,用 pandapower 来做最合适,免费、可脚本化、能跑各种潮流算法,而且内置常用线路型号库,不用自己维护线路参数。先搭一个简化版:110kV 并网点作为外网平衡节点,通过主变降压到 35kV 汇流母线,再接三条集电线路,每条线路上挂一台风机。
import pandapower as pp net = pp.create_empty_network(name='wind_farm_demo') # 110kV 并网点:作为外网等值,电压基准 1.0pu hv_bus = pp.create_bus(net, vn_kv=110.0, name='HV 并网点') pp.create_ext_grid(net, hv_bus, vm_pu=1.0) # 主变:110kV/35kV,容量按实际主变容量填 mv_bus = pp.create_bus(net, vn_kv=35.0, name='35kV 汇流排') pp.create_transformer(net, hv_bus, mv_bus, sn_mva=50.0, vn_hv_kv=110.0, vn_lv_kv=35.0, vkr_percent=0.5, vk_percent=10.5) # 集电线路1:35kV,2.5km,用内置线路型号 feeder1 = pp.create_bus(net, vn_kv=35.0, name='集电1') pp.create_line(net, mv_bus, feeder1, length_km=2.5, std_type='35kV_NAYY_3x185_50Hz') # 风机1:作为静态发电机接入,P=1.5MW,Q=-0.3Mvar(吸收无功) pp.create_sgen(net, feeder1, p_mw=1.5, q_mvar=-0.3, name='WT1') pp.runpp(net, algorithm='nr') print(net.res_bus[['vm_pu', 'va_degree']]) print(net.res_line[['loading_percent']])这段代码里的关键参数有三个:ext_grid 的 vm_pu 是并网点电压标幺值,通常取 1.0,但实际运行中会随系统方式波动,做安全分析时还可以按 1.05 或 0.97 校核;sgen 的 p_mw 和 q_mvar 代表风机注入功率,q 为负表示风机吸收无功,这是双馈机组常见的功率因数运行方式;std_type 选用了 pandapower 内置的 35kV 线路型号,实际项目中应替换成 WIND1.zip 里对应的线规。
运行后 res_bus 里的 vm_pu 就是各母线电压标幺值,res_line 里 loading_percent 是线路负载率。这里要先建立一个基本判断框架:35kV 母线电压一般在 0.97~1.07pu 之间,线路负载率超过 80% 就要关注,超过 100% 就判越限。如果风机数量多,可以循环创建母线和线路,但要注意为每条线路命名清晰,否则后面 N-1 扫描的结果很难对应到物理位置。
4.2 N-1 安全分析脚本:逐一断开集电线路并记录越限情况
静态安全分析的核心是 N-1 校验,在风电场里最典型的场景是某条集电线路跳闸后,它所挂的机组全部脱网,潮流重新分布到剩余线路上。此时容易出现相邻线路过载,或者 35kV 母线电压越限。实现起来很直接:deepcopy 原网络,删掉一条线路,重新跑潮流,记录结果。
import pandapower as pp def n_1_scan(net): cases = [] for lid in net.line.index: n = net.deepcopy() n.line.drop(lid, inplace=True) try: pp.runpp(n, algorithm='iwamoto_nr') cases.append((lid, round(n.res_bus.vm_pu.min(), 4), round(n.res_line.loading_percent.max(), 2))) except pp.LoadflowNotConverged: cases.append((lid, None, None)) return cases result = n_1_scan(net) for lid, vmin, load in result: print(f'断线 {lid}: 最低电压 {vmin}pu, 最大负载率 {load}%')这段 N-1 扫描脚本有三个设计要点。第一个是 deepcopy,pandapower 的网络对象在每次潮流后结果都写在 net.res_xxx 里,如果直接删除原网络里的线路,下一次扫描就缺数据,所以每个场景必须复制一份。第二个是算法改用 iwamoto_nr,相比纯牛顿-拉夫逊法,它在接近不收敛时带有阻尼步长调整,在 35kV 这种 R/X 比值较高的网络上表现稳定得多。第三个是异常处理,断线后如果潮流不收敛,返回 None 而不是中断整个循环,安全分析报告里“潮流不收敛”本身就是一条重要的不通过记录。
扫描结果的解读逻辑要清楚:min vm_pu 低于 0.95 判电压越限,max load 超过 100% 判过载。实际工程中我会把负载率超过 80% 也列入预警清单,因为集电线路的载流量通常按最大连续出力设计,留的裕量并不大。把这一段跑完,WIND1.zip 数据包的核心价值才真正体现出来——不再是静态看参数,而是能批量回答“哪条线断了最危险”。
注意:N-1 扫描耗时与线路数成正比,几十条线路的模型用牛顿法逐条跑通常在秒级。如果数据包规模到上百条线路,建议把 deepcopy 换成 net.deepcopy() 后用 with 进入独立计算,或者改用 pandapower 自带的 pp.runpp 搭配 net 副本。不要尝试在原网络上做完 N-1 再恢复,那会留下隐藏脏数据。
5. 风电场潮流安全分析避坑:5 个让结果翻车的常见原因
5.1 模型填参层面的坑:额定出力、线路参数与 R/X 比值
坑一:把风机全部按额定容量填入,导致 N-1 结果失真。现象是扫描出来的线路负载率普遍偏低,现场却出现过载报警。原因是数据包里的风机容量是额定值 MW,而实际出力随风速变化,如果直接用额定值填,等于默认全场 100% 满发;反过来,如果取平均风速对应的出力,又会低估大风时段。解决方法是始终从风速时序出发,先经功率曲线折算再填成 sgen 的 p_mw。如果数据包只给了一个典型工况,至少把满发和半发两个场景分开算。
坑二:35kV 集电线路 R/X 比值高,牛顿法频繁不收敛。现象是 runpp 报 LoadflowNotConverged,或迭代几十次后电压振幅不衰减。原因不是模型错了,而是牛顿-拉夫逊法对初值敏感,而 35kV 电缆和架空线的电阻相对电抗占比远比 110kV 电网大,辐射状结构又加剧了这种敏感。解决方法是换 iwamoto_nr 算法,或者在初始化时把母线电压初值统一设置为 1.0pu,不要沿用上一次不收敛的残差。作为后备方案,把线路模型改成 π 型等值,并在变压器分接头处加一个合理的抽头位置,也能明显改善收敛性。
坑三:主变和线路的标幺值基准没统一,电压结果偏得离谱。现象是 35kV 母线电压算出来 1.15pu,怎么调无功都压不下来。原因多为数据包里的阻抗百分数不是相对 100MVA 的,而 pandapower 里 vk_percent 是相对变压器自身 sn_mva 的百分数。如果原数据按主变 50MVA 折算,而模型填的 sn_mva=100MVA,阻抗就翻了一倍。解决方法是在建模前先确认数据包的基准容量,并用 vk_new = vk_old * sn_new / sn_old 换算回来。这是 WIND1.zip 类数据包最容易栽跟头的地方,没有之一。
5.2 运行场景层面的坑:无功补偿装置与单点工况
坑四:SVG、电容器组和电抗器等无功补偿装置没有建模。现象是满发时 35kV 母线电压算出来在 1.06~1.08pu 越限,但现场实际电压正常。原因是数据包里并网点附近通常配置了 SVG 或分组电容器,它们的无功输出会动态维持母线电压,而简化模型里只建了风机和主变,等于拿掉了一个关键电压支撑。解决方法是把无功补偿装进模型:电容器用 shunt 元件按分组容量填入,SVG 在静态分析里可以按恒电压控制近似,或按典型无功出力填成可控的静态无功源。安全分析结束后,还要单列一项“SVG 退出”的 N-1 校核,因为那才是真正的恶劣工况。
坑五:只跑一个典型工况,用单点结果代表全年运行状态。现象是报告里写“各母线电压合格,线路无过载”,但在大风增速时段或夜间低负荷时段会出问题。原因在于风电场出力波动大,安全分析不能只看额定工况或平均工况,而要看边界工况:满发与最小负荷组合、低发与最大负荷组合、单机脱网叠加外部电网故障。这一条严格说不是潮流计算问题,而是安全分析方案问题,但却是实际并网审查中专家最爱追问的点。我的习惯是先跑满发、半发、零发三个基础工况,再叠加每条线路的 N-1,基本能把绝大部分静态安全问题暴露出来。
6. 进阶:用风速时序批量跑安全分析,把单点结果变成概率区间
如果你已经能把单场景 N-1 跑通,下一步值得做的是把 WIND1.zip 里的风速时序批量灌进模型,逐小时计算潮流并统计越限概率,而不是只信几个典型工况的数据。这个做法的价值很直接:风电场全生命周期里真正触发保护动作的往往是某些极端小时,单点扫描根本看不见。做法是在风速时序上循环,每次把风速折算成出力,再对当前风速做一次或多次 N-1 扫描,最后统计每条线路的越限小时数。
import pandas as pd import pandapower as pp wind_series = pd.read_csv('WIND1/wind_hourly.csv', parse_dates=['time']) def build_net_for_wind_speed(v): net = pp.create_empty_network() # 与第4章相同的母线、主变、线路建模逻辑 # 风机出力通过 wind_to_power(v) 折算后写入 sgen return net records = [] for _, row in wind_series.iterrows(): net = build_net_for_wind_speed(row['wind_speed_mps']) pp.runpp(net, algorithm='iwamoto_nr') records.append({ 'time': row['time'], 'vmin_pu': net.res_bus.vm_pu.min(), 'max_loading': net.res_line.loading_percent.max(), }) res_df = pd.DataFrame(records) print(res_df['vmin_pu'].describe()) overload_hours = (res_df['max_loading'] > 100).sum() print(f'过载小时数: {overload_hours}')这段代码后面有两个值得关注的输出:vmin_pu 的 describe() 能直接看到全年电压最低点的分布,过载小时数则是线路扩容或改造决策的直接依据。工程中我不会把 8760 小时全部跑完再写报告,而是先用典型日聚类选出高风、中风、低风三个场景,各取代表性风速跑 N-1,然后对重点线路做全时序校核,这样既省时间又不容易漏掉边界。
这个方向值不值得投入?我的判断是,只要你的工作涉及风电场并网审查或接入系统设计,就值得把整套流程固化下来。WIND1.zip 这类数据包的价值不在压缩包本身,而在它给了你一个可以反复跑批量安全分析的模型基础。最后一次提醒:不管用哪个工具跑完潮流,先看一眼无功流向,再谈结果。我早年做接入报告时,曾拿着一版全过载合格的扫描结果去上会,被专家追问“你这个 SVG 在哪”,当场才发现模型里漏了动态无功支撑。现在我的习惯是每次运行后先打印各母线无功和风机 Q,确认无功流向合理,再落报告结论。希望帮到你。
本文还有配套的精品资源,点击获取