Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abacus: update the read of stress and force for ABACUS v3.4.1 #560

Merged
merged 3 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions dpdata/abacus/relax.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

import numpy as np

from .scf import bohr2ang, get_cell, get_coords, get_geometry_in, kbar2evperang3
from .scf import (
bohr2ang,
collect_force,
collect_stress,
get_cell,
get_coords,
get_geometry_in,
kbar2evperang3,
)

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

Expand Down Expand Up @@ -40,8 +48,6 @@ def get_coords_from_log(loglines, natoms):
energy = []
cells = []
coords = []
force = []
stress = []
coord_direct = [] # if the coordinate is direct type or not

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

elif line[4:15] == "TOTAL-FORCE":
force.append([])
for j in range(5, 5 + natoms):
force[-1].append(
list(map(lambda x: float(x), loglines[i + j].split()[1:4]))
)
elif line[1:13] == "TOTAL-STRESS":
stress.append([])
for j in range(4, 7):
stress[-1].append(
list(map(lambda x: float(x), loglines[i + j].split()[0:3]))
)
force = collect_force(loglines)
stress = collect_stress(loglines)

# delete last structures which has no energy
while len(energy) < len(coords):
Expand Down
84 changes: 65 additions & 19 deletions dpdata/abacus/scf.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,33 +123,79 @@
return Etot, False


def get_force(outlines, natoms):
def collect_force(outlines):
force = []
force_inlines = get_block(
outlines, "TOTAL-FORCE (eV/Angstrom)", skip=4, nlines=np.sum(natoms)
)
if force_inlines is None:
print(
"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."
)
for i, line in enumerate(outlines):
if "TOTAL-FORCE (eV/Angstrom)" in line:
value_pattern = re.compile(
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*$"
)
j = i
# find the first line of force
noforce = False
while not value_pattern.match(outlines[j]):
j += 1
if (
j >= i + 10
): # if can not find the first line of force in 10 lines, then stop
print("Warning: can not find the first line of force")
noforce = True
break

Check warning on line 143 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L141-L143

Added lines #L141 - L143 were not covered by tests
if noforce:
break

Check warning on line 145 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L145

Added line #L145 was not covered by tests

force.append([])
while value_pattern.match(outlines[j]):
force[-1].append([float(ii) for ii in outlines[j].split()[1:4]])
j += 1
return force # only return the last force


def get_force(outlines, natoms):
force = collect_force(outlines)
if len(force) == 0:
return [[]]
for line in force_inlines:
force.append([float(f) for f in line.split()[1:4]])
force = np.array(force)
return force
else:
return np.array(force[-1]) # only return the last force


def get_stress(outlines):
def collect_stress(outlines):
stress = []
stress_inlines = get_block(outlines, "TOTAL-STRESS (KBAR)", skip=3, nlines=3)
if stress_inlines is None:
return None
for line in stress_inlines:
stress.append([float(f) for f in line.split()])
stress = np.array(stress) * kbar2evperang3
for i, line in enumerate(outlines):
if "TOTAL-STRESS (KBAR)" in line:
value_pattern = re.compile(
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*$"
)
j = i
nostress = False
while not value_pattern.match(outlines[j]):
j += 1
if (
j >= i + 10
): # if can not find the first line of stress in 10 lines, then stop
print("Warning: can not find the first line of stress")
njzjz marked this conversation as resolved.
Show resolved Hide resolved
nostress = True
break

Check warning on line 178 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L176-L178

Added lines #L176 - L178 were not covered by tests
if nostress:
break

Check warning on line 180 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L180

Added line #L180 was not covered by tests

stress.append([])
while value_pattern.match(outlines[j]):
stress[-1].append(
list(map(lambda x: float(x), outlines[j].split()[0:3]))
)
j += 1
return stress


def get_stress(outlines):
stress = collect_stress(outlines)
if len(stress) == 0:
return None

Check warning on line 194 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L194

Added line #L194 was not covered by tests
else:
return np.array(stress[-1]) * kbar2evperang3 # only return the last stress


def get_frame(fname):
data = {
"atom_names": [],
Expand Down
Loading
Loading