ARTICLE DETAIL

资讯详情

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

cost733天气分型软件Linux源码编译安装实战指南

cost733天气分型软件Linux源码编译安装实战指南 在气象科研圈里提到“天气分型”很多做气候诊断、极端事件归因和环流分型分析的朋友都会碰到一个叫cost733的软件。它是从COST733行动框架下发展起来的一套命令行分型工具支持PCA聚类、k-means、SANDRA、模拟退火等多种主流分型方法输入NetCDF格点场输出每个时间步对应的环流型编号论文出镜率相当高。我这次在一台CentOS7服务器上从头到尾装了一遍cost733也把数据跑通了。过程说复杂也复杂说简单也简单关键是先把依赖环境捋顺再处理编译细节。这篇文章面向两类读者一类是刚接触cost733、想在实验室服务器上把它跑起来的气象专业研究生另一类是已经装了但编译时总是报错、整天在依赖库里打转的“受害者”。我会把方案选型、依赖安装、本体编译、最小测试和常见报错全部写清楚尽量做到你对着敲就能复现。1. 装之前先搞清楚的两个问题1.1 cost733到底是什么形态的软件很多第一次接触cost733的人会误以为它像GrADS或者NCL一样装完有一个交互界面其实不是。cost733是一个纯命令行的Fortran程序没有图形界面也没有Python API。你给它一个NetCDF文件告诉它用哪种分型方法、分几类、迭代多少次它就在后台跑计算最后输出一堆文本和统计结果。它的核心能力是“天气分型”也就是把每天的海平面气压场、500hPa位势高度场这种高维格点数据压缩成若干个典型的环流型然后给每一天贴一个类型编号。这个编号序列可以用来做环流型频率的趋势分析、与地面气象要素的统计关系、以及极端事件对应的环流背景分析。国内做气象统计、气候诊断、天气预报方法研究的同行用得比较多。因为它是Fortran写的安装就要走源码编译这条路。好在这类软件的结构不算复杂整个依赖链也就两三层只要会Linux基本操作按部就班走下来是能装通的。真正让人头大的是NetCDF生态链的编译顺序和版本配合后面我会专门说。1.2 安装方案怎么选源码编译是主流cost733的官方发布包提供的是源码没有预编译的二进制。想用yum直接装是不可能的CentOS7的软件仓库里虽然有netcdf、netcdf-fortran这些库但版本通常比较老而且不同机器的仓库配置不一样装上之后能不能被cost733正确识别完全是碰运气。所以我这次选的是最稳妥的路线手动源码编译全套依赖。虽然步骤多一些但每一步都能控制版本出问题也知道去哪里排查。如果你希望更省事也可以尝试用conda创建独立环境但这需要cost733支持动态链接那些conda里的库实际操作中会有兼容性隐患不如源码编译干净。还有一点要提醒不要用root编译。我见过很多人图方便直接root操作装到一半改坏了系统库最后只能重装系统。正确的做法是准备一个专门用来编译安装的普通用户把依赖统一装到/usr/local或$HOME/software下全局环境变量由这个用户配置。这样即使后面装坏了也不会把系统搞瘫。2. 依赖环境搭建zlib、hdf5、netcdf一条龙2.1 先给系统补基础工具CentOS7最小化安装通常缺很多编译工具。我在正式编译前先把这些包装齐yum install -y gcc gcc-gfortran gcc-c make csh m4 libtool其中gcc-gfortran是Fortran编译器cost733编译必需csh是因为NetCDF官方源码里有些配置脚本是C shell写的m4是autoconf的依赖缺了的话NetCDF配置阶段会报错。如果你后续还想用NCO、CDO这些工具这会儿顺手把curl-devel、python3-devel也装上省得后面又缺。装完之后检查一下编译器版本gcc --version gfortran --versionCentOS7自带的gcc是4.8.5gfortran也是配套的4.8.x。这个版本对编译早期版本的NetCDF没问题但如果你要编比较新的NetCDF库或者后面还想编译其他气象软件会碰到各种“不支持Fortran 2008特性”的报错。我这次的策略是直接用系统自带编译器先试因为cost733和配套依赖库并不算新4.8.5完全够用。但如果读者手头的cost733版本比较新建议用SCL安装更新的编译器yum install -y centos-release-scl yum install -y devtoolset-9 scl enable devtoolset-9 bash进入这个shell后gcc和gfortran都会变成9.x版本稳定性很好。这个版本的切换只对当前shell有效不影响系统全局非常适合用来做软件编译。2.2 源码编译NetCDF生态链NetCDF生态链的编译顺序是有讲究的zlib → hdf5 → netcdf-c → netcdf-fortran。 这个顺序不能乱因为后面每一步都要依赖前一步生成的头文件和库文件。用生活类比的话zlib是地基hdf5是承重墙netcdf-c是门框netcdf-fortran才是你能推开的那扇门。我这次统一把依赖装到了/usr/local下没有单独设置前缀。如果你不想污染系统目录也可以给每步单独指定--prefix$HOME/libs/xxx后面的环境变量指过去就行。下面是我用的版本组合实测稳定zlib-1.2.11hdf5-1.10.6netcdf-c-4.8.1netcdf-fortran-4.5.3先编译zlibtar -zxvf zlib-1.2.11.tar.gz cd zlib-1.2.11 ./configure --prefix/usr/local make make install接着是hdf5注意需要开启Fortran接口并且用-fPIC编译。如果不加-fPIC后面链接netcdf-fortran时经常出现类似“relocation R_X86_64_32S”的报错很磨人tar -zxvf hdf5-1.10.6.tar.gz cd hdf5-1.10.6 export CFLAGS-fPIC export FFLAGS-fPIC ./configure --prefix/usr/local --enable-fortran --with-zlib/usr/local make make installhdf5的编译时间偏长十几分钟很正常不要看到屏幕刷了一堆日志就以为卡住了。我的经验是直接make -j4并行编译速度能快不少只要机器内存不低于4G就没问题。接下来是netcdf-ctar -zxvf netcdf-c-4.8.1.tar.gz cd netcdf-c-4.8.1 export CPPFLAGS-I/usr/local/include export LDFLAGS-L/usr/local/lib export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH ./configure --prefix/usr/local make -j4 make install最后是netcdf-fortran。这个包的作用是给Fortran程序提供nf_*接口而cost733正是通过nf_open_、nf_get_var_*这类函数读写NetCDF文件的。没有它后面编译cost733时一定会报“undefined reference to nf_open_”tar -zxvf netcdf-fortran-4.5.3.tar.gz cd netcdf-fortran-4.5.3 export CPPFLAGS-I/usr/local/include export LDFLAGS-L/usr/local/lib ./configure --prefix/usr/local make -j4 make install装完这四样之后用nf-config --all检查一下能看到--prefix/usr/local、--fcgfortran这些信息就说明依赖层已经通了。这个命令在netcdf-fortran装好之后会出现在/usr/local/bin下也是后面排查问题很好用的工具。需要特别注意把/usr/local/lib加进LD_LIBRARY_PATH这一步最好写进~/.bashrc否则每次新开一个shell都会遇到“找不到libnetcdff.so”的运行时错误。我习惯在~/.bashrc末尾追加export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH export PATH/usr/local/bin:$PATH然后source ~/.bashrc生效。3. 编译cost733本体关键一步是Makefile3.1 解压源码先看README和目录结构cost733的源码包不大解压后能看到一堆.f90、.f源文件还有一些示例脚本和文档。我拿到手的第一件事不是急着make而是先看它根目录下的README和Install说明。这一步特别重要因为不同小版本的编译方式有差异有的版本自带configure脚本有的版本没有只有Makefile。以比较常见的cost733-1.2为例源码包里通常可以看到类似src/、bin/、doc/这样的目录。源码主体放在src/下编译后生成的可执行文件会被复制到bin/下。它一般不带configure脚本直接用Makefile管理编译。先把包解压到自己的工作目录tar -xzf cost733-1.2.tar.gz cd cost733-1.2 ls -la cat READMEREADME里面会有编译依赖说明和基本用法比如它支持的方法列表、输入数据格式要求、输出文件类型。这些信息必须亲眼看一下不要完全相信网上的教程因为很多人写的版本和你下载的版本不一定一样。3.2 修改Makefile让编译器找到NetCDF打开Makefile之后几个关键变量是绕不开的。不同版本里命名可能略有差异但核心就是三样Fortran编译器路径、NetCDF的头文件路径、NetCDF的库文件路径。我在这次安装里主要改了这几行FC gfortran FFLAGS -O2 -fPIC NETCDF_INC /usr/local/include NETCDF_LIB /usr/local/lib LIBS -lnetcdff -lnetcdf如果你想把优化级别调高比如-O3也问题不大但我在测试中发现cost733本身不是计算密集型软件-O2和-O3差别几乎感觉不出来。反倒是-fPIC建议保留防止后面链接时出现重定位问题。如果Makefile里默认写的是ifort而你机器上装的是gfortran一定要改过来。有些版本还会把NETCDF_INC写成硬编码路径比如/usr/local/netcdf/include如果你实际安装路径不是这个编译阶段会报找不到netcdf.mod文件。遇到这种情况不用慌先确认一下你的netcdf.mod到底在哪个目录find /usr/local -name netcdf.mod把查到的目录填进NETCDF_INC就行。netcdf.mod和typesizes.mod这两个Fortran模块文件能不能被编译器找到是编译能否通过的第一个关卡。3.3 编译和安装改完Makefile后直接执行make第一次编译时会跳出一大堆Fortran编译日志只要没有以Error开头的行就让它继续跑。编译结束后在bin/或源码根目录下会出现一个名叫cost733的可执行文件。我习惯把它复制到系统PATH覆盖的目录里方便全局调用cp cost733 /usr/local/bin/ cost733 -h如果能看到一堆命令行参数说明说明安装已经成功了大半。看到-h输出时我建议你顺手把所有参数选项截图存一下后面跑实际任务要用到的-dat、-var、-method、-ncls这些关键字都在这个帮助文本里。4. 跑通一个最小分型流程4.1 准备测试数据cost733读的是NetCDF格式的格点数据。很多人的数据来源是ERA5或者NCEP再分析资料这些数据本身就能直接用。但如果只是想验证软件能不能跑没必要一上来就下载几十GB的再分析数据可以先构造一个小的测试文件。我是用Python的netCDF4库生成的一个微型三维场维度是时间、纬度、经度变量模拟海平面气压from netCDF4 import Dataset import numpy as np nt, ny, nx 30, 6, 8 data np.random.randn(nt, ny, nx) * 8 1013 with Dataset(test_slp.nc, w, formatNETCDF3_CLASSIC) as ds: ds.createDimension(time, nt) ds.createDimension(lat, ny) ds.createDimension(lon, nx) times ds.createVariable(time, i4, (time,)) lats ds.createVariable(lat, f4, (lat,)) lons ds.createVariable(lon, f4, (lon,)) slp ds.createVariable(slp, f4, (time, lat, lon)) times[:] np.arange(nt) lats[:] np.linspace(20, 50, ny) lons[:] np.linspace(100, 130, nx) slp[:] data这里有个细节如果你的输入数据是ERA5这样的grib或netCDF格式建议先检查一下维度名。cost733对变量名和维度名的要求比较严格通常需要显式告诉它变量名有的版本还会要求时间维是第一个。如果维度顺序不对可以在Python里用np.transpose调整或者用NCL的transpose函数预处理反正要保证数据形状是时间, 纬度, 经度。4.2 跑一个k-means分型数据准备好了就可以开始第一次分型测试。cost733支持的典型命令结构长这样cost733 -dat test_slp.nc -var slp -method KMEANS -ncls 4 -niter 50-dat指定输入NetCDF文件-var指定要分型的变量名-method选择分型算法-ncls是分型类别数-niter是迭代次数。这个命令的含义是基于海平面气压场用k-means聚成4种天气型。不同版本对区域裁剪的写法不太一样有的用-min和-max有的用-latmin-latmax-lonmin-lonmax。我建议以cost733 -h输出的参数说明为准不要硬套别人的命令行格式。比如我测试用的测试数据只有30个时次迭代50次绰绰有余几秒钟就出结果了。4.3 看懂输出文件跑完之后当前目录下会多出几个文件典型的包括.cat类型的目录文件、.stat统计文件和.log日志文件。.cat文件是最核心的结果它记录每一个时次被划分到哪一类通常是一个纯数字序列第一行可能是“1,1,2,3,4,1,2...”这样的类别编号。.stat文件里是各个类的统计特征比如每一类对应的平均场、频次、转移概率。这些文件直接用文本编辑器打开就能看。这里分享一个排查小技巧如果你发现.cat文件里所有时次都被分到了同一类十有八九是输入数据有问题比如所有格点都是同一个常数或者缺失值填成了0导致均值被拉偏。遇到这种情况先回退到数据预处理环节检查一下数据规范化和标准化是否正确。cost733本身不会自动处理缺失值这一点和很多统计软件不同。5. 常见报错与排查实录5.1 编译期报错速查表编译阶段是最容易让人崩溃的因为报错信息往往很抽象。我把这次安装中遇到和收集到的典型问题列成一张表方便你对照排查报错信息可能原因解决方案gfortran: command not found没装Fortran编译器yum install gcc-gfortranError: Cant open module file netcdf.modinclude路径没配好确认NETCDF_INC/usr/local/include检查netcdf.mod实际位置undefined reference tonf_open_没链接netcdf-fortran库在LIBS中加入-lnetcdff -lnetcdf注意库顺序undefined reference toH5_open_netcdf-c依赖hdf5但链接不到确认/usr/local/lib下有libhdf5.soLDFLAGS和LD_LIBRARY_PATH都包含该路径relocation R_X86_64_32S against ...编译NetCDF时没加-fPIC返回hdf5/netcdf-c编译步骤加CFLAGS-fPIC重新编译Error: Unexpected element ( 编译器版本过老用SCL安装新版本GCC如devtoolset-9第一条和最后一条我这次没有遇到但在帮朋友装其他Fortran气象软件时经常见。特别是“Unexpected element”这类语法报错基本都是编译器版本太老不支持源码用到的Fortran新特性。如果系统自带gfortran不行直接用devtoolset-9切换环境很多问题自动消失。5.2 运行期报错速查表编译过了不代表万事大吉软件能不能跑起来是另一回事。运行阶段的报错主要集中在这几类报错信息可能原因解决方案error while loading shared libraries: libnetcdff.so.12动态链接库路径没配export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATHSegmentation Fault输入数据维度或变量名与预期不符用ncdump -h检查NetCDF结构确认维度顺序和变量名Not a NetCDF file文件格式不是真正的NetCDF确认文件是否经grib转netCDF尝试ncdump -h是否能正常读取所有时次分到同一类数据标准化问题或缺失值未处理检查数据极差、方差避免全0或缺失值填充为0程序卡住不输出迭代次数过大或数据量过大调小-niter观察是否立即出结果排除计算规模问题“所有时次分到同一类”这个问题值得多说一句。我在做真实数据测试时踩过一次当时是拿一套温度格点数据直接跑原始值在280到320之间波动按理说不可能所有时次都聚到一类。排查之后发现是数据预处理阶段把缺失值填成了0把整个场的平均值拉偏了。之后我就养成了习惯分型之前一定先做一次数据质量控制缺测值要么剔除要么用插值补上绝不能用0这种占位符糊弄过去。5.3 我踩过的三个印象最深的坑第一个坑是hdf5忘了加--enable-fortran。我当时以为netcdf-fortran自带hdf5 Fortran支持结果编译到一半报错代码在HDF5的Fortran接口部分直接卡住。后来返回去重新配置hdf5加上--enable-fortran再编译后面就顺了。cost733本身的依赖是netcdf-fortran但netcdf-fortran往下又依赖hdf5的Fortran接口所以这一项不能省。第二个坑是LD_LIBRARY_PATH没有持久化。第一次运行时提示找不到libnetcdff.so我当时以为库没装好重新编译了两次netcdf-fortran后来才发现只是当前shell的环境变量没配。新开一个SSH窗口之后又把export命令执行一遍问题就没了。现在我都把环境变量写进~/.bashrc一步到位。第三个坑是编译器版本选择。我最初为了追求新装了devtoolset-9用新版gfortran编译结果cost733个别源文件反而报了一堆“legacy”相关的警告。虽然不影响生成可执行文件但我担心数值结果有偏差就切回系统自带的gfortran 4.8.5重新编译。结果两版编译出来的分型结果几乎完全一样。这件事给我的教训是气象软件里面的数值算法有时候对编译器版本很敏感但大多数时候用系统自带编译器反而是最稳的不要盲目追新。如果你编译时遇到奇怪的数值结果比如同一命令两次运行得到的分类结果略有不同可以检查一下是不是没有设置随机数种子。部分分型方法比如k-means初始中心点可能是随机生成的这种情况下不同运行之间结果有微小差异是正常的不算bug。要复现严格一致的分类需要固定随机种子。安装cost733这件事说难不难说容易也不容易。依赖关系捋清楚之后整个过程其实就是标准的Linux源码编译流程。我个人的体会是这类气象领域的小众软件安装踩坑是常态但只要记住“先看README、再查依赖、最后调Makefile”这个顺序绝大多数问题都能定位到具体环节。尤其是NetCDF生态链版本和先后顺序一定要控制住前面多花时间把基础库装扎实后面cost733本体基本就是顺手的事。希望这篇记录能帮你少走几步弯路早点把精力放回分型结果的分析上。
返回列表