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 all 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
85 changes: 66 additions & 19 deletions dpdata/abacus/scf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import re
import warnings

import numpy as np

Expand Down Expand Up @@ -123,33 +124,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
warnings.warn("Warning: can not find the first line of force")
noforce = True
break

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

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L142-L144

Added lines #L142 - L144 were not covered by tests
if noforce:
break

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

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L146

Added line #L146 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
warnings.warn("Warning: can not find the first line of stress")
nostress = True
break

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

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L177-L179

Added lines #L177 - L179 were not covered by tests
if nostress:
break

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

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L181

Added line #L181 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 195 in dpdata/abacus/scf.py

View check run for this annotation

Codecov / codecov/patch

dpdata/abacus/scf.py#L195

Added line #L195 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