Skip to content

Commit a937461

Browse files
abacus: update the read of stress and force for ABACUS v3.4.1 (#560)
Signed-off-by: Peng Xingliang <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7fb45d8 commit a937461

File tree

6 files changed

+1599
-34
lines changed

6 files changed

+1599
-34
lines changed

dpdata/abacus/relax.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22

33
import numpy as np
44

5-
from .scf import bohr2ang, get_cell, get_coords, get_geometry_in, kbar2evperang3
5+
from .scf import (
6+
bohr2ang,
7+
collect_force,
8+
collect_stress,
9+
get_cell,
10+
get_coords,
11+
get_geometry_in,
12+
kbar2evperang3,
13+
)
614

715
# Read in geometries from an ABACUS RELAX(CELL-RELAX) trajectory in OUT.XXXX/runnning_relax/cell-relax.log.
816

@@ -40,8 +48,6 @@ def get_coords_from_log(loglines, natoms):
4048
energy = []
4149
cells = []
4250
coords = []
43-
force = []
44-
stress = []
4551
coord_direct = [] # if the coordinate is direct type or not
4652

4753
for i in range(len(loglines)):
@@ -91,18 +97,8 @@ def get_coords_from_log(loglines, natoms):
9197
# get the energy of current structure
9298
energy.append(float(line.split()[-2]))
9399

94-
elif line[4:15] == "TOTAL-FORCE":
95-
force.append([])
96-
for j in range(5, 5 + natoms):
97-
force[-1].append(
98-
list(map(lambda x: float(x), loglines[i + j].split()[1:4]))
99-
)
100-
elif line[1:13] == "TOTAL-STRESS":
101-
stress.append([])
102-
for j in range(4, 7):
103-
stress[-1].append(
104-
list(map(lambda x: float(x), loglines[i + j].split()[0:3]))
105-
)
100+
force = collect_force(loglines)
101+
stress = collect_stress(loglines)
106102

107103
# delete last structures which has no energy
108104
while len(energy) < len(coords):

dpdata/abacus/scf.py

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import re
3+
import warnings
34

45
import numpy as np
56

@@ -123,33 +124,79 @@ def get_energy(outlines):
123124
return Etot, False
124125

125126

126-
def get_force(outlines, natoms):
127+
def collect_force(outlines):
127128
force = []
128-
force_inlines = get_block(
129-
outlines, "TOTAL-FORCE (eV/Angstrom)", skip=4, nlines=np.sum(natoms)
130-
)
131-
if force_inlines is None:
132-
print(
133-
"TOTAL-FORCE (eV/Angstrom) is not found in OUT.XXX/running_scf.log. May be you haven't set 'cal_force 1' in the INPUT."
134-
)
129+
for i, line in enumerate(outlines):
130+
if "TOTAL-FORCE (eV/Angstrom)" in line:
131+
value_pattern = re.compile(
132+
r"^\s*[A-Z][a-z]?[1-9][0-9]*\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$"
133+
)
134+
j = i
135+
# find the first line of force
136+
noforce = False
137+
while not value_pattern.match(outlines[j]):
138+
j += 1
139+
if (
140+
j >= i + 10
141+
): # if can not find the first line of force in 10 lines, then stop
142+
warnings.warn("Warning: can not find the first line of force")
143+
noforce = True
144+
break
145+
if noforce:
146+
break
147+
148+
force.append([])
149+
while value_pattern.match(outlines[j]):
150+
force[-1].append([float(ii) for ii in outlines[j].split()[1:4]])
151+
j += 1
152+
return force # only return the last force
153+
154+
155+
def get_force(outlines, natoms):
156+
force = collect_force(outlines)
157+
if len(force) == 0:
135158
return [[]]
136-
for line in force_inlines:
137-
force.append([float(f) for f in line.split()[1:4]])
138-
force = np.array(force)
139-
return force
159+
else:
160+
return np.array(force[-1]) # only return the last force
140161

141162

142-
def get_stress(outlines):
163+
def collect_stress(outlines):
143164
stress = []
144-
stress_inlines = get_block(outlines, "TOTAL-STRESS (KBAR)", skip=3, nlines=3)
145-
if stress_inlines is None:
146-
return None
147-
for line in stress_inlines:
148-
stress.append([float(f) for f in line.split()])
149-
stress = np.array(stress) * kbar2evperang3
165+
for i, line in enumerate(outlines):
166+
if "TOTAL-STRESS (KBAR)" in line:
167+
value_pattern = re.compile(
168+
r"^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$"
169+
)
170+
j = i
171+
nostress = False
172+
while not value_pattern.match(outlines[j]):
173+
j += 1
174+
if (
175+
j >= i + 10
176+
): # if can not find the first line of stress in 10 lines, then stop
177+
warnings.warn("Warning: can not find the first line of stress")
178+
nostress = True
179+
break
180+
if nostress:
181+
break
182+
183+
stress.append([])
184+
while value_pattern.match(outlines[j]):
185+
stress[-1].append(
186+
list(map(lambda x: float(x), outlines[j].split()[0:3]))
187+
)
188+
j += 1
150189
return stress
151190

152191

192+
def get_stress(outlines):
193+
stress = collect_stress(outlines)
194+
if len(stress) == 0:
195+
return None
196+
else:
197+
return np.array(stress[-1]) * kbar2evperang3 # only return the last stress
198+
199+
153200
def get_frame(fname):
154201
data = {
155202
"atom_names": [],

0 commit comments

Comments
 (0)