计算化学公社

 找回密码 Forget password
 注册 Register
Views: 9150|回复 Reply: 2
打印 Print 上一主题 Last thread 下一主题 Next thread

[VASP] 求助:sortcar.py脚本报错

[复制链接 Copy URL]

112

帖子

0

威望

851

eV
积分
963

Level 4 (黑子)

跳转到指定楼层 Go to specific reply
楼主
大家好,在学习Learn by the hard way中https://www.bigbrosci.com/2018/10/07/ex59/谈到使用sortcar.py脚本进行原子分层,但是发现:使用之后POSCAR只剩余一行原子,我的python2.7.12。具体情况如下,想请教大家如何解决?

1、运行后系统报错:
Traceback (most recent call last):
  File "/bin/sortcar.py", line 61, in <module>
    for j in get_elements(i):
  File "/bin/sortcar.py", line 36, in get_elements
    coord_list = lines[j+8].strip().split()[0:3]
IndexError: list index out of range

2、Cu111-4layer的POSCAR
Cu\(1\1\1)
1.0
        2.5559999943         0.0000000000         0.0000000000
       -1.2779999971         2.2135609271         0.0000000000
        0.0000000000         0.0000000000        21.2607994080
   Cu
    4
Direct
     0.000000000         0.000000000         0.000000000
    -0.000000000        -0.000000000         0.294479990
     0.666670035         0.333329996         0.196320001
     0.333329991         0.666670009         0.098160000

3、使用脚本后的POSCAR
Cu\(1\1\1)
1.0
        2.5559999943         0.0000000000         0.0000000000
       -1.2779999971         2.2135609271         0.0000000000
        0.0000000000         0.0000000000        21.2607994080
   Cu
    4
Direct
     0.000000000         0.000000000         0.000000000

4、脚本如下:
#!/usr/bin/env python
from collections import defaultdict
import numpy as np
import sys

in_file = sys.argv[1]

### READ input file ###
def read_inputcar(in_file):
    f = open(in_file, 'r')
    lines = f.readlines()
    f.close()
    ele_name  = lines[5].strip().split()
    ele_num = [int(i) for i in lines[6].strip().split()]
    dict_contcar =  {ele_name:ele_num for i in range(0, len(ele_name))}
    dict_contcar2 = defaultdict(list)
    for element in ele_name:
        indice  = ele_name.index(element)
        n_start = sum(ele_num for i in range(0, indice+1)) - dict_contcar.get(element) +1
        n_end = sum(ele_num for i in range(0, indice+1)) +1
        dict_contcar2[element].append(range(n_start, n_end))
    return lines, ele_name, ele_num, dict_contcar2, dict_contcar

def get_elements(ele):
    lines, ele_name, ele_num, dict_contcar2, dict_contar = read_inputcar(in_file)
    coord_total = []
    my_list = []
    my_dict = {}
    for j in dict_contcar2.get(ele)[0]:
        coord_list = lines[j+8].strip().split()[0:3]
        tf_list = lines[j+8].strip().split()[3:]
        my_list.append(coord_list)
        dict_key = '-'.join(coord_list)
        my_dict[dict_key] = tf_list
      
    data = np.array(my_list)
    data=data[np.argsort(data[:,2])]

    for k in data:
         coord = '  '.join(k)
         tf = '  '.join(my_dict.get('-'.join(k)))
         coord_total.append(coord + '  ' + tf )
    return coord_total

## Generate the New POSCAR file

def Get_and_Save_lines(file_name, start_line, end_line):
    f = open(file_name)
    lines =  f.readlines()
    for line in lines[int(start_line):int(end_line)]:
        file_out.write(line.rstrip()+'\n')

out_name = in_file + '_sorted'
file_out = open(out_name, 'w')
Get_and_Save_lines(in_file, 0, 9)

ele_name = read_inputcar(in_file)[1]
dict_contcar = read_inputcar(in_file)[-1]

for i in ele_name:
    if dict_contcar.get(i) > 1 :
        file_out.write('\n'.join(get_elements(i)))
    else:
        file_out.write('\n %s \n' %('  '.join(get_elements(i))))

3754

帖子

3

威望

1万

eV
积分
19675

Level 6 (一方通行)

围观吃瓜群众

2#
发表于 Post on 2019-5-22 09:57:58 | 只看该作者 Only view this author
本帖最后由 卡开发发 于 2019-5-22 10:14 编辑

一、测试了一下(python3.6.4):
1、加入Selective的行。
2、注释48行
3、49行改为coord_total.append(coord + '  ')
这样或许可行。
二、如果只是对原子按坐标进行固定而不进行排序,可以试试这个脚本:
  1. """
  2. 作者:卡开发发
  3. 日期:2019-5-22
  4. 使用方法: atom_frozen.py POSCAR condition
  5. condition为原子被固定所满足的条件(python风格),如:"x<0.5",
  6. "0<x<0.3" "x>0.2 or 0<z<0.8"等都为合法表示
  7. """

  8. import sys
  9. import re

  10. try:
  11.         #读取POSCAR文件内容
  12.         f=open(sys.argv[1])
  13.         info_=f.read()
  14.         f.close()
  15.         """
  16.         POSCAR解析:
  17.         第一行为POSCAR注释;
  18.         第二行为晶格缩放因子;
  19.         第三至五行为3x3晶格矢量;
  20.         第六至第九行依次可能为元素名称(可选)、原子数目、
  21.         Selective dynamics选项(可选)、坐标类型(分数坐标或笛卡尔坐标)之后
  22.         为原子坐标数据。

  23.         思路:
  24.         原子坐标部分的格式为“回车、空格(0或多个)、数据、空格(1或多个)、
  25.         数据、空格(1或多个)、数据、回车”。使用正则表达式按照此格式查找时,
  26.         元素名称和原子数目这两行可能会对原子坐标读取产生干扰,因此先挑出第
  27.         八行之后的文本再用正则表达式按上述格式进行查找较为可行。
  28.         然后以原子坐标部分的第一行将文本进行分割保留前半部分,这部分文本内
  29.         容在构造新的POSCAR时不变。
  30.         再将原子坐标部分的文本逐行分割数据并转换为float型。
  31.         """
  32.         #按回车分割7次
  33.         info=info_.split('\n',7)[-1]
  34.         #按照格式进行查找
  35.         xyz_=re.findall('\n*\s*(\S+\s+\S+\s+\S+)\n',info)
  36.         #按照原子坐标部分第一行分割
  37.         head=info_.split(xyz_[0])[0].strip()+'\n'
  38.         #分割圆子坐标并转换为float型
  39.         xyz=[[float(r) for r in r_.split()] for r_ in xyz_]
  40. except:
  41.         exit('POSCAR error!')

  42. try:
  43.         #xyz_用来储存固定原子后的原子坐标文本
  44.         xyz_=''
  45.         """
  46.         思路:
  47.         输入的条件以文本形式保存,将文本转换为python指令并通过exec执行,
  48.         其中文本x、y、z替换成某一原子坐标r中的r[0]、r[1]、r[2]。当r满足
  49.         给定条件时cond为True,flag为'F F F',原子被固定;反之为False,flag为
  50.         'T T T',原子可弛豫。
  51.         """
  52.         #将条件改写成python表达式
  53.         cond_='cond=('+sys.argv[2]+')'
  54.         #替换x、y、z为r的分量
  55.         if 'x' in cond_:
  56.                 cond_=cond_.replace('x','r[0]')
  57.         if 'y' in cond_:
  58.                 cond_=cond_.replace('y','r[1]')
  59.         if 'z' in cond_:
  60.                 cond_=cond_.replace('z','r[2]')
  61.         for r in xyz:
  62.                 #执行上述表达式
  63.                 exec(cond_)
  64.                 if cond:
  65.                         flag='F   F   F'
  66.                 else:
  67.                         flag='T   T   T'
  68.                 #以坐标xyz flag格式保存
  69.                 r_='%16.9f    %16.9f    %16.9f    %s\n'%(r[0],r[1],r[2],flag)
  70.                 xyz_+=r_
  71. except:
  72.         exit('Conditions error')

  73. #将修改后的内容写入到POSCAR_frozen中
  74. fname=sys.argv[1]+'_fronzen'
  75. f=open(fname,'w+')
  76. f.write(head)
  77. f.write(xyz_)
  78. f.close()
  79. print('%s has been created!'%fname)
复制代码


评分 Rate

参与人数
Participants 2
eV +6 收起 理由
Reason
wrtgcn + 3
sobereva + 3

查看全部评分 View all ratings

日常打哑谜&&探寻更多可能。
原理问题不公开讨论,非商业性质讨论欢迎私聊。不做培*,不接代*,不接*发谢谢。

112

帖子

0

威望

851

eV
积分
963

Level 4 (黑子)

3#
 楼主 Author| 发表于 Post on 2019-5-29 19:55:52 | 只看该作者 Only view this author
卡开发发 发表于 2019-5-22 09:57
一、测试了一下(python3.6.4):
1、加入Selective的行。
2、注释48行

非常感谢您的回复   还提供了自写脚本

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2025-8-15 20:44 , Processed in 0.160340 second(s), 21 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list