LCOV - code coverage report
Current view: top level - src - kg_environment.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 87.4 % 294 257
Test Date: 2025-07-25 12:55:17 Functions: 83.3 % 6 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines for a Kim-Gordon-like partitioning into molecular subunits
      10              : !> \par History
      11              : !>       2012.07 created [Martin Haeufel]
      12              : !> \author Martin Haeufel
      13              : ! **************************************************************************************************
      14              : MODULE kg_environment
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      16              :                                               get_atomic_kind
      17              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      18              :                                               gto_basis_set_type
      19              :    USE bibliography,                    ONLY: Andermatt2016,&
      20              :                                               cite_reference
      21              :    USE cell_types,                      ONLY: cell_type
      22              :    USE cp_files,                        ONLY: close_file,&
      23              :                                               open_file
      24              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      25              :                                               cp_logger_get_default_io_unit,&
      26              :                                               cp_logger_type
      27              :    USE distribution_1d_types,           ONLY: distribution_1d_type
      28              :    USE distribution_2d_types,           ONLY: distribution_2d_type
      29              :    USE external_potential_types,        ONLY: get_potential,&
      30              :                                               local_potential_type
      31              :    USE input_constants,                 ONLY: kg_tnadd_atomic,&
      32              :                                               kg_tnadd_embed,&
      33              :                                               kg_tnadd_embed_ri,&
      34              :                                               kg_tnadd_none
      35              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      36              :                                               section_vals_type,&
      37              :                                               section_vals_val_get
      38              :    USE integration_grid_types,          ONLY: allocate_intgrid,&
      39              :                                               integration_grid_type
      40              :    USE kg_environment_types,            ONLY: kg_environment_type
      41              :    USE kg_vertex_coloring_methods,      ONLY: kg_vertex_coloring
      42              :    USE kinds,                           ONLY: dp,&
      43              :                                               int_4,&
      44              :                                               int_4_size,&
      45              :                                               int_8
      46              :    USE lri_environment_init,            ONLY: lri_env_basis,&
      47              :                                               lri_env_init
      48              :    USE message_passing,                 ONLY: mp_para_env_type
      49              :    USE molecule_types,                  ONLY: molecule_type
      50              :    USE particle_types,                  ONLY: particle_type
      51              :    USE qs_environment_types,            ONLY: get_qs_env,&
      52              :                                               qs_environment_type
      53              :    USE qs_grid_atom,                    ONLY: initialize_atomic_grid
      54              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      55              :                                               qs_kind_type
      56              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      57              :                                               neighbor_list_iterate,&
      58              :                                               neighbor_list_iterator_create,&
      59              :                                               neighbor_list_iterator_p_type,&
      60              :                                               neighbor_list_iterator_release,&
      61              :                                               neighbor_list_set_p_type,&
      62              :                                               release_neighbor_list_sets
      63              :    USE qs_neighbor_lists,               ONLY: atom2d_build,&
      64              :                                               atom2d_cleanup,&
      65              :                                               build_neighbor_lists,&
      66              :                                               local_atoms_type,&
      67              :                                               pair_radius_setup,&
      68              :                                               write_neighbor_lists
      69              :    USE string_utilities,                ONLY: uppercase
      70              :    USE task_list_types,                 ONLY: deallocate_task_list
      71              :    USE util,                            ONLY: sort
      72              : #include "./base/base_uses.f90"
      73              : 
      74              :    IMPLICIT NONE
      75              : 
      76              :    PRIVATE
      77              : 
      78              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kg_environment'
      79              : 
      80              :    PUBLIC :: kg_env_create, kg_build_neighborlist, kg_build_subsets
      81              : 
      82              : CONTAINS
      83              : 
      84              : ! **************************************************************************************************
      85              : !> \brief Allocates and intitializes kg_env
      86              : !> \param qs_env ...
      87              : !> \param kg_env the object to create
      88              : !> \param qs_kind_set ...
      89              : !> \param input ...
      90              : !> \par History
      91              : !>       2012.07 created [Martin Haeufel]
      92              : !> \author Martin Haeufel
      93              : ! **************************************************************************************************
      94           66 :    SUBROUTINE kg_env_create(qs_env, kg_env, qs_kind_set, input)
      95              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      96              :       TYPE(kg_environment_type), POINTER                 :: kg_env
      97              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      98              :       TYPE(section_vals_type), OPTIONAL, POINTER         :: input
      99              : 
     100           66 :       ALLOCATE (kg_env)
     101           66 :       CALL init_kg_env(qs_env, kg_env, qs_kind_set, input)
     102           66 :    END SUBROUTINE kg_env_create
     103              : 
     104              : ! **************************************************************************************************
     105              : !> \brief Initializes kg_env
     106              : !> \param qs_env ...
     107              : !> \param kg_env ...
     108              : !> \param qs_kind_set ...
     109              : !> \param input ...
     110              : !> \par History
     111              : !>       2012.07 created [Martin Haeufel]
     112              : !>       2018.01 TNADD correction {JGH]
     113              : !> \author Martin Haeufel
     114              : ! **************************************************************************************************
     115           66 :    SUBROUTINE init_kg_env(qs_env, kg_env, qs_kind_set, input)
     116              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     117              :       TYPE(kg_environment_type), POINTER                 :: kg_env
     118              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     119              :       TYPE(section_vals_type), OPTIONAL, POINTER         :: input
     120              : 
     121              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'init_kg_env'
     122              : 
     123              :       CHARACTER(LEN=10)                                  :: intgrid
     124              :       INTEGER                                            :: handle, i, iatom, ib, ikind, iunit, n, &
     125              :                                                             na, natom, nbatch, nkind, np, nr
     126           66 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: bid
     127              :       REAL(KIND=dp)                                      :: load, radb, rmax
     128              :       TYPE(cp_logger_type), POINTER                      :: logger
     129              :       TYPE(gto_basis_set_type), POINTER                  :: lri_aux_basis
     130              :       TYPE(integration_grid_type), POINTER               :: ig_full, ig_mol
     131              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     132              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     133              :       TYPE(section_vals_type), POINTER                   :: lri_section
     134              : 
     135           66 :       CALL timeset(routineN, handle)
     136              : 
     137           66 :       CALL cite_reference(Andermatt2016)
     138              : 
     139           66 :       NULLIFY (para_env)
     140           66 :       NULLIFY (kg_env%sab_orb_full)
     141           66 :       NULLIFY (kg_env%sac_kin)
     142           66 :       NULLIFY (kg_env%subset_of_mol)
     143           66 :       NULLIFY (kg_env%subset)
     144           66 :       NULLIFY (kg_env%tnadd_mat)
     145           66 :       NULLIFY (kg_env%lri_env)
     146           66 :       NULLIFY (kg_env%lri_env1)
     147           66 :       NULLIFY (kg_env%int_grid_atom)
     148           66 :       NULLIFY (kg_env%int_grid_molecules)
     149           66 :       NULLIFY (kg_env%int_grid_full)
     150           66 :       NULLIFY (kg_env%lri_density)
     151           66 :       NULLIFY (kg_env%lri_rho1)
     152              : 
     153           66 :       kg_env%nsubsets = 0
     154              : 
     155              :       ! get coloring method settings
     156           66 :       CALL section_vals_val_get(input, "DFT%KG_METHOD%COLORING_METHOD", i_val=kg_env%coloring_method)
     157              :       ! get method for nonadditive kinetic energy embedding potential
     158           66 :       CALL section_vals_val_get(input, "DFT%KG_METHOD%TNADD_METHOD", i_val=kg_env%tnadd_method)
     159              :       !
     160          118 :       SELECT CASE (kg_env%tnadd_method)
     161              :       CASE (kg_tnadd_embed, kg_tnadd_embed_ri)
     162              :          ! kinetic energy functional
     163           52 :          kg_env%xc_section_kg => section_vals_get_subs_vals(input, "DFT%KG_METHOD%XC")
     164           52 :          IF (.NOT. ASSOCIATED(kg_env%xc_section_kg)) THEN
     165              :             CALL cp_abort(__LOCATION__, &
     166            0 :                           "KG runs require a kinetic energy functional set in &KG_METHOD")
     167              :          END IF
     168              :       CASE (kg_tnadd_atomic, kg_tnadd_none)
     169           14 :          NULLIFY (kg_env%xc_section_kg)
     170              :       CASE DEFAULT
     171           66 :          CPABORT("KG:TNADD METHOD")
     172              :       END SELECT
     173              : 
     174           66 :       IF (kg_env%tnadd_method == kg_tnadd_embed_ri) THEN
     175              :          ! initialize the LRI environment
     176              :          ! Check if LRI_AUX basis is available
     177            2 :          rmax = 0.0_dp
     178            2 :          nkind = SIZE(qs_kind_set)
     179            6 :          DO ikind = 1, nkind
     180            4 :             qs_kind => qs_kind_set(ikind)
     181            4 :             NULLIFY (lri_aux_basis)
     182            4 :             CALL get_qs_kind(qs_kind, basis_set=lri_aux_basis, basis_type="LRI_AUX")
     183            4 :             CPASSERT(ASSOCIATED(lri_aux_basis))
     184            4 :             CALL get_gto_basis_set(gto_basis_set=lri_aux_basis, kind_radius=radb)
     185            6 :             rmax = MAX(rmax, radb)
     186              :          END DO
     187            2 :          rmax = 1.25_dp*rmax
     188            2 :          lri_section => section_vals_get_subs_vals(input, "DFT%KG_METHOD%LRIGPW")
     189            2 :          CALL lri_env_init(kg_env%lri_env, lri_section)
     190            2 :          CALL lri_env_basis("LRI", qs_env, kg_env%lri_env, qs_kind_set)
     191              :          !
     192              :          ! if energy correction is performed with force calculation,
     193              :          ! then response calculation requires
     194              :          ! perturbation density for kernel calculation
     195            2 :          CALL lri_env_init(kg_env%lri_env1, lri_section)
     196            2 :          CALL lri_env_basis("LRI", qs_env, kg_env%lri_env1, qs_kind_set)
     197              :          !
     198              :          ! integration grid
     199              :          !
     200            2 :          CALL section_vals_val_get(input, "DFT%KG_METHOD%INTEGRATION_GRID", c_val=intgrid)
     201            2 :          CALL uppercase(intgrid)
     202            2 :          SELECT CASE (intgrid)
     203              :          CASE ("SMALL")
     204            2 :             nr = 50
     205            2 :             na = 38
     206              :          CASE ("MEDIUM")
     207            0 :             nr = 100
     208            0 :             na = 110
     209              :          CASE ("LARGE")
     210            0 :             nr = 200
     211            0 :             na = 302
     212              :          CASE ("HUGE")
     213            0 :             nr = 400
     214            0 :             na = 590
     215              :          CASE DEFAULT
     216            2 :             CPABORT("KG:INTEGRATION_GRID")
     217              :          END SELECT
     218            2 :          NULLIFY (logger)
     219            2 :          logger => cp_get_default_logger()
     220            2 :          iunit = cp_logger_get_default_io_unit(logger)
     221            2 :          CALL initialize_atomic_grid(kg_env%int_grid_atom, nr, na, rmax, iunit=iunit)
     222              :          ! load balancing
     223            2 :          CALL get_qs_env(qs_env=qs_env, natom=natom, para_env=para_env)
     224            2 :          np = para_env%num_pe
     225            2 :          load = REAL(natom, KIND=dp)*kg_env%int_grid_atom%ntot/REAL(np, KIND=dp)
     226              :          !
     227            2 :          CALL allocate_intgrid(kg_env%int_grid_full)
     228            2 :          ig_full => kg_env%int_grid_full
     229            2 :          CALL allocate_intgrid(kg_env%int_grid_molecules)
     230            2 :          ig_mol => kg_env%int_grid_molecules
     231            2 :          nbatch = (natom*kg_env%int_grid_atom%nbatch)/np
     232            2 :          nbatch = NINT((nbatch + 1)*1.2_dp)
     233            6 :          ALLOCATE (bid(2, nbatch))
     234           12 :          nbatch = 0
     235           12 :          DO iatom = 1, natom
     236          892 :             DO ib = 1, kg_env%int_grid_atom%nbatch
     237          890 :                IF (para_env%mepos == MOD(iatom + ib, np)) THEN
     238          440 :                   nbatch = nbatch + 1
     239          440 :                   CPASSERT(nbatch <= SIZE(bid, 2))
     240          440 :                   bid(1, nbatch) = iatom
     241          440 :                   bid(2, nbatch) = ib
     242              :                END IF
     243              :             END DO
     244              :          END DO
     245              :          !
     246            2 :          ig_full%nbatch = nbatch
     247          452 :          ALLOCATE (ig_full%grid_batch(nbatch))
     248              :          !
     249            2 :          ig_mol%nbatch = nbatch
     250          450 :          ALLOCATE (ig_mol%grid_batch(nbatch))
     251              :          !
     252          442 :          DO i = 1, nbatch
     253          440 :             iatom = bid(1, i)
     254          440 :             ib = bid(2, i)
     255              :             !
     256          440 :             ig_full%grid_batch(i)%ref_atom = iatom
     257          440 :             ig_full%grid_batch(i)%ibatch = ib
     258          440 :             ig_full%grid_batch(i)%np = kg_env%int_grid_atom%batch(ib)%np
     259          440 :             ig_full%grid_batch(i)%radius = kg_env%int_grid_atom%batch(ib)%rad
     260         3080 :             ig_full%grid_batch(i)%rcenter(1:3) = kg_env%int_grid_atom%batch(ib)%rcenter(1:3)
     261          440 :             n = ig_full%grid_batch(i)%np
     262         1320 :             ALLOCATE (ig_full%grid_batch(i)%rco(3, n))
     263         1320 :             ALLOCATE (ig_full%grid_batch(i)%weight(n))
     264          880 :             ALLOCATE (ig_full%grid_batch(i)%wref(n))
     265          880 :             ALLOCATE (ig_full%grid_batch(i)%wsum(n))
     266        19440 :             ig_full%grid_batch(i)%weight(:) = kg_env%int_grid_atom%batch(ib)%weight(:)
     267              :             !
     268          440 :             ig_mol%grid_batch(i)%ref_atom = iatom
     269          440 :             ig_mol%grid_batch(i)%ibatch = ib
     270          440 :             ig_mol%grid_batch(i)%np = kg_env%int_grid_atom%batch(ib)%np
     271          440 :             ig_mol%grid_batch(i)%radius = kg_env%int_grid_atom%batch(ib)%rad
     272         3080 :             ig_mol%grid_batch(i)%rcenter(1:3) = kg_env%int_grid_atom%batch(ib)%rcenter(1:3)
     273          440 :             n = ig_mol%grid_batch(i)%np
     274         1320 :             ALLOCATE (ig_mol%grid_batch(i)%rco(3, n))
     275         1320 :             ALLOCATE (ig_mol%grid_batch(i)%weight(n))
     276          880 :             ALLOCATE (ig_mol%grid_batch(i)%wref(n))
     277          880 :             ALLOCATE (ig_mol%grid_batch(i)%wsum(n))
     278        19442 :             ig_mol%grid_batch(i)%weight(:) = kg_env%int_grid_atom%batch(ib)%weight(:)
     279              :          END DO
     280              :          !
     281            2 :          DEALLOCATE (bid)
     282              :       END IF
     283              : 
     284           66 :       CALL timestop(handle)
     285              : 
     286           66 :    END SUBROUTINE init_kg_env
     287              : 
     288              : ! **************************************************************************************************
     289              : !> \brief builds either the full neighborlist or neighborlists of molecular
     290              : !> \brief subsets, depending on parameter values
     291              : !> \param qs_env ...
     292              : !> \param sab_orb the return type, a neighborlist
     293              : !> \param sac_kin ...
     294              : !> \param molecular if false, the full neighborlist is build
     295              : !> \param subset_of_mol the molecular subsets
     296              : !> \param current_subset the subset of which the neighborlist is to be build
     297              : !> \par History
     298              : !>       2012.07 created [Martin Haeufel]
     299              : !> \author Martin Haeufel
     300              : ! **************************************************************************************************
     301          306 :    SUBROUTINE kg_build_neighborlist(qs_env, sab_orb, sac_kin, &
     302              :                                     molecular, subset_of_mol, current_subset)
     303              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     304              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     305              :          OPTIONAL, POINTER                               :: sab_orb, sac_kin
     306              :       LOGICAL, OPTIONAL                                  :: molecular
     307              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: subset_of_mol
     308              :       INTEGER, OPTIONAL                                  :: current_subset
     309              : 
     310              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kg_build_neighborlist'
     311              : 
     312              :       INTEGER                                            :: handle, ikind, nkind
     313              :       LOGICAL                                            :: mic, molecule_only
     314              :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: orb_present, tpot_present
     315              :       REAL(dp)                                           :: subcells
     316              :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: orb_radius, tpot_radius
     317              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: pair_radius
     318          306 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     319              :       TYPE(cell_type), POINTER                           :: cell
     320              :       TYPE(distribution_1d_type), POINTER                :: distribution_1d
     321              :       TYPE(distribution_2d_type), POINTER                :: distribution_2d
     322              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     323          306 :       TYPE(local_atoms_type), ALLOCATABLE, DIMENSION(:)  :: atom2d
     324              :       TYPE(local_potential_type), POINTER                :: tnadd_potential
     325          306 :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     326              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     327          306 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     328          306 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     329              :       TYPE(section_vals_type), POINTER                   :: neighbor_list_section
     330              : 
     331          306 :       CALL timeset(routineN, handle)
     332          306 :       NULLIFY (para_env)
     333              : 
     334              :       ! restrict lists to molecular subgroups
     335          306 :       molecule_only = .FALSE.
     336          306 :       IF (PRESENT(molecular)) molecule_only = molecular
     337              :       ! enforce minimum image convention if we use molecules
     338          306 :       mic = molecule_only
     339              : 
     340              :       CALL get_qs_env(qs_env=qs_env, &
     341              :                       atomic_kind_set=atomic_kind_set, &
     342              :                       qs_kind_set=qs_kind_set, &
     343              :                       cell=cell, &
     344              :                       distribution_2d=distribution_2d, &
     345              :                       molecule_set=molecule_set, &
     346              :                       local_particles=distribution_1d, &
     347              :                       particle_set=particle_set, &
     348          306 :                       para_env=para_env)
     349              : 
     350          306 :       CALL section_vals_val_get(qs_env%input, "DFT%SUBCELLS", r_val=subcells)
     351              : 
     352              :       ! Allocate work storage
     353          306 :       nkind = SIZE(atomic_kind_set)
     354         1224 :       ALLOCATE (orb_radius(nkind), tpot_radius(nkind))
     355          770 :       orb_radius(:) = 0.0_dp
     356          770 :       tpot_radius(:) = 0.0_dp
     357         1224 :       ALLOCATE (orb_present(nkind), tpot_present(nkind))
     358         1224 :       ALLOCATE (pair_radius(nkind, nkind))
     359         1382 :       ALLOCATE (atom2d(nkind))
     360              : 
     361              :       CALL atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, &
     362          306 :                         molecule_set, molecule_only, particle_set=particle_set)
     363              : 
     364          770 :       DO ikind = 1, nkind
     365          464 :          CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom2d(ikind)%list)
     366          464 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     367          770 :          IF (ASSOCIATED(orb_basis_set)) THEN
     368          464 :             orb_present(ikind) = .TRUE.
     369          464 :             IF (PRESENT(subset_of_mol)) THEN
     370          258 :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, kind_radius=orb_radius(ikind))
     371              :             ELSE
     372          206 :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, short_kind_radius=orb_radius(ikind))
     373              :             END IF
     374              :          ELSE
     375            0 :             orb_present(ikind) = .FALSE.
     376            0 :             orb_radius(ikind) = 0.0_dp
     377              :          END IF
     378              :       END DO
     379              : 
     380          306 :       IF (PRESENT(sab_orb)) THEN
     381              :          ! Build the orbital-orbital overlap neighbor list
     382          284 :          CALL pair_radius_setup(orb_present, orb_present, orb_radius, orb_radius, pair_radius)
     383          284 :          IF (PRESENT(subset_of_mol)) THEN
     384              :             CALL build_neighbor_lists(sab_orb, particle_set, atom2d, cell, pair_radius, &
     385              :                                       mic=mic, subcells=subcells, molecular=molecule_only, subset_of_mol=subset_of_mol, &
     386          170 :                                       current_subset=current_subset, nlname="sab_orb")
     387              :          ELSE
     388              :             CALL build_neighbor_lists(sab_orb, particle_set, atom2d, cell, pair_radius, &
     389          114 :                                       mic=mic, subcells=subcells, molecular=molecule_only, nlname="sab_orb")
     390              :          END IF
     391              :          ! Print out the neighborlist
     392          284 :          neighbor_list_section => section_vals_get_subs_vals(qs_env%input, "DFT%KG_METHOD%PRINT%NEIGHBOR_LISTS")
     393          284 :          IF (molecule_only) THEN
     394              :             CALL write_neighbor_lists(sab_orb, particle_set, cell, para_env, neighbor_list_section, &
     395          172 :                                       "/SAB_ORB_MOLECULAR", "sab_orb", "MOLECULAR SUBSET NEIGHBORLIST")
     396              :          ELSE
     397              :             CALL write_neighbor_lists(sab_orb, particle_set, cell, para_env, neighbor_list_section, &
     398          112 :                                       "/SAB_ORB_FULL", "sab_orb", "FULL NEIGHBORLIST")
     399              :          END IF
     400              :       END IF
     401              : 
     402          306 :       IF (PRESENT(sac_kin)) THEN
     403           56 :          DO ikind = 1, nkind
     404           34 :             tpot_present(ikind) = .FALSE.
     405           34 :             CALL get_qs_kind(qs_kind_set(ikind), tnadd_potential=tnadd_potential)
     406           56 :             IF (ASSOCIATED(tnadd_potential)) THEN
     407           34 :                CALL get_potential(potential=tnadd_potential, radius=tpot_radius(ikind))
     408           34 :                tpot_present(ikind) = .TRUE.
     409              :             END IF
     410              :          END DO
     411           22 :          CALL pair_radius_setup(orb_present, tpot_present, orb_radius, tpot_radius, pair_radius)
     412              :          CALL build_neighbor_lists(sac_kin, particle_set, atom2d, cell, pair_radius, &
     413           22 :                                    subcells=subcells, operator_type="ABC", nlname="sac_kin")
     414              :          neighbor_list_section => section_vals_get_subs_vals(qs_env%input, &
     415           22 :                                                              "DFT%KG_METHOD%PRINT%NEIGHBOR_LISTS")
     416              :          CALL write_neighbor_lists(sac_kin, particle_set, cell, para_env, neighbor_list_section, &
     417           22 :                                    "/SAC_KIN", "sac_kin", "ORBITAL kin energy potential")
     418              :       END IF
     419              : 
     420              :       ! Release work storage
     421          306 :       CALL atom2d_cleanup(atom2d)
     422          306 :       DEALLOCATE (atom2d)
     423          306 :       DEALLOCATE (orb_present, tpot_present)
     424          306 :       DEALLOCATE (orb_radius, tpot_radius)
     425          306 :       DEALLOCATE (pair_radius)
     426              : 
     427          306 :       CALL timestop(handle)
     428              : 
     429          918 :    END SUBROUTINE kg_build_neighborlist
     430              : 
     431              : ! **************************************************************************************************
     432              : !> \brief Removes all replicated pairs from a 2d integer buffer array
     433              : !> \param pairs_buffer the array, assumed to have the shape (2,:)
     434              : !> \param n number of pairs (in), number of disjunct pairs (out)
     435              : !> \par History
     436              : !>       2012.07 created [Martin Haeufel]
     437              : !>       2014.11 simplified [Ole Schuett]
     438              : !> \author Martin Haeufel
     439              : ! **************************************************************************************************
     440          123 :    SUBROUTINE kg_remove_duplicates(pairs_buffer, n)
     441              :       INTEGER(KIND=int_4), DIMENSION(:, :), &
     442              :          INTENT(INOUT)                                   :: pairs_buffer
     443              :       INTEGER, INTENT(INOUT)                             :: n
     444              : 
     445              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kg_remove_duplicates'
     446              : 
     447              :       INTEGER                                            :: handle, i, npairs
     448          246 :       INTEGER, DIMENSION(n)                              :: ind
     449          246 :       INTEGER(KIND=int_8), DIMENSION(n)                  :: sort_keys
     450          246 :       INTEGER(KIND=int_4), DIMENSION(2, n)               :: work
     451              : 
     452          123 :       CALL timeset(routineN, handle)
     453              : 
     454          123 :       IF (n > 0) THEN
     455              :          ! represent a pair of int_4 as a single int_8 number, simplifies sorting.
     456         4489 :          sort_keys(1:n) = ISHFT(INT(pairs_buffer(1, 1:n), KIND=int_8), 8*int_4_size)
     457         4489 :          sort_keys(1:n) = sort_keys(1:n) + pairs_buffer(2, 1:n) !upper + lower bytes
     458          111 :          CALL sort(sort_keys, n, ind)
     459              : 
     460              :          ! add first pair, the case npairs==0 was excluded above
     461          111 :          npairs = 1
     462          333 :          work(:, 1) = pairs_buffer(:, ind(1))
     463              : 
     464              :          ! remove duplicates from the sorted list
     465         4378 :          DO i = 2, n
     466         4378 :             IF (sort_keys(i) /= sort_keys(i - 1)) THEN
     467          195 :                npairs = npairs + 1
     468          585 :                work(:, npairs) = pairs_buffer(:, ind(i))
     469              :             END IF
     470              :          END DO
     471              : 
     472          111 :          n = npairs
     473         1029 :          pairs_buffer(:, :n) = work(:, :n)
     474              :       END IF
     475              : 
     476          123 :       CALL timestop(handle)
     477              : 
     478          123 :    END SUBROUTINE kg_remove_duplicates
     479              : 
     480              : ! **************************************************************************************************
     481              : !> \brief writes the graph to file using the DIMACS standard format
     482              : !>        for a definition of the file format see
     483              : !>        mat.gsia.cmu.edu?COLOR/general/ccformat.ps
     484              : !>        c comment line
     485              : !>        p edge NODES EDGES
     486              : !>        with NODES - number of nodes
     487              : !>        EDGES - numer of edges
     488              : !>        e W V
     489              : !>        ...
     490              : !>        there is one edge descriptor line for each edge in the graph
     491              : !>        for an edge (w,v) the fields W and V specify its endpoints
     492              : !> \param pairs ...
     493              : !> \param nnodes the total number of nodes
     494              : ! **************************************************************************************************
     495            0 :    SUBROUTINE write_to_file(pairs, nnodes)
     496              :       INTEGER(KIND=int_4), ALLOCATABLE, &
     497              :          DIMENSION(:, :), INTENT(IN)                     :: pairs
     498              :       INTEGER, INTENT(IN)                                :: nnodes
     499              : 
     500              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_to_file'
     501              : 
     502              :       INTEGER                                            :: handle, i, imol, jmol, npairs, unit_nr
     503              :       INTEGER(KIND=int_4), ALLOCATABLE, DIMENSION(:, :)  :: sorted_pairs
     504              : 
     505            0 :       CALL timeset(routineN, handle)
     506              : 
     507              :       ! get the number of disjunct pairs
     508            0 :       npairs = SIZE(pairs, 2)
     509              : 
     510            0 :       ALLOCATE (sorted_pairs(2, npairs))
     511              : 
     512              :       ! reorder pairs such that pairs(1,*) < pairs(2,*)
     513            0 :       DO i = 1, npairs
     514              :          ! get molecular ids
     515            0 :          imol = pairs(1, i)
     516            0 :          jmol = pairs(2, i)
     517            0 :          IF (imol > jmol) THEN
     518              :             ! switch pair and store
     519            0 :             sorted_pairs(1, i) = jmol
     520            0 :             sorted_pairs(2, i) = imol
     521              :          ELSE
     522              :             ! keep ordering just copy
     523            0 :             sorted_pairs(1, i) = imol
     524            0 :             sorted_pairs(2, i) = jmol
     525              :          END IF
     526              :       END DO
     527              : 
     528              :       ! remove duplicates and get the number of disjunct pairs (number of edges)
     529            0 :       CALL kg_remove_duplicates(sorted_pairs, npairs)
     530              : 
     531              :       ! should now be half as much pairs as before
     532            0 :       CPASSERT(npairs == SIZE(pairs, 2)/2)
     533              : 
     534            0 :       CALL open_file(unit_number=unit_nr, file_name="graph.col")
     535              : 
     536            0 :       WRITE (unit_nr, '(A6,1X,I8,1X,I8)') "p edge", nnodes, npairs
     537              : 
     538              :       ! only write out the first npairs entries
     539            0 :       DO i = 1, npairs
     540            0 :          WRITE (unit_nr, '(A1,1X,I8,1X,I8)') "e", sorted_pairs(1, i), sorted_pairs(2, i)
     541              :       END DO
     542              : 
     543            0 :       CALL close_file(unit_nr)
     544              : 
     545            0 :       DEALLOCATE (sorted_pairs)
     546              : 
     547            0 :       CALL timestop(handle)
     548              : 
     549            0 :    END SUBROUTINE write_to_file
     550              : 
     551              : ! **************************************************************************************************
     552              : !> \brief ...
     553              : !> \param kg_env ...
     554              : !> \param para_env ...
     555              : ! **************************************************************************************************
     556           82 :    SUBROUTINE kg_build_subsets(kg_env, para_env)
     557              :       TYPE(kg_environment_type), POINTER                 :: kg_env
     558              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     559              : 
     560              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'kg_build_subsets'
     561              : 
     562              :       INTEGER                                            :: color, handle, i, iatom, imol, isub, &
     563              :                                                             jatom, jmol, nmol, npairs, npairs_local
     564              :       INTEGER(KIND=int_4)                                :: ncolors
     565           82 :       INTEGER(KIND=int_4), ALLOCATABLE, DIMENSION(:)     :: color_of_node
     566           82 :       INTEGER(KIND=int_4), ALLOCATABLE, DIMENSION(:, :)  :: msg_gather, pairs, pairs_buffer
     567           82 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nnodes_of_color
     568              :       TYPE(neighbor_list_iterator_p_type), &
     569           82 :          DIMENSION(:), POINTER                           :: nl_iterator
     570              : 
     571           82 :       CALL timeset(routineN, handle)
     572              : 
     573              :       ! first: get a (local) list of pairs from the (local) neighbor list data
     574           82 :       nmol = SIZE(kg_env%molecule_set)
     575              : 
     576           82 :       npairs = 0
     577           82 :       CALL neighbor_list_iterator_create(nl_iterator, kg_env%sab_orb_full)
     578         4976 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     579         4894 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom)
     580              : 
     581         4894 :          imol = kg_env%atom_to_molecule(iatom)
     582         4894 :          jmol = kg_env%atom_to_molecule(jatom)
     583              : 
     584              :          !IF (imol<jmol) THEN
     585         4976 :          IF (imol .NE. jmol) THEN
     586              : 
     587         2087 :             npairs = npairs + 2
     588              : 
     589              :          END IF
     590              : 
     591              :       END DO
     592           82 :       CALL neighbor_list_iterator_release(nl_iterator)
     593              : 
     594          238 :       ALLOCATE (pairs_buffer(2, npairs))
     595              : 
     596           82 :       npairs = 0
     597           82 :       CALL neighbor_list_iterator_create(nl_iterator, kg_env%sab_orb_full)
     598         4976 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     599         4894 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom)
     600              : 
     601         4894 :          imol = kg_env%atom_to_molecule(iatom)
     602         4894 :          jmol = kg_env%atom_to_molecule(jatom)
     603              : 
     604         4976 :          IF (imol .NE. jmol) THEN
     605              : 
     606              :             ! add pair to the local list
     607              : 
     608              :             ! add both orderings - makes it easier to build the neighborlist
     609         2087 :             npairs = npairs + 1
     610              : 
     611         2087 :             pairs_buffer(1, npairs) = imol
     612         2087 :             pairs_buffer(2, npairs) = jmol
     613              : 
     614         2087 :             npairs = npairs + 1
     615              : 
     616         2087 :             pairs_buffer(2, npairs) = imol
     617         2087 :             pairs_buffer(1, npairs) = jmol
     618              : 
     619              :          END IF
     620              : 
     621              :       END DO
     622           82 :       CALL neighbor_list_iterator_release(nl_iterator)
     623              : 
     624              :       ! remove duplicates
     625           82 :       CALL kg_remove_duplicates(pairs_buffer, npairs)
     626              : 
     627              :       ! get the maximum number of local pairs on all nodes (size of the mssg)
     628              :       ! remember how many pairs we have local
     629           82 :       npairs_local = npairs
     630           82 :       CALL para_env%max(npairs)
     631              : 
     632              :       ! allocate message
     633          238 :       ALLOCATE (pairs(2, npairs))
     634              : 
     635          694 :       pairs(:, 1:npairs_local) = pairs_buffer(:, 1:npairs_local)
     636           82 :       pairs(:, npairs_local + 1:) = 0
     637              : 
     638           82 :       DEALLOCATE (pairs_buffer)
     639              : 
     640              :       ! second: gather all data on the master node
     641              :       ! better would be a scheme where duplicates are removed in a tree-like reduction scheme.
     642              :       ! this step can be needlessly memory intensive in the current implementation.
     643              : 
     644           82 :       IF (para_env%is_source()) THEN
     645          119 :          ALLOCATE (msg_gather(2, npairs*para_env%num_pe))
     646              :       ELSE
     647           41 :          ALLOCATE (msg_gather(2, 1))
     648              :       END IF
     649              : 
     650          817 :       msg_gather = 0
     651              : 
     652           82 :       CALL para_env%gather(pairs, msg_gather)
     653              : 
     654           82 :       DEALLOCATE (pairs)
     655              : 
     656           82 :       IF (para_env%is_source()) THEN
     657              : 
     658              :          ! shift all non-zero entries to the beginning of the array and count the number of actual pairs
     659           41 :          npairs = 0
     660              : 
     661          245 :          DO i = 1, SIZE(msg_gather, 2)
     662          245 :             IF (msg_gather(1, i) .NE. 0) THEN
     663          204 :                npairs = npairs + 1
     664          612 :                msg_gather(:, npairs) = msg_gather(:, i)
     665              :             END IF
     666              :          END DO
     667              : 
     668              :          ! remove duplicates
     669           41 :          CALL kg_remove_duplicates(msg_gather, npairs)
     670              : 
     671          119 :          ALLOCATE (pairs(2, npairs))
     672              : 
     673          347 :          pairs(:, 1:npairs) = msg_gather(:, 1:npairs)
     674              : 
     675           41 :          DEALLOCATE (msg_gather)
     676              : 
     677              :          !WRITE(*,'(A48,5X,I10,4X,A2,1X,I10)') " KG| Total number of overlapping molecular pairs",npairs/2,"of",nmol*(nmol-1)/2
     678              : 
     679              :          ! write to file, nnodes = number of molecules
     680              :          IF (.FALSE.) THEN
     681              :             CALL write_to_file(pairs, SIZE(kg_env%molecule_set))
     682              :          END IF
     683              : 
     684              :          ! vertex coloring algorithm
     685           41 :          CALL kg_vertex_coloring(kg_env, pairs, ncolors, color_of_node)
     686              : 
     687           41 :          DEALLOCATE (pairs)
     688              : 
     689              :       ELSE
     690              : 
     691           41 :          DEALLOCATE (msg_gather)
     692              : 
     693              :       END IF
     694              : 
     695              :       !WRITE(*,'(A27,40X,I6,1X,A6)') ' KG| Vertex coloring result', ncolors, 'colors'
     696              : 
     697              :       ! broadcast the number of colors to all nodes
     698           82 :       CALL para_env%bcast(ncolors)
     699              : 
     700          164 :       IF (.NOT. ALLOCATED(color_of_node)) ALLOCATE (color_of_node(nmol))
     701              : 
     702              :       ! broadcast the resulting coloring to all nodes.....
     703           82 :       CALL para_env%bcast(color_of_node)
     704              : 
     705           82 :       IF ((kg_env%nsubsets .NE. 0) .AND. (ncolors .NE. kg_env%nsubsets)) THEN
     706              :          ! number of subsets has changed
     707              : 
     708              :          ! deallocate stuff if necessary
     709            0 :          IF (ASSOCIATED(kg_env%subset)) THEN
     710            0 :             DO isub = 1, kg_env%nsubsets
     711            0 :                CALL release_neighbor_list_sets(kg_env%subset(isub)%sab_orb)
     712            0 :                CALL deallocate_task_list(kg_env%subset(isub)%task_list)
     713              :             END DO
     714            0 :             DEALLOCATE (kg_env%subset)
     715            0 :             NULLIFY (kg_env%subset)
     716              :          END IF
     717              : 
     718              :       END IF
     719              : 
     720              :       ! allocate and nullify some stuff
     721           82 :       IF (.NOT. ASSOCIATED(kg_env%subset)) THEN
     722              : 
     723          256 :          ALLOCATE (kg_env%subset(ncolors))
     724              : 
     725          156 :          DO i = 1, ncolors
     726          106 :             NULLIFY (kg_env%subset(i)%sab_orb)
     727          156 :             NULLIFY (kg_env%subset(i)%task_list)
     728              :          END DO
     729              :       END IF
     730              : 
     731              :       ! set the number of subsets
     732           82 :       kg_env%nsubsets = ncolors
     733              : 
     734              :       ! counting loop
     735          246 :       ALLOCATE (nnodes_of_color(ncolors))
     736          252 :       nnodes_of_color = 0
     737          268 :       DO i = 1, nmol ! nmol=nnodes
     738          186 :          color = color_of_node(i)
     739          186 :          kg_env%subset_of_mol(i) = color
     740          268 :          nnodes_of_color(color) = nnodes_of_color(color) + 1
     741              :       END DO
     742              : 
     743           82 :       DEALLOCATE (nnodes_of_color)
     744           82 :       DEALLOCATE (color_of_node)
     745              : 
     746           82 :       CALL timestop(handle)
     747              : 
     748          164 :    END SUBROUTINE kg_build_subsets
     749              : 
     750              : END MODULE kg_environment
        

Generated by: LCOV version 2.0-1