先说一下我遇到的问题。之前跑某个开源CFD求解器的算例,默认配置跑完之后生成了七八个文件,但我想监控的壁面热流和局部质量流量反而不在history文件里,场输出文件里也混了一堆我不关心的变量。那段时间我反复改config、反复看文档,才把对"输出结果变量"的控制逻辑彻底理清楚。其实这类求解器的输出体系并不复杂,只是入口分散,很多人卡在不知道哪个选项管哪个文件。
这篇就专门讲清楚一个事:在使用SU2这类开源CFD求解器时,怎么通过配置文件来控制结果变量的种类、范围和输出节奏。文章面向正在跑SU2算例、被输出文件困扰的工程人员和研究生,不需要你懂C++,只需要会看config文件即可。
1. 先认清SU2把"结果变量"放在哪几条输出管线里
很多人的误区是直接在求解器源码里找"输出变量"的开关,或者以为有一个隐藏配置项能决定每个变量写不写。实际上SU2的输出变量不是靠一个入口统一管理的,它被分散在至少四条输出管线上。你不把这四条管线分清,改配置就永远像在打地鼠。
1.1 四类输出文件,各管一类变量
第一条管线是流场体输出文件,对应常见名称如flow.csv、flow.vtu,里面保存的是全流场节点的守恒变量和原始变量,比如密度、速度分量、压力、温度,以及湍流模型相关的变量。这类文件服务于云图后处理,也是你判断流场结构是否合理的主要依据。
第二条管线是表面输出文件,对应surface_flow.csv、surface_flow.vtu这类名字,只写指定边界上的量,常见的包括壁面压力系数、摩擦阻力系数、壁面热流、壁面Y+等。它把三维体数据压缩成边界面数据,文件比体文件小很多,但信息密度很高。
第三条管线是历史/监控输出文件,通常叫history.csv。它按迭代步记录积分量,比如升力系数、阻力系数、力矩系数、某个监控面上的质量流量、某个壁面的平均温度等。这是判断收敛和监控目标量的核心文件。
第四条管线是重启文件,通常叫restart_flow之类的名字。它保存的是求解器内部完整状态,目的是让算例能接着跑,所以里面的变量往往是守恒变量而不是后处理变量,文件格式也偏二进制或紧凑型CSV。
1.2 默认配置下的主要困惑来源
默认配置文件通常会把好几条管线的输出全部打开,于是你经常会看到flow.csv、flow.vtu、surface_flow.vtu、surface_flow.csv、history.csv、restart_flow.csv同时生成。文件一多,很多人就分不清哪个才是自己需要的。
另一个常见困惑是,history.csv里默认只有那几条积分量,像气动力系数、力矩系数,而你在研究的是热问题,想看壁面热流,翻遍整个文件都找不到。这是因为历史输出变量是由"输出组"控制的,默认组只包含气动力相关变量,你需要显式加上其它组,后面第4节会详细说。
1.3 一个核心原则:先分清"求解变量"和"输出变量"
还有一点容易让人绕进去:SU2内部求解的变量和最终写到文件里的变量并不完全一致。内部求解通常用守恒量,输出时可以选择写原始变量,也可以写守恒变量,不同文件格式能容纳的字段也不同。比如Paraview的VTU格式和CSV格式,写出的字段集就有差异。
所以改变输出结果变量的第一步,不是急着去改某个变量名,而是先问自己:我要的变量属于哪条管线?是全场体量、边界面量,还是随迭代变化的积分量?管线选对了,后面的配置才有意义。
| 输出管线 | 常见文件 | 典型变量 | 主要用途 |
|---|---|---|---|
| 流场体输出 | flow.csv / flow.vtu | 压力、温度、密度、速度 | 云图、流场诊断 |
| 表面输出 | surface_flow.* | 壁面压力系数、热流、Y+ | 翼面载荷分析 |
| 历史监控输出 | history.csv | 升力系数、阻力系数、监视量 | 收敛判断、目标量监控 |
| 重启输出 | restart_flow.* | 守恒变量、湍流变量 | 断点续算 |
2. 控制文件类型和字段载体的入口:OUTPUT_FILES选项
想改变"写出来的结果变量具体是什么",最直接的操作是修改配置文件里的OUTPUT_FILES。这个选项决定求解器运行时生成哪些文件,以及每个文件用什么格式打包数据。
2.1 单行配置是怎么工作的
在SU2的config文件里,OUTPUT_FILES可以写成类似这样:
OUTPUT_FILES= (CSV, PARAVIEW_ASCII, RESTART_ASCII, SURFACE_PARAVIEW_ASCII)这行的意思是让求解器在计算过程中输出一个CSV格式的流场文件、一个ASCII版Paraview文件、一个ASCII版重启文件,以及一个ASCII版表面Paraview文件。括号里每一项都代表一条独立的输出管线。
需要强调的是,OUTPUT_FILES改变的是"结果变量打包成什么格式、写成什么文件",并不会改变求解器内部状态。同一个流场解,你把它写成CSV还是VTU,底层数据是一样的,只是字段组织和读取方式不同。
2.2 如何按需取舍文件类型
实际项目中,你不需要每次都开全部输出。我的习惯是分场景处理:
- 如果只想做力系数收敛监控,就只保留
RESTART_ASCII和CSV格式的历史输出,不开体文件和表面文件。 - 如果需要云图后处理,至少开一个
PARAVIEW_ASCII或PARAVIEW,不建议同时开CSV和Paraview两种体输出,纯占磁盘。 - 如果分析的是翼面压力分布或壁面热流,就开
SURFACE_PARAVIEW或SURFACE_CSV,不需要把整个流场都写出来。 - 如果算例要长期跑、准备续算,
RESTART系列必须保留,否则断了只能从头再来。
2.3 版本升级时的选项变化
这一点特别提醒在用老配置的人。SU2从早期版本到v7、v8,OUTPUT_FILES的选项集合发生过变化。早期版本里,文件格式相关选项比较分散,例如有单独的OUTPUT_FORMAT、WRT_CSV_OVERWRITE、SURFACE_CSV等,而新版本倾向于统一用OUTPUT_FILES这个列表管理。
我遇到过的情况是:把旧的config文件直接拿到新版跑,求解器不报错,但某些旧选项被静默忽略,结果就是某个表面文件没生成,我还以为是配置写错了。解决方法是跑之前先看一眼求解器自带的默认config模板,它通常会把当前版本支持的全部输出选项列全,你只需要照着模板改。
3. 让特定边界的变量进入输出:MARKER_PLOTTING与MARKER_MONITORING
文件类型选好之后,下一步要控制的是"哪些边界的变量被写出来"。这一步由MARKER_PLOTTING和MARKER_MONITORING两个选项负责,它们经常被搞混,但实际职责差异很大。
3.1 两个MARKER选项各自控制什么
MARKER_PLOTTING控制的是表面输出文件中包含哪些边界,也就是哪些壁面、哪些远场边界的表面量会被写进surface_flow.*文件。如果你希望后处理时看到机翼表面的压力系数分布,就得把机翼对应的marker加进来。
MARKER_MONITORING控制的是哪些边界参与气动力/力矩的积分统计,并把统计结果写进历史文件。比如你想让history.csv里的升力系数CL反映整架飞机的升力,就要把机翼、机身对应的marker都列进MARKER_MONITORING。
3.2 一个容易踩的坑:marker名字对不上
很多算例跑完,history.csv里升力阻力全是0,原因很简单:MARKER_MONITORING= (airfoil),但网格文件里那块翼面marker其实叫wing,名字对不上,求解器就等于没有找到监控对象。改动方法也很直白:要么改config里的marker名,要么改网格文件里的marker名,两者保持一致即可。
我在实际项目中习惯把config里的MARKER_PLOTTING和MARKER_MONITORING写成同样的边界集合,除非有特殊目的。比如我只想看某个壁面的温度分布,但不想让它参与力系数统计,那我只把它放进MARKER_PLOTTING,不放MARKER_MONITORING。
3.3 多部件算例的配置示例
假设一个简单的两段翼型算例,前缘缝翼叫slat,主翼叫main,我想同时得到两者各自的表面数据和总的气动力系数,可以这样配置:
MARKER_PLOTTING= (slat, main) MARKER_MONITORING= (slat, main) OUTPUT_FILES= (SURFACE_CSV, SURFACE_PARAVIEW_ASCII, RESTART_ASCII)这样跑完之后,surface_flow.csv里会同时包含slat和main两套表面数据,history.csv里也会给出这两部分边界合并后的升力、阻力、力矩等积分量。
有人会问:那我想分别看slat和main各自的升力怎么办?这取决于版本支持。旧版本里通常只能得到两个marker的合力,想拆分就得分别跑两个算例或做后处理;新版本通过历史输出的SURFACE组或相关监控设置,可以在一个算例里输出更多细分监控量。建议先查手头版本的文档,看HISTORY_OUTPUT支持哪些细分选项。
4. 历史输出里没有目标变量?改HISTORY_OUTPUT和SCREEN_OUTPUT
历史文件是日常调试最常看的,但很多人对它的预期过高,以为所有物理量都会随迭代写进去。实际上history.csv里的每一类变量都属于某个"输出组",你要做的就是告诉求解器:这次算例需要哪些组。
4.1 HISTORY_OUTPUT的组概念
SU2的历史输出按组组织,例如AERODYNAMIC组包含典型的气动力系数,WALL_ABORT组包含发散监测相关的壁面量,SURFACE组通常包含选定边界上的统计量,还有针对质量流量、传感器、旋转机械等专门设计的组。
默认配置里往往只开着少数几个组,所以你的history.csv里看不到壁面热流或质量流量是很正常的。解决办法是显式把需要的组写进HISTORY_OUTPUT。
4.2 一个具体算例的修改过程
我做过一个平板传热算例,目标是监控一块壁面的平均温度和质量流量,原来的历史文件里只有升阻力系数。我改了两处:一是把监控壁面的marker加进MARKER_MONITORING,二是把历史输出组改成需要监控的组。
配置片段大致如下:
MARKER_MONITORING= (hot_wall) HISTORY_OUTPUT= (AERODYNAMIC, SURFACE) OUTPUT_WRT_FREQ= 50OUTPUT_WRT_FREQ的意思是每50个迭代步写一次历史文件。这样做的好处是history.csv里既保留了力系数,又新增了与该壁面相关的统计量,而且文件条目不会像每步都写那样膨胀得飞快。
4.3 SCREEN_OUTPUT:控制你实时看到的内容
屏幕输出也是"输出变量"的一部分,只是它不进文件,而是显示在终端里。默认屏幕输出通常包含残差和升阻力系数,但如果你想在调试阶段实时看到某个变量,比如温度残差或某个边界的平均压力,就可以调整SCREEN_OUTPUT。
例如我经常把屏幕输出设成这样,方便肉眼判断:
SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_DENSITY, LIFT, DRAG, TIME_PER_ITER)用TIME_PER_ITER的好处是能直观看到每步迭代的耗时,发现网格量太大或配置不合理时,可以及时控制算例,不用等跑完才发现问题。
5. 输出频率与重启场景:改动结果变量时的节奏控制
很多人把注意力全放在"输出什么变量"上,忽略了"多久输出一次"和"重启时输出什么"这两个问题。非定常算例尤其明显,如果不控制输出频率,几个物理时间步就能把磁盘写满。
5.1 OUTPUT_WRT_FREQ怎么定才合理
OUTPUT_WRT_FREQ控制全场文件和历史文件的写入频率。默认值往往偏保守,对小型算例无所谓,一旦网格到数百万量级,每10步写一次全场文件会让IO时间远超计算时间。
我的经验是:
- 调试阶段:网格不大,可以把输出频率设小一些,比如100步一次,方便反复看流场演化。
- 稳定计算阶段:把频率设到500甚至1000,减少IO干扰。
- 非定常算例:按物理时间步来控制,通常每几个或每几十个物理时间步写一次,具体看你想捕捉的流动频率。
5.2 调整输出变量后能否接着重启
这是一个很多新手会问的问题:我已经跑了一部分,现在想改OUTPUT_FILES,能不能直接重启续算?
答案是可以的。因为OUTPUT_FILES、HISTORY_OUTPUT、SCREEN_OUTPUT这些选项只影响输出后处理,不影响流场求解状态。你只需要保证重启文件对应的那部分设置不变,比如网格名、marker名、求解器类型这些核心配置不要随便改,续算就能正常进行。
5.3 重启时最容易翻车的变量匹配问题
重启文件里保存的是求解器内部状态。假如你第一次用层流配置跑,重启后改成湍流模型,重启文件里可能没有湍流变量,这时就会导致读取失败或变量初始化异常。这不是"输出变量"的问题,而是"状态变量"不匹配的问题。
所以我的建议是:如果打算以后改湍流模型或改物理模型,最好从一开始就把这些模型选项定好;输出变量层面随便改都行,但物理模型和网格层面要慎重。
6. 改了很多次输出配置之后,我总结出的几个坑
这部分完全是实操层面的心得,写出来供后来者避坑。
6.1 别迷信"全开"输出,磁盘和IO是真实成本
有段时间我为了省事,把所有输出选项都打开,结果一个稳态算例跑完,输出文件加起来比网格文件还大好几倍。更麻烦的是,写文件的IO时间明显拖慢了迭代速度,尤其是每步都写全场Paraview文件时,计算过程卡得像在放幻灯片。
后来我给自己定了规矩:第一遍试算只开最小输出,包括重启文件、历史文件;确定流场基本合理后,再针对性开表面或体输出。这种方式既省磁盘,也减少干扰。
6.2 表面文件里变量显示为0的常见原因
我之前遇到过surface_flow.csv打开后,某些变量列全是0的情况。排查后发现不是求解器算错了,而是该表面所在的区域本身没有被求解器赋予相应的量,比如固壁边界上的某个量需要特殊模型才能计算。
遇到这种问题,先别急着怀疑输出配置,用Paraview打开对应的VTU文件看看,或检查该边界的物理边界条件类型是否合理。很多时候是边界条件设得不对,输出文件只是如实反映了结果。
6.3 升级求解器版本后,输出文件名会变
版本升级后,同样的配置可能生成不同后缀的文件,比如旧版是restart_flow.dat,新版可能是restart_flow.csv。如果你的自动化脚本写死了文件名,升级后脚本就会找不到文件。
解决这类问题,我一般不在脚本里写死完整文件名,而是用通配符匹配,或者先跑一个极小的算例,把当前版本实际生成的文件清单打出来,再改脚本。这样能省掉很多不必要的踩坑时间。
6.4 一个实用技巧:用历史输出做"传感器"监控
如果你想监控某个非边界位置或某个剖面上的量,不一定要靠MARKER_PLOTTING。可以在几何上提前把那个位置做成一个小marker,或者利用历史输出的传感器相关功能,输出该点或该线的物理量变化。
这个思路在做旋转机械和管道流动时特别有用。比如监控某个截面上的平均速度或总压,不用每次跑完都去后处理软件里切面,直接在历史文件里就能看到随迭代的变化趋势,极大提高了调参效率。
我在实际使用中最大的体会是,SU2这类求解器的输出机制很像一个四层过滤器:第一层决定写哪些文件,第二层决定哪些边界参与表面输出,第三层决定哪些边界参与监控积分,第四层决定这些结果以什么频率写出来。把四层串起来理解,就不会再为了找某个变量而反复试错了。最后分享一个小经验:每次新建算例时,先花两分钟把默认config模板里的输出部分过一遍,勾掉不需要的选项,再开始跑正式算例,这个习惯能帮你省掉后面大量的磁盘清理和变量排查时间。