# notebook utils
from tqdm.notebook import tqdm
from IPython.display import Image
# web utils
import requests
# data utils
import pickle
import itertools
import numpy as np
# import pymatgen
import pymatgen
from pymatgen.core import Lattice, Structure, Molecule
from pymatgen.ext.matproj import MPRester
lieb_reference = Structure(
Lattice.from_parameters(a=5, b=5, c=5, alpha=90, beta=90, gamma=90),
["Sn", "Fe", "Sn"],
[[1 / 2, 0, 0], [0, 0, 0], [0, 1 / 2, 0]],
)
lieb_reference.to(filename="lieb.cif")
def is_lieb_lattice(structure):
distinct_species = set(structure.species)
if len(structure.species) != 3 or len(distinct_species) not in (2, 3): return False # 3 total species, 2-3 distinct species
if structure.lattice.angles != (90.0, 90.0, 90.0): return False # square lattice
z_coords = structure.frac_coords.transpose()[-1]
if not np.all(z_coords == z_coords[0]): return False # all species are at the same z-coord
if len(distinct_species) == 2: # if there are 2 distinct species, make sure the edge species are the same (as opposed to the corner species and one edge species)
edge_species = [structure.sites[i].species for i in np.nonzero(structure.frac_coords)[0]]
if edge_species[0] != edge_species[1]: return False
return True
def has_lieb_lattice(structure, max_num_lieb_species=20):
if len(structure.species) < 3: return False # at least 3 total atoms (needed to form the Lieb lattice)
if structure.lattice.angles.count(90.0) < 1: return False # at least one lattice angle must be 90 (the lieb lattice axis angle)
for species in set(structure.species):
species_idx = structure.indices_from_symbol(species.value)
if len(species_idx) not in range(3, max_num_lieb_species+ 1): continue # at least three of the same element, bounded above to reduce query time
if np.zeros(3) not in np.array([ structure.frac_coords[i] for i in species_idx ]): continue # at least one atom of the element is @ origin
for atom_triple in itertools.combinations(species_idx, 3): # for each triple of the same element (candidate Lieb lattice atoms)
nonzero_coords = np.nonzero(np.array([ structure.frac_coords[i] for i in atom_triple ]))
if len(nonzero_coords[0]) != 2 or len(set(nonzero_coords[0])) != 2 or len(set(nonzero_coords[1])) != 2: return False # one @ origin, two along a lattice vector
for axis, plane in enumerate(np.array([ structure.frac_coords[i] for i in atom_triple ]).transpose()):
if np.all(plane[0] == plane[:]): lieb_axis, lieb_plane = axis, plane[0]
if structure.lattice.angles[lieb_axis] != 90.0: return False # lieb lattice axis angle must be 90 (square lattice)
if all([structure.frac_coords[i][lieb_axis] != lieb_plane for i in set(species_idx) ^ set(atom_triple)]): return True # no other species of *same element* in lieb lattice plane
return False
has_lieb_lattice(lieb_reference)
def unit_vector(vector):
return vector / np.linalg.norm(vector)
def angle_between(v1, v2):
v1_u = unit_vector(v1)
v2_u = unit_vector(v2)
return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0)) * 180/np.pi
def get_nearest_neighbors(structure):
return np.array([len(structure.get_neighbors(site, min(np.delete(structure.distance_matrix[site_idx], site_idx)) + 0.0000001 )) for site_idx, site in enumerate(structure.sites)])
def is_lieb_lattice(structure, verbose=False):
if not (len(structure.species) == 3 and len(set(structure.species)) in (1, 2)):
if verbose: print("# Species Constraint: # of species is %d and number of distinct species is %d." % (len(structure.species), len(set(structure.species))))
return False # exactly 3 atoms, 1 or 2 distinct atoms
nearest_neighbors = get_nearest_neighbors(structure)
if not (sorted(nearest_neighbors) == [2, 2, 4]):
if verbose: print("Nearest Neighbors Constraint: # of nearest neighbors for each species is %s." % str(nearest_neighbors))
return False # 4 nearest neighbors for corner, 2 nearest neighbor for edge
if len(set(structure.species)) == 2:
edge_species = [ site.species for site in np.array(structure.sites)[np.where(nearest_neighbors == 2)[0]] ]
if not (edge_species[0] == edge_species[1]):
if verbose: print("Edge Species Constraint: edge species are %s and %s." % (str(edge_species[0]), str(edge_species[1])))
return False # edge species are the same element
lattice_vectors = structure.cart_coords[np.where(nearest_neighbors == 2)[0]] - structure.cart_coords[np.where(nearest_neighbors == 4)[0]]
if not (angle_between(lattice_vectors[0], lattice_vectors[1]) == 90.0):
if verbose: print("Right Angle Constraint: angle between lattice vectors is %f." % (angle_between(lattice_vectors[0], lattice_vectors[1]) * 180/np.pi) )
return False # 90 degree angle between lattice vectors
return True
def lieb_plane_is_empty(structure, lieb_species, lieb_species_idx):
for stray_lieb_species in set(np.concatenate([ np.array(structure.indices_from_symbol(species.value)) for species in lieb_species ])) ^ lieb_species_idx:
species_coords = np.array(structure.frac_coords)[list(lieb_species_idx.union({stray_lieb_species}))]
if np.linalg.det(species_coords[1:] - species_coords[0]) == 0: return False # stray_lieb_species is coplanar w/ lieb_species
return True
def has_lieb_lattice(structure,
max_num_total_species=None,
total_species=None,
max_num_lieb_species=None,
include_two_element_lattice=True):
if len(structure.species) < 3 or (len(structure.species) > max_num_total_species) if max_num_total_species else False or len(structure.species) != total_species if total_species else False: return False # at least 3 atoms
for species in set(structure.species):
species_idx = structure.indices_from_symbol(species.value)
if len(species_idx) < 2 if include_two_element_lattice else 3 or (len(species_idx) >= max_num_lieb_species) if max_num_lieb_species else False: continue # at least 2 or 3 of the same atom
if include_two_element_lattice:
for edge_species_pair in itertools.combinations(species_idx, 2): # every triple of (2 same atom, 1 other atom)
for corner_species in set(range(len(structure.species))) ^ set(species_idx):
lieb_species_idx = set(edge_species_pair).union({corner_species})
lieb_structure = Structure.from_sites(list(np.array(structure.sites)[list(lieb_species_idx)]))
if is_lieb_lattice(lieb_structure) and lieb_plane_is_empty(structure, {species, structure.species[corner_species]}, lieb_species_idx): return lieb_structure
if len(species_idx) >= 3:
for lieb_species_idx in itertools.combinations(species_idx, 3): # every triple of same atom
lieb_structure = Structure.from_sites(list(np.array(structure.sites)[list(lieb_species_idx)]))
if is_lieb_lattice(lieb_structure) and lieb_plane_is_empty(structure, {species}, set(lieb_species_idx)): return lieb_structure
return False
material_id = "mp-1019593"
with MPRester(API_KEY) as m:
result = m.query(criteria={"material_id": material_id}, properties=["pretty_formula", "structure"])
structure = result[0]["structure"]
structure
is_lieb_lattice(structure, verbose=True)
# Species Constraint: # of species is 136 and number of distinct species is 3.
for species in set(structure.species): print(len(structure.indices_from_symbol(species.value)))
96
8
32
lieb_structure = has_lieb_lattice(structure)
lieb_structure
is_lieb_lattice(lieb_structure)
with open('mapi_localdb.pkl', 'rb') as f: local_db = pickle.load(f)
len(local_db)
lieb_lattices = { compound['material_id']: compound for compound in tqdm(local_db) if is_lieb_lattice(compound["structure"])}
len(lieb_lattices)
for id, lattice in lieb_lattices.items():
print(id, lattice['pretty_formula'])
mp-1147667 CuI2
mp-1147672 CuF2
mp-1147758 CuCl2
mp-1147756 CuCl2
mp-1147670 CuF2
mp-1147532 CuBr2
mp-1147530 CuBr2
with open('is_lieb_lattice_db.pkl', 'wb') as f: pickle.dump(lieb_lattices, f)
lieb_lattices = {}
for material in tqdm(local_db):
# print(material["material_id"], material["pretty_formula"])
lieb_structure = has_lieb_lattice(material["structure"], total_species=10)
if lieb_structure: lieb_lattices[material["material_id"]] = {
"material_properties": material,
"lieb_substructure": lieb_structure
}
len(lieb_lattices)
for id, lattice in lieb_lattices.items():
print(id, lattice['material_properties']['pretty_formula'], lattice['lieb_substructure'].species)
# lattice['lieb_structure'].to(filename=id+"_lieb.cif")
mp-1179715 RbHfCu3Se4 [Element Hf, Element Cu, Element Cu]
mp-1180325 MgTlCu3Se4 [Element Tl, Element Cu, Element Cu]
mp-1179753 RbCu3SiSe4 [Element Cu, Element Cu, Element Si]
mp-1180844 KCu3SiSe4 [Element Cu, Element Cu, Element Si]
mp-1180276 MgVCu3Se4 [Element V, Element Cu, Element Cu]
mp-1182239 BaCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1179135 ScZnCu3Se4 [Element Sc, Element Cu, Element Cu]
mp-1178984 TlZnCu3Se4 [Element Tl, Element Cu, Element Cu]
mp-1179525 ScCu3PbSe4 [Element Sc, Element Cu, Element Cu]
mp-1179003 SrYCu3Se4 [Element Y, Element Cu, Element Cu]
mp-1179889 NaCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1179142 SrCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1232330 Na2CuAg2(SO)2 [Element O, Element Cu, Element O]
mp-1094069 Sr2Cd2Cu(SO)2 [Element O, Element Cu, Element O]
mp-1225101 Fe6Ge2N [Element Fe, Element N, Element Fe]
mp-1179516 ScCu3HgSe4 [Element Sc, Element Cu, Element Cu]
mp-1182182 BaScCu3Se4 [Element Sc, Element Cu, Element Cu]
mp-1181331 GaCu3HgSe4 [Element Ga, Element Cu, Element Cu]
mp-1178705 YMgCu3Se4 [Element Y, Element Cu, Element Cu]
mp-1179119 SrInCu3Se4 [Element In, Element Cu, Element Cu]
mp-1182859 AlZnCu3Se4 [Element Al, Element Cu, Element Cu]
mp-1179864 NaMnCu3Se4 [Element Mn, Element Cu, Element Cu]
mp-1180289 MgCrCu3Se4 [Element Cr, Element Cu, Element Cu]
mp-1181967 CaCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1095024 Ti4H5 [Element H, Element H, Element H]
mp-1179118 SrGaCu3Se4 [Element Ga, Element Cu, Element Cu]
mp-1180284 MgCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1178824 VCu3PbSe4 [Element V, Element Cu, Element Cu]
mp-1179021 TlCdCu3Se4 [Element Tl, Element Cu, Element Cu]
mp-1180332 MgAlCu3Se4 [Element Al, Element Cu, Element Cu]
mp-1181852 CaTlCu3Se4 [Element Tl, Element Cu, Element Cu]
mp-1222737 LaTi2O6 [Element O, Element La, Element O]
mp-1232329 K2Zn2Cu(SO)2 [Element O, Element Cu, Element O]
mp-1173069 Ba2In2O5 [Element O, Element O, Element O]
mp-1179749 RbCu3GeSe4 [Element Cu, Element Cu, Element Ge]
mp-1180283 MgGaCu3Se4 [Element Ga, Element Cu, Element Cu]
mp-1178643 ZnCrCu3Se4 [Element Cr, Element Cu, Element Cu]
mp-1182176 BaAlCu3Se4 [Element Al, Element Cu, Element Cu]
mp-1215493 Zr2BIr6 [Element B, Element Ir, Element Ir]
mp-1078706 Ba2CoCu2(SO)2 [Element O, Element Co, Element O]
mp-1179028 TlCu3PbSe4 [Element Tl, Element Cu, Element Cu]
mp-1181585 CsHfCu3Se4 [Element Hf, Element Cu, Element Cu]
mp-1178644 ZnGaCu3Se4 [Element Ga, Element Cu, Element Cu]
mp-1182227 BaGaCu3Se4 [Element Ga, Element Cu, Element Cu]
mp-1178804 VCu3HgSe4 [Element V, Element Cu, Element Cu]
mp-1178697 YCu3PbSe4 [Element Y, Element Cu, Element Cu]
mp-1178806 VCdCu3Se4 [Element V, Element Cu, Element Cu]
mp-1180674 KZrCu3Se4 [Element Zr, Element Cu, Element Cu]
mp-1180884 KHfCu3Se4 [Element Hf, Element Cu, Element Cu]
mp-1180322 MgCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1223822 K3SO4F [Element K, Element K, Element F]
mp-1178753 VZnCu3Se4 [Element V, Element Cu, Element Cu]
mp-1181879 CdCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1178729 YCdCu3Se4 [Element Y, Element Cu, Element Cu]
mp-1181597 CsCu3GeSe4 [Element Cu, Element Cu, Element Ge]
mp-1078198 Ba2CoAg2(SeO)2 [Element O, Element Co, Element O]
mp-1180089 NaZrCu3Se4 [Element Zr, Element Cu, Element Cu]
mp-1181943 CaVCu3Se4 [Element V, Element Cu, Element Cu]
mp-867699 Li4TiS4 [Element Li, Element Li, Element Ti]
mp-1223830 Hf2BIr6 [Element B, Element Ir, Element Ir]
mp-1181720 CrCu3PbSe4 [Element Cr, Element Cu, Element Cu]
mp-1181874 CdGaCu3Se4 [Element Ga, Element Cu, Element Cu]
mp-1181558 CsZrCu3Se4 [Element Zr, Element Cu, Element Cu]
mp-1225046 Er2BPd6 [Element B, Element Pd, Element Pd]
mp-1182242 BaYCu3Se4 [Element Y, Element Cu, Element Cu]
mp-1228078 Ba2ZrO6 [Element Zr, Element O, Element O]
mp-9453 Sr2ZnCu2(SO)2 [Element O, Element Zn, Element O]
mp-505611 Sr2Cu2Ni(SO)2 [Element O, Element Ni, Element O]
mp-1181785 CoCu3HgSe4 [Element Co, Element Cu, Element Cu]
mp-1179860 NaCu3SnSe4 [Element Cu, Element Cu, Element Sn]
mp-1205913 Ba2FeF6 [Element F, Element Fe, Element F]
mp-1226779 Ce2BPd6 [Element B, Element Pd, Element Pd]
mp-1182175 BaInCu3Se4 [Element In, Element Cu, Element Cu]
mp-1180817 KCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1179880 NaCu3GeSe4 [Element Cu, Element Cu, Element Ge]
mp-20942 Ba2TlCuO5 [Element Cu, Element O, Element O]
mp-1179752 RbCu3SnSe4 [Element Cu, Element Cu, Element Sn]
mp-1179174 SrAlCu3Se4 [Element Al, Element Cu, Element Cu]
mp-1225365 Eu2BPd6 [Element B, Element Pd, Element Pd]
mp-1179676 RbZrCu3Se4 [Element Zr, Element Cu, Element Cu]
mp-1232337 K2CuNi2(SO)2 [Element O, Element Cu, Element O]
mp-1178645 ZnInCu3Se4 [Element In, Element Cu, Element Cu]
mp-1179014 SrVCu3Se4 [Element V, Element Cu, Element Cu]
mp-1181468 Cu3NiHgSe4 [Element Cu, Element Cu, Element Ni]
mp-1179901 NaCu3NiSe4 [Element Cu, Element Cu, Element Ni]
mp-1179697 RbTiCu3Se4 [Element Ti, Element Cu, Element Cu]
mp-1180995 InCu3HgSe4 [Element In, Element Cu, Element Cu]
mp-1181716 CrCu3HgSe4 [Element Cr, Element Cu, Element Cu]
mp-1181881 CdCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1225050 Er2BPt6 [Element B, Element Pt, Element Pt]
mp-1180796 KCu3SnSe4 [Element Cu, Element Cu, Element Sn]
mp-1182890 AlCu3PbSe4 [Element Al, Element Cu, Element Cu]
mp-1078720 Pt(NCl)4 [Element Cl, Element Pt, Element Cl]
mp-1182880 AlCu3HgSe4 [Element Al, Element Cu, Element Cu]
mp-1182878 AlCdCu3Se4 [Element Al, Element Cu, Element Cu]
mp-1211279 La2Fe2S2O3 [Element O, Element Fe, Element Fe]
mp-1178642 ZnCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1224072 In2Ni6C [Element C, Element Ni, Element Ni]
mp-37331 Sr2Co2O5 [Element O, Element O, Element O]
mp-1186075 Na3SO4F [Element Na, Element Na, Element F]
mp-1224829 Ga2Co6C [Element C, Element Co, Element Co]
mp-1180804 KCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1180688 KTiCu3Se4 [Element Ti, Element Cu, Element Cu]
mp-1181975 CaCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1181713 CrCdCu3Se4 [Element Cr, Element Cu, Element Cu]
mp-1181925 CaScCu3Se4 [Element Sc, Element Cu, Element Cu]
mp-1180832 KMnCu3Se4 [Element Mn, Element Cu, Element Cu]
mp-1181577 CsTiCu3Se4 [Element Ti, Element Cu, Element Cu]
mp-30883 V4Zn5 [Element Zn, Element Zn, Element Zn]
mp-1224932 Ga2Fe6C [Element C, Element Fe, Element Fe]
mp-1182006 CaCrCu3Se4 [Element Cr, Element Cu, Element Cu]
mp-1179750 RbCoCu3Se4 [Element Co, Element Cu, Element Cu]
mp-1179075 SrScCu3Se4 [Element Sc, Element Cu, Element Cu]
mp-1180689 KVCu3Se4 [Element V, Element Cu, Element Cu]
mp-1094045 Sr2CuAg2(SO)2 [Element O, Element Cu, Element O]
mp-14769 Ba2Zn3(AsO)2 [Element O, Element Zn, Element O]
mp-7112 Sr2Cu3(SO)2 [Element O, Element Cu, Element O]
mp-1217030 TiBi2(O2F)2 [Element Ti, Element O, Element O]
mp-1180842 KCu3GeSe4 [Element Cu, Element Cu, Element Ge]
mp-1181927 CaYCu3Se4 [Element Y, Element Cu, Element Cu]
mp-1094065 Sr2Co2O5 [Element Sr, Element Sr, Element O]
mp-1178710 YCu3HgSe4 [Element Y, Element Cu, Element Cu]
mp-620290 Sr2TlCuO5 [Element O, Element Cu, Element O]
mp-1179510 ScCdCu3Se4 [Element Sc, Element Cu, Element Cu]
# get bandstructure
material_id = "mp-637576"
response = requests.get("https://www.materialsproject.org/rest/v2/materials/%s/vasp/bandstructure" % material_id, params={'API_KEY': API_KEY})
for material_id in lieb_lattices.keys():
print("%s (%s)" % (lieb_lattices[material_id]['material_properties']['pretty_formula'], material_id))
display(Image(url='https://materialsproject.org/electronic_structure/bandstructure/plot/%s' % material_id))