Source code for dpgen.auto_test.VASP
import os
from dpgen import dlog
from dpgen.util import sepline
import dpgen.auto_test.lib.vasp as vasp
from dpgen.auto_test.Task import Task
from dpgen.generator.lib.vasp import incar_upper
from dpdata import LabeledSystem
from monty.serialization import dumpfn
from pymatgen.io.vasp import Incar, Kpoints
from pymatgen.core.structure import Structure
[docs]class VASP(Task):
def __init__(self,
inter_parameter,
path_to_poscar):
self.inter = inter_parameter
self.inter_type = inter_parameter['type']
self.incar = inter_parameter['incar']
self.potcar_prefix = inter_parameter.get('potcar_prefix', '')
self.potcars = inter_parameter['potcars']
self.path_to_poscar = path_to_poscar
[docs] def make_potential_files(self,
output_dir):
potcar_not_link_list = ['vacancy', 'interstitial']
task_type = output_dir.split('/')[-2].split('_')[0]
ele_pot_list = [key for key in self.potcars.keys()]
poscar = os.path.abspath(os.path.join(output_dir, 'POSCAR'))
pos_str = Structure.from_file(poscar)
ele_pos_list_tmp = list(ii.as_dict()['element'] for ii in pos_str.species)
ele_pos_list = [ele_pos_list_tmp[0]]
for ii in range(1, len(ele_pos_list_tmp)):
if not ele_pos_list_tmp[ii] == ele_pos_list_tmp[ii - 1]:
ele_pos_list.append(ele_pos_list_tmp[ii])
if task_type in potcar_not_link_list:
with open(os.path.join(output_dir, 'POTCAR'), 'w') as fp:
for ii in ele_pos_list:
for jj in ele_pot_list:
if ii == jj:
with open(os.path.join(self.potcar_prefix, self.potcars[jj]), 'r') as fin:
for line in fin:
print(line.strip('\n'), file=fp)
else:
if not os.path.isfile(os.path.join(output_dir, '../POTCAR')):
with open(os.path.join(output_dir, '../POTCAR'), 'w') as fp:
for ii in ele_pos_list:
for jj in ele_pot_list:
if ii == jj:
with open(os.path.join(self.potcar_prefix, self.potcars[jj]), 'r') as fin:
for line in fin:
print(line.strip('\n'), file=fp)
cwd = os.getcwd()
os.chdir(output_dir)
if not os.path.islink('POTCAR'):
os.symlink('../POTCAR', 'POTCAR')
elif not '../POTCAR' == os.readlink('POTCAR'):
os.remove('POTCAR')
os.symlink('../POTCAR', 'POTCAR')
os.chdir(cwd)
dumpfn(self.inter, os.path.join(output_dir, 'inter.json'), indent=4)
[docs] def make_input_file(self,
output_dir,
task_type,
task_param):
sepline(ch=output_dir)
dumpfn(task_param, os.path.join(output_dir, 'task.json'), indent=4)
assert (os.path.exists(self.incar)), 'no INCAR file for relaxation'
relax_incar_path = os.path.abspath(self.incar)
incar_relax = incar_upper(Incar.from_file(relax_incar_path))
# deal with relaxation
cal_type = task_param['cal_type']
cal_setting = task_param['cal_setting']
# user input INCAR for property calculation
if 'input_prop' in cal_setting and os.path.isfile(cal_setting['input_prop']):
incar_prop = os.path.abspath(cal_setting['input_prop'])
incar = incar_upper(Incar.from_file(incar_prop))
# revise INCAR based on the INCAR provided in the "interaction"
else:
incar = incar_relax
if cal_type == 'relaxation':
relax_pos = cal_setting['relax_pos']
relax_shape = cal_setting['relax_shape']
relax_vol = cal_setting['relax_vol']
if [relax_pos, relax_shape, relax_vol] == [True, False, False]:
isif = 2
elif [relax_pos, relax_shape, relax_vol] == [True, True, True]:
isif = 3
elif [relax_pos, relax_shape, relax_vol] == [True, True, False]:
isif = 4
elif [relax_pos, relax_shape, relax_vol] == [False, True, False]:
isif = 5
elif [relax_pos, relax_shape, relax_vol] == [False, True, True]:
isif = 6
elif [relax_pos, relax_shape, relax_vol] == [False, False, True]:
isif = 7
elif [relax_pos, relax_shape, relax_vol] == [False, False, False]:
nsw = 0
isif = 2
if not ('NSW' in incar and incar.get('NSW') == nsw):
dlog.info("%s setting NSW to %d" % (self.make_input_file.__name__, nsw))
incar['NSW'] = nsw
else:
raise RuntimeError("not supported calculation setting for VASP")
if not ('ISIF' in incar and incar.get('ISIF') == isif):
dlog.info("%s setting ISIF to %d" % (self.make_input_file.__name__, isif))
incar['ISIF'] = isif
elif cal_type == 'static':
nsw = 0
if not ('NSW' in incar and incar.get('NSW') == nsw):
dlog.info("%s setting NSW to %d" % (self.make_input_file.__name__, nsw))
incar['NSW'] = nsw
else:
raise RuntimeError("not supported calculation type for VASP")
if 'ediff' in cal_setting:
dlog.info("%s setting EDIFF to %s" % (self.make_input_file.__name__, cal_setting['ediff']))
incar['EDIFF'] = cal_setting['ediff']
if 'ediffg' in cal_setting:
dlog.info("%s setting EDIFFG to %s" % (self.make_input_file.__name__, cal_setting['ediffg']))
incar['EDIFFG'] = cal_setting['ediffg']
if 'encut' in cal_setting:
dlog.info("%s setting ENCUT to %s" % (self.make_input_file.__name__, cal_setting['encut']))
incar['ENCUT'] = cal_setting['encut']
if 'kspacing' in cal_setting:
dlog.info("%s setting KSPACING to %s" % (self.make_input_file.__name__, cal_setting['kspacing']))
incar['KSPACING'] = cal_setting['kspacing']
if 'kgamma' in cal_setting:
dlog.info("%s setting KGAMMA to %s" % (self.make_input_file.__name__, cal_setting['kgamma']))
incar['KGAMMA'] = cal_setting['kgamma']
try:
kspacing = incar.get('KSPACING')
except KeyError:
raise RuntimeError("KSPACING must be given in INCAR")
if 'KGAMMA' in incar:
kgamma = incar.get('KGAMMA')
else:
kgamma = False
incar.write_file(os.path.join(output_dir, '../INCAR'))
cwd = os.getcwd()
os.chdir(output_dir)
if not os.path.islink('INCAR'):
os.symlink('../INCAR', 'INCAR')
elif not '../INCAR' == os.readlink('INCAR'):
os.remove('INCAR')
os.symlink('../INCAR', 'INCAR')
os.chdir(cwd)
ret = vasp.make_kspacing_kpoints(self.path_to_poscar, kspacing, kgamma)
kp = Kpoints.from_string(ret)
kp.write_file(os.path.join(output_dir, "KPOINTS"))
[docs] def compute(self,
output_dir):
outcar = os.path.join(output_dir, 'OUTCAR')
if not os.path.isfile(outcar):
dlog.warning("cannot find OUTCAR in " + output_dir + " skip")
return None
else:
ls = LabeledSystem(outcar)
stress = []
with open(outcar, 'r') as fin:
lines = fin.read().split('\n')
for line in lines:
if 'in kB' in line:
stress_xx = float(line.split()[2])
stress_yy = float(line.split()[3])
stress_zz = float(line.split()[4])
stress_xy = float(line.split()[5])
stress_yz = float(line.split()[6])
stress_zx = float(line.split()[7])
stress.append([])
stress[-1].append([stress_xx, stress_xy, stress_zx])
stress[-1].append([stress_xy, stress_yy, stress_yz])
stress[-1].append([stress_zx, stress_yz, stress_zz])
outcar_dict = ls.as_dict()
outcar_dict['data']['stress'] = {"@module": "numpy", "@class": "array", "dtype": "float64", "data": stress}
return outcar_dict
[docs] def forward_files(self, property_type='relaxation'):
return ['INCAR', 'POSCAR', 'KPOINTS', 'POTCAR']
[docs] def forward_common_files(self, property_type='relaxation'):
potcar_not_link_list = ['vacancy', 'interstitial']
if property_type == 'elastic':
return ['INCAR', 'KPOINTS', 'POTCAR']
elif property_type in potcar_not_link_list:
return ['INCAR']
else:
return ['INCAR', 'POTCAR']
[docs] def backward_files(self, property_type='relaxation'):
return ['OUTCAR', 'outlog', 'CONTCAR', 'OSZICAR', 'XDATCAR']