def change_cell_length(atoms, space_group): print(atoms.get_atomic_numbers()) name = get_name(atoms.get_atomic_numbers()) print(name) # to do molecule1, molecule2, molecule3, molecule4 = molecule_lists( atoms)[0], molecule_lists(atoms)[1], molecule_lists( atoms)[2], molecule_lists(atoms)[3] # [1,5,9,13,17,21,etc] print(molecule1) print(molecule2) print(molecule3) print(molecule4) scaled_positions = atoms.get_scaled_positions() #print("scaled_positions: ", scaled_positions) molecule1_scaled_positions = np.array( [scaled_positions[i] for i in molecule1]) cell_params = atoms.get_cell() #print(cell_params) #print(atoms.get_positions()) a_vector, b_vector, c_vector = cell_params[0], cell_params[1], cell_params[ 2] molecule1_vectors = np.array([ faction[0] * a_vector + faction[1] * b_vector + faction[2] * c_vector for faction in molecule1_scaled_positions ]) new_atoms = atoms.copy() new_atoms.set_cell(cell_params + np.array([[1, 0, 0], [0, 1, 0], [0.1, 0, 1]]), scale_atoms=False) new_cell_params = new_atoms.get_cell() print("new_cell_params: ", new_cell_params) new_a_vector, new_b_vector, new_c_vector = new_cell_params[ 0], new_cell_params[1], new_cell_params[2] new_vectors = [] for v in molecule1_vectors: Va = np.dot( np.cross(new_b_vector, new_c_vector) / np.dot(new_a_vector, np.cross(new_b_vector, new_c_vector)), v) Vb = np.dot( np.cross(new_c_vector, new_a_vector) / np.dot(new_b_vector, np.cross(new_c_vector, new_a_vector)), v) Vc = np.dot( np.cross(new_a_vector, new_b_vector) / np.dot(new_c_vector, np.cross(new_a_vector, new_b_vector)), v) new_vectors.append([Va, Vb, Vc]) new_sclaed_positions = np.array(new_vectors) print("get_symop(): ", space_group.get_symop()) sites = [] for kind, pos in enumerate(new_sclaed_positions): for rot, trans in space_group.get_symop(): site = np.dot(rot, pos) + trans sites.append(site) print(np.array(sites)) new_positions = np.array([ faction[0] * new_a_vector + faction[1] * new_b_vector + faction[2] * new_c_vector for faction in sites ]) print(new_positions) #wire = Atoms('', # positions=[[0, L / 2, L / 2]], # cell=[d, L, L], # pbc=[1, 0, 0]) writer = Atoms(name, positions=new_positions, cell=new_atoms.get_cell(), pbc=[1, 1, 1]) #final_scaled_positions = get_equivalent_sites(new_sclaed_positions, space_group) #print("final_scaled_positions: ", final_scaled_positions) #new_atoms.set_scaled_positions(final_scaled_positions) for i in molecule1: print( writer.get_distances(i, molecule1) - atoms.get_distances(i, molecule1)) #print(atoms.get_distance(24,36, mic=False, vector=True)) #print(new_atoms.get_distance(24,36, mic=False, vector=True)) print(writer.get_cell()) return writer
def _calculate_distances(atoms: ase.Atoms, min_im_conv: bool = True, no_console: bool = False) -> np.array: '''Calculates the distances between each pair of ions By defaul it uses the minimum image convention It returns a square array 'dist_array' with the distances between ions i and j in dist_array[i][j] ''' # calculate distances between the points in A # D = atoms.get_all_distances(mic=True, simple=True) # eats up ALL the ram N=30 MAX # TODO: parallelize num_atoms = len(atoms) dist_array = np.zeros((num_atoms, num_atoms), dtype=np.float64) for i in tqdm(range(num_atoms), unit='atoms', total=num_atoms, desc='Calculating distances', disable=no_console): dist_array[i, i:num_atoms] = atoms.get_distances(i, range(i, num_atoms), mic=min_im_conv) # get the distance along the c axis divided by two # dmaxReal = atoms.cell[2][2]/2; # dist_array[dist_array > dmaxReal] = 0 # discard distances longer than dmax dist_array = dist_array + dist_array.T # make symmetrical # Ds_mic = get_all_distances(atoms) # Ds = csr_matrix(dist_array) return dist_array
a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)]) a.set_cell((9, 2, 2)) a.set_pbc((True, False, False)) # Calculate indiviually with mic=True assert a.get_distance(0, 1, mic=True) == 2 assert a.get_distance(1, 2, mic=True) == 3 assert a.get_distance(0, 2, mic=True) == 4 # Calculate indiviually with mic=False assert a.get_distance(0, 1, mic=False) == 2 assert a.get_distance(1, 2, mic=False) == 3 assert a.get_distance(0, 2, mic=False) == 5 # Calculate in groups with mic=True assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all() # Calculate in groups with mic=False assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all() # Calculate all with mic=True assert (a.get_all_distances(mic=True) == [[0, 2, 4], [2, 0, 3], [4, 3, 0]]).all() # Calculate all with mic=False assert (a.get_all_distances(mic=False) == [[0, 2, 5], [2, 0, 3], [5, 3, 0]]).all()
def take_cluster(old_conf_name, type_map, idx, jdata): cutoff = jdata['cluster_cutoff'] cutoff_hard = jdata.get('cluster_cutoff_hard', None) sys = dpdata.System(old_conf_name, fmt = 'lammps/dump', type_map = type_map) atom_names = sys['atom_names'] atom_types = sys['atom_types'] cell = sys['cells'][0] coords = sys['coords'][0] symbols = [atom_names[atom_type] for atom_type in atom_types] # detect fragment frag_numb, frag_index, graph = _crd2frag(symbols, coords, True, cell, return_bonds=True) # get_distances all_atoms = Atoms(symbols = symbols, positions = coords, pbc=True, cell=cell) all_atoms[idx].tag = 1 distances = all_atoms.get_distances(idx, range(len(all_atoms)), mic=True) distancescutoff = distances < cutoff cutoff_atoms_idx = np.where(distancescutoff)[0] if cutoff_hard is not None: distancescutoff_hard = distances < cutoff_hard cutoff_atoms_idx_hard = np.where(distancescutoff_hard)[0] # make cutoff atoms in molecules taken_atoms_idx = [] added = [] for ii in range(frag_numb): frag_atoms_idx = np.where(frag_index == ii)[0] if cutoff_hard is not None: # drop atoms out of the hard cutoff anyway frag_atoms_idx = np.intersect1d(frag_atoms_idx, cutoff_atoms_idx_hard) if np.any(np.isin(frag_atoms_idx, cutoff_atoms_idx)): if 'cluster_minify' in jdata and jdata['cluster_minify']: # support for organic species take_frag_idx=[] for aa in frag_atoms_idx: if np.any(np.isin(aa, cutoff_atoms_idx)): # atom is in the soft cutoff # pick up anyway take_frag_idx.append(aa) elif np.count_nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]==1)): # atom is between the hard cutoff and the soft cutoff # and has a single bond with the atom inside if all_atoms[aa].symbol == 'H': # for atom H: just add it take_frag_idx.append(aa) else: # for other atoms (C, O, etc.): replace it with a ghost H atom near_atom_idx = np.nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]>0))[0][0] vector = all_atoms[aa].position - all_atoms[near_atom_idx].position new_position = all_atoms[near_atom_idx].position + vector / np.linalg.norm(vector) * 1.09 added.append(Atom('H', new_position)) elif np.count_nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]>1)): # if that atom has a double bond with the atom inside # just pick up the whole fragment (within the hard cutoff) # TODO: use a more fantastic method take_frag_idx=frag_atoms_idx break else: take_frag_idx = frag_atoms_idx taken_atoms_idx.append(take_frag_idx) all_taken_atoms_idx = np.concatenate(taken_atoms_idx) # wrap cutoff_atoms = sum(added, all_atoms[all_taken_atoms_idx]) cutoff_atoms.wrap( center=coords[idx] / cutoff_atoms.get_cell_lengths_and_angles()[0: 3], pbc=True) coords = cutoff_atoms.get_positions() sys.data['coords'] = np.array([coords]) sys.data['atom_types'] = np.array(list(atom_types[all_taken_atoms_idx]) + [atom_names.index('H')]*len(added)) sys.data['atom_pref'] = np.array([cutoff_atoms.get_tags()]) for ii, _ in enumerate(atom_names): sys.data['atom_numbs'][ii] = np.count_nonzero(sys.data['atom_types']==ii) return sys
a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)]) a.set_cell((9, 2, 2)) a.set_pbc((True, False, False)) # Calculate indiviually with mic=True assert a.get_distance(0, 1, mic=True) == 2 assert a.get_distance(1, 2, mic=True) == 3 assert a.get_distance(0, 2, mic=True) == 4 # Calculate indiviually with mic=False assert a.get_distance(0, 1, mic=False) == 2 assert a.get_distance(1, 2, mic=False) == 3 assert a.get_distance(0, 2, mic=False) == 5 # Calculate in groups with mic=True assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all() # Calculate in groups with mic=False assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all() # Calculate all with mic=True assert (a.get_all_distances(mic=True) == [[0, 2, 4], [2, 0, 3], [4, 3, 0]]).all() # Calculate all with mic=False assert (a.get_all_distances(mic=False) == [[0, 2, 5], [2, 0, 3], [5, 3, 0]]).all() # Scale Distance old = a.get_distance(0, 1) a.set_distance(0, 1, 0.9, add=True, factor=True)
def test_atoms_distance(): # Setup a chain of H,O,C # H-O Dist = 2 # O-C Dist = 3 # C-H Dist = 5 with mic=False # C-H Dist = 4 with mic=True a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)]) a.set_cell((9, 2, 2)) a.set_pbc((True, False, False)) # Calculate indiviually with mic=True assert a.get_distance(0, 1, mic=True) == 2 assert a.get_distance(1, 2, mic=True) == 3 assert a.get_distance(0, 2, mic=True) == 4 # Calculate indiviually with mic=False assert a.get_distance(0, 1, mic=False) == 2 assert a.get_distance(1, 2, mic=False) == 3 assert a.get_distance(0, 2, mic=False) == 5 # Calculate in groups with mic=True assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all() # Calculate in groups with mic=False assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all() # Calculate all with mic=True assert (a.get_all_distances(mic=True) == [[0, 2, 4], [2, 0, 3], [4, 3, 0]]).all() # Calculate all with mic=False assert (a.get_all_distances(mic=False) == [[0, 2, 5], [2, 0, 3], [5, 3, 0]]).all() # Scale Distance old = a.get_distance(0, 1) a.set_distance(0, 1, 0.9, add=True, factor=True) new = a.get_distance(0, 1) diff = new - 0.9 * old assert abs(diff) < 10e-6 # Change Distance old = a.get_distance(0, 1) a.set_distance(0, 1, 0.9, add=True) new = a.get_distance(0, 1) diff = new - old - 0.9 assert abs(diff) < 10e-6
def take_cluster(old_conf_name, type_map, idx, jdata): cutoff = jdata['cluster_cutoff'] sys = dpdata.System(old_conf_name, fmt = 'lammps/dump', type_map = type_map) atom_names = sys['atom_names'] atom_types = sys['atom_types'] cell = sys['cells'][0] coords = sys['coords'][0] symbols = [atom_names[atom_type] for atom_type in atom_types] # detect fragment frag_numb, frag_index, graph = _crd2frag(symbols, coords, True, cell, return_bonds=True) # get_distances all_atoms = Atoms(symbols = symbols, positions = coords, pbc=True, cell=cell) all_atoms[idx].tag = 1 distances = all_atoms.get_distances(idx, range(len(all_atoms)), mic=True) distancescutoff = distances < cutoff cutoff_atoms_idx = np.where(distancescutoff)[0] # make cutoff atoms in molecules taken_atoms_idx = [] added = [] for ii in range(frag_numb): frag_atoms_idx = np.where(frag_index == ii)[0] if np.any(np.isin(frag_atoms_idx, cutoff_atoms_idx)): if 'cluster_minify' in jdata and jdata['cluster_minify']: # currently support C, H take_frag_idx=[] for aa in frag_atoms_idx: if np.any(np.isin(aa, cutoff_atoms_idx)): take_frag_idx.append(aa) elif np.count_nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]==1)): if all_atoms[aa].symbol == 'H': take_frag_idx.append(aa) elif all_atoms[aa].symbol == 'C': near_atom_idx = np.nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]>0))[0][0] vector = all_atoms[aa].position - all_atoms[near_atom_idx].position new_position = all_atoms[near_atom_idx].position + vector / np.linalg.norm(vector) * 1.09 added.append(Atom('H', new_position)) elif np.count_nonzero(np.logical_and(distancescutoff, graph.toarray()[aa]>1)): take_frag_idx=frag_atoms_idx break else: take_frag_idx = frag_atoms_idx taken_atoms_idx.append(take_frag_idx) all_taken_atoms_idx = np.concatenate(taken_atoms_idx) # wrap cutoff_atoms = sum(added, all_atoms[all_taken_atoms_idx]) cutoff_atoms.wrap( center=coords[idx] / cutoff_atoms.get_cell_lengths_and_angles()[0: 3], pbc=True) coords = cutoff_atoms.get_positions() sys.data['coords'] = np.array([coords]) sys.data['atom_types'] = np.array(list(atom_types[all_taken_atoms_idx]) + [atom_names.index('H')]*len(added)) sys.data['atom_pref'] = np.array([cutoff_atoms.get_tags()]) for ii, _ in enumerate(atom_names): sys.data['atom_numbs'][ii] = np.count_nonzero(sys.data['atom_types']==ii) return sys