自动生成POTCAR的脚本

前面我们介绍了KPOINTS的小脚本的写法,本节我们主要讲解一下生成POTCAR的脚本。学习完本节,脚本的神秘色彩基本烟消云散,大家都可以尝试写自己的脚本了。再强调说明三点:

1)Windows用户不要用记事本写脚本;

2)Windows用户写完脚本后,在服务器上先运行:dos2unix XXX (XXX 是你的脚本名)

3)Windows用户,如果计算出错,第一个要排除的是自己提交任务前有没有运行:dos2unix.

1 手动示例:

比如我们POSCAR中包含有Cu C H O 四种种元素,那么我们就需要按照顺序生成一个对应的POTCAR。首先回顾一下前面介绍的POTCAR的制备方法:

1.1)获取这四个元素各自的POTCAR:并命名成POTCAR_Cu,POTCAR_C,POTCAR_H,POTCAR_O

1.2)使用cat 命令将这四个POTCAR合并在一起:cat POTCAR_Cu POTCAR_C POTCAR_H POTCAR_O > POTCAR

前面我们学过了 > 的使用。分步练习:第一步将这些元素的POTCAR全部打印出来:

cat POTCAR_Cu POTCAR_C POTCAR_H POTCAR_O

第二步:将打印出来的内容通过 > 保存到最终的POTCAR里面。

脚本目的:

自动从赝势库中提取所需元素的POTCAR并将它们合并在一起。我们赝势库的目录为:/THFS/home/iciq-lq/bin/pot 这个pot文件夹(我自己随便命名的)就包含了VASP的所有元素的POTCAR,最好放在一个不经常变动的地方,这里我们放到了~/bin目录里面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iciq-lq@ln3:/THFS/home/iciq-lq/bin/pot$ ls
Ac At_sv_GW Bi_sv_GW C_GW C_s ....
iciq-lq@ln3:/THFS/home/iciq-lq/bin/pot$ ls B*
B:
POTCAR PSCTR

Ba_sv:
POTCAR PSCTR

Ba_sv_GW:
POTCAR PSCTR

Be:
POTCAR PSCTR

Be_GW:
POTCAR PSCTR

所以我们可以使用下面的命令生成POTCAR:(不将这几个POTCAR先保存到当前目录下,直接调用赝势库中的POTCAR)

1
2
3
4
5
6
7
8
iciq-lq@ln3:/THFS/home/iciq-lq$ cat /THFS/home/iciq-lq/bin/pot/Cu/POTCAR  /THFS/home/iciq-lq/bin/pot/C/POTCAR /THFS/home/iciq-lq/bin/pot/H/POTCAR  /THFS/home/iciq-lq/bin/pot/O/POTCAR  > POTCAR
iciq-lq@ln3:/THFS/home/iciq-lq$ grep TIT POTCAR
TITEL = PAW_PBE Cu 22Jun2005
TITEL = PAW_PBE C 08Apr2002
TITEL = PAW_PBE H 15Jun2001
TITEL = PAW_PBE O 08Apr2002
iciq-lq@ln3:/THFS/home/iciq-lq$

但这样子也很麻烦。

2 脚本预览:

首先看下自动生成POTCAR的脚本,大家尽量先不看下面的解释,自己理解一下脚本的整个框架和运行的流程;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env bash
# Create a GGA_PAW POTCAR file
# by BigBro
# To Use it: potcar.sh Cu C H O

# Define local potpaw_GGA pseudopotentialrepository:
repo="/THFS/home/iciq-lq/bin/pot"

# Check if older version of POTCAR ispresent
if [ -f POTCAR ] ; then
mv -f POTCAR old-POTCAR
echo " ** Warning: old POTCAR file found and renamed to 'old-POTCAR'."
fi

# Main loop - concatenate the appropriatePOTCARs (or archives)
for i in $*
do
if test -f $repo/$i/POTCAR ; then
cat $repo/$i/POTCAR>> POTCAR
else
echo " ** Warning: No suitable POTCAR for element '$i' found!! Skipped thiselement."
fi
done

讲解,这个脚本里面:

1)首先我们先设定赝势库的目录;repo="/THFS/home/iciq-lq/bin/pot" 等号前后不能有空格!!!

2)然后我们检查一下当前目录下是否存在POTCAR,如果存在的话,将其重命名为:POTCAR-old, 并输出警告信息。这里我们学到的是 if 句型:if [ ] ; then; fi[] 中间是if判断的条件,如果成立,则继续执行then后面的动作。

if [ -f POTCAR ]; then 意思是如果存在POTCAR这个文件,那么… 注意:

a)[ ] 和里面的内容 –f POTCAR 要通过空格分开。所以:

  • if [-f POTCAR ][-f之间没有空格)

  • if [ -f POTCAR] (POTCAR] 之间没有空格)

  • if [-f POTCAR]-fPOTCAR[] 之间都没有空格)

这三种写法都是错误的;if [ -f POTCAR ] 是正确的

b)then 后面如果另起一行的话,分号 (;) 可加可不加;

c)then 后面的内容如果和then 在同一行,必须加上分号(;) ,前后有无空格均可,建议加上,这样语言会很清晰;

d)then 后面的命令执行完毕后,要加上 fi 结束。同理,如果fi 另起一行,则前面可以不加;如果fithen 后面执行的命令在一行,前面需要加上分号(;)。

3)生成新的POTCAR文件; 这里我们用到的是一个for循环:

a) for i in $*

这一行的意思是,对于命令后面的所有参数(arguments),前面一节我们已经学过了$1 $2 ... 的含义,这里用的$* 可以让我们在命令后面加任意数目的参数;因为另起了一行,后面加不加分号(;)不重要。

b) do 执行的意思

c)do后面有个if 语句,如果目录下面是POTCAR的话,那么使用cat 命令将所有$*对应的POTCAR输出到最新的POTCAR中,注意,这里我们用到的是>>; 因为for循环是对于后面的参数挨个执行的。

d) 有两个elif,判断目录下的另外两个POTCAR文件的格式,如果是POTCAR.Z 文件的话,则使用zcat 将其输出到最新的POTCAR;如果是POTCAR.gz 文件的话,则使用gunzip –c 命令。

e)else 指的是除了前面三种以外的情况,如果POTCAR,POTCAR.Z或者POTCAR.gz都不存在,那么使用echo命令,输出警告,提醒用户检查。

f)使用fi 结束if 语句

g)使用 done 结束 for 循环。

3 运行脚本:

3.1)赋予脚本可执行权限,然后将其转移到主目录下的bin文件夹中,前面几节已经讲过了。

1
2
chmod u+x potcar.sh
mv potcar.sh ~/bin

3.2 运行实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iciq-lq@ln3:/THFS/home/iciq-lq$ ls
bin LVASPTHW old-POTCAR POTCAR potcar.sh test_jobs
iciq-lq@ln3:/THFS/home/iciq-lq$ potcar.sh Cu C H O
** Warning: old POTCAR file found and renamed to 'old-POTCAR'.
iciq-lq@ln3:/THFS/home/iciq-lq$ ls
bin LVASPTHW old-POTCAR POTCAR potcar.sh test_jobs
iciq-lq@ln3:/THFS/home/iciq-lq$ grep TIT POTCAR
TITEL = PAW_PBE Cu 22Jun2005
TITEL = PAW_PBE C 08Apr2002
TITEL = PAW_PBE H 15Jun2001
TITEL = PAW_PBE O 08Apr2002
iciq-lq@ln3:/THFS/home/iciq-lq$
iciq-lq@ln3:/THFS/home/iciq-lq$ potcar.sh BigBro
** Warning: old POTCAR file found and renamed to 'old-POTCAR'.
** Warning: No suitable POTCAR for element 'BigBro' found!! Skipped thiselement.
iciq-lq@ln3:/THFS/home/iciq-lq$

当前目录下存在POTCAR,脚本会给出警告,将其重命名为old-POTCAR,然后生成新的POTCAR文件,包含Cu C H O 这四种元素。如果有一个元素不存在(上面实例总的BigBro),potcar库里找不到,则输出错误提示。

注意!注意!注意!

上面例子中的错误,还可能是因为:

  • 1) 你的POSCAR的格式有问题(Windows用户常见的问题),如果发现这个错误,先运行下:dos2unix POSCAR 这个命令排除是Windows的格式问题。

  • 2) 如果还不能解决,去你的POTCAR库里面找找,是不是真的没有这个元素的POTCAR文件。

4 脚本分析:

4.1)生成一些特殊的POTCAR文件:

我们知道,每一个元素存在好几个不同的POTCAR,如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
iciq-lq@ln3:/THFS/home/iciq-lq/bin/pot$ ls Cu*
Cu:
POTCAR PSCTR

Cu_GW:
POTCAR PSCTR

Cu_pv:
POTCAR PSCTR

Cu_sv_GW:
POTCAR PSCTR
iciq-lq@ln3:/THFS/home/iciq-lq/bin/pot$ ls H
H/ H1.33/ H1.66/ H.25/ H.42/ H.58/ H.75/ He/ He_GW/ Hf_pv/ Hf_sv_GW/ Hg_sv_GW/ H_h/ Ho/ H_s/
H1.25/ H1.5/ H1.75/ H.33/ H.5/ H.66/ H_AE/ He_AE/ Hf/ Hf_sv/ Hg/ H_GW/ H_h_GW/ Ho_3/

当我们需要使用 Cu_pv, C,H1.25,和O对应的POTCAR时,我们需要这样执行命令:

1
2
3
4
5
6
7
8
9
10
11
iciq-lq@ln3:/THFS/home/iciq-lq$ ls
bin LVASPTHW test_jobs
iciq-lq@ln3:/THFS/home/iciq-lq$ potcar.sh Cu_pv C H1.25 O
iciq-lq@ln3:/THFS/home/iciq-lq$ ls
bin LVASPTHW POTCAR test_jobs
iciq-lq@ln3:/THFS/home/iciq-lq$ grep TIT POTCAR
TITEL = PAW_PBE Cu_pv 06Sep2000
TITEL = PAW_PBE C 08Apr2002
TITEL = PAW_PBE H1.25 07Sep2000
TITEL = PAW_PBE O 08Apr2002
iciq-lq@ln3:/THFS/home/iciq-lq$

因此,如果我们使用脚本的时候直接输入元素符号,默认读取的是与该元素符号相对应文件下的POTCAR。

5 读取POSCAR,自动生成POTCAR (防止出错的一个秘诀)

在我们的计算中,可以通过读取POSCAR中的元素信息,生成对应的POTCAR文件,这样可以避免POSCAR中元素和POTCAR中不一致的情况。那么我们需要怎么做呢?

5.1 首先我们要获取POSCAR中的元素信息: 查看一下POSCAR文件,发现元素信息在第6行,因此加了一个tail命令提取出来:

1
2
3
4
5
6
7
8
9
10
11
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ ls
POSCAR
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ head -n 6 POSCAR
Ru H
1.00000000000000
8.1377999784000004 0.0000000000000000 0.0000000000000000
4.0688999892000002 7.0475415119999996 0.0000000000000000
0.0000000000000000 0.0000000000000000 21.5631999968999999
Ru H
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ head -n 6 POSCAR | tail -n 1
Ru H

5.2 使用我们刚刚写出来的脚本,通过使用$()调用前面命令的结果: (将获取的元素信息作为脚本命令的参数)

1
2
3
4
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$  potcar.sh  $(head -n 6  POSCAR | tail -n 1)
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ grep TIT POTCAR
TITEL = PAW_PBE Ru 04Feb2005
TITEL = PAW_PBE H 15Jun2001

大功告成!!!!

5.3 不想每次输入这么长的命令:可以将其写进 ~/.bashrc文件中:

1
alias pos2pot="potcar.sh  $(head -n 6 POSCAR  | tail -n 1)"
1
2
3
4
5
6
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ ls
POSCAR POTCAR
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ vi ~/.bashrc
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ . ~/.bashrc
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ pos2pot
** Warning: old POTCAR file found and renamed to 'old-POTCAR'.

5.4 看完上面的部分,相信大家已经可以掌握很多内容了,额外福利,大师兄本人并没有使用head -n 6 POSCAR | tail -n 1 来获取POSCAR中的元素信息。而是使用的sed命令:

1
2
iciq-lq@ln3:/THFS/home/iciq-lq/LVASPTHW/potcar$ sed -n 6p POSCAR
Ru H

6 扩展练习:

6.1)手动将这个脚本打一遍,理解里面的内容,如果出错了,对比我的脚本,进行改正,直至可以正确运行为止;

6.2)去官网查看POTCAR相关的内容,了解每一个元素不同的POTCAR之间的区别,例如:Cu 和 Cu_pv

6.3) 复习alias,学习本文第5节的方法,思考一下,如何通过操控脚本,避免计算中的一些失误,有了自己的想法后,通过脚本付诸实践。

7 总结:

写到这里,相信大家对于Linux系统下的一些基本操作已经熟练掌握了,脚本的怎么写,怎么去运行,心里也有了一个大致的了解,至少不会感觉写脚本是多么牛逼的工作了。这些内容都是我们保证计算准确,高效的很重要的一个因素。希望大家可以熟练掌握,最关键的是,要硬着头皮去练习,脚本看起来简单,等你写的时候就会出现各种各样的错误,只有不断练习,才能写出漂亮的脚本,提高自己的工作效率。 脚本已经上传至QQ群文件,也可百度网盘下载:链接:https://pan.baidu.com/s/1eqeVVOo5nzGJsfPgClNJDg