编译带 dftd4 的 vasp.6.2.1

VASP 从 6.2.0 开始支持 DFT-D4 方法, 但是需要作为外部包在编译的时候额外编译进去。实际操作的时候, 我发现其实想要用上带 DFT-D4 的 vasp 没那么简单, 本贴子记录了一下本人在学校的 hpc 集群上安装 Grimme 的 dftd4 程序和编译带 dftd4 的 vasp.6.2.1 时的过程, 希望对有兴趣和需求的人有启发和帮助。本文先发在计算化学公社论坛, 简单修改后发到这来凑个数。

1. 安装 dftd4
社长的博文中有对 DFT-D4 方法的介绍, 而且提供了 2 种编译方法——简单粗暴的方法和基于 meson+ninja 的编译方法。当时的 dftd4 是 ver 2.0, 目前最新的 dftd4 已经到了 ver 3.3.0, 程序已经被重写了一遍。但是非常蛋疼的是, vasp 的代码中用的 api 是基于 2.x 版本的, 如果编译的 dftd4 是 3.2.0 及之前的 3.x 版本, vasp 编译会出错, 好在 3.3 版中重新增加了 vasp 用的 2.x api。(https://github.com/dftd4/dftd4/issues/85, https://zhuanlan.zhihu.com/p/375207527)
编译环境:
GCCcore-10.3.0, CentOS Linux release 8.4.2105, meson-0.58.0, ninja-1.10.2, python-3.9.5 我分别在 Intel® Parallel Studio XE 2020 Update 1 (19.1.1.217) 和 Intel® Parallel Studio XE 2019 Update 1 (19.0.1.144)环境下尝试编译 dftd4。
根据 dftd4 的github上的指南, 用以下 4 条指令编译 dftd4

1
2
3
4
meson setup _build
meson test -C _build --print-errorlogs
meson configure _build --prefix=/path/to/install
meson install -C _build

但发现均无法正常编译, 并且没有产生 ver 3.3.0 新加的给 vasp 使用的旧 api。
首先编译问题可以在第一条命令中, 添加通过指定编译器的环境变量解决。如果是 Intel® Parallel Studio XE 2020 update 1 (19.1.1.217) 环境, 则用

1
FC=ifort CC=icc CXX=icpc meson setup _build

如果是 Intel® Parallel Studio XE 2019 update 1 (19.0.1.144) 环境, 则用

1
FC=ifort CC=icc CXX=icpc meson setup _build

(在我的测试中, 如果反过来均会报错导致编译失败, 非常神奇但是不清楚为什么)

然后在第三条指令中, 加入 -Dapi_v2=True 变成

1
meson configure _build --prefix=/path/to/install -Dapi_v2=True

来生成 vasp 可用的 api。

最后在 .bashrc 中加入并且source ~/.bashrc

1
export LD_LIBRARY_PATH=$HOME/bin/dftd4/lib64:$LD_LIBRARY_PATH

(编译 dftd4 时 --prefix=$HOME/bin/dftd4)

2.编译 vasp
(关于编译 vasp 中遇到的问题不在本贴子的讨论范围内)
Vasp wiki中
给出指南是这样的(应该适用于ver 2.x版本的 dftd3

1
2
3
CPP_OPTIONS += -DDFTD4
LLIBS += -Lyour-libdftd4-build -ldftd4
INCS += -Iyour-libdftd4-build/libdftd4.a.p

我英语能力有限, 实在是没理解 your-libdftd4-build 到底是指什么目录, 并且 ver 3.x 的dftd4似乎没有生成 libdftd4.a.p 文件。我用以下路径能够得到编译成功并且可以使用 dftd4 的 vasp 二进制文件

1
2
3
CPP_OPTIONS += -DDFTD4
LLIBS += -L$HOME/bin/dftd4/lib64 -ldftd4
INCS += -I$HOME/bin/dftd4/include/dftd4/intel-xx.x.x.xxx

(若编译 dftd 4时 --prefix=$HOME/bin/dftd4)
其中 intel-xx.x.x.xxx 中的数字为编译时使用的 intel 编译器版本号

3.在 vasp.6.2.0 前的版本使用dftd4
我发现在 vasp.6.1.0 中已经有关于 dftd4 的源代码, 主要是 vdwforcefield.F 和 subdftd4.F 这两个。简单对比了一下发现和 6.2.0 的没什么区别, 应该是可以直接用。再之前的版本, 根据 dftd4 的 GitHub page 上的一个 subproject, 似乎可以通过修改和增加代码来用上 dftd4, 这里搬运一下。

首先修改 src/vdwforcefield.F 文件, 在 vdw_forces_main subroutine 中加入

1
USE vdwD4

然后在

1
2
3
!c D3(BJ-damping) by Jonas Moellman
CASE(12)
CALL vdw_forces_D3(IO,LATT_CUR,DYN,T_INFO,TSIF,TIFOR,TOTEN,ELEM,historycounter,4,IVDW)

下方加入

1
2
3
! D4-ATM(EEQ) implemented by Eike Caldeweyher
CASE(13)
CALL vdw_forces_D4(IO,LATT_CUR,DYN,T_INFO,TSIF,TIFOR,TOTEN,ELEM,IVDW)

然后找到 vdw_read subroutine 中读取 INCAR 中 IVDW flag 的值的这段代码

1
2
3
4
5
6
7
8
9
IF (IVDW==1 .OR. IVDW==2 .OR. IVDW==3 .OR. IVDW==4 .OR. (IVDW>=10 .AND. IVDW<=12) .OR.  &
& IVDW==101 .OR. (IVDW>=20 .AND. IVDW<=22) .OR. IVDW==26 .OR. IVDW==202 &
& .OR. IVDW==212 .OR. IVDW==263 .OR. IVDW==612 ) THEN
LVDW=.TRUE.
ELSE
LVDW=.FALSE.
CALL PROCESS_INCAR(LOPEN, IO%IU0, IO%IU5, 'LVDW', LVDW, IERR, WRITEXMLINCAR)
IF (LVDW) IVDW=1
ENDIF

(IVDW>=10 .AND. IVDW<=12) 改成 (IVDW>=10 .AND. IVDW<=13)
然后把 subdftd4.F 放到 src 文件夹下。如果是 vasp5 的话, 需要把 subdftd4.F 中所有关于 vtutor 的代码注释掉, vtutor module 是 vasp6 新加的。
最后修改 /src/.object, 找到 subdftd3.o\, 在它下面一行加上 subdftd4.o\

然后就可以修改 makeflie.include 进行编译了。不过注意这里 CCP_OPTIONS 里是 -DWITH_DFTD4 不是 -DDFTD4

p.s. 其实在写本文的时候 dftd4 还在 3.2 版, 但是支持 vasp 的源代码 compat.f90 已经在 github page 上了, 原本是想介绍一下怎么用 compat.f90 微微魔改一下dftd4的代码, 提前体验这个新功能的, 结果计划赶不上变化hhhhhhh