ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

WRF-Chem配置实战:chem_opt与emiss_opt匹配及namelist避坑指南

WRF-Chem配置实战:chem_opt与emiss_opt匹配及namelist避坑指南 说起来挺尴尬我第一次完整跑通 WRF-Chem不是被 WPS 的地理数据折腾到崩溃也不是死在编译阶段而是在 namelist.input 里被chem_opt和emiss_opt这一对“看起来只是数字”的参数反复吊打。手册告诉你chem_opt2是 RADM2emiss_opt1是人为排放但没人告诉你这两个数字必须在同一套“暗语”体系里才能对上话。更麻烦的是很多坑不会直接报错而是让你跑出一张浓度非常“可爱”、毫无物理意义的图然后你开始怀疑气象场、怀疑排放清单、怀疑自己的人生。这篇文章就是写给刚接触 WRF-Chem 的新手以及那些已经跑通 WRF 但第一次在 namelist 里开化学开关的人。我会把chem_opt、emiss_opt、bio_emiss_opt这些开关背后的职责边界、组合规则、排查链路一次讲清楚并给出一份可以直接上手的最小配置模板。全程以 WRF-Chem v4.x 的常见行为为基准具体选项编号在不同小版本里可能有出入建议你随时用我提到的方法核对你自己安装版本的 Registry 文件。这些内容大多确实是手册里没明说的。1. 先分清命名空间chem_opt、emiss_opt、bio_emiss_opt 到底各管哪一段1.1 别把“化学机制”和“排放接口”混为一谈新手最容易犯的第一个错误是以为chem_opt决定了“要不要化学”emiss_opt决定了“排放开多大”。这是一个非常自然的误解但也是所有后续混乱的根源。我用一个生活化的类比来解释chem_opt是后厨的菜谱。它决定你要做哪几道菜、需要哪些食材、按什么顺序下锅。在模型里它决定气相反应的化学机制RADM2、CBMZ、RACM、SAPRC99 等等、气溶胶方案MADE/SORGAM、MOSAIC、CMAQ-AE5/AE6 等等以及最终输出哪些化学物种。emiss_opt是供应商的送货单格式。它不决定“送多少菜”只决定“送货单上每一样东西叫什么、单位是什么、怎么对应到后厨需要的食材”。在模型里它决定 wrfchemi 排放文件里的E_NO、E_SO2、E_PM25这类变量如何被读入并映射到chem_opt指定的机制物种。bio_emiss_opt是你的自留菜地。它负责计算植被、土壤在线产生的生物源排放比如异戊二烯、萜烯类不走人为排放文件而是由模型根据下垫面和气象条件实时估算。换句话说你完全可以把chem_opt和emiss_opt看成两个必须匹配的协议端口菜谱需要的食材必须对应得上送货单上的品名。如果送货单上写的是“青椒”后厨需要的却是“二荆条”结果不是炒不出菜而是模型在搬运数组时直接越界崩溃或者更隐蔽地给你一个全零排放。1.2 chem_opt 的数字背后是“气相机制 气溶胶方案”的组合很多人看到chem_opt有一长串整数就以为这只是不同机构的编号。实际上这个数字背后是两套正交选择的组合向量气相化学机制以及气溶胶方案。我整理了一个非常精简的表格覆盖新手最常碰到的几组chem_opt气相气相机制气溶胶方案典型使用场景0关闭无纯气象模拟化学完全关闭1CBMZ无臭氧/光化学入门2RADM2无很多教程默认的入门机制4RACM无臭氧/光化学机制更细腻5RADM2MADE/SORGAM含硫酸盐/硝酸盐/二次有机气溶胶的老牌方案6CBMZMADE/SORGAM气溶胶入门16CBMZMOSAIC 4bin关注 PM2.5 分粒径/成分时常用17CBMZMOSAIC 8bin更精细的气溶胶粒径分布19RADM2MOSAIC 4bin需要 RADM2 气相配合的气溶胶模拟22RACMMOSAIC 8bin机制更细的气溶胶模拟如果你把这张表横向看就会发现一个规律数字越往后通常意味着气相机制和气溶胶方案绑定得越紧。chem_opt16不等于“比 2 更高级”它是“CBMZ 气相 MOSAIC 4bin 气溶胶”这个特定组合。所以千万不要从网上抄到某个机制编号就盲填你要先问自己我的研究目标是臭氧、PM2.5还是成分分析另外一个容易被忽略的点是chem_opt0和“选一个化学机制但把排放关掉”完全不是一回事。chem_opt0时模型根本不调用化学驱动模块输出变量里基本不会有 O3、NO2、PM2.5你后处理时拿不到化学量。而你如果想“先不开排放、只测化学机制能否跑通”正确做法是chem_opt2, emiss_opt0这样化学机制会启动物种会在背景浓度基础上反应但没有外源输入。1.3 emiss_opt 的真实身份一个“读表索引”不是排放强度emiss_opt最常见的取值是 0、1、2。0 表示完全不读人为排放文件1 表示读取标准人为排放文件wrfchemi_d01以及嵌套域的wrfchemi_d02等文件里的变量名通常是E_NO、E_NO2、E_SO2、E_CO、E_ETH、E_OLT、E_PM25这一整套2 通常与 GOCART 一类特殊气溶胶映射配套变量名和一些单位的约定会不一样。这里有一个“手册里没说透”的重点emiss_opt的数字越大不代表排放量越大。它只是让模型去查不同的映射表。我之前见过有新手为了让污染“更严重”一点把emiss_opt从 1 改成 2结果模型读入排放时找不到匹配变量直接在 wrfchemi 输入阶段段错误崩溃。这不是“强度”问题是“格式”问题。另一个经验是emiss_opt只处理人为源工业、交通、居民燃烧等。火灾排放由fire_emiss相关开关控制生物源由bio_emiss_opt控制沙尘和海盐等自然源又有自己的在线参数化开关。把这几类源分开理解你才不会在排查“为什么 AQI 图里 PM2.5 还是这么低”的时候找错方向。2. 新手最常踩的五个组合坑附真实报错特征2.1 chem_opt 改了emiss_opt 没跟着换运行直接段错误场景很典型你之前用教程跑通了chem_opt2后来想换成chem_opt16做气溶胶于是只改了chem_optemiss_opt还保持原来的 1。然后模型在积分到化学驱动阶段时毫无征兆地给你一个段错误SIGSEGV。报错特征通常是 rsl.error.0000 的最后几行出现类似forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source wrf.exe ... chem_driver ... module_chem_driver.F不同版本的行号、函数名会不太一样但核心信息是崩溃发生在化学驱动模块。为什么会崩因为emiss_opt1映射出来的排放变量列表是照着 RADM2 的气相物种表设计的当你把chem_opt改成 16机制里的物种数组长度、顺序都变了排放读入程序把E_*变量往新的数组里塞的时候下标对不上于是越界。我自己的排查习惯是遇到这种崩溃先别急着看代码直接重新跑一遍emiss_opt0的配置。如果关了排放就能跑那就基本锁定是排放与机制不匹配。然后打开ncdump -h wrfchemi_d01检查文件里到底有哪些E_*变量再对照你当前chem_opt对应的机制物种表看看缺口在哪里。2.2 嵌套域 chem_opt 不一致子域边界污染被“心态良好”地吃掉嵌套域是 WRF 的常规操作但到了 WRF-Chem 里嵌套的约束比纯气象严格得多。父域要给子域提供化学边界条件那么父域算出来的 O3、NO2、PM2.5 这些量就必须能在子域的化学变量向量里找到对应的位置。如果 d01 用chem_opt2d02 用chem_opt16两个域的物种列表长度和排列顺序都不同子域边界上的化学变量插值轻则错位重则产生 NaN。更隐蔽的情况是某些版本下模型不会立即崩溃但你在子域边界附近会看到浓度场出现明显的“拼接线”——内点浓度正常靠近边界却出现异常高值或负值。这就是父域与子域化学机制不一致造成的。所以我的建议非常直接第一次配置嵌套化学模拟所有域的chem_opt必须完全一致。不要想着“d01 粗网格用简单机制省时间d02 细网格用复杂机制提精度”这个想法在 WRF-Chem 里现阶段基本行不通。你只能全区域统一机制通过调整气溶胶档位或打开/关闭某些辅助参数来折中计算量。2.3 wrfchemi 的层数与 e_vert 不匹配时数据会“静默丢失”这个坑最阴险因为模型不报错跑得开开心心但你后处理时发现排放源附近污染物浓度低得离谱像没排放一样。问题往往出在排放文件的垂直层数上。你用 PREP-CHEM-SRC 或其他工具生成wrfchemi_d01时如果那个工具使用的是某个旧版本模板它输出的emissions_zdim可能是 19 或者 24而你的 namelist.input 里e_vert45。WRF 在读入排放时按高度层逐层读入但如果文件层数少于模式的e_vert多出来的层要么被当作 0要么整体错位——具体行为取决于版本但结果都一样边界层内的排放根本没有被正确地送你到第一层。检查方法很简单一行命令ncdump -h wrfchemi_d01 | grep -E emissions_zdim|bottom_top|west_east|south_north然后跟 namelist.input 里的e_vert比对。不一致就去重新生成排放文件或者用 NCL / Python 的 xarray 把排放变量插值到模式层上。不要天真地以为 WRF 会自动帮你处理层数匹配它很多时候真的不会。2.4 没有真实化学初值就启动前几小时浓度在“洗牌”另一个新手常有的困惑我明明开了化学和排放为什么前 12 小时的臭氧和 PM2.5 几乎一条直线这不是代码坏了而是化学初值缺失。WRF-Chem 的化学初始场和边界场通常不是 WPS 的 met_em 文件自动附带的。如果你直接从 metgrid 输出跑 real.exereal 会尝试在 met_em 里找化学变量O3、NO2、CO 等找不到时各版本的默认行为不同有的给一个全球背景值有的直接设 0。带着这样的化学初场启动模型需要相当长的 spin-up 时间让化学过程自己把浓度“熬”出来。对于臭氧来说前几小时可能都在低浓度区徘徊。我建议新手的处理办法有两个如果只是验证配置能否跑通接受 spin-up 阶段浓度不合理的事实重点看模拟后期是否出现日变化。如果要做科研级模拟去下载与模拟时段匹配的全球化学模式输出比如 CAM-chem、WACCM 等再分析/预报结果转换后作为化学初始场和边界场写入 wrfbdy / wrfinput。这一步比较折腾但它是做短期模拟绕不过去的基本功。2.5 restart 时化学状态被覆盖第二天浓度“一夜回到解放前”WRF 的 restart 机制很成熟但 WRF-Chem 的 restart 有一个藏得很深的细节restart 文件里的化学变量必须和当前 namelist 的chem_opt配置兼容。我曾经干过一件蠢事用chem_opt0跑了一个月的“气象 restart 累积”然后某天想从中间开始做化学模拟直接把 restart 改成.true.还在chem里填了chem_opt2。模型启动得很顺利但我对比前后两天的 PM2.5发现后一天直接从 0 开始爬坡。原因就是restart 文件里根本没有化学变量或者化学变量全为默认值重启时化学场被清空了等于重新 spin-up。所以记住两条铁律restart 文件必须来自相同或兼容的化学配置不能拿纯气象 restart 来接化学模拟。每次修改chem_opt、emiss_opt这类核心选项后最好把旧的 restart 文件改名或删除重新从初始时间跑起不要让模型“带病重启”。3. 参数选型的决策顺序先用最小可用机制跑通再逐步加复杂度3.1 阶段一chem_opt0 全关化学先验证气象场没问题很多新手一上来就急着把化学参数填满然后模型一崩分不清是化学问题还是气象问题。我的习惯是先让 WRF 以chem_opt0、emiss_opt0、bio_emiss_opt0跑通一遍确认 WPS 生成的地形、土地利用、气象初边场没有明显问题。这一步花不了多少时间但它能帮你把“气象场异常”和“化学模块异常”切成两个独立变量。如果你连气象都跑出高空负水汽、地面温度跳变那后面配化学基本是浪费时间。3.2 阶段二先选气相机制不要一上来就上 MOSAIC如果是初次接触 WRF-Chem我的推荐顺序是先用无气溶胶的机制跑通比如chem_opt1CBMZ或chem_opt2RADM2。这两个机制不涉及复杂的气溶胶热力学平衡化学积分相对稳定出问题也好排查。等这个配置稳定运行输出的 O3、NO2 日变化符合常识之后再考虑是否切换到含气溶胶的机制。选择依据很简单研究目标推荐方向臭氧、NOx、VOC 光化学RADM2 或 CBMZ 类即可硫酸盐/硝酸盐/铵盐、SOAMADE/SORGAM 或 MOSAIC 类PM2.5 分粒径与化学成分MOSAIC 4bin 或 8bin沙尘/海盐传输考虑 GOCART 或专门的 dust/salt 参数化与 CMAQ 结果横向对比考虑 CMAQ-AE5/AE6 系列注意如果你最终目的是 PM2.5 成分模拟完全可以跳过无气溶胶阶段太久毕竟气溶胶机制的行为差异很大。但第一次跑通建议还是先用简单机制。3.3 阶段三选完 chem_opt再回头检查 wrfchemi 文件能不能喂饱机制确定了chem_opt之后emiss_opt的选择就不是自由发挥了。你需要拿着手头的排放文件问自己几个问题这个wrfchemi_d01是谁生成的PREP-CHEM-SRCanthro_emiss还是直接从某个课题组分到的现成文件文件里的E_*变量清单覆盖了当前chem_opt气相机制的哪些物种文件里有没有气溶胶前体物比如E_PM25、E_EC、E_OC、E_SULF我见过太多人拿到的排放文件是为chem_opt2RADM2准备的结果换了chem_opt16CBMZ-MOSAIC之后文件里没有E_PM25或E_EC模型照样启动但气溶胶模块一直在“吃零”最终模拟出的 PM2.5 就靠气象和天然源撑着完全失真。如果你不确定当前机制需要哪些排放物种最简单的方法是把 Registry 里对应 chem 选项的物种列表调出来和ncdump -h出来的变量清单做个差集。这个习惯比在网上问“为什么 PM2.5 这么低”靠谱一万倍。3.4 配套开关怎么设phot_opt、aer_ra_feedback、drydepchem_opt和emiss_opt之外还有一组“看起来很不起眼但会联手搞事”的开关phot_opt光解频率方案。它决定 NO2、O3 等物种光解的速率从哪来。新手最稳的选择是先跟教程保持一致多数入门配置用 1 即可。如果你改用其他chem_opt要注意光解方案和机制是否兼容否则大晴天臭氧也能纹丝不动。aer_ra_feedback气溶胶辐射反馈。开成 1 后气溶胶会通过散射/吸收改变辐射通量进而影响气象场。新手强烈建议先设 0。理由很简单反馈开启会显著增加计算量还容易让气象场和化学场互相“甩锅”出了问题很难定位。gas_drydep_opt和aer_drydep_opt干沉降方案。不同版本差异很大有的机制强制要求特定干沉降选项不匹配会报错。我的建议是跑通之前先按安装包自带的例子填不要自己发明组合。3.5 时间步长与化学积分的隐性联动还有一个容易被忽略的配置dt。WRF-Chem 的气相化学积分通常是一个刚性常微分方程组虽然模式内部会做子步拆分但过大的物理步长仍然会导致某个网格点的化学物质浓度变成负值进而引发连锁的数值不稳定。如果你在 rsl.error.0000 里看到某些物种的负浓度诊断信息或者污染物图上出现规则格点状的异常低值先反思是不是为了赶进度把dt调得太大了城市尺度模拟常见做法是 3 公里网格用 18 秒或更小但这不是化学模块独有的限制气象 CFL 本身也会有要求。稳妥起见不要在官方推荐值的基础上去挑战极限。4. 报错排查的完整链路从 rsl.error 到 ncdump4.1 第一步判断崩溃发生在哪个阶段WRF-Chem 的报错信息看起来很乱但思路只有一个先确认崩溃发生在读入排放阶段、化学初始化阶段还是在积分过程中。打开运行目录执行tail -n 100 rsl.error.0000如果最后几行有forrtl: severe (174): SIGSEGV、Segmentation fault、NaN这类字眼基本可以推断是数值或数组越界问题。如果看到Error、not found、Cannot open这类字眼通常是文件缺失或变量缺失。还有一种情况是 rsl.error.0000 本身没有明显异常但 rsl.out.0000 里出现了WARNING这种最容易漏掉。我的习惯是同时打开两个文件交叉看。4.2 第二步用 grep 检查 namelist 的交叉一致性排查化学配置问题最土但最有效的方法是先把 namelist.input 里的化学相关项全部拉出来grep -nE chem_opt|emiss_opt|bio_emiss_opt|phot_opt|aer_ra_feedback|gas_drydep_opt|aer_drydep_opt namelist.input然后逐项核对所有域的chem_opt是否完全一致emiss_opt是否与chem_opt有对应关系bio_emiss_opt是否开启如果开启met_em 文件里是否有在线生物源需要的变量phot_opt是否在chem_opt允许的范围内aer_ra_feedback是否已经人为打开而气溶胶方案本身不支持这些问题在 namelist 层面就能排除掉一大半。4.3 第三步用 ncdump 检查 wrfchemi 和 wrfbdy 的内容排放文件和边界场是化学模拟的两大外部输入。检查排放文件ncdump -h wrfchemi_d01 | head -60重点看dimensions 里的emissions_zdim是否等于e_vertE_*变量名覆盖哪些物种变量的单位是否为mol km^-2 hr^-1或者类似约定Time 维有没有覆盖你完整的模拟时段检查边界场ncdump -h wrfbdy_d01 | grep -iE o3|no2|co|pm|chem如果在 wrfbdy 里完全找不到化学边界变量说明你的 real.exe 是拿一套不带化学变量的 wrfbdy 跑的化学边界场被设成了默认值。这种情况短期模拟可能还能看但超过几天污染物的区域传输就会明显失真。4.4 第四步回到编译配置确认 WRF_CHEM 真的开了这个问题听起来很基础但实际上很常见你在编译 WRF 时没有开WRF_CHEM1或者选择的是某个不支持化学的默认选项。结果 namelist 里填了chem_opt2但 wrf.exe 内部根本没有编译化学模块。报错形式多种多样有的版本会直接提示化学模块不可用有的版本干脆假装没看见chem_opt输出文件里一个化学变量都不带。所以在排查任何化学问题之前先确认一下你的 configure.wrf 里包含化学相关宏定义。如果是在集群上用的模块化环境还要确认你加载的库和编译这套 WRF 时一致否则运行阶段莫名其妙崩溃也是常事。4.5 一个真实的排查案例emiss_opt 不匹配导致的段错误我记忆很深的一次配置是 d01/d02 两层嵌套chem_opt16emiss_opt1。d01 跑得好好的一进入 d02 积分段就崩。当时我第一反应是子域边界问题检查了嵌套设置、物理参数化全都没问题。最后打开ncdump -h wrfchemi_d02发现 d02 的排放文件是从旧机器上拷贝来的文件里只有E_NO、E_NO2、E_SO2、E_CO等气相物种完全没有E_PM25、E_EC这些 MOSAIC 气溶胶需要的变量。emiss_opt1在读入 d02 排放时需要把文件里的变量映射到 CBMZ-MOSAIC 机制对应的数组里结果找不到关键变量数组长度不匹配于是段错误。后来我用 Python 脚本把缺失的气溶胶物种变量补 0生成新的 wrfchemi_d02问题立刻消失。这个案例给我最大的教训是排放文件不是你改个变量名就能通用的它必须和chem_opt的物种需求严格对应。5. 一份可以直接抄的 namelist 最小可用配置模板5.1 基础配置模板单域版以下模板适用于 WPS 已经跑通、气象初边场已生成、met_em文件齐全的单域模拟场景。化学部分我以chem_opt2RADM2emiss_opt1为例这是相对稳定、报错少、适合第一次跑通化学的组合。time_control run_days 2, run_hours 0, run_minutes 0, run_seconds 0, start_year 2023, start_month 06, start_day 01, start_hour 00, end_year 2023, end_month 06, end_day 03, end_hour 00, restart .false., io_form_auxinput2 2, / domains time_step 18, e_we 100, e_sn 100, e_vert 45, dx 3000, dy 3000, / physics mp_physics 8, ra_lw_physics 4, ra_sw_physics 4, radt 10, sf_sfclay_physics 1, sf_surface_physics 2, bl_pbl_physics 1, bldt 0, cu_physics 1, / chem chem_opt 2, emiss_opt 1, bio_emiss_opt 1, phot_opt 1, aer_ra_feedback 0, gas_drydep_opt 1, aer_drydep_opt 1, /注意gas_drydep_opt、aer_drydep_opt这两个参数在不同版本里的默认要求和取值范围差异较大我的模板给出的是一个在大版本 v4.x 常见配置里能跑通的值但你在动手之前仍然要打开自己安装目录下的 Registry/Registry.EM_COMMON 或 chem 相关 Registry 文件确认这几个选项是否支持。这不是啰嗦是每个跑过 WRF-Chem 的人都会养成的肌肉记忆。5.2 模板里每一项为什么这样设chem_opt2RADM2 是公认比较稳健的气相机制资料最多配套的排放映射说明也最齐全。新手用它起步能在最大程度上避免“机制本身太新、教材还没跟上”的问题。emiss_opt1对应标准人为排放文件接口也是 PREP-CHEM-SRC 等老牌预处理工具默认输出的格式。它要求E_*变量命名规范对新手来说最容易自查。bio_emiss_opt1开启在线生物源排放。如果只是验证流程可以先设 0但对于夏季污染过程模拟不开生物源会让臭氧模拟明显偏低。phot_opt1常见的光解频率方案与 RADM2 机制配合成熟。aer_ra_feedback0第一次跑通化学别开气溶胶辐射反馈。先把化学与气象的“单向耦合”跑明白再去碰双向反馈否则问题来的时候你根本分不清是化学算错还是气象被反馈改了。gas_drydep_opt1、aer_drydep_opt1开启标准干沉降。如果编译时没有配套的沉降模块这里可能会报错对应版本查一下 Registry 即可。5.3 运行前自检清单我每次提交 WRF-Chem 任务前都会过一遍下面这组问题能拦截掉绝大多数低级事故[ ] 所有嵌套域的chem_opt是否完全一致[ ]emiss_opt对应的排放文件是否存在文件名里的日期是否完整覆盖模拟时段[ ]wrfchemi_*文件的垂直层数是否等于e_vert[ ]wrfchemi_*文件里的E_*变量是否覆盖当前机制需要的关键物种尤其是气溶胶前体物[ ] wrfbdy 里是否包含化学边界变量还是全靠默认背景值[ ] 如果restart.true.restart 文件是否来自相同chem_opt配置[ ] 编译时是否开启了 WRF_CHEM且运行环境与编译环境一致[ ] 计划模拟时长是否足够覆盖化学 spin-up至少不能把前 12 小时当有效结果这套清单我一开始也没有全是被各种“跑完才发现”的坑教会了才总结出来的。你按这个顺序排查一轮至少能省下几天在论坛翻帖子的时间。我自己后来养成的习惯是每次修改 namelist 之前先把原始文件备份一份并直接在文件头部注释里写清楚“这一次改了哪些参数、为什么改”。看似很笨但在多嵌套、多实验组对比的时候这种记录能救命。WRF-Chem 的参数组合太自由自由到每一个“我记得我好像改过什么”的时刻都可能是下一轮熬夜排查的开始。对新手来说与其急着上最复杂的机制不如先跑通一套最小可用组合再一步一步往里面加东西。
返回列表