CentOS上装VASP 5.4.1,可能是很多课题组最常遇见的坑。VASP 5.4.1本身不算新,却因为兼容性、MPI库和数学库的排列组合问题,装起来比用现成预编译脚本的新版本还要麻烦。尤其当你面对的是intel、openmpi、fftw这套组合时,任何一个库编译时手一滑,后面都会回报你一段莫名其妙的错误。这篇文章是我自己在某课题组服务器上反复重装后整理的完整流程,适合要在CentOS系统上,用Intel编译器加OpenMPI、FFTW环境编译VASP 5.4.1的同行参考。不管你是刚进组的学生,还是要帮师弟师妹兜底的学长,照着走一遍基本能把环境和可执行文件顺利搞定。
1. 安装前的环境规划与版本选择
动手敲命令之前,先把要装的东西理清楚。VASP 5.4.1是材料计算领域很经典的版本,尽管官方早就有更新,但很多老脚本、赝势库、后处理工具都是围绕这个版本跑的,所以它至今还在各种服务器上服役。编译VASP本身并不复杂,真正的难点在于它依赖了三条链子:编译器、MPI库、FFT库,这三者必须能“对话”。你用了Intel的ifort编译程序,mpif90就必须是用Intel编译器包装出来的,FFTW又必须能被ifort顺利调用,否则链接阶段会出现一堆找不到符号、类型不匹配的报错。
CentOS上做这套环境,优先选择经典的Intel编译器路线。原因很简单:VASP的原生代码对Intel编译器优化得最充分,性能通常比gfortran版本高出一截,而且MKL数学库自带LAPACK、BLAS和ScaLAPACK,能省掉很多手动拼库的麻烦。但要注意,VASP 5.4.1发布较早,对太新的Intel编译器支持并不算好,不建议一上来就装最新版的oneAPI。我这边验证过比较稳定的组合是Intel Parallel Studio XE 2017到2019版本中的ifort,配合OpenMPI 3.1.x。
OpenMPI版本的选择也有讲究。VASP 5.4.1在OpenMPI 4.x之后偶尔会碰到比较新的接口变化,导致编译过但要运行时报MPI库版本冲突。所以如果没有特殊需求,OpenMPI 3.1.6是性价比很高的选择,网上资料多,踩坑记录也丰富。FFTW则建议使用3.3.8或3.3.10,这两个版本都经过很长时间考验,用默认参数编译出来就能满足VASP需求。
另外要做一个操作系统的检验。CentOS 7.9和CentOS 8都支持这套流程,但CentOS 8的gcc默认版本更高,编译OpenMPI时可能会影响旧兼容性,建议装完基础包后先确认gcc、g++、make、wget这些工具都在。很多人在装依赖之前忽略了一个问题:没有安装libtool和bison库文件,编译OpenMPI时就会报缺少遗留文件。最好提前运行:
sudo yum install -y gcc gcc-c++ gfortran make wget tar sudo yum install -y libtool bison flex确认系统里没有残留的其他MPI版本也很关键。如果之前装过,建议先卸载或者把PATH、LD_LIBRARY_PATH里相关路径清理干净,免得后面的VASP编译链接到一套错误的MPI库。
2. Intel编译器、OpenMPI与FFTW的安装细节
2.1 Intel编译器的安装与环境变量
拿到Intel Parallel Studio XE安装包后,执行install脚本即可。安装过程中选择典型安装,不需要装太多组件,但必须确保ifort编译器、MKL数学库这两个核心模块被选中。装完后默认位置一般是/opt/intel/,但要注意设置环境变量。很多人安装步骤照做,后面编译VASP却报ifort命令不存在,十有八九就是没有执行:
source /opt/intel/bin/compilervars.sh intel64这个命令会同时载入MKL环境变量和Intel的库搜索路径。你可以把这行写进/etc/bashrc,这样每次打开终端都自动生效。但要注意,如果服务器上有其他用户不同版本的Intel编译器,写在全局目录可能冲突,更稳妥的方式是放到自己用户的.bashrc里:
echo 'source /opt/intel/bin/compilervars.sh intel64' >> ~/.bashrc完成后验证一下:
ifort --version如果能看到类似ifort (IFORT) 18.0.5的输出,说明编译器这部分已经就绪。这里要插一句,很多新手的误区是光有ifort就够了,其实VASP 5.4.1默认还要用C预处理器对源码做预处理,所以gcc也是必须的,不能为了追求“纯净”把系统自带gcc删掉。
2.2 用Intel编译器包装OpenMPI
OpenMPI本身要编译,而不是直接用系统的二进制安装。原因正如前面所说,mpif90这个包装脚本必须知道调用哪个Fortran编译器。如果系统里的OpenMPI是用gfortran编译的,你后面的FC只能写gfortran,那VASP就无法用ifort优化。所以这里要自己动手编译。
下载OpenMPI 3.1.6源码后,配置命令建议如下:
./configure CC=gcc CXX=g++ F77=ifort FC=ifort --prefix=/opt/openmpi-3.1.6这里指定F77和FC都用ifort,这样OpenMPI生成的mpif90就会在背后调用ifort。configure过程会检查很多依赖项,包括Fortran编译器是否可用、是否支持MPI模块等。如果检查到某些库缺失,往往会提示你安装,但也有警告是不影响编译的,比如“是否支持Java”之类的提示,忽略即可。
编译和安装:
make -j4 make install-j4是并行编译参数,根据机器核数调整。之后设置环境变量:
export PATH=/opt/openmpi-3.1.6/bin:$PATH export LD_LIBRARY_PATH=/opt/openmpi-3.1.6/lib:$LD_LIBRARY_PATH export MANPATH=/opt/openmpi-3.1.6/share/man:$MANPATH仍然建议写进.bashrc。然后用mpif90 --version验证,不出意外应该能看到ifort的版本号,这说明mpif90的底层确实是ifort。
注意:OpenMPI从某个版本开始禁止以root用户直接运行mpirun,如果你当前是root登录,测试并行程序时会收到“cannot run as root”的提示。要么切到普通用户运行,要么给mpirun加
--allow-run-as-root参数。我一般建议用普通用户做实际计算,更安全也更贴近集群使用习惯。
2.3 编译FFTW,避免精度踩雷
FFTW也需要源码编译,VASP链接的是Fourier变换库,这个库要支持双精度计算。很多人在configure阶段习惯性加上--enable-float,认为单精度能省内存,结果编译VASP时就会因为复数类型大小不匹配,链接阶段报一串“undefined reference”或者类型不匹配错误。VASP默认的DFT计算使用双精度,FFTW必须使用默认的双精度版本。
我常用的编译命令:
./configure CC=gcc FC=ifort F77=ifort --prefix=/opt/fftw-3.3.8 --enable-mpi --enable-shared make -j4 make install--enable-shared生成动态库,一会儿让VASP链接比较方便。--enable-mpi可以启用FFTW的并行变换,但VASP内部又有自己的一套FFT封装,很多时候只用串行库就够了。我保留这个选项是因为有些测试应用会需要,不影响VASP本身的链接。
装好后检查/opt/fftw-3.3.8/lib下有没有libfftw3.so和libfftw3_mpi.so。如果只看到mpi版本,说明串行库没生成,需要检查configure输出。也可以顺便编译一个Fortran接口的测试程序,确认ifort能正确找到fftw3.mod。
这里有个小技巧:为了防止目录混乱,建议把OpenMPI和FFTW都安装在/opt下的独立目录中,版本号写清楚。比如/opt/openmpi-3.1.6和/opt/fftw-3.3.8,这样后续切换版本或者清理环境时一目了然。
3. VASP源码准备与makefile.include配置
3.1 源码目录结构与arch模板
VASP是有版权的商业软件,需要跟随课题组购买许可证或从合法渠道获取源码包。拿到源码包后解压,你会看到src/目录,以及arch/目录,下面有一个makefile.include的模板文件。VASP编译时不会自动选择编译器配置,需要你把合适的配置复制为源码根目录下的makefile.include,然后执行make。
arch/目录下有很多已经写好的模板,例如makefile.include.linux_intel等,你可以先看看。但直接照搬往往不够,因为模板里的FFTW路径、MKL库名、MPI编译器名可能和你的实际环境不匹配。所以最好的办法是复制模板后,再按照自己机器的路径逐项修改。
3.2 一个可用的makefile.include参考
下面是我在CentOS 7.9 + ifort 18 + OpenMPI 3.1.6 + FFTW 3.3.8环境里验证过的配置模板,供参考:
# Precompiler CPP = gcc -E -P -C -traditional-cpp CPP_OPTIONS = -DHOST=\"LinuxIFC\" -Dkind8 -Ddcabs1 -DNGZhalf -DCACHE_SIZE=4000 -DPGF90 -DMPI -DMPI_BLOCK=8000 -Duse_collective -DscaLAPACK -DnoAugFillMeta -DCCDNE -Dw_work # Fortran compiler FC = mpif90 FCL = mpif90 # Compilation flags FREE = -free FFLAGS = -O2 -FR OFLAG = -O2 OFLAG_IN = -O2 DEBUG = -O0 CFLAGS = -O2 # MKL path and libraries MKL_PATH = $(MKLROOT) BLAS = -L$(MKL_PATH)/lib/intel64 -lmkl_intel_lp64 -lmkl_sequential -lmkl_core LAPACK = $(BLAS) BLACS = -lmkl_blacs_openmpi_lp64 SCALAPACK = $(BLACS) -lmkl_scalapack_lp64 # FFTW path FFTW_PATH = /opt/fftw-3.3.8 OBJECTS = fftmpiw.o fftmpi_map.o fft3dlib.o fftw3d.o FFT3D_LIBS = -L$(FFTW_PATH)/lib -lfftw3 LIBS = $(SCALAPACK) $(LAPACK) $(BLAS) $(FFT3D_LIBS)这个配置里有几个关键点值得说明。第一,FC和FCL写的是mpif90而不是mpiifort。mpiifort是Intel MPI的包装器,既然我们用的是OpenMPI,就要用OpenMPI的mpif90包装器,它才能正确连接OpenMPI的库。第二,CPP_OPTIONS里的-DMPI和-DscaLAPACK是开启并行和ScaLAPACK支持的开关,不能漏掉。-Duse_collective会使用MPI群集通信,对大规模计算有性能帮助。第三,BLACS我写的是-lmkl_blacs_openmpi_lp64,这对应OpenMPI接口。如果MKL版本较老,可能没有这个库名,那时可以试试-lmkl_blacs_intelmpi_lp64,不过需要额外把OpenMPI的动态库加入LD_LIBRARY_PATH,保证能解析。
LIBS行的顺序也有讲究:ScaLAPACK、LAPACK、BLAS、FFTW依次排列,因为静态库链接时有依赖顺序,库列表前面的必须是被后面需要的。如果你把FFTW放在最前面,可能会遇到fftw3库被使用时找不到依赖的符号。
3.3 路径检查与常见陷阱
配置文件里最容易出错的就是MKL_PATH。如果你执行source compilervars.sh intel64之后,echo $MKLROOT是空的,那后面-L$(MKLROOT)/lib就会变成-L/lib,链接阶段会有一堆找不到库的错误。遇到这种问题,先回过来检查Intel环境变量是否正常。
另一个常见问题是FFTW的include路径没有加入。VASP源文件里有include fftw3.f03这样的语句,如果你的FFTW_PATH没有指向正确目录,预编译时就会报找不到fftw3.f03。可以在makefile.include的CPP_OPTIONS里增加-I$(FFTW_PATH)/include,或者在链接库路径里保证FFTW_PATH/lib存在。我通常还会单独写一个环境变量:
export FFTW_HOME=/opt/fftw-3.3.8然后在makefile.include里引用$(FFTW_HOME),这样项目里其他地方也能复用。
4. 编译过程、链接测试与性能验证
4.1 make的流程和产物说明
配置好makefile.include后,进入VASP源码目录,先执行:
make veryclean这个命令会清除历史编译缓存,防止之前失败的编译残留影响新一轮编译。然后:
make allVASP 5.4.1的make all会依次编译三个可执行文件:vasp_std、vasp_gam和vasp_low。其中高精度版本是vasp_std,大多数计算会用到;vasp_gam针对Gamma点计算优化;vasp_low是低精度版本。如果机器性能不够,也可以只编译vasp_std,修改目标为make std。
编译过程中会看到大量的Fortran编译输出,这是正常现象。最终成功结束后,源码目录下会看到三个蓝色或者带有可执行权限的文件。如果不放心,可以用:
file vasp_std确认是ELF可执行文件。
4.2 编译失败时的错误定位思路
编译报错时不要慌,先看错误类型分成三类。
第一类:找不到ifort、mpif90或者头文件。这多半是环境变量没有生效,或者路径拼写错误。比如报错ifort: command not found,需要回到第2章检查source命令;报错fftw3.f03: No such file or directory,需要检查FFTW_PATH是否正确。
第二类:OpenMPI相关库无法解析。常见的报错是libmpi_so.so: cannot open shared object file。这时候给LD_LIBRARY_PATH加上OpenMPI的lib目录就行。还有一种情况是链接时MPI版本不一致,比如VASP源码里有的模块是基于MPI-2函数写的,而OpenMPI 4.x对某些旧接口有所调整,会报symbol not found。解决方案就是我之前建议的,用OpenMPI 3.1.x。
第三类:Intel编译器的数据类型或语法兼容性报错。更常见的表现是MKL的ScaLAPACK库和LAPACK库冲突,提示multiple definition of ...。出现这类报错时,先回去检查BLACS库名是否和MPI匹配。如果用的是OpenMPI,但库名误写成intelmpi,就会产生这种问题。修改为-lmkl_blacs_openmpi_lp64后重新make veryclean && make all即可。
另外还有一个很容易忽略的问题:在make all的过程中,如果某一阶段中断,残留的.o文件可能会让下一次编译变得莫名其妙。此时不要急着搜索错误,执行make veryclean再来一遍,往往能解决一半的灵异问题。
4.3 小体系测试与并行验证
编译完成后,找个非常简单的小体系测试,例如晶格常数为5.43埃的硅、4个原子,或者VASP自带的一些benchmark目录。先准备POSCAR、POTCAR、KPOINTS和INCAR文件。如果你是第一次运行,建议用串行方式先跑通:
./vasp_std如果能正常产生OUTCAR并且能量收敛,说明程序本身没有故障。然后测试并行:
mpirun -np 4 ./vasp_std这一步可以检验OpenMPI配置是否正常。如果mpirun报错orte_abort或者“unable to allocate shared memory”,通常是因为节点上的共享内存限制,或者是root用户运行限制。实在不行可以加--mca shmem_mmap_enable_nls_support 1,但治标不治本,最好还是切换普通用户。
测试并行时还要顺便看下CPU占用率,用top观察每个进程是否都满负荷。如果某些核闲置,说明MPI没有完全跑起来,需要检查INCAR文件里的并行参数,尤其是NPAR。经验上,NPAR通常设置为节点核心数的平方根,同时不要大于总核数。对于小体系,用4核并行时NPAR=2,8核并行时NPAR=2或4。这个参数直接影响通信开销,调好了能明显改善加速比。
5. 常见问题排查与实战经验
5.1 Intel编译器版本过旧或过新怎么处理
VASP 5.4.1的代码里有一些老式的Fortran语法,如果编译器版本太老,比如ifort 2011,可能会因为不支持某些新特性而报错;如果版本太新,比如oneAPI 2023,反而会警告甚至因为整数长度默认值变化导致计算结果异常。面对这种情况,我的建议是专门准备一套旧版Intel环境放在/opt/intel-2018,避免影响其他新项目。如果你必须用新编译器,可以尝试给FFLAGS加上-assume byterecl或-std 2008这类兼容选项,但这属于“碰运气”,不如直接切编译器版本稳定。
5.2 OpenMPI运行时出现“无法生成共享库文件”
真实场景中很常见的情况是,mpirun在多个节点跨机运行时报错,而单机测试没问题。原因是OpenMPI运行时需要访问每个节点上的相同路径。例如你安装在/opt/openmpi-3.1.6,那所有计算节点都要在该路径下有相同版本的OpenMPI。一个简单的方法是下载官方打包的二进制或者把整个目录同步到每个节点。另外一个更隐蔽的问题是,登录节点与计算节点共享/home目录,但/opt不共享,导致mpirun在计算节点上找不到库。解决思路:要么将/opt也做成网络磁盘挂载,要么在提交作业脚本里带上module load或者source环境变量的语句,确保每个计算节点都能得到正确的环境。
5.3 FFTW库造成的虚惊
有一个特别容易让人误解的报错是undefined reference: 'zf_fftw_plan_dft_3d'。看到这种错误,很多人以为是FFTW没有编好,其实是编译VASP时选择了自带的fft3dlib而不是外部的FFTW。VASP源码在src/内部有一套自己的FFT实现,叫fft3dlib,官方makefile默认使用它。如果你在makefile.include中设置了OBJECTS,一定确保里面包含fft3dlib.o和fftw3d.o的组合,不要只留一个。另外,如果你想让VASP使用MKL的FFTW接口,可以把FFTW_PATH改成MKL路径并设置-Dmkl_fft,但那样就不算独立FFTW环境了。既然标题用的是intel、openmpi、fftw环境,保持独立FFTW更符合本教程意图。
5.4 运行时的“非法指令”错误
这种情况在校园集群中常见:登录节点CPU有新指令集,但计算节点是老的架构。你在登录节点上用-xHost编译,VASP会利用当前CPU的最大指令集,比如AVX512。然后作业被调度到不支持AVX512的老节点上,程序一运行就崩溃。解决方式是编译时不要用-xHost,而是选择一个所有节点都支持的保守指令集。比如Sandy Bridge及以后都有AVX,可以写-xCORE-AVX2或者-xAVX。性能损失不多,但稳定性大大提升。
6. 编译完成后的若干细节优化
可执行文件生成后用起来,还会有一些小地方可以打磨。
首先是环境变量一条龙。建议写一个vasp_env.sh文件,里面把Intel、OpenMPI、FFTW的环境变量一次性加载好,然后在VASP计算脚本里source这个文件。这样既能避免每次手敲,也能防止提交作业时环境变量丢失。一个简单版本:
source /opt/intel/bin/compilervars.sh intel64 export PATH=/opt/openmpi-3.1.6/bin:$PATH export LD_LIBRARY_PATH=/opt/openmpi-3.1.6/lib:/opt/fftw-3.3.8/lib:$LD_LIBRARY_PATH其次是编译缓存。VASP运行生成的OUTCAR、WAVECAR、CHGCAR都很大,建议在计算目录用软链接指向大容量磁盘。如果在同一个目录反复计算,记得清理旧的WAVECAR,否则VASP会从旧波函数继续迭代,可能影响新计算的结果。这个不算编译问题,但确实是很多人踩过的坑。
最后是关于要不要真正使用libfftw3库的思考。有时你会发现,不装FFTW,直接用MKL自带的FFTW接口,VASP也能编译通过。那为什么还要独立编译FFTW?我的理解是,VASP 5.4.1自带源码在个别体系上性能偏弱,而独立FFTW允许你针对自己的CPU做更精细的编译优化,同时避免MKL库版本升级带来的ABI变化。尤其是当你需要在一个特定集群(比如旧处理器+qxed系统)上折腾时,独立FFTW更可控。当然,如果你只有一套环境,直接MKL也是省事的选择。这个取舍没有绝对答案,只是取决于你后续运维的舒适度。
从流程上看,CentOS安装VASP 5.4.1的难度其实不大,核心在于把Intel编译器、OpenMPI、FFTW三者匹配好。如果这三者和谐,整个编译过程甚至不需要改动太多源码。我的个人习惯是拿到一套服务器后,先把这几个库装进/opt统一管理,再写一个环境脚本固化下来,以后不管编译什么版本的计算软件都能少走弯路。如果你在配置中卡了很久,不妨从版本匹配角度重新审视一遍,而不是盯着某一个报错反复硬怼。希望这篇教程能帮你把环境一次配好,顺利跑起来。