dockonsurf / modules / add_adsorbate_euler+dissociation.py @ 86112fec
Historique | Voir | Annoter | Télécharger (9,76 ko)
1 | 86112fec | Marti Aliod Carles | #!/usr/bin/env python
|
---|---|---|---|
2 | 86112fec | Marti Aliod Carles | # -*- coding: utf-8 -*-
|
3 | 86112fec | Marti Aliod Carles | |
4 | 86112fec | Marti Aliod Carles | import sys |
5 | 86112fec | Marti Aliod Carles | import numpy as np |
6 | 86112fec | Marti Aliod Carles | import ase |
7 | 86112fec | Marti Aliod Carles | from ase import io |
8 | 86112fec | Marti Aliod Carles | from ase.io import read |
9 | 86112fec | Marti Aliod Carles | from ase.io import write |
10 | 86112fec | Marti Aliod Carles | from ase import Atom |
11 | 86112fec | Marti Aliod Carles | from ase import build |
12 | 86112fec | Marti Aliod Carles | from ase.build import add_adsorbate |
13 | 86112fec | Marti Aliod Carles | from ase import constraints |
14 | 86112fec | Marti Aliod Carles | from ase.constraints import FixAtoms |
15 | 86112fec | Marti Aliod Carles | from ase import neighborlist |
16 | 86112fec | Marti Aliod Carles | from ase.neighborlist import NeighborList |
17 | 86112fec | Marti Aliod Carles | from ase import utils |
18 | 86112fec | Marti Aliod Carles | import ase_Fe1_Fe2 |
19 | 86112fec | Marti Aliod Carles | |
20 | 86112fec | Marti Aliod Carles | if len(sys.argv) < 7 : |
21 | 86112fec | Marti Aliod Carles | print "This script has to be used with at least 6 arguments." |
22 | 86112fec | Marti Aliod Carles | print "1. Name of the file containing the surface" |
23 | 86112fec | Marti Aliod Carles | print "2. Atom number of the atom of the surface where the adsorbate will be adsorbed" |
24 | 86112fec | Marti Aliod Carles | print "3. Name of the file containing the molecule to be adsorbed" |
25 | 86112fec | Marti Aliod Carles | print "4. Atom number of the atom of the molecule that will be adsorbed of the surface" |
26 | 86112fec | Marti Aliod Carles | print "5. Distance between the molecule and the surface" |
27 | 86112fec | Marti Aliod Carles | print "6. Name of the output file" |
28 | 86112fec | Marti Aliod Carles | print "Other arguments can be added before the name of the output file :" |
29 | 86112fec | Marti Aliod Carles | print " Second atom of the molecule" |
30 | 86112fec | Marti Aliod Carles | print " phi angle (rotation around z)" |
31 | 86112fec | Marti Aliod Carles | print " theta angle (rotation around new x)" |
32 | 86112fec | Marti Aliod Carles | print " psi angle (rotation around new z) " |
33 | 86112fec | Marti Aliod Carles | sys.exit(1)
|
34 | 86112fec | Marti Aliod Carles | |
35 | 86112fec | Marti Aliod Carles | |
36 | 86112fec | Marti Aliod Carles | #############################################################
|
37 | 86112fec | Marti Aliod Carles | # Définition de la fonction permettant de calculer les angles
|
38 | 86112fec | Marti Aliod Carles | #############################################################
|
39 | 86112fec | Marti Aliod Carles | |
40 | 86112fec | Marti Aliod Carles | def get_proper_angle(v1, v2, degrees=True): |
41 | 86112fec | Marti Aliod Carles | norm_dot = np.dot(v1/np.linalg.norm(v1), v2/np.linalg.norm(v2)) |
42 | 86112fec | Marti Aliod Carles | angle = np.arccos(np.sign(norm_dot) if np.abs(norm_dot) >= 1 else norm_dot) |
43 | 86112fec | Marti Aliod Carles | return(angle*180/np.pi if degrees else angle) |
44 | 86112fec | Marti Aliod Carles | |
45 | 86112fec | Marti Aliod Carles | |
46 | 86112fec | Marti Aliod Carles | ##########################################
|
47 | 86112fec | Marti Aliod Carles | # Lecture des différents arguments de base
|
48 | 86112fec | Marti Aliod Carles | ##########################################
|
49 | 86112fec | Marti Aliod Carles | |
50 | 86112fec | Marti Aliod Carles | surface_file = sys.argv[1]
|
51 | 86112fec | Marti Aliod Carles | atom_surface = int(sys.argv[2]) |
52 | 86112fec | Marti Aliod Carles | molecule_file = sys.argv[3]
|
53 | 86112fec | Marti Aliod Carles | atom_molecule = int(sys.argv[4]) |
54 | 86112fec | Marti Aliod Carles | distance = int(sys.argv[5]) |
55 | 86112fec | Marti Aliod Carles | if len(sys.argv) < 8 : |
56 | 86112fec | Marti Aliod Carles | output = sys.argv[6]
|
57 | 86112fec | Marti Aliod Carles | |
58 | 86112fec | Marti Aliod Carles | surface = read(surface_file) |
59 | 86112fec | Marti Aliod Carles | molecule = read(molecule_file) |
60 | 86112fec | Marti Aliod Carles | |
61 | 86112fec | Marti Aliod Carles | #################################
|
62 | 86112fec | Marti Aliod Carles | # Lecture des positions de atomes
|
63 | 86112fec | Marti Aliod Carles | #################################
|
64 | 86112fec | Marti Aliod Carles | |
65 | 86112fec | Marti Aliod Carles | atom_surf_1 = surface[atom_surface].position |
66 | 86112fec | Marti Aliod Carles | x_atom_surf_1 = atom_surf_1[0]
|
67 | 86112fec | Marti Aliod Carles | y_atom_surf_1 = atom_surf_1[1]
|
68 | 86112fec | Marti Aliod Carles | z_atom_surf_1 = atom_surf_1[2]
|
69 | 86112fec | Marti Aliod Carles | |
70 | 86112fec | Marti Aliod Carles | atom_mol_1 = molecule[atom_molecule].position |
71 | 86112fec | Marti Aliod Carles | x_atom_mol_1 = atom_mol_1[0]
|
72 | 86112fec | Marti Aliod Carles | y_atom_mol_1 = atom_mol_1[1]
|
73 | 86112fec | Marti Aliod Carles | z_atom_mol_1 = atom_mol_1[2]
|
74 | 86112fec | Marti Aliod Carles | |
75 | 86112fec | Marti Aliod Carles | nb_atom_mol = int(len(molecule)) |
76 | 86112fec | Marti Aliod Carles | |
77 | 86112fec | Marti Aliod Carles | |
78 | 86112fec | Marti Aliod Carles | #######################################################
|
79 | 86112fec | Marti Aliod Carles | # Cas avec un plus grand nombre d'arguments (rotations)
|
80 | 86112fec | Marti Aliod Carles | #######################################################
|
81 | 86112fec | Marti Aliod Carles | |
82 | 86112fec | Marti Aliod Carles | |
83 | 86112fec | Marti Aliod Carles | if len(sys.argv) > 7 : |
84 | 86112fec | Marti Aliod Carles | |
85 | 86112fec | Marti Aliod Carles | #######################
|
86 | 86112fec | Marti Aliod Carles | # Lecture des arguments
|
87 | 86112fec | Marti Aliod Carles | #######################
|
88 | 86112fec | Marti Aliod Carles | |
89 | 86112fec | Marti Aliod Carles | atom_molecule_2 = int(sys.argv[6]) |
90 | 86112fec | Marti Aliod Carles | phi = int(sys.argv[7]) |
91 | 86112fec | Marti Aliod Carles | theta = int(sys.argv[8]) |
92 | 86112fec | Marti Aliod Carles | psi = int(sys.argv[9]) |
93 | 86112fec | Marti Aliod Carles | output = sys.argv[10]
|
94 | 86112fec | Marti Aliod Carles | |
95 | 86112fec | Marti Aliod Carles | theta_min = theta - 0.01
|
96 | 86112fec | Marti Aliod Carles | theta_max = theta + 0.01
|
97 | 86112fec | Marti Aliod Carles | phi_min = phi - 0.01
|
98 | 86112fec | Marti Aliod Carles | phi_max = phi + 0.01
|
99 | 86112fec | Marti Aliod Carles | psi_min = psi - 0.01
|
100 | 86112fec | Marti Aliod Carles | psi_max = psi + 0.01
|
101 | 86112fec | Marti Aliod Carles | |
102 | 86112fec | Marti Aliod Carles | atom_mol_2 = molecule[atom_molecule_2].position |
103 | 86112fec | Marti Aliod Carles | x_atom_mol_2 = atom_mol_2[0]
|
104 | 86112fec | Marti Aliod Carles | y_atom_mol_2 = atom_mol_2[1]
|
105 | 86112fec | Marti Aliod Carles | z_atom_mol_2 = atom_mol_2[2]
|
106 | 86112fec | Marti Aliod Carles | |
107 | 86112fec | Marti Aliod Carles | ##################################
|
108 | 86112fec | Marti Aliod Carles | # Rotation avec les angles d'Euler
|
109 | 86112fec | Marti Aliod Carles | ##################################
|
110 | 86112fec | Marti Aliod Carles | |
111 | 86112fec | Marti Aliod Carles | #Initialisation : placement du second atome de la molecule sur Oy
|
112 | 86112fec | Marti Aliod Carles | vect_y = [0, 1, 0] |
113 | 86112fec | Marti Aliod Carles | vect_atom_mol_2 = molecule[atom_molecule_2].position - molecule[atom_molecule].position |
114 | 86112fec | Marti Aliod Carles | angle_1 = get_proper_angle(vect_y, vect_atom_mol_2) |
115 | 86112fec | Marti Aliod Carles | if (angle_1 != 0) : |
116 | 86112fec | Marti Aliod Carles | vect_normal = np.cross(vect_y, vect_atom_mol_2) |
117 | 86112fec | Marti Aliod Carles | molecule.rotate(-angle_1, vect_normal, center=(x_atom_mol_1,y_atom_mol_1,z_atom_mol_1)) |
118 | 86112fec | Marti Aliod Carles | vect_atom_mol_2_verif = molecule[atom_molecule_2].position - molecule[atom_molecule].position |
119 | 86112fec | Marti Aliod Carles | angle_1_verif = get_proper_angle(vect_atom_mol_2_verif, vect_y) |
120 | 86112fec | Marti Aliod Carles | angle_max = 0.01
|
121 | 86112fec | Marti Aliod Carles | angle_min = -0.01
|
122 | 86112fec | Marti Aliod Carles | if (angle_1_verif < angle_min or angle_1_verif > angle_max) : |
123 | 86112fec | Marti Aliod Carles | print 'Error in initialisation' |
124 | 86112fec | Marti Aliod Carles | |
125 | 86112fec | Marti Aliod Carles | #Rotation Euler
|
126 | 86112fec | Marti Aliod Carles | molecule.euler_rotate(phi, theta, psi, center=(x_atom_mol_1,y_atom_mol_1,z_atom_mol_1)) |
127 | 86112fec | Marti Aliod Carles | |
128 | 86112fec | Marti Aliod Carles | #Correction des collisions entre la molécule et la surface
|
129 | 86112fec | Marti Aliod Carles | z_atom_surf_max = z_atom_surf_1 + 1
|
130 | 86112fec | Marti Aliod Carles | |
131 | 86112fec | Marti Aliod Carles | collision = 0.5
|
132 | 86112fec | Marti Aliod Carles | rotation_tot = 0
|
133 | 86112fec | Marti Aliod Carles | nb_atom_collision_min = 0
|
134 | 86112fec | Marti Aliod Carles | rotation_opt = 0
|
135 | 86112fec | Marti Aliod Carles | rotation_modif = 5
|
136 | 86112fec | Marti Aliod Carles | |
137 | 86112fec | Marti Aliod Carles | for i in range(0,nb_atom_mol) : |
138 | 86112fec | Marti Aliod Carles | atom_test = molecule[i].position |
139 | 86112fec | Marti Aliod Carles | z_atom_test = atom_test[2]
|
140 | 86112fec | Marti Aliod Carles | z_atom_test_final = z_atom_test - z_atom_mol_1 + z_atom_surf_1 + distance |
141 | 86112fec | Marti Aliod Carles | if (z_atom_test_final < z_atom_surf_max) :
|
142 | 86112fec | Marti Aliod Carles | collision = 1
|
143 | 86112fec | Marti Aliod Carles | nb_atom_collision_min += 1
|
144 | 86112fec | Marti Aliod Carles | if collision == 1 : |
145 | 86112fec | Marti Aliod Carles | print 'Collision between the molecule and the surface - modification of theta angle' |
146 | 86112fec | Marti Aliod Carles | |
147 | 86112fec | Marti Aliod Carles | vect_z = [0, 0, 1] |
148 | 86112fec | Marti Aliod Carles | |
149 | 86112fec | Marti Aliod Carles | while (collision == 1 and rotation_tot < 354) : |
150 | 86112fec | Marti Aliod Carles | vect_atom_mol_2_post_euler = molecule[atom_molecule_2].position - molecule[atom_molecule].position |
151 | 86112fec | Marti Aliod Carles | |
152 | 86112fec | Marti Aliod Carles | if (vect_atom_mol_2_post_euler[0] != 0 and vect_atom_mol_2_post_euler[1] != 0) : |
153 | 86112fec | Marti Aliod Carles | vect_rotation_theta = np.cross(vect_atom_mol_2_post_euler, vect_z) |
154 | 86112fec | Marti Aliod Carles | else :
|
155 | 86112fec | Marti Aliod Carles | vect_rotation_theta = [0.0001, 0.0001 , 0] |
156 | 86112fec | Marti Aliod Carles | molecule.rotate(rotation_modif, vect_rotation_theta, center=(x_atom_mol_1,y_atom_mol_1,z_atom_mol_1)) |
157 | 86112fec | Marti Aliod Carles | rotation_tot += 5
|
158 | 86112fec | Marti Aliod Carles | |
159 | 86112fec | Marti Aliod Carles | collision = 0
|
160 | 86112fec | Marti Aliod Carles | nb_atom_collision = 0
|
161 | 86112fec | Marti Aliod Carles | |
162 | 86112fec | Marti Aliod Carles | for i in range(0,nb_atom_mol) : |
163 | 86112fec | Marti Aliod Carles | atom_test = molecule[i].position |
164 | 86112fec | Marti Aliod Carles | z_atom_test = atom_test[2]
|
165 | 86112fec | Marti Aliod Carles | z_atom_test_final = z_atom_test - z_atom_mol_1 + z_atom_surf_1 + distance |
166 | 86112fec | Marti Aliod Carles | if (z_atom_test_final < z_atom_surf_max) :
|
167 | 86112fec | Marti Aliod Carles | nb_atom_collision += 1
|
168 | 86112fec | Marti Aliod Carles | collision = 1
|
169 | 86112fec | Marti Aliod Carles | if (nb_atom_collision < nb_atom_collision_min) :
|
170 | 86112fec | Marti Aliod Carles | nb_atom_collision_min = nb_atom_collision |
171 | 86112fec | Marti Aliod Carles | rotation_opt = rotation_tot |
172 | 86112fec | Marti Aliod Carles | |
173 | 86112fec | Marti Aliod Carles | if nb_atom_collision_min != 0 : |
174 | 86112fec | Marti Aliod Carles | rotation_tot_2 = 0
|
175 | 86112fec | Marti Aliod Carles | rotation_opt_2 = 0
|
176 | 86112fec | Marti Aliod Carles | |
177 | 86112fec | Marti Aliod Carles | while (collision == 1 and rotation_tot_2 < 354) : |
178 | 86112fec | Marti Aliod Carles | vect_atom_mol_2_post_euler = molecule[atom_molecule_2].position - molecule[atom_molecule].position |
179 | 86112fec | Marti Aliod Carles | molecule.rotate(rotation_modif, vect_atom_mol_2_post_euler, center=(x_atom_mol_1,y_atom_mol_1,z_atom_mol_1)) |
180 | 86112fec | Marti Aliod Carles | rotation_tot_2 += 5
|
181 | 86112fec | Marti Aliod Carles | |
182 | 86112fec | Marti Aliod Carles | collision = 0
|
183 | 86112fec | Marti Aliod Carles | nb_atom_collision = 0
|
184 | 86112fec | Marti Aliod Carles | |
185 | 86112fec | Marti Aliod Carles | for i in range(0,nb_atom_mol) : |
186 | 86112fec | Marti Aliod Carles | atom_test = molecule[i].position |
187 | 86112fec | Marti Aliod Carles | z_atom_test = atom_test[2]
|
188 | 86112fec | Marti Aliod Carles | z_atom_test_final = z_atom_test - z_atom_mol_1 + z_atom_surf_1 + distance |
189 | 86112fec | Marti Aliod Carles | if (z_atom_test_final < z_atom_surf_max) :
|
190 | 86112fec | Marti Aliod Carles | nb_atom_collision += 1
|
191 | 86112fec | Marti Aliod Carles | collision = 1
|
192 | 86112fec | Marti Aliod Carles | if (nb_atom_collision < nb_atom_collision_min) :
|
193 | 86112fec | Marti Aliod Carles | nb_atom_collision_min = nb_atom_collision |
194 | 86112fec | Marti Aliod Carles | rotation_opt_2 = rotation_tot_2 |
195 | 86112fec | Marti Aliod Carles | |
196 | 86112fec | Marti Aliod Carles | if collision == 0 : |
197 | 86112fec | Marti Aliod Carles | print 'Collision corrected' |
198 | 86112fec | Marti Aliod Carles | elif collision == 1 : |
199 | 86112fec | Marti Aliod Carles | print 'Error: the collision could not be corrected' |
200 | 86112fec | Marti Aliod Carles | pos1 = output.rfind('/')
|
201 | 86112fec | Marti Aliod Carles | pos = pos1 + 1
|
202 | 86112fec | Marti Aliod Carles | num_coll=output[pos:] |
203 | 86112fec | Marti Aliod Carles | j = output[:pos1] |
204 | 86112fec | Marti Aliod Carles | pos2 = j.rfind('/')
|
205 | 86112fec | Marti Aliod Carles | molecule_directory = j[:pos2] |
206 | 86112fec | Marti Aliod Carles | fichier = open("%s/errors" % molecule_directory , "a") |
207 | 86112fec | Marti Aliod Carles | fichier.write("Adsorption %s : ERROR the collision could not be corrected\n" % num_coll )
|
208 | 86112fec | Marti Aliod Carles | fichier.close() |
209 | 86112fec | Marti Aliod Carles | |
210 | 86112fec | Marti Aliod Carles | |
211 | 86112fec | Marti Aliod Carles | ##########################################
|
212 | 86112fec | Marti Aliod Carles | # Adsorption de la molecule sur la surface
|
213 | 86112fec | Marti Aliod Carles | ##########################################
|
214 | 86112fec | Marti Aliod Carles | |
215 | 86112fec | Marti Aliod Carles | add_adsorbate(surface, molecule, distance, (x_atom_surf_1,y_atom_surf_1), mol_index=atom_molecule) |
216 | 86112fec | Marti Aliod Carles | |
217 | 86112fec | Marti Aliod Carles | out=output+".xyz"
|
218 | 86112fec | Marti Aliod Carles | write(out, surface) |
219 | 86112fec | Marti Aliod Carles | |
220 | 86112fec | Marti Aliod Carles | |
221 | 86112fec | Marti Aliod Carles | ############################
|
222 | 86112fec | Marti Aliod Carles | # Dissociation si necessaire
|
223 | 86112fec | Marti Aliod Carles | ############################
|
224 | 86112fec | Marti Aliod Carles | |
225 | 86112fec | Marti Aliod Carles | if collision == 0 : |
226 | 86112fec | Marti Aliod Carles | surface = read(surface_file) |
227 | 86112fec | Marti Aliod Carles | molecule_reminder = molecule |
228 | 86112fec | Marti Aliod Carles | |
229 | 86112fec | Marti Aliod Carles | list_cutoffs = utils.natural_cutoffs(molecule) |
230 | 86112fec | Marti Aliod Carles | nl=NeighborList(list_cutoffs, self_interaction=False, bothways=True) |
231 | 86112fec | Marti Aliod Carles | |
232 | 86112fec | Marti Aliod Carles | nl.update(molecule) |
233 | 86112fec | Marti Aliod Carles | neighbor_indices, offsets = nl.get_neighbors(atom_molecule) |
234 | 86112fec | Marti Aliod Carles | |
235 | 86112fec | Marti Aliod Carles | symbols = molecule.get_chemical_symbols() |
236 | 86112fec | Marti Aliod Carles | |
237 | 86112fec | Marti Aliod Carles | neighbors_symbols=[] |
238 | 86112fec | Marti Aliod Carles | for i in neighbor_indices: |
239 | 86112fec | Marti Aliod Carles | neighbors_symbols.append(symbols[i]) |
240 | 86112fec | Marti Aliod Carles | |
241 | 86112fec | Marti Aliod Carles | nb_neighbors = len(neighbor_indices)
|
242 | 86112fec | Marti Aliod Carles | |
243 | 86112fec | Marti Aliod Carles | diss=0
|
244 | 86112fec | Marti Aliod Carles | for i in range(0,nb_neighbors): |
245 | 86112fec | Marti Aliod Carles | if neighbors_symbols[i] == "H": |
246 | 86112fec | Marti Aliod Carles | diss=1
|
247 | 86112fec | Marti Aliod Carles | H_atom=neighbor_indices[i] #nb of the H atom
|
248 | 86112fec | Marti Aliod Carles | print "Dissociation possible" |
249 | 86112fec | Marti Aliod Carles | |
250 | 86112fec | Marti Aliod Carles | if diss == 1: |
251 | 86112fec | Marti Aliod Carles | list_cutoffs_surface = utils.natural_cutoffs(surface) |
252 | 86112fec | Marti Aliod Carles | nl2=NeighborList(list_cutoffs_surface, self_interaction=False, bothways=True) |
253 | 86112fec | Marti Aliod Carles | nl2.update(surface) |
254 | 86112fec | Marti Aliod Carles | neighbor_indices_surf, offsets_surf = nl2.get_neighbors(atom_surface) |
255 | 86112fec | Marti Aliod Carles | symbols_surf = surface.get_chemical_symbols() |
256 | 86112fec | Marti Aliod Carles | for i in neighbor_indices_surf: |
257 | 86112fec | Marti Aliod Carles | surface = read(surface_file) |
258 | 86112fec | Marti Aliod Carles | molecule = molecule_reminder |
259 | 86112fec | Marti Aliod Carles | neighbor_surf_coord = surface[i].position |
260 | 86112fec | Marti Aliod Carles | coord_H_atom=molecule[H_atom].position |
261 | 86112fec | Marti Aliod Carles | if (neighbor_surf_coord[2] > z_atom_surf_1-1 and symbols_surf[i] == "O"): |
262 | 86112fec | Marti Aliod Carles | vector_H_diss=[neighbor_surf_coord[0]-coord_H_atom[0], neighbor_surf_coord[1]-coord_H_atom[1], neighbor_surf_coord[2]+1-coord_H_atom[2]] |
263 | 86112fec | Marti Aliod Carles | translation_matrix_dissociation=[] |
264 | 86112fec | Marti Aliod Carles | for k in range (0, nb_atom_mol): |
265 | 86112fec | Marti Aliod Carles | if k != H_atom:
|
266 | 86112fec | Marti Aliod Carles | translation_matrix_dissociation.append([0,0,0]) |
267 | 86112fec | Marti Aliod Carles | else:
|
268 | 86112fec | Marti Aliod Carles | translation_matrix_dissociation.append(vector_H_diss) |
269 | 86112fec | Marti Aliod Carles | molecule.translate(translation_matrix_dissociation) |
270 | 86112fec | Marti Aliod Carles | add_adsorbate(surface, molecule, distance, (x_atom_surf_1,y_atom_surf_1), mol_index=atom_molecule) |
271 | 86112fec | Marti Aliod Carles | output_diss = output + "_diss_" + str(i) + ".xyz" |
272 | 86112fec | Marti Aliod Carles | write(output_diss, surface) |
273 | 86112fec | Marti Aliod Carles | |
274 | 86112fec | Marti Aliod Carles | |
275 | 86112fec | Marti Aliod Carles | |
276 | 86112fec | Marti Aliod Carles | |
277 | 86112fec | Marti Aliod Carles |