Skip to content
Open
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
12 changes: 12 additions & 0 deletions dpdata/formats/vasp/poscar.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ def move_flag_mapper(flag):
system["atom_names"] = [str(ii) for ii in lines[5].split()]
system["atom_numbs"] = [int(ii) for ii in lines[6].split()]
scale = float(lines[1])
# VASP interprets a negative scale as a target cell volume (in A^3), not
# as a negative vector multiplier. Convert it to a positive linear scale
# after reading the unscaled lattice vectors.
if scale < 0:
target_volume = abs(scale)
raw_cell = np.array(
[[float(jj) for jj in lines[ii].split()] for ii in range(2, 5)]
)
raw_volume = abs(np.linalg.det(raw_cell))
if raw_volume == 0:
raise ValueError("negative POSCAR scale requires a non-zero cell volume")
scale = (target_volume / raw_volume) ** (1.0 / 3.0)
cell = []
move_flags = []
for ii in range(2, 5):
Expand Down
51 changes: 51 additions & 0 deletions tests/test_vasp_poscar_to_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from context import dpdata
from poscars.poscar_ref_oh import TestPOSCARoh

from dpdata.formats.vasp.poscar import to_system_data


class TestPOSCARCart(unittest.TestCase, TestPOSCARoh):
def setUp(self):
Expand Down Expand Up @@ -89,5 +91,54 @@ def setUp(self):
self.v_places = 6


class TestVaspNegativeScale(unittest.TestCase):
def test_negative_scale_is_target_volume(self):
Comment thread
njzjz-bot marked this conversation as resolved.
lines = """test
-8
1 0 0
0 1 0
0 0 1
H
1
Direct
0.5 0.0 0.0
""".splitlines()
data = to_system_data(lines)
np.testing.assert_allclose(np.linalg.det(data["cells"][0]), 8.0)
np.testing.assert_allclose(data["coords"][0, 0], [1.0, 0.0, 0.0])

def test_negative_scale_rescales_cartesian_coordinates(self):
lines = """test
-8
1 0 0
0 1 0
0 0 1
H
1
Cartesian
0.25 0.5 0.75
""".splitlines()

data = to_system_data(lines)

np.testing.assert_allclose(np.linalg.det(data["cells"][0]), 8.0)
np.testing.assert_allclose(data["coords"][0, 0], [0.5, 1.0, 1.5])

def test_negative_scale_rejects_zero_volume_cell(self):
lines = """test
-8
1 0 0
0 0 0
0 0 1
H
1
Direct
0.5 0.0 0.0
""".splitlines()

with self.assertRaisesRegex(ValueError, "non-zero cell volume"):
to_system_data(lines)


if __name__ == "__main__":
unittest.main()
Loading