Révision dadc6016
b/modules/screening.py | ||
---|---|---|
24 | 24 |
def vect_avg(vects): |
25 | 25 |
"""Computes the element-wise mean of a set of vectors. |
26 | 26 |
|
27 |
@param vects: np.ndarray with shape (num_vectors, length_vector). |
|
27 |
@param vects: list of lists-like: containing the vectors (num_vectors, |
|
28 |
length_vector). |
|
28 | 29 |
@return: vector average computed doing the element-wise mean. |
29 | 30 |
""" |
30 | 31 |
from utilities import try_command |
31 | 32 |
err = "vect_avg parameter vects must be a list-like, able to be converted" \ |
32 | 33 |
" np.array" |
33 |
vects = try_command(np.array, [(ValueError, err)], vects)
|
|
34 |
if len(vects.shape) == 1:
|
|
35 |
return vects
|
|
34 |
array = try_command(np.array, [(ValueError, err)], vects)
|
|
35 |
if len(array.shape) == 1:
|
|
36 |
return array
|
|
36 | 37 |
else: |
37 |
num_vects = vects.shape[1]
|
|
38 |
return np.array([np.average(vects[:, i]) for i in range(num_vects)])
|
|
38 |
num_vects = array.shape[1]
|
|
39 |
return np.array([np.average(array[:, i]) for i in range(num_vects)])
|
|
39 | 40 |
|
40 | 41 |
|
41 | 42 |
def get_atom_coords(atoms: ase.Atoms, ctrs_list): |
... | ... | |
65 | 66 |
return np.array(coords) |
66 | 67 |
|
67 | 68 |
|
68 |
def add_adsorbate(slab, adsorbate, surf_pos, mol_pos, height, offset=None,
|
|
69 |
def add_adsorbate(slab, adsorbate, site_coord, ctr_coord, height, offset=None,
|
|
69 | 70 |
norm_vect=(0, 0, 1)): |
70 | 71 |
"""Add an adsorbate to a surface. |
71 | 72 |
|
... | ... | |
76 | 77 |
@param slab: ase.Atoms object containing the coordinates of the surface |
77 | 78 |
@param adsorbate: ase.Atoms object containing the coordinates of the |
78 | 79 |
adsorbate. |
79 |
@param surf_pos: The coordinates of the adsorption site on the surface.
|
|
80 |
@param mol_pos: The coordinates of the adsorption center in the molecule.
|
|
81 |
@param height: The height above the surface |
|
80 |
@param site_coord: The coordinates of the adsorption site on the surface.
|
|
81 |
@param ctr_coord: The coordinates of the adsorption center in the molecule.
|
|
82 |
@param height: The height above the surface where to adsorb.
|
|
82 | 83 |
@param offset: Offsets the adsorbate by a number of unit cells. Mostly |
83 | 84 |
useful when adding more than one adsorbate. |
84 | 85 |
@param norm_vect: The vector perpendicular to the surface. |
85 | 86 |
""" |
86 | 87 |
info = slab.info.get('adsorbate_info', {}) |
87 |
pos = np.array([0.0, 0.0, 0.0]) # (x, y, z) part
|
|
88 |
pos = np.array([0.0, 0.0, 0.0]) # part of absolute coordinates
|
|
88 | 89 |
spos = np.array([0.0, 0.0, 0.0]) # part relative to unit cell |
89 |
norm_vect = np.array(norm_vect) / np.linalg.norm(norm_vect) |
|
90 |
norm_vect_u = np.array(norm_vect) / np.linalg.norm(norm_vect)
|
|
90 | 91 |
if offset is not None: |
91 | 92 |
spos += np.asarray(offset, float) |
92 |
if isinstance(surf_pos, str):
|
|
93 |
if isinstance(site_coord, str):
|
|
93 | 94 |
# A site-name: |
94 | 95 |
if 'sites' not in info: |
95 | 96 |
raise TypeError('If the atoms are not made by an ase.build ' |
96 | 97 |
'function, position cannot be a name.') |
97 |
if surf_pos not in info['sites']:
|
|
98 |
raise TypeError('Adsorption site %s not supported.' % surf_pos)
|
|
99 |
spos += info['sites'][surf_pos]
|
|
98 |
if site_coord not in info['sites']:
|
|
99 |
raise TypeError('Adsorption site %s not supported.' % site_coord)
|
|
100 |
spos += info['sites'][site_coord]
|
|
100 | 101 |
else: |
101 |
pos += surf_pos
|
|
102 |
pos += site_coord
|
|
102 | 103 |
if 'cell' in info: |
103 | 104 |
cell = info['cell'] |
104 | 105 |
else: |
... | ... | |
112 | 113 |
else: |
113 | 114 |
# Assume it is a string representing a single Atom |
114 | 115 |
ads = ase.Atoms([ase.Atom(adsorbate)]) |
115 |
pos += height * norm_vect |
|
116 |
pos += height * norm_vect_u
|
|
116 | 117 |
# Move adsorbate into position |
117 |
ads.translate(pos - mol_pos)
|
|
118 |
ads.translate(pos - ctr_coord)
|
|
118 | 119 |
# Attach the adsorbate |
119 | 120 |
slab.extend(ads) |
120 | 121 |
|
... | ... | |
132 | 133 |
|
133 | 134 |
|
134 | 135 |
def adsorb_confs(conf_list, surf, ads_ctrs, sites, algo, num_pts, neigh_ctrs, |
135 |
norm_vect): |
|
136 |
norm_vect, coll_bttm):
|
|
136 | 137 |
"""Generates a number of adsorbate-surface structure coordinates. |
137 | 138 |
|
138 | 139 |
Given a list of conformers, a surface, a list of atom indices (or list of |
... | ... | |
148 | 149 |
@param neigh_ctrs: the indices of the neighboring atoms to the adsorption |
149 | 150 |
atoms. |
150 | 151 |
@param norm_vect: The vector perpendicular to the surface. |
152 |
@param coll_bttm: The lowermost height for which to detect a collision |
|
151 | 153 |
@return: list of ase.Atoms for the adsorbate-surface structures |
152 | 154 |
""" |
153 | 155 |
surf_ads_list = [] |
... | ... | |
158 | 160 |
for site in sites_coords: |
159 | 161 |
for i, molec_ctr in enumerate(molec_ctr_coords): |
160 | 162 |
if algo == 'euler': |
161 |
surf_ads_list.append(ads_euler(conf, surf, site, molec_ctr,
|
|
163 |
surf_ads_list.extend(ads_euler(conf, surf, molec_ctr, site,
|
|
162 | 164 |
num_pts, norm_vect, |
165 |
coll_bttm, |
|
163 | 166 |
molec_neigh_coords[i])) |
164 | 167 |
elif algo == 'chemcat': |
165 |
surf_ads_list.append(ads_chemcat(site, molec_ctr, num_pts))
|
|
168 |
surf_ads_list.extend(ads_chemcat(site, molec_ctr, num_pts))
|
|
166 | 169 |
return surf_ads_list |
167 | 170 |
|
168 | 171 |
|
... | ... | |
185 | 188 |
raise ValueError(err) |
186 | 189 |
|
187 | 190 |
conf_list = read_coords(inp_vars['code'], 'isolated', 'rdkit') |
188 |
# TODO Implement neighbors algorithm |
|
191 |
# TODO Implement neighbors algorithm / align molecule to surface
|
|
189 | 192 |
# neigh_list = get_neighbors(conf_list[0], inp_vars['molec_ads_ctrs']) |
190 | 193 |
conf_enrgs = read_energies(inp_vars['code'], 'isolated') |
191 | 194 |
mois = np.array([get_moments_of_inertia(conf)[0] for conf in conf_list]) |
192 | 195 |
rmsd_mtx = get_rmsd(conf_list) |
193 |
exemplars = clustering(rmsd_mtx) |
|
194 |
conf_list = [conf_list[idx] for idx in exemplars] |
|
195 |
conf_list = [rdkit_mol_to_ase_atoms(conf) for conf in conf_list] |
|
196 |
exemplars = clustering(rmsd_mtx) # TODO Kind of Clustering
|
|
197 |
clust_conf_list = [conf_list[idx] for idx in exemplars]
|
|
198 |
conf_list = [rdkit_mol_to_ase_atoms(conf) for conf in clust_conf_list]
|
|
196 | 199 |
surf = adapt_format('ase', inp_vars['surf_file']) |
197 | 200 |
surf_ads_list = adsorb_confs(conf_list, surf, inp_vars['molec_ads_ctrs'], |
198 | 201 |
inp_vars['sites'], inp_vars['ads_algo'], |
199 | 202 |
inp_vars['sample_points_per_angle'], |
200 | 203 |
inp_vars['molec_neigh_ctrs'], |
201 |
inp_vars['surf_norm_vect']) |
|
204 |
inp_vars['surf_norm_vect'], |
|
205 |
inp_vars['collision_bottom']) |
|
202 | 206 |
run_calc('screening', inp_vars, surf_ads_list) |
Formats disponibles : Unified diff