LCOV - code coverage report
Current view: top level - src - kg_environment.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 87.4 % 294 257
Test Date: 2026-05-06 07:07:47 Functions: 83.3 % 6 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 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           94 :    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           94 :       ALLOCATE (kg_env)
     101           94 :       CALL init_kg_env(qs_env, kg_env, qs_kind_set, input)
     102           94 :    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           94 :    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           94 :       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           94 :       CALL timeset(routineN, handle)
     136              : 
     137           94 :       CALL cite_reference(Andermatt2016)
     138              : 
     139           94 :       NULLIFY (para_env)
     140           94 :       NULLIFY (kg_env%sab_orb_full)
     141           94 :       NULLIFY (kg_env%sac_kin)
     142           94 :       NULLIFY (kg_env%subset_of_mol)
     143           94 :       NULLIFY (kg_env%subset)
     144           94 :       NULLIFY (kg_env%tnadd_mat)
     145           94 :       NULLIFY (kg_env%lri_env)
     146           94 :       NULLIFY (kg_env%lri_env1)
     147           94 :       NULLIFY (kg_env%int_grid_atom)
     148           94 :       NULLIFY (kg_env%int_grid_molecules)
     149           94 :       NULLIFY (kg_env%int_grid_full)
     150           94 :       NULLIFY (kg_env%lri_density)
     151           94 :       NULLIFY (kg_env%lri_rho1)
     152              : 
     153           94 :       kg_env%nsubsets = 0
     154              : 
     155              :       ! get coloring method settings
     156           94 :       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           94 :       CALL section_vals_val_get(input, "DFT%KG_METHOD%TNADD_METHOD", i_val=kg_env%tnadd_method)
     159              :       !
     160          166 :       SELECT CASE (kg_env%tnadd_method)
     161              :       CASE (kg_tnadd_embed, kg_tnadd_embed_ri)
     162              :          ! kinetic energy functional
     163           72 :          kg_env%xc_section_kg => section_vals_get_subs_vals(input, "DFT%KG_METHOD%XC")
     164           72 :          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           22 :          NULLIFY (kg_env%xc_section_kg)
     170              :       CASE DEFAULT
     171           94 :          CPABORT("KG:TNADD METHOD")
     172              :       END SELECT
     173              : 
     174           94 :       IF (kg_env%tnadd_method == kg_tnadd_embed_ri) THEN
     175              :          ! initialize the LRI environment
     176              :          ! Check if LRI_AUX basis is available
     177           10 :          rmax = 0.0_dp
     178           10 :          nkind = SIZE(qs_kind_set)
     179           30 :          DO ikind = 1, nkind
     180           20 :             qs_kind => qs_kind_set(ikind)
     181           20 :             NULLIFY (lri_aux_basis)
     182           20 :             CALL get_qs_kind(qs_kind, basis_set=lri_aux_basis, basis_type="LRI_AUX")
     183           20 :             CPASSERT(ASSOCIATED(lri_aux_basis))
     184           20 :             CALL get_gto_basis_set(gto_basis_set=lri_aux_basis, kind_radius=radb)
     185           30 :             rmax = MAX(rmax, radb)
     186              :          END DO
     187           10 :          rmax = 1.25_dp*rmax
     188           10 :          lri_section => section_vals_get_subs_vals(input, "DFT%KG_METHOD%LRIGPW")
     189           10 :          CALL lri_env_init(kg_env%lri_env, lri_section)
     190           10 :          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           10 :          CALL lri_env_init(kg_env%lri_env1, lri_section)
     196           10 :          CALL lri_env_basis("LRI", qs_env, kg_env%lri_env1, qs_kind_set)
     197              :          !
     198              :          ! integration grid
     199              :          !
     200           10 :          CALL section_vals_val_get(input, "DFT%KG_METHOD%INTEGRATION_GRID", c_val=intgrid)
     201           10 :          CALL uppercase(intgrid)
     202           10 :          SELECT CASE (intgrid)
     203              :          CASE ("SMALL")
     204           10 :             nr = 50
     205           10 :             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           10 :             CPABORT("KG:INTEGRATION_GRID")
     217              :          END SELECT
     218           10 :          NULLIFY (logger)
     219           10 :          logger => cp_get_default_logger()
     220           10 :          iunit = cp_logger_get_default_io_unit(logger)
     221           10 :          CALL initialize_atomic_grid(kg_env%int_grid_atom, nr, na, rmax, iunit=iunit)
     222              :          ! load balancing
     223           10 :          CALL get_qs_env(qs_env=qs_env, natom=natom, para_env=para_env)
     224           10 :          np = para_env%num_pe
     225           10 :          load = REAL(natom, KIND=dp)*kg_env%int_grid_atom%ntot/REAL(np, KIND=dp)
     226              :          !
     227           10 :          CALL allocate_intgrid(kg_env%int_grid_full)
     228           10 :          ig_full => kg_env%int_grid_full
     229           10 :          CALL allocate_intgrid(kg_env%int_grid_molecules)
     230           10 :          ig_mol => kg_env%int_grid_molecules
     231           10 :          nbatch = (natom*kg_env%int_grid_atom%nbatch)/np
     232           10 :          nbatch = NINT((nbatch + 1)*1.2_dp)
     233           30 :          ALLOCATE (bid(2, nbatch))
     234           60 :          nbatch = 0
     235           60 :          DO iatom = 1, natom
     236         4460 :             DO ib = 1, kg_env%int_grid_atom%nbatch
     237         4450 :                IF (para_env%mepos == MOD(iatom + ib, np)) THEN
     238         2200 :                   nbatch = nbatch + 1
     239         2200 :                   CPASSERT(nbatch <= SIZE(bid, 2))
     240         2200 :                   bid(1, nbatch) = iatom
     241         2200 :                   bid(2, nbatch) = ib
     242              :                END IF
     243              :             END DO
     244              :          END DO
     245              :          !
     246           10 :          ig_full%nbatch = nbatch
     247         2260 :          ALLOCATE (ig_full%grid_batch(nbatch))
     248              :          !
     249           10 :          ig_mol%nbatch = nbatch
     250         2250 :          ALLOCATE (ig_mol%grid_batch(nbatch))
     251              :          !
     252         2210 :          DO i = 1, nbatch
     253         2200 :             iatom = bid(1, i)
     254         2200 :             ib = bid(2, i)
     255              :             !
     256         2200 :             ig_full%grid_batch(i)%ref_atom = iatom
     257         2200 :             ig_full%grid_batch(i)%ibatch = ib
     258         2200 :             ig_full%grid_batch(i)%np = kg_env%int_grid_atom%batch(ib)%np
     259         2200 :             ig_full%grid_batch(i)%radius = kg_env%int_grid_atom%batch(ib)%rad
     260        15400 :             ig_full%grid_batch(i)%rcenter(1:3) = kg_env%int_grid_atom%batch(ib)%rcenter(1:3)
     261         2200 :             n = ig_full%grid_batch(i)%np
     262         6600 :             ALLOCATE (ig_full%grid_batch(i)%rco(3, n))
     263         6600 :             ALLOCATE (ig_full%grid_batch(i)%weight(n))
     264         4400 :             ALLOCATE (ig_full%grid_batch(i)%wref(n))
     265         4400 :             ALLOCATE (ig_full%grid_batch(i)%wsum(n))
     266        97200 :             ig_full%grid_batch(i)%weight(:) = kg_env%int_grid_atom%batch(ib)%weight(:)
     267              :             !
     268         2200 :             ig_mol%grid_batch(i)%ref_atom = iatom
     269         2200 :             ig_mol%grid_batch(i)%ibatch = ib
     270         2200 :             ig_mol%grid_batch(i)%np = kg_env%int_grid_atom%batch(ib)%np
     271         2200 :             ig_mol%grid_batch(i)%radius = kg_env%int_grid_atom%batch(ib)%rad
     272        15400 :             ig_mol%grid_batch(i)%rcenter(1:3) = kg_env%int_grid_atom%batch(ib)%rcenter(1:3)
     273         2200 :             n = ig_mol%grid_batch(i)%np
     274         6600 :             ALLOCATE (ig_mol%grid_batch(i)%rco(3, n))
     275         6600 :             ALLOCATE (ig_mol%grid_batch(i)%weight(n))
     276         4400 :             ALLOCATE (ig_mol%grid_batch(i)%wref(n))
     277         4400 :             ALLOCATE (ig_mol%grid_batch(i)%wsum(n))
     278        97210 :             ig_mol%grid_batch(i)%weight(:) = kg_env%int_grid_atom%batch(ib)%weight(:)
     279              :          END DO
     280              :          !
     281           10 :          DEALLOCATE (bid)
     282              :       END IF
     283              : 
     284           94 :       CALL timestop(handle)
     285              : 
     286           94 :    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          402 :    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          402 :       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          402 :       TYPE(local_atoms_type), ALLOCATABLE, DIMENSION(:)  :: atom2d
     324              :       TYPE(local_potential_type), POINTER                :: tnadd_potential
     325          402 :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     326              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     327          402 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     328          402 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     329              :       TYPE(section_vals_type), POINTER                   :: neighbor_list_section
     330              : 
     331          402 :       CALL timeset(routineN, handle)
     332          402 :       NULLIFY (para_env)
     333              : 
     334              :       ! restrict lists to molecular subgroups
     335          402 :       molecule_only = .FALSE.
     336          402 :       IF (PRESENT(molecular)) molecule_only = molecular
     337              :       ! enforce minimum image convention if we use molecules
     338          402 :       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          402 :                       para_env=para_env)
     349              : 
     350          402 :       CALL section_vals_val_get(qs_env%input, "DFT%SUBCELLS", r_val=subcells)
     351              : 
     352              :       ! Allocate work storage
     353          402 :       nkind = SIZE(atomic_kind_set)
     354         1608 :       ALLOCATE (orb_radius(nkind), tpot_radius(nkind))
     355          994 :       orb_radius(:) = 0.0_dp
     356          994 :       tpot_radius(:) = 0.0_dp
     357         1608 :       ALLOCATE (orb_present(nkind), tpot_present(nkind))
     358         1608 :       ALLOCATE (pair_radius(nkind, nkind))
     359         1798 :       ALLOCATE (atom2d(nkind))
     360              : 
     361              :       CALL atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, &
     362          402 :                         molecule_set, molecule_only, particle_set=particle_set)
     363              : 
     364          994 :       DO ikind = 1, nkind
     365          592 :          CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom2d(ikind)%list)
     366          592 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     367          994 :          IF (ASSOCIATED(orb_basis_set)) THEN
     368          592 :             orb_present(ikind) = .TRUE.
     369          592 :             IF (PRESENT(subset_of_mol)) THEN
     370          326 :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, kind_radius=orb_radius(ikind))
     371              :             ELSE
     372          266 :                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          402 :       IF (PRESENT(sab_orb)) THEN
     381              :          ! Build the orbital-orbital overlap neighbor list
     382          372 :          CALL pair_radius_setup(orb_present, orb_present, orb_radius, orb_radius, pair_radius)
     383          372 :          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          222 :                                       current_subset=current_subset, nlname="sab_orb")
     387              :          ELSE
     388              :             CALL build_neighbor_lists(sab_orb, particle_set, atom2d, cell, pair_radius, &
     389          150 :                                       mic=mic, subcells=subcells, molecular=molecule_only, nlname="sab_orb")
     390              :          END IF
     391              :          ! Print out the neighborlist
     392          372 :          neighbor_list_section => section_vals_get_subs_vals(qs_env%input, "DFT%KG_METHOD%PRINT%NEIGHBOR_LISTS")
     393          372 :          IF (molecule_only) THEN
     394              :             CALL write_neighbor_lists(sab_orb, particle_set, cell, para_env, neighbor_list_section, &
     395          232 :                                       "/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          140 :                                       "/SAB_ORB_FULL", "sab_orb", "FULL NEIGHBORLIST")
     399              :          END IF
     400              :       END IF
     401              : 
     402          402 :       IF (PRESENT(sac_kin)) THEN
     403           72 :          DO ikind = 1, nkind
     404           42 :             tpot_present(ikind) = .FALSE.
     405           42 :             CALL get_qs_kind(qs_kind_set(ikind), tnadd_potential=tnadd_potential)
     406           72 :             IF (ASSOCIATED(tnadd_potential)) THEN
     407           42 :                CALL get_potential(potential=tnadd_potential, radius=tpot_radius(ikind))
     408           42 :                tpot_present(ikind) = .TRUE.
     409              :             END IF
     410              :          END DO
     411           30 :          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           30 :                                    subcells=subcells, operator_type="ABC", nlname="sac_kin")
     414              :          neighbor_list_section => section_vals_get_subs_vals(qs_env%input, &
     415           30 :                                                              "DFT%KG_METHOD%PRINT%NEIGHBOR_LISTS")
     416              :          CALL write_neighbor_lists(sac_kin, particle_set, cell, para_env, neighbor_list_section, &
     417           30 :                                    "/SAC_KIN", "sac_kin", "ORBITAL kin energy potential")
     418              :       END IF
     419              : 
     420              :       ! Release work storage
     421          402 :       CALL atom2d_cleanup(atom2d)
     422          402 :       DEALLOCATE (atom2d)
     423          402 :       DEALLOCATE (orb_present, tpot_present)
     424          402 :       DEALLOCATE (orb_radius, tpot_radius)
     425          402 :       DEALLOCATE (pair_radius)
     426              : 
     427          402 :       CALL timestop(handle)
     428              : 
     429         1206 :    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          153 :    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          306 :       INTEGER, DIMENSION(n)                              :: ind
     449          306 :       INTEGER(KIND=int_8), DIMENSION(n)                  :: sort_keys
     450          306 :       INTEGER(KIND=int_4), DIMENSION(2, n)               :: work
     451              : 
     452          153 :       CALL timeset(routineN, handle)
     453              : 
     454          153 :       IF (n > 0) THEN
     455              :          ! represent a pair of int_4 as a single int_8 number, simplifies sorting.
     456         9195 :          sort_keys(1:n) = ISHFT(INT(pairs_buffer(1, 1:n), KIND=int_8), 8*int_4_size)
     457         9195 :          sort_keys(1:n) = sort_keys(1:n) + pairs_buffer(2, 1:n) !upper + lower bytes
     458          141 :          CALL sort(sort_keys, n, ind)
     459              : 
     460              :          ! add first pair, the case npairs==0 was excluded above
     461          141 :          npairs = 1
     462          423 :          work(:, 1) = pairs_buffer(:, ind(1))
     463              : 
     464              :          ! remove duplicates from the sorted list
     465         9054 :          DO i = 2, n
     466         9054 :             IF (sort_keys(i) /= sort_keys(i - 1)) THEN
     467          297 :                npairs = npairs + 1
     468          891 :                work(:, npairs) = pairs_buffer(:, ind(i))
     469              :             END IF
     470              :          END DO
     471              : 
     472          141 :          n = npairs
     473         1455 :          pairs_buffer(:, :n) = work(:, :n)
     474              :       END IF
     475              : 
     476          153 :       CALL timestop(handle)
     477              : 
     478          153 :    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          102 :    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          102 :       INTEGER(KIND=int_4), ALLOCATABLE, DIMENSION(:)     :: color_of_node
     566          102 :       INTEGER(KIND=int_4), ALLOCATABLE, DIMENSION(:, :)  :: msg_gather, pairs, pairs_buffer
     567          102 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nnodes_of_color
     568              :       TYPE(neighbor_list_iterator_p_type), &
     569          102 :          DIMENSION(:), POINTER                           :: nl_iterator
     570              : 
     571          102 :       CALL timeset(routineN, handle)
     572              : 
     573              :       ! first: get a (local) list of pairs from the (local) neighbor list data
     574          102 :       nmol = SIZE(kg_env%molecule_set)
     575              : 
     576          102 :       npairs = 0
     577          102 :       CALL neighbor_list_iterator_create(nl_iterator, kg_env%sab_orb_full)
     578        10421 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     579        10319 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom)
     580              : 
     581        10319 :          imol = kg_env%atom_to_molecule(iatom)
     582        10319 :          jmol = kg_env%atom_to_molecule(jatom)
     583              : 
     584              :          !IF (imol<jmol) THEN
     585        10421 :          IF (imol /= jmol) THEN
     586              : 
     587         4381 :             npairs = npairs + 2
     588              : 
     589              :          END IF
     590              : 
     591              :       END DO
     592          102 :       CALL neighbor_list_iterator_release(nl_iterator)
     593              : 
     594          298 :       ALLOCATE (pairs_buffer(2, npairs))
     595              : 
     596          102 :       npairs = 0
     597          102 :       CALL neighbor_list_iterator_create(nl_iterator, kg_env%sab_orb_full)
     598        10421 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     599        10319 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom)
     600              : 
     601        10319 :          imol = kg_env%atom_to_molecule(iatom)
     602        10319 :          jmol = kg_env%atom_to_molecule(jatom)
     603              : 
     604        10421 :          IF (imol /= jmol) THEN
     605              : 
     606              :             ! add pair to the local list
     607              : 
     608              :             ! add both orderings - makes it easier to build the neighborlist
     609         4381 :             npairs = npairs + 1
     610              : 
     611         4381 :             pairs_buffer(1, npairs) = imol
     612         4381 :             pairs_buffer(2, npairs) = jmol
     613              : 
     614         4381 :             npairs = npairs + 1
     615              : 
     616         4381 :             pairs_buffer(2, npairs) = imol
     617         4381 :             pairs_buffer(1, npairs) = jmol
     618              : 
     619              :          END IF
     620              : 
     621              :       END DO
     622          102 :       CALL neighbor_list_iterator_release(nl_iterator)
     623              : 
     624              :       ! remove duplicates
     625          102 :       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          102 :       npairs_local = npairs
     630          102 :       CALL para_env%max(npairs)
     631              : 
     632              :       ! allocate message
     633          298 :       ALLOCATE (pairs(2, npairs))
     634              : 
     635          978 :       pairs(:, 1:npairs_local) = pairs_buffer(:, 1:npairs_local)
     636          102 :       pairs(:, npairs_local + 1:) = 0
     637              : 
     638          102 :       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          102 :       IF (para_env%is_source()) THEN
     645          149 :          ALLOCATE (msg_gather(2, npairs*para_env%num_pe))
     646              :       ELSE
     647           51 :          ALLOCATE (msg_gather(2, 1))
     648              :       END IF
     649              : 
     650         1131 :       msg_gather = 0
     651              : 
     652          102 :       CALL para_env%gather(pairs, msg_gather)
     653              : 
     654          102 :       DEALLOCATE (pairs)
     655              : 
     656          102 :       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           51 :          npairs = 0
     660              : 
     661          343 :          DO i = 1, SIZE(msg_gather, 2)
     662          343 :             IF (msg_gather(1, i) /= 0) THEN
     663          292 :                npairs = npairs + 1
     664          876 :                msg_gather(:, npairs) = msg_gather(:, i)
     665              :             END IF
     666              :          END DO
     667              : 
     668              :          ! remove duplicates
     669           51 :          CALL kg_remove_duplicates(msg_gather, npairs)
     670              : 
     671          149 :          ALLOCATE (pairs(2, npairs))
     672              : 
     673          489 :          pairs(:, 1:npairs) = msg_gather(:, 1:npairs)
     674              : 
     675           51 :          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           51 :          CALL kg_vertex_coloring(kg_env, pairs, ncolors, color_of_node)
     686              : 
     687           51 :          DEALLOCATE (pairs)
     688              : 
     689              :       ELSE
     690              : 
     691           51 :          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          102 :       CALL para_env%bcast(ncolors)
     699              : 
     700          204 :       IF (.NOT. ALLOCATED(color_of_node)) ALLOCATE (color_of_node(nmol))
     701              : 
     702              :       ! broadcast the resulting coloring to all nodes.....
     703          102 :       CALL para_env%bcast(color_of_node)
     704              : 
     705          102 :       IF ((kg_env%nsubsets /= 0) .AND. (ncolors /= 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          102 :       IF (.NOT. ASSOCIATED(kg_env%subset)) THEN
     722              : 
     723          368 :          ALLOCATE (kg_env%subset(ncolors))
     724              : 
     725          228 :          DO i = 1, ncolors
     726          158 :             NULLIFY (kg_env%subset(i)%sab_orb)
     727          228 :             NULLIFY (kg_env%subset(i)%task_list)
     728              :          END DO
     729              :       END IF
     730              : 
     731              :       ! set the number of subsets
     732          102 :       kg_env%nsubsets = ncolors
     733              : 
     734              :       ! counting loop
     735          306 :       ALLOCATE (nnodes_of_color(ncolors))
     736          324 :       nnodes_of_color = 0
     737          340 :       DO i = 1, nmol ! nmol=nnodes
     738          238 :          color = color_of_node(i)
     739          238 :          kg_env%subset_of_mol(i) = color
     740          340 :          nnodes_of_color(color) = nnodes_of_color(color) + 1
     741              :       END DO
     742              : 
     743          102 :       DEALLOCATE (nnodes_of_color)
     744          102 :       DEALLOCATE (color_of_node)
     745              : 
     746          102 :       CALL timestop(handle)
     747              : 
     748          204 :    END SUBROUTINE kg_build_subsets
     749              : 
     750              : END MODULE kg_environment
        

Generated by: LCOV version 2.0-1