From a4cc1faf8140cc57fee12474866e427327be9783 Mon Sep 17 00:00:00 2001 From: Han Yang Date: Tue, 10 Sep 2024 13:30:42 +0000 Subject: [PATCH] copy tests --- tests/applications/test_phonon.py | 78 +++++++++++++++ tests/applications/test_relax.py | 160 ++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 tests/applications/test_phonon.py create mode 100644 tests/applications/test_relax.py diff --git a/tests/applications/test_phonon.py b/tests/applications/test_phonon.py new file mode 100644 index 0000000..146903e --- /dev/null +++ b/tests/applications/test_phonon.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +import unittest + +import numpy as np +from ase import Atoms +from ase.calculators.emt import EMT +from phonopy import Phonopy + +from mattersim.applications.phonon import PhononWorkflow + + +class PhononTestCase(unittest.TestCase): + def setUp(self): + # Create an example structure for testing + a = 1.786854996 + positions = [ + (1.78685500, 1.78685500, 1.78685500), + (2.68028249, 2.68028249, 2.68028249), + ] + cell = [(0, a, a), (a, 0, a), (a, a, 0)] + + self.atoms = Atoms("C2", positions=positions, cell=cell, pbc=True) + + # Create an conventional cell for testing + a2 = a * 2 + positions2 = [ + (0, 0, 0), + (0, a2 / 2, a2 / 2), + (a2 / 2, 0, a2 / 2), + (a2 / 2, a2 / 2, 0), + (a2 / 4, a2 / 4, a2 / 4), + (a2 / 4, 3 * a2 / 4, 3 * a2 / 4), + (3 * a2 / 4, a2 / 4, 3 * a2 / 4), + (3 * a2 / 4, 3 * a2 / 4, a2 / 4), + ] + + cell2 = [(a2, 0, 0), (0, a2, 0), (0, 0, a2)] + + self.atoms_conv = Atoms("C8", positions=positions2, cell=cell2, pbc=True) + + self.calculator = EMT() + self.atoms.calc = self.calculator + self.atoms_conv.calc = self.calculator + + def test_phonon(self): + phononworkflow = PhononWorkflow(self.atoms, work_dir="/tmp/diamond") + has_imaginary, phonon = phononworkflow.run() + + self.assertTrue(has_imaginary) + self.assertIsInstance(phonon, Phonopy) + + def test_phonon_supercell(self): + supercell_matrix = np.array([[4, 0, 0], [0, 4, 0], [0, 0, 4]]) + qpoints_mesh = np.array([12, 12, 12]) + phononworkflow = PhononWorkflow( + self.atoms, + work_dir="/tmp/diamond", + supercell_matrix=supercell_matrix, + qpoints_mesh=qpoints_mesh, + ) + has_imaginary, phonon = phononworkflow.run() + + self.assertTrue(has_imaginary) + self.assertIsInstance(phonon, Phonopy) + + def test_phonon_prim(self): + phononworkflow = PhononWorkflow( + self.atoms_conv, work_dir="/tmp/diamond_conv", find_prim=True + ) + has_imaginary, phonon = phononworkflow.run() + has_imaginary, phonon = phononworkflow.run() + + self.assertTrue(has_imaginary) + self.assertIsInstance(phonon, Phonopy) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/applications/test_relax.py b/tests/applications/test_relax.py new file mode 100644 index 0000000..df508f9 --- /dev/null +++ b/tests/applications/test_relax.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +import unittest + +from ase import Atoms +from ase.calculators.emt import EMT +from pymatgen.io.ase import AseAtomsAdaptor +from pymatgen.symmetry.analyzer import SpacegroupAnalyzer + +from mattersim.applications.relax import Relaxer + + +class RelaxerTestCase(unittest.TestCase): + def setUp(self): + # Create an example structure with displaced atoms for testing + a = 1.786854996 # Angstroms + positions = [ + (0, 0, 0), + (a / 4, a / 4, a / 4), + (a / 2, a / 2, 0), + (a / 2, 0, a / 2), + (0, a / 2, a / 2), + (a / 4, 3 * a / 4, 3 * a / 4.01), # displaced + (3 * a / 4, a / 4.01, 3 * a / 4), # displaced + (3 * a / 4, 3 * a / 4, a / 4), + ] + cell = [(a, 0, 0), (0, a, 0), (0, 0, a)] + self.atoms_displaced = Atoms( + "C8", positions=positions, cell=cell, pbc=True # noqa: E501 + ) + + # Create an example structure with expanded cell for testing + a = 1.786854996 * 1.2 + positions = [ + (0, 0, 0), + (a / 4, a / 4, a / 4), + (a / 2, a / 2, 0), + (a / 2, 0, a / 2), + (0, a / 2, a / 2), + (a / 4, 3 * a / 4, 3 * a / 4), + (3 * a / 4, a / 4, 3 * a / 4), + (3 * a / 4, 3 * a / 4, a / 4), + ] + cell = [(a, 0, 0), (0, a, 0), (0, 0, a)] + self.atoms_expanded = Atoms( + "C8", positions=positions, cell=cell, pbc=True # noqa: E501 + ) + + self.calculator = EMT() + + def test_default_relaxer(self): + relaxer = Relaxer() + atoms_displaced = self.atoms_displaced.copy() + atoms_displaced.set_calculator(self.calculator) + converged, relaxed_atoms = relaxer.relax( + atoms_displaced, fmax=0.1, steps=500 + ) # noqa: E501 + self.assertTrue(converged) + self.assertIsInstance(relaxed_atoms, Atoms) + + def test_relax_structures(self): + atoms_list = [ + self.atoms_displaced.copy(), + self.atoms_displaced.copy(), + self.atoms_displaced.copy(), + ] + for atoms in atoms_list: + atoms.set_calculator(self.calculator) + + converged_list, relaxed_atoms_list = Relaxer.relax_structures( + atoms_list, fmax=0.1, steps=500 + ) + self.assertIsInstance(converged_list, list) + for converged in converged_list: + self.assertTrue(converged) + + def test_relax_structures_under_pressure(self): + atoms_displaced = self.atoms_displaced.copy() + atoms_displaced.set_calculator(self.calculator) + init_volume = atoms_displaced.get_volume() + print(f"Initial volume: {init_volume}") + + # First, relax under 0 pressure + converged, relaxed_atoms = Relaxer.relax_structures( + atoms_displaced, + steps=500, + fmax=0.1, + filter="FrechetCellFilter", + pressure_in_GPa=0.0, + ) + intermediate_volume = relaxed_atoms.get_volume() + print(f"Intermediate volume: {intermediate_volume}") + self.assertTrue(converged) + + # Second, relax under 100 GPa + converged, relaxed_atoms = Relaxer.relax_structures( + relaxed_atoms, + steps=500, + fmax=0.1, + filter="FrechetCellFilter", + pressure_in_GPa=100.0, + ) + final_volume = relaxed_atoms.get_volume() + print(f"Final volume: {final_volume}") + self.assertTrue(converged) + self.assertLess(final_volume, intermediate_volume) + print(f"Final cell: {relaxed_atoms.cell}") + + def test_relax_with_filter_and_constrained_symmetry(self): + atoms_expanded = self.atoms_expanded.copy() + atoms_expanded.set_calculator(self.calculator) + init_volume = atoms_expanded.get_volume() + print(f"Initial volume: {init_volume}") + + init_analyzer = SpacegroupAnalyzer( + AseAtomsAdaptor.get_structure(self.atoms_expanded) + ) + init_spacegroup = init_analyzer.get_space_group_number() + + # First, relax under 0 pressure + converged, relaxed_atoms = Relaxer.relax_structures( + atoms_expanded, + steps=500, + fmax=0.1, + filter="FrechetCellFilter", + pressure_in_GPa=0.0, + constrain_symmetry=True, + ) + intermediate_volume = relaxed_atoms.get_volume() + print(f"Intermediate volume: {intermediate_volume}") + self.assertTrue(converged) + + # Second, relax under 100 GPa + converged, relaxed_atoms = Relaxer.relax_structures( + relaxed_atoms, + steps=500, + fmax=0.1, + filter="FrechetCellFilter", + pressure_in_GPa=100.0, + constrain_symmetry=True, + ) + final_volume = relaxed_atoms.get_volume() + print(f"Final volume: {final_volume}") + self.assertTrue(converged) + self.assertLess(final_volume, intermediate_volume) + + final_analyzer = SpacegroupAnalyzer( + AseAtomsAdaptor.get_structure(relaxed_atoms) + ) + final_spacegroup = final_analyzer.get_space_group_number() + self.assertEqual(init_spacegroup, final_spacegroup) + print(f"Final cell: {relaxed_atoms.cell}") + cell_a = relaxed_atoms.cell[0, 0] + cell_b = relaxed_atoms.cell[1, 1] + cell_c = relaxed_atoms.cell[2, 2] + self.assertAlmostEqual(cell_a, cell_b) + self.assertAlmostEqual(cell_a, cell_c) + + +if __name__ == "__main__": + unittest.main()