Source code for pymatgen.transformations.defect_transformations
# coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.
from __future__ import division, unicode_literals
"""
This module defines classes for point defect transformations on structures
"""
__author__ = "Bharat Medasani"
__copyright__ = "Copyright 2014, The Materials Project"
__version__ = "0.1"
__maintainier__ = "Bharat Medasani"
__email__ = "mbkumar@gmail.com"
__date__ = "Jul 1 2014"
from pymatgen.core.periodic_table import Specie, Element
from pymatgen.analysis.defects.point_defects import Vacancy, \
ValenceIonicRadiusEvaluator, Interstitial
from pymatgen.transformations.transformation_abc import AbstractTransformation
[docs]class VacancyTransformation(AbstractTransformation):
"""
Generates vacancy structures
"""
def __init__(self, supercell_dim, species=None, valences=None, radii=None):
"""
:param supecell_dim: Supercell scaling matrix
:param species: Species in the structure for which vacancy
transformation is applied
:return:
"""
self.supercell_dim = supercell_dim
self.species = species
self.valences = valences
self.radii = radii
[docs] def apply_transformation(self, structure, return_ranked_list=False):
"""
:param structure:
:param return_ranked_list (Logical or integer): Use big enough
number to return all defect structures
:return:
scs: Supercells with one vacancy in each structure.
"""
if not return_ranked_list:
raise ValueError("VacancyTransformation has no single best structure"
" output. Must use return_ranked_list.")
try:
num_to_return = int(return_ranked_list)
except ValueError:
num_to_return = 1
vac = Vacancy(structure,self.valences,self.radii)
scs = vac.make_supercells_with_defects(
self.supercell_dim,self.species, num_to_return)
#if num_to_return < len(scs)-1:
# raise ValueError("VacancyTransformation has no ordering of best "
# "structure. Must increase return_ranked_list.")
structures = []
for sc in scs[1:]:
structures.append({'structure':sc})
return structures
def __str__(self):
inp_args = ["Supercell scaling matrix = {}".format(self.supercell_dim),
"Vacancy species = {}".format(self.species),
"Valences of ions = {}".format(self.valences),
"Radii of ions = {}".format(self.radii)]
return "Vacancy Transformation : " + ", ".join(inp_args)
def __repr__(self):
return self.__str__()
@property
def inverse(self):
pass
@property
def is_one_to_many(self):
return True
[docs]class SubstitutionDefectTransformation(AbstractTransformation):
"""
Generates substiutional defect structures.
The first structure is the supercell of the original structure
and is not a defect structure.
"""
def __init__(self, species_map, supercell_dim,
valences=None, radii=None):
"""
:param supecell_dim: Supercell scaling matrix
:return:
"""
#self.substitute_specie = substitute_specie
#self.site_specie = site_specie
self.species_map = species_map
self.supercell_dim = supercell_dim
self.valences = valences
self.radii = radii
[docs] def apply_transformation(self, structure, return_ranked_list=False):
"""
:param structure:
:param return_ranked_list (Logical or integer): Use big enough
number to return all defect structures
:return:
scs: Supercells with one substitution defect in each structure.
"""
if not return_ranked_list:
raise ValueError("SubstitutionDefectTransformation has no single"
"best structure output. Must use return_ranked_list.")
try:
num_to_return = int(return_ranked_list)
except ValueError:
num_to_return = 1
species = self.species_map.keys()
vac = Vacancy(structure,self.valences,self.radii)
scs = vac.make_supercells_with_defects(
self.supercell_dim,species,num_to_return)
blk_sc = scs[0]
sub_scs = []
for i in range(1,len(scs)):
vac_sc = scs[i]
vac_site = list(set(blk_sc.sites) - set(vac_sc.sites))[0]
if isinstance(vac_site.specie,Specie):
site_specie = vac_site.specie.element.symbol
elif isinstance(vac_site.specie,Element):
site_specie = vac_site.specie.symbol
if site_specie in self.species_map.keys():
substitute_specie = self.species_map[site_specie]
vac_sc.append(substitute_specie, vac_site.frac_coords)
sub_scs.append(vac_sc.get_sorted_structure())
#if num_to_return < len(sub_scs)-1:
# raise ValueError("SubstitutionDefectTransformation has no ordering"
# " of best structure. Must increase return_ranked_list.")
num_to_return = min(num_to_return, len(sub_scs))
structures = []
if num_to_return:
for sc in sub_scs[0:num_to_return]:
structures.append({'structure':sc})
else:
structures.append({'structure':scs[0]})
return structures
def __str__(self):
specie_map_string = ", ".join(
[str(k) + "->" + str(v) for k, v in self.species_map.items()])
inp_args = ["Specie map = {}".format(specie_map_string),
"Supercell scaling matrix = {}".format(self.supercell_dim),
"Valences of ions = {}".format(self.valences),
"Radii of ions = {}".format(self.radii)]
return "Substitutional Defect Transformation : " + ", ".join(inp_args)
def __repr__(self):
return self.__str__()
@property
def inverse(self):
pass
@property
def is_one_to_many(self):
return True
[docs]class AntisiteDefectTransformation(AbstractTransformation):
"""
Generates antisite defect structures
"""
def __init__(self, supercell_dim, valences=None, radii=None):
"""
:param supecell_dim: Supercell scaling matrix
:return:
"""
self.supercell_dim = supercell_dim
self.valences = valences
self.radii = radii
[docs] def apply_transformation(self, structure, return_ranked_list=False):
"""
:param structure:
:param return_ranked_list (Logical or integer): Use big enough
number to return all defect structures
:return:
scs: Supercells with one antisite defect in each structure.
"""
if not return_ranked_list:
raise ValueError("AntisiteDefectTransformation has no single best"
"structure output. Must use return_ranked_list.")
try:
num_to_return = int(return_ranked_list)
except ValueError:
num_to_return = 1
vac = Vacancy(structure,self.valences,self.radii)
scs = vac.make_supercells_with_defects(self.supercell_dim)
blk_sc = scs[0]
as_scs = []
struct_species = blk_sc.types_of_specie
for i in range(1,len(scs)):
vac_sc = scs[i]
vac_site = list(set(blk_sc.sites) - set(vac_sc.sites))[0]
for specie in set(struct_species) - set([vac_site.specie]):
anti_struct = vac_sc.copy()
anti_struct.append(specie, vac_site.frac_coords)
as_scs.append(anti_struct.get_sorted_structure())
#if num_to_return < len(as_scs)-1:
# raise ValueError("AntisiteDefectTransformation has no ordering "
# "of best structures. Must increase return_ranked_list.")
num_to_return = min(num_to_return,len(as_scs))
structures = []
for sc in as_scs[0:num_to_return]:
structures.append({'structure':sc})
return structures
def __str__(self):
inp_args = ["Supercell scaling matrix = {}".format(self.supercell_dim),
"Valences of ions = {}".format(self.valences),
"Radii of ions = {}".format(self.radii)]
return "Antisite Defect Transformation : " + ", ".join(inp_args)
def __repr__(self):
return self.__str__()
@property
def inverse(self):
pass
@property
def is_one_to_many(self):
return True
[docs]class InterstitialTransformation(AbstractTransformation):
"""
Generates interstitial structures from the input structure
"""
def __init__(self, interstitial_specie, supercell_dim,
valences=None, radii=None):
"""
:param supercell_dim:
:param valences:
:param radii:
:return:
"""
self.supercell_dim = supercell_dim
self.valences = valences or {}
self.radii = radii or {}
self.interstitial_specie = interstitial_specie
[docs] def apply_transformation(self, structure, return_ranked_list=False):
"""
:param structure:
:param return_ranked_list (Logical or integer): Use big enough
number to return all defect structures
:return:
scs: Supercells with one interstitial defect in each structure.
"""
if not return_ranked_list:
raise ValueError("InterstitialTransformation has no single best "
"structure output. Must use return_ranked_list.")
try:
num_to_return = int(return_ranked_list)
except ValueError:
num_to_return = 1
if self.radii:
inter = Interstitial(structure, self.valences, self.radii)
else:
s = structure.copy()
valrad_eval = ValenceIonicRadiusEvaluator(s)
s = valrad_eval.structure
val = valrad_eval.valences
rad = valrad_eval.radii
inter = Interstitial(s,val,rad,oxi_state=True)
scs = inter.make_supercells_with_defects(
self.supercell_dim, self.interstitial_specie)
#if num_to_return < len(scs)-1:
# raise ValueError("InterstitialTransformation has no ordering "
# "of best structures. Must increase return_ranked_list.")
structures = []
num_to_return = min(num_to_return,len(scs)-1)
for sc in scs[1:num_to_return+1]:
structures.append({'structure':sc})
return structures
def __str__(self):
inp_args = ["Supercell scaling matrix = {}".format(self.supercell_dim),
"Valences of ions = {}".format(self.valences),
"Radii of ions = {}".format(self.radii),
"interstitial specie = {}".format(self.interstitial_specie)]
return "Interstitial Transformation : " + ", ".join(inp_args)
def __repr__(self):
return self.__str__()
@property
def inverse(self):
pass
@property
def is_one_to_many(self):
return True