Skip to content

Commit ddbcaa9

Browse files
kevinwenminionkevinwenminion
andauthored
add bcc interstitial calculation and change some default parameters in lmp (#696)
* metal testing for alloys and pair_coeff compatible with the latest lammps * add bcc self interstitial calculations * bcc interstitial optimization and change some default parameters in lmp * fix lmp default parameters * bcc interstitial optimization * add bcc interstitial unittest Co-authored-by: kevinwenminion <tongqi_wen@qq.com>
1 parent 9e3b958 commit ddbcaa9

File tree

5 files changed

+248
-16
lines changed

5 files changed

+248
-16
lines changed

dpgen/auto_test/Interstitial.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,120 @@ def make_confs(self,
172172
dumpfn(self.supercell, 'supercell.json')
173173
os.chdir(cwd)
174174

175+
176+
if 'bcc_self' in self.parameter and self.parameter['bcc_self']:
177+
os.chdir(path_to_work)
178+
with open('POSCAR', 'r') as fin:
179+
fin.readline()
180+
scale = float(fin.readline().split()[0])
181+
latt_param = float(fin.readline().split()[0])
182+
latt_param *= scale
183+
184+
if not os.path.isfile('task.000000/POSCAR'):
185+
raise RuntimeError("need task.000000 structure as reference")
186+
187+
with open('task.000000/POSCAR', 'r') as fin:
188+
pos_line = fin.read().split('\n')
189+
190+
super_latt_param = float(pos_line[2].split()[0])
191+
192+
output_task1 = os.path.join(path_to_work, 'task.%06d' % (len(dss)))
193+
os.makedirs(output_task1, exist_ok=True)
194+
os.chdir(output_task1)
195+
task_list.append(output_task1)
196+
with open(insert_element_task, 'a+') as fout:
197+
print(self.insert_ele[0], file=fout)
198+
dumpfn(self.supercell, 'supercell.json')
199+
pos_line[-2] = '%.6f' % float(latt_param/4/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' 0.000000 ' + self.insert_ele[0]
200+
with open('POSCAR', 'w+') as fout:
201+
for ii in pos_line:
202+
print(ii, file=fout)
203+
print('gen bcc tetrahedral')
204+
os.chdir(cwd)
205+
206+
output_task2 = os.path.join(path_to_work, 'task.%06d' % (len(dss)+1))
207+
os.makedirs(output_task2, exist_ok=True)
208+
os.chdir(output_task2)
209+
task_list.append(output_task2)
210+
with open(insert_element_task, 'a+') as fout:
211+
print(self.insert_ele[0], file=fout)
212+
dumpfn(self.supercell, 'supercell.json')
213+
pos_line[-2] = '%.6f' % float(latt_param/2/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' 0.000000 ' + self.insert_ele[0]
214+
with open('POSCAR', 'w+') as fout:
215+
for ii in pos_line:
216+
print(ii, file=fout)
217+
print('gen bcc octahedral')
218+
os.chdir(cwd)
219+
220+
output_task3 = os.path.join(path_to_work, 'task.%06d' % (len(dss)+2))
221+
os.makedirs(output_task3, exist_ok=True)
222+
os.chdir(output_task3)
223+
task_list.append(output_task3)
224+
with open(insert_element_task, 'a+') as fout:
225+
print(self.insert_ele[0], file=fout)
226+
dumpfn(self.supercell, 'supercell.json')
227+
pos_line[-2] = '%.6f' % float(latt_param/4/super_latt_param) + ' ' + '%.6f' % float(latt_param/4/super_latt_param) + ' ' + '%.6f' % float(latt_param/4/super_latt_param) + ' ' + self.insert_ele[0]
228+
with open('POSCAR', 'w+') as fout:
229+
for ii in pos_line:
230+
print(ii, file=fout)
231+
print('gen bcc crowdion')
232+
os.chdir(cwd)
233+
234+
for idx, ii in enumerate(pos_line):
235+
ss = ii.split()
236+
if len(ss) > 3:
237+
if abs(latt_param/2/super_latt_param - float(ss[0])) < 1e-5 and abs(latt_param/2/super_latt_param - float(ss[1])) < 1e-5 and abs(latt_param/2/super_latt_param - float(ss[2])) < 1e-5:
238+
replace_label = idx
239+
240+
output_task4 = os.path.join(path_to_work, 'task.%06d' % (len(dss)+3))
241+
os.makedirs(output_task4, exist_ok=True)
242+
os.chdir(output_task4)
243+
task_list.append(output_task4)
244+
with open(insert_element_task, 'a+') as fout:
245+
print(self.insert_ele[0], file=fout)
246+
dumpfn(self.supercell, 'supercell.json')
247+
pos_line[-2] = '%.6f' % float(latt_param/3/super_latt_param) + ' ' + '%.6f' % float(latt_param/3/super_latt_param) + ' ' + '%.6f' % float(latt_param/3/super_latt_param) + ' ' + self.insert_ele[0]
248+
pos_line[replace_label] = '%.6f' % float(latt_param/3*2/super_latt_param) + ' ' + '%.6f' % float(latt_param/3*2/super_latt_param) + ' ' + '%.6f' % float(latt_param/3*2/super_latt_param) + ' ' + self.insert_ele[0]
249+
250+
with open('POSCAR', 'w+') as fout:
251+
for ii in pos_line:
252+
print(ii, file=fout)
253+
print('gen bcc <111> dumbbell')
254+
os.chdir(cwd)
255+
256+
output_task5 = os.path.join(path_to_work, 'task.%06d' % (len(dss)+4))
257+
os.makedirs(output_task5, exist_ok=True)
258+
os.chdir(output_task5)
259+
task_list.append(output_task5)
260+
with open(insert_element_task, 'a+') as fout:
261+
print(self.insert_ele[0], file=fout)
262+
dumpfn(self.supercell, 'supercell.json')
263+
pos_line[-2] = '%.6f' % float((latt_param+2.1/2**0.5)/2/super_latt_param) + ' ' + '%.6f' % float((latt_param-2.1/2**0.5)/2/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' ' + self.insert_ele[0]
264+
pos_line[replace_label] = '%.6f' % float((latt_param-2.1/2**0.5)/2/super_latt_param) + ' ' + '%.6f' % float((latt_param+2.1/2**0.5)/2/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' ' + self.insert_ele[0]
265+
266+
with open('POSCAR', 'w+') as fout:
267+
for ii in pos_line:
268+
print(ii, file=fout)
269+
print('gen bcc <110> dumbbell')
270+
os.chdir(cwd)
271+
272+
output_task6 = os.path.join(path_to_work, 'task.%06d' % (len(dss)+5))
273+
os.makedirs(output_task6, exist_ok=True)
274+
os.chdir(output_task6)
275+
task_list.append(output_task6)
276+
with open(insert_element_task, 'a+') as fout:
277+
print(self.insert_ele[0], file=fout)
278+
dumpfn(self.supercell, 'supercell.json')
279+
pos_line[-2] = '%.6f' % float(latt_param/2/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' ' + '%.6f' % float((latt_param-2.1)/2/super_latt_param) + ' ' + self.insert_ele[0]
280+
pos_line[replace_label] = '%.6f' % float(latt_param/2/super_latt_param) + ' ' + '%.6f' % float(latt_param/2/super_latt_param) + ' ' + '%.6f' % float((latt_param+2.1)/2/super_latt_param) + ' ' + self.insert_ele[0]
281+
282+
with open('POSCAR', 'w+') as fout:
283+
for ii in pos_line:
284+
print(ii, file=fout)
285+
print('gen bcc <100> dumbbell')
286+
os.chdir(cwd)
287+
288+
175289
return task_list
176290

177291
def post_process(self, task_list):

dpgen/auto_test/common_equi.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,34 @@ def make_equi(confs,
3939
# ...
4040
cwd = os.getcwd()
4141
# generate poscar for single element crystal
42-
if len(ele_list) == 1:
42+
if len(ele_list) == 1 or 'single' in inter_param:
43+
if 'single' in inter_param:
44+
element_label = int(inter_param['single'])
45+
else:
46+
element_label = 0
4347
for ii in conf_dirs:
4448
os.chdir(ii)
4549
crys_type = ii.split('/')[-1]
4650
dlog.debug('crys_type: %s' % crys_type)
4751
dlog.debug('pwd: %s' % os.getcwd())
4852
if crys_type == 'std-fcc':
4953
if not os.path.exists('POSCAR'):
50-
crys.fcc1(ele_list[0]).to('POSCAR', 'POSCAR')
54+
crys.fcc1(ele_list[element_label]).to('POSCAR', 'POSCAR')
5155
elif crys_type == 'std-hcp':
5256
if not os.path.exists('POSCAR'):
53-
crys.hcp(ele_list[0]).to('POSCAR', 'POSCAR')
57+
crys.hcp(ele_list[element_label]).to('POSCAR', 'POSCAR')
5458
elif crys_type == 'std-dhcp':
5559
if not os.path.exists('POSCAR'):
56-
crys.dhcp(ele_list[0]).to('POSCAR', 'POSCAR')
60+
crys.dhcp(ele_list[element_label]).to('POSCAR', 'POSCAR')
5761
elif crys_type == 'std-bcc':
5862
if not os.path.exists('POSCAR'):
59-
crys.bcc(ele_list[0]).to('POSCAR', 'POSCAR')
63+
crys.bcc(ele_list[element_label]).to('POSCAR', 'POSCAR')
6064
elif crys_type == 'std-diamond':
6165
if not os.path.exists('POSCAR'):
62-
crys.diamond(ele_list[0]).to('POSCAR', 'POSCAR')
66+
crys.diamond(ele_list[element_label]).to('POSCAR', 'POSCAR')
6367
elif crys_type == 'std-sc':
6468
if not os.path.exists('POSCAR'):
65-
crys.sc(ele_list[0]).to('POSCAR', 'POSCAR')
69+
crys.sc(ele_list[element_label]).to('POSCAR', 'POSCAR')
6670

6771
os.chdir(cwd)
6872
task_dirs = []

dpgen/auto_test/lib/lammps.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def inter_deepmd(param):
115115
ret += "%s out_freq 10 out_file model_devi.out\n" % model_list
116116
else:
117117
ret += models[0] + '\n'
118-
ret += "pair_coeff\n"
118+
ret += "pair_coeff * *\n"
119119
return ret
120120

121121

@@ -175,7 +175,7 @@ def make_lammps_eval(conf, type_map, interaction, param):
175175
ret += "clear\n"
176176
ret += "units metal\n"
177177
ret += "dimension 3\n"
178-
ret += "boundary p p p\n"
178+
ret += "boundary p p p\n"
179179
ret += "atom_style atomic\n"
180180
ret += "box tilt large\n"
181181
ret += "read_data %s\n" % conf
@@ -212,7 +212,7 @@ def make_lammps_eval(conf, type_map, interaction, param):
212212

213213

214214
def make_lammps_equi(conf, type_map, interaction, param,
215-
etol=1e-12, ftol=1e-6,
215+
etol=0, ftol=1e-10,
216216
maxiter=5000, maxeval=500000,
217217
change_box=True):
218218
type_map_list = element_list(type_map)
@@ -224,7 +224,7 @@ def make_lammps_equi(conf, type_map, interaction, param,
224224
ret += "clear\n"
225225
ret += "units metal\n"
226226
ret += "dimension 3\n"
227-
ret += "boundary p p p\n"
227+
ret += "boundary p p p\n"
228228
ret += "atom_style atomic\n"
229229
ret += "box tilt large\n"
230230
ret += "read_data %s\n" % conf
@@ -268,7 +268,7 @@ def make_lammps_equi(conf, type_map, interaction, param,
268268

269269

270270
def make_lammps_elastic(conf, type_map, interaction, param,
271-
etol=1e-12, ftol=1e-6,
271+
etol=0, ftol=1e-10,
272272
maxiter=5000, maxeval=500000):
273273
type_map_list = element_list(type_map)
274274

@@ -279,7 +279,7 @@ def make_lammps_elastic(conf, type_map, interaction, param,
279279
ret += "clear\n"
280280
ret += "units metal\n"
281281
ret += "dimension 3\n"
282-
ret += "boundary p p p\n"
282+
ret += "boundary p p p\n"
283283
ret += "atom_style atomic\n"
284284
ret += "box tilt large\n"
285285
ret += "read_data %s\n" % conf
@@ -314,7 +314,7 @@ def make_lammps_elastic(conf, type_map, interaction, param,
314314

315315
def make_lammps_press_relax(conf, type_map, scale2equi, interaction, param,
316316
B0=70, bp=0,
317-
etol=1e-12, ftol=1e-6,
317+
etol=0, ftol=1e-10,
318318
maxiter=5000, maxeval=500000):
319319
type_map_list = element_list(type_map)
320320

@@ -371,7 +371,7 @@ def make_lammps_press_relax(conf, type_map, scale2equi, interaction, param,
371371

372372

373373
def make_lammps_phonon(conf, masses, interaction, param,
374-
etol=1e-12, ftol=1e-6,
374+
etol=0, ftol=1e-10,
375375
maxiter=5000, maxeval=500000):
376376
"""
377377
make lammps input for elastic calculation
@@ -380,7 +380,7 @@ def make_lammps_phonon(conf, masses, interaction, param,
380380
ret += "clear\n"
381381
ret += "units metal\n"
382382
ret += "dimension 3\n"
383-
ret += "boundary p p p\n"
383+
ret += "boundary p p p\n"
384384
ret += "atom_style atomic\n"
385385
ret += "box tilt large\n"
386386
ret += "read_data %s\n" % conf
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
V2
2+
1.0000000000000000
3+
2.9975462819866885 0.0000000000000000 0.0000000000000000
4+
0.0000000000000000 2.9975462819866885 0.0000000000000000
5+
0.0000000000000000 0.0000000000000000 2.9975462819866885
6+
V
7+
2
8+
Direct
9+
0.0000000000000000 0.0000000000000000 0.0000000000000000
10+
0.5000000000000000 0.5000000000000000 0.5000000000000000
11+
12+
0.00000000E+00 0.00000000E+00 0.00000000E+00
13+
0.00000000E+00 0.00000000E+00 0.00000000E+00
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import os, sys, json, glob, shutil
2+
import dpdata
3+
import numpy as np
4+
import unittest
5+
import dpdata
6+
from monty.serialization import loadfn, dumpfn
7+
from pymatgen.core import Structure
8+
from pymatgen.io.vasp import Incar
9+
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
10+
from pymatgen.analysis.defects.core import Interstitial as pmg_Interstitial
11+
12+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
13+
__package__ = 'auto_test'
14+
15+
from .context import make_kspacing_kpoints
16+
from .context import setUpModule
17+
18+
from dpgen.auto_test.Interstitial import Interstitial
19+
20+
21+
class TestInterstitial(unittest.TestCase):
22+
23+
def setUp(self):
24+
_jdata = {
25+
"structures": ["confs/std-bcc"],
26+
"interaction": {
27+
"type": "vasp",
28+
"incar": "vasp_input/INCAR.rlx",
29+
"potcar_prefix": "vasp_input",
30+
"potcars": {"V": "POTCAR"}
31+
},
32+
"properties": [
33+
{
34+
"type": "interstitial",
35+
"supercell": [1, 1, 1],
36+
"insert_ele": ["V"],
37+
"bcc_self": True
38+
}
39+
]
40+
}
41+
42+
self.equi_path = 'confs/std-bcc/relaxation/relax_task'
43+
self.source_path = 'equi/vasp'
44+
self.target_path = 'confs/std-bcc/interstitial_00'
45+
if not os.path.exists(self.equi_path):
46+
os.makedirs(self.equi_path)
47+
if not os.path.exists(self.target_path):
48+
os.makedirs(self.target_path)
49+
50+
self.confs = _jdata["structures"]
51+
self.inter_param = _jdata["interaction"]
52+
self.prop_param = _jdata['properties']
53+
54+
self.interstitial = Interstitial(_jdata['properties'][0])
55+
56+
def tearDown(self):
57+
if os.path.exists(self.equi_path):
58+
shutil.rmtree(self.equi_path)
59+
if os.path.exists(self.target_path):
60+
shutil.rmtree(self.target_path)
61+
62+
def test_task_type(self):
63+
self.assertEqual('interstitial', self.interstitial.task_type())
64+
65+
def test_task_param(self):
66+
self.assertEqual(self.prop_param[0], self.interstitial.task_param())
67+
68+
def test_make_confs_bcc(self):
69+
if not os.path.exists(os.path.join(self.equi_path, 'CONTCAR')):
70+
with self.assertRaises(RuntimeError):
71+
self.interstitial.make_confs(self.target_path, self.equi_path)
72+
shutil.copy(os.path.join(self.source_path, 'CONTCAR_V_bcc'), os.path.join(self.equi_path, 'CONTCAR'))
73+
task_list = self.interstitial.make_confs(self.target_path, self.equi_path)
74+
dfm_dirs = glob.glob(os.path.join(self.target_path, 'task.*'))
75+
self.assertEqual(len(dfm_dirs), 7)
76+
77+
incar0 = Incar.from_file(os.path.join('vasp_input', 'INCAR.rlx'))
78+
incar0['ISIF'] = 3
79+
80+
self.assertEqual(os.path.realpath(os.path.join(self.equi_path, 'CONTCAR')),
81+
os.path.realpath(os.path.join(self.target_path, 'POSCAR')))
82+
ref_st = Structure.from_file(os.path.join(self.target_path, 'POSCAR'))
83+
dfm_dirs.sort()
84+
for ii in dfm_dirs[:4]:
85+
st_file = os.path.join(ii, 'POSCAR')
86+
self.assertTrue(os.path.isfile(st_file))
87+
st0 = Structure.from_file(st_file)
88+
inter_site = st0[-1]
89+
inter = pmg_Interstitial(ref_st, inter_site, charge=0.0)
90+
st1 = inter.generate_defect_structure(self.prop_param[0]['supercell'])
91+
self.assertEqual(st0, st1)
92+
93+
for ii in dfm_dirs[4:]:
94+
st_file = os.path.join(ii, 'POSCAR')
95+
self.assertTrue(os.path.isfile(st_file))
96+
st0 = Structure.from_file(st_file)
97+
inter_site1 = st0.pop(-1)
98+
inter_site2 = st0.pop(-1)
99+
center = (inter_site1.coords + inter_site2.coords) / 2
100+
self.assertTrue((center[0] - center[1]) < 1e-4)
101+
self.assertTrue((center[1] - center[2]) < 1e-4)

0 commit comments

Comments
 (0)