예제 #1
0
    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)
예제 #2
0
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)
예제 #3
0
    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 = []
예제 #4
0
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))
예제 #5
0
 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)
예제 #6
0
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)
예제 #7
0
 def __init__(self, atoms):
     self.TM_list = ['Pt', 'Cu', 'Co', 'Pd', 'Fe', 'Cr', 'Rh', 'Ru']
     self.dict_EF = {}
     self.atoms = PerfectZeolite(atoms)
예제 #8
0
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