Skip to content

Commit c35f1ab

Browse files
Adds PhonopyAtomsAdaptor
Bridges between ASE and Phonopy Atoms objects, similarly to how we have used AseAtomsAdaptor from Pymatgen.
1 parent d64e456 commit c35f1ab

File tree

3 files changed

+85
-50
lines changed

3 files changed

+85
-50
lines changed

janus_core/calculations/phonons.py

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
PathLike,
2828
PhononCalcs,
2929
)
30+
from janus_core.helpers.struct_io import PhonopyAtomsAdaptor
3031
from janus_core.helpers.utils import (
3132
build_file_dir,
3233
none_to_dict,
@@ -498,7 +499,7 @@ def calc_force_constants(
498499

499500
self._set_info_units()
500501

501-
cell = self._ASE_to_PhonopyAtoms(self.struct)
502+
cell = PhonopyAtomsAdaptor.get_phonopy_atoms(self.struct)
502503

503504
if len(self.supercell) == 3:
504505
supercell_matrix = (
@@ -988,53 +989,6 @@ def write_pdos(
988989
build_file_dir(self.pdos_plot_file)
989990
bplt.savefig(self.pdos_plot_file)
990991

991-
# No magnetic moments considered
992-
# Disable invalid-function-name
993-
def _Phonopy_to_ASEAtoms(self, struct: PhonopyAtoms) -> Atoms: # noqa: N802
994-
"""
995-
Convert Phonopy Atoms structure to ASE Atoms structure.
996-
997-
Parameters
998-
----------
999-
struct
1000-
PhonopyAtoms structure to be converted.
1001-
1002-
Returns
1003-
-------
1004-
Atoms
1005-
Converted ASE Atoms structure.
1006-
"""
1007-
return Atoms(
1008-
symbols=struct.symbols,
1009-
scaled_positions=struct.scaled_positions,
1010-
cell=struct.cell,
1011-
masses=struct.masses,
1012-
pbc=True,
1013-
calculator=self.calc,
1014-
)
1015-
1016-
# Disable invalid-function-name
1017-
def _ASE_to_PhonopyAtoms(self, struct: Atoms) -> PhonopyAtoms: # noqa: N802
1018-
"""
1019-
Convert ASE Atoms structure to Phonopy Atoms structure.
1020-
1021-
Parameters
1022-
----------
1023-
struct
1024-
ASE Atoms structure to be converted.
1025-
1026-
Returns
1027-
-------
1028-
PhonopyAtoms
1029-
Converted PhonopyAtoms structure.
1030-
"""
1031-
return PhonopyAtoms(
1032-
symbols=struct.get_chemical_symbols(),
1033-
cell=struct.cell.array,
1034-
scaled_positions=struct.get_scaled_positions(),
1035-
masses=struct.get_masses(),
1036-
)
1037-
1038992
def _calc_forces(self, struct: PhonopyAtoms) -> ndarray:
1039993
"""
1040994
Calculate forces on PhonopyAtoms structure.
@@ -1049,8 +1003,7 @@ def _calc_forces(self, struct: PhonopyAtoms) -> ndarray:
10491003
ndarray
10501004
Forces on the structure.
10511005
"""
1052-
atoms = self._Phonopy_to_ASEAtoms(struct)
1053-
return atoms.get_forces()
1006+
return PhonopyAtomsAdaptor.get_atoms(struct).get_forces()
10541007

10551008
def run(self) -> None:
10561009
"""Run phonon calculations."""

janus_core/helpers/struct_io.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
from typing import Any, get_args
1010

1111
from ase import Atoms
12+
from ase.calculators.calculator import Calculator
1213
from ase.calculators.singlepoint import SinglePointCalculator
1314
from ase.io import read, write
1415
from ase.io.formats import filetype
16+
from phonopy.structure.atoms import PhonopyAtoms
1517

1618
from janus_core.helpers.janus_types import (
1719
Architectures,
@@ -321,3 +323,56 @@ def output_structs(
321323

322324
build_file_dir(write_kwargs["filename"])
323325
write(images=images, **write_kwargs)
326+
327+
328+
class PhonopyAtomsAdaptor:
329+
"""Adaptor to bridge between ASE and pymatgen atoms."""
330+
331+
# No magnetic moments considered
332+
@staticmethod
333+
def get_atoms(struct: PhonopyAtoms, calc: Calculator | None = None) -> Atoms:
334+
"""
335+
Convert Phonopy Atoms structure to ASE Atoms structure.
336+
337+
Parameters
338+
----------
339+
struct
340+
PhonopyAtoms structure to be converted.
341+
calc
342+
Optional calculator to attach.
343+
344+
Returns
345+
-------
346+
Atoms
347+
Converted ASE Atoms structure.
348+
"""
349+
return Atoms(
350+
symbols=struct.symbols,
351+
scaled_positions=struct.scaled_positions,
352+
cell=struct.cell,
353+
masses=struct.masses,
354+
pbc=True,
355+
calculator=calc,
356+
)
357+
358+
@staticmethod
359+
def get_phonopy_atoms(struct: Atoms) -> PhonopyAtoms:
360+
"""
361+
Convert ASE Atoms structure to Phonopy Atoms structure.
362+
363+
Parameters
364+
----------
365+
struct
366+
ASE Atoms structure to be converted.
367+
368+
Returns
369+
-------
370+
PhonopyAtoms
371+
Converted PhonopyAtoms structure.
372+
"""
373+
return PhonopyAtoms(
374+
symbols=struct.get_chemical_symbols(),
375+
cell=struct.cell.array,
376+
scaled_positions=struct.get_scaled_positions(),
377+
masses=struct.get_masses(),
378+
)

tests/test_struct_io.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Test utility functions."""
2+
3+
from __future__ import annotations
4+
5+
from pathlib import Path
6+
7+
from ase.calculators.lj import LennardJones
8+
from ase.io import read
9+
10+
from janus_core.helpers.struct_io import PhonopyAtomsAdaptor
11+
12+
DATA_PATH = Path(__file__).parent / "data"
13+
14+
15+
def test_phonopyadaptor():
16+
"""Test Phonopy atoms to ASE atoms adpator."""
17+
struct = read(DATA_PATH / "NaCl.cif")
18+
phonopy_struct = PhonopyAtomsAdaptor.get_phonopy_atoms(struct)
19+
assert struct == PhonopyAtomsAdaptor.get_atoms(phonopy_struct)
20+
21+
struct.calc = LennardJones()
22+
phonopy_struct = PhonopyAtomsAdaptor.get_phonopy_atoms(struct)
23+
24+
assert PhonopyAtomsAdaptor.get_atoms(phonopy_struct).calc is None
25+
assert (
26+
PhonopyAtomsAdaptor.get_atoms(phonopy_struct, struct.calc).calc == struct.calc
27+
)

0 commit comments

Comments
 (0)