在Arch上安装WRF和WPS

WRF

This article was last updated on <span id="expire-date"></span> days ago, the information described in the article may be outdated.

老高让我学 WRF,我就装 WRF。装 WRf 的过程出现了很多问题,就开贴记录一下。

WRF 版本 V4.4.1

WRF 安装

clone 源码

根据 官网 的描述,先执行以下代码将源代码 clone 下来。

1
git clone --recurse-submodules https://github.com/wrf-model/WRF

安装依赖

1
sudo pacman -S netcdf hdf5 netcdf-fortran

gcc、gcc-fortran什么的都默认你已经装好了嗷,没有的话快装。

生成 configure.wrf

首先需要在环境变量中设置以下 NETCDFNETCDF_INCNETCDF_LIB

1
2
3
export NETCDF=/usr
export NETCDF_INC=/usr/include
export NETCDF_LIB=/usr/lib

然后执行下面的命令运行 configure

1
bash ./configure

选择编译器的那里我选择的 34,因为用到了 GCC 的编译器。

在输出一长串日志以后,configure.wrf 就生成成功了。

但是需要注意的是,需要修改几个地方,否则后面编译的时候会报错。

修改 CPP 编译器路径

定位到 configure.wrf 的第 162 行,这里的内容应该是

1
CPP             =      /lib/cpp -P -nostdinc

将其修改为

1
CPP             =      cpp -P -nostdinc

正常人谁特么会写死编译器路径?

去除调用 time 命令的设置

之所以要去掉,是因为编译的时候会出现 make 找不到 time 命令的错误。翻了一下 Github 的 issue,开发者说 time 命令无关紧要,可以去掉。那你特么调这个命令干啥。定位到 configure.wrf 的第 139 行,内容应该如下

1
FC              =       time $(DM_FC)

将其修改为

1
FC              =       $(DM_FC)

开始编译

做完上面的修改以后执行下面命令开始编译,然后等待编译程序报错🐶。(该报错的时候我才发现,留一份完整的日志是多么的重要)

1
./compile em_real > compile.log 2>&1

上面的命令会将所有的输出 (包括 make 报的错误) 全部重定向进文件,先看会文献然后等待程序运行完成。

解决报错

dfft1f_ 符号未定义

从后往前查找日志,定位到第一个出现问题的地方,出现如下错误

1
2
3
/usr/bin/ld: libwrflib.a(module_polarfft.o): in function `__module_polarfft_MOD_polar_filter_fft_2d_ncar':
module_polarfft.f90:(.text+0x5883): undefined reference to `rfftmi_'
/usr/bin/ld: module_polarfft.f90:(.text+0x5c69): undefined reference to `dfft1f_'

看样子是 module_polarfft 这个代码出了问题。对吗?不对。通过谷歌发现,在 external/fftpack/fftpack5 下存在一个名叫 dfftf1.F 的文件,使用 nm 看一眼这个目录下编译出来的静态链接库 libfftpack.a

1
nm -n libfftpack.a
image-20221026133310607

WRF,你tm在逗我吗?

在日志里向上搜寻编译出 libfftpack.a 的命令,结果发现只调用了 ar 来打包,没有编译过程。原来这些 .o 文件在 clone 下来的时候就出问题了。。。

于是我只好现场查询 Makefile 的用法,对 Makefile 进行了修改并自己手动编译。

首先现在 Makefile 开头 .SUFFIXES 的下一行加入以下内容

1
2
3
4
5
CPP = cpp -P -nostdinc
CPPFLAGS = -DEM_CORE=1 -DNMM_CORE=0 -DNMM_MAX_DIM=2600 -DDA_CORE=0 -DWRFPLUS=0 -DIWORDSIZE=4 -DDWORDSIZE=8 -DRWORDSIZE=4 -DLWORDSIZE=4 -DNONSTANDARD_SYSTEM_SUBR -DWRF_USE_CLM -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT -DDM_PARALLEL -DNETCDF -DLANDREAD_STUB=1 -DUSE_ALLOCATABLES -Dwrfmodel -DGRIB1 -DINTIO -DKEEP_INT_AROUND -DLIMIT_ARGS -DBUILD_RRTMG_FAST=0 -DBUILD_RRTMK=0 -DBUILD_SBM_FAST=1 -DSHOW_ALL_VARS_USED=0 -DCONFIG_BUF_LEN=65536 -DMAX_DOMAINS_F=21 -DMAX_HISTORY=25 -DNMM_NEST=0 -I. -traditional-cpp -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT
FC = mpif90
FFLAGS = -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -fallow-argument-mismatch -fallow-invalid-boz
RM = rm -f

然后在最后添加以下部分

1
2
3
4
build:
$(CPP) $(CPPFLAGS) $(name).F > $(name).f90
$(FC) -c $(FFLAGS) $(name).f90
$(RM) -f $(name).f90

最后在终端中运行以下命令重新把文件全部编译一遍

注意

我使用的是 zsh,若你使用其他类型的 shell,请注意修改 make 那一行的字符串切片

1
2
3
4
ls *.F | while read line
do
make build name=${line[1,-3]}
done

在输出一长串编译日志以后,.o 文件都已经重新编译好了。然后在直接运行 make 命令打包出 libfftpack.a

1
make

最后再重新去运行一下下面的命令编译出 wrf.exe,可以发现 dfft1f_ 符号未定义的错误已经消失了,但是还有其他符号未定义问题需要解决。

1
mpif90  -o wrf.exe  -O2 -ftree-vectorize -funroll-loops -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -fallow-argument-mismatch -fallow-invalid-boz    wrf.o ../main/module_wrf_top.o libwrflib.a  /home/syize/Apps/WRF/external/fftpack/fftpack5/libfftpack.a /home/syize/Apps/WRF/external/io_grib1/libio_grib1.a /home/syize/Apps/WRF/external/io_grib_share/libio_grib_share.a /home/syize/Apps/WRF/external/io_int/libwrfio_int.a -L/home/syize/Apps/WRF/external/esmf_time_f90 -lesmf_time /home/syize/Apps/WRF/external/RSL_LITE/librsl_lite.a /home/syize/Apps/WRF/frame/module_internal_header_util.o /home/syize/Apps/WRF/frame/pack_utils.o -L/home/syize/Apps/WRF/external/io_netcdf -lwrfio_nf -L/usr/lib -lnetcdff -lnetcdf

上面的 /home/syize/Apps/ 需要替换成你自己的 WRF 路径,若你觉得麻烦,直接在 compile.log 里面找就好了

get_dims_ 符号未定义

使用 grep 命令在 WRF 目录递归搜索字符串 get_dims_,将问题定位到 external/io_grib_share/io_grib_share.o 这个文件,再用 nm 命令看一下 libio_grib_share.a,第一行就发现了猫腻

image-20221026140105987

好吧,看来又要我手动修了。首先执行以下命令清理 .o 文件

1
make clean

然后执行以下命令重新进行编译打包

1
make -j 2 CC="gcc" CFLAGS="-w -O3 -c  -DRPC_TYPES=2  -DDM_PARALLEL -DLANDREAD_STUB=1 -DMAX_HISTORY=25 -DNMM_CORE=0" RM="rm -f" RANLIB="ranlib" CPP="cpp -P -nostdinc" FC="gfortran  -I.  -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -fallow-argument-mismatch -fallow-invalid-boz  " TRADFLAG="-traditional-cpp -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT" AR="ar" ARFLAGS="ru" archive

编译好以后看一眼 libio_grib_share.a,发现修好了

image-20221026140725866

再执行命令编译 wrf.exe,终于修好了。但是,你先别急,还有其他错误呢🐶。

module_wps_io_arw.mod 文件找不到

还是那句话,你要是觉得敲命令麻烦,就自己去日志文件里面复制就好了

还是使用递归搜索,定位带文件 dyn_em/module_wps_io_arw.o,检查一遍发现由 F 文件生成的 f90 文件的大小竟然是0。。。

分别使用下面的命令重新生成 module_wps_io_arw.o

1
2
3
4
5
6
7
sed -e "s/^\!.*'.*//" -e "s/^ *\!.*'.*//" module_wps_io_arw.F > module_wps_io_arw.G

cpp -P -nostdinc -I/home/syize/Apps/WRF/inc -DEM_CORE=1 -DNMM_CORE=0 -DNMM_MAX_DIM=2600 -DDA_CORE=0 -DWRFPLUS=0 -DIWORDSIZE=4 -DDWORDSIZE=8 -DRWORDSIZE=4 -DLWORDSIZE=4 -DNONSTANDARD_SYSTEM_SUBR -DWRF_USE_CLM -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT -DDM_PARALLEL -DNETCDF -DLANDREAD_STUB=1 -DUSE_ALLOCATABLES -Dwrfmodel -DGRIB1 -DINTIO -DKEEP_INT_AROUND -DLIMIT_ARGS -DBUILD_RRTMG_FAST=0 -DBUILD_RRTMK=0 -DBUILD_SBM_FAST=1 -DSHOW_ALL_VARS_USED=0 -DCONFIG_BUF_LEN=65536 -DMAX_DOMAINS_F=21 -DMAX_HISTORY=25 -DNMM_NEST=0 -I. -traditional-cpp -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT module_wps_io_arw.G > module_wps_io_arw.bb

/home/syize/Apps/WRF/tools/standard.exe module_wps_io_arw.bb | cpp -P -nostdinc -traditional-cpp -DUSE_NETCDF4_FEATURES -DWRFIO_NCD_LARGE_FILE_SUPPORT > module_wps_io_arw.f90

mpif90 -o module_wps_io_arw.o -c -O2 -ftree-vectorize -funroll-loops -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -fallow-argument-mismatch -fallow-invalid-boz -I../dyn_em -I/home/syize/Apps/WRF/external/esmf_time_f90 -I/home/syize/Apps/WRF/main -I/home/syize/Apps/WRF/external/io_netcdf -I/home/syize/Apps/WRF/external/io_int -I/home/syize/Apps/WRF/frame -I/home/syize/Apps/WRF/share -I/home/syize/Apps/WRF/phys -I/home/syize/Apps/WRF/wrftladj -I/home/syize/Apps/WRF/chem -I/home/syize/Apps/WRF/inc -I/usr/include module_wps_io_arw.f90

注意修改命令中的路径为你自己的 WRF 路径

然后在执行命令重新编译 real_em.o 文件

1
mpif90  -o real_em.o -c -O2 -ftree-vectorize -funroll-loops -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4 -fallow-argument-mismatch -fallow-invalid-boz   -I../dyn_em  -I/home/syize/Apps/WRF/external/esmf_time_f90  -I/home/syize/Apps/WRF/main -I/home/syize/Apps/WRF/external/io_netcdf -I/home/syize/Apps/WRF/external/io_int -I/home/syize/Apps/WRF/frame -I/home/syize/Apps/WRF/share -I/home/syize/Apps/WRF/phys -I/home/syize/Apps/WRF/wrftladj -I/home/syize/Apps/WRF/chem -I/home/syize/Apps/WRF/inc -I/usr/include    real_em.f90

到此为止,基本所有额外的修复工作均已完成,剩下的工作就是复制编译失败的命令重新执行以下就可以了,为了保持博客简洁我就不再赘述了。

贴一张完成的图片,根据日志需要编译出的4个可执行文件均已成功编译出。

image-20221026142907877

WPS 安装

clone 源码

执行以下命令 clone 最新的 WPS 源码

1
git clone https://github.com/wrf-model/WPS

然后 configurecompile,记得用以下命令将日志输出到文件,方便后续查找报错修复

1
./compile em_real > compile.log 2>&1

解决报错

compile 命令执行完成以后看了一眼日志,果然报错了,开始修复。

nf_strerror_ 符号未定义

这里其实是解决所有以 nf 开头的符号未定义的解决方案,经查询这些符号均是在 libnetcdff.so 动态链接库中的,但是查看最后连接时候的命令可以看到只链接了 libnetcdf.so 这个库,解决方法也很简单,复制编译日志中的链接指令,在最后加上 -lnetcdff 即可。

jpc_decode 符号未定义

出现这个错误是因为新版本的 jasper 中已经弃用了该函数,官方也推荐使用 jas_image_decode 来代替。解决这个错误的方法只好是下载一个旧版本的 jasper 源码自己编译一个动态链接库。这是 2.0.14 版本的下载地址

解压压缩包,并进入文件夹

1
2
tar -zxvf jasper-2.0.14.tar.gz
cd jasper-2.0.14/build

可以发现 CMakeLists.txt 都给你写好了,直接 cmake 开始编译

1
2
cmake ..
make

编译到最后会报错,但是没关系,libjasper.so.4.0.0 已经给你编译好了,直接复制该链接库到 WPS 的路径下的 ungrib/src 文件夹中,然后复制日志中的指令开始编译就好了。

最后我们还需要复制该链接库到系统的 library 路径中,并命名为 libjasper.so.4,这样你运行 ungrid.exe 时才不会报下面的错误

1
./ungrib.exe: error while loading shared libraries: libjasper.so.4: cannot open shared object file: No such file or directory

__netcdf_MOD_nf90_get_var_4d_fourbytereal 符号未定义

这个也是由于没有链接 libnetcdff.so 造成的,解决方法和 nf_strerror_ 一样。

Author: Syize

Permalink: https://blog.syize.cn/2022/10/25/install-wrf-on-arch/

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Syizeのblog

Comments