Source code for dpgen.auto_test.ABACUS
import os
from dpgen import dlog
from dpgen.util import sepline
import dpgen.auto_test.lib.abacus as abacus
import dpgen.generator.lib.abacus_scf as abacus_scf
from dpgen.auto_test.Task import Task
from dpdata import LabeledSystem
from monty.serialization import dumpfn
import numpy as np
[docs]class ABACUS(Task):
def __init__(self,
inter_parameter,
path_to_poscar):
self.inter = inter_parameter
self.inter_type = inter_parameter['type']
self.incar = inter_parameter.get('incar',{})
self.potcar_prefix = inter_parameter.get('potcar_prefix', '')
self.potcars = inter_parameter.get('potcars',None)
self.orbfile = inter_parameter.get('orb_files',None)
self.deepks = inter_parameter.get('deepks_desc',None)
self.path_to_poscar = path_to_poscar
self.if_define_orb_file = False if self.orbfile == None else True
[docs] def make_potential_files(self,
output_dir):
stru = os.path.abspath(os.path.join(output_dir, 'STRU'))
if not os.path.isfile(stru):
raise FileNotFoundError("No file %s" % stru)
stru_data = abacus_scf.get_abacus_STRU(stru)
atom_names = stru_data['atom_names']
orb_files = stru_data['orb_files']
pp_files = stru_data["pp_files"]
dpks_descriptor = stru_data['dpks_descriptor']
if os.path.islink(os.path.join(output_dir, 'STRU')):
stru_path,tmpf = os.path.split(os.readlink(os.path.join(output_dir, 'STRU')))
else:
stru_path = output_dir
if pp_files == None:
raise RuntimeError("No pseudopotential information in STRU file")
pp_dir = os.path.abspath(self.potcar_prefix)
cwd = os.getcwd()
os.chdir(output_dir)
if not os.path.isdir("./pp_orb"): os.mkdir("./pp_orb")
for i in range(len(atom_names)):
pp_orb_file = [[pp_files[i],self.potcars]]
if orb_files != None:
pp_orb_file.append([orb_files[i],self.orbfile])
elif self.orbfile != None:
assert(atom_names[i] in self.orbfile),"orb_file of %s is not defined" % atom_names[i]
pp_orb_file.append([self.orbfile[atom_names[i]],self.orbfile])
if dpks_descriptor != None:
pp_orb_file.append([dpks_descriptor[i],self.deepks])
elif self.deepks != None:
pp_orb_file.append([self.deepks,self.deepks])
for tmpf,tmpdict in pp_orb_file:
atom = atom_names[i]
if os.path.isfile(os.path.join(stru_path,tmpf)):
linked_file = os.path.join(stru_path,tmpf)
elif tmpdict != None and os.path.isfile(os.path.join(pp_dir,tmpdict[atom])):
linked_file = os.path.join(pp_dir,tmpdict[atom])
else:
raise RuntimeError("Can not find file %s" % tmpf.split('/')[-1])
target_file = os.path.join("./pp_orb/",tmpf.split('/')[-1])
if os.path.isfile(target_file):
os.remove(target_file)
os.symlink(linked_file, target_file)
os.chdir(cwd)
dumpfn(self.inter, os.path.join(output_dir, 'inter.json'), indent=4)
[docs] def modify_input(self,incar,x,y):
if x in incar and incar[x] != y:
dlog.info("setting %s to %s" % (x,y))
incar[x] = y
[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 INPUT file for relaxation'
relax_incar_path = os.path.abspath(self.incar)
incar_relax = abacus_scf.get_abacus_input_parameters(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 = abacus_scf.get_abacus_input_parameters(incar_prop)
dlog.info("Detected 'input_prop' in 'relaxation', use %s as INPUT, and ignore 'cal_setting'" % incar_prop)
# revise INCAR based on the INCAR provided in the "interaction"
else:
incar = incar_relax
for key in cal_setting:
if key in ['relax_pos','relax_shape','relax_vol','K_POINTS','']:continue
if key[0] == '_' : continue
if 'interaction' in key.lower():continue
incar[key.lower()] = cal_setting[key]
fix_atom = [False,False,False]
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]:
self.modify_input(incar,'calculation','relax')
elif [relax_pos, relax_shape, relax_vol] == [True, True, True]:
self.modify_input(incar,'calculation','cell-relax')
elif [relax_pos, relax_shape, relax_vol] == [True, True, False]:
self.modify_input(incar,'calculation','cell-relax')
self.modify_input(incar,'fixed_axes','volume')
elif [relax_pos, relax_shape, relax_vol] == [False, True, False]:
self.modify_input(incar,'calculation','cell-relax')
self.modify_input(incar,'fixed_axes','volume')
fix_atom = [True,True,True]
elif [relax_pos, relax_shape, relax_vol] == [False, True, True]:
self.modify_input(incar,'calculation','cell-relax')
fix_atom = [True,True,True]
elif [relax_pos, relax_shape, relax_vol] == [False, False, True]:
raise RuntimeError("relax volume but fix shape is not supported for ABACUS")
elif [relax_pos, relax_shape, relax_vol] == [False, False, False]:
self.modify_input(incar,'calculation','scf')
else:
raise RuntimeError("not supported calculation setting for ABACUS")
elif cal_type == 'static':
self.modify_input(incar,'calculation','scf')
else:
raise RuntimeError("not supported calculation type for ABACUS")
#modify STRU file base on the value of fix_atom
abacus.stru_fix_atom(os.path.join(output_dir, 'STRU'),fix_atom)
if 'basis_type' not in incar:
dlog.info("'basis_type' is not defined, set to be 'pw'!")
self.modify_input(incar,'basis_type','pw')
if 'ntype' not in incar:
raise RuntimeError("ntype is not defined in INPUT")
if 'lcao' in incar['basis_type'].lower() and not self.if_define_orb_file:
mess = "The basis_type is %s, but not define orbital file!!!" % incar['basis_type']
raise RuntimeError(mess)
abacus.write_input(os.path.join(output_dir, '../INPUT'),incar)
cwd = os.getcwd()
os.chdir(output_dir)
if not os.path.islink('INPUT'):
os.symlink('../INPUT', 'INPUT')
elif not '../INPUT' == os.readlink('INPUT'):
os.remove('INPUT')
os.symlink('../INPUT', 'INPUT')
os.chdir(cwd)
if 'kspacing' in incar:
kspacing = float(incar['kspacing'])
if os.path.isfile(os.path.join(output_dir, 'STRU')):
kpt = abacus.make_kspacing_kpt(os.path.join(output_dir, 'STRU'),kspacing)
kpt += [0,0,0]
else:
kpt = [1,1,1,0,0,0]
elif 'K_POINTS' in cal_setting:
kpt = cal_setting['K_POINTS']
else:
mess = "K point information is not defined\n"
mess += "You can set key word 'kspacing' (unit in 1/bohr) as a float value in INPUT\n"
mess += "or set key word 'K_POINTS' as a list in 'cal_setting', e.g. [1,2,3,0,0,0]\n"
raise RuntimeError(mess)
abacus.write_kpt(os.path.join(output_dir, 'KPT'),kpt)
[docs] def compute(self,
output_dir):
if not os.path.isfile(os.path.join(output_dir,'INPUT')):
dlog.warning("cannot find INPUT in " + output_dir + " skip")
return None
ls = LabeledSystem(output_dir,fmt='abacus/relax')
outcar_dict = ls.as_dict()
return outcar_dict
[docs] def forward_files(self, property_type='relaxation'):
return ['INPUT', 'STRU', 'KPT', 'pp_orb']