File size: 4,881 Bytes
fd35ee7 59bbad9 fd35ee7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | from pathlib import Path
import numpy as np
import pytest
from induced_exchange import (
VectorMappingError,
infer_target_site,
map_exchange_file,
map_exchange_vector,
prepare_positions,
read_jfile,
)
def test_maptypes_2_and_3_agree_for_a_basis_inside_the_first_cell():
positions = [(1, "Fe", 0.0, 0.0, 0.0)]
prepared = prepare_positions(positions, np.eye(3))
map2 = map_exchange_vector(1, 1, [1, 0, 0], positions=prepared, maptype=2)
map3 = map_exchange_vector(1, 1, [1, 0, 0], positions=prepared, maptype=3)
assert np.allclose(map2, [1, 0, 0])
assert np.allclose(map2, map3)
def test_maptypes_2_and_3_differ_for_an_out_of_cell_basis_position(tmp_path: Path):
positions = [(1, "Fe", -0.25, 0.0, 0.0), (2, "Pt", 0.25, 0.0, 0.0)]
jfile = tmp_path / "jfile"
jfile.write_text("1 2 0 0 0 4\n", encoding="utf-8")
prepared = prepare_positions(positions, np.eye(3))
map2 = map_exchange_file(jfile, positions=prepared, maptype=2)
map3 = map_exchange_file(jfile, positions=prepared, maptype=3)
assert np.allclose(map2[0].rij_cart, [-0.5, 0, 0])
assert np.allclose(map3[0].rij_cart, [0.5, 0, 0])
assert map2[0].inferred_target_cell_offset == (0, 0, 0)
assert map3[0].inferred_target_cell_offset == (1, 0, 0)
def test_direct_coordinate_positions_are_converted_before_folding():
cell = np.diag([2.0, 3.0, 4.0])
prepared = prepare_positions([(1, 1, 0.5, 0.5, 0.5)], cell, posfiletype="D")
assert np.allclose(prepared.positions_raw[1], [1.0, 1.5, 2.0])
assert np.allclose(prepared.positions_folded[1], [1.0, 1.5, 2.0])
def test_cartesian_coordinate_positions_are_preserved():
position = [0.25, 0.5, 0.75]
prepared = prepare_positions([(1, 1, *position)], np.diag([2.0, 3.0, 4.0]), posfiletype="C")
assert np.allclose(prepared.positions_raw[1], position)
assert np.allclose(prepared.positions_folded[1], position)
def test_maptype_1_uses_cartesian_bond_vectors_without_basis_difference():
prepared = prepare_positions([(1, 1, 0.0, 0.0, 0.0), (2, 2, 0.25, 0.0, 0.0)], np.eye(3))
result = map_exchange_vector(1, 2, [0.75, 0, 0], positions=prepared, maptype=1, posfiletype="C")
assert np.allclose(result, [0.75, 0, 0])
def test_duplicate_cartesian_vectors_use_the_last_jij(tmp_path: Path):
jfile = tmp_path / "jfile"
jfile.write_text("1 1 1 0 0 1\n1 1 1 0 0 2\n", encoding="utf-8")
records = map_exchange_file(
jfile,
positions=[(1, "Fe", 0.0, 0.0, 0.0)],
cell=np.eye(3),
maptype=1,
)
assert len(records) == 1
assert records[0].Jij == 2.0
def test_jfile_reader_ignores_trailing_columns_and_text(tmp_path: Path):
jfile = tmp_path / "jfile"
jfile.write_text("1 1 1 0 0 2 trailing columns and text\n", encoding="utf-8")
parsed = read_jfile(jfile)
mapped = map_exchange_file(
jfile,
positions=[(1, "Fe", 0.0, 0.0, 0.0)],
cell=np.eye(3),
maptype=1,
)
assert len(parsed) == 1
assert parsed[0].Jij == 2.0
assert mapped[0].Jij == 2.0
assert mapped[0].supplied_distance is None
def test_periodic_offsets_are_reduced_and_free_offsets_are_rejected(tmp_path: Path):
jfile = tmp_path / "jfile"
jfile.write_text("1 1 2 0 0 1\n", encoding="utf-8")
positions = [(1, 1, 0.0, 0.0, 0.0)]
periodic = map_exchange_file(jfile, positions=positions, cell=np.eye(3), maptype=2, ncell=(2, 2, 2), bc=("P", "P", "P"))
assert periodic[0].inferred_target_cell_offset == (0, 0, 0)
with pytest.raises(VectorMappingError, match="outside the non-periodic supercell"):
map_exchange_file(jfile, positions=positions, cell=np.eye(3), maptype=2, ncell=(2, 2, 2), bc=("F", "F", "F"))
def test_random_alloy_rows_retain_metadata_but_use_basis_atom_types(tmp_path: Path):
jfile = tmp_path / "jfile"
jfile.write_text("1 1 Fe Pt 1 0 0 3\n", encoding="utf-8")
parsed = read_jfile(jfile)
mapped = map_exchange_file(
jfile,
positions=[(1, "basis-Fe", 0.0, 0.0, 0.0)],
cell=np.eye(3),
maptype=1,
)
assert parsed[0].chemical_i == "Fe"
assert parsed[0].chemical_j == "Pt"
assert mapped[0].atom_type_i == "basis-Fe"
assert mapped[0].atom_type_j == "basis-Fe"
def test_vector_mapping_reports_invalid_maptype_missing_site_and_unmatched_target():
prepared = prepare_positions([(1, 1, 0.0, 0.0, 0.0)], np.eye(3))
with pytest.raises(VectorMappingError, match="maptype must be 1, 2, or 3"):
map_exchange_vector(1, 1, [0, 0, 0], positions=prepared, maptype=4)
with pytest.raises(VectorMappingError, match="missing from positions"):
map_exchange_vector(1, 2, [0, 0, 0], positions=prepared, maptype=1)
with pytest.raises(VectorMappingError, match="does not match a basis site"):
infer_target_site([0.25, 0.0, 0.0], prepared)
|