Révision 5fb01677
b/modules/dos_input.py | ||
---|---|---|
47 | 47 |
import logging |
48 | 48 |
from configparser import ConfigParser, NoSectionError, NoOptionError, \ |
49 | 49 |
MissingSectionHeaderError, DuplicateOptionError |
50 |
import numpy as np |
|
50 | 51 |
from modules.utilities import try_command |
51 | 52 |
|
52 | 53 |
logger = logging.getLogger('DockOnSurf') |
... | ... | |
457 | 458 |
|
458 | 459 |
|
459 | 460 |
def get_surf_norm_vect(): |
460 |
import numpy as np |
|
461 | 461 |
err = "'surf_norm_vect' must be either a 3 component vector or 'x', 'y' " \ |
462 | 462 |
"or 'z'" |
463 |
coords = {'x': [1.0, 0.0, 0.0],
|
|
464 |
'y': [0.0, 1.0, 0.0],
|
|
465 |
'z': [0.0, 0.0, 1.0]}
|
|
463 |
cart_coords = {'x': [1.0, 0.0, 0.0], '-x': [-1.0, 0.0, 0.0],
|
|
464 |
'y': [0.0, 1.0, 0.0], '-y': [0.0, -1.0, 0.0],
|
|
465 |
'z': [0.0, 0.0, 1.0], '-z': [0.0, 0.0, -1.0]}
|
|
466 | 466 |
surf_norm_vect_str = dos_inp.get('Screening', 'surf_norm_vect', |
467 |
fallback="0.0 0.0 1.0")
|
|
467 |
fallback="z")
|
|
468 | 468 |
|
469 |
if len(surf_norm_vect_str) == 1 and surf_norm_vect_str in coords:
|
|
470 |
surf_norm_vect = coords[surf_norm_vect_str] |
|
469 |
if surf_norm_vect_str in cart_coords:
|
|
470 |
surf_norm_vect = cart_coords[surf_norm_vect_str]
|
|
471 | 471 |
else: |
472 | 472 |
surf_norm_vect = try_command(str2lst, [(ValueError, err)], |
473 |
surf_norm_vect_str) |
|
473 |
surf_norm_vect_str, float)
|
|
474 | 474 |
if len(surf_norm_vect) != 3: |
475 | 475 |
logger.error(err) |
476 | 476 |
raise ValueError(err) |
... | ... | |
523 | 523 |
return screen_rmsd |
524 | 524 |
|
525 | 525 |
|
526 |
def get_coll_bottom():
|
|
527 |
err_msg = num_error % ('collision_bottom', 'decimal number')
|
|
528 |
coll_bottom = dos_inp.get('Screening', 'collision_bottom',
|
|
529 |
fallback="False") |
|
530 |
if coll_bottom.lower() in turn_false_answers:
|
|
531 |
coll_bottom = False
|
|
526 |
def get_min_coll_height():
|
|
527 |
err_msg = num_error % ('min_coll_height', 'decimal number')
|
|
528 |
min_coll_height = dos_inp.get('Screening', 'min_coll_height',
|
|
529 |
fallback="False")
|
|
530 |
if min_coll_height.lower() in turn_false_answers:
|
|
531 |
min_coll_height = False
|
|
532 | 532 |
else: |
533 |
coll_bottom = try_command(float, [(ValueError, err_msg)], coll_bottom) |
|
533 |
min_coll_height = try_command(float, [(ValueError, err_msg)], |
|
534 |
min_coll_height) |
|
534 | 535 |
|
535 |
return coll_bottom
|
|
536 |
return min_coll_height
|
|
536 | 537 |
|
537 | 538 |
|
538 | 539 |
def get_try_disso(): |
... | ... | |
678 | 679 |
return_vars['ads_algo'] = get_ads_algo() |
679 | 680 |
return_vars['sample_points_per_angle'] = get_pts_per_angle() |
680 | 681 |
return_vars['collision_threshold'] = get_coll_thrsld() |
681 |
return_vars['collision_bottom'] = get_coll_bottom() |
|
682 |
return_vars['min_coll_height'] = get_min_coll_height() |
|
683 |
cart_coords = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] |
|
684 |
if return_vars['min_coll_height'] is not False and \ |
|
685 |
list(map(abs, return_vars['surf_norm_vect'].tolist())) not in \ |
|
686 |
cart_coords: |
|
687 |
logger.warning("'min_coll_height' option is only implemented for " |
|
688 |
"'surf_norm_vect' to be one of the x, y or z axes") |
|
682 | 689 |
|
683 | 690 |
# Refinement |
684 | 691 |
if refinement: |
b/modules/screening.py | ||
---|---|---|
148 | 148 |
@return: bool, whether the surface and the molecule collide. |
149 | 149 |
""" |
150 | 150 |
from ase.neighborlist import natural_cutoffs, neighbor_list |
151 |
if (vect == np.array([1.0, 0.0, 0.0])).all \ |
|
152 |
or (vect == np.array([0.0, 1.0, 0.0])).all \ |
|
153 |
or (vect == np.array([0.0, 0.0, 1.0])).all: |
|
154 |
for atom in slab_molec[slab_num_atoms:]: |
|
155 |
if np.linalg.norm(atom.position * vect) < min_height: |
|
156 |
return True |
|
157 |
slab_molec_cutoffs = natural_cutoffs(slab_molec, mult=coll_coeff) |
|
158 |
slab_molec_nghbs = len(neighbor_list("i", slab_molec, slab_molec_cutoffs)) |
|
159 |
if slab_molec_nghbs > nn_slab + nn_molec: |
|
160 |
return True |
|
151 |
if min_height is not False: |
|
152 |
cart_coords = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] |
|
153 |
if list(map(abs, vect.tolist())) in cart_coords: |
|
154 |
for atom in slab_molec[slab_num_atoms:]: |
|
155 |
if np.linalg.norm(atom.position * vect) < min_height: |
|
156 |
# TODO Check norm when there are negative values |
|
157 |
return True |
|
161 | 158 |
else: |
162 |
return False |
|
159 |
slab_molec_cutoffs = natural_cutoffs(slab_molec, mult=coll_coeff) |
|
160 |
slab_molec_nghbs = len(neighbor_list("i", slab_molec, slab_molec_cutoffs)) |
|
161 |
if slab_molec_nghbs > nn_slab + nn_molec: |
|
162 |
return True |
|
163 |
else: |
|
164 |
return False |
|
163 | 165 |
|
164 | 166 |
|
165 | 167 |
def correct_coll(molec, slab, ctr_coord, site_coord, num_pts, |
166 |
coll_bttm, norm_vect, slab_nghbs, molec_nghbs, coll_coeff): |
|
168 |
min_coll_height, norm_vect, slab_nghbs, molec_nghbs, |
|
169 |
coll_coeff): |
|
167 | 170 |
# TODO Rethink this function |
168 | 171 |
"""Tries to adsorb a molecule on a slab trying to avoid collisions by doing |
169 | 172 |
small rotations. |
... | ... | |
176 | 179 |
@param site_coord: The coordinates of the surface on which to adsorb the |
177 | 180 |
molecule |
178 | 181 |
@param num_pts: Number on which to sample Euler angles. |
179 |
@param coll_bttm: The lowermost height for which to detect a collision
|
|
182 |
@param min_coll_height: The lowermost height for which to detect a collision
|
|
180 | 183 |
@param norm_vect: The vector perpendicular to the surface. |
181 | 184 |
@param slab_nghbs: Number of neigbors in the surface. |
182 | 185 |
@param molec_nghbs: Number of neighbors in the molecule. |
... | ... | |
199 | 202 |
center=ctr_coord) |
200 | 203 |
add_adsorbate(slab_molec, molec, site_coord, ctr_coord, 2.5, |
201 | 204 |
norm_vect=norm_vect) |
202 |
collision = check_collision(slab_molec, slab_num_atoms, coll_bttm,
|
|
205 |
collision = check_collision(slab_molec, slab_num_atoms, min_coll_height,
|
|
203 | 206 |
norm_vect, slab_nghbs, molec_nghbs, |
204 | 207 |
coll_coeff) |
205 | 208 |
num_corr += 1 |
... | ... | |
207 | 210 |
|
208 | 211 |
|
209 | 212 |
def ads_euler(orig_molec, slab, ctr_coord, site_coord, num_pts, |
210 |
coll_bttm, coll_coeff, norm_vect, slab_nghbs, molec_nghbs):
|
|
213 |
min_coll_height, coll_coeff, norm_vect, slab_nghbs, molec_nghbs):
|
|
211 | 214 |
"""Generates adsorbate-surface structures by sampling over Euler angles. |
212 | 215 |
|
213 | 216 |
This function generates a number of adsorbate-surface structures at |
... | ... | |
220 | 223 |
@param site_coord: The coordinates of the surface on which to adsorb the |
221 | 224 |
molecule |
222 | 225 |
@param num_pts: Number on which to sample Euler angles. |
223 |
@param coll_bttm: The lowermost height for which to detect a collision
|
|
226 |
@param min_coll_height: The lowermost height for which to detect a collision
|
|
224 | 227 |
@param coll_coeff: The coefficient that multiplies the covalent radius of |
225 | 228 |
atoms resulting in a distance that two atoms being closer to that is |
226 | 229 |
considered as atomic collision. |
... | ... | |
241 | 244 |
molec = deepcopy(orig_molec) |
242 | 245 |
molec.euler_rotate(alpha, beta, gamma, center=ctr_coord) |
243 | 246 |
slab_molec, collision = correct_coll(molec, slab, |
244 |
ctr_coord, site_coord, num_pts, coll_bttm, norm_vect, |
|
245 |
slab_nghbs, molec_nghbs, coll_coeff) |
|
247 |
ctr_coord, site_coord, |
|
248 |
num_pts, min_coll_height, |
|
249 |
norm_vect, |
|
250 |
slab_nghbs, molec_nghbs, |
|
251 |
coll_coeff) |
|
246 | 252 |
if not collision: |
247 | 253 |
slab_ads_list.append(slab_molec) |
248 | 254 |
|
... | ... | |
254 | 260 |
|
255 | 261 |
|
256 | 262 |
def adsorb_confs(conf_list, surf, molec_ctrs, sites, algo, num_pts, neigh_ctrs, |
257 |
norm_vect, coll_bttm, coll_coeff):
|
|
263 |
norm_vect, min_coll_height, coll_coeff):
|
|
258 | 264 |
"""Generates a number of adsorbate-surface structure coordinates. |
259 | 265 |
|
260 | 266 |
Given a list of conformers, a surface, a list of atom indices (or list of |
... | ... | |
270 | 276 |
@param neigh_ctrs: the indices of the neighboring atoms to the adsorption |
271 | 277 |
atoms. |
272 | 278 |
@param norm_vect: The vector perpendicular to the surface. |
273 |
@param coll_bttm: The lowermost height for which to detect a collision
|
|
279 |
@param min_coll_height: The lowermost height for which to detect a collision
|
|
274 | 280 |
@param coll_coeff: The coefficient that multiplies the covalent radius of |
275 | 281 |
atoms resulting in a distance that two atoms being closer to that is |
276 | 282 |
considered as atomic collision. |
... | ... | |
279 | 285 |
from ase.neighborlist import natural_cutoffs, neighbor_list |
280 | 286 |
surf_ads_list = [] |
281 | 287 |
sites_coords = get_atom_coords(surf, sites) |
282 |
surf_cutoffs = natural_cutoffs(surf, mult=coll_coeff) |
|
283 |
surf_nghbs = len(neighbor_list("i", surf, surf_cutoffs)) |
|
288 |
if min_coll_height is not False: |
|
289 |
surf_cutoffs = natural_cutoffs(surf, mult=coll_coeff) |
|
290 |
surf_nghbs = len(neighbor_list("i", surf, surf_cutoffs)) |
|
291 |
else: |
|
292 |
surf_nghbs = 0 |
|
284 | 293 |
for conf in conf_list: |
285 | 294 |
molec_ctr_coords = get_atom_coords(conf, molec_ctrs) |
286 | 295 |
molec_neigh_coords = get_atom_coords(conf, neigh_ctrs) |
287 |
conf_cutoffs = natural_cutoffs(conf, mult=coll_coeff) |
|
288 |
molec_nghbs = len(neighbor_list("i", conf, conf_cutoffs)) |
|
296 |
if min_coll_height is not False: |
|
297 |
conf_cutoffs = natural_cutoffs(conf, mult=coll_coeff) |
|
298 |
molec_nghbs = len(neighbor_list("i", conf, conf_cutoffs)) |
|
299 |
else: |
|
300 |
molec_nghbs = 0 |
|
289 | 301 |
for site in sites_coords: |
290 | 302 |
for ctr in molec_ctr_coords: |
291 | 303 |
if algo == 'euler': |
292 | 304 |
surf_ads_list.extend(ads_euler(conf, surf, ctr, site, |
293 |
num_pts, coll_bttm,
|
|
305 |
num_pts, min_coll_height,
|
|
294 | 306 |
coll_coeff, norm_vect, |
295 | 307 |
surf_nghbs, molec_nghbs)) |
296 | 308 |
elif algo == 'chemcat': |
... | ... | |
332 | 344 |
inp_vars['sample_points_per_angle'], |
333 | 345 |
inp_vars['molec_neigh_ctrs'], |
334 | 346 |
inp_vars['surf_norm_vect'], |
335 |
inp_vars['collision_bottom'],
|
|
347 |
inp_vars['min_coll_height'],
|
|
336 | 348 |
inp_vars['collision_threshold']) |
337 | 349 |
run_calc('screening', inp_vars, surf_ads_list) |
b/tests/test_dos_input.py | ||
---|---|---|
58 | 58 |
'try_disso': True, |
59 | 59 |
'sample_points_per_angle': 4, |
60 | 60 |
'collision_threshold': 0.9, |
61 |
'collision_bottom': 5.2,
|
|
61 |
'min_coll_height': 5.2,
|
|
62 | 62 |
'refine_inp_file': 'refine.inp', |
63 | 63 |
'energy_cutoff': 1.0 |
64 | 64 |
} |
... | ... | |
132 | 132 |
self.assertEqual(get_coll_thrsld(), 0.9) |
133 | 133 |
|
134 | 134 |
def test_coll_bottom(self): |
135 |
self.assertEqual(get_coll_bottom(), 5.2)
|
|
135 |
self.assertEqual(get_min_coll_height(), 5.2)
|
|
136 | 136 |
|
137 | 137 |
def test_refine_inp_file(self): |
138 | 138 |
self.assertEqual(get_refine_inp_file(), 'refine.inp') |
... | ... | |
205 | 205 |
self.assertRaises(ValueError, get_coll_thrsld) |
206 | 206 |
|
207 | 207 |
def test_coll_bottom(self): |
208 |
self.assertRaises(ValueError, get_coll_bottom)
|
|
208 |
self.assertRaises(ValueError, get_min_coll_height)
|
|
209 | 209 |
|
210 | 210 |
def test_refine_inp_file(self): |
211 | 211 |
self.assertRaises(FileNotFoundError, get_refine_inp_file) |
Formats disponibles : Unified diff