def test_register_with_parent(self): with self.subTest(msg='test simple case, no additions'): parent = PerfectZeolite.make('BEA') child = Zeolite.make('BEA') child = child.retag_self() child.register_with_parent(parent) self.assertEqual(parent.index_mapper, child.index_mapper) self.assertEqual(parent, child.parent_zeotype) self.assertIn(child.name, child.index_mapper.names) with self.subTest(msg='test additions'): parent = PerfectZeolite.make('BEA') additions_dict = copy.deepcopy(parent.additions) child = Zeolite.make('BEA') child = child.add_atoms( Atoms("H2", positions=[[0, 0, 0], [1, 1, 1]]), 'H2').delete_atoms([1, 2, 3, 4]) ads_map = child.build_additions_map() child.additions = additions_dict child = child.retag_self() child.register_with_parent(parent, ads_map) self.assertEqual(parent.index_mapper, child.index_mapper) self.assertEqual(parent, child.parent_zeotype) self.assertIn(child.name, child.index_mapper.names) name_list = [] for key in ads_map: name_list.extend(list(ads_map[key])) for name in name_list: self.assertIn(name, child.index_mapper.names)
def main(): # input_data_dir = '/Users/dda/Box/Kulkarni/data/sn_bea_tmpo_structures/' # output_data_dir = '/Users/dda/Box/Kulkarni/data/sn_bea_tmpo_structures/output' # make sure to add / at end of path name to avoid annoying bug input_data_dir = '/Users/dda/Desktop/t29_tmpo_fix/' output_data_dir = '/Users/dda/Desktop/t29_tmpo_fix/output/' glob_cmd = os.path.join(input_data_dir, '**/*.traj') traj_files = glob.glob(glob_cmd, recursive=True) print(traj_files) for traj_file in traj_files: z = PerfectZeolite(read(traj_file)) tmpo = find_tmpo(z) tin_index = [a.index for a in z if a.symbol == 'Sn'][0] cluster_indices = Cluster.get_oh_cluster_multi_t_sites(z, [tin_index]) if len(tmpo) != 0: cluster_indices = list(set(cluster_indices).union(set(tmpo))) else: cluster_indices = list(cluster_indices) if None in cluster_indices: cluster_indices.remove(None) # fixes bug that shouldn't exist print(cluster_indices) cluster, od = z.get_cluster(cluster_indices=cluster_indices) cluster = cluster.cap_atoms() folder_path = traj_file.split(input_data_dir)[-1].split( os.path.basename(traj_file))[0] output_dir_path = os.path.join(output_data_dir, folder_path) output_filepath = os.path.join(output_dir_path, 'cluster.traj') Path(output_dir_path).mkdir(exist_ok=True, parents=True) write(output_filepath, cluster) print("wrote cluster to ", output_filepath)
def __init__(self, iza_code=None, optimized_zeolite_path=None, user_input_path=None): """ This is an extra-framework class :param iza_code: 3 letter code for the zeolite structures (IZA database) """ if iza_code is not None: self.EFzeolite = Zeolite.make(iza_code) if optimized_zeolite_path is not None: read_vasp(optimized_zeolite_path, Zeolite.make(iza_code)) if user_input_path is not None: # self.EFzeolite = read(user_input_path, '0') self.EFzeolite = Zeolite( PerfectZeolite.build_from_cif_with_labels( filepath=user_input_path)) self.t_site_indices = {} self.t_site_indices_count = {} self.traj_1Al = [] self.traj_2Al = [] self.count_all_Al_pairs = 0 self.TM_list = ['Pt', 'Cu', 'Co', 'Pd', 'Fe', 'Cr', 'Rh', 'Ru'] self.dict_1Al_replaced = {} self.dict_2Al_replaced = {} self.T_site_pair = [] self.T_index_pair = []
def main(): cif_dir = "/Users/dda/Code/MAZE-sim/data/BEA.cif" zeolite = PerfectZeolite.build_from_cif_with_labels(cif_dir) print('t_site_to_atom_indices', zeolite._site_to_atom_indices) print('atom_indices_to_t_site', zeolite._atom_indices_to_site) atom_types = zeolite.get_atom_types() for key, val in atom_types.items(): print(key, val) indices, count = zeolite.count_elements() print('atom type count', dict(count))
def test_init_with_no_arguments(self): my_zeotype = PerfectZeolite() # tests inheritance self.assertIsInstance(my_zeotype, PerfectZeolite) self.assertIsInstance(my_zeotype, Atoms) # tests empty list attributes # tests corretly defined parameters self.assertEqual(my_zeotype._site_to_atom_indices, None) self.assertEqual(my_zeotype._atom_indices_to_site, None) self.assertEqual('parent', my_zeotype.name) self.assertEqual(my_zeotype.parent_zeotype, my_zeotype) self.assertNotEqual(my_zeotype.index_mapper, None)
import os from maze.zeolite import PerfectZeolite from maze.io_zeolite import * if __name__ == "__main__": data_path = '/Users/dda/Code/MAZE-sim/data/' cif_path = os.path.join(data_path, 'BEA.cif') output_path = os.path.join(data_path, 'my_first_zeotype') my_zeotype = PerfectZeolite.build_from_cif_with_labels(cif_path) print(my_zeotype.index_mapper.main_index) cluster, od = my_zeotype.get_cluster(1, 10, 10) # data_dir = os.path.join(Path(os.getcwd()).parent, 'data') # output_traj = os.path.join(data_dir, 'test.traj') # cif_dir = os.path.join(data_dir, 'BEA.cif') # zeolite = Zeotype.build_from_cif_with_labels(cif_dir) save_zeolites(output_path, [my_zeotype, cluster, od]) new_dict = read_zeotypes(output_path + '.zeo') print(new_dict) print(new_dict['parent']) print(new_dict['parent'].index_mapper.main_index) # Trajectory(output_traj,'w', zeolite)
def __init__(self, atoms): self.TM_list = ['Pt', 'Cu', 'Co', 'Pd', 'Fe', 'Cr', 'Rh', 'Ru'] self.dict_EF = {} self.atoms = PerfectZeolite(atoms)
class ExtraFrameworkAnalyzer(object): def __init__(self, atoms): self.TM_list = ['Pt', 'Cu', 'Co', 'Pd', 'Fe', 'Cr', 'Rh', 'Ru'] self.dict_EF = {} self.atoms = PerfectZeolite(atoms) @property def EF_bond_vectors(self): return self.get_all_bonds() @property def EF_angles(self): return self.get_all_angles() @staticmethod def recentering_atoms(atoms, pos_to_center): """ This function recenters the atoms object by translating the the input position "pos_to_center" to the center of the cell. :param atoms: zeolite backbone with two Al inserted :param pos_to_center: some positions to be centered :return: recentered atoms object, translation vector """ vec_translate = np.matmul([0.5, 0.5, 0.5], atoms.get_cell()) - pos_to_center atoms.translate(vec_translate) atoms.wrap() return atoms, vec_translate """ def get_extraframework_atoms(self): #TODO: MORE GENERAL EXTRA FRAMEWORK DETECTION (CUFRRENTLY LIMITED TO TM-O-TM) index_EF_TM = [a.index for a in self.atoms if a.symbol in self.TM_list] index_Al = [a.index for a in self.atoms if a.symbol == 'Al'] assert len(index_EF_TM) == 2 assert len(index_Al) == 2 # self.atoms.update_nl(1.2) need larger cutoff for tracking ZOCu oxygens TM_neigh_list = np.concatenate((self.atoms.neighbor_list.get_neighbors(index_EF_TM[0])[0], self.atoms.neighbor_list.get_neighbors(index_EF_TM[1])[0])) Al_neigh_list = np.concatenate((self.atoms.neighbor_list.get_neighbors(index_Al[0])[0], self.atoms.neighbor_list.get_neighbors(index_Al[1])[0])) # print(TM_neigh_list, Al_neigh_list) # This is wrong! Not always return desired O index! centering_o = [[x for x in TM_neigh_list if list(TM_neigh_list).count(x) > 1][0]] # print(centering_o) o_between_T_Cu = [val for val in TM_neigh_list if val in Al_neigh_list and self.atoms[val].symbol == 'O'] # print(o_between_T_Cu) self.centering_atom_index = centering_o[0] assert len(centering_o) == 1 assert self.atoms[centering_o].symbols == 'O' EF_indices = [index_EF_TM] EF_indices.extend(centering_o) EF_symbols = [self.atoms[index_EF_TM[0]].symbol] EF_symbols.extend('O') self.EF_indices = list(centering_o) self.EF_indices.extend([value for value in index_EF_TM]) for count, index in enumerate(EF_indices): self.dict_EF_atoms[EF_symbols[count]] = index self.o_between_T_Cu = o_between_T_Cu # self.dict_EF_atoms['OZ'] = self.o_between_T_Cu """ def get_extraframework_cluster(self, predefined_centering_o=None): """ extract extra-framework cluster including Cu-O-Cu, 2 Al, and 8 O around the Als (13 atoms total) :param predefined_centering_o: get the mode of all possible centering O index by training a bunch of configurations for the same zeolite, to remove bias. """ index_EF_TM = [a.index for a in self.atoms if a.symbol in self.TM_list] index_Al = [a.index for a in self.atoms if a.symbol == 'Al'] Al_neigh_list = np.concatenate( (self.atoms.neighbor_list.get_neighbors(index_Al[0])[0], self.atoms.neighbor_list.get_neighbors(index_Al[1])[0])) Al_neigh_list = [ x for x in Al_neigh_list if self.atoms[x].symbol == 'O' ] if predefined_centering_o is not None: centering_o = copy.copy(predefined_centering_o) else: TM_neigh_list = np.concatenate( (self.atoms.neighbor_list.get_neighbors(index_EF_TM[0])[0], self.atoms.neighbor_list.get_neighbors(index_EF_TM[1])[0])) centering_o = [[ x for x in TM_neigh_list if list(TM_neigh_list).count(x) > 1 and x not in Al_neigh_list ][0]] assert len(index_EF_TM) == 2 assert len(index_Al) == 2 assert len(centering_o) == 1 assert len(Al_neigh_list) == 8 return Al_neigh_list + index_Al + index_EF_TM + centering_o """ def get_extraframework_cluster(self): # extraframework atoms, 2 Al and surrounding 8 O index_EF_TM = [a.index for a in self.atoms if a.symbol in self.TM_list] index_Al = [a.index for a in self.atoms if a.symbol == 'Al'] assert len(index_EF_TM) == 2 assert len(index_Al) == 2 TM_neigh_list = np.concatenate((self.atoms.neighbor_list.get_neighbors(index_EF_TM[0])[0], self.atoms.neighbor_list.get_neighbors(index_EF_TM[1])[0])) Al_neigh_list = np.concatenate((self.atoms.neighbor_list.get_neighbors(index_Al[0])[0], self.atoms.neighbor_list.get_neighbors(index_Al[1])[0])) centering_o = [288] #[[x for x in TM_neigh_list if list(TM_neigh_list).count(x) > 1][0]] self.centering_atom_index = centering_o[0] assert len(centering_o) == 1 assert self.atoms[centering_o].symbols == 'O' self.EF_indices = list(centering_o) self.EF_indices.extend([value for value in index_EF_TM]) return np.unique(list(Al_neigh_list) + centering_o + index_Al + index_EF_TM) """ def get_O_index_between_atoms(self, index_1, index_2, scale=3.0, O_count=2): # find the closest O in between two atoms since nl of ASE is so annoying self.atoms.update_nl(scale) nl_1 = self.atoms.neighbor_list.get_neighbors(index_1)[0] nl_2 = self.atoms.neighbor_list.get_neighbors(index_2)[0] index_O = [ val for val in nl_1 if val in nl_2 and self.atoms[val].symbol == 'O' ] index_list = [] dist_list = [] for index in index_O: index_list.append(index) dist_list.append( 0.5 * (self.atoms.get_distance(index_1, index, mic=True) + self.atoms.get_distance(index_2, index, mic=True))) unsorted_dist_list = copy.copy(dist_list) dist_list.sort() closed_O_index = [] if O_count == 1: for index, element in enumerate(unsorted_dist_list): if element == dist_list[0]: closed_O_index.append(index_list[index]) else: for index, element in enumerate(unsorted_dist_list): if element == dist_list[0]: closed_O_index.append(index_list[index]) if element == dist_list[1]: closed_O_index.append(index_list[index]) return closed_O_index def get_extraframework(self): index_Al = [a.index for a in self.atoms if a.symbol == 'Al'] index_Cu = [a.index for a in self.atoms if a.symbol == 'Cu'] index_Al1, index_Al2 = index_Al[0], index_Al[1] if self.atoms.get_distance(index_Al1, index_Cu[0], mic=True) < self.atoms.get_distance( index_Al1, index_Cu[1], mic=True): index_Cu1, index_Cu2 = index_Cu[0], index_Cu[1] else: index_Cu1, index_Cu2 = index_Cu[1], index_Cu[0] centering_O = [ 288 ] # [108] # self.get_O_index_between_atoms(index_Cu1, index_Cu2, scale=0.85, O_count=1) Cu1_O_neigh = self.get_O_index_between_atoms(index_Al1, index_Cu1) Cu2_O_neigh = self.get_O_index_between_atoms(index_Al2, index_Cu2) self.dict_EF['Cu1'] = [index_Cu1, [index_Al1] + centering_O ] # [index_Cu1, Cu1_O_neigh+centering_O] self.dict_EF['Cu2'] = [index_Cu2, [index_Al2] + centering_O ] # [index_Cu2, Cu2_O_neigh+centering_O] self.dict_EF['O'] = [centering_O[0], [index_Cu1, index_Cu2]] def get_all_bonds(self): dict_EF_bonds = {} for atom_tag, index_list in self.dict_EF.items(): atom_index = index_list[0] neighbor_index = index_list[1] d_vec = [] d_mag = [] for index in neighbor_index: d_vec.append( self.atoms.get_distance(index, atom_index, mic=True, vector=True)) d_mag.append( self.atoms.get_distance(index, atom_index, mic=True, vector=False)) dict_EF_bonds[atom_tag] = [d_vec, d_mag] return dict_EF_bonds def get_all_angles(self): dict_EF_angles = {} for atom_tag, index_list in self.dict_EF.items(): atom_index = index_list[0] """ neighbor_index = index_list[1][0:2] if 'Cu' in atom_tag: angle = [] for index in neighbor_index: angle.append(self.atoms.get_angle(index, atom_index, index_list[1][2], mic=True) / 180 * np.pi) # O, Cu, O else: angle = [self.atoms.get_angle(neighbor_index[0], atom_index, neighbor_index[1], mic=True) / 180 * np.pi] """ neighbor_index = index_list[1] angle = [ self.atoms.get_angle( neighbor_index[0], atom_index, neighbor_index[1], mic=True) / 180 * np.pi ] dict_EF_angles[atom_tag] = angle return dict_EF_angles def get_angle_force_dir(self): angle_dir = [] dict_EF_bonds = self.get_all_bonds() for atom_tag, val in dict_EF_bonds.items(): vector = val[0] angle_dir.append(-0.5 * (vector[0] + vector[1])) return angle_dir def get_forces(self): dict_EF_forces = {} for atom_tag, index_list in self.dict_EF.items(): atom_index = index_list[0] f_vec = self.atoms.calc.results['forces'][ atom_index] # self.atoms.get_forces()[atom_index] f_mag = np.linalg.norm(f_vec) dict_EF_forces[atom_tag] = [f_vec, f_mag] return dict_EF_forces @staticmethod def morse_force(r, a, e, rm): return 2 * a * e * np.exp(-a * (r - rm)) * (1 - np.exp(-a * (r - rm))) @staticmethod def harmonic(theta, k, k1, theta_o): return 2 * k * (theta - theta_o) + 3 * k1 * (theta - theta_o)**2 def get_predicted_forces(self, param): O_param = param[0] Cu_param = param[1] dict_EF_predicted_forces = {} dict_EF_bonds = self.get_all_bonds() dict_EF_angles = self.get_all_angles() angle_dir = self.get_angle_force_dir() dict_morse = {} for atom_tag, dist_list in dict_EF_bonds.items(): d_vec, d_mag, f = [], [], [0, 0, 0] for vec, mag in zip(dist_list[0], dist_list[1]): d_vec.append(vec) d_mag.append(mag) if 'Cu' in atom_tag: my_param = Cu_param f += self.morse_force( d_mag[0], * my_param[0:3]) * d_vec[0] / d_mag[0] # for Cu-O-Z bond f += self.morse_force( d_mag[1], * my_param[6:9]) * d_vec[1] / d_mag[1] # for Cu-O-Cu bond if 'O' in atom_tag: my_param = O_param for count, vec in enumerate(d_vec): f += self.morse_force(d_mag[count], * my_param[0:3]) * vec / d_mag[count] dict_morse[atom_tag] = f for index, (atom_tag, angle_list) in enumerate(dict_EF_angles.items()): if 'Cu' in atom_tag: my_param = Cu_param[3:6] else: my_param = O_param[3:6] f = np.array( self.harmonic(angle_list[0], *my_param) * angle_dir[index]) / np.linalg.norm(angle_dir[index]) dict_EF_predicted_forces[atom_tag] = dict_morse[atom_tag] + f return dict_EF_predicted_forces