mirror of https://github.com/phonopy/phonopy.git
336 lines
11 KiB
Python
336 lines
11 KiB
Python
"""Pytest configuration."""
|
|
import os
|
|
from typing import Tuple
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import phonopy
|
|
from phonopy import Phonopy
|
|
from phonopy.structure.atoms import PhonopyAtoms
|
|
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_si() -> Phonopy:
|
|
"""Return Phonopy class instance of Si-prim 2x2x2."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_params_Si.yaml")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
is_compact_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
born_filename = os.path.join(current_dir, "BORN_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
born_filename=born_filename,
|
|
is_compact_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_nofcsym() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2 without symmetrizing fc2."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
born_filename = os.path.join(current_dir, "BORN_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
born_filename=born_filename,
|
|
symmetrize_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_compact_fcsym() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2 with compact fc2."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
born_filename = os.path.join(current_dir, "BORN_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
born_filename=born_filename,
|
|
is_compact_fc=True,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_nonac() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2 without NAC."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
is_nac=False,
|
|
is_compact_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_nonac_compact_fc() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2 without NAC with compact fc2."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
is_nac=False,
|
|
is_compact_fc=True,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_nonac_dense_svecs() -> Phonopy:
|
|
"""Return Phonopy class instance of NaCl 2x2x2 without NAC with dense svecs."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_NaCl.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_NaCl")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
is_nac=False,
|
|
is_compact_fc=True,
|
|
store_dense_svecs=True,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_sno2() -> Phonopy:
|
|
"""Return Phonopy class instance of rutile SnO2 2x2x3."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_SnO2.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_SnO2")
|
|
born_filename = os.path.join(current_dir, "BORN_SnO2")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
born_filename=born_filename,
|
|
is_compact_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_tio2() -> Phonopy:
|
|
"""Return Phonopy class instance of anataze TiO2 3x3x1."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_disp_TiO2.yaml")
|
|
force_sets_filename = os.path.join(current_dir, "FORCE_SETS_TiO2")
|
|
born_filename = os.path.join(current_dir, "BORN_TiO2")
|
|
return phonopy.load(
|
|
yaml_filename,
|
|
force_sets_filename=force_sets_filename,
|
|
born_filename=born_filename,
|
|
is_compact_fc=False,
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_zr3n4() -> Phonopy:
|
|
"""Return Phonopy class instance of anataze Zr3N4 1x1x1."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_params_Zr3N4.yaml")
|
|
return phonopy.load(
|
|
yaml_filename, is_compact_fc=False, log_level=1, produce_fc=True
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_tipn3() -> Phonopy:
|
|
"""Return Phonopy class instance of anataze TiPN3 4x2x1."""
|
|
yaml_filename = os.path.join(current_dir, "phonopy_params_TiPN3.yaml.xz")
|
|
return phonopy.load(
|
|
yaml_filename, is_compact_fc=False, log_level=1, produce_fc=True
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def ph_nacl_gruneisen() -> Tuple[Phonopy, Phonopy, Phonopy]:
|
|
"""Return Phonopy class instances of NaCl 2x2x2 at three volumes."""
|
|
ph0 = phonopy.load(
|
|
os.path.join(current_dir, "phonopy_params_NaCl-1.00.yaml.xz"),
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
ph_minus = phonopy.load(
|
|
os.path.join(current_dir, "phonopy_params_NaCl-0.995.yaml.xz"),
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
ph_plus = phonopy.load(
|
|
os.path.join(current_dir, "phonopy_params_NaCl-1.005.yaml.xz"),
|
|
log_level=1,
|
|
produce_fc=True,
|
|
)
|
|
return ph0, ph_minus, ph_plus
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def convcell_sio2() -> PhonopyAtoms:
|
|
"""Return PhonopyAtoms class instance of rutile SiO2."""
|
|
symbols = ["Si"] * 2 + ["O"] * 4
|
|
lattice = [[4.65, 0, 0], [0, 4.75, 0], [0, 0, 3.25]]
|
|
points = [
|
|
[0.0, 0.0, 0.0],
|
|
[0.5, 0.5, 0.5],
|
|
[0.3, 0.3, 0.0],
|
|
[0.7, 0.7, 0.0],
|
|
[0.2, 0.8, 0.5],
|
|
[0.8, 0.2, 0.5],
|
|
]
|
|
return PhonopyAtoms(cell=lattice, scaled_positions=points, symbols=symbols)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def primcell_si() -> PhonopyAtoms:
|
|
"""Return PhonopyAtoms class instance of primitive cell of Si."""
|
|
symbols = ["Si"] * 2
|
|
lattice = [[0, 2.73, 2.73], [2.73, 0, 2.73], [2.73, 2.73, 0]]
|
|
points = [[0.75, 0.75, 0.75], [0.5, 0.5, 0.5]]
|
|
return PhonopyAtoms(cell=lattice, scaled_positions=points, symbols=symbols)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def convcell_nacl() -> PhonopyAtoms:
|
|
"""Return PhonopyAtoms instance of conventional unit cell of NaCl."""
|
|
symbols = ["Na"] * 4 + ["Cl"] * 4
|
|
a = 5.6903014761756712
|
|
lattice = [[a, 0, 0], [0, a, 0], [0, 0, a]]
|
|
points = [
|
|
[0.0, 0.0, 0.0],
|
|
[0.0, 0.5, 0.5],
|
|
[0.5, 0.0, 0.5],
|
|
[0.5, 0.5, 0.0],
|
|
[0.5, 0.5, 0.5],
|
|
[0.5, 0.0, 0.0],
|
|
[0.0, 0.5, 0.0],
|
|
[0.0, 0.0, 0.5],
|
|
]
|
|
return PhonopyAtoms(cell=lattice, scaled_positions=points, symbols=symbols)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def primcell_nacl() -> PhonopyAtoms:
|
|
"""Return PhonopyAtoms class instance of primitive cell of NaCl."""
|
|
symbols = ["Na", "Cl"]
|
|
x = 5.6903014761756712 / 2
|
|
lattice = [[0, x, x], [x, 0, x], [x, x, 0]]
|
|
points = [[0, 0, 0], [0.5, 0.5, 0.5]]
|
|
return PhonopyAtoms(cell=lattice, scaled_positions=points, symbols=symbols)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def convcell_cr() -> PhonopyAtoms:
|
|
"""Return PhonopyAtoms class instance of primitive cell of Cr."""
|
|
symbols = ["Cr"] * 2
|
|
a = 2.812696943681890
|
|
lattice = [[a, 0, 0], [0, a, 0], [0, 0, a]]
|
|
points = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]
|
|
return PhonopyAtoms(cell=lattice, scaled_positions=points, symbols=symbols)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def helper_methods():
|
|
"""Return methods to compare cells."""
|
|
|
|
class HelperMethods:
|
|
@classmethod
|
|
def compare_cells_with_order(
|
|
cls, cell: PhonopyAtoms, cell_ref: PhonopyAtoms, symprec=1e-5
|
|
):
|
|
"""Compare two cells with the same orders of positions."""
|
|
np.testing.assert_allclose(cell.cell, cell_ref.cell, atol=symprec)
|
|
cls.compare_positions_with_order(
|
|
cell.scaled_positions, cell_ref.scaled_positions, cell.cell
|
|
)
|
|
np.testing.assert_array_equal(cell.numbers, cell_ref.numbers)
|
|
np.testing.assert_allclose(cell.masses, cell_ref.masses, atol=symprec)
|
|
if cell.magnetic_moments is None:
|
|
assert cell_ref.magnetic_moments is None
|
|
else:
|
|
np.testing.assert_allclose(
|
|
cell.magnetic_moments, cell_ref.magnetic_moments, atol=symprec
|
|
)
|
|
|
|
@classmethod
|
|
def compare_positions_with_order(cls, pos, pos_ref, lattice, symprec=1e-5):
|
|
"""Compare two lists of positions and orders.
|
|
|
|
lattice :
|
|
Basis vectors in row vectors.
|
|
|
|
"""
|
|
diff = pos - pos_ref
|
|
diff -= np.rint(diff)
|
|
dist = (np.dot(diff, lattice) ** 2).sum(axis=1)
|
|
assert (dist < symprec).all()
|
|
|
|
@classmethod
|
|
def compare_cells(
|
|
cls, cell: PhonopyAtoms, cell_ref: PhonopyAtoms, symprec=1e-5
|
|
):
|
|
"""Compare two cells where position orders can be different."""
|
|
np.testing.assert_allclose(cell.cell, cell_ref.cell, atol=symprec)
|
|
|
|
indices = cls.compare_positions_in_arbitrary_order(
|
|
cell.scaled_positions, cell_ref.scaled_positions, cell.cell
|
|
)
|
|
np.testing.assert_array_equal(cell.numbers, cell_ref.numbers[indices])
|
|
np.testing.assert_allclose(
|
|
cell.masses, cell_ref.masses[indices], atol=symprec
|
|
)
|
|
if cell.magnetic_moments is None:
|
|
assert cell_ref.magnetic_moments is None
|
|
else:
|
|
np.testing.assert_allclose(
|
|
cell.magnetic_moments,
|
|
cell_ref.magnetic_moments[indices],
|
|
atol=symprec,
|
|
)
|
|
|
|
@classmethod
|
|
def compare_positions_in_arbitrary_order(
|
|
cls, pos_in, pos_ref, lattice, symprec=1e-5
|
|
):
|
|
"""Compare two sets of positions irrespective of orders.
|
|
|
|
lattice :
|
|
Basis vectors in row vectors.
|
|
|
|
"""
|
|
indices = []
|
|
for pos in pos_in:
|
|
diff = pos_ref - pos
|
|
diff -= np.rint(diff)
|
|
dist = (np.dot(diff, lattice) ** 2).sum(axis=1)
|
|
matches = np.where(dist < symprec)[0]
|
|
assert len(matches) == 1
|
|
indices.append(matches[0])
|
|
return indices
|
|
|
|
return HelperMethods
|