☰
flexpart.tar.gz 实战:从源码编译到可信污染扩散模拟
2026/10/16 18:19:14 网站建设 项目流程

简介:Flexpart 10.4 大气粒子轨迹模型源码包,面向需要在大气污染扩散模拟、气溶胶传输分析中部署该模型的研究者与工程师。内容涵盖Flexpart 10.4完整源代码,以及libemos、HDF5、NetCDF等依赖库的配置说明,还包括编译安装文档、示例控制文件与运行数据,重点解决Ubuntu 18.04环境下源码编译步骤繁琐、依赖版本匹配与冲突频出的难题。压缩包共718个文件,约328.8MB,包含大量网页说明页、示意图、文本资料、数据表、辅助脚本与Fortran源程序等,目录结构较完整,便于检索对照。已有608人学习下载。通过这份资源,读者可系统梳理从环境准备、依赖编译到Flexpart安装测试的完整链路,参考输入控制文件与输出配置,理解模型运行所需的文件组织方式,并结合包内测试数据复现模拟过程,为后续科学计算和模式调试打下基础。 拿到flexpart.tar.gz这个源码包,很多第一次接触大气扩散模型的人会下意识以为“解压、编译、跑一下”三步就能出结果。等你真正打开它,看到的是一堆 Fortran 源码、配置模板和依赖库的清单,这时才意识到真正的工程问题才开始:气象数据怎么准备、参数怎么填、编译链路怎么打通。这个包对应的是一整套拉格朗日粒子扩散模型,常被用来回答“污染物从哪来、往哪去、落地浓度多少”这类问题,也是污染溯源、火山灰扩散、核素迁移场景里的常用工具。这篇文章就按一线操作顺序,把这个包从 tar.gz 变成可信结果的全过程讲清楚,包括参数设置和那些容易翻车的细节。

1. flexpart.tar.gz 是什么:一个解压后才是开始的大气扩散模型包

flexpart.tar.gz是拉格朗日粒子扩散模型的源码压缩包形式,模型本身通过投放大量粒子,让它们随风场、湍流、沉降和衰变过程运动,最后在网格上统计粒子分布,得到污染物浓度、沉降量、轨迹等信息。它和传统欧拉网格模型不同,不容易出现数值扩散,特别适合做污染事件溯源和长距离传输分析。你在环境科研、环评、应急评估里听到的“气团足迹”“源区追溯”,很多背后跑的就是这个模型。

这套东西能解决的问题很实在:某个站点观测到高浓度污染,反推它可能来自哪个区域;火山喷发后火山灰朝哪个方向扩散;核设施异常释放后放射性物质的地面浓度分布。它适合的人也不难对号入座——有一定气象学基础、想用开源模型替代商业软件的环境工程师和研究者。本文接下来要讲的,就是从解压到出图的完整落地路径,包括编译依赖、气象数据准备、关键参数和排查思路。

2. 从 flexpart.tar.gz 到可执行文件:解压结构、依赖库与 makefile 修改

下载到的是压缩包,第一步永远是从解压和熟悉包结构开始,不要直接去翻源码。这步虽然简单,但决定后面所有环节的效率,尤其是依赖库版本不匹配时,你先知道包里有什么,才能判断问题是出在系统环境还是代码本身。

2.1 解压后先看清包结构:源码、配置模板与示例数据

先执行解压,再列目录看结构:

tar -zxvf flexpart.tar.gz cd flexpart ls -l

常见的包结构里会有src/存放 Fortran 源码,tests/或者runs/放测试用例和运行目录,options/或settings/放配置模板,docs/或README说明编译依赖和版本信息。不同发布形态的目录名不完全一样,但源码和配置模板一般都会在明显位置。

解压后第一件事是读 README 或者 docs 目录里的编译说明,确认这个包对编译器、NetCDF、GRIB 工具库的最低版本要求。老版本的代码往往在新编译器上会暴露语法兼容问题,提前知道要求能省很多时间。另外要注意解压出双层目录的情况,也就是最外层包一层同名目录,这时候建议把路径统一记下来,后面 pathnames 配置文件里要用绝对路径,目录嵌套越深越容易在路径末尾少写斜杠。

2.2 编译器与第三方库:装什么、怎么验证装对了

编译拉格朗日模型必须的依赖不多,但每一个都直接影响成败。最少要有 Fortran 编译器、NetCDF 的 Fortran 接口、处理 GRIB 格式气象数据的解码库,以及用于 GRIB2 压缩解码的 JPEG 2000 工具库。GRIB 是气象场数据最常见的二进制编码格式之一,模型读取风速、温度、气压等字段时依赖这套解码链路,少了它编译直接失败。

依赖库的角色和验证方式可以看这张表:

依赖作用验证命令
Fortran 编译器(gfortran 或 Intel Fortran)编译全部源码gfortran --version
NetCDF(含 Fortran 接口)输出网格浓度、粒子位置nf-config --version
GRIB 解码库读取气象场文件grib_ls -V
JPEG 2000 工具库解码 GRIB2 压缩数据在 makefile 中指定路径后编译通过

用 gfortran 是常见做法,免费且容易获得。我在新机器上一般先验证 NetCDF 的 Fortran 接口是否真的可用,因为很多人只装了 C 版本的 NetCDF,导致编译到一半才报链接错误。执行下面的命令,如果这个命令能输出编译和链接参数,说明 Fortran 接口存在;如果报“command not found”,需要重新装带 Fortran 支持的 NetCDF 包。

nf-config --fflags --flibs

依赖版本的问题非常像玄学,同样一套代码,在这台机器上编译过了,换一台机器就报错,多半是 NetCDF 和编译器版本组合不同。我的经验是不要追求最新版本,常用发行版自带的稳定版本配合默认优化级别就够了。Intel Fortran 编译器的优化能力更强,但老代码在用高版本 Intel 编译器时容易遇到标准语法检查变严的问题,如果遇到莫名奇妙的报错,先把优化级别降到 O1 再试。

2.3 改 makefile 编译:关键变量与两种常见出错提示

进入src/目录后,你会看到几个 makefile 模板文件,常见命名带后缀区分气象场来源,比如一个面向全球气象中心 GRIB 数据的模板,一个面向中尺度气象模型输出的模板。编译前先打开对应模板,找到这几组关键变量:

FC = gfortran FFLAGS = -O1 -fopenmp NETCDF = -I/path/to/netcdf/include -L/path/to/netcdf/lib -lnetcdff -lnetcdf GRIB = -I/path/to/grib/include -L/path/to/grib/lib -lgrib_api

FC指定编译器,FFLAGS控制优化和并行选项,NETCDF和GRIB分别指向两个依赖库的头文件和链接库路径。填写的核心原则是不要手写猜测,用nf-config输出的参数直接替换路径部分,避免出现版本不匹配。GRIB 解码库的路径则用工具库自带的配置命令输出,或者直接查默认安装路径。

确认配置后执行编译:

make -f makefile_ecmwf

等待编译日志滚动结束后,检查当前目录是否生成了flexpart可执行文件。如果编译中途报错,最常见的两类信息是“undefined reference to nf_create”和“module not found”。前者说明链接 NetCDF Fortran 接口出了问题,检查-lnetcdff是否在链接参数里;后者说明 include 路径没找对,回头看NETCDF变量的-I参数。解决这两类问题后,编译通常能顺利通过,得到可执行文件后再用ldd flexpart检查动态库链接是否完整。这个环节做完,整个流程才刚走完三分之一,接下来要给它喂数据。

3. 跑通最小案例:气象数据准备、路径配置与首次运行

有了可执行文件,下一步不是直接跑大案例,而是用最小配置先跑通。这个模型本身不生成气象场,它的所有运动过程都依赖外界输入的网格化气象数据,所以数据准备的质量直接决定模拟结果是否可信。

3.1 气象场数据从哪来:格式、时间窗口与字段要求

模型需要的气象场,通常有两类来源。一类是全球网格化气象再分析资料,以 GRIB 编码发布,覆盖范围大、时间连续性好;另一类是区域中尺度气象模型的输出,空间分辨率更高,适合局地污染事件分析。无论哪类数据,都必须覆盖整个模拟时间窗口,并且时间步长要与模型配置匹配,常见的气象场时间间隔在 1 到 3 小时之间。

拿到气象文件后,我一般先做一个检查清单:文件的时间范围是否完全覆盖释放起止时间、空间范围是否覆盖释放源和预期传输路径、是否包含模型必需的变量。模型最少需要三维风场、温度、气压和湿度,湿沉降计算还需要云量、降水量等字段。最怕的就是下载了精简版数据,跑起来才发现缺了某些变量,报错信息又指向某个内部函数,排查成本非常高。

检查字段可以用工具库自带的查询命令,比如grib_ls -p name,typeOfLevel,level列出所有变量名和层次;如果是 NetCDF 格式的气象数据,用ncdump -h看变量清单。这个习惯能帮你提前发现字段缺失,而不是等模型运行到一半才报错。

3.2 pathnames 与输入文件清单:每个路径的角色

模型运行前要告诉它每个输入输出目录的位置,这个信息写在路径配置文件里。文件内容非常朴素,通常就是几行绝对路径,分别指向气象数据目录、输出目录和物种定义目录。下面是一个示例格式:

/home/user/flex_input/metdata/ /home/user/flex_output/ /home/user/flex_input/

路径末尾的斜杠不能省,这是很多第一次运行就失败的原因。另外,这些路径必须写绝对路径,不能写相对路径,因为程序在运行过程中可能切换工作目录。如果解压包里有现成的pathnames模板,直接在里面改路径,不要自己新建,避免格式行数对不上。

除了路径文件,还要确认这些输入文件是否齐全:

文件作用
气象场文件提供驱动模型的风场、温度、湿度等数据
控制命令文件定义模拟时段、输出频率、网格等全局设置
释放源文件定义源位置、释放时段、粒子数
物种定义文件定义污染物的密度、沉降参数、衰变参数

把这些文件都准备好后,整个过程就完成了数据侧的准备工作。对小规模案例,缺少任一文件程序都会在启动阶段报错或者直接退出,所以建议先完整跑一遍官方示例,再切换到自己准备的数据。

3.3 首次运行命令与输出文件:判断是不是真的跑起来了

运行时的常见做法是直接把路径文件作为参数传给可执行程序:

./flexpart pathnames

跑起来后,程序会在日志里打印当前时间和进度信息。第一次运行不需要追求大网格和大量粒子,建议开一个 48 小时的小窗口,释放一个点源,粒子数控制在万级,跑完后检查输出目录。

正常情况下输出目录会生成网格浓度文件,文件名通常以 CONC 开头,代表各网格的污染物浓度;还会生成粒子位置文件,记录每个粒子的历史轨迹。这两个文件出现,说明模型主流程已经走通。还有一类以时间命名的中间文件,不要随手清理,后续做质量守恒验证要用。

如果程序报错,先分清是启动阶段还是运行中途。启动阶段报错大多是路径、时段或参数格式问题;运行中途报错则多半指向气象数据读取或某些字段计算异常。把日志文件中第一次出现的错误信息作为排查起点,往往能找到真正原因,不要盯着最下面那行看。

4. 决定结果质量的关键参数:释放源、粒子数与输出网格怎么设

跑通之后,真正的调试工作才开始。很多人以为参数随便填一填能出图就行,但拉格朗日粒子模型对参数非常敏感,尤其是释放源定义、粒子数量和输出网格这三组设置,直接决定结果是否可信。

4.1 释放源定义:位置、高度、时段与排放率

释放源的定义通常单独放在释放源文件中,核心字段包括源编号、释放开始和结束时间、源类型、经纬度范围、释放高度以及粒子总数。点源只需要一组经纬度坐标;面源则需要两个角点坐标。释放高度的坐标系必须搞清楚,是相对于地面的高度,还是相对于海平面的高度,这个字段填错会导致粒子从一开始就落在错误的位置,后面的轨迹全错。

一个典型释放源文件中某个释放源的字段含义大致如下:

1 2016 12 1 000000 2016 12 2 000000 2 116.2 39.9 116.2 39.9 50. 100000.

按常见模板理解,第一行是源编号,第二行是释放起止时间,第三行表示源类型,第四行是源区的经纬度范围,第五行是释放高度,第六行是粒子总数。不同版本字段顺序可能不同,你一定要以包内模板为准。错误地把两个点的经纬度顺序填反,或者把高度单位按英尺填,都会让结果完全背离预期。

释放时段建议与气象数据的起始时间之间留出富余量,比如模拟窗口从 48 小时前就开始,释放源在中间某时刻开启,这样粒子有足够的时间建立扩散形态,边缘效应会小很多。排放率如果已知总量的质量,可以先折算成对应粒子数释放,再在后期处理时换算回浓度值。

4.2 粒子数与输出网格:计算量、内存与分辨率怎么平衡

粒子数是拉格朗日模型里最核心的计算量参数。粒子太少,网格内统计噪声很大,浓度场看起来像随机散点;粒子太多,内存占用和计算时间成倍增加。常见案例里,区域尺度的模拟用十万到百万级粒子比较合理,全球尺度则需要更大规模。经验做法是先用较少数量的粒子跑通流程,看输出形态基本合理后,再逐步增加粒子数对比结果变化。

输出网格的参数同样关键,它决定了浓度场的空间分辨率。网格范围要覆盖整个可能扩散的区域,网格间距不能比气象场分辨率细太多,否则没有实际意义。较小空间尺度如 0.1 度,网格间距取 0.05 度,输出文件会膨胀为原来的约四倍,却不会带来同比例的精度提升。跑长时间案例前,先用粗网格快速验证,确认形态合理后再加密,这是我一直沿用的流程。

粒子数和输出频率之间也有关系。输出间隔如果设置得比气象场时间分辨率还密,只会增加海量中间文件,对结果精度没有帮助。常见的做法是让输出间隔与气象场时间间隔保持一致,或者略粗一些。当某个网格内的粒子数特别少时,该网格的浓度值波动很大,这类位置的结果解释要谨慎,不要当作有效浓度点直接拿去画图。

4.3 物种属性:沉降、衰变与气体和粒子的区别

每个模拟的污染物物种都有独立的属性定义,包括干沉降速度、湿沉降洗除系数、密度、摩尔质量以及衰变常数。这些参数在物种定义文件中配置,字段顺序和单位同样以包内模板为准。

干沉降速度是重力沉降和气溶胶沉降的综合结果,尺度通常在每秒零点几厘米到几厘米之间。湿沉降系数描述降水对污染物的清除效率,一个很小的系数差异可能导致远距离落地浓度差出数倍。放射性物质的衰变常数由半衰期换算而来,如果模拟铯-137 这类长半衰期核素,衰变项对短程结果影响不大,但长距离传输时必须开启,否则浓度会被明显高估。

气体污染物和气溶胶颗粒在这套模型中的处理逻辑不同:颗粒物要设密度和粒径相关的沉降参数,气态污染物则更多依赖干沉降速度和化学反应项。拿不准某个值的时候,参考同类污染物在文献中的常用取值,不要随便从其他来源复制。每个参数修改后都重新看一遍单点源输出,观察源附近和下风向的浓度变化是否符合常识,再继续调下一个参数。

5. 常见问题与排查:编译失败、运行崩溃与全零结果的诊断路径

这套流程里的坑很密集,多数问题集中在编译、气象数据读取和结果合理性三个环节。这一章把最典型的踩坑记录整理成诊断路径,每条都按现象、原因、解决三步说明,可以直接对照排查。

5.1 编译链路的 3 个经典失败信息与对治

现象一:编译进行到中途,链接阶段报大量undefined reference to nf_create或nf90_create。原因:操作系统里虽然安装了 NetCDF,但只有 C 接口,没有 Fortran 接口模块,链接器找不到 Fortran 需要的符号。解决:重新安装带 Fortran 支持的 NetCDF 包,安装完后用nf-config --version确认接口存在,再把nf-config --fflags --flibs的输出直接替换 makefile 里的路径参数。

现象二:编译刚开始就报某个 Fortran 模块找不到,比如Error: Can't open module file 'netcdf.mod'。原因:include 路径写错或者 NetCDF 的 Fortran 模块没装在默认位置。解决:用find / -name 'netcdf.mod' 2>/dev/null定位模块实际路径,把该路径加到 makefile 的-I参数里。

现象三:编译通过,运行后立刻崩溃,日志提示“段错误”。原因:往往不是程序本身 bug,而是气象数据文件格式与编译时使用的解码库版本不匹配。解决:先确认气象文件是 GRIB2 还是 GRIB1 编码,再看编译时链接的解码库版本是否支持对应编码,必要时重编译并链接新版解码库。这个问题的典型特征是无法复现,同一套二进制换一台机器就恢复,基本就是环境版本问题。

5.2 气象数据读取失败与字段缺失怎么查

现象:模型启动后几秒钟内退出,日志报找不到某个气象文件。原因:气象文件的命名规则与程序期望的不一致。程序拼接文件名有固定模板,年月日时分各项都有固定位置,文件名对不上就读不到。解决:先去源码或日志里查文件名拼接模板,然后把气象文件批量重命名成模板要求的格式,路径配置里的目录也要替换为实际目录。

现象:运行到某个时间步报错,提示找不到变量,比如垂直速度或云量。原因:使用了不完整的气象数据集,缺少模型计算湍流或湿沉降必需的字段。解决:用grib_ls -p name或ncdump -h列出文件中的变量清单,和模型要求的变量列表逐一核对,缺失字段就得换完整版本的数据,不要试图通过修改配置绕过。湿沉降参数开启时,缺少云量或降水数据会导致湿沉降通量恒为零,检查时先看这类字段有没有。

5.3 结果为零或轨迹异常:时间窗口、高度与随机性

现象:模型正常跑完,但输出浓度全部是零。原因中最常见的是释放时段与气象场时间窗口完全不重叠,粒子从一开始就不存在;另一种常见原因是释放高度设置得过高或低于地形高度,粒子直接落在阻挡层或地下。解决:先核对释放文件的起止时间是否落在气象场覆盖范围内,再检查释放高度是相对地面还是海平面,以及释放源地形的实际海拔。

现象:两次完全相同配置的模拟,结果有细微差异,甚至被判为“复现失败”。原因:拉格朗日模型的粒子运动包含随机扰动,每次运行生成随机序列不同,统计涨落导致结果有差异。解决:这是模型固有特性,不是 bug。做对比实验时建议固定随机种子,保证同配置结果可严格复现,否则很难判断参数修改带来的到底是真实变化还是统计噪声。

现象:粒子轨迹在下风向剧烈跳跃,呈锯齿状而非连续路径。原因:气象场时间间隔过大,或者粒子数太少导致湍流扩散项统计波动。解决:检查气象数据时间分辨率,3 小时以上的间隔在强风场里会让轨迹明显失真;同时适度增加粒子数压制随机噪声。遇到这种情况,先查数据时间分辨率再改参数,不要盲目加粒子数。

6. 跑通之后先验证 3 个指标:再谈长周期模拟、复现与换气象源

输出文件生成不代表结果能用。我每次跑完新案例,都会在画图之前先做三个指标的验证,这样能拦住大部分低级错误。第一步看粒子总数守恒,对没有沉降和衰变的物种,模拟结束时仍在计算域内的粒子数与沉降出域外的粒子数之和,应该等于初始释放粒子数。这个检查可以用一个简单脚本统计粒子位置文件,如果总数不对,说明有粒子因为网格设置或时间步长被错误丢弃。

第二步看浓度场空间分布是否符合气象常识,比如污染羽是否沿着盛行风方向拉伸,源附近浓度是否最高,远距离浓度是否平滑递减。如果出现浓度斑块状跳跃或者羽轴严重偏折,优先怀疑气象场时间和空间分辨率不足。第三步做一次保守性验证,把某个网格的浓度积分结果与排放量做粗略对比,量级上不能差出数倍以上。

复现性是长周期模拟里的隐藏考点。批量跑多个案例时,固定随机种子能让同一配置的输出完全一致,对比不同释放方案或气象场版本时才不会把统计噪声当成信号差异。此外,分段模拟是一个实用技巧,把一个月案例切成三段,每段结束时输出状态文件,下一段用重启动方式续跑,这样能避开长时间运行导致的内存膨胀,也能在中途换用更新的气象数据。换气象源时,重点检查物理解、变量名和数据投影是否与模型要求一致,中尺度气象模型的输出往往需要先转成模型默认的格式和投影,再进行路径配置。

最后补一个操作习惯:画图前把浓度输出插值到地图投影上,和站点观测叠加对比,这是判断结果可信度的最直观方式。有一次我碰到的某次案例里模型结果和站点观测在高峰时间上差了 6 小时,排查了很久发现是气象场文件时间标记记成了 UTC,而本地时间没有做转换——自那以后我每次拿到气象文件都会先核对时间基准。这些验证不一定能让你立刻得到完美结果,但能帮你避免在错误的方向上花费大量时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询