1!--------------------------------------------------------------------------------------------------! 2! CP2K: A general program to perform molecular dynamics simulations ! 3! Copyright (C) 2000 - 2019 CP2K developers group ! 4!--------------------------------------------------------------------------------------------------! 5 6! ************************************************************************************************** 7!> \brief Generate the atomic neighbor lists for FIST. 8!> \par History 9!> - build and update merged (11.02.2005,MK) 10!> - bug fix for PERIODIC NONE (24.02.06,MK) 11!> - Major rewriting (light memory neighbor lists): teo and joost (05.2006) 12!> - Completely new algorithm for the neighbor lists 13!> (faster and memory lighter) (Teo 08.2006) 14!> \author MK (19.11.2002,24.07.2003) 15!> Teodoro Laino (08.2006) - MAJOR REWRITING 16! ************************************************************************************************** 17MODULE fist_neighbor_lists 18 19 USE atomic_kind_types, ONLY: atomic_kind_type,& 20 get_atomic_kind,& 21 get_atomic_kind_set 22 USE cell_types, ONLY: cell_type,& 23 get_cell,& 24 pbc,& 25 plane_distance,& 26 scaled_to_real 27 USE cp_log_handling, ONLY: cp_get_default_logger,& 28 cp_logger_get_default_unit_nr,& 29 cp_logger_type 30 USE cp_output_handling, ONLY: cp_p_file,& 31 cp_print_key_finished_output,& 32 cp_print_key_should_output,& 33 cp_print_key_unit_nr 34 USE cp_para_types, ONLY: cp_para_env_type 35 USE cp_units, ONLY: cp_unit_from_cp2k 36 USE distribution_1d_types, ONLY: distribution_1d_type 37 USE exclusion_types, ONLY: exclusion_type 38 USE fist_neighbor_list_types, ONLY: fist_neighbor_add,& 39 fist_neighbor_deallocate,& 40 fist_neighbor_init,& 41 fist_neighbor_type,& 42 neighbor_kind_pairs_type 43 USE input_section_types, ONLY: section_vals_type,& 44 section_vals_val_get 45 USE kinds, ONLY: default_string_length,& 46 dp 47 USE mathlib, ONLY: matvec_3x3 48 USE memory_utilities, ONLY: reallocate 49 USE particle_types, ONLY: particle_type 50 USE qmmm_ff_fist, ONLY: qmmm_ff_precond_only_qm 51 USE string_utilities, ONLY: compress 52 USE subcell_types, ONLY: allocate_subcell,& 53 deallocate_subcell,& 54 give_ijk_subcell,& 55 reorder_atoms_subcell,& 56 subcell_type 57 USE util, ONLY: sort 58#include "./base/base_uses.f90" 59 60 IMPLICIT NONE 61 62 PRIVATE 63 64 ! Global parameters (in this module) 65 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fist_neighbor_lists' 66 67 TYPE local_atoms_type 68 INTEGER, DIMENSION(:), POINTER :: list, & 69 list_local_a_index 70 END TYPE local_atoms_type 71 72 ! Public subroutines 73 PUBLIC :: build_fist_neighbor_lists 74 75CONTAINS 76 77! ************************************************************************************************** 78!> \brief ... 79!> \param atomic_kind_set ... 80!> \param particle_set ... 81!> \param local_particles ... 82!> \param cell ... 83!> \param r_max ... 84!> \param r_minsq ... 85!> \param ei_scale14 ... 86!> \param vdw_scale14 ... 87!> \param nonbonded ... 88!> \param para_env ... 89!> \param build_from_scratch ... 90!> \param geo_check ... 91!> \param mm_section ... 92!> \param full_nl ... 93!> \param exclusions ... 94!> \par History 95!> 08.2006 created [tlaino] 96!> \author Teodoro Laino 97! ************************************************************************************************** 98 SUBROUTINE build_fist_neighbor_lists(atomic_kind_set, particle_set, & 99 local_particles, cell, r_max, r_minsq, ei_scale14, vdw_scale14, & 100 nonbonded, para_env, build_from_scratch, geo_check, mm_section, & 101 full_nl, exclusions) 102 103 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set 104 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set 105 TYPE(distribution_1d_type), OPTIONAL, POINTER :: local_particles 106 TYPE(cell_type), POINTER :: cell 107 REAL(dp), DIMENSION(:, :), INTENT(IN) :: r_max, r_minsq 108 REAL(KIND=DP), INTENT(IN) :: ei_scale14, vdw_scale14 109 TYPE(fist_neighbor_type), POINTER :: nonbonded 110 TYPE(cp_para_env_type), POINTER :: para_env 111 LOGICAL, INTENT(IN) :: build_from_scratch, geo_check 112 TYPE(section_vals_type), POINTER :: mm_section 113 LOGICAL, DIMENSION(:, :), OPTIONAL, POINTER :: full_nl 114 TYPE(exclusion_type), DIMENSION(:), OPTIONAL :: exclusions 115 116 CHARACTER(LEN=*), PARAMETER :: routineN = 'build_fist_neighbor_lists', & 117 routineP = moduleN//':'//routineN 118 119 CHARACTER(LEN=default_string_length) :: kind_name, print_key_path, unit_str 120 INTEGER :: atom_a, handle, iatom_local, ikind, iw, & 121 maxatom, natom_local_a, nkind, & 122 output_unit 123 LOGICAL :: present_local_particles, & 124 print_subcell_grid 125 LOGICAL, DIMENSION(:), POINTER :: skip_kind 126 LOGICAL, DIMENSION(:, :), POINTER :: my_full_nl 127 TYPE(atomic_kind_type), POINTER :: atomic_kind 128 TYPE(cp_logger_type), POINTER :: logger 129 TYPE(local_atoms_type), ALLOCATABLE, DIMENSION(:) :: atom 130 131 CALL timeset(routineN, handle) 132 NULLIFY (logger) 133 logger => cp_get_default_logger() 134 135 print_subcell_grid = .FALSE. 136 output_unit = cp_print_key_unit_nr(logger, mm_section, "PRINT%SUBCELL", & 137 extension=".Log") 138 IF (output_unit > 0) print_subcell_grid = .TRUE. 139 140 CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, & 141 maxatom=maxatom) 142 143 present_local_particles = PRESENT(local_particles) 144 145 ! if exclusions matters local particles are present. Seems like only the exclusions 146 ! for the local particles are needed, which would imply a huge memory savings for fist 147 IF (PRESENT(exclusions)) THEN 148 CPASSERT(present_local_particles) 149 ENDIF 150 151 ! Allocate work storage 152 nkind = SIZE(atomic_kind_set) 153 ALLOCATE (atom(nkind)) 154 ALLOCATE (skip_kind(nkind)) 155 ! full_nl 156 IF (PRESENT(full_nl)) THEN 157 my_full_nl => full_nl 158 ELSE 159 ALLOCATE (my_full_nl(nkind, nkind)) 160 my_full_nl = .FALSE. 161 END IF 162 ! Initialize the local data structures 163 DO ikind = 1, nkind 164 atomic_kind => atomic_kind_set(ikind) 165 NULLIFY (atom(ikind)%list) 166 NULLIFY (atom(ikind)%list_local_a_index) 167 168 CALL get_atomic_kind(atomic_kind=atomic_kind, & 169 atom_list=atom(ikind)%list, name=kind_name) 170 skip_kind(ikind) = qmmm_ff_precond_only_qm(kind_name) 171 IF (present_local_particles) THEN 172 natom_local_a = local_particles%n_el(ikind) 173 ELSE 174 natom_local_a = SIZE(atom(ikind)%list) 175 END IF 176 IF (natom_local_a > 0) THEN 177 ALLOCATE (atom(ikind)%list_local_a_index(natom_local_a)) 178 ! Build index vector for mapping 179 DO iatom_local = 1, natom_local_a 180 IF (present_local_particles) THEN 181 atom_a = local_particles%list(ikind)%array(iatom_local) 182 ELSE 183 atom_a = atom(ikind)%list(iatom_local) 184 END IF 185 atom(ikind)%list_local_a_index(iatom_local) = atom_a 186 END DO 187 188 END IF 189 END DO 190 191 IF (build_from_scratch) THEN 192 IF (ASSOCIATED(nonbonded)) THEN 193 CALL fist_neighbor_deallocate(nonbonded) 194 END IF 195 END IF 196 197 ! Build the nonbonded neighbor lists 198 CALL build_neighbor_lists(nonbonded, particle_set, atom, cell, & 199 print_subcell_grid, output_unit, r_max, r_minsq, & 200 ei_scale14, vdw_scale14, geo_check, "NONBONDED", skip_kind, & 201 my_full_nl, exclusions) 202 203 ! Sort the list according kinds for each cell 204 CALL sort_neighbor_lists(nonbonded, nkind) 205 206 print_key_path = "PRINT%NEIGHBOR_LISTS" 207 208 IF (BTEST(cp_print_key_should_output(logger%iter_info, mm_section, print_key_path), & 209 cp_p_file)) THEN 210 iw = cp_print_key_unit_nr(logger=logger, & 211 basis_section=mm_section, & 212 print_key_path=print_key_path, & 213 extension=".out", & 214 middle_name="nonbonded_nl", & 215 local=.TRUE., & 216 log_filename=.FALSE., & 217 file_position="REWIND") 218 CALL section_vals_val_get(mm_section, TRIM(print_key_path)//"%UNIT", c_val=unit_str) 219 CALL write_neighbor_lists(nonbonded, particle_set, cell, para_env, iw, & 220 "NONBONDED NEIGHBOR LISTS", unit_str) 221 CALL cp_print_key_finished_output(unit_nr=iw, & 222 logger=logger, & 223 basis_section=mm_section, & 224 print_key_path=print_key_path, & 225 local=.TRUE.) 226 END IF 227 228 ! Release work storage 229 DO ikind = 1, nkind 230 NULLIFY (atom(ikind)%list) 231 IF (ASSOCIATED(atom(ikind)%list_local_a_index)) THEN 232 DEALLOCATE (atom(ikind)%list_local_a_index) 233 END IF 234 END DO 235 IF (PRESENT(full_nl)) THEN 236 NULLIFY (my_full_nl) 237 ELSE 238 DEALLOCATE (my_full_nl) 239 END IF 240 DEALLOCATE (atom) 241 242 DEALLOCATE (skip_kind) 243 244 CALL cp_print_key_finished_output(unit_nr=output_unit, & 245 logger=logger, & 246 basis_section=mm_section, & 247 print_key_path="PRINT%SUBCELL") 248 CALL timestop(handle) 249 250 END SUBROUTINE build_fist_neighbor_lists 251 252! ************************************************************************************************** 253!> \brief ... 254!> \param nonbonded ... 255!> \param particle_set ... 256!> \param atom ... 257!> \param cell ... 258!> \param print_subcell_grid ... 259!> \param output_unit ... 260!> \param r_max ... 261!> \param r_minsq ... 262!> \param ei_scale14 ... 263!> \param vdw_scale14 ... 264!> \param geo_check ... 265!> \param name ... 266!> \param skip_kind ... 267!> \param full_nl ... 268!> \param exclusions ... 269!> \par History 270!> 08.2006 created [tlaino] 271!> \author Teodoro Laino 272! ************************************************************************************************** 273 SUBROUTINE build_neighbor_lists(nonbonded, particle_set, atom, cell, & 274 print_subcell_grid, output_unit, r_max, r_minsq, & 275 ei_scale14, vdw_scale14, geo_check, name, skip_kind, full_nl, exclusions) 276 277 TYPE(fist_neighbor_type), POINTER :: nonbonded 278 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set 279 TYPE(local_atoms_type), DIMENSION(:), INTENT(IN) :: atom 280 TYPE(cell_type), POINTER :: cell 281 LOGICAL, INTENT(IN) :: print_subcell_grid 282 INTEGER, INTENT(IN) :: output_unit 283 REAL(dp), DIMENSION(:, :), INTENT(IN) :: r_max, r_minsq 284 REAL(KIND=dp), INTENT(IN) :: ei_scale14, vdw_scale14 285 LOGICAL, INTENT(IN) :: geo_check 286 CHARACTER(LEN=*), INTENT(IN) :: name 287 LOGICAL, DIMENSION(:), POINTER :: skip_kind 288 LOGICAL, DIMENSION(:, :), POINTER :: full_nl 289 TYPE(exclusion_type), DIMENSION(:), OPTIONAL :: exclusions 290 291 CHARACTER(LEN=*), PARAMETER :: routineN = 'build_neighbor_lists', & 292 routineP = moduleN//':'//routineN 293 294 INTEGER :: a_i, a_j, a_k, atom_a, atom_b, b_i, b_j, b_k, b_pi, b_pj, b_pk, bg_i, bg_j, bg_k, & 295 handle, i, i1, iatom_local, icell, icellmap, id_kind, ii, ii_start, ij, ij_start, ik, & 296 ik_start, ikind, imap, imax_cell, invcellmap, iw, ix, j, j1, jatom_local, jcell, jkind, & 297 jx, k, kcell, kx, natom_local_a, ncellmax, nkind, nkind00, tmpdim, xdim, ydim, zdim 298 INTEGER, ALLOCATABLE, DIMENSION(:) :: kind_of, work 299 INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: cellmap 300 INTEGER, DIMENSION(3) :: isubcell, ncell, nsubcell, periodic 301 LOGICAL :: any_full, atom_order, check_spline, & 302 is_full, subcell000 303 LOGICAL, ALLOCATABLE, DIMENSION(:, :, :) :: sphcub 304 REAL(dp) :: rab2, rab2_max, rab2_min, rab_max 305 REAL(dp), DIMENSION(3) :: abc, cell_v, cv_b, rab, rb, sab_max 306 REAL(KIND=dp) :: ic(3), icx(3), radius, vv 307 REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: coord 308 TYPE(neighbor_kind_pairs_type), POINTER :: inv_neighbor_kind_pair, & 309 neighbor_kind_pair 310 TYPE(subcell_type), DIMENSION(:, :, :), POINTER :: subcell_a, subcell_b 311 312 CALL timeset(routineN, handle) 313 nkind = SIZE(atom) 314 nsubcell = 1 315 isubcell = 0 316 ncell = 0 317 any_full = ANY(full_nl) 318 CALL get_cell(cell=cell, & 319 abc=abc, & 320 periodic=periodic) 321 ! Determines the number of subcells 322 DO ikind = 1, nkind 323 DO jkind = ikind, nkind 324 ! Calculate the square of the maximum interaction distance 325 rab_max = r_max(ikind, jkind) 326 IF (skip_kind(ikind) .AND. skip_kind(jkind)) CYCLE 327 nsubcell(1) = MAX(nsubcell(1), CEILING(plane_distance(1, 0, 0, cell)/rab_max)) 328 nsubcell(2) = MAX(nsubcell(2), CEILING(plane_distance(0, 1, 0, cell)/rab_max)) 329 nsubcell(3) = MAX(nsubcell(3), CEILING(plane_distance(0, 0, 1, cell)/rab_max)) 330 END DO 331 END DO 332 ! Determines the number of periodic images and the number of interacting subcells 333 DO ikind = 1, nkind 334 DO jkind = ikind, nkind 335 IF (skip_kind(ikind) .AND. skip_kind(jkind)) CYCLE 336 ! Calculate the square of the maximum interaction distance 337 rab_max = r_max(ikind, jkind) 338 sab_max(1) = rab_max/plane_distance(1, 0, 0, cell) 339 sab_max(2) = rab_max/plane_distance(0, 1, 0, cell) 340 sab_max(3) = rab_max/plane_distance(0, 0, 1, cell) 341 ncell = MAX(ncell(:), CEILING(sab_max(:)*periodic(:))) 342 isubcell = MAX(isubcell(:), CEILING(sab_max(:)*REAL(nsubcell(:), KIND=dp))) 343 END DO 344 END DO 345 CALL fist_neighbor_init(nonbonded, ncell) 346 ! Print headline 347 IF (print_subcell_grid) THEN 348 WRITE (UNIT=output_unit, FMT="(/,/,T2,A,/)") & 349 "SUBCELL GRID INFO FOR THE "//TRIM(name)//" NEIGHBOR LISTS" 350 WRITE (UNIT=output_unit, FMT="(T4,A,10X,3I10)") " NUMBER OF SUBCELLS ::", nsubcell 351 WRITE (UNIT=output_unit, FMT="(T4,A,10X,3I10)") " NUMBER OF PERIODIC IMAGES ::", ncell 352 WRITE (UNIT=output_unit, FMT="(T4,A,10X,3I10)") " NUMBER OF INTERACTING SUBCELLS ::", isubcell 353 END IF 354 ! Allocate subcells 355 CALL allocate_subcell(subcell_a, nsubcell, cell=cell) 356 CALL allocate_subcell(subcell_b, nsubcell, cell=cell) 357 ! Let's map the sequence of the periodic images 358 ncellmax = MAXVAL(ncell) 359 ALLOCATE (cellmap(-ncellmax:ncellmax, -ncellmax:ncellmax, -ncellmax:ncellmax)) 360 cellmap = -1 361 imap = 0 362 nkind00 = nkind*(nkind + 1)/2 363 DO imax_cell = 0, ncellmax 364 DO kcell = -imax_cell, imax_cell 365 DO jcell = -imax_cell, imax_cell 366 DO icell = -imax_cell, imax_cell 367 IF (cellmap(icell, jcell, kcell) == -1) THEN 368 imap = imap + 1 369 cellmap(icell, jcell, kcell) = imap 370 CPASSERT(imap <= nonbonded%nlists) 371 neighbor_kind_pair => nonbonded%neighbor_kind_pairs(imap) 372 373 neighbor_kind_pair%cell_vector(1) = icell 374 neighbor_kind_pair%cell_vector(2) = jcell 375 neighbor_kind_pair%cell_vector(3) = kcell 376 ENDIF 377 ENDDO 378 ENDDO 379 ENDDO 380 ENDDO 381 ! Mapping the spherical interaction between subcells 382 ALLOCATE (sphcub(-isubcell(1):isubcell(1), & 383 -isubcell(2):isubcell(2), & 384 -isubcell(3):isubcell(3))) 385 sphcub = .FALSE. 386 IF (ALL(isubcell /= 0)) THEN 387 radius = REAL(isubcell(1), KIND=dp)**2 + REAL(isubcell(2), KIND=dp)**2 + & 388 REAL(isubcell(3), KIND=dp)**2 389 loop1: DO k = -isubcell(3), isubcell(3) 390 loop2: DO j = -isubcell(2), isubcell(2) 391 loop3: DO i = -isubcell(1), isubcell(1) 392 ic = REAL((/i, j, k/), KIND=dp) 393 ! subcell cube vertex 394 DO kx = -1, 1 395 icx(3) = ic(3) + SIGN(0.5_dp, REAL(kx, KIND=dp)) 396 DO jx = -1, 1 397 icx(2) = ic(2) + SIGN(0.5_dp, REAL(jx, KIND=dp)) 398 DO ix = -1, 1 399 icx(1) = ic(1) + SIGN(0.5_dp, REAL(ix, KIND=dp)) 400 vv = icx(1)*icx(1) + icx(2)*icx(2) + icx(3)*icx(3) 401 vv = vv/radius 402 IF (vv <= 1.0_dp) THEN 403 sphcub(i, j, k) = .TRUE. 404 CYCLE loop3 405 END IF 406 END DO 407 END DO 408 END DO 409 END DO loop3 410 END DO loop2 411 END DO loop1 412 END IF 413 ! Mapping locally all atoms in the zeroth cell 414 ALLOCATE (coord(3, SIZE(particle_set))) 415 DO atom_a = 1, SIZE(particle_set) 416 coord(:, atom_a) = pbc(particle_set(atom_a)%r, cell) 417 END DO 418 ! Associate particles to subcells (local particles) 419 DO ikind = 1, nkind 420 IF (.NOT. ASSOCIATED(atom(ikind)%list_local_a_index)) CYCLE 421 natom_local_a = SIZE(atom(ikind)%list_local_a_index) 422 DO iatom_local = 1, natom_local_a 423 atom_a = atom(ikind)%list_local_a_index(iatom_local) 424 CALL give_ijk_subcell(coord(:, atom_a), i, j, k, cell, nsubcell) 425 subcell_a(i, j, k)%natom = subcell_a(i, j, k)%natom + 1 426 END DO 427 END DO 428 DO k = 1, nsubcell(3) 429 DO j = 1, nsubcell(2) 430 DO i = 1, nsubcell(1) 431 ALLOCATE (subcell_a(i, j, k)%atom_list(subcell_a(i, j, k)%natom)) 432 subcell_a(i, j, k)%natom = 0 433 END DO 434 END DO 435 END DO 436 DO ikind = 1, nkind 437 IF (.NOT. ASSOCIATED(atom(ikind)%list_local_a_index)) CYCLE 438 natom_local_a = SIZE(atom(ikind)%list_local_a_index) 439 DO iatom_local = 1, natom_local_a 440 atom_a = atom(ikind)%list_local_a_index(iatom_local) 441 CALL give_ijk_subcell(coord(:, atom_a), i, j, k, cell, nsubcell) 442 subcell_a(i, j, k)%natom = subcell_a(i, j, k)%natom + 1 443 subcell_a(i, j, k)%atom_list(subcell_a(i, j, k)%natom) = atom_a 444 END DO 445 END DO 446 ! Associate particles to subcells (distributed particles) 447 DO atom_b = 1, SIZE(particle_set) 448 CALL give_ijk_subcell(coord(:, atom_b), i, j, k, cell, nsubcell) 449 subcell_b(i, j, k)%natom = subcell_b(i, j, k)%natom + 1 450 END DO 451 DO k = 1, nsubcell(3) 452 DO j = 1, nsubcell(2) 453 DO i = 1, nsubcell(1) 454 ALLOCATE (subcell_b(i, j, k)%atom_list(subcell_b(i, j, k)%natom)) 455 subcell_b(i, j, k)%natom = 0 456 END DO 457 END DO 458 END DO 459 DO atom_b = 1, SIZE(particle_set) 460 CALL give_ijk_subcell(coord(:, atom_b), i, j, k, cell, nsubcell) 461 subcell_b(i, j, k)%natom = subcell_b(i, j, k)%natom + 1 462 subcell_b(i, j, k)%atom_list(subcell_b(i, j, k)%natom) = atom_b 463 END DO 464 ! Reorder atoms associated to subcells 465 tmpdim = MAXVAL(subcell_a(:, :, :)%natom) 466 tmpdim = MAX(tmpdim, MAXVAL(subcell_b(:, :, :)%natom)) 467 ALLOCATE (work(3*tmpdim)) 468 ALLOCATE (kind_of(SIZE(particle_set))) 469 DO i = 1, SIZE(particle_set) 470 kind_of(i) = particle_set(i)%atomic_kind%kind_number 471 END DO 472 DO k = 1, nsubcell(3) 473 DO j = 1, nsubcell(2) 474 DO i = 1, nsubcell(1) 475 CALL reorder_atoms_subcell(subcell_a(i, j, k)%atom_list, kind_of, work) 476 CALL reorder_atoms_subcell(subcell_b(i, j, k)%atom_list, kind_of, work) 477 END DO 478 END DO 479 END DO 480 DEALLOCATE (work, kind_of) 481 zdim = nsubcell(3) 482 ydim = nsubcell(2) 483 xdim = nsubcell(1) 484 is_full = .FALSE. 485 ! We can skip until ik>=0.. this prescreens the order of the subcells 486 ik_start = -isubcell(3) 487 IF (.NOT. any_full) ik_start = 0 488 ! Loop over first subcell 489 loop_a_k: DO a_k = 1, nsubcell(3) 490 loop_a_j: DO a_j = 1, nsubcell(2) 491 loop_a_i: DO a_i = 1, nsubcell(1) 492 IF (subcell_a(a_i, a_j, a_k)%natom == 0) CYCLE 493 ! Loop over second subcell 494 loop_b_k: DO ik = ik_start, isubcell(3) 495 bg_k = a_k + ik 496 b_k = MOD(bg_k, zdim) 497 b_pk = bg_k/zdim 498 IF (b_k <= 0) THEN 499 b_k = zdim + b_k 500 b_pk = b_pk - 1 501 END IF 502 IF ((periodic(3) == 0) .AND. (ABS(b_pk) > 0)) CYCLE 503 ! Setup the starting point.. this prescreens the order of the subcells 504 ij_start = -isubcell(2) 505 IF ((ik == 0) .AND. (ik_start == 0)) ij_start = 0 506 loop_b_j: DO ij = ij_start, isubcell(2) 507 bg_j = a_j + ij 508 b_j = MOD(bg_j, ydim) 509 b_pj = bg_j/ydim 510 IF (b_j <= 0) THEN 511 b_j = ydim + b_j 512 b_pj = b_pj - 1 513 END IF 514 IF ((periodic(2) == 0) .AND. (ABS(b_pj) > 0)) CYCLE 515 ! Setup the starting point.. this prescreens the order of the subcells 516 ii_start = -isubcell(1) 517 IF ((ij == 0) .AND. (ij_start == 0)) ii_start = 0 518 loop_b_i: DO ii = ii_start, isubcell(1) 519 ! Ellipsoidal screening of subcells 520 IF (.NOT. sphcub(ii, ij, ik)) CYCLE 521 bg_i = a_i + ii 522 b_i = MOD(bg_i, xdim) 523 b_pi = bg_i/xdim 524 IF (b_i <= 0) THEN 525 b_i = xdim + b_i 526 b_pi = b_pi - 1 527 END IF 528 IF ((periodic(1) == 0) .AND. (ABS(b_pi) > 0)) CYCLE 529 IF (subcell_b(b_i, b_j, b_k)%natom == 0) CYCLE 530 ! Find the proper neighbor kind pair 531 icellmap = cellmap(b_pi, b_pj, b_pk) 532 neighbor_kind_pair => nonbonded%neighbor_kind_pairs(icellmap) 533 ! Find the replica vector 534 cell_v = 0.0_dp 535 IF ((b_pi /= 0) .OR. (b_pj /= 0) .OR. (b_pk /= 0)) THEN 536 cv_b(1) = b_pi; cv_b(2) = b_pj; cv_b(3) = b_pk 537 CALL scaled_to_real(cell_v, cv_b, cell) 538 END IF 539 subcell000 = (a_k == bg_k) .AND. (a_j == bg_j) .AND. (a_i == bg_i) 540 ! Loop over particles inside subcell_a and subcell_b 541 DO jatom_local = 1, subcell_b(b_i, b_j, b_k)%natom 542 atom_b = subcell_b(b_i, b_j, b_k)%atom_list(jatom_local) 543 jkind = particle_set(atom_b)%atomic_kind%kind_number 544 rb(1) = coord(1, atom_b) + cell_v(1) 545 rb(2) = coord(2, atom_b) + cell_v(2) 546 rb(3) = coord(3, atom_b) + cell_v(3) 547 DO iatom_local = 1, subcell_a(a_i, a_j, a_k)%natom 548 atom_a = subcell_a(a_i, a_j, a_k)%atom_list(iatom_local) 549 ikind = particle_set(atom_a)%atomic_kind%kind_number 550 ! Screen interaction to avoid double counting 551 atom_order = (atom_a <= atom_b) 552 ! Special case for kind combination requiring the full NL 553 IF (any_full) THEN 554 is_full = full_nl(ikind, jkind) 555 IF (is_full) THEN 556 atom_order = (atom_a == atom_b) 557 ELSE 558 IF (ik < 0) CYCLE 559 IF (ik == 0 .AND. ij < 0) CYCLE 560 IF (ij == 0 .AND. ii < 0) CYCLE 561 END IF 562 END IF 563 IF (subcell000 .AND. atom_order) CYCLE 564 rab(1) = rb(1) - coord(1, atom_a) 565 rab(2) = rb(2) - coord(2, atom_a) 566 rab(3) = rb(3) - coord(3, atom_a) 567 rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3) 568 rab_max = r_max(ikind, jkind) 569 rab2_max = rab_max*rab_max 570 IF (rab2 < rab2_max) THEN 571 ! Diagonal storage 572 j1 = MIN(ikind, jkind) 573 i1 = MAX(ikind, jkind) - j1 + 1 574 j1 = nkind - j1 + 1 575 id_kind = nkind00 - (j1*(j1 + 1)/2) + i1 576 ! Store the pair 577 CALL fist_neighbor_add(neighbor_kind_pair, atom_a, atom_b, & 578 rab=rab, & 579 check_spline=check_spline, id_kind=id_kind, & 580 skip=(skip_kind(ikind) .AND. skip_kind(jkind)), & 581 cell=cell, ei_scale14=ei_scale14, & 582 vdw_scale14=vdw_scale14, exclusions=exclusions) 583 ! This is to handle properly when interaction radius is larger than cell size 584 IF ((atom_a == atom_b) .AND. (ik_start == 0)) THEN 585 invcellmap = cellmap(-b_pi, -b_pj, -b_pk) 586 inv_neighbor_kind_pair => nonbonded%neighbor_kind_pairs(invcellmap) 587 rab = rab - 2.0_dp*cell_v 588 CALL fist_neighbor_add(inv_neighbor_kind_pair, atom_a, atom_b, & 589 rab=rab, & 590 check_spline=check_spline, id_kind=id_kind, & 591 skip=(skip_kind(ikind) .AND. skip_kind(jkind)), & 592 cell=cell, ei_scale14=ei_scale14, & 593 vdw_scale14=vdw_scale14, exclusions=exclusions) 594 END IF 595 ! Check for too close hits 596 IF (check_spline) THEN 597 rab2_min = r_minsq(ikind, jkind) 598 IF (rab2 < rab2_min) THEN 599 iw = cp_logger_get_default_unit_nr() 600 WRITE (iw, '(T2,A,2I7,2(A,F15.8),A)') "WARNING| Particles: ", & 601 atom_a, atom_b, & 602 " at distance [au]:", SQRT(rab2), " less than: ", & 603 SQRT(rab2_min), & 604 "; increase EMAX_SPLINE." 605 IF (rab2 < rab2_min/(1.06_dp)**2) THEN 606 IF (geo_check) THEN 607 CPABORT("GEOMETRY wrong or EMAX_SPLINE too small!") 608 END IF 609 END IF 610 END IF 611 END IF 612 END IF 613 END DO 614 END DO 615 END DO loop_b_i 616 END DO loop_b_j 617 END DO loop_b_k 618 END DO loop_a_i 619 END DO loop_a_j 620 END DO loop_a_k 621 DEALLOCATE (coord) 622 DEALLOCATE (cellmap) 623 DEALLOCATE (sphcub) 624 CALL deallocate_subcell(subcell_a) 625 CALL deallocate_subcell(subcell_b) 626 627 CALL timestop(handle) 628 END SUBROUTINE build_neighbor_lists 629 630! ************************************************************************************************** 631!> \brief Write a set of neighbor lists to the output unit. 632!> \param nonbonded ... 633!> \param particle_set ... 634!> \param cell ... 635!> \param para_env ... 636!> \param output_unit ... 637!> \param name ... 638!> \param unit_str ... 639!> \par History 640!> 08.2006 created [tlaino] 641!> \author Teodoro Laino 642! ************************************************************************************************** 643 SUBROUTINE write_neighbor_lists(nonbonded, particle_set, cell, para_env, output_unit, & 644 name, unit_str) 645 646 TYPE(fist_neighbor_type), POINTER :: nonbonded 647 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set 648 TYPE(cell_type), POINTER :: cell 649 TYPE(cp_para_env_type), POINTER :: para_env 650 INTEGER, INTENT(IN) :: output_unit 651 CHARACTER(LEN=*), INTENT(IN) :: name, unit_str 652 653 CHARACTER(LEN=default_string_length) :: string 654 INTEGER :: atom_a, atom_b, iab, ilist, mype, & 655 nneighbor 656 LOGICAL :: print_headline 657 REAL(dp) :: conv, dab 658 REAL(dp), DIMENSION(3) :: cell_v, ra, rab, rb 659 TYPE(neighbor_kind_pairs_type), POINTER :: neighbor_kind_pair 660 661 mype = para_env%mepos 662 ! Print headline 663 string = "" 664 WRITE (UNIT=string, FMT="(A,I5,A)") & 665 TRIM(name)//" IN "//TRIM(unit_str)//" (PROCESS", mype, ")" 666 CALL compress(string) 667 IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") TRIM(string) 668 669 print_headline = .TRUE. 670 nneighbor = 0 671 conv = cp_unit_from_cp2k(1.0_dp, TRIM(unit_str)) 672 DO iab = 1, SIZE(nonbonded%neighbor_kind_pairs) 673 neighbor_kind_pair => nonbonded%neighbor_kind_pairs(iab) 674 CALL matvec_3x3(cell_v, cell%hmat, REAL(neighbor_kind_pair%cell_vector, KIND=dp)) 675 DO ilist = 1, neighbor_kind_pair%npairs 676 nneighbor = nneighbor + 1 677 IF (output_unit > 0) THEN 678 ! Print second part of the headline 679 atom_a = neighbor_kind_pair%list(1, ilist) 680 atom_b = neighbor_kind_pair%list(2, ilist) 681 IF (print_headline) THEN 682 WRITE (UNIT=output_unit, FMT="(T3,2(A6,3(5X,A,5X)),1X,A11,10X,A8,A5,A10,A9)") & 683 "Atom-A", "X", "Y", "Z", "Atom-B", "X", "Y", "Z", "Cell(i,j,k)", & 684 "Distance", "ONFO", "VDW-scale", "EI-scale" 685 print_headline = .FALSE. 686 END IF 687 688 ra(:) = pbc(particle_set(atom_a)%r, cell) 689 rb(:) = pbc(particle_set(atom_b)%r, cell) 690 rab = rb(:) - ra(:) + cell_v 691 dab = SQRT(DOT_PRODUCT(rab, rab)) 692 IF (ilist <= neighbor_kind_pair%nscale) THEN 693 WRITE (UNIT=output_unit, FMT="(T3,2(I6,3(1X,F10.6)),3(1X,I3),10X,F8.4,L4,F11.5,F9.5)") & 694 atom_a, ra(1:3)*conv, & 695 atom_b, rb(1:3)*conv, & 696 neighbor_kind_pair%cell_vector, & 697 dab*conv, & 698 neighbor_kind_pair%is_onfo(ilist), & 699 neighbor_kind_pair%vdw_scale(ilist), & 700 neighbor_kind_pair%ei_scale(ilist) 701 ELSE 702 WRITE (UNIT=output_unit, FMT="(T3,2(I6,3(1X,F10.6)),3(1X,I3),10X,F8.4)") & 703 atom_a, ra(1:3)*conv, & 704 atom_b, rb(1:3)*conv, & 705 neighbor_kind_pair%cell_vector, & 706 dab*conv 707 END IF 708 END IF 709 END DO ! ilist 710 END DO ! iab 711 712 string = "" 713 WRITE (UNIT=string, FMT="(A,I12,A,I12)") & 714 "Total number of neighbor interactions for process", mype, ":", & 715 nneighbor 716 CALL compress(string) 717 IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="(/,T2,A)") TRIM(string) 718 719 END SUBROUTINE write_neighbor_lists 720 721! ************************************************************************************************** 722!> \brief Sort the generated neighbor list according the kind 723!> \param nonbonded ... 724!> \param nkinds ... 725!> \par History 726!> 09.2007 created [tlaino] University of Zurich - Reducing memory usage 727!> for the FIST neighbor lists 728!> \author Teodoro Laino - University of Zurich 729! ************************************************************************************************** 730 SUBROUTINE sort_neighbor_lists(nonbonded, nkinds) 731 732 TYPE(fist_neighbor_type), POINTER :: nonbonded 733 INTEGER, INTENT(IN) :: nkinds 734 735 CHARACTER(LEN=*), PARAMETER :: routineN = 'sort_neighbor_lists', & 736 routineP = moduleN//':'//routineN 737 738 INTEGER :: handle, iab, id_kind, ikind, ipair, & 739 jkind, max_alloc_size, npairs, nscale, & 740 tmp 741 INTEGER, ALLOCATABLE, DIMENSION(:) :: indj 742 INTEGER, DIMENSION(:), POINTER :: work 743 INTEGER, DIMENSION(:, :), POINTER :: list_copy 744 TYPE(neighbor_kind_pairs_type), POINTER :: neighbor_kind_pair 745 746 NULLIFY (neighbor_kind_pair) 747 CALL timeset(routineN, handle) 748 ! define a lookup table to get jkind for a given id_kind 749 ALLOCATE (indj(nkinds*(nkinds + 1)/2)) 750 id_kind = 0 751 DO jkind = 1, nkinds 752 DO ikind = jkind, nkinds 753 id_kind = id_kind + 1 754 indj(id_kind) = jkind 755 END DO 756 END DO 757 ! loop over all nlists and sort the pairs within each list. 758 DO iab = 1, nonbonded%nlists 759 neighbor_kind_pair => nonbonded%neighbor_kind_pairs(iab) 760 npairs = neighbor_kind_pair%npairs 761 nscale = neighbor_kind_pair%nscale 762 IF (npairs /= 0) THEN 763 IF (npairs > nscale) THEN 764 ! 1) Sort the atom pairs by id_kind. Pairs whose interactions are 765 ! scaled (possibly to zero for exclusion) are not touched. They 766 ! stay packed in the beginning. Sorting is skipped altogether when 767 ! all pairs have scaled interactions. 768 ALLOCATE (work(1:npairs - nscale)) 769 ALLOCATE (list_copy(2, 1:npairs - nscale)) 770 ! Copy of the pair list is required to perform the permutation below 771 ! correctly. 772 list_copy = neighbor_kind_pair%list(:, nscale + 1:npairs) 773 CALL sort(neighbor_kind_pair%id_kind(nscale + 1:npairs), npairs - nscale, work) 774 ! Reorder atoms using the same permutation that was used to sort 775 ! the array id_kind. 776 DO ipair = nscale + 1, npairs 777 tmp = work(ipair - nscale) 778 neighbor_kind_pair%list(1, ipair) = list_copy(1, tmp) 779 neighbor_kind_pair%list(2, ipair) = list_copy(2, tmp) 780 END DO 781 DEALLOCATE (work) 782 DEALLOCATE (list_copy) 783 END IF 784 ! 2) determine the intervals (groups) in the pair list that correspond 785 ! to a certain id_kind. also store the corresponding ikind and 786 ! jkind. Note that this part does not assume ikind to be sorted, 787 ! but it only makes sense when contiguous blobs of the same ikind 788 ! are present. 789 ! Allocate sufficient memory in case all pairs of atom kinds are 790 ! present, and also provide storage for the pairs with exclusion 791 ! flags, which are unsorted. 792 max_alloc_size = nkinds*(nkinds + 1)/2 + nscale 793 IF (ASSOCIATED(neighbor_kind_pair%grp_kind_start)) THEN 794 DEALLOCATE (neighbor_kind_pair%grp_kind_start) 795 END IF 796 ALLOCATE (neighbor_kind_pair%grp_kind_start(max_alloc_size)) 797 IF (ASSOCIATED(neighbor_kind_pair%grp_kind_end)) THEN 798 DEALLOCATE (neighbor_kind_pair%grp_kind_end) 799 END IF 800 ALLOCATE (neighbor_kind_pair%grp_kind_end(max_alloc_size)) 801 IF (ASSOCIATED(neighbor_kind_pair%ij_kind)) THEN 802 DEALLOCATE (neighbor_kind_pair%ij_kind) 803 END IF 804 ALLOCATE (neighbor_kind_pair%ij_kind(2, max_alloc_size)) 805 ! Start the first interval. 806 ipair = 1 807 neighbor_kind_pair%ngrp_kind = 1 808 neighbor_kind_pair%grp_kind_start(neighbor_kind_pair%ngrp_kind) = ipair 809 ! Get ikind and jkind corresponding to id_kind. 810 id_kind = neighbor_kind_pair%id_kind(ipair) 811 jkind = indj(id_kind) 812 tmp = nkinds - jkind 813 ikind = nkinds + id_kind - nkinds*(nkinds + 1)/2 + (tmp*(tmp + 1)/2) 814 neighbor_kind_pair%ij_kind(1, neighbor_kind_pair%ngrp_kind) = ikind 815 neighbor_kind_pair%ij_kind(2, neighbor_kind_pair%ngrp_kind) = jkind 816 ! Define the remaining intervals. 817 DO ipair = 2, npairs 818 IF (neighbor_kind_pair%id_kind(ipair) /= neighbor_kind_pair%id_kind(ipair - 1)) THEN 819 neighbor_kind_pair%grp_kind_end(neighbor_kind_pair%ngrp_kind) = ipair - 1 820 neighbor_kind_pair%ngrp_kind = neighbor_kind_pair%ngrp_kind + 1 821 neighbor_kind_pair%grp_kind_start(neighbor_kind_pair%ngrp_kind) = ipair 822 ! Get ikind and jkind corresponding to id_kind. 823 id_kind = neighbor_kind_pair%id_kind(ipair) 824 jkind = indj(id_kind) 825 tmp = nkinds - jkind 826 ikind = nkinds + id_kind - nkinds*(nkinds + 1)/2 + (tmp*(tmp + 1)/2) 827 neighbor_kind_pair%ij_kind(1, neighbor_kind_pair%ngrp_kind) = ikind 828 neighbor_kind_pair%ij_kind(2, neighbor_kind_pair%ngrp_kind) = jkind 829 END IF 830 END DO 831 ! Finish the last interval. 832 neighbor_kind_pair%grp_kind_end(neighbor_kind_pair%ngrp_kind) = npairs 833 ! Reduce the grp arrays to the actual size because not all pairs of 834 ! atom types have to be present in this pair list. 835 CALL reallocate(neighbor_kind_pair%grp_kind_start, 1, neighbor_kind_pair%ngrp_kind) 836 CALL reallocate(neighbor_kind_pair%grp_kind_end, 1, neighbor_kind_pair%ngrp_kind) 837 CALL reallocate(neighbor_kind_pair%ij_kind, 1, 2, 1, neighbor_kind_pair%ngrp_kind) 838 END IF 839 ! Clean the memory.. 840 DEALLOCATE (neighbor_kind_pair%id_kind) 841 END DO 842 DEALLOCATE (indj) 843 CALL timestop(handle) 844 END SUBROUTINE sort_neighbor_lists 845 846END MODULE fist_neighbor_lists 847