
1. 项目概述从零构建大气污染模拟的“数字实验室”如果你正在读这篇文章大概率和我一样是个和环境模型、大气科学或者高性能计算打交道的“手艺人”。我们面对的往往不是现成的软件包而是一堆需要自己编译、链接、配置的源代码。CMAQCommunity Multiscale Air Quality modeling system和它的“黄金搭档”WRFWeather Research and Forecasting model就是这类工作中的典型代表。它们共同构成了一个从气象场驱动到大气化学过程模拟的完整链条是科研和业务预报中不可或缺的工具。然而CMAQ5.2的安装过程尤其是与WRF的联调堪称一场对系统知识、耐心和排错能力的综合考验。网上能找到的教程要么年代久远要么语焉不详或者就是某个特定系统下的“幸运记录”换个环境就遍地是坑。我最近在Ubuntu 22.04 LTS系统上从零开始完整走通了一遍CMAQ5.2包含其所需的I/O API、netCDF库等以及WRF含WPS的编译安装并成功运行了测试案例。这个过程踩遍了能想到的几乎所有坑也总结出了一套相对稳定、可复现的流程。这篇记录的目的就是把我这套“成功版”的安装经验包括每个步骤背后的原理、关键配置的选择、以及那些官方文档不会告诉你的“暗坑”完整地分享出来。无论你是刚接触模式的新手还是被旧教程折磨已久的老手希望这篇超过5000字的详实指南能帮你搭建起一个稳固的模拟环境把时间更多地花在科学问题上而不是和编译错误作斗争。2. 环境准备与基础依赖库部署安装像CMAQ和WRF这样的大型科学计算软件第一步不是急着下载源代码而是打造一个坚实、纯净的基础环境。这就像盖房子前先打好地基地基不稳后面所有的构建都可能是徒劳。我强烈建议在一个新安装的Ubuntu 22.04 LTS系统上进行避免残留的旧库文件引发难以排查的冲突。2.1 系统更新与编译环境搭建首先我们需要一个完整的编译工具链和必要的开发库。打开终端执行以下命令sudo apt update sudo apt upgrade -y sudo apt install -y build-essential gcc gfortran g make m4 csh tcsh git curl wget perl python3 python3-dev libcurl4-openssl-dev autoconf automake cmake libtool zip unzip这里解释几个关键点build-essential 这是Ubuntu下编译软件的基础元包包含了gcc, g, make, libc-dev等核心工具。没有它后续编译无从谈起。gfortran Fortran编译器。WRF和CMAQ的绝大部分代码是用Fortran尤其是F90写的这是绝对的核心依赖。csh/tcsh C Shell。CMAQ的编译脚本bldit和运行脚本大量使用了csh语法虽然你可以通过修改脚本或设置兼容环境来避免但直接安装是最省事的办法。m4 一个宏处理器。在编译某些底层库如MPICH时configure脚本会用到它。注意 有些极简的服务器系统或Docker基础镜像可能默认没有安装gfortran务必确认其已成功安装并用gfortran --version检查版本。建议使用系统仓库提供的稳定版本如Ubuntu 22.04的gcc-11系列避免使用过于前沿或陈旧的版本。2.2 核心依赖库netCDF-C与netCDF-Fortran的精准安装netCDFNetwork Common Data Form是地球科学领域事实上的标准数据格式CMAQ和WRF的输入输出都重度依赖它。这里有个最大的坑必须严格按照顺序先安装C库再安装Fortran库并且确保Fortran库链接到正确的C库版本。很多安装失败都是因为这两个库的版本不匹配或路径混乱。第一步安装netCDF-C库我们选择从源码编译安装以便更好地控制安装路径和编译选项。我选择安装在/opt目录下方便集中管理。# 创建并进入软件安装目录 sudo mkdir -p /opt/software/src /opt/software/netcdf cd /opt/software/src # 下载稳定版本的netCDF-C源码以4.9.2为例这是一个广泛兼容的版本 wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v4.9.2.tar.gz tar -xzvf v4.9.2.tar.gz cd netcdf-c-4.9.2 # 配置、编译、安装 # --prefix 指定安装路径 # --disable-dap 禁用不常用的DAP远程访问功能简化依赖 # CCgcc 指定C编译器 mkdir build cd build CCgcc ../configure --prefix/opt/software/netcdf --disable-dap make -j$(nproc) # 使用所有CPU核心并行编译加快速度 sudo make install安装完成后将库路径和头文件路径添加到系统环境变量中这是关键一步# 编辑你的shell配置文件如 ~/.bashrc echo export NETCDF/opt/software/netcdf ~/.bashrc echo export PATH$NETCDF/bin:$PATH ~/.bashrc echo export LD_LIBRARY_PATH$NETCDF/lib:$LD_LIBRARY_PATH ~/.bashrc echo export CPPFLAGS-I$NETCDF/include $CPPFLAGS ~/.bashrc echo export LDFLAGS-L$NETCDF/lib $LDFLAGS ~/.bashrc source ~/.bashrc第二步安装netCDF-Fortran库现在在netCDF-C的基础上安装Fortran接口。cd /opt/software/src wget https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v4.6.1.tar.gz tar -xzvf v4.6.1.tar.gz cd netcdf-fortran-4.6.1 mkdir build cd build # 关键配置指定Fortran编译器并确保找到上一步安装的netcdf-c FCgfortran ../configure --prefix/opt/software/netcdf make -j$(nproc) sudo make install验证安装是否成功nc-config --all # 查看netcdf-c配置 nf-config --all # 查看netcdf-fortran配置确认nf-config输出的includedir和libdir指向的是我们自定义的/opt/software/netcdf路径并且版本信息正确。2.3 并行环境选择MPICH vs OpenMPICMAQ和WRF都支持并行计算以加速模拟。你需要选择一个MPIMessage Passing Interface实现。MPICH和OpenMPI是最常见的两个选择。根据我的经验对于CMAQ和WRFMPICH的兼容性和稳定性通常更好特别是WRF的某些版本与新版OpenMPI可能存在链接问题。cd /opt/software/src wget https://www.mpich.org/static/downloads/4.1.2/mpich-4.1.2.tar.gz tar -xzvf mpich-4.1.2.tar.gz cd mpich-4.1.2 # 配置安装路径并指定Fortran编译器 ./configure --prefix/opt/software/mpich FCgfortran CCgcc CXXg make -j$(nproc) sudo make install同样将MPICH加入环境变量echo export MPI_ROOT/opt/software/mpich ~/.bashrc echo export PATH$MPI_ROOT/bin:$PATH ~/.bashrc echo export LD_LIBRARY_PATH$MPI_ROOT/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc验证执行mpif90 --version和mpirun --version应显示MPICH的信息。实操心得 我强烈建议将所有这些自定义安装的库netCDF, MPICH放在一个独立的目录下如/opt/software。这样做有两大好处一是与系统自带的库完全隔离避免污染和冲突二是当需要清理或重建时直接删除整个目录即可非常干净。此外在编译任何上层软件WRF/CMAQ之前务必source ~/.bashrc或开一个新的终端确保环境变量生效。3. WRF模型系统编译详解WRF为CMAQ提供精确的气象驱动场其编译是第一个真正的挑战。WRF编译是一个高度自动化的过程但自动化背后隐藏着许多配置选择。3.1 获取源码与基础配置首先从官方仓库获取稳定版本的源码。我使用WRF V4.5这是一个经过充分测试的版本。cd /opt/software/src wget https://github.com/wrf-model/WRF/archive/refs/tags/v4.5.tar.gz tar -xzvf v4.5.tar.gz cd WRF-4.5在编译之前需要运行configure脚本。这个脚本会检测你的系统环境并让你选择编译选项。./configure你会看到一个交互式选择界面。这里的选择至关重要选择编译器组合 你会看到类似34. (dmpar) GNU (gfortran/gcc)的选项。这里dmpar代表分布式内存并行即使用MPI。因为我们安装了MPICH所以应该选择包含dmpar且对应GNU编译器的选项。数字编号可能因版本而异请仔细阅读描述。通常选择34. (dmpar) GNU (gfortran/gcc)。编译类型 接下来会问Compile for nesting?通常选择1基本嵌套这对于大多数应用包括驱动CMAQ已经足够。选择完成后脚本会生成一个configure.wrf文件。不要急着编译我们需要手动检查并修改这个文件。3.2 关键配置修改与编译排错用文本编辑器打开configure.wrf找到以下几行并进行核对或修改# 检查并确认以下宏定义指向正确的路径和库 SFC gfortran SCC gcc CCOMP gcc DM_FC mpif90 DM_CC mpicc # 这是关键确保NETCDF路径设置正确 NETCDFPATH /opt/software/netcdf有时候自动检测的NETCDFPATH可能不对务必手动修改为你安装netCDF的路径。同时检查文件中-L和-I的链接选项是否包含了$(NETCDFPATH)/lib和$(NETCDFPATH)/include。现在开始编译。WRF编译分为两个阶段# 第一阶段编译依赖工具和基础框架 ./compile em_real 21 | tee compile.logem_real代表“真实数据的中尺度模拟”这是我们需要的模式。21 | tee compile.log将屏幕输出同时保存到日志文件便于后续排查错误。这个过程会持续较长时间取决于CPU核心数。编译结束后检查是否成功查看主要可执行文件 在main目录下应生成ndown.exereal.exewrf.exe。使用ls -lah main/*.exe查看。检查日志结尾 查看compile.log文件的最后部分寻找Executables built successfully之类的成功信息。常见错误排查mpif90: command not found MPI环境变量未生效。确认source ~/.bashrc且which mpif90路径正确。NetCDF库找不到 通常是NETCDFPATH设置错误或环境变量LD_LIBRARY_PATH未包含netCDF的lib路径。手动在configure.wrf中修正路径。Fortran语法错误 可能是gfortran版本与WRF代码兼容性问题。尝试在configure.wrf中的FCFLAGS或FFLAGS里添加-fallow-argument-mismatch对于较新的gfortran如gcc-11以允许某些历史代码的参数不匹配警告。内存不足 编译过程消耗大量内存。如果是在虚拟机上请确保分配了足够的内存建议至少4GB。可以尝试使用./compile -j 1 em_real减少并行编译任务数。3.3 WPSWRF预处理系统编译WRF模式需要经过预处理的输入数据这就是WPS的工作。其编译相对独立。cd /opt/software/src wget https://github.com/wrf-model/WPS/archive/refs/tags/v4.5.tar.gz tar -xzvf v4.5.tar.gz cd WPS-4.5首先需要配置环境指向我们编译好的WRF目录和netCDF库# 设置环境变量WPS的configure脚本会读取它们 export WRF_DIR/opt/software/src/WRF-4.5 export NETCDF/opt/software/netcdf然后运行配置脚本./configure在出现的选项中选择与之前WRF编译时完全相同的并行选项例如同样是3. Linux x86_64, gfortran (dmpar)。这会生成configure.wps文件。同样建议检查configure.wps中的NETCDF路径是否正确指向/opt/software/netcdf。开始编译./compile 21 | tee wps_compile.log成功编译后会在当前目录下生成三个关键的可执行文件geogrid.exe 处理静态地理数据地形、土地利用等。ungrib.exe 从GRIB格式的气象分析/预报数据中提取变量。metgrid.exe 将ungrib提取的变量插值到geogrid定义的网格上。使用ls -lah *.exe检查它们是否存在。至此WRF模型系统安装完毕。注意事项 WRF和WPS的版本最好保持一致如都是V4.5。混合使用不同大版本可能会导致接口不兼容。编译过程中如果遇到错误第一件事就是查看compile.log或wps_compile.log中错误信息出现位置附近的详细输出绝大多数问题都有明确的错误提示。4. CMAQ5.2核心库与主程序编译CMAQ的编译结构比WRF更模块化它依赖于几个额外的库并且其主程序CCTM的编译选项与机器架构紧密相关。4.1 获取CMAQ源码与第三方库I/O API, BLISSCMAQ的源代码和所需库可以从US EPA的CMAS中心网站或GitHub仓库获取。这里我们使用一个包含所有依赖的稳定版本。cd /opt/software # 假设下载的压缩包为 CMAQ-5.2.1.tar.gz tar -xzvf CMAQ-5.2.1.tar.gz cd CMAQ-5.2.1解压后目录结构通常包含DOCS/ 文档。PREP/ 数据预处理工具源码如ICON, BCON。CCTM/ 核心化学传输模型源码。POST/ 后处理工具源码。LIB/ 需要手动编译的第三方库目录。首先我们需要编译两个关键的第三方库I/O API和BLISS一个用于生成化学机理文件的工具某些安装包可能已包含编译好的版本。编译I/O APII/O API是CMAQ用于读写netCDF格式文件的接口库必须首先正确编译。cd LIB/ioapi-3.2 # 编辑 Makefile 或 Makeinclude 文件 # 关键是要设置好 NETCDF 和 MPI 的路径 # 通常需要修改 Makeinclude.linux4_gfortran或其他类似文件 cp Makeinclude.linux4_gfortran Makeinclude.my_linux vim Makeinclude.my_linux在Makeinclude.my_linux中你需要修改或确认以下变量BIN Linux4_x86_64gfort # 或根据你的系统修改 # 指定编译器 CC gcc FC gfortran # 指定MPI编译器如果使用并行IO MPI -DMPI MPIFC mpif90 # 最关键指定netCDF库的路径 NETCDF /opt/software/netcdf # 包含头文件和库 INC -I$(NETCDF)/include -I$(NETCDF)/lib LIB -L$(NETCDF)/lib -lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz -lm保存后使用这个自定义的配置文件进行编译make -f Makefile MYLINKmy_linux编译成功后在Linux4_x86_64gfort或你指定的BIN目录下会生成libioapi.a等库文件。记下这个库文件的完整路径后续编译CMAQ主程序时需要。4.2 配置CMAQ编译环境bldit脚本与配置CMAQ使用一套名为bldit的csh脚本和config.cmaq配置文件来驱动编译。我们需要先配置环境变量。进入CMAQ主目录通常有一个config_cmaq.csh或类似的模板文件。复制一份并进行编辑cd /opt/software/CMAQ-5.2.1 cp config_cmaq.csh config_my_linux.csh vim config_my_linux.csh需要修改的关键环境变量包括setenv CMK_HOME /bin/pwd # CMAQ主目录通常自动获取 setenv CMK_BUILD uname -s_uname -m # 构建目录名如Linux_x86_64 setenv CMK_TARGET uname -s_uname -m # 目标目录名同上 # 编译器设置 setenv FC mpif90 # 使用MPI Fortran编译器 setenv CC gcc # C编译器 # 库路径设置 - 这是核心 setenv NETCDF /opt/software/netcdf setenv IOAPI_INCL_DIR /opt/software/CMAQ-5.2.1/LIB/ioapi-3.2/Linux4_x86_64gfort # I/O API头文件路径 setenv IOAPI_LIB_DIR /opt/software/CMAQ-5.2.1/LIB/ioapi-3.2/Linux4_x86_64gfort # I/O API库文件路径 setenv MPI_INCL_DIR /opt/software/mpich/include # MPI头文件路径通常自动检测 setenv MPI_LIB_DIR /opt/software/mpich/lib # MPI库文件路径 # 编译选项 setenv myCplr -openmp # 或 -fopenmp根据编译器启用OpenMP setenv myMath -lm # 数学库 setenv myOpt -O3 -funroll-loops -ftree-vectorize # 优化选项保存配置文件后加载它source config_my_linux.csh4.3 编译CCTM化学传输模型主程序CCTM是CMAQ的核心模拟引擎。其编译过程通过运行bldit脚本完成。cd CCTM/scripts # 运行bldit脚本指定配置文件和构建版本 ./bldit_cctm.csh my_linux gcc | tee bldit.log这个脚本会读取config_my_linux.csh中的配置。在CCTM/scripts目录下创建一个以构建版本如gcc命名的子目录如BLD_gcc。进入该目录生成Makefile并开始编译。编译过程较长请耐心等待。成功的关键标志是在BLD_gcc目录下生成了名为cctm_*的可执行文件如cctm_gcc。编译失败怎么办这是最可能出问题的环节。首先查看日志 仔细阅读bldit.log和BLD_gcc目录下的编译输出文件错误信息通常很明确。常见错误1找不到I/O API库或netCDF库。检查config_my_linux.csh中IOAPI_LIB_DIR和NETCDF的路径是否正确以及这些路径下是否存在对应的.a或.so库文件。常见错误2MPI函数未定义引用。确认FC设置为mpif90并且MPI_LIB_DIR路径正确包含了MPI的库文件如libmpi.so。常见错误3Fortran模块文件.mod找不到。检查IOAPI_INCL_DIR是否包含了I/O API生成的.mod文件。有时需要手动将ioapi-3.2编译目录下的.mod文件复制到IOAPI_INCL_DIR指向的目录。降低优化等级 如果遇到奇怪的段错误或优化相关的错误可以尝试在config_my_linux.csh中将myOpt从-O3改为-O2或-O1先保证编译通过。5. 环境集成、测试与实战排错指南当WRF和CMAQ都编译出可执行文件后工作只完成了一半。让它们协同工作并确保能成功运行一个测试案例才是真正的挑战。5.1 环境变量最终整合与路径设置为了在任何终端会话中都能方便地调用WRF和CMAQ我们需要将所有的关键路径整合到shell的配置文件中。编辑你的~/.bashrc文件在末尾添加以下内容# WRF CMAQ Environment export WRF_HOME/opt/software/src/WRF-4.5 export WPS_HOME/opt/software/src/WPS-4.5 export CMAQ_HOME/opt/software/CMAQ-5.2.1 # NetCDF export NETCDF/opt/software/netcdf export PATH$NETCDF/bin:$PATH export LD_LIBRARY_PATH$NETCDF/lib:$LD_LIBRARY_PATH export CPPFLAGS-I$NETCDF/include $CPPFLAGS export LDFLAGS-L$NETCDF/lib $LDFLAGS # MPI (MPICH) export MPI_ROOT/opt/software/mpich export PATH$MPI_ROOT/bin:$PATH export LD_LIBRARY_PATH$MPI_ROOT/lib:$LD_LIBRARY_PATH # I/O API (根据你的实际编译路径调整) export IOAPI/opt/software/CMAQ-5.2.1/LIB/ioapi-3.2/Linux4_x86_64gfort export LD_LIBRARY_PATH$IOAPI:$LD_LIBRARY_PATH # 将WRF和CMAQ的可执行文件目录加入PATH可选建议使用绝对路径调用 # export PATH$WRF_HOME/main:$WPS_HOME:$CMAQ_HOME/CCTM/scripts/BLD_gcc:$PATH # WRF CMAQ Environment 保存后执行source ~/.bashrc使配置生效。现在你可以通过echo $WRF_HOME等命令来验证环境变量是否设置正确。5.2 运行测试案例从WRF到CMAQ的完整链路一个完整的测试通常包括以下步骤这能验证整个工具链是否通畅1. WPS地理数据处理进入$WPS_HOME你需要下载静态地理数据geogrid数据包体积很大。配置namelist.wps运行./geogrid.exe生成静态地形文件。对于简单的测试可以使用WPS自带的test/目录下的小规模示例数据。2. WPS气象数据处理下载GRIB格式的初始气象场数据如NCEP FNL数据。配置namelist.wps中的ungrib和metgrid部分依次运行./ungrib.exe和./metgrid.exe生成met_em.*.nc文件。3. WRF真实数据模拟将met_em.*.nc文件链接或复制到$WRF_HOME/test/em_real目录。进入该目录仔细配置namelist.input时间、区域、物理参数化方案等。首先运行./real.exe将met_em文件处理为WRF可读的初始和边界条件文件wrfinput_d01,wrfbdy_d01。如果成功再运行./wrf.exe进行积分模拟输出wrfout_d01_*文件。4. MCIP气象化学接口处理器处理CMAQ不能直接使用wrfout文件。你需要使用MCIP工具位于CMAQ的PREP/mcip/src目录下需要单独编译将wrfout文件转换为CMAQ需要的GRID,METCRO2D/3D等文件。这需要配置一个MCIP控制文件run.mcip指定输入输出文件和时间段。5. 其他CMAQ前处理ICON, BCON根据你的模拟需求可能还需要运行ICON生成初始条件和BCON生成边界条件程序。它们位于CMAQ的PREP目录下同样需要编译和配置。6. 运行CCTM这是最后一步。进入$CMAQ_HOME/CCTM/scripts目录你会找到一个示例运行脚本如run_cctm.csh。你需要根据你的测试案例修改这个脚本设置正确的输入文件路径GRID,MET,ICON,BCON等。配置化学机理Mechanism例如cb6r3_ae7_aq。设置模拟的起始和结束时间、输出频率等。指定正确的可执行文件路径指向你编译好的cctm_gcc。运行脚本./run_cctm.csh | tee run.log。如果一切顺利你将看到模型开始迭代计算并最终生成一系列输出文件如CONC,DRYDEP,WETDEP等。5.3 典型问题排查与解决技巧即使按照指南操作你也可能遇到问题。以下是我在实战中总结的排查清单问题运行./real.exe或./wrf.exe时立即段错误Segmentation fault。排查 这通常是编译问题或库不匹配。首先回到WRF目录运行./clean -a彻底清理然后重新configure并编译。在configure.wrf中尝试将优化选项-O3改为-O2或-O0调试模式。确保NETCDFPATH绝对正确。如果使用虚拟机检查是否分配了足够内存。问题CMAQ的CCTM编译失败提示undefined reference to ‘nf_open_’等netCDF函数。排查 这是经典的链接顺序问题。netCDF的Fortran库(libnetcdff)依赖于C库(libnetcdf)。在链接时-lnetcdff必须放在-lnetcdf之前。检查config_my_linux.csh或bldit脚本生成的Makefile中的LIB或LDFLAGS变量顺序确保是-lnetcdff -lnetcdf ...。问题运行CCTM时提示找不到动态库.so文件例如libnetcdff.so.7: cannot open shared object file。排查 动态链接库路径未设置。确保LD_LIBRARY_PATH环境变量包含了netCDF、MPI和I/O API的所有库目录。可以用ldd /path/to/your/cctm_executable命令检查可执行文件依赖的库是否能全部找到。问题MCIP运行出错提示网格维度不匹配。排查 WRF输出的域domain定义与你在MCIP控制文件中指定的不一致。仔细核对namelist.input中的e_we,e_sn网格点数和dx,dy网格距确保它们与MCIP输入设置完全一致。同时检查地图投影参数map_proj,truelat1等。问题模型运行结果异常如浓度全为0或出现极大/极小值。排查 首先检查输入文件。用ncdump -h查看关键的输入netCDF文件如GRID,METCRO3D的变量和维度信息确保数据看起来合理没有NaN数值在物理范围内。其次检查CCTM的运行日志看是否有警告Warning或错误Error信息。最后从一个极短时间如1小时的模拟开始并输出每一步的调试信息在CCTM运行脚本中设置更高的输出日志级别逐步定位问题源头。终极建议 保持耐心仔细阅读错误信息。科学计算软件的编译错误信息通常非常直接会明确指出是哪个文件、哪一行、哪个函数出了问题。善用搜索引擎但要注意信息的时效性。将你的错误信息直接复制搜索往往能找到在GitHub Issues或专业论坛上的相关讨论。记录下你每一次成功的配置和每一步操作这将成为你最宝贵的财富。