Skip to content

Commit

Permalink
pymatgen interconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
mcgalcode committed Oct 30, 2023
1 parent 2819996 commit 607b0d8
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 1 deletion.
Empty file.
46 changes: 46 additions & 0 deletions src/pylattica/atomic/pymatgen_struct_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from pymatgen.core.structure import Structure as PmgStructure
from pymatgen.core.lattice import Lattice as PmgLattice

from ..core import Lattice as PylLattice, StructureBuilder, PeriodicStructure


class PymatgenStructureConverter:
def to_pylattica_lattice(self, pmg_lat: PmgLattice):
pmg_lat = pmg_lat
pyl_lat = PylLattice(pmg_lat.matrix)
return pyl_lat

def to_pylattica_structure_builder(self, pmg_struct: PmgStructure):
lat = self.to_pylattica_lattice(pmg_struct.lattice)

struct_motif = {}

for site in pmg_struct.sites:
site_cls = site.species_string
frac_coords = site.frac_coords

if site_cls in struct_motif:
struct_motif.get(site_cls).append(frac_coords)
else:
struct_motif[site_cls] = [frac_coords]

struct_builder = StructureBuilder(lat, struct_motif)
struct_builder.frac_coords = True
return struct_builder

def to_pymatgen_lattice(self, pyl_lat: PylLattice):
return PmgLattice(pyl_lat.vecs)

def to_pymatgen_structure(self, pyl_struct: PeriodicStructure):
pmg_lat = self.to_pymatgen_lattice(pyl_struct.lattice)

species = []
coords = []

for sid in pyl_struct.site_ids:
species.append(pyl_struct.site_class(sid))
coords.append(
pyl_struct.lattice.get_fractional_coords(pyl_struct.site_location(sid))
)

return PmgStructure(pmg_lat, species, coords)
1 change: 1 addition & 0 deletions src/pylattica/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .simulation import Simulation
from .lattice import Lattice
from .analyzer import StateAnalyzer
from .structure_builder import StructureBuilder

from .neighborhoods import Neighborhood, StochasticNeighborhood
from .neighborhood_builders import (
Expand Down
6 changes: 6 additions & 0 deletions src/pylattica/core/periodic_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ def site_at(self, location: Tuple[float]) -> Dict:
else:
return None

def site_class(self, site_id: int) -> str:
return self.get_site(site_id)[SITE_CLASS]

def site_location(self, site_id: int) -> str:
return self.get_site(site_id)[LOCATION]

def get_site(self, site_id: int) -> Dict:
"""Returns the site with the specified ID.
Expand Down
2 changes: 1 addition & 1 deletion src/pylattica/core/runner/synchronous_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def _run(
if self.workers is None:
PROCESSES = mp.cpu_count()
else:
PROCESSES = self.workers # pragma: no cover
PROCESSES = self.workers # pragma: no cover

printif(verbose, f"Running in parallel using {PROCESSES} workers")
num_sites = initial_state.size
Expand Down
28 changes: 28 additions & 0 deletions tests/atomic/Zr.cif
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# generated using pymatgen
data_Zr
_symmetry_space_group_name_H-M 'P 1'
_cell_length_a 3.23923141
_cell_length_b 3.23923141
_cell_length_c 5.17222000
_cell_angle_alpha 90.00000000
_cell_angle_beta 90.00000000
_cell_angle_gamma 120.00000000
_symmetry_Int_Tables_number 1
_chemical_formula_structural Zr
_chemical_formula_sum Zr2
_cell_volume 46.99931972
_cell_formula_units_Z 2
loop_
_symmetry_equiv_pos_site_id
_symmetry_equiv_pos_as_xyz
1 'x, y, z'
loop_
_atom_site_type_symbol
_atom_site_label
_atom_site_symmetry_multiplicity
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_occupancy
Zr Zr0 1 0.33333333 0.66666667 0.25000000 1
Zr Zr1 1 0.66666667 0.33333333 0.75000000 1
26 changes: 26 additions & 0 deletions tests/atomic/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pytest

from pathlib import Path
from pymatgen.core.structure import Structure

from pylattica.core import Lattice, StructureBuilder

THIS_DIR = Path(__file__).parent

@pytest.fixture()
def zr_pmg_struct():
return Structure.from_file(THIS_DIR / "./Zr.cif")

@pytest.fixture()
def pyl_struct():

lat = Lattice([[1,0,0], [0,1,0], [0,0,1]])

motif = {
"Zr": [[
0.5, 0.5, 0.5
]]
}

builder = StructureBuilder(lat, motif)
return builder.build((1, 2, 3))
65 changes: 65 additions & 0 deletions tests/atomic/test_convert_pymatgen_structure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pytest

from pylattica.atomic.pymatgen_struct_converter import PymatgenStructureConverter
from pylattica.core.constants import SITE_CLASS, LOCATION
from pymatgen.core.structure import Structure as PmgStructure
from pylattica.core import PeriodicStructure

import numpy as np

def test_can_convert_lattice(zr_pmg_struct: PmgStructure):
converter = PymatgenStructureConverter()

lattice = converter.to_pylattica_lattice(zr_pmg_struct.lattice)

assert np.isclose(lattice.vec_lengths[0], zr_pmg_struct.lattice.a)
assert np.isclose(lattice.vec_lengths[1], zr_pmg_struct.lattice.b)
assert np.isclose(lattice.vec_lengths[2], zr_pmg_struct.lattice.c)

assert np.allclose(lattice.vecs[0], zr_pmg_struct.lattice.matrix[0])
assert np.allclose(lattice.vecs[1], zr_pmg_struct.lattice.matrix[1])
assert np.allclose(lattice.vecs[2], zr_pmg_struct.lattice.matrix[2])

def test_can_convert_pmg_struct(zr_pmg_struct: PmgStructure):
converter = PymatgenStructureConverter()

struct_builder = converter.to_pylattica_structure_builder(zr_pmg_struct)

struct = struct_builder.build(1)

assert len(struct.site_ids) == zr_pmg_struct.num_sites

species_label = zr_pmg_struct.sites[0].species_string
assert struct.site_class(0) == species_label

# brittle - relies on the order in which sites are enumerated
assert np.allclose(struct.site_location(0),zr_pmg_struct.sites[0].coords)
assert np.allclose(struct.site_location(1),zr_pmg_struct.sites[1].coords)

assert np.allclose(struct.lattice.get_fractional_coords(struct.site_location(1)), zr_pmg_struct.sites[1].frac_coords)

def test_can_convert_pyl_lat(pyl_struct: PeriodicStructure):
converter = PymatgenStructureConverter()

pmg_lat = converter.to_pymatgen_lattice(pyl_struct.lattice)
assert pmg_lat.a == pyl_struct.lattice.vec_lengths[0]
assert pmg_lat.b == pyl_struct.lattice.vec_lengths[1]
assert pmg_lat.c == pyl_struct.lattice.vec_lengths[2]

assert np.allclose(pyl_struct.lattice.vecs[0], pmg_lat.matrix[0])
assert np.allclose(pyl_struct.lattice.vecs[1], pmg_lat.matrix[1])
assert np.allclose(pyl_struct.lattice.vecs[2], pmg_lat.matrix[2])

def test_can_convert_pyl_struct(pyl_struct: PeriodicStructure):
converter = PymatgenStructureConverter()

pmg_struct = converter.to_pymatgen_structure(pyl_struct)

assert pmg_struct.num_sites == len(pyl_struct.site_ids)

for site in pmg_struct.sites:
matching_site = pyl_struct.site_at(site.coords)
assert matching_site is not None
assert matching_site[SITE_CLASS] == site.species_string

assert np.all(pyl_struct.lattice.get_fractional_coords(matching_site[LOCATION]) == site.frac_coords)

0 comments on commit 607b0d8

Please sign in to comment.