# xfoil-python
**Repository Path**: openminds/xfoil-python
## Basic Information
- **Project Name**: xfoil-python
- **Description**: XFOIL 翼型气动分析工具的 Python 封装模块。
本项目支持两种使用模式:Python 库模式(在代码中直接调用 xfoil 分析功能)和 MCP 服务模式(通过 FastMCP 将分析功能暴露为 MCP 服务,供 AI 客户端调用)。
- **Primary Language**: Python
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-10-15
- **Last Updated**: 2026-06-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: Python, XFOIL, MCP
## README
# xfoil-python
XFOIL 翼型气动分析工具的 Python 封装模块。
本项目支持两种使用模式:**Python 库模式**(在代码中直接调用 xfoil 分析功能)和 **MCP 服务模式**(通过 FastMCP 将分析功能暴露为 MCP 服务,供 AI 客户端调用)。
**特点:** Python 代码通过 ctypes 直接调用编译好的 Fortran 共享库,无需读写磁盘文件、无需与 XFOIL 可执行文件进程通信。消除了持续的磁盘 I/O 开销,尤其能显著加速并行计算框架。
## 应用模式
本项目支持两种使用模式:
### 1. Python 库模式(Library)
将 xfoil 作为 Python 模块导入,在代码中直接调用翼型气动分析功能。适用于科学计算脚本、自动化分析流程、参数优化等场景。
```python
from xfoil import XFoil
xf = XFoil()
xf.naca('2412')
xf.Re = 1e6
cl, cd, cm, cp = xf.a(5)
print(f'CL={cl:.4f}, CD={cd:.4f}')
```
### 2. MCP 服务模式(Service)
通过 FastMCP 将分析功能以 MCP(Model Context Protocol)形式暴露为独立服务,供 AI 客户端(如 Claude Desktop、Cursor)通过 stdio 或 HTTP 调用。适用于 AI 辅助设计、对话式气动分析、集成到 AI IDE 工作流等场景。
```bash
# stdio 模式(AI IDE 集成)
xfoil-mcp
# HTTP 模式(远程服务)
xfoil-mcp --http
```
详见下方的 [MCP 服务](#mcp-服务) 章节。
---
## 安装
### 前置条件
- Windows 64位系统
- Python >= 3.8
- NumPy
### 安装方式
使用 uv(推荐):
```bash
uv sync
```
或使用 pip:
```bash
pip install .
```
> 本版本使用预编译的 Fortran 动态链接库(`libxfoil.dll`),**无需**安装 gfortran、CMake 等编译工具,即装即用。
---
## 数据模型:`Airfoil`
`Airfoil` 类定义在 `xfoil/model.py`,用于表示翼型几何数据。
### 坐标约定
翼型坐标采用 XFOIL 标准约定:
- **坐标系:** 弦长归一化坐标 (x/c, y/c)。弦长 c = 1,前缘在 x=0,后缘在 x=1。
- **排列顺序:** 坐标点从**后缘上表面** (x=1) 出发,沿上表面到**前缘** (x=0),再沿下表面回到**后缘** (x=1),形成闭合环。
- **方向约定:** **逆时针**绕行标准。但库会自动检测顺时针方向并反转,所以两种方向均可。路径为:后缘上 (1,0) → 上表面 → 前缘 (0,0) → 下表面 → 后缘下 (1,0)。
### 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `x` | `np.ndarray` | 翼型表面点的 x 坐标 (x/c) |
| `y` | `np.ndarray` | 翼型表面点的 y 坐标 (y/c) |
| `n_coords` | `int` | 坐标点总数(只读) |
### 用户输入坐标的格式要求
1. **类型:** `numpy.ndarray`,或任何可被 `np.array()` 转换的序列(list、tuple)。
2. **长度:** `x` 和 `y` 的长度必须相同,建议至少 100~200 个点以保证面板精度。
3. **包含上下表面:** 必须同时涵盖上表面 (y>0) 和下表面 (y<0) 的坐标,形成完整封闭轮廓。
4. **后缘处理:** 后缘一般有一小段间隙,而不是完全闭合的一点。后缘顶面和底面通常各有一个稍有不同的坐标,这是正常的。
5. **坐标方向:** 库会自动检测逆时针/顺时针并处理,无需用户额外操作。
### 创建示例
```python
import numpy as np
from xfoil import Airfoil
# 简单三角翼型(7 个点)
airfoil = Airfoil(
x=np.array([1.0, 0.9, 0.5, 0.0, 0.5, 0.9, 1.0]),
y=np.array([0.0, 0.05, 0.1, 0.0, -0.1, -0.05, 0.0]),
)
# 排列顺序说明:
# 后缘上 (1.0, 0.0) → 上表面 → 前缘 (0.0, 0.0) → 下表面 → 后缘下 (1.0, 0.0)
```
### 读取翼型坐标文件
从坐标文件加载翼型(标准 XFOIL 坐标格式,每行一个点):
```python
import numpy as np
from xfoil import Airfoil
# 读取.dat 坐标文件(忽略首行文件名)
data = np.loadtxt('airfoil.dat', skiprows=1)
x = data[:, 0]
y = data[:, 1]
airfoil = Airfoil(x=x, y=y)
```
### 常见错误
| 错误 | 结果 | 说明 |
|------|------|------|
| 只提供上表面坐标 | 翼型不闭合,分析失败 | 必须包含上下表面完整轮廓 |
| `x` 和 `y` 长度不同 | `ValueError` | 两个数组必须长度相同 |
| 坐标未归一化(弦长 ≠ 1) | 结果比例异常 | 设置属性时把 `LNOrm=True`(默认)即可自动归一化 |
---
## 核心类:`XFoil`
`XFoil` 类定义在 `xfoil/xfoil.py`,封装了所有 XFOIL 气动分析功能。
### 创建实例
```python
from xfoil import XFoil
xf = XFoil()
```
---
## API 参考
### 配置属性
#### `xf.print`
- **类型:** `bool`
- **默认值:** `True`
- **含义:** 控制 XFOIL 是否在控制台输出详细计算日志。静默模式下仍会输出收敛/失败信息。
- **读写性:** 可读可写
```python
xf.print = False # 静默模式
# 读取当前值
is_silent = xf.print
```
#### `xf.airfoil`
- **类型:** `Airfoil`
- **含义:** 要分析的翼型。设置该属性会将翼型坐标加载到 Fortran 库中,会自动判断坐标方向(逆/顺时针)并进行归一化。
- **读写性:** 可读可写
- **注意:** 也可以通过 `xf.naca()` 方法直接加载标准 NACA 翼型
```python
# 写入
from xfoil import Airfoil, XFoil
import numpy as np
xf = XFoil()
xf.airfoil = Airfoil(
x=np.array([1.0, 0.9, ..., 0.0, ..., 0.9, 1.0]),
y=np.array([0.0, 0.05, ..., 0.0, ..., -0.05, 0.0]),
)
# 读取已加载的翼型
loaded_airfoil = xf.airfoil
```
#### `xf.Re`
- **类型:** `float`
- **默认值:** `0`
- **含义:** 雷诺数(Reynolds number)。设置为 `0` 时表示无黏流计算(不考虑黏性边界层)。
- **读写性:** 可读可写
```python
xf.Re = 1e6 # 黏性计算, Re=100万
xf.Re = 0 # 无黏计算
```
#### `xf.M`
- **类型:** `float`
- **默认值:** `0`
- **含义:** 马赫数(Mach number)。设置可压缩流参数。
- **读写性:** 可读可写
```python
xf.M = 0.1 # 亚音速可压缩流, M=0.1
```
#### `xf.xtr`
- **类型:** `tuple(float, float)`
- **默认值:** `(1.0, 1.0)`
- **含义:** 强制转捩位置(x/c 比值)。`xtr[0]` 为上表面,`xtr[1]` 为下表面。设为 `1.0` 表示不强制转捩(自然转捩)。
- **读写性:** 可读可写
```python
xf.xtr = (0.3, 0.5) # 上表面 x/c=0.3 处转捩,下表面 x/c=0.5 处转捩
# 读取当前转捩位置
top_xtr, bot_xtr = xf.xtr
```
#### `xf.n_crit`
- **类型:** `float`
- **默认值:** `9.0`
- **含义:** 边界层转捩的临界 N 因子(e^N 方法),控制自然转捩的敏感程度。
- **读写性:** 可读可写
```python
xf.n_crit = 9.0 # 标准风洞条件 ≈ 0.1% 湍流度
# xf.n_crit = 12.0 # 极低湍流度条件(飞行器)
# xf.n_crit = 4.0 # 高湍流度条件(叶片、涡轮)
```
#### `xf.max_iter`
- **类型:** `int`
- **默认值:** `20`
- **含义:** 黏性迭代的最大步数。大攻角或复杂翼型可能需要更多步才能收敛。
- **读写性:** 可读可写
```python
xf.max_iter = 100 # 增加迭代上限以处理难收敛情况
```
---
### 分析方法
#### `xf.a(alpha)`
- **含义:** 在**固定攻角**下进行气动分析。
- **输入:** `alpha` — 攻角(度),`float`
- **输出:** 四元组 `(cl, cd, cm, cp_min)`,均为 `float`
- **不收敛返回:** `(NaN, NaN, NaN, NaN)`
```python
cl, cd, cm, cp = xf.a(10.0)
# cl ≈ 1.0809, cd ≈ 0.0150, cm ≈ 0.0053, cp ≈ -5.5077
```
#### `xf.cl(cl_target)`
- **含义:** 在**固定升力系数**下进行气动分析,自动调整攻角到目标 CL。
- **输入:** `cl_target` — 目标升力系数,`float`
- **输出:** 四元组 `(alpha, cd, cm, cp_min)`,均为 `float`
- **不收敛返回:** `(NaN, NaN, NaN, NaN)`
```python
alpha, cd, cm, cp = xf.cl(1.0)
# alpha ≈ 9.0617°, cd ≈ 0.0135, cm ≈ 0.0013, cp ≈ -4.7361
```
#### `xf.aseq(alpha_start, alpha_end, alpha_step)`
- **含义:** 对一系列攻角进行扫描分析。相邻攻角间会复用流场解作为初值以提高收敛性。
- **输入:** `alpha_start` — 起始攻角(度),`alpha_end` — 结束攻角(度),`alpha_step` — 步长(度),均为 `float`
- **输出:** 五元组 `(a, cl, cd, cm, cp_min)`,均为 `np.ndarray`
- **不收敛的点:** 对应位置填充 `NaN`
```python
a, cl, cd, cm, cp = xf.aseq(-20, 20, 0.5)
# a.shape == (80,), 从 -20° 到 19.5°,步长 0.5°
```
#### `xf.cseq(cl_start, cl_end, cl_step)`
- **含义:** 对一系列目标升力系数进行扫描分析。相邻点间复用流场解。
- **输入:** `cl_start` — 起始 CL,`cl_end` — 结束 CL,`cl_step` — 步长,均为 `float`
- **输出:** 五元组 `(a, cl, cd, cm, cp_min)`,均为 `np.ndarray`
- **不收敛的点:** 对应位置填充 `NaN`
```python
a, cl, cd, cm, cp = xf.cseq(-0.5, 0.5, 0.05)
# a.shape == (20,), 从 -0.5 到 0.45,步长 0.05
```
---
### 辅助方法
#### `xf.naca(specifier)`
- **含义:** 生成并加载一个 NACA 四位/五位数字翼型。比手动构造 `Airfoil` 对象更便捷。
- **输入:** `specifier` — 数字字符串,如 `'0012'`、`'2412'`、`'23012'`
- **输出:** 无
- **注意:** 调用后 `xf.airfoil` 自动更新为此翼型
```python
xf.naca('2412') # NACA 2412 翼型
xf.naca('0012') # NACA 0012 对称翼型
xf.naca('23012') # NACA 23012 五位数字翼型
```
#### `xf.reset_bls()`
- **含义:** 重置边界层状态。在进行新的分析前调用,强制重新初始化边界层,避免前一个解的尾迹影响当前计算。
- **输入:** 无
- **输出:** 无
```python
xf.reset_bls()
```
#### `xf.repanel(n_nodes, cv_par, cte_ratio, ctr_ratio, xt_ref, xb_ref)`
- **含义:** 重新划分翼型面板。默认面板用于光滑 NACA 翼型效果良好,对于有襟翼、钝后缘等特殊几何的翼型需要自定义。
- **输入:**
| 参数 | 类型 | 默认值 | 含义 |
|------|------|--------|------|
| `n_nodes` | `int` | `160` | 面板节点数 |
| `cv_par` | `float` | `1.0` | 面板聚集参数(>1 更多聚集在前缘) |
| `cte_ratio` | `float` | `0.15` | 后缘/前缘面板密度比 |
| `ctr_ratio` | `float` | `0.2` | 加密区/前缘面板密度比 |
| `xt_ref` | `tuple` | `(1, 1)` | 上表面加密区 x/c 范围 |
| `xb_ref` | `tuple` | `(1, 1)` | 下表面加密区 x/c 范围 |
- **输出:** 无
```python
xf.repanel()
xf.repanel(n_nodes=200, cv_par=1.2, cte_ratio=0.2, ctr_ratio=0.3)
```
#### `xf.filter(factor)`
- **含义:** 对表面速度分布应用修正 Hanning 滤波。用于平滑因面板划分产生的小尺度数值振荡。
- **输入:** `factor` — 滤波参数(`float`),默认 `0.2`,设为 `1.0` 使用完整 Hanning 滤波
- **输出:** 无
```python
xf.filter(0.2)
```
#### `xf.get_cp_distribution()`
- **含义:** 获取上一个收敛点的压力系数(Cp)沿翼面的分布。
- **输入:** 无
- **输出:** 三元组 `(x, y, cp)`,均为 `np.ndarray`
- **注意:** 只有在最后一次分析收敛后调用才能获得有效数据
```python
x, y, cp = xf.get_cp_distribution()
```
---
## 输出参数说明
| 符号 | 名称 | 说明 |
|------|------|------|
| `CL` | 升力系数 | Lift coefficient,无量纲 |
| `CD` | 阻力系数 | Drag coefficient,无量纲 |
| `CM` | 俯仰力矩系数 | Pitching moment coefficient,绕参考点的力矩,无量纲 |
| `Cp_min` | 最小压力系数 | 翼面上最低的 Cp 值,用于判断是否发生空化 |
| `α` | 攻角 | Angle of attack,单位:度 |
---
## 示例脚本
完整示例见 [`examples/`](examples/) 目录:
| 脚本 | 覆盖的 API |
|------|-----------|
| `01_basic_analysis.py` | `naca()`, `airfoil`, `Re`, `max_iter`, `print`, `a()`, `cl()` |
| `02_sequence_analysis.py` | `M`, `n_crit`, `aseq()`, `cseq()` |
| `03_advanced_features.py` | `xtr`, `repanel()`, `filter()`, `reset_bls()`, `get_cp_distribution()` |
| `04_cp_distribution.py` | `a()`, `get_cp_distribution()` — 绘制 Cp 分布图 |
| `05_lift_drag_moment.py` | `aseq()` — 绘制 CL-α、CD-α、CM-α、CL-CD 曲线 |
运行示例:
```bash
uv run python examples/01_basic_analysis.py
uv run python examples/02_sequence_analysis.py
uv run python examples/03_advanced_features.py
uv run python examples/04_cp_distribution.py
uv run python examples/05_lift_drag_moment.py
```
---
## MCP 服务
本项目提供了一个 [FastMCP](https://gofastmcp.com) 服务器,将 xfoil 的翼型气动分析功能以 MCP(Model Context Protocol)形式暴露,供 AI 客户端(如 Claude Desktop、Cursor 等)直接调用。
### 安装
```bash
uv sync --group dev
# 或
uv sync --extra mcp
```
### 启动方式
```bash
# stdio 模式(供 Claude Desktop、Cursor 等 IDE 集成)
xfoil-mcp
# Streamable HTTP 模式(远程服务)
xfoil-mcp --http
# MCP Inspector Web UI(交互式测试)
fastmcp dev xfoil_mcp.py
```
### 暴露的组件
| 类型 | 数量 | 详情 |
|------|------|------|
| **Resources** | 3 + 1 模板 | `xfoil://info` — 服务信息
`xfoil://config` — 当前配置
`xfoil://airfoil/current` — 当前翼型几何
`xfoil://naca/{code}` — NACA 翼型定义 |
| **Tools** | 11 | `load_naca` / `load_airfoil` — 加载翼型
`configure` — 设置 Re、M、Ncrit 等参数
`analyze_angle` / `analyze_cl` — 单点分析
`analyze_angle_sequence` / `analyze_cl_sequence` — 极曲线扫描
`get_cp_distribution` — 获取 Cp 分布
`repanel` / `filter_speed` / `reset_boundary_layers` — 辅助功能 |
| **Prompts** | 2 | `analyze_airfoil` — 翼型分析工作流引导
`compare_airfoils` — 多翼型对比引导 |
### AI 客户端配置
将以下配置添加到客户端的 `mcpServers`:
```json
{
"mcpServers": {
"xfoil-mcp": {
"command": "uv",
"args": ["run", "xfoil-mcp"],
"cwd": "E:\\myWorkspace\\xfoil-python"
}
}
}
```
### 测试
```bash
uv run python -m unittest tests/test_mcp.py -v
```
测试覆盖所有 11 个工具、4 个资源和 2 个提示共 25 个用例。
---
## 注意事项
1. **Windows 专用:** 本版本仅提供 Windows 64 位平台的预编译 DLL。其他操作系统需要自行编译 Fortran 源码。
2. **收敛性:** 黏性分析可能不收敛,尤其是大攻角(接近失速)时。不收敛的点返回 `NaN`。
3. **翼型坐标方向:** 翼型点应按逆时针顺序排列。如果按顺时针排列,库会自动反转顺序。
4. **尾迹初始化:** 连续分析不同攻角时,XFOIL 会复用上一个收敛点的尾迹解作为初值,可提高收敛速度。如需重置(例如跳过分离区后),调用 `reset_bls()`。
5. **DLL 依赖:** `libxfoil.dll` 依赖 MinGW 运行时库(`libgfortran-5.dll`、`libgcc_s_seh-1.dll`、`libwinpthread-1.dll`、`libquadmath-0.dll`),这些文件已一并打包在 `xfoil/` 目录下。