Révision 9cd032cf modules/screening.py
b/modules/screening.py | ||
---|---|---|
314 | 314 |
|
315 | 315 |
|
316 | 316 |
def check_collision(slab_molec, slab_num_atoms, min_height, vect, nn_slab=0, |
317 |
nn_molec=0, coll_coeff=1.2): |
|
317 |
nn_molec=0, coll_coeff=1.2, exclude_atom=False):
|
|
318 | 318 |
"""Checks whether a slab and a molecule collide or not. |
319 | 319 |
|
320 | 320 |
@param slab_molec: The system of adsorbate-slab for which to detect if there |
... | ... | |
328 | 328 |
@param min_height: The minimum height atoms can have to not be considered as |
329 | 329 |
colliding. |
330 | 330 |
@param vect: The vector perpendicular to the slab. |
331 |
@param exclude_atom: Whether to exclude the adsorption center in the |
|
332 |
molecule in the collision detection. |
|
331 | 333 |
@return: bool, whether the surface and the molecule collide. |
332 | 334 |
""" |
335 |
from copy import deepcopy |
|
333 | 336 |
from ase.neighborlist import natural_cutoffs, neighbor_list |
334 | 337 |
|
335 | 338 |
# Check structure overlap by height |
... | ... | |
342 | 345 |
logger.error(err_msg) |
343 | 346 |
raise ValueError(err_msg) |
344 | 347 |
for atom in slab_molec[slab_num_atoms:]: |
348 |
if exclude_atom is not False \ |
|
349 |
and atom.index == exclude_atom: |
|
350 |
continue |
|
345 | 351 |
for i, coord in enumerate(vect): |
346 | 352 |
if coord == 0: |
347 | 353 |
continue |
... | ... | |
350 | 356 |
|
351 | 357 |
# Check structure overlap by sphere collision |
352 | 358 |
if coll_coeff is not False: |
353 |
slab_molec_cutoffs = natural_cutoffs(slab_molec, mult=coll_coeff) |
|
354 |
slab_molec_nghbs = len( |
|
355 |
neighbor_list("i", slab_molec, slab_molec_cutoffs)) |
|
359 |
if exclude_atom is not False: |
|
360 |
slab_molec_wo_ctr = deepcopy(slab_molec) |
|
361 |
del slab_molec_wo_ctr[exclude_atom + slab_num_atoms] |
|
362 |
slab_molec_cutoffs = natural_cutoffs(slab_molec_wo_ctr, |
|
363 |
mult=coll_coeff) |
|
364 |
slab_molec_nghbs = len(neighbor_list("i", slab_molec_wo_ctr, |
|
365 |
slab_molec_cutoffs)) |
|
366 |
else: |
|
367 |
slab_molec_cutoffs = natural_cutoffs(slab_molec, mult=coll_coeff) |
|
368 |
slab_molec_nghbs = len(neighbor_list("i", slab_molec, |
|
369 |
slab_molec_cutoffs)) |
|
356 | 370 |
if slab_molec_nghbs > nn_slab + nn_molec: |
357 | 371 |
return True |
358 | 372 |
|
... | ... | |
361 | 375 |
|
362 | 376 |
def correct_coll(molec, slab, ctr_coord, site_coord, num_pts, |
363 | 377 |
min_coll_height, norm_vect, slab_nghbs, molec_nghbs, |
364 |
coll_coeff, height=2.5): |
|
365 |
# TODO Rethink this function
|
|
378 |
coll_coeff, height=2.5, excl_atom=False):
|
|
379 |
# TODO Rename this function
|
|
366 | 380 |
"""Tries to adsorb a molecule on a slab trying to avoid collisions by doing |
367 | 381 |
small rotations. |
368 | 382 |
|
... | ... | |
382 | 396 |
atoms resulting in a distance that two atoms being closer to that is |
383 | 397 |
considered as atomic collision. |
384 | 398 |
@param height: Height on which to try adsorption. |
399 |
@param excl_atom: Whether to exclude the adsorption center in the |
|
400 |
molecule in the collision detection. |
|
385 | 401 |
@return collision: bool, whether the structure generated has collisions |
386 | 402 |
between slab and adsorbate. |
387 | 403 |
""" |
... | ... | |
401 | 417 |
norm_vect=norm_vect) |
402 | 418 |
collision = check_collision(slab_molec, slab_num_atoms, min_coll_height, |
403 | 419 |
norm_vect, slab_nghbs, molec_nghbs, |
404 |
coll_coeff) |
|
420 |
coll_coeff, excl_atom)
|
|
405 | 421 |
num_corr += 1 |
406 | 422 |
return slab_molec, collision |
407 | 423 |
|
... | ... | |
506 | 522 |
|
507 | 523 |
def ads_euler(orig_molec, slab, ctr_coord, site_coord, num_pts, |
508 | 524 |
min_coll_height, coll_coeff, norm_vect, slab_nghbs, molec_nghbs, |
509 |
h_donor, h_acceptor, height): |
|
525 |
h_donor, h_acceptor, height, excl_atom):
|
|
510 | 526 |
"""Generates adsorbate-surface structures by sampling over Euler angles. |
511 | 527 |
|
512 | 528 |
This function generates a number of adsorbate-surface structures at |
... | ... | |
530 | 546 |
@param h_donor: List of atom types or atom numbers that are H-donors. |
531 | 547 |
@param h_acceptor: List of atom types or atom numbers that are H-acceptors. |
532 | 548 |
@param height: Height on which to try adsorption. |
549 |
@param excl_atom: Whether to exclude the adsorption center in the |
|
550 |
molecule in the collision detection. |
|
533 | 551 |
@return: list of ase.Atoms object conatining all the orientations of a given |
534 | 552 |
conformer. |
535 | 553 |
""" |
... | ... | |
546 | 564 |
continue |
547 | 565 |
molec = deepcopy(prealigned_molec) |
548 | 566 |
molec.euler_rotate(alpha, beta, gamma, center=ctr_coord) |
549 |
slab_molec, collision = correct_coll(molec, slab, |
|
550 |
ctr_coord, site_coord, |
|
551 |
num_pts, min_coll_height, |
|
552 |
norm_vect, |
|
567 |
slab_molec, collision = correct_coll(molec, slab, ctr_coord, |
|
568 |
site_coord, num_pts, |
|
569 |
min_coll_height, norm_vect, |
|
553 | 570 |
slab_nghbs, molec_nghbs, |
554 |
coll_coeff, height) |
|
571 |
coll_coeff, height, |
|
572 |
excl_atom) |
|
555 | 573 |
if not collision and not any([np.allclose(slab_molec.positions, |
556 | 574 |
conf.positions) |
557 | 575 |
for conf in slab_ads_list]): |
... | ... | |
832 | 850 |
|
833 | 851 |
def ads_internal(orig_molec, slab, ctr1_mol, ctr2_mol, ctr3_mol, ctr1_surf, |
834 | 852 |
ctr2_surf, num_pts, min_coll_height, coll_coeff, norm_vect, |
835 |
slab_nghbs, molec_nghbs, h_donor, h_acceptor, max_hel, height): |
|
853 |
slab_nghbs, molec_nghbs, h_donor, h_acceptor, max_hel, height, |
|
854 |
excl_atom): |
|
836 | 855 |
"""Generates adsorbate-surface structures by sampling over internal angles. |
837 | 856 |
|
838 | 857 |
@param orig_molec: ase.Atoms object of the molecule to adsorb (adsorbate). |
... | ... | |
861 | 880 |
@param max_hel: Maximum value for sampling the helicopter |
862 | 881 |
(surf-adsorbate dihedral) angle. |
863 | 882 |
@param height: Height on which to try adsorption. |
883 |
@param excl_atom: Whether to exclude the adsorption center in the |
|
884 |
molecule in the collision detection. |
|
864 | 885 |
@return: list of ase.Atoms object conatining all the orientations of a given |
865 | 886 |
conformer. |
866 | 887 |
""" |
... | ... | |
887 | 908 |
num_pts, min_coll_height, |
888 | 909 |
norm_vect, slab_nghbs, |
889 | 910 |
molec_nghbs, coll_coeff, |
890 |
height) |
|
911 |
height, excl_atom)
|
|
891 | 912 |
if not collision and \ |
892 | 913 |
not any([np.allclose(slab_molec.positions, |
893 | 914 |
conf.positions) |
... | ... | |
913 | 934 |
@param inp_vars: Calculation parameters from input file. |
914 | 935 |
@return: list of ase.Atoms for the adsorbate-surface structures |
915 | 936 |
""" |
937 |
from copy import deepcopy |
|
916 | 938 |
from ase.neighborlist import natural_cutoffs, neighbor_list |
917 | 939 |
molec_ctrs = inp_vars['molec_ctrs'] |
918 | 940 |
sites = inp_vars['sites'] |
... | ... | |
921 | 943 |
inp_norm_vect = inp_vars['surf_norm_vect'] |
922 | 944 |
min_coll_height = inp_vars['min_coll_height'] |
923 | 945 |
coll_coeff = inp_vars['collision_threshold'] |
946 |
exclude_ads_ctr = inp_vars['exclude_ads_ctr'] |
|
924 | 947 |
h_donor = inp_vars['h_donor'] |
925 | 948 |
h_acceptor = inp_vars['h_acceptor'] |
926 | 949 |
height = inp_vars['adsorption_height'] |
... | ... | |
941 | 964 |
if inp_vars['pbc_cell'] is not False: |
942 | 965 |
conf.set_pbc(True) |
943 | 966 |
conf.set_cell(inp_vars['pbc_cell']) |
944 |
if coll_coeff is not False: |
|
945 |
conf_cutoffs = natural_cutoffs(conf, mult=coll_coeff) |
|
946 |
molec_nghbs = len(neighbor_list("i", conf, conf_cutoffs)) |
|
947 |
else: |
|
948 |
molec_nghbs = 0 |
|
949 | 967 |
for s, site in enumerate(sites_coords): |
950 | 968 |
if isinstance(inp_norm_vect, str) and inp_norm_vect == 'auto': |
951 | 969 |
norm_vect = compute_norm_vect(surf, sites[s], |
... | ... | |
953 | 971 |
else: |
954 | 972 |
norm_vect = inp_norm_vect |
955 | 973 |
for c, ctr in enumerate(molec_ctr_coords): |
974 |
if exclude_ads_ctr and isinstance(molec_ctrs[c], int): |
|
975 |
exclude_atom = molec_ctrs[c] |
|
976 |
else: |
|
977 |
exclude_atom = False |
|
978 |
if exclude_ads_ctr and not isinstance(molec_ctrs[c], int): |
|
979 |
logger.warning("'exclude_ads_ctr' only works for atomic" |
|
980 |
"centers and not for many-atoms " |
|
981 |
f"barycenters. {molec_ctrs[c]} are not " |
|
982 |
f"going to be excluded from collison.") |
|
983 |
if coll_coeff and exclude_atom is not False: |
|
984 |
conf_wo_ctr = deepcopy(conf) |
|
985 |
del conf_wo_ctr[exclude_atom] |
|
986 |
conf_cutoffs = natural_cutoffs(conf_wo_ctr, mult=coll_coeff) |
|
987 |
molec_nghbs = len(neighbor_list("i", conf_wo_ctr, |
|
988 |
conf_cutoffs)) |
|
989 |
elif coll_coeff and exclude_atom is False: |
|
990 |
conf_cutoffs = natural_cutoffs(conf, mult=coll_coeff) |
|
991 |
molec_nghbs = len(neighbor_list("i", conf, conf_cutoffs)) |
|
992 |
else: |
|
993 |
molec_nghbs = 0 |
|
956 | 994 |
if angles == 'euler': |
957 | 995 |
surf_ads_list.extend(ads_euler(conf, surf, ctr, site, |
958 | 996 |
num_pts, min_coll_height, |
959 | 997 |
coll_coeff, norm_vect, |
960 | 998 |
surf_nghbs, molec_nghbs, |
961 |
h_donor, h_acceptor, height)) |
|
999 |
h_donor, h_acceptor, height, |
|
1000 |
exclude_atom)) |
|
962 | 1001 |
elif angles == 'internal': |
963 | 1002 |
mol_ctr1 = molec_ctrs[c] |
964 | 1003 |
mol_ctr2 = inp_vars["molec_ctrs2"][c] |
... | ... | |
973 | 1012 |
coll_coeff, norm_vect, |
974 | 1013 |
surf_nghbs, molec_nghbs, |
975 | 1014 |
h_donor, h_acceptor, |
976 |
max_h, height)) |
|
1015 |
max_h, height, |
|
1016 |
exclude_atom)) |
|
977 | 1017 |
return surf_ads_list |
978 | 1018 |
|
979 | 1019 |
|
Formats disponibles : Unified diff