ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

WRF与WPS编译实战:从环境配置到常见报错排查指南

2026/9/16 7:25:14 拓冰建站 浏览量
WRF与WPS编译实战:从环境配置到常见报错排查指南 写这篇东西的时候我刚帮一位师弟折腾完一台新服务器上的WRF和WPS。他对着屏幕上的编译报错一脸茫然我一看又是那个“循环依赖”的老问题。说实话WRF和WPS的安装编译本身不难真正磨人的是那些藏在细节里的坑环境变量差一个、库的编译器不一致、configure选项选错都能让你在同一个地方卡上好几天。这篇文章就是把我在x86_64 Linux平台上用gfortran工具链编译WRF 4.x和WPS过程中遇到的高频问题、排查链路和最终解法完整记录下来给正在被configure、compile日志折磨的人做一个参考。1. 装WRF前先把这几个模块之间的关系理清楚很多新人上来就直接./configure然后./compile报错之后就懵了根本不知道错在哪里。我建议先花十分钟搞清楚WRF和WPS到底由哪些部分组成以及它们之间是怎么配合的这样再去排查问题会快很多。1.1 WRF和WPS不是同一个东西模块构成与编译产物WRFWeather Research and Forecasting是大气模式的主体编译之后会生成wrf.exe、real.exe、ndown.exe这几个可执行文件。其中real.exe负责把气象分析场数据插值到WRF的网格上wrf.exe才是真正跑时间积分的核心程序。WPSWRF Preprocessing System是WRF的预处理系统它在WRF之前运行充当“数据预处理网格生成”的角色。WPS编译之后会生成三个工具geogrid.exe负责定义模拟区域并把地理静态数据插值到网格上ungrib.exe负责把GRIB格式的气象数据解压成中间格式metgrid.exe再把ungrib出来的气象数据和geogrid的地理数据合并成WRF的初始场和边界场输入文件。简单来说处理流程是WPS的geogrid生成geo_em文件ungrib生成中间文件metgrid合并为met_em文件然后real.exe读met_em生成wrfinput和wrfbdy最后wrf.exe跑积分。所以WPS编译失败会直接卡住后面的整条链路而WPS又依赖netCDF和GRIB2相关的库这就是坑的起点。1.2 依赖库之间的“环环相扣”才是最大的坑WRF和WPS编译依赖的库不是孤立的它们之间有明显的前置关系。以最常见的GNU工具链为例你至少需要以下这些组件netCDF-C提供C接口、netCDF-Fortran提供Fortran接口、MPICH提供并行环境、zlib、libpng、jasperWPS处理GRIB2数据需要。这里就要强调一个很多人忽略的问题netCDF-C和netCDF-Fortran是分开的两个包。老版本教程里一个netcdf就够了但新版本4.x之后官方把Fortran接口拆了出来。如果你只装了netcdf-cWRF编译时会出现undefined reference to nc_open这类链接错误因为它确实找到了netcdf的头文件但找不到Fortran接口的符号。另一个关键点是编译器一致性。用gcc编译netcdf-c用gfortran编译netcdf-fortran再让WRF用gfortran去链接这通常没问题因为netcdf-fortran在configure时已经通过LD_LIBRARY_PATH找到了netcdf-c的库。但如果你中间混入了Intel编译器编译的库那就非常容易在运行时出现奇怪的浮点错误甚至直接崩溃。我踩过一次ifort和gfortran混用的坑最后全用gcc/gfortran重编才稳定。1.3 新手先选gcc/gfortran不要一上来就纠结Intel英特尔编译器ifort/icc在WRF上的性能确实有优势但它的安装、授权和mpi配合对新手一点都不友好。对于绝大多数学习和科研场景GNU工具链完全够用而且社区资料最多报错也容易被搜索引擎找到。等你自己能熟练处理gfortran链路之后再换ifort也不迟。典型的工具链版本组合是gcc/gfortran 9.x以上MPICH 3.3.x以上netcdf-c 4.7.x以上netcdf-fortran 4.5.x以上。不要盲目追求最新版本WRF和WPS这类大型Fortran项目对过新的编译器也可能有未知问题当然也不要太老否则有些新语法不支持。总之用发行版自带或者官方稳定版即可。2. 依赖库编译阶段的错误大多能提前避开依赖库的编译是整个链条里最枯燥却又最关键的环节。我把每一步常见报错和排查经验列出来你照着做能省下很多时间。2.1 netCDF的经典报错明明装了为什么configure还找不到WRF和WPS的configure脚本都会去查NETCDF这个环境变量所以最常见的报错就是ERROR: NetCDF not found这时候你要做的第一件事不是去网上搜而是先检查环境变量echo $NETCDF如果输出是空的那问题就在这儿。在bash里设置export NETCDF/opt/netcdf export PATH$NETCDF/bin:$PATH export LD_LIBRARY_PATH$NETCDF/lib:$LD_LIBRARY_PATH注意NETCDF要指向安装netcdf目录的根目录不是/opt/netcdf/lib不是/opt/netcdf/bin更不是/opt/netcdf/include。我见过有人把NETCDF设成/opt/netcdf/lib然后跑configure报错一直说找不到后来检查环境变量才发现这个低级错误。还有一个坑是如果你用的是csh/tcsh语法应该是setenv NETCDF /opt/netcdf。不要把你的bash export直接粘到.cshrc里用shell语法不兼容照样白搭。2.2 netcdf-fortran没装是第二高频的坑确认NETCDF变量没问题之后还是会遇到类似undefined reference to nc_open undefined reference to nf_create出现这个十有八九是netcdf-fortran没有安装。编译netcdf-c本身不难./configure --prefix/opt/netcdf --disable-dap make -j4 make install但在这之后你还需要单独编译netcdf-fortran。而且有个顺序问题必须先保证netcdf-c已经装好并且LD_LIBRARY_PATH里能找得到它的库再编译netcdf-fortran否则它检测不到netcdf-c会报错退出。编译netcdf-fortran时还要把netcdf的库路径导出来export LD_LIBRARY_PATH/opt/netcdf/lib:$LD_LIBRARY_PATH export CPPFLAGS-I/opt/netcdf/include export LDFLAGS-L/opt/netcdf/lib ./configure --prefix/opt/netcdf make -j4 make install装完之后可以到/opt/netcdf/lib里确认一下有没有libnetcdff.so或libnetcdff.a有这个文件才说明Fortran接口装好了。2.3 MPICH编译时非常容易忽略的两个细节MPICH本身编译比较简单最常见的坑有两个。第一个是configure阶段提示找不到Fortran编译器这多半是因为你的PATH里没有gfortran或者gfortran版本太老换成9.x以上的gfortran即可。第二个坑比较隐蔽MPICH安装完之后一定要检查它的mpif90到底指向哪个Fortran编译器用mpif90 -v看一下。为什么这个重要因为WRF configure会通过mpif90来检测MPI环境如果这个mpif90来自另一个MPI实现比如OpenMPI或者系统自带的MPI那么后续WRF编译时可能会出现库接口不匹配的问题。尤其是你之前还装过Anacondaconda环境里的mpich可能把PATH搅乱了。我遇到过WRF configure正常但compile时链接一堆MPI符号错误最后发现是which mpif90指向了conda里的一个版本和系统MPICH冲突。解决办法很简单把MPICH的bin目录放到PATH最前面或者干脆移除conda的mpi相关包。2.4 zlib、libpng、jasper这组GRIB2依赖WPS的地形数据不依赖但grib2数据依赖WPS编译时需要有GRIB2的支持否则ungrib在处理现代的GFS数据时会心有余而力不足。需要安装zlib、libpng、jasper这三个库。很多人在编译jasper时会遇到configure: error: in /home/user/jasper-2.0.33: configure: error: C compiler cannot create executables这个报错通常不是jasper本身的问题而是缺少依赖的头文件例如libpng的include路径不在系统默认搜索路径里。一个比较稳妥的处理是把它们都统一安装到一个前缀下比如/opt/grib2./configure --prefix/opt/grib2 make -j4 make install安装顺序是zlib → libpng → jasper。在编译libpng和jasper之前同样要把前一阶段安装目录的bin、include、lib路径加进环境变量export PATH/opt/grib2/bin:$PATH export CPPFLAGS-I/opt/grib2/include export LDFLAGS-L/opt/grib2/libWPS的configure脚本会要求设置JASPERLIB和JASPERINC两个变量分别指到jasper的lib和include目录。如果你的jasper装在/opt/grib2那么export JASPERLIB/opt/grib2/lib export JASPERINC/opt/grib2/include这里有个细节JASPERINC一定是include目录不是某个头文件的完整路径。网上有帖子写export JASPERINC/opt/grib2/include/jasper.h那是错的configure脚本要用的是目录名。3. WRF主程序编译时的报错排查我不信只有我卡过这些依赖库都到位之后WRF主程序的编译相对顺利但依然有几个经典的报错场景。我按阶段来拆解。3.1 configure阶段的选择dmpar、嵌套级别和grib2的选项要选对在WRF目录下执行./configure会让选择操作系统和编译器组合比如Linux x86_64 gfortran (dmpar)后面括号里的serial表示串行、smpar表示共享内存并行、dmpar表示分布式内存并行。对绝大多数需要跑高分辨率模拟的场景选dmpar因为它能在多节点上扩展smpar只适合单节点serial就是玩具。接下来是嵌套选项1basic、2advanced、3benchmark。如果你只是为了跑通默认案例basic也够但如果你要在真实研究中用嵌套网格建议选advanced它支持更灵活的网格交互设置。选错不会导致编译失败但可能会影响后续namelist里的某些选项支持。configure完成后看看configure.wrf文件里相关设置是否正常。有个很实用的小技巧打开configure.wrf搜索NETCDF关键字确认路径和头文件都指到了你安装的netcdf目录。如果这里不对后面编译一定报错。3.2 compile阶段最常见的三类报错及定位方式WRF编译命令一般这么按./compile em_real 21 | tee compile.log注意把输出同时写到compile.log方便后面追查。compile过程中最常见的是以下三类错误。第一类是找不到netcdf相关的库或头文件报错形如/opt/netcdf/include/netcdf.inc: No such file or directory或者链接阶段cannot find -lnetcdff前者说明netcdf-inc路径没配对后者说明netcdff库没装在系统搜索路径里。确认configure.wrf里的NETCDFPATH是否指向netcdf根目录并且LD_LIBRARY_PATH包含了netcdf的lib目录。第二类是内存或栈空间相关的段错误。WRF编译时部分Fortran文件需要很大的栈帧如果编译进程直接崩溃而且日志尾部出现signal SIGSEGV或Killed先执行ulimit -s unlimited然后重新编译。这个命令只对当前shell有效所以编译前要记得再执行一次。很多教程里提到“编译WRF时莫名其妙被内核killed”十有八九就是栈限制。第三类是链接时MPI符号冲突。日志里出现大量Multiple definition of MPI_Comm_rank之类的重复定义基本可以判定是MPI库混乱前面2.3小节已经说过原因这里就不再重复。3.3 compile.log和rsl.error.0000是排查问题的核心依据很多新手编译一失败就重来其实WRF自带的编译日志已经给出了足够的信息。编译失败时先用grep找错误关键字grep -i error compile.log | head -50如果段错误或者Killed是浮层问题再看quick build脚本输出。定位到具体是哪个.c或.f90文件编译失败后去搜这个文件名基本能找到方向。WRF编译过程中还会生成rsl.error.0000这类运行日志文件虽然多数时候是空的但如果出现文件可以提前暴露IO权限问题。另外强烈建议整个编译过程不要开多个./compile进程也不要在同一个目录里反复改configure选项。WRF的构建系统对增量编译支持得一般出问题之后最好的办法就是./clean -a把环境彻底清理干净再重新configure。我已经数不清自己省掉这一步后在莫名其妙的旧产物上浪费了多少时间。4. WPS编译失败的必修课geogrid、ungrib、metgrid三件套WPS编译是另一个重灾区很多人在WRF已经编译成功后以为WPS不会有什么问题结果被它折磨得更惨。4.1 WPS configure脚本的检查项与隐藏要求WPS的configure脚本会检查netCDF、MPI、以及GRIB2相关库。一个非常常见的现象是./configure结束后编辑configure.wps文件发现里面的COMPRESSION_LIBS和COMPRESSION_INC是空的而后面编译时如果ungrib相关代码涉及grib2就会报错找不到jasper头文件。提前设置好JASPERLIB和JASPERINC是必须的但还有一个隐藏要求WPS在某些Linux发行版上检测libpng时依赖的是png.h头文件如果libpng没有安装开发包那么即使JASPERLIB指向正确也会报错。这时候用发行版自带的包管理器安装就好sudo apt install libpng-dev不要小看这一步很多WPS编译到一半报png.h: No such file or directory就是因为没装libpng开发包而教程里默认你已经装好了。4.2 链接错误undefined reference才是真正的信息量WPS编译报错里最经典的是这种geogrid/src/geogrid.f90: undefined reference to nf_create不要只看最后一行先确认nf_create这个符号是netcdf-fortran提供的。出现这个符号说明WPS调用netCDF时使用的是Fortran接口而你的netcdf-fortran没有安装或链接不对。解决办法和WRF部分一样重新确认netcdf-fortran安装。同时检查configure.wps里的NETCDF路径变量它指向的应该是netcdf根目录。另一个常见链接错误是undefined reference to mpi_init_对应MPI Fortran接口。这通常是因为WPS configure时检测到了mpif90但后面编译时实际用的是普通gfortran来链接导致MPI符号缺失。解决方式是在./configure时如果看到选项里带了(dmpar)就选它然后确认SFC和SCC变量确实指向mpif90和mpicc。4.3 只生成部分exe单步编译排查法在WPS目录下执行./compile之后正常情况下会生成geogrid.exe、ungrib.exe、metgrid.exe三个文件。但有时候你会发现只有两个甚至一个都没有。这时候用单步编译试试./compile 1 ./compile 2 ./compile 3其中1是geogrid2是ungrib3是metgrid。哪个编号报错就能直接定位到对应程序。比如geogrid编译失败多半是netCDF或地理数据路径的问题ungrib失败多半是GRIB2相关库的问题。有时候三个exe都生成了但一运行就报error while loading shared libraries: libnetcdff.so.12这种错。这属于运行时动态库路径问题而不是编译问题。在configure.wps里或者shell里把LD_LIBRARY_PATH加上netcdf的lib路径即可export LD_LIBRARY_PATH/opt/netcdf/lib:$LD_LIBRARY_PATH4.4 WPS版本与WRF版本要配套最后再强调一个细节WPS和WRF的版本号要匹配。我见过有人用WPS 4.5去配WRF 3.9.1编译能过但metgrid出来的文件和real的输入格式对不上运行阶段才暴露问题。最稳妥的就是去WRF官网找到和WRF版本配套的WPS版本别自己混搭。5. 编译成功的下一步环境变量和测试案例里的隐性坑WRF和WPS都编译通过不代表事情就结束了。我自己第一次真正跑通测试案例的时候又遇到过几个和环境、运行时相关的坑这里一并记录下来。5.1 把环境变量固化下来别每次登录都重敲一遍很多人编译完设置了NETCDF、PATH、LD_LIBRARY_PATH之后就以为万事大吉结果下次登录服务器一切回到原点。建议把这些变量写进~/.bashrcexport NETCDF/opt/netcdf export PATH/opt/netcdf/bin:/opt/mpich/bin:/opt/grib2/bin:$PATH export LD_LIBRARY_PATH/opt/netcdf/lib:/opt/grib2/lib:$LD_LIBRARY_PATH export JASPERLIB/opt/grib2/lib export JASPERINC/opt/grib2/include改完后执行source ~/.bashrc或者重新登录。有个小经验如果我们在某个节点上通过调度系统提交作业调度脚本里也要重新source这些变量否则作业运行时找不到动态库。这个坑在集群环境里特别隐蔽我第一次用PBS提交时wrf.exe直接报libnetcdff.so.12: cannot open shared object file查了半天才发现是作业脚本没把环境变量带进去。5.2 测试案例跑不通先看namelist和目录结构编译成功之后应该先进到WRF/test/em_real目录用官方测试数据跑一遍流程。这一步能暴露大量运行时问题。如果./geogrid.exe报错找不到geo_em.d01.nc先检查namelist.wps里的geog_data_path是否指向你的地理静态数据目录。这个路径意思是存放地形、土地利用等geogrid原始数据的目录不是生成结果的目录。很多新手把这个路径填成输出目录自然找不到。如果./ungrib.exe报错常见原因是Vtable和GRIB数据版本不匹配。比如你处理的是GFS的GRIB2文件就需要链接ungrib/Variable_Tables/Vtable.GFS到Vtableln -sf ungrib/Variable_Tables/Vtable.GFS Vtable还有一点ungrib需要借助link_grib.csh脚本把GRIB文件链接成一个特定格式的序列文件比如GRIBFILE.AAA、GRIBFILE.AAB等等。如果link脚本没有执行ungrib会告诉你找不到GRIB数据。5.3 并行运行时mpirun的各种报错最后说一个高频问题运行mpirun -np 4 ./wrf.exe时报错比如There are not enough slots available in the system这个大多数情况不是你系统资源不够而是你的MPI实现配置要求指定host数量。如果是MPICH可以尝试mpirun -hosts localhost -np 4 ./wrf.exe但更推荐的做法是使用同一种MPI实现编译WRF和使用mpirun。如果你编译WRF时用的是MPICH而运行环境里OpenMPI的mpirun被调用了后面极容易出现看起来莫名其妙的异常。临时解决办法是把MPICH的bin目录放前面长期做法还是统一MPI版本。还有一类问题运行real.exe或wrf.exe时提示需要从标准输入读入namelist.input但脚本里没有自动重定向。正常的运行方式是./real.exe它会读取当前目录下的namelist.input。如果你改过目录名或者用了符号链接记得检查namelist.input是否真的存在且内容不是空文件。写在最后我在实际装过这么多次WRF和WPS之后最大的感受是这些编译报错百分之八十是环境变量或依赖库匹配问题真正复杂的代码逻辑错误反而很少。每装一次我都会习惯性地把所有库的编译脚本和路径记录在一个笔记里下次换机器直接照做能省下一整天的试错时间。如果你现在卡在某个步骤里先别急着重装老老实实把日志翻完把echo $NETCDF、which mpif90这些基本信息打印出来问题往往就暴露了。