def check_occupancy(atoms, ref_pos, Al_pos): """ This function checks the number of close-framework atoms around some reference position (ref_pos), with an radius cutoff determined by the difference between ref_pos and Al_pos. :param ref_pos: :param Al_pos: :return: """ cf_atoms = 0 distances = mic(ref_pos - atoms.positions, atoms.cell) distances = np.linalg.norm(distances, axis=1) for dist in distances: mic(ref_pos - atoms.positions, atoms.cell) if dist <= 4: # np.linalg.norm(mic(ref_pos - Al_pos, atoms.cell)) cf_atoms += 1 return cf_atoms
def wrapped_displacement_vectors(r_x: np.ndarray, r_y: np.ndarray, lattice: np.ndarray, remove_self_interaction=True) -> np.ndarray: """ Find all displacement vectors between atom/s at position/s r_x and atom/s at position/s r_y, in the minimum image convention. wrapped_vectors = [[r0 - r0], [r1 - r0], ... [r_Ny - r_Nx]] :return wrapped_vectors: Displacement vectors between positions r_x and r_y, in the minimum image convention. """ displacement_vectors = [] for i in range(r_x.shape[0]): for j in range(r_y.shape[0]): displacement_vectors.append(r_y[j, :] - r_x[i, :]) if remove_self_interaction: zeros = (displacement_vectors == np.array([0., 0., 0.])).all(-1) non_zeros = [not x for x in zeros] displacement_vectors = np.asarray(displacement_vectors) displacement_vectors = displacement_vectors[non_zeros, :] # Apply minimum image convention to these vectors # TODO(Alex) Check this works as expected wrapped_vectors = mic(displacement_vectors, lattice, pbc=True) return wrapped_vectors
def _insert_ExtraFrameworkAtoms(self, ini_atoms, EF_atoms, mid_AlAl, ref_list=None, ref_index=None, skip_rotation=False, min_cutoff=0, max_cutoff=6, zeolite_dist_cutoff=1.5): """ Hidden function doing the insertion """ atoms, vec_translate = self.recentering_atoms(ini_atoms, mid_AlAl) mid_AlAl = np.matmul([0.5, 0.5, 0.5], atoms.cell) if skip_rotation is False: EF_atoms = self.rotate_EF_based_on_Als(atoms, EF_atoms, ref_list) EF_atoms_ini = copy.deepcopy(EF_atoms) EF_atoms_radius = self.get_cluster_radius(EF_atoms) if EF_atoms_radius == 0: # true for single atom EF-cluster EF_atoms_radius = 1.5 max_count, closest_distance = 1000, zeolite_dist_cutoff + EF_atoms_radius # radius of Si atom ~ 1.5 Ang for d_thres in np.arange(min_cutoff, max_cutoff, 0.5): count = 0 while count < max_count: my_EF_atoms = copy.deepcopy(EF_atoms_ini) u_dir, step_size = self._get_random_dir( atoms), d_thres * np.random.random_sample() trial_pos = np.array(mid_AlAl + u_dir * step_size) EF_atoms_cop = np.sum(my_EF_atoms.positions, 0) / len(my_EF_atoms) my_EF_atoms.translate(trial_pos - EF_atoms_cop) if skip_rotation is False: my_EF_atoms = self.rotate_EF_away_from_Als( my_EF_atoms, u_dir, ref_index) my_EF_atoms = self.rotate_EF_based_on_Als( atoms, my_EF_atoms, ref_list) # print(np.linalg.norm(u_dir)) EF_atoms_cop = np.sum(my_EF_atoms.positions, 0) / len(my_EF_atoms) distances = mic(EF_atoms_cop - atoms.positions, atoms.cell) distances = np.linalg.norm(distances, axis=1) if min(distances) > closest_distance: new_atoms = atoms + my_EF_atoms new_atoms.translate(-1 * vec_translate) new_atoms.wrap() return new_atoms else: count += 1 atoms.translate(-1 * vec_translate) atoms.wrap() return None
def get_cluster_radius(EF_atoms): """ This function returns the averaged distance between atoms on the extra-framework cluster and the center-of-mass coordinate, which is used to represent/approximate the cluster size. :param EF_atoms: extra-framework cluster :return: """ EF_center = EF_atoms.get_center_of_mass() distances = mic(EF_center - EF_atoms.positions, EF_atoms.cell) distances = np.linalg.norm(distances, axis=1) return np.mean(distances)
def rotate_EF_away_from_Als(self, EF_atoms, u_dir, ref_index=None): """ This function rotates the ExtraFramework atoms again, after the "rotate_EF_based_on_Als" function, such that the ExtraFramework oxygen is pointing aways from the Al-Al vector. :param EF_atoms: extra-framework atoms :param u_dir: direction to move the ExtraFramework atoms away from :param ref_index: :return: """ EF_center = EF_atoms.get_center_of_mass() if ref_index is not None: vec_ref = mic(EF_atoms.positions[ref_index] - EF_center, EF_atoms.cell) else: O_index = [ atom.index for atom in EF_atoms if atom.symbol not in self.TM_list ] vec_ref = mic(EF_atoms.positions[O_index] - EF_center, EF_atoms.cell)[0] EF_atoms.rotate(vec_ref, u_dir, center=EF_center) return EF_atoms
def get_mid_AlAl(atoms, AlAl_dist_cutoff=9): """ This function returns a coordinate in between 2Al """ Al_index = [a.index for a in atoms if a.symbol in ['Al']] shifting_dirs = [] all_coor = [[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, -1], [0, -1, 0], [-1, 0, 0], [1, 1, 1], [-1, 1, 1], [1, -1, 1], [1, 1, -1], [-1, -1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1], [1, 1, 0], [1, -1, 0], [-1, 1, 0], [-1, -1, 0], [0, 1, 1], [0, 1, -1], [0, -1, 1], [0, -1, -1], [1, 0, 1], [1, 0, -1], [-1, 0, 1], [-1, 0, -1]] cell_param = list(atoms.get_cell()) for possible_coor in all_coor: temp_vec = [ possible_coor[i] * np.array(cell_param[i]) for i in range(3) ] sum_each_dir = np.zeros(3) for i in range(3): sum_each_dir[i] = np.sum([a[i] for a in temp_vec]) shifting_dirs.append(sum_each_dir) """ # print([possible_coor[i] * np.array(cell_param[i]) for i in range(3)]) # print([np.sum(possible_coor[i] * np.array(cell_param[i]) for i in range(3))]) shifting_dirs.append(np.sum(possible_coor[i] * np.array(cell_param[i]) for i in range(3))) """ # print(shifting_dirs) assert len(all_coor) == len(shifting_dirs) Al1_positions, mid_AlAl_positions = [], [] [ Al1_positions.append(atoms.get_positions()[Al_index[0]] + possible_dir) for possible_dir in shifting_dirs ] # print(Al1_positions) for Al1_position in Al1_positions: if abs( np.linalg.norm(Al1_position - atoms.get_positions()[ Al_index[1]])) < AlAl_dist_cutoff: mid_AlAl_positions.append( mic(0.5 * (Al1_position + atoms.get_positions()[Al_index[1]]), atoms.cell, pbc=False)) return mid_AlAl_positions
def test_neighbor_kernel(): tol = 1e-7 # two atoms a = ase.Atoms('CC', positions=[[0.5, 0.5, 0.5], [1, 1, 1]], cell=[10, 10, 10], pbc=True) i, j, d = neighbor_list("ijd", a, 1.1) assert (i == np.array([0, 1])).all() assert (j == np.array([1, 0])).all() assert np.abs(d - np.array([np.sqrt(3 / 4), np.sqrt(3 / 4)])).max() < tol # test_neighbor_list for pbc in [True, False, [True, False, True]]: a = ase.Atoms('4001C', cell=[29, 29, 29]) a.set_scaled_positions( np.transpose([ np.random.random(len(a)), np.random.random(len(a)), np.random.random(len(a)) ])) j, dr, i, abs_dr, shift = neighbor_list("jDidS", a, 1.85) assert (np.bincount(i) == np.bincount(j)).all() r = a.get_positions() dr_direct = mic(r[j] - r[i], a.cell) assert np.abs(r[j] - r[i] + shift.dot(a.cell) - dr_direct).max() < tol abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1)) assert np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12) assert np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12) assert np.all(np.abs(dr - dr_direct) < 1e-12) # test_neighbor_list_atoms_outside_box for pbc in [True, False, [True, False, True]]: a = ase.Atoms('4001C', cell=[29, 29, 29]) a.set_scaled_positions( np.transpose([ np.random.random(len(a)), np.random.random(len(a)), np.random.random(len(a)) ])) a.set_pbc(pbc) a.positions[100, :] += a.cell[0, :] a.positions[200, :] += a.cell[1, :] a.positions[300, :] += a.cell[2, :] j, dr, i, abs_dr, shift = neighbor_list("jDidS", a, 1.85) assert (np.bincount(i) == np.bincount(j)).all() r = a.get_positions() dr_direct = mic(r[j] - r[i], a.cell) assert np.abs(r[j] - r[i] + shift.dot(a.cell) - dr_direct).max() < tol abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1)) assert np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12) assert np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12) assert np.all(np.abs(dr - dr_direct) < 1e-12) # test_small_cell a = ase.Atoms('C', positions=[[0.5, 0.5, 0.5]], cell=[1, 1, 1], pbc=True) i, j, dr, shift = neighbor_list("ijDS", a, 1.1) assert np.bincount(i)[0] == 6 assert (dr == shift).all() i, j = neighbor_list("ij", a, 1.5) assert np.bincount(i)[0] == 18 a.set_pbc(False) i = neighbor_list("i", a, 1.1) assert len(i) == 0 a.set_pbc([True, False, False]) i = neighbor_list("i", a, 1.1) assert np.bincount(i)[0] == 2 a.set_pbc([True, False, True]) i = neighbor_list("i", a, 1.1) assert np.bincount(i)[0] == 4 # test_out_of_cell_small_cell a = ase.Atoms('CC', positions=[[0.5, 0.5, 0.5], [1.1, 0.5, 0.5]], cell=[1, 1, 1], pbc=False) i1, j1, r1 = neighbor_list("ijd", a, 1.1) a.set_cell([2, 1, 1]) i2, j2, r2 = neighbor_list("ijd", a, 1.1) assert (i1 == i2).all() assert (j1 == j2).all() assert np.abs(r1 - r2).max() < tol # test_out_of_cell_large_cell a = ase.Atoms('CC', positions=[[9.5, 0.5, 0.5], [10.1, 0.5, 0.5]], cell=[10, 10, 10], pbc=False) i1, j1, r1 = neighbor_list("ijd", a, 1.1) a.set_cell([20, 10, 10]) i2, j2, r2 = neighbor_list("ijd", a, 1.1) assert (i1 == i2).all() assert (j1 == j2).all() assert np.abs(r1 - r2).max() < tol # test_hexagonal_cell for sx in range(3): a = ase.lattice.hexagonal.Graphite('C', latticeconstant=(2.5, 10.0), size=[sx + 1, sx + 1, 1]) i = neighbor_list("i", a, 1.85) assert np.all(np.bincount(i) == 3) # test_first_neighbors i = [1, 1, 1, 1, 3, 3, 3] assert (first_neighbors(5, i) == np.array([0, 0, 4, 4, 7, 7])).all() i = [0, 1, 2, 3, 4, 5] assert (first_neighbors(6, i) == np.array([0, 1, 2, 3, 4, 5, 6])).all() # test_multiple_elements a = molecule('HCOOH') a.center(vacuum=5.0) i = neighbor_list("i", a, 1.85) assert (np.bincount(i) == np.array([2, 3, 1, 1, 1])).all() cutoffs = {(1, 6): 1.2} i = neighbor_list("i", a, cutoffs) assert (np.bincount(i) == np.array([0, 1, 0, 0, 1])).all() cutoffs = {(6, 8): 1.4} i = neighbor_list("i", a, cutoffs) assert (np.bincount(i) == np.array([1, 2, 1])).all() cutoffs = {('H', 'C'): 1.2, (6, 8): 1.4} i = neighbor_list("i", a, cutoffs) assert (np.bincount(i) == np.array([1, 3, 1, 0, 1])).all() cutoffs = [0.0, 0.9, 0.0, 0.5, 0.5] i = neighbor_list("i", a, cutoffs) assert (np.bincount(i) == np.array([0, 1, 0, 0, 1])).all() cutoffs = [0.7, 0.9, 0.7, 0.5, 0.5] i = neighbor_list("i", a, cutoffs) assert (np.bincount(i) == np.array([2, 3, 1, 1, 1])).all() # test_noncubic a = bulk("Al", cubic=False) i, j, d = neighbor_list("ijd", a, 3.1) assert (np.bincount(i) == np.array([12])).all() assert np.abs(d - [2.86378246] * 12).max() < tol # test pbc nat = 10 atoms = ase.Atoms(numbers=range(nat), cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6), (1.3, 2.0, -0.1)]) atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1) for p1 in range(2): for p2 in range(2): for p3 in range(2): atoms.set_pbc((p1, p2, p3)) i, j, d, D, S = neighbor_list("ijdDS", atoms, atoms.numbers * 0.2 + 0.5) c = np.bincount(i, minlength=len(atoms)) atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1)) i2, j2, d2, D2, S2 = neighbor_list("ijdDS", atoms2, atoms2.numbers * 0.2 + 0.5) c2 = np.bincount(i2, minlength=len(atoms)) c2.shape = (-1, nat) dd = d.sum() * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2.sum() dr = np.linalg.solve( atoms.cell.T, (atoms.positions[1] - atoms.positions[0]).T).T + np.array( [0, 0, 3]) assert abs(dd) < 1e-10 assert not (c2 - c).any() c = 0.0058 i, j, d = primitive_neighbor_list('ijd', [True, True, True], np.eye(3) * 7.56, np.array([[0, 0, 0], [0, 0, 0.99875]]), [c, c], self_interaction=False, use_scaled_positions=True) assert np.all(i == [0, 1]) assert np.all(j == [1, 0]) assert np.allclose(d, [0.00945, 0.00945]) # Empty atoms object i, D, d, j, S = neighbor_list("iDdjS", ase.Atoms(), 1.0) assert i.dtype == int assert j.dtype == int assert d.dtype == float assert D.dtype == float assert S.dtype == int assert i.shape == (0, ) assert j.shape == (0, ) assert d.shape == (0, ) assert D.shape == (0, 3) assert S.shape == (0, 3) # Check that only a scalar (not a tuple) is returned if we request a single # argument. i = neighbor_list("i", ase.Atoms(), 1.0) assert i.dtype == int assert i.shape == (0, )
def get_d2min_config(config0, config, config_format, cutoff, dimension=2): """ Get the d2min field of a configuration refer to one configuration. Args: config0: str, reference configuration, should be supported by ASE.io config: str, current configuration config_format: str, format of configuration, e.g. 'lammps-dump' cutoff: double, cutoff to build neighbor list Return: Natom array of tuple (d2min, J, eta_s) sorted in the order of atom id. """ # read atoms from configurations atoms0 = read(config0, format=config_format) atoms = read(config, format=config_format) if dimension == 2: atoms0.set_pbc([True, True, False]) atoms.set_pbc([True, True, False]) elif dimension == 3: atoms0.set_pbc(True) atoms.set_pbc(True) #natoms = len(atoms0.positions) d2mins = [] eta_ss = [] Js = [] # build neighbour list on reference configuration using cutoff # neighbour list is sorted according to i ilist, jlist, Dlist0 = neighbor_list('ijD', atoms0, cutoff) nbonds = len(ilist) bonds0 = [] bonds = [] current_id = 0 cell = atoms.get_cell() #neighbors = [] #neighbors.append(atoms0.positions[0][:2]) for i, j, D0 in zip(ilist, jlist, Dlist0): if i == current_id: #neighbors.append(atoms0.positions[j][:2]) #print("i:",i) #print("j:",j) #print("D0:",D0) bonds0.append(D0[:dimension]) dr = atoms.positions[j] - atoms.positions[i] dr = mic(dr, cell) #distance = np.sqrt(sum(dr*dr)) #print("distance:",distance) bonds.append(dr[:dimension]) else: d2min, J, eta_s = get_d2min(bonds0, bonds) d2mins.append(d2min) eta_ss.append(eta_s) Js.append(J) bonds0.clear() bonds.clear() bonds0.append(D0[:dimension]) dr = atoms.positions[j] - atoms.positions[i] dr = mic(dr, cell) bonds.append(dr[:dimension]) current_id = i # for the last atom d2min, J, eta_s = get_d2min(bonds0, bonds) d2mins.append(d2min) eta_ss.append(eta_s) Js.append(J) return (d2mins, Js, eta_ss)
def find_descriptor(file): #read file into ASE atoms object my_atoms = read(file) symbols = my_atoms.get_chemical_symbols() #find nearest neighbour vectors FirstAtom, SecondAtom, vects = nl.neighbor_list(['i', 'j', 'D'], my_atoms, 4.25, self_interaction=False) #ensure periodic boundary conditions are kept cell = my_atoms.get_cell() newvects = nl.mic(vects, cell, pbc=[True, True, True]) #work out symmetry functions for each particle descriptors = [] for i in range(len(symbols)): #find indices of neighburs of i indices = [a for a, x in enumerate(FirstAtom) if x == i] #find vectors between i and its neighbours neigh_vec = np.array([newvects[b] for b in indices]) #sum each function over all the neighbours f1 = 0 f2 = 0 s1 = 0 s2 = 0 s3 = 0 t1 = 0 t2 = 0 t3 = 0 t4 = 0 fo1 = 0 fo2 = 0 fo3 = 0 fo4 = 0 fo5 = 0 ff1 = 0 ff2 = 0 ff3 = 0 ff4 = 0 ff5 = 0 ff6 = 0 bfo = 0 #for each neighbouring particle to particle i: for j, n in enumerate(neigh_vec): #normalise the vector connecting i to j vector = n / np.linalg.norm(n) #split into x, y and z x, y, z = vector[0], vector[1], vector[2] #Work out all symmetry functions first_1 = 0.5 * x + 0.866025 * y first_2 = z f1 += first_1 f2 += first_2 second_1 = 0.540062 * x**2 - 0.801784 * x * y + 0.0771517 * y**2 - 0.617213 * z**2 second_2 = 0.92582 * x * y + 0.534522 * y**2 - 0.534522 * z**2 second_3 = 0.707107 * x * z + 1.22474 * y * z s1 += second_1 s2 += second_2 s3 += second_3 third_1 = 0.53619 * x**3 + 0.121136 * x**2 * y - 1.32882 * x * y**2 + 0.121136 * y**3 - 0.279751 * x * z**2 - 0.484544 * y * z**2 third_2 = 0.312772 * x**2 * y + 0.722315 * x * y**2 + 0.312772 * y**3 - 0.722315 * x * z**2 - 1.25109 * y * z**2 third_3 = 1.12916 * x**2 * z - 1.15045 * x * y * z + 0.464948 * y**2 * z - 0.531369 * z**3 third_4 = 1.78227 * x * y * z + 1.02899 * y**2 * z - 0.342997 * z**3 t1 += third_1 t2 += third_2 t3 += third_3 t4 += third_4 fourth_1 = 0.285044 * x**4 + 0.542539 * x**3 * y - 0.432264 * x**2 * y**2 - 0.97657 * x * y**3 + 0.15975 * y**4 - 1.278 * x**2 * z**2 + 1.30209 * x * y * z**2 - 0.526235 * y**2 * z**2 + 0.300706 * z**4 fourth_2 = 1.19161 * x**3 * y - 0.893343 * x**2 * y**2 - 0.63434 * x * y**3 + 0.16087 * y**4 + 0.893343 * x**2 * z**2 - 1.67181 * x * y * z**2 - 0.0718782 * y**2 * z**2 - 0.136911 * z**4 fourth_3 = 1.14953 * x**3 * z + 0.48431 * x**2 * y * z - 2.33014 * x * y**2 * z + 0.48431 * y**3 * z - 0.372822 * x * z**3 - 0.645746 * y * z**3 fourth_4 = 0.518321 * x**2 * y**2 + 0.598506 * x * y**3 + 0.172774 * y**4 - 0.518321 * x**2 * z**2 - 1.79552 * x * y * z**2 - 1.55496 * y**2 * z**2 + 0.345547 * z**4 fourth_5 = 0.854242 * x**2 * y * z + 1.97279 * x * y**2 * z + 0.854242 * y**3 * z - 0.657596 * x * z**3 - 1.13899 * y * z**3 fo1 += fourth_1 fo2 += fourth_2 fo3 += fourth_3 fo4 += fourth_4 fo5 += fourth_5 fifth_1 = 0.240391 * x**5 - 0.509292 * x**4 * y - 0.876962 * x**3 * y**2 + 1.23302 * x**2 * y**3 - 0.077379 * x * y**4 - 0.0589707 * y**5 - 1.52695 * x**3 * z**2 - 0.643317 * x**2 * y * z**2 + 3.09516 * x * y**2 * z**2 - 0.643317 * y**3 * z**2 + 0.247613 * x * z**4 + 0.428878 * y * z**4 fifth_2 = 0.96686 * x**4 * y + 0.964265 * x**3 * y**2 - 1.72842 * x**2 * y**3 - 0.727203 * x * y**4 + 0.234432 * y**5 - 0.964265 * x**3 * z**2 - 0.615905 * x**2 * y * z**2 + 1.47042 * x * y**2 * z**2 - 0.615905 * y**3 * z**2 + 0.237062 * x * z**4 + 0.410603 * y * z**4 fifth_3 = 0.900562 * x**4 * z + 0.400687 * x**3 * y * z - 0.0495722 * x**2 * y**2 * z - 2.00344 * x * y**3 * z + 0.437888 * y**4 * z - 1.7846 * x**2 * z**3 + 1.60275 * x * y * z**3 - 0.859252 * y**2 * z**3 + 0.264385 * z**5 fifth_4 = 0.17967 * x**3 * y**2 + 0.518662 * x**2 * y**3 + 0.419229 * x * y**4 + 0.103732 * y**5 - 0.17967 * x**3 * z**2 - 1.55599 * x**2 * y * z**2 - 3.05439 * x * y**2 * z**2 - 1.55599 * y**3 * z**2 + 0.598899 * x * z**4 + 1.03732 * y * z**4 fifth_5 = 3.13679 * x**3 * y * z - 2.06432 * x**2 * y**2 * z - 1.33807 * x * y**3 * z + 0.519245 * y**4 * z + 0.688106 * x**2 * z**3 - 1.79872 * x * y * z**3 - 0.350385 * y**2 * z**3 - 0.0337721 * z**5 fifth_6 = 1.77394 * x**2 * y**2 * z + 2.04837 * x * y**3 * z + 0.591312 * y**4 * z - 0.591312 * x**2 * z**3 - 2.04837 * x * y * z**3 - 1.77394 * y**2 * z**3 + 0.236525 * z**5 ff1 += fifth_1 ff2 += fifth_2 ff3 += fifth_3 ff4 += fifth_4 ff5 += fifth_5 ff6 += fifth_6 beta_fourth = 0.365148 * x**4 - 1.09545 * x**2 * y**2 + 0.365148 * y**4 - 1.09545 * x**2 * z**2 - 1.09545 * y**2 * z**2 + 0.365148 * z**4 bfo += beta_fourth #arrange all functions at each order into vector, and find magnitude of each vector first_order = np.linalg.norm(np.array([f1, f2])) second_order = np.linalg.norm(np.array([s1, s2, s3])) third_order = np.linalg.norm(np.array([t1, t2, t3, t4])) fourth_order = np.linalg.norm(np.array([fo1, fo2, fo3, fo4, fo5])) fifth_order = np.linalg.norm(np.array([ff1, ff2, ff3, ff4, ff5, ff6])) beta_fourth_order = np.linalg.norm(np.array([bfo])) #arrange descriptors into list of 6 components desc = [ first_order, second_order, third_order, fourth_order, fifth_order, beta_fourth_order ] #append descriptor for particle i into overall descriptor list descriptors.append(desc) #write parameters to seperate file to be used for machine learning with open('quenched_sym_run0-19.txt', 'ab') as file: pickle.dump(descriptors, file) return descriptors
# test_neighbor_list for pbc in [True, False, [True, False, True]]: a = ase.Atoms('4001C', cell=[29, 29, 29]) a.set_scaled_positions( np.transpose([ np.random.random(len(a)), np.random.random(len(a)), np.random.random(len(a)) ])) j, dr, i, abs_dr, shift = neighbor_list("jDidS", a, 1.85) assert (np.bincount(i) == np.bincount(j)).all() r = a.get_positions() dr_direct = mic(r[j] - r[i], a.cell) assert np.abs(r[j] - r[i] + shift.dot(a.cell) - dr_direct).max() < tol abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1)) abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1)) assert np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12) assert np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12) assert np.all(np.abs(dr - dr_direct) < 1e-12) # test_neighbor_list_atoms_outside_box for pbc in [True, False, [True, False, True]]: a = ase.Atoms('4001C', cell=[29, 29, 29]) a.set_scaled_positions( np.transpose([
vec_translate = np.matmul([0.5, 0.5, 0.5], atoms.get_cell()) - TM_pos atoms.translate(vec_translate) atoms.wrap() Al_index = [atom.index for atom in atoms if atom.symbol == 'Al'] TM_index = [atom.index for atom in atoms if atom.symbol == TM_type] TM_pos = atoms.get_positions()[TM_index] vec = np.random.normal(size=(3, )) vec = vec / np.linalg.norm(vec) oh_pos = [TM_pos[0] + vec * 2, TM_pos[0] + vec * 3] oh_atoms = Atoms('OH', positions=oh_pos) oh_cop = np.sum(oh_atoms.positions, 0) / len(oh_atoms) distances = mic(oh_cop - oh_atoms.positions, atoms.cell) distances = np.linalg.norm(distances, axis=1) while min(distances) < tol: vec = np.random.normal(size=(3, )) vec = vec / np.linalg.norm(vec) oh_pos = [TM_pos[0] + vec * 2, TM_pos[0] + vec * 3] oh_cop = np.sum(oh_atoms.positions, 0) / len(oh_atoms) oh_atoms.translate(oh_pos - oh_cop) oh_cop = np.sum(oh_atoms.positions, 0) / len(oh_atoms) distances = mic(oh_cop - oh_atoms.positions, atoms.cell) distances = np.linalg.norm(distances, axis=1) new_atoms = atoms + Atoms('OH', positions=oh_pos)
def obtain_parameters(file): atomsGeTe = read(file) symbols = atomsGeTe.get_chemical_symbols() FirstAtom, SecondAtom, vects = nl.neighbor_list(['i', 'j', 'D'], atomsGeTe, 4.25, self_interaction=False) cell = atomsGeTe.get_cell() newvects = nl.mic(vects, cell, pbc=[True, True, True]) descriptors = [] # This returns the seperated Ge Te vectors between their repective nearest neighbours for j in range(len(symbols)): indices = [c for c, atom in enumerate(FirstAtom) if atom == j] vectors = np.array([newvects[i] for i in indices]) ord1_fn_1 = [] ord1_fn_2 = [] ord2_fn_1 = [] ord2_fn_2 = [] ord2_fn_3 = [] ord3_fn_1 = [] ord3_fn_2 = [] ord3_fn_3 = [] ord3_fn_4 = [] ord4_fn_1 = [] ord4_fn_2 = [] ord4_fn_3 = [] ord4_fn_4 = [] ord4_fn_5 = [] ord5_fn_1 = [] ord5_fn_2 = [] ord5_fn_3 = [] ord5_fn_4 = [] ord5_fn_5 = [] ord5_fn_6 = [] b_ord4_fn_1 = [] #List of the symmetry adapted functions for alpha and beta GeTe for a, i in enumerate(vectors): mag_vector = np.linalg.norm(i) x, y, z = i[0] / mag_vector, i[1] / mag_vector, i[2] / mag_vector o1_f1 = 0.5 * x**1 + 0.866025 * y**1 o1_f2 = 1 * z**1 o2_f1 = 0.540062 * x**2 + -0.801784 * x**1 * y**1 + 0.0771517 * y**2 + -0.617213 * z**2 o2_f2 = 0.92582 * x**1 * y**1 + 0.534522 * y**2 + -0.534522 * z**2 o2_f3 = 0.707107 * x**1 * z**1 + 1.22474 * y**1 * z**1 o3_f1 = 0.53619 * x**3 + 0.121136 * x**2 * y**1 + -1.32882 * x**1 * y**2 + 0.121136 * y**3 + -0.279751 * x**1 * z**2 + -0.484544 * y**1 * z**2 o3_f2 = 0.312772 * x**2 * y**1 + 0.722315 * x**1 * y**2 + 0.312772 * y**3 + -0.722315 * x**1 * z**2 + -1.25109 * y**1 * z**2 o3_f3 = 1.12916 * x**2 * z**1 + -1.15045 * x**1 * y**1 * z**1 + 0.464948 * y**2 * z**1 + -0.531369 * z**3 o3_f4 = 1.78227 * x**1 * y**1 * z**1 + 1.02899 * y**2 * z**1 + -0.342997 * z**3 o4_f1 = +0.285044 * x**4 + 0.542539 * x**3 * y**1 + -0.432264 * x**2 * y**2 + -0.97657 * x**1 * y**3 + 0.15975 * y**4 + -1.278 * x**2 * z**2 + 1.30209 * x**1 * y**1 * z**2 + -0.526235 * y**2 * z**2 + 0.300706 * z**4 o4_f2 = +1.19161 * x**3 * y**1 + -0.893343 * x**2 * y**2 + -0.63434 * x**1 * y**3 + 0.16087 * y**4 + 0.893343 * x**2 * z**2 + -1.67181 * x**1 * y**1 * z**2 + -0.0718782 * y**2 * z**2 + -0.136911 * z**4 o4_f3 = +1.14953 * x**3 * z**1 + 0.48431 * x**2 * y**1 * z**1 + -2.33014 * x**1 * y**2 * z**1 + 0.48431 * y**3 * z**1 + -0.372822 * x**1 * z**3 + -0.645746 * y**1 * z**3 o4_f4 = +0.518321 * x**2 * y**2 + 0.598506 * x**1 * y**3 + 0.172774 * y**4 + -0.518321 * x**2 * z**2 + -1.79552 * x**1 * y**1 * z**2 + -1.55496 * y**2 * z**2 + 0.345547 * z**4 o4_f5 = +0.854242 * x**2 * y**1 * z**1 + 1.97279 * x**1 * y**2 * z**1 + 0.854242 * y**3 * z**1 + -0.657596 * x**1 * z**3 + -1.13899 * y**1 * z**3 o5_f1 = +0.240391 * x**5 + -0.509292 * x**4 * y**1 + -0.876962 * x**3 * y**2 + 1.23302 * x**2 * y**3 + -0.077379 * x**1 * y**4 + -0.0589707 * y**5 + -1.52695 * x**3 * z**2 + -0.643317 * x**2 * y**1 * z**2 + 3.09516 * x**1 * y**2 * z**2 + -0.643317 * y**3 * z**2 + 0.247613 * x**1 * z**4 + 0.428878 * y**1 * z**4 o5_f2 = +0.96686 * x**4 * y**1 + 0.964265 * x**3 * y**2 + -1.72842 * x**2 * y**3 + -0.727203 * x**1 * y**4 + 0.234432 * y**5 + -0.964265 * x**3 * z**2 + -0.615905 * x**2 * y**1 * z**2 + 1.47042 * x**1 * y**2 * z**2 + -0.615905 * y**3 * z**2 + 0.237062 * x**1 * z**4 + 0.410603 * y**1 * z**4 o5_f3 = +0.900562 * x**4 * z**1 + 0.400687 * x**3 * y**1 * z**1 + -0.0495722 * x**2 * y**2 * z**1 + -2.00344 * x**1 * y**3 * z**1 + 0.437888 * y**4 * z**1 + -1.7846 * x**2 * z**3 + 1.60275 * x**1 * y**1 * z**3 + -0.859252 * y**2 * z**3 + 0.264385 * z**5 o5_f4 = +0.17967 * x**3 * y**2 + 0.518662 * x**2 * y**3 + 0.419229 * x**1 * y**4 + 0.103732 * y**5 + -0.17967 * x**3 * z**2 + -1.55599 * x**2 * y**1 * z**2 + -3.05439 * x**1 * y**2 * z**2 + -1.55599 * y**3 * z**2 + 0.598899 * x**1 * z**4 + 1.03732 * y**1 * z**4 o5_f5 = +3.13679 * x**3 * y**1 * z**1 + -2.06432 * x**2 * y**2 * z**1 + -1.33807 * x**1 * y**3 * z**1 + 0.519245 * y**4 * z**1 + 0.688106 * x**2 * z**3 + -1.79872 * x**1 * y**1 * z**3 + -0.350385 * y**2 * z**3 + -0.0337721 * z**5 o5_f6 = +1.77394 * x**2 * y**2 * z**1 + 2.04837 * x**1 * y**3 * z**1 + 0.591312 * y**4 * z**1 + -0.591312 * x**2 * z**3 + -2.04837 * x**1 * y**1 * z**3 + -1.77394 * y**2 * z**3 + 0.236525 * z**5 b_o4_f1 = +0.365148 * x**4 + -1.09545 * x**2 * y**2 + 0.365148 * y**4 + -1.09545 * x**2 * z**2 + -1.09545 * y**2 * z**2 + 0.365148 * z**4 # symmetry adapted functions will be calculated for one neighour ord1_fn_1.append(o1_f1) ord1_fn_2.append(o1_f2) ord2_fn_1.append(o2_f1) ord2_fn_2.append(o2_f2) ord2_fn_3.append(o2_f3) ord3_fn_1.append(o3_f1) ord3_fn_2.append(o3_f2) ord3_fn_3.append(o3_f3) ord3_fn_4.append(o3_f4) ord4_fn_1.append(o4_f1) ord4_fn_2.append(o4_f2) ord4_fn_3.append(o4_f3) ord4_fn_4.append(o4_f4) ord4_fn_5.append(o4_f5) ord5_fn_1.append(o5_f1) ord5_fn_2.append(o5_f2) ord5_fn_3.append(o5_f3) ord5_fn_4.append(o5_f4) ord5_fn_5.append(o5_f5) ord5_fn_6.append(o5_f6) b_ord4_fn_1.append(b_o4_f1) # this will append each set of values to a list #This returns the sum of all the neighbours for each symmetry adapted function s11 = sum(ord1_fn_1) s12 = sum(ord1_fn_2) s21 = sum(ord2_fn_1) s22 = sum(ord2_fn_2) s23 = sum(ord2_fn_3) s31 = sum(ord3_fn_1) s32 = sum(ord3_fn_2) s33 = sum(ord3_fn_3) s34 = sum(ord3_fn_4) s41 = sum(ord4_fn_1) s42 = sum(ord4_fn_2) s43 = sum(ord4_fn_3) s44 = sum(ord4_fn_4) s45 = sum(ord4_fn_5) s51 = sum(ord5_fn_1) s52 = sum(ord5_fn_2) s53 = sum(ord5_fn_3) s54 = sum(ord5_fn_4) s55 = sum(ord5_fn_5) s56 = sum(ord5_fn_6) sb1 = sum(b_ord4_fn_1) #This calucates the magnitude of each of the symmetry adapted function and concatenates them into one descriptor component_1 = np.sqrt(s11**2 + s12**2) component_2 = np.sqrt(s21**2 + s22**2 + s23**2) component_3 = np.sqrt(s31**2 + s32**2 + s33**2 + s34**2) component_4 = np.sqrt(s41**2 + s42**2 + s43**2 + s44**2 + s45**2) component_5 = np.sqrt(s51**2 + s52**2 + s53**2 + s54**2 + s55**2 + s56**2) component_6 = np.sqrt(sb1**2) descr = [ component_1, component_2, component_3, component_4, component_5, component_6 ] descriptors.append(descr) #This function output a 500 componet 1d array, with each element containing a 6 componet descriptor for each particle in the configuration with open('symmetry_adapted_GeTe_quenched.txt', 'ab') as filehandle: # store the data as binary data stream pickle.dump(descriptors, filehandle) return descriptors