-
Notifications
You must be signed in to change notification settings - Fork 0
/
bond_length_YSrTiO_oxides.py
106 lines (89 loc) · 3.48 KB
/
bond_length_YSrTiO_oxides.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import os
import pandas as pd
from ase import neighborlist
from mpds_client import MPDSDataRetrieval, MPDSDataTypes, APIError
def calculate_neighbors(atom_dict, molecule):
"""
Calculate the number of neighbors for each atom type in the molecule.
Parameters:
atom_dict (dict): Dictionary to store the neighbor counts.
molecule (ase.Atoms): Molecule object.
Returns:
dict: Updated dictionary with neighbor counts.
"""
cutoffs = neighborlist.natural_cutoffs(molecule)
nl = neighborlist.NeighborList(cutoffs, self_interaction=False, bothways=True)
nl.update(molecule)
neighbor_counts = {atom.symbol: set() for atom in molecule if atom.symbol in atom_dict}
for i, atom in enumerate(molecule):
indices, _ = nl.get_neighbors(i)
if atom.symbol in atom_dict:
neighbor_counts[atom.symbol].add(len(indices))
for symbol, counts in neighbor_counts.items():
if symbol in atom_dict:
atom_dict[symbol].extend(list(counts))
else:
atom_dict[symbol] = list(counts)
return atom_dict
def calculate_lengths(ase_obj, element_a, element_b, limit=13):
"""
Calculate the bond lengths between two elements within a specified limit.
Parameters:
ase_obj (ase.Atoms): ASE atoms object.
element_a (str): Symbol of the first element.
element_b (str): Symbol of the second element.
limit (float): Maximum distance to consider for bond lengths.
Returns:
list: Unique bond lengths between element_a and element_b within the limit.
"""
lengths = []
for i, atom_a in enumerate(ase_obj):
if atom_a.symbol == element_a:
for j, atom_b in enumerate(ase_obj):
if element_a == element_b and j == i:
continue
if atom_b.symbol == element_b:
try:
distance = round(ase_obj.get_distance(i, j), 2)
except Exception:
continue
if distance < limit:
lengths.append(distance)
return list(set(lengths))
# Set MPDS API key
os.environ['MPDS_KEY'] = 'your_mpds_key' # INSERT_KEY
# Initialize MPDS client
client = MPDSDataRetrieval(dtype=MPDSDataTypes.PEER_REVIEWED)
# Define sets of elements to search for
element_sets = ["Y-Sr-O", "Ti-Sr-O", "Y-Ti-O", "Y-O", "Sr-O", "Ti-O"]
dataframe = pd.DataFrame(columns=['O-O'])
all_lengths = []
# Retrieve data and calculate bond lengths
for elements in element_sets:
try:
response = client.get_data(
{"elements": elements, "props": "atomic structure", "classes": "non-disordered"},
fields={'S': [
'phase_id',
'entry',
'chemical_formula',
'cell_abc',
'sg_n',
'basis_noneq',
'els_noneq'
]}
)
except APIError as e:
print(f"API Error: {e}")
continue
for item in response:
crystal = MPDSDataRetrieval.compile_crystal(item, 'ase')
if not crystal:
continue
all_lengths.extend(calculate_lengths(crystal, 'O', 'O'))
# Process and save results
dataframe['O-O'] = sorted(all_lengths)
dataframe.to_csv('SrTiOY_bondlengths_perN/sorted_O-O.csv', index=False)
dataframe['occurrence O-O'] = dataframe.groupby('O-O')['O-O'].transform('count')
dataframe.drop_duplicates('O-O', inplace=True)
dataframe.to_csv('SrTiOY_bondlengths_perN/bondLength_O-O.csv', index=False)