简介:《风电开源仿真软件 OpenFAST v3.2.1 源码》是一份面向风电建模仿真、电气工程和数值计算研究人员的完整源代码资源。OpenFAST 将 AeroDyn、SubDyn、InflowWind、BeamDyn 等气动载荷、结构动力学、入流风场与叶片塔架模型整合为可耦合求解的整机仿真框架,适合开展风力机动态响应分析、控制器验证和模块级二次开发,也可用于风电课程设计与科研平台搭建。该压缩包约四百三十四兆,包内文件总数暂未提供,主要文件类型包括 Fortran 源码、VS 解决方案文件、CMake 构建配置及模块头文件/接口定义;通过 Visual Studio 解决方案可一键配置编译参数与模块依赖,免去手动处理多个组件构建关系的麻烦;而 CMake 命令行方式则便于 Linux 用户自动化配置。已有 1661 人学习下载。读者下载后可直接获得全模块源码与构建脚本,根据自身环境选择 Windows 或 Linux 编译路径,在理解模块耦合机制的基础上进行仿真计算、调试排错或功能扩展,是风电仿真领域深入学习与工程实践不可多得的开源参考。
1. openfast仿真软件:风电建模仿真的开源主力
实测风速只有 13m/s,塔筒顶部振动却在几分钟里翻了三倍。这类动态效应靠经验公式根本推不出来,必须回到时域仿真里去解。OpenFAST 就是干这个的——它把叶片气动、结构弹性、发电机控制和塔基支撑耦合到同一套时间步里推进,输出每个时刻的载荷与响应。v3.2.1 源码包的价值在于:你能看到方程在哪里组装、状态量如何跨模块传递,而不是把一个商业黑匣子当摆设。适合做整机载荷计算、控制器开发和动力学研究的工程师,也适合想在毕业论文里写清楚算法机理的学生。
2. 看懂 OpenFAST 的源码骨架:模块化架构与 v3.2.1 的关键差异
2.1 从 FAST 到 OpenFAST:为什么这套代码值得读
FAST 在风电领域跑了二十多年,NREL 后来把它按模块重构,仓库迁移到 GitHub 上,名字改成 OpenFAST。v3.x 延续了模块化设计,主程序负责调度,气动、结构、水动力、控制各自独立成模块,模块之间通过注册好的输入输出变量交换数据。这个设计对做仿真的人非常友好:你想换一套变桨控制策略,只需要动 ServoDyn,结构模块和气动模块的代码不用碰。
源码里最值得读的不是算法公式本身,而是模块之间的耦合方式。气动载荷算完写到哪个变量,结构模块从哪个变量读入,再算出位移和速度反过来喂给气动模块,这一来一回的时序决定了整个时间步的稳定性。我拆这套 v3.2.1 源码时,先画了一张模块数据流图,后面排查问题基本都靠它。
2.2 模块间的数据流:一个时间步里发生了什么
OpenFAST 的时间推进逻辑集中在 src/FAST.f90 里。每个时间步大致做这几件事:先调用 AeroDyn 根据当前风速、桨距、转速和叶片变形算气动力,再把它映射到结构网格上;ElastoDyn 接收气动力后做结构积分,更新节点位移和速度;如果是海上风机,HydroDyn 同时计算波浪载荷;最后 ServoDyn 根据当前转速和桨距角状态算出新的控制指令,交给发电机和变桨执行器。
这套流程里最容易出问题的是气动模块的时间步长。气动力的变化比结构响应快得多,DT 一旦设得过大,BEM 迭代不收敛,载荷曲线会出现锯齿状的数值振荡。我一般先把 DT 设为 0.0125 秒跑一遍,再对比 0.005 秒的结果,确认载荷差异在 1% 以内再放大步长。
2.3 源码目录里找什么:入口文件与依赖清单
openfast/ ├── modules/ # 各物理模块 │ ├── aerodyn/ # 气动载荷,BEM 与涡尾迹方法 │ ├── elastodyn/ # 结构动力学,叶片与塔筒 │ ├── hydrodyn/ # 波浪与水动力 │ ├── servodyn/ # 发电机、变桨与控制器 │ └── inowind/ # 入流风场生成 ├── src/ # 主程序与胶水代码 │ ├── FAST.f90 # 主入口,时间推进循环 │ └── FAST_ConfigSubs.f90 ├── reg_tests/ # 回归测试算例 ├── docs/ # 文档 └── CMakeLists.txt读取源码时先看 modules 目录下的每个子目录,它们各自维护一套独立的状态变量和输入文件。src 目录里的 FAST.f90 是主入口,整个仿真循环在这里跑。依赖方面,v3.x 离不开 libxml2 和 yaml-cpp,这两个库负责解析 fst 和 yaml 格式的输入文件,编译前必须先装好。
2.4 为什么选 v3.2.1 而不是更早版本
v3.x 相比 v2.x 最大的变化是主输入文件格式统一了,不再兼容老 FAST 直接生成的 fst 文件。你在网上找到的很多旧教程里那一套输入格式,塞给 v3.2.1 大概率会报错。v3.2.1 这个 tag 的回归测试和文档都比较完整,拿来学习或做工程验证比追最新主分支要省心。对于只做陆上风机载荷计算的人,HydroDyn 相关的代码可以暂时不深入,但不能在 CMake 里直接关掉,因为整机装配时模块列表是写死的。
3. 源码编译与安装:从 v3.2.1 源码到可运行的 openfast 命令
3.1 准备环境:依赖、编译器与 CMake 版本
编译 OpenFAST 需要 gfortran、CMake 和两个基础库。以 Ubuntu/Debian 为例,安装命令如下:
sudo apt update sudo apt install -y build-essential gfortran cmake \ libxml2-dev libyaml-cpp-devgfortran 是 Fortran 编译核心,OpenFAST 主体代码是 Fortran 写的,不能用 gcc 顶替。libxml2-dev 提供 XML 解析支持,libyaml-cpp-dev 负责 yaml 格式配置解析。CMake 版本建议不低于 3.16,太老的 CMake 可能不认项目里的一些 target 定义。装完这些依赖后,可以用gfortran --version和cmake --version确认版本。
3.2 拉取源码并配置构建
我一般直接从 GitHub 拉 v3.2.1 这个 tag,而不是下整个仓库所有历史,省时间也避免切错分支:
git clone --depth 1 --branch v3.2.1 \ https://github.com/OpenFAST/openfast.git cd openfast mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=RELEASE \ -DOPENFAST_DOUBLE_PRECISION=ON make -j4-DCMAKE_BUILD_TYPE=RELEASE开启编译器优化,仿真速度明显比 Debug 快,但编译失败时的报错信息会少一些,我通常在首次编译时先用默认 Debug,跑通后再切 RELEASE。-DOPENFAST_DOUBLE_PRECISION=ON强制双精度浮点,这是复现论文结果的关键,默认单精度的舍入误差会在长时仿真里被积分放大。make -j4开 4 个并行任务,如果内存只有 4GB,建议改成-j2,否则链接阶段可能直接 OOM 翻车。
3.3 安装与验证
编译完成后安装到系统目录,再验证版本号:
sudo make install openfast --version默认安装路径在 /usr/local,可执行文件是 openfast。如果直接敲命令提示找不到,先export PATH=/usr/local/bin:$PATH再试。openfast --version输出类似 v3.2.1 的版本信息,说明主程序已经能运行。这一步没做下一步,直接跑算例是白费力气。
3.4 Windows 用户的实际路径:WSL 还是 MSYS2
Windows 下原生编译 OpenFAST 挺折腾的,路径里的反斜杠、空格以及 Fortran 编译器环境变量都能让人耗掉一整天。我的建议是装 WSL,里面跑 Ubuntu,然后完全按上面三步走。这条路线最省心,而且后续处理仿真数据的 Python 环境也能共用。如果必须原生 Windows,常见做法是装 MSYS2,用 pacman 装 gcc-fortran、cmake、libxml2、yaml-cpp,再按同样流程 cmake 和 make。但要注意 MSYS2 里库路径和编译器默认查找路径不一样,CMake 经常报找不到依赖,得有心理准备。
4. 跑通第一个风电仿真算例:参数设置与输出解读
4.1 从基准风机开始:NREL 5MW 算例为什么是首选
OpenFAST 自带 reg_tests 回归测试目录,里面有大量现成的算例配置。我第一次编译完不会立刻去建自己的机型,而是先找 NREL 5MW 基准风机的算例跑一遍。这个机型的数据公开了十几年,塔筒和叶片的物理参数全是公开的,仿真结果能直接跟论文和设计报告对比,环境有没有问题一目了然。
在 reg_tests/glue-codes/openfast 下能找到一堆 fst 主输入文件。先列一下再决定跑哪个:
cd openfast/reg_tests/glue-codes/openfast ls *.fst openfast <选中的算例>.fst算例运行后会在当前目录生成对应名字的 out 文件,里面的通道就是仿真结果。第一次跑不需要纠结选哪个算例,主要目的是验证程序能完整推进一个仿真周期并正常落盘。
4.2 读懂 fst 文件里的关键参数
fst 文件是 OpenFAST 的主输入文件,里面按区块排布仿真控制、输入输出和模块开关参数。以下几个字段是每次跑算例我都会先确认的:
| 参数 | 作用 | 我一般这样给 |
|---|---|---|
| DT | 仿真时间步长,单位秒 | 0.0125,气动不收敛时再调小 |
| TMax | 仿真总时长,单位秒 | 600 起步,稳态统计建议 1200 |
| DT_Out | 输出数据采样间隔 | DT 的整数倍,比如 0.05 |
| TStart | 从哪个时刻开始输出 | 跳过瞬态段时设为 60 或 120 |
| OutFmt | 输出数据的格式串 | 保持默认,想提高精度改 E16.8E3 |
DT 这个参数最敏感。步长太大,BEM 气动模块里的迭代容易不收敛,载荷序列会出现高频振荡;步长太小,计算时间成倍上涨,数据量也大。我的习惯是先跑一遍短时仿真,把 DT 从 0.0125 改到 0.00625 对比结果,差异小于 1% 就认为步长合适。TStart 常常被忽略,实际上风轮启动和控制器介入的头几十秒包含大量瞬态分量,如果直接拿整段数据做统计,极值和均值都偏大。
4.3 输出数据解读:先把表头吃透
OpenFAST 的 out 文件是纯文本,前面几行是注释和表头,后面是时间序列。格式问题常常让人卡住,我建议先用 head 看前十几行:
head -n 12 <算例>.out确认表头在哪一行、单位在哪一行,再写 Python 脚本读取。常见的处理方式是用 pandas 加 skiprows 跳过注释和表头:
import pandas as pd # 如果表头前有 2 行注释 + 1 行表头 + 1 行单位,则跳过 3 行 df = pd.read_csv("<算例>.out", sep=r"\s+", skiprows=3) print(df.columns) print(df.head())提示:skiprows 的数值一定要以 head 实际输出为准,不同版本的文件头行数可能不一样,宁可多打印几行手数,也不要盲猜。
读进来之后,通道名以 Time、Wind1VelX、RootMxb1、RotThrust、GenPwr 这类形式出现,分别代表时间、风速、叶根弯矩、风轮推力和发电机功率。我先打印 columns 确认单位列已被跳过,再进行后续计算。
4.4 第一条曲线:画功率和叶根弯矩
数据读进来后,最快的验证方式是画两条曲线:
import matplotlib.pyplot as plt fig, ax1 = plt.subplots(figsize=(10, 4)) ax1.plot(df["Time"], df["GenPwr"], label="GenPwr", color="tab:blue") ax1.set_xlabel("Time (s)") ax1.set_ylabel("GenPwr (kW)") ax2 = ax1.twinx() ax2.plot(df["Time"], df["RootMyb1"], label="RootMyb1", color="tab:red") ax2.set_ylabel("RootMyb1 (kN*m)") plt.tight_layout() plt.show()功率曲线在稳态风速下应当收敛到接近额定功率的平直线,叶根弯矩曲线则是围绕均值波动的宽带信号。如果这两条曲线表现异常,先回去检查输入文件里的风速和转速设置,而不是怀疑程序装坏了。
5. 避坑排查:编译、运行与旧输入文件迁移常见的翻车记录
5.1 编译时找不到 yaml-cpp:cmake 缓存把依赖指丢了
现象:cmake 阶段报 Could NOT find YAMLCPP,配置直接中止。
原因:系统里其实装了 libyaml-cpp-dev,但 CMake 的 find_package 在第一次配置失败后会把空结果写进缓存,哪怕你后来补装了库,不清理缓存它依然按旧的失败结果走。
解决:先sudo apt install -y libyaml-cpp-dev,然后删除整个 build 目录重新建,确保缓存从零开始。如果依然找不到,用dpkg -L libyaml-cpp-dev | grep yaml-cpp-config查安装路径,再手动指定-Dyaml-cpp_DIR=/usr/lib/cmake/yaml-cpp。
5.2 运行时提示找不到 libxml2.so.2:编译过了,运行却失败
现象:编译和链接都成功,执行 openfast 时提示 error while loading shared libraries: libxml2.so.2。
原因:编译阶段靠头文件找到开发包,运行时需要动态库参与,但某些系统默认没装运行时库,或者装到了 ldconfig 不扫描的目录。
解决:首先sudo apt install -y libxml2补运行时库,执行ldconfig -p | grep libxml2确认动态库存在。如果库在自定义目录,用export LD_LIBRARY_PATH=/your/libdir:$LD_LIBRARY_PATH临时指定,再写进 ~/.bashrc 避免每次配置。
5.3 结果和论文对不上:单精度编译的舍入误差被积分放大
现象:跑同样的 NREL 5MW 算例,输出的额定功率、叶根载荷极值和公开论文对不上,误差在 2%~3%,而且载荷曲线有细微毛刺。
原因:编译时没显式开启双精度,浮点运算的舍入误差在长时间积分里积累,导致载荷均值偏移和数值振荡。
解决:重新用-DOPENFAST_DOUBLE_PRECISION=ON配置编译,再跑同一算例对比。这个改动只影响编译选项,不需要改输入文件,但要重新 make 并安装。从那以后我每次拿到新机器,第一件事就是确认这个开关是 ON。
5.4 风轮启动段疯狂振荡:TStart 没把瞬态甩掉
现象:仿真前面 30 秒的功率和弯矩曲线大幅振荡,对比稳态段完全不是一个量级,整体统计结果偏高。
原因:初始条件给出的转速、桨距角与实际风速不匹配,OpenFAST 从非平衡状态开始积分,前几十秒其实是控制系统把风轮拉回平衡点的时间,不是真实的稳态响应。
解决:统计前把 TStart 设为 60 到 120 秒,只对之后的输出做均值、极值和频谱分析。新建算例时不要图省事设 TStart 为 0,除非你明确要研究启动瞬态过程。
5.5 老版 FAST 输入文件迁移失败:v3.x 格式不兼容
现象:把 FAST v1/v2 时代的 fst 文件直接放进 v3.2.1 运行,解析阶段就报错,有时提示某一行未知参数,有时直接卡在 Echo 开关。
原因:v3.x 统一了主输入文件的语法和参数命名,旧文件里的部分行被重新定义或删除,编译器不再接受老写法。
解决:不建议手工去补老文件里的字段。正确做法是打开 reg_tests 里同类型机型的 fst 模板,把模型相关的叶片、塔筒、机舱参数迁移进新模板,模块开关按新版本默认值走。迁移完成后跑一遍基准算例,载荷差异超过 5% 就说明迁移过程中漏掉了某个结构参数。
6. 进阶验证:用输出通道做叶根载荷对比验证
仿真跑完只是开始,载荷校核才是工程上真正关心的事。我通常拿 RootMyb1 通道的叶根挥舞弯矩做两个验证:一个是看时序极值是否落在设计报告允许范围内,另一个是用局部极大值筛出循环峰值,估算等效疲劳载荷的量级。下面这段代码做的是第一件事,把局部极大值挑出来看分布:
import numpy as np mom = df["RootMyb1"].to_numpy() t = df["Time"].to_numpy() # 寻找局部极大值点:左右邻居都比它小 peak_idx = np.where( (mom[1:-1] > mom[:-2]) & (mom[1:-1] > mom[2:]) )[0] + 1 print(f"峰值个数: {len(peak_idx)}") print(f"最大叶根挥舞弯矩: {mom[peak_idx].max():.2f} kN*m") print(f"平均峰值: {mom[peak_idx].mean():.2f} kN*m")极值对应的时刻也要打印出来,方便回到 out 文件里核对当时的桨距角和转速状态。如果极值出现在风速大幅下降的时段,很可能是动态失速造成的载荷尖峰,比额定风速附近的极值更需要关注。工程上做疲劳评估时还要把峰值序列做雨流循环统计,这里先用极值分布确认载荷量级合理,再决定是否进入疲劳分析流程。
每次仿真新机型,我都会强制走一遍基准算例对标:用 NREL 5MW 的公开参数跑同一工况,先把功率曲线和叶根弯矩极值对齐,确认载荷量级和趋势都合理,才敢把后续结果拿去做塔筒和叶片校核。这个习惯帮我挡掉了好几次因为输入文件迁移错误而导致的无效载荷输出。这套 v3.2.1 源码包下载后,第 3 章的编译流程就能直接跑起来,记得先打开双精度开关。希望帮到你。
本文还有配套的精品资源,点击获取