Skip to content

Commit

Permalink
crystal: Implemnted to_cif
Browse files Browse the repository at this point in the history
  • Loading branch information
Somerandomguy10111 committed Jun 30, 2024
1 parent 494c01a commit e554379
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 40 deletions.
79 changes: 39 additions & 40 deletions CrystalStructure/crystal/crystal.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ class CrystalStructure(JsonDataclass):
wyckoff_symbols : Optional[list[str]] = None
crystal_system : Optional[str] = None

@classmethod
def from_cif(cls, cif_content : str) -> CrystalStructure:
pymatgen_structure = Structure.from_str(cif_content, fmt='cif')
crystal_structure = cls.from_pymatgen(pymatgen_structure)
return crystal_structure

@classmethod
def from_pymatgen(cls, pymatgen_structure: Structure) -> CrystalStructure:
lattice = pymatgen_structure.lattice
base : CrystalBase = CrystalBase()

for index, site in enumerate(pymatgen_structure.sites):
site_composition = site.species
for species, occupancy in site_composition.items():
if isinstance(species, Element):
species = Species(symbol=species.symbol, oxidation_state=0)
x,y,z = lattice.get_fractional_coords(site.coords)
atomic_site = AtomicSite(x, y, z, occupancy=occupancy, species_str=str(species))
base.append(atomic_site)

crystal_str = cls(lengths=Lengths(a=lattice.a, b=lattice.b, c=lattice.c),
angles=Angles(alpha=lattice.alpha, beta=lattice.beta, gamma=lattice.gamma),
base=base)

return crystal_str

# ---------------------------------------------------------
# properties

def calculate_properties(self):
pymatgen_structure = self.to_pymatgen()
analyzer = SpacegroupAnalyzer(structure=pymatgen_structure, symprec=0.1, angle_tolerance=10)
Expand All @@ -42,7 +71,6 @@ def calculate_properties(self):
pymatgen_spacegroup = SpaceGroup.from_int_number(self.space_group)
self.crystal_system = pymatgen_spacegroup.crystal_system


def standardize(self):
"""Permutes lattice primitives such that a <= b <=c and permutes lattice sites such that i > j => d(i) > d(j) with d(i) = (x_i**2+y_i**2+z_i**2)"""
a,b,c = self.lengths
Expand Down Expand Up @@ -71,50 +99,24 @@ def distance_from_origin(atomic_site : AtomicSite):
new_base = sorted(new_base.atomic_sites, key=distance_from_origin)
self.base = CrystalBase(new_base)


@classmethod
def from_cif(cls, cif_content : str) -> CrystalStructure:
# print(f'Cif content is {cif_content}')

pymatgen_structure = Structure.from_str(cif_content, fmt='cif')
crystal_structure = cls.from_pymatgen(pymatgen_structure)
return crystal_structure
def scale(self, target_density: float):
volume_scaling = self.packing_density / target_density
cbrt_scaling = volume_scaling ** (1 / 3)
self.lengths = self.lengths * cbrt_scaling
self.volume_uc = self.volume_uc * volume_scaling

@property
def packing_density(self) -> float:
volume_uc = self.volume_uc
atomic_volume = self.base.calculate_atomic_volume()
return atomic_volume/volume_uc

def scale(self, target_density : float):
volume_scaling = self.packing_density/target_density
cbrt_scaling = volume_scaling ** (1/3)
self.lengths = self.lengths * cbrt_scaling
self.volume_uc = self.volume_uc * volume_scaling


@classmethod
def from_pymatgen(cls, pymatgen_structure: Structure) -> CrystalStructure:
lattice = pymatgen_structure.lattice
base : CrystalBase = CrystalBase()

for index, site in enumerate(pymatgen_structure.sites):
site_composition = site.species
for species, occupancy in site_composition.items():
if isinstance(species, Element):
species = Species(symbol=species.symbol, oxidation_state=0)
x,y,z = lattice.get_fractional_coords(site.coords)
atomic_site = AtomicSite(x, y, z, occupancy=occupancy, species_str=str(species))
base.append(atomic_site)

crystal_str = cls(lengths=Lengths(a=lattice.a, b=lattice.b, c=lattice.c),
angles=Angles(alpha=lattice.alpha, beta=lattice.beta, gamma=lattice.gamma),
base=base)

return crystal_str

# ---------------------------------------------------------
# get
# conversion

def to_cif(self) -> str:
pymatgen_structure = self.to_pymatgen()
return pymatgen_structure.to(filename='', fmt='cif')

def to_pymatgen(self) -> Structure:
a, b, c = self.lengths.as_tuple()
Expand All @@ -126,9 +128,6 @@ def to_pymatgen(self) -> Structure:
positions = [(site.x, site.y, site.z) for site in non_void_sites]
return Structure(lattice, atoms, positions)

# ---------------------------------------------------------
# print

def as_str(self) -> str:
the_dict = asdict(self)
the_dict = {str(key) : str(value) for key, value in the_dict.items() if not isinstance(value, Structure)}
Expand Down
4 changes: 4 additions & 0 deletions tests/t_crystal/t_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def test_pymatgen(self):

print(f'Composition = {actual.composition}')

def test_to_cif(self):
for struct, crystal in zip(self.pymatgen_structures, self.crystals):
cif = crystal.to_cif()
print(f'CIF = \n{cif}')

def test_volumes(self):
for crystal in self.crystals:
Expand Down

0 comments on commit e554379

Please sign in to comment.