Skip to content

Commit 0b6bf2f

Browse files
support to read coord/cell from STRU_ION*_D in abacus/relax (#957)
fix #951 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced ABACUS relaxation structure parsing with improved coordinate and lattice vector unit conversion during parsing. * Added fallback logic to recover missing structure data from alternate sources in relaxation workflows. * **Tests** * Added comprehensive test coverage for relaxation data reading scenarios. * **Chores** * Updated dependency management with Python version-gated requirements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: root <pxlxingliang> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 80abfc5 commit 0b6bf2f

File tree

15 files changed

+1665
-9
lines changed

15 files changed

+1665
-9
lines changed

dpdata/abacus/relax.py

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import glob
34
import os
45

56
import numpy as np
@@ -31,7 +32,22 @@ def get_log_file(fname, inlines):
3132
return logf
3233

3334

34-
def get_coords_from_log(loglines, natoms):
35+
def get_relax_stru_files(output_dir):
36+
"""Find the STRU files in the output directory.
37+
38+
Args:
39+
output_dir (str): output directory
40+
41+
Returns
42+
-------
43+
strus: list of STRU files
44+
example:
45+
["STRU_ION1_D", "STRU_ION2_D"]
46+
"""
47+
return glob.glob(os.path.join(output_dir, "STRU_ION*_D"))
48+
49+
50+
def get_coords_from_log(loglines, natoms, stru_files=None):
3551
"""NOTICE: unit of coords and cells is Angstrom
3652
order:
3753
coordinate
@@ -72,7 +88,12 @@ def get_coords_from_log(loglines, natoms):
7288
coord_direct.append(False)
7389
for k in range(2, 2 + natoms):
7490
coords[-1].append(
75-
list(map(lambda x: float(x) * a0, loglines[i + k].split()[1:4]))
91+
list(
92+
map(
93+
lambda x: float(x) * a0 * bohr2ang,
94+
loglines[i + k].split()[1:4],
95+
)
96+
)
7697
)
7798
else:
7899
assert False, "Unrecongnized coordinate type, %s, line:%d" % ( # noqa: UP031
@@ -91,7 +112,12 @@ def get_coords_from_log(loglines, natoms):
91112
cells.append([])
92113
for k in range(1, 4):
93114
cells[-1].append(
94-
list(map(lambda x: float(x) * a0, loglines[i + k].split()[0:3]))
115+
list(
116+
map(
117+
lambda x: float(x) * a0 * bohr2ang,
118+
loglines[i + k].split()[0:3],
119+
)
120+
)
95121
)
96122

97123
elif line[1:14] == "final etot is" or "#TOTAL ENERGY#" in line:
@@ -101,6 +127,27 @@ def get_coords_from_log(loglines, natoms):
101127
# get the energy of current structure
102128
energy.append(float(line.split()[-2]))
103129

130+
# in some relax method (like: bfgs_trad), the coordinate is not outputed in running_relax.log
131+
# but if out_stru is true, then STRU_ION*_D will be outputed in OUT.ABACUS
132+
# we should read cell and coord from STRU_ION*_D files
133+
if len(energy) > 1 and len(coords) == 1:
134+
# the energies of all structrues are collected, but coords have only the first structure
135+
if (
136+
stru_files is not None and len(stru_files) > 1
137+
): # if stru_files are not only STRU_ION_D
138+
stru_file_name = [os.path.basename(i) for i in stru_files]
139+
coords = coords[:1] + [np.nan for i in range(len(energy) - 1)]
140+
coord_direct = coord_direct[:1] + [False for i in range(len(energy) - 1)]
141+
cells = cells[:1] + [np.nan for i in range(len(energy) - 1)]
142+
for iframe in range(1, len(energy)):
143+
if f"STRU_ION{iframe}_D" in stru_file_name:
144+
# read the structure from STRU_ION*_D
145+
stru_data = get_frame_from_stru(
146+
stru_files[stru_file_name.index(f"STRU_ION{iframe}_D")]
147+
)
148+
coords[iframe] = stru_data["coords"][0]
149+
cells[iframe] = stru_data["cells"][0]
150+
104151
force = collect_force(loglines)
105152
stress = collect_stress(loglines)
106153

@@ -133,7 +180,11 @@ def get_coords_from_log(loglines, natoms):
133180

134181
# delete structures whose energy is np.nan
135182
for i in range(minl):
136-
if np.isnan(energy[i - minl]):
183+
if (
184+
np.isnan(energy[i - minl])
185+
or np.any(np.isnan(coords[i - minl]))
186+
or np.any(np.isnan(cells[i - minl]))
187+
):
137188
del energy[i - minl]
138189
del coords[i - minl]
139190
del cells[i - minl]
@@ -154,10 +205,6 @@ def get_coords_from_log(loglines, natoms):
154205
if coord_direct[i]:
155206
coords[i] = coords[i].dot(cells[i])
156207

157-
# transfer bohrium to angstrom
158-
cells *= bohr2ang
159-
coords *= bohr2ang
160-
161208
if len(stress) > 0:
162209
virial = np.zeros([len(cells), 3, 3])
163210
for i in range(len(cells)):
@@ -191,7 +238,11 @@ def get_frame(fname):
191238
with open_file(logf) as f1:
192239
lines = f1.readlines()
193240

194-
energy, cells, coords, force, stress, virial = get_coords_from_log(lines, natoms)
241+
relax_stru_files = get_relax_stru_files(os.path.dirname(logf))
242+
243+
energy, cells, coords, force, stress, virial = get_coords_from_log(
244+
lines, natoms, stru_files=relax_stru_files
245+
)
195246

196247
magmom, magforce = get_mag_force(lines)
197248

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
INPUT_PARAMETERS RUNNING ABACUS-DFT
2+
3+
#Parameters (1.General)
4+
suffix ABACUS # suffix of OUTPUT DIR
5+
nspin 1 # 1/2/4
6+
symmetry 0 # 0/1
7+
esolver_type ksdft # ksdft/ofdft/sdft/tddft/lj/dp
8+
dft_functional pbe # lda/pbe/scan/hf/pbe0/hse/libxc
9+
ks_solver genelpa # genelpa/scalapack_avx for lcao, cg/dav for pw
10+
vdw_method none # d3/d3_bj/none
11+
12+
#Parameters (2.Iteration)
13+
calculation cell-relax # scf/relax/cell-relax/md
14+
ecutwfc 100 # Rydberg, in lcao is for grid density
15+
scf_thr 1e-7 # Rydberg
16+
scf_nmax 100
17+
#printe 300 # default eq scf_nmax
18+
relax_nmax 3
19+
relax_method bfgs_trad # cg/bfgs/bfgs_trad/sd/"fire"
20+
force_thr_ev 0.05
21+
# stress_thr 1 # GPa
22+
23+
#Parameters (3.Basis)
24+
basis_type lcao # lcao or pw
25+
# kspacing 0.14 0.50 0.14 # replace KPT
26+
gamma_only 1 # 0/1, replace KPT
27+
28+
#Parameters (4.Smearing)
29+
smearing_method mp # mp/gauss/fixed/mp-n/fd
30+
smearing_sigma 0.008 # Rydberg
31+
32+
#Parameters (5.Mixing)
33+
mixing_type broyden # pulay/broyden
34+
mixing_ndim 20
35+
#mixing_beta 0.4 # use default
36+
#mixing_gg0 1.0 # use default
37+
38+
#Parameters (6.Calculation)
39+
cal_force 1
40+
cal_stress 1
41+
#init_chg atomic # atomic/auto/file
42+
#init_wfc atomic # atomic/file
43+
out_stru 1 # print STRU in OUT
44+
out_chg -1 # -1 no, 0 binary, 1 cube, more number as cube prec
45+
out_bandgap 1
46+
out_mul 1 # print charge and mag of atom in mulliken.txt
47+
# out_wfc_lcao 0 # 0 no, 1 txt, 2 dat
48+
49+
50+
# #Parameters (7. Dipole Correction)
51+
# efield_flag 1 # open added potential, if 0, all below useless
52+
# dip_cor_flag 1 # open dipole correction
53+
# efield_dir 1 # direction of dipole correction, 0,1,2 for x,y,z
54+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ATOMIC_SPECIES
2+
Ga 69.7230 Ga.upf upf201
3+
As 74.9216 As.PD04.PBE.UPF upf201
4+
5+
NUMERICAL_ORBITAL
6+
Ga_gga_7au_100Ry_2s2p2d1f.orb
7+
As_gga_8au_100Ry_2s2p1d.orb
8+
9+
LATTICE_CONSTANT
10+
1.8897160000
11+
12+
LATTICE_VECTORS
13+
5.7532352224 -0.0000000000 0.0000000000
14+
-0.0000000000 5.7532352224 -0.0000000000
15+
0.0000000000 -0.0000000000 5.7532352224
16+
17+
ATOMIC_POSITIONS
18+
Direct
19+
20+
Ga #label
21+
0.0000 #magnetism
22+
4 #number of atoms
23+
1.0000000000 0.0000000000 1.0000000000 m 1 1 1
24+
1.0000000000 0.5000000000 0.5000000000 m 1 1 1
25+
0.5000000000 0.0000000000 0.5000000000 m 1 1 1
26+
0.5000000000 0.5000000000 1.0000000000 m 1 1 1
27+
28+
As #label
29+
0.0000 #magnetism
30+
4 #number of atoms
31+
0.2500000000 0.2500000000 0.2500000000 m 1 1 1
32+
0.2500000000 0.7500000000 0.7500000000 m 1 1 1
33+
0.7500000000 0.2500000000 0.7500000000 m 1 1 1
34+
0.7500000000 0.7500000000 0.2500000000 m 1 1 1
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ATOMIC_SPECIES
2+
Ga 69.7230 Ga.upf upf201
3+
As 74.9216 As.PD04.PBE.UPF upf201
4+
5+
NUMERICAL_ORBITAL
6+
Ga_gga_7au_100Ry_2s2p2d1f.orb
7+
As_gga_8au_100Ry_2s2p1d.orb
8+
9+
LATTICE_CONSTANT
10+
1.8897160000
11+
12+
LATTICE_VECTORS
13+
5.7532858910 -0.0000000000 0.0000000000
14+
-0.0000000000 5.7532858910 -0.0000000000
15+
0.0000000000 -0.0000000000 5.7532858910
16+
17+
ATOMIC_POSITIONS
18+
Direct
19+
20+
Ga #label
21+
0.0000 #magnetism
22+
4 #number of atoms
23+
0.0000000001 1.0000000000 0.0000000001 m 1 1 1
24+
0.0000000001 0.5000000000 0.5000000001 m 1 1 1
25+
0.5000000001 1.0000000000 0.5000000001 m 1 1 1
26+
0.5000000001 0.5000000000 0.0000000001 m 1 1 1
27+
28+
As #label
29+
0.0000 #magnetism
30+
4 #number of atoms
31+
0.2499999999 0.2500000000 0.2499999999 m 1 1 1
32+
0.2499999999 0.7500000000 0.7499999999 m 1 1 1
33+
0.7499999999 0.2500000000 0.7499999999 m 1 1 1
34+
0.7499999999 0.7500000000 0.2499999999 m 1 1 1
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ATOMIC_SPECIES
2+
Ga 69.7230 Ga.upf upf201
3+
As 74.9216 As.PD04.PBE.UPF upf201
4+
5+
NUMERICAL_ORBITAL
6+
Ga_gga_7au_100Ry_2s2p2d1f.orb
7+
As_gga_8au_100Ry_2s2p1d.orb
8+
9+
LATTICE_CONSTANT
10+
1.8897160000
11+
12+
LATTICE_VECTORS
13+
5.7532858910 -0.0000000000 0.0000000000
14+
-0.0000000000 5.7532858910 -0.0000000000
15+
0.0000000000 -0.0000000000 5.7532858910
16+
17+
ATOMIC_POSITIONS
18+
Direct
19+
20+
Ga #label
21+
0.0000 #magnetism
22+
4 #number of atoms
23+
0.0000000001 1.0000000000 0.0000000001 m 1 1 1
24+
0.0000000001 0.5000000000 0.5000000001 m 1 1 1
25+
0.5000000001 1.0000000000 0.5000000001 m 1 1 1
26+
0.5000000001 0.5000000000 0.0000000001 m 1 1 1
27+
28+
As #label
29+
0.0000 #magnetism
30+
4 #number of atoms
31+
0.2499999999 0.2500000000 0.2499999999 m 1 1 1
32+
0.2499999999 0.7500000000 0.7499999999 m 1 1 1
33+
0.7499999999 0.2500000000 0.7499999999 m 1 1 1
34+
0.7499999999 0.7500000000 0.2499999999 m 1 1 1
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ATOMIC_SPECIES
2+
Ga 69.7230 Ga.upf upf201
3+
As 74.9216 As.PD04.PBE.UPF upf201
4+
5+
NUMERICAL_ORBITAL
6+
Ga_gga_7au_100Ry_2s2p2d1f.orb
7+
As_gga_8au_100Ry_2s2p1d.orb
8+
9+
LATTICE_CONSTANT
10+
1.8897160000
11+
12+
LATTICE_VECTORS
13+
5.7532858910 -0.0000000000 0.0000000000
14+
-0.0000000000 5.7532858910 -0.0000000000
15+
0.0000000000 -0.0000000000 5.7532858910
16+
17+
ATOMIC_POSITIONS
18+
Direct
19+
20+
Ga #label
21+
0.0000 #magnetism
22+
4 #number of atoms
23+
0.0000000001 1.0000000000 0.0000000001 m 1 1 1
24+
0.0000000001 0.5000000000 0.5000000001 m 1 1 1
25+
0.5000000001 1.0000000000 0.5000000001 m 1 1 1
26+
0.5000000001 0.5000000000 0.0000000001 m 1 1 1
27+
28+
As #label
29+
0.0000 #magnetism
30+
4 #number of atoms
31+
0.2499999999 0.2500000000 0.2499999999 m 1 1 1
32+
0.2499999999 0.7500000000 0.7499999999 m 1 1 1
33+
0.7499999999 0.2500000000 0.7499999999 m 1 1 1
34+
0.7499999999 0.7500000000 0.2499999999 m 1 1 1

0 commit comments

Comments
 (0)