def ternary_smact_combos(position1, position2, position3, threshold=8): """ Combinatorially generate Pymatgen Species compositions using SMACT when up to three different lists are needed to draw species from (e.g. Ternary metal halides.) Args: position(n) (list of species): Species to be considered iteratively for each position. threshold (int): Max stoichiometry threshold. Returns: species_comps (list): Compositions as tuples of Pymatgen Species objects. """ initial_comps_list = [] for sp1, sp2, an in tqdm(itertools.product(position1, position2, position3)): e1, oxst1 = sp1.symbol, int(sp1.oxi_state) eneg1 = Element(e1).pauling_eneg e2, oxst2 = sp2.symbol, int(sp2.oxi_state) eneg2 = Element(e2).pauling_eneg e3, oxst3 = an.symbol, int(an.oxi_state) eneg3 = Element(e3).pauling_eneg symbols = [e1, e2, e3] ox_states = [oxst1, oxst2, oxst3] cn_e, cn_r = neutral_ratios(ox_states, threshold=threshold) if cn_e: enegs = [eneg1, eneg2, eneg3] eneg_ok = pauling_test(ox_states, enegs, symbols=symbols, repeat_cations=False) if eneg_ok: for ratio in cn_r: comp = (symbols, ox_states, list(ratio)) initial_comps_list.append(comp) print('Number of compositions before reduction: {}'.format( len(initial_comps_list))) # Create a list of pymatgen species for each comp print('Converting to Pymatgen Species...') species_comps = [] for i in tqdm(initial_comps_list): comp = {} for sym, ox, ratio in zip(i[0], i[1], i[2]): comp[Specie(sym, ox)] = ratio comp_list = [[key] * val for key, val in comp.items()] comp_list = [item for sublist in comp_list for item in sublist] species_comps.append(comp_list) # Sort and ditch duplicates print( 'Ditching duplicates (sorry to have got your hopes up with the big numbers)...' ) for i in species_comps: i.sort() i.sort(key=lambda x: x.oxi_state, reverse=True) species_comps = list(set([tuple(i) for i in species_comps])) print('Total number of new compounds unique compositions: {0}'.format( len(species_comps))) return species_comps
def check_electronegativity_2(formula): pauling_count = 0 comp = mg.Composition(formula) reduce_formula = comp.get_el_amt_dict() list_of_elements = list(reduce_formula.keys()) max_num = max(reduce_formula.values()) for i, ele_a in enumerate(list_of_elements): paul_a = smact.Element(ele_a).pauling_eneg for ox_a in smact.Element(ele_a).oxidation_states: for j, ele_b in enumerate(list_of_elements[i + 1:]): paul_b = smact.Element(ele_b).pauling_eneg for ox_b in smact.Element(ele_b).oxidation_states: # Puts elements, oxidation states and electronegativites into lists for convenience # elements = [ele_a, ele_b] oxidation_states = [ox_a, ox_b] pauling_electro = [paul_a, paul_b] # Checks if the electronegativity makes sense and if the combination is charge neutral # electroneg_makes_sense = pauling_test( oxidation_states, pauling_electro, elements) cn_e, cn_r = neutral_ratios([ox_a, ox_b], threshold=int(max_num)) if cn_e: if electroneg_makes_sense: pauling_count = pauling_count + 1 for num in cn_r: if tuple(reduce_formula.values()) == num: # print('{0:2s}{1:3d} {2:2s}{3:3d} {4:2s}{5:3d}'.format(ele_a, ox_a, ele_b, # ox_b, ele_c, ox_c)) return True print('Number of combinations = {0}'.format(pauling_count)) print("--- {0} seconds to run ---".format(time.time() - start_time)) return False
def check_electronegativity_4(formula): pauling_count = 0 comp = mg.Composition(formula) reduce_formula = comp.get_el_amt_dict() list_of_elements = list(reduce_formula.keys()) stoichs = list( np.array(list(reduce_formula.values())).astype(np.int32)[:, np.newaxis]) max_num = max(reduce_formula.values()) for i, ele_a in enumerate(list_of_elements): paul_a = smact.Element(ele_a).pauling_eneg for ox_a in smact.Element(ele_a).oxidation_states: for j, ele_b in enumerate(list_of_elements[i + 1:]): paul_b = smact.Element(ele_b).pauling_eneg for ox_b in smact.Element(ele_b).oxidation_states: for k, ele_c in enumerate(list_of_elements[i + j + 2:]): paul_c = smact.Element(ele_c).pauling_eneg for ox_c in smact.Element(ele_c).oxidation_states: for m, ele_d in enumerate( list_of_elements[i + j + k + 3:]): paul_d = smact.Element(ele_d).pauling_eneg for ox_d in smact.Element( ele_d).oxidation_states: # Puts elements, oxidation states and electronegativites into lists for convenience # elements = [ele_a, ele_b, ele_c, ele_d] oxidation_states = [ox_a, ox_b, ox_c, ox_d] pauling_electro = [ paul_a, paul_b, paul_c, paul_d ] if None in pauling_electro: print( "No pauling electronegativity data" ) return False # Checks if the electronegativity makes sense and if the combination is charge neutral # electroneg_makes_sense = pauling_test( oxidation_states, pauling_electro, elements) cn_e, cn_r = neutral_ratios( [ox_a, ox_b, ox_c, ox_d], stoichs=stoichs, threshold=int(max_num)) if cn_e: if electroneg_makes_sense: pauling_count = pauling_count + 1 for num in cn_r: if tuple(reduce_formula.values( )) == num: # print('{0:2s}{1:3d} {2:2s}{3:3d} {4:2s}{5:3d}'.format(ele_a, ox_a, ele_b, # ox_b, ele_c, ox_c)) return True # print('Number of combinations = {0}'.format(pauling_count)) # print("--- {0} seconds to run ---".format(time.time() - start_time)) return False
def check_electronegativity_7(formula): pauling_count = 0 comp = mg.Composition(formula) reduce_formula = comp.get_el_amt_dict() list_of_elements = list(reduce_formula.keys()) max_num = max(reduce_formula.values()) # for element in reduce_formula.keys(): # print(len(smact.Element(element).oxidation_states), end = ",") for i, ele_a in enumerate(list_of_elements): paul_a = smact.Element(ele_a).pauling_eneg for ox_a in smact.Element(ele_a).oxidation_states: for j, ele_b in enumerate(list_of_elements[i+1:]): paul_b = smact.Element(ele_b).pauling_eneg for ox_b in smact.Element(ele_b).oxidation_states: for k, ele_c in enumerate(list_of_elements[i+j+2:]): paul_c = smact.Element(ele_c).pauling_eneg for ox_c in smact.Element(ele_c).oxidation_states: for m, ele_d in enumerate(list_of_elements[i+j+k+3:]): paul_d = smact.Element(ele_d).pauling_eneg for ox_d in smact.Element(ele_d).oxidation_states: for n, ele_e in enumerate(list_of_elements[i+j+k+m+4:]): paul_e = smact.Element(ele_e).pauling_eneg for ox_e in smact.Element(ele_e).oxidation_states: for p, ele_f in enumerate(list_of_elements[i+j+k+m+n+5:]): paul_f = smact.Element(ele_f).pauling_eneg for ox_f in smact.Element(ele_f).oxidation_states: for q, ele_g in enumerate(list_of_elements[i+j+k+m+n+p+6:]): paul_g = smact.Element(ele_g).pauling_eneg for ox_g in smact.Element(ele_g).oxidation_states: # Puts elements, oxidation states and electronegativites into lists for convenience # elements = [ele_a, ele_b, ele_c, ele_d, ele_e, ele_f, ele_g] oxidation_states = [ox_a, ox_b, ox_c, ox_d, ox_e, ox_f, ox_g] pauling_electro = [paul_a, paul_b, paul_c, paul_d, paul_e, paul_f, paul_g] if None in pauling_electro: print("No pauling electronegativity data") return False # Checks if the electronegativity makes sense and if the combination is charge neutral # electroneg_makes_sense = pauling_test(oxidation_states, pauling_electro, elements) cn_e, cn_r = neutral_ratios([ox_a, ox_b, ox_c, ox_d, ox_e, ox_f, ox_g], threshold = int(max_num)) if cn_e: if electroneg_makes_sense: pauling_count = pauling_count + 1 for num in cn_r: if tuple(reduce_formula.values()) == num: # print('{0:2s}{1:3d} {2:2s}{3:3d} {4:2s}{5:3d}'.format(ele_a, ox_a, ele_b, # ox_b, ele_c, ox_c)) return True # print('Number of combinations = {0}'.format(pauling_count)) # print("--- {0} seconds to run ---".format(time.time() - start_time)) return False
pauling_perov = [] anion_stats = [] for C in C_list: anion_hex = 0 anion_cub = 0 anion_ort = 0 for B in B_list: for A in A_list: if B[0] != A[0]: if C[0] != A[0] and C[0] != B[0]: if int(A[1]) + int(B[1]) + 3 * int(C[1]) == 0: charge_balanced.append([A[0], B[0], C[0]]) paul_a = smact.Element(A[0]).pauling_eneg paul_b = smact.Element(B[0]).pauling_eneg paul_c = smact.Element(C[0]).pauling_eneg electroneg_makes_sense = screening.pauling_test( [A[1], B[1], C[1]], [paul_a, paul_b, paul_c]) if electroneg_makes_sense: pauling_perov.append([A[0], B[0], C[0]]) tol = (float(A[2]) + C[2]) / (np.sqrt(2) * (float(B[2]) + C[2])) if tol > 1.0: a_too_large.append([A[0], B[0], C[0]]) anion_hex = anion_hex + 1 if tol > 0.9 and tol <= 1.0: goldschmidt_cubic.append([A[0], B[0], C[0]]) anion_cub = anion_cub + 1 if tol >= 0.71 and tol < 0.9: goldschmidt_ortho.append([A[0], B[0], C[0]]) anion_ort = anion_ort + 1 if tol < 0.71: A_B_similar.append([A[0], B[0], C[0]])
raw_ion_count = raw_ion_count + 1 elements = [ele_A, ele_B, ele_C] ox_states = [ox_A, ox_B, ox_C] electronegativities = [paul_A, paul_B, paul_C] # Test for charge balance cn_e, cn_r = smact.neutral_ratios( ox_states, threshold=stoichiometry_limit) if cn_e: charge_balanced_count = charge_balanced_count + len( cn_r) # Electronegativity test electroneg_OK = screening.pauling_test( ox_states, electronegativities, elements, threshold=0.0) if electroneg_OK: electroneg_OK_count = electroneg_OK_count + len( cn_r) # Band gap test SSE_A = smact.Element(ele_A).SSE SSE_B = smact.Element(ele_B).SSE SSE_C = smact.Element(ele_C).SSE BG_1 = abs(SSE_A - SSE_B) BG_2 = abs(SSE_A - SSE_C) if (BG_1 <= BG_max) and (BG_1 >= BG_min): BG_OK_count = BG_OK_count + len(cn_r) entry = [elements, SSE_A, SSE_B, BG_1]
pauling_perov = [] anion_stats = [] for C in C_list: anion_hex = 0 anion_cub = 0 anion_ort = 0 for B in B_list: for A in A_list: if B[0] != A[0]: if C[0] != A[0] and C[0] != B[0]: if int(A[1])+int(B[1])+3*int(C[1]) == 0: charge_balanced.append([A[0],B[0],C[0]]) paul_a = smact.Element(A[0]).pauling_eneg paul_b = smact.Element(B[0]).pauling_eneg paul_c = smact.Element(C[0]).pauling_eneg electroneg_makes_sense = screening.pauling_test([A[1],B[1],C[1]], [paul_a,paul_b,paul_c]) if electroneg_makes_sense: pauling_perov.append([A[0],B[0],C[0]]) tol = (float(A[2]) + C[2])/(np.sqrt(2)*(float(B[2])+C[2])) if tol > 1.0: a_too_large.append([A[0],B[0],C[0]]) anion_hex = anion_hex+1 if tol > 0.9 and tol <= 1.0: goldschmidt_cubic.append([A[0],B[0],C[0]]) anion_cub = anion_cub + 1 if tol >= 0.71 and tol < 0.9: goldschmidt_ortho.append([A[0],B[0],C[0]]) anion_ort = anion_ort + 1 if tol < 0.71: A_B_similar.append([A[0],B[0],C[0]]) anion_stats.append([anion_hex,anion_cub,anion_ort])
for k, ele_C in enumerate(C_elements): paul_C = smact.Element(ele_C).pauling_eneg for ox_C in smact.Element(ele_C).oxidation_states: raw_ion_count = raw_ion_count + 1 elements = [ele_A, ele_B, ele_C] ox_states = [ox_A, ox_B, ox_C] electronegativities = [paul_A, paul_B, paul_C] # Test for charge balance cn_e, cn_r = smact.neutral_ratios(ox_states,threshold = stoichiometry_limit) if cn_e: charge_balanced_count = charge_balanced_count + len(cn_r) # Electronegativity test electroneg_OK = screening.pauling_test(ox_states, electronegativities, elements, threshold = 0.0) if electroneg_OK: electroneg_OK_count = electroneg_OK_count + len(cn_r) # Band gap test SSE_A = smact.Element(ele_A).SSE SSE_B = smact.Element(ele_B).SSE SSE_C = smact.Element(ele_C).SSE BG_1 = abs(SSE_A - SSE_B) BG_2 = abs(SSE_A - SSE_C) if (BG_1 <= BG_max) and (BG_1 >= BG_min): BG_OK_count = BG_OK_count + len(cn_r) entry = [elements, SSE_A, SSE_B, BG_1] if entry not in unique_ABCs: unique_ABCs.append(entry) elif (BG_2 <= BG_max) and (BG_2 >= BG_min):