Statistiques
| Branche: | Tag: | Révision :

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