LCOV - code coverage report
Current view: top level - src - population_analyses.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cb5d5fc) Lines: 97.9 % 243 238
Test Date: 2026-04-24 07:01:27 Functions: 100.0 % 4 4

            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              : !> \brief Provide various population analyses and print the requested output
       9              : !>        information
      10              : !>
      11              : !> \author  Matthias Krack (MK)
      12              : !> \date    09.07.2010
      13              : !> \version 1.0
      14              : ! **************************************************************************************************
      15              : 
      16              : MODULE population_analyses
      17              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18              :                                               get_atomic_kind,&
      19              :                                               get_atomic_kind_set
      20              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      21              :                                               gto_basis_set_type
      22              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      23              :    USE cp_dbcsr_api,                    ONLY: &
      24              :         dbcsr_copy, dbcsr_deallocate_matrix, dbcsr_get_block_p, dbcsr_iterator_blocks_left, &
      25              :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      26              :         dbcsr_p_type, dbcsr_set, dbcsr_type
      27              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      28              :                                               cp_dbcsr_sm_fm_multiply
      29              :    USE cp_dbcsr_output,                 ONLY: cp_dbcsr_write_sparse_matrix,&
      30              :                                               write_fm_with_basis_info
      31              :    USE cp_fm_diag,                      ONLY: cp_fm_power
      32              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      33              :                                               cp_fm_struct_release,&
      34              :                                               cp_fm_struct_type
      35              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      36              :                                               cp_fm_get_diag,&
      37              :                                               cp_fm_release,&
      38              :                                               cp_fm_type
      39              :    USE cp_result_methods,               ONLY: cp_results_erase,&
      40              :                                               put_results
      41              :    USE cp_result_types,                 ONLY: cp_result_type
      42              :    USE kinds,                           ONLY: default_string_length,&
      43              :                                               dp
      44              :    USE kpoint_methods,                  ONLY: lowdin_kp_trans
      45              :    USE kpoint_types,                    ONLY: kpoint_type
      46              :    USE machine,                         ONLY: m_flush
      47              :    USE message_passing,                 ONLY: mp_para_env_type
      48              :    USE orbital_pointers,                ONLY: nso
      49              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      50              :    USE particle_methods,                ONLY: get_particle_set
      51              :    USE particle_types,                  ONLY: particle_type
      52              :    USE qs_environment_types,            ONLY: get_qs_env,&
      53              :                                               qs_environment_type
      54              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      55              :                                               get_qs_kind_set,&
      56              :                                               qs_kind_type
      57              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      58              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      59              :                                               qs_rho_type
      60              :    USE qs_scf_diagonalization,          ONLY: diag_kp_smat
      61              :    USE scf_control_types,               ONLY: scf_control_type
      62              : #include "./base/base_uses.f90"
      63              : 
      64              :    IMPLICIT NONE
      65              : 
      66              :    PRIVATE
      67              : 
      68              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'population_analyses'
      69              : 
      70              :    PUBLIC :: lowdin_population_analysis, &
      71              :              mulliken_population_analysis
      72              : 
      73              : CONTAINS
      74              : 
      75              : ! **************************************************************************************************
      76              : !> \brief Perform a Lowdin population analysis based on a symmetric
      77              : !>        orthogonalisation of the density matrix using S^(1/2)
      78              : !>
      79              : !> \param qs_env ...
      80              : !> \param output_unit ...
      81              : !> \param print_level ...
      82              : !> \date    06.07.2010
      83              : !> \author  Matthias Krack (MK)
      84              : !> \version 1.0
      85              : ! **************************************************************************************************
      86          108 :    SUBROUTINE lowdin_population_analysis(qs_env, output_unit, print_level)
      87              : 
      88              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      89              :       INTEGER, INTENT(IN)                                :: output_unit, print_level
      90              : 
      91              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'lowdin_population_analysis'
      92              : 
      93              :       CHARACTER(LEN=default_string_length)               :: headline
      94              :       INTEGER                                            :: handle, i, ispin, ndep, nimg, nsgf, nspin
      95              :       LOGICAL                                            :: do_kpoints, print_gop
      96          108 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: orbpop
      97          108 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      98              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
      99              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     100              :       TYPE(cp_fm_type)                                   :: fm_s_half, fm_work1, fm_work2
     101          108 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
     102          108 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_p
     103          108 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrixkp_p, matrixkp_s
     104              :       TYPE(dbcsr_type), POINTER                          :: sm_p, sm_s
     105              :       TYPE(kpoint_type), POINTER                         :: kpoints
     106              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     107              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     108          108 :          POINTER                                         :: sab_nl
     109          108 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     110          108 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     111              :       TYPE(qs_rho_type), POINTER                         :: rho
     112              :       TYPE(scf_control_type), POINTER                    :: scf_control
     113              : 
     114          108 :       CALL timeset(routineN, handle)
     115              : 
     116          108 :       NULLIFY (sm_p, sm_s)
     117              : 
     118              :       CALL get_qs_env(qs_env=qs_env, &
     119              :                       atomic_kind_set=atomic_kind_set, &
     120              :                       qs_kind_set=qs_kind_set, &
     121              :                       do_kpoints=do_kpoints, &
     122              :                       matrix_s_kp=matrixkp_s, &
     123              :                       particle_set=particle_set, &
     124              :                       rho=rho, &
     125              :                       scf_control=scf_control, &
     126              :                       para_env=para_env, &
     127          108 :                       blacs_env=blacs_env)
     128              : 
     129          108 :       CALL qs_rho_get(rho, rho_ao_kp=matrixkp_p) ! Density matrices in sparse format
     130          108 :       nspin = SIZE(matrixkp_p, 1)
     131          108 :       nimg = SIZE(matrixkp_p, 2)
     132              : 
     133              :       ! Get the total number of contracted spherical Gaussian basis functions
     134          108 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nsgf)
     135              :       ! Provide an array to store the orbital populations for each spin
     136          432 :       ALLOCATE (orbpop(nsgf, nspin))
     137         3238 :       orbpop(:, :) = 0.0_dp
     138              : 
     139              :       ! Write headline
     140          108 :       IF (output_unit > 0) THEN
     141           54 :          WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") "LOWDIN POPULATION ANALYSIS"
     142              :       END IF
     143              : 
     144          108 :       IF (do_kpoints) THEN
     145              : 
     146            4 :          CALL get_qs_env(qs_env=qs_env, kpoints=kpoints, sab_orb=sab_nl)
     147              : 
     148              :          ! work matrices
     149              :          CALL cp_fm_struct_create(fmstruct, para_env=para_env, context=blacs_env, &
     150            4 :                                   nrow_global=nsgf, ncol_global=nsgf)
     151           20 :          ALLOCATE (fmwork(4))
     152           20 :          DO i = 1, 4
     153           20 :             CALL cp_fm_create(fmwork(i), matrix_struct=fmstruct, name="work")
     154              :          END DO
     155            4 :          CALL cp_fm_struct_release(fmstruct)
     156              : 
     157              :          ! S^1/2
     158            4 :          CALL diag_kp_smat(matrixkp_s, kpoints, fmwork)
     159              :          ! Lowdin P Matrix Transform
     160            4 :          CALL lowdin_kp_trans(kpoints, orbpop)
     161              : 
     162            4 :          CALL cp_fm_release(fmwork)
     163              : 
     164              :       ELSE
     165              : 
     166          104 :          sm_s => matrixkp_s(1, 1)%matrix ! Overlap matrix in sparse format
     167          104 :          matrix_p => matrixkp_p(:, 1)
     168              : 
     169              :          ! Provide full size work matrices
     170              :          CALL cp_fm_struct_create(fmstruct=fmstruct, &
     171              :                                   para_env=para_env, &
     172              :                                   context=blacs_env, &
     173              :                                   nrow_global=nsgf, &
     174          104 :                                   ncol_global=nsgf)
     175              :          CALL cp_fm_create(matrix=fm_s_half, &
     176              :                            matrix_struct=fmstruct, &
     177          104 :                            name="S^(1/2) MATRIX")
     178              :          CALL cp_fm_create(matrix=fm_work1, &
     179              :                            matrix_struct=fmstruct, &
     180          104 :                            name="FULL WORK MATRIX 1")
     181          104 :          headline = "SYMMETRICALLY ORTHOGONALISED DENSITY MATRIX"
     182              :          CALL cp_fm_create(matrix=fm_work2, &
     183              :                            matrix_struct=fmstruct, &
     184          104 :                            name=TRIM(headline))
     185          104 :          CALL cp_fm_struct_release(fmstruct=fmstruct)
     186              : 
     187              :          ! Build full S^(1/2) matrix (computationally expensive)
     188          104 :          CALL copy_dbcsr_to_fm(sm_s, fm_s_half)
     189          104 :          CALL cp_fm_power(fm_s_half, fm_work1, 0.5_dp, scf_control%eps_eigval, ndep)
     190          104 :          IF (ndep /= 0) &
     191              :             CALL cp_warn(__LOCATION__, &
     192              :                          "Overlap matrix exhibits linear dependencies. At least some "// &
     193            0 :                          "eigenvalues have been quenched.")
     194              : 
     195              :          ! Build Lowdin population matrix for each spin
     196          212 :          DO ispin = 1, nspin
     197          108 :             sm_p => matrix_p(ispin)%matrix ! Density matrix for spin ispin in sparse format
     198              :             ! Calculate S^(1/2)*P*S^(1/2) as a full matrix (Lowdin)
     199          108 :             CALL cp_dbcsr_sm_fm_multiply(sm_p, fm_s_half, fm_work1, nsgf)
     200              :             CALL parallel_gemm(transa="N", &
     201              :                                transb="N", &
     202              :                                m=nsgf, &
     203              :                                n=nsgf, &
     204              :                                k=nsgf, &
     205              :                                alpha=1.0_dp, &
     206              :                                matrix_a=fm_s_half, &
     207              :                                matrix_b=fm_work1, &
     208              :                                beta=0.0_dp, &
     209          108 :                                matrix_c=fm_work2)
     210          108 :             IF (print_level > 2) THEN
     211              :                ! Write the full Lowdin population matrix
     212            4 :                IF (nspin > 1) THEN
     213            4 :                   IF (ispin == 1) THEN
     214            2 :                      fm_work2%name = TRIM(headline)//" FOR ALPHA SPIN"
     215              :                   ELSE
     216            2 :                      fm_work2%name = TRIM(headline)//" FOR BETA SPIN"
     217              :                   END IF
     218              :                END IF
     219              :                CALL write_fm_with_basis_info(fm_work2, 4, 6, qs_env, para_env, &
     220            4 :                                              output_unit=output_unit)
     221              :             END IF
     222          212 :             CALL cp_fm_get_diag(fm_work2, orbpop(:, ispin))
     223              :          END DO ! next spin ispin
     224              : 
     225              :          ! Release local working storage
     226          104 :          CALL cp_fm_release(matrix=fm_s_half)
     227          104 :          CALL cp_fm_release(matrix=fm_work1)
     228          104 :          CALL cp_fm_release(matrix=fm_work2)
     229              : 
     230              :       END IF
     231              : 
     232              :       ! Write atomic populations and charges
     233          108 :       IF (output_unit > 0) THEN
     234           54 :          print_gop = (print_level > 1) ! Print also orbital populations
     235           54 :          CALL write_orbpop(orbpop, atomic_kind_set, qs_kind_set, particle_set, output_unit, print_gop)
     236              :       END IF
     237              : 
     238          108 :       DEALLOCATE (orbpop)
     239              : 
     240          108 :       CALL timestop(handle)
     241              : 
     242          324 :    END SUBROUTINE lowdin_population_analysis
     243              : 
     244              : ! **************************************************************************************************
     245              : !> \brief Perform a Mulliken population analysis
     246              : !>
     247              : !> \param qs_env ...
     248              : !> \param output_unit ...
     249              : !> \param print_level ...
     250              : !> \date    10.07.2010
     251              : !> \author  Matthias Krack (MK)
     252              : !> \version 1.0
     253              : ! **************************************************************************************************
     254         5030 :    SUBROUTINE mulliken_population_analysis(qs_env, output_unit, print_level)
     255              : 
     256              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     257              :       INTEGER, INTENT(IN)                                :: output_unit, print_level
     258              : 
     259              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mulliken_population_analysis'
     260              : 
     261              :       CHARACTER(LEN=default_string_length)               :: headline
     262              :       INTEGER                                            :: handle, iatom, ic, isgf, ispin, jatom, &
     263              :                                                             jsgf, natom, nsgf, nspin, sgfa, sgfb
     264         5030 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: first_sgf_atom
     265              :       LOGICAL                                            :: found, print_gop
     266              :       REAL(KIND=dp)                                      :: ps
     267         5030 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: orbpop
     268         5030 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: p_block, ps_block, s_block
     269         5030 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     270              :       TYPE(dbcsr_iterator_type)                          :: iter
     271         5030 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p, matrix_s
     272              :       TYPE(dbcsr_type), POINTER                          :: sm_p, sm_ps, sm_s
     273              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     274         5030 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     275         5030 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     276              :       TYPE(qs_rho_type), POINTER                         :: rho
     277              : 
     278         5030 :       CALL timeset(routineN, handle)
     279              : 
     280         5030 :       NULLIFY (sm_p, sm_ps, sm_s)
     281         5030 :       NULLIFY (p_block, s_block, ps_block)
     282              : 
     283              :       CALL get_qs_env(qs_env=qs_env, &
     284              :                       atomic_kind_set=atomic_kind_set, &
     285              :                       qs_kind_set=qs_kind_set, &
     286              :                       matrix_s_kp=matrix_s, &
     287              :                       particle_set=particle_set, &
     288              :                       rho=rho, &
     289         5030 :                       para_env=para_env)
     290              : 
     291         5030 :       CALL qs_rho_get(rho, rho_ao_kp=matrix_p) ! Density matrices in sparse format
     292         5030 :       nspin = SIZE(matrix_p, 1)
     293              : 
     294              :       ! Get the total number of contracted spherical Gaussian basis functions
     295         5030 :       CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
     296         5030 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nsgf)
     297        15090 :       ALLOCATE (first_sgf_atom(natom))
     298        26182 :       first_sgf_atom(:) = 0
     299              : 
     300         5030 :       CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf_atom)
     301              : 
     302              :       ! Provide an array to store the orbital populations for each spin
     303        20120 :       ALLOCATE (orbpop(nsgf, nspin))
     304       175836 :       orbpop(:, :) = 0.0_dp
     305              : 
     306              :       ! Write headline
     307         5030 :       IF (output_unit > 0) THEN
     308              :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     309         2529 :             '!-----------------------------------------------------------------------------!'
     310         2529 :          WRITE (UNIT=output_unit, FMT="(T22,A)") "Mulliken Population Analysis"
     311              :       END IF
     312              : 
     313              :       ! Create a DBCSR work matrix, if needed
     314         5030 :       IF (print_level > 2) THEN
     315            2 :          sm_s => matrix_s(1, 1)%matrix ! Overlap matrix in sparse format
     316            2 :          ALLOCATE (sm_ps)
     317            2 :          headline = "MULLIKEN NET ATOMIC ORBITAL AND OVERLAP POPULATION MATRIX"
     318            2 :          IF (nspin > 1) THEN
     319            2 :             IF (ispin == 1) THEN
     320            0 :                headline = TRIM(headline)//" For Alpha Spin"
     321              :             ELSE
     322            2 :                headline = TRIM(headline)//" For Beta Spin"
     323              :             END IF
     324              :          END IF
     325            2 :          CALL dbcsr_copy(matrix_b=sm_ps, matrix_a=sm_s, name=TRIM(headline))
     326              :       END IF
     327              : 
     328              :       ! Build Mulliken population matrix for each spin
     329        10824 :       DO ispin = 1, nspin
     330        17320 :          DO ic = 1, SIZE(matrix_s, 2)
     331        11526 :             IF (print_level > 2) THEN
     332            4 :                CALL dbcsr_set(sm_ps, 0.0_dp)
     333              :             END IF
     334        11526 :             sm_s => matrix_s(1, ic)%matrix ! Overlap matrix in sparse format
     335        11526 :             sm_p => matrix_p(ispin, ic)%matrix ! Density matrix for spin ispin in sparse format
     336              :             ! Calculate Hadamard product of P and S as sparse matrix (Mulliken)
     337              :             ! CALL dbcsr_hadamard_product(sm_p,sm_s,sm_ps)
     338        11526 :             CALL dbcsr_iterator_start(iter, sm_s)
     339       105530 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
     340        94004 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, s_block)
     341        94004 :                IF (.NOT. (ASSOCIATED(s_block))) CYCLE
     342              :                CALL dbcsr_get_block_p(matrix=sm_p, &
     343              :                                       row=iatom, &
     344              :                                       col=jatom, &
     345              :                                       block=p_block, &
     346        94004 :                                       found=found)
     347        94004 :                IF (print_level > 2) THEN
     348              :                   CALL dbcsr_get_block_p(matrix=sm_ps, &
     349              :                                          row=iatom, &
     350              :                                          col=jatom, &
     351              :                                          block=ps_block, &
     352           12 :                                          found=found)
     353           12 :                   CPASSERT(ASSOCIATED(ps_block))
     354              :                END IF
     355              : 
     356        94004 :                sgfb = first_sgf_atom(jatom)
     357       555906 :                DO jsgf = 1, SIZE(s_block, 2)
     358      5972682 :                   DO isgf = 1, SIZE(s_block, 1)
     359      5510780 :                      ps = p_block(isgf, jsgf)*s_block(isgf, jsgf)
     360      5510780 :                      IF (ASSOCIATED(ps_block)) ps_block(isgf, jsgf) = ps_block(isgf, jsgf) + ps
     361      5972682 :                      orbpop(sgfb, ispin) = orbpop(sgfb, ispin) + ps
     362              :                   END DO
     363       555906 :                   sgfb = sgfb + 1
     364              :                END DO
     365       105530 :                IF (iatom /= jatom) THEN
     366        74412 :                   sgfa = first_sgf_atom(iatom)
     367       422459 :                   DO isgf = 1, SIZE(s_block, 1)
     368      3861376 :                      DO jsgf = 1, SIZE(s_block, 2)
     369      3513329 :                         ps = p_block(isgf, jsgf)*s_block(isgf, jsgf)
     370      3861376 :                         orbpop(sgfa, ispin) = orbpop(sgfa, ispin) + ps
     371              :                      END DO
     372       422459 :                      sgfa = sgfa + 1
     373              :                   END DO
     374              :                END IF
     375              :             END DO
     376        28846 :             CALL dbcsr_iterator_stop(iter)
     377              :          END DO
     378              : 
     379        10824 :          IF (print_level > 2) THEN
     380              :             ! Write the full Mulliken net AO and overlap population matrix
     381            4 :             CALL cp_dbcsr_write_sparse_matrix(sm_ps, 4, 6, qs_env, para_env, output_unit=output_unit)
     382              :          END IF
     383              :       END DO
     384              : 
     385         5030 :       CALL para_env%sum(orbpop)
     386              : 
     387              :       ! Write atomic populations and charges
     388         5030 :       IF (output_unit > 0) THEN
     389         2529 :          print_gop = (print_level > 1) ! Print also orbital populations
     390         2529 :          CALL write_orbpop(orbpop, atomic_kind_set, qs_kind_set, particle_set, output_unit, print_gop)
     391              :       END IF
     392              : 
     393              :       ! Save the Mulliken charges to results
     394         5030 :       CALL save_mulliken_charges(orbpop, atomic_kind_set, qs_kind_set, particle_set, qs_env)
     395              : 
     396              :       ! Release local working storage
     397         5030 :       IF (ASSOCIATED(sm_ps)) CALL dbcsr_deallocate_matrix(sm_ps)
     398         5030 :       DEALLOCATE (orbpop)
     399         5030 :       DEALLOCATE (first_sgf_atom)
     400              : 
     401         5030 :       IF (output_unit > 0) THEN
     402              :          WRITE (UNIT=output_unit, FMT="(T2,A)") &
     403         2529 :             '!-----------------------------------------------------------------------------!'
     404              :       END IF
     405              : 
     406         5030 :       CALL timestop(handle)
     407              : 
     408        15090 :    END SUBROUTINE mulliken_population_analysis
     409              : 
     410              : ! **************************************************************************************************
     411              : !> \brief Save the Mulliken atomic orbital populations and charges in results
     412              : !>
     413              : !> \param orbpop ...
     414              : !> \param atomic_kind_set ...
     415              : !> \param qs_kind_set ...
     416              : !> \param particle_set ...
     417              : !> \param qs_env ...
     418              : !> \par History
     419              : !>       27.05.2022 BT
     420              : !>       16.07.2025 RK
     421              : !> \author  Bo Thomsen (BT)
     422              : !>          Rangsiman Ketkaew (RK)
     423              : !> \version 1.0
     424              : ! **************************************************************************************************
     425         5030 :    SUBROUTINE save_mulliken_charges(orbpop, atomic_kind_set, qs_kind_set, particle_set, qs_env)
     426              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: orbpop
     427              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     428              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     429              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     430              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     431              : 
     432              :       CHARACTER(LEN=default_string_length)               :: description
     433              :       INTEGER                                            :: iao, iatom, ikind, iset, isgf, ishell, &
     434              :                                                             iso, l, natom, nset, nsgf, nspin
     435         5030 :       INTEGER, DIMENSION(:), POINTER                     :: nshell
     436         5030 :       INTEGER, DIMENSION(:, :), POINTER                  :: lshell
     437              :       REAL(KIND=dp)                                      :: zeff
     438              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: all_sumorbpop, charges_save
     439              :       REAL(KIND=dp), DIMENSION(3)                        :: sumorbpop
     440              :       TYPE(cp_result_type), POINTER                      :: results
     441              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     442              : 
     443         5030 :       nspin = SIZE(orbpop, 2)
     444              : 
     445         5030 :       CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
     446         5030 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nsgf)
     447         5030 :       CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
     448         5030 :       NULLIFY (results)
     449         5030 :       CALL get_qs_env(qs_env, results=results)
     450        15090 :       ALLOCATE (all_sumorbpop(natom))
     451        10060 :       ALLOCATE (charges_save(natom))
     452              : 
     453         5030 :       iao = 1
     454        26182 :       DO iatom = 1, natom
     455        21152 :          sumorbpop(:) = 0.0_dp
     456        21152 :          NULLIFY (orb_basis_set)
     457              :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     458        21152 :                               kind_number=ikind)
     459        21152 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set, zeff=zeff)
     460        26182 :          IF (ASSOCIATED(orb_basis_set)) THEN
     461              :             CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     462              :                                    nset=nset, &
     463              :                                    nshell=nshell, &
     464        21152 :                                    l=lshell)
     465        21152 :             isgf = 1
     466        57538 :             DO iset = 1, nset
     467       123790 :                DO ishell = 1, nshell(iset)
     468        66252 :                   l = lshell(ishell, iset)
     469       243718 :                   DO iso = 1, nso(l)
     470       141080 :                      IF (nspin == 1) THEN
     471       117148 :                         sumorbpop(1) = sumorbpop(1) + orbpop(iao, 1)
     472              :                      ELSE
     473        71796 :                         sumorbpop(1:2) = sumorbpop(1:2) + orbpop(iao, 1:2)
     474        23932 :                         sumorbpop(3) = sumorbpop(3) + orbpop(iao, 1) - orbpop(iao, 2)
     475              :                      END IF
     476       141080 :                      isgf = isgf + 1
     477       207332 :                      iao = iao + 1
     478              :                   END DO
     479              :                END DO
     480              :             END DO
     481        21152 :             IF (nspin == 1) THEN
     482        18260 :                charges_save(iatom) = zeff - sumorbpop(1)
     483        18260 :                all_sumorbpop(iatom) = sumorbpop(1)
     484              :             ELSE
     485         2892 :                charges_save(iatom) = zeff - sumorbpop(1) - sumorbpop(2)
     486         2892 :                all_sumorbpop(iatom) = sumorbpop(1) + sumorbpop(2)
     487              :             END IF
     488              :          END IF ! atom has an orbital basis
     489              :       END DO ! next atom iatom
     490              : 
     491              :       ! Store atomic orbital populations in results
     492         5030 :       description = "[MULLIKEN-ORBPOP]"
     493         5030 :       CALL cp_results_erase(results=results, description=description)
     494              :       CALL put_results(results=results, description=description, &
     495         5030 :                        values=orbpop)
     496              : 
     497              :       ! Store sum orbital population in results
     498         5030 :       description = "[MULLIKEN-SUMORBPOP]"
     499         5030 :       CALL cp_results_erase(results=results, description=description)
     500              :       CALL put_results(results=results, description=description, &
     501         5030 :                        values=all_sumorbpop)
     502              : 
     503              :       ! Store charges in results
     504         5030 :       description = "[MULLIKEN-CHARGES]"
     505         5030 :       CALL cp_results_erase(results=results, description=description)
     506              :       CALL put_results(results=results, description=description, &
     507         5030 :                        values=charges_save)
     508              : 
     509         5030 :       DEALLOCATE (all_sumorbpop)
     510         5030 :       DEALLOCATE (charges_save)
     511              : 
     512         5030 :    END SUBROUTINE save_mulliken_charges
     513              : 
     514              : ! **************************************************************************************************
     515              : !> \brief Write atomic orbital populations and net atomic charges
     516              : !>
     517              : !> \param orbpop ...
     518              : !> \param atomic_kind_set ...
     519              : !> \param qs_kind_set ...
     520              : !> \param particle_set ...
     521              : !> \param output_unit ...
     522              : !> \param print_orbital_contributions ...
     523              : !> \date    07.07.2010
     524              : !> \author  Matthias Krack (MK)
     525              : !> \version 1.0
     526              : ! **************************************************************************************************
     527         2583 :    SUBROUTINE write_orbpop(orbpop, atomic_kind_set, qs_kind_set, particle_set, output_unit, &
     528              :                            print_orbital_contributions)
     529              : 
     530              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: orbpop
     531              :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     532              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     533              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     534              :       INTEGER, INTENT(IN)                                :: output_unit
     535              :       LOGICAL, INTENT(IN)                                :: print_orbital_contributions
     536              : 
     537              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_orbpop'
     538              : 
     539              :       CHARACTER(LEN=2)                                   :: element_symbol
     540         2583 :       CHARACTER(LEN=6), DIMENSION(:), POINTER            :: sgf_symbol
     541              :       INTEGER                                            :: handle, iao, iatom, ikind, iset, isgf, &
     542              :                                                             ishell, iso, l, natom, nset, nsgf, &
     543              :                                                             nspin
     544         2583 :       INTEGER, DIMENSION(:), POINTER                     :: nshell
     545         2583 :       INTEGER, DIMENSION(:, :), POINTER                  :: lshell
     546              :       REAL(KIND=dp)                                      :: zeff
     547              :       REAL(KIND=dp), DIMENSION(3)                        :: sumorbpop, totsumorbpop
     548              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     549              : 
     550         2583 :       CALL timeset(routineN, handle)
     551              : 
     552         2583 :       nspin = SIZE(orbpop, 2)
     553              : 
     554         2583 :       CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
     555         2583 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nsgf)
     556              : 
     557              :       ! Select and write headline
     558         2583 :       IF (nspin == 1) THEN
     559         2198 :          IF (print_orbital_contributions) THEN
     560              :             WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     561            0 :                "# Orbital  AO symbol  Orbital population                            Net charge"
     562              :          ELSE
     563              :             WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     564         2198 :                "#  Atom  Element  Kind  Atomic population                           Net charge"
     565              :          END IF
     566              :       ELSE
     567          385 :          IF (print_orbital_contributions) THEN
     568              :             WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     569            3 :                "# Orbital  AO symbol  Orbital population (alpha,beta)  Net charge  Spin moment"
     570              :          ELSE
     571              :             WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     572          382 :                "#  Atom  Element  Kind  Atomic population (alpha,beta) Net charge  Spin moment"
     573              :          END IF
     574              :       END IF
     575              : 
     576         2583 :       totsumorbpop(:) = 0.0_dp
     577              : 
     578         2583 :       iao = 1
     579        13352 :       DO iatom = 1, natom
     580        10769 :          sumorbpop(:) = 0.0_dp
     581        10769 :          NULLIFY (orb_basis_set)
     582              :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     583              :                               element_symbol=element_symbol, &
     584        10769 :                               kind_number=ikind)
     585        10769 :          CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set, zeff=zeff)
     586        13352 :          IF (ASSOCIATED(orb_basis_set)) THEN
     587              :             CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     588              :                                    nset=nset, &
     589              :                                    nshell=nshell, &
     590              :                                    l=lshell, &
     591        10769 :                                    sgf_symbol=sgf_symbol)
     592        10769 :             isgf = 1
     593        29523 :             DO iset = 1, nset
     594        63349 :                DO ishell = 1, nshell(iset)
     595        33826 :                   l = lshell(ishell, iset)
     596       124664 :                   DO iso = 1, nso(l)
     597        72084 :                      IF (nspin == 1) THEN
     598        60014 :                         sumorbpop(1) = sumorbpop(1) + orbpop(iao, 1)
     599        60014 :                         IF (print_orbital_contributions) THEN
     600            0 :                            IF (isgf == 1) WRITE (UNIT=output_unit, FMT="(A)") ""
     601              :                            WRITE (UNIT=output_unit, &
     602              :                                   FMT="(T2,I9,2X,A2,1X,A,T30,F12.6)") &
     603            0 :                               iao, element_symbol, sgf_symbol(isgf), orbpop(iao, 1)
     604              :                         END IF
     605              :                      ELSE
     606        36210 :                         sumorbpop(1:2) = sumorbpop(1:2) + orbpop(iao, 1:2)
     607        12070 :                         sumorbpop(3) = sumorbpop(3) + orbpop(iao, 1) - orbpop(iao, 2)
     608        12070 :                         IF (print_orbital_contributions) THEN
     609          117 :                            IF (isgf == 1) WRITE (UNIT=output_unit, FMT="(A)") ""
     610              :                            WRITE (UNIT=output_unit, &
     611              :                                   FMT="(T2,I9,2X,A2,1X,A,T29,2(1X,F12.6),T68,F12.6)") &
     612          117 :                               iao, element_symbol, sgf_symbol(isgf), orbpop(iao, 1:2), &
     613          234 :                               orbpop(iao, 1) - orbpop(iao, 2)
     614              :                         END IF
     615              :                      END IF
     616        72084 :                      isgf = isgf + 1
     617       105910 :                      iao = iao + 1
     618              :                   END DO
     619              :                END DO
     620              :             END DO
     621        10769 :             IF (nspin == 1) THEN
     622         9315 :                totsumorbpop(1) = totsumorbpop(1) + sumorbpop(1)
     623         9315 :                totsumorbpop(3) = totsumorbpop(3) + zeff - sumorbpop(1)
     624              :                WRITE (UNIT=output_unit, &
     625              :                       FMT="(T2,I7,5X,A2,2X,I6,T30,F12.6,T68,F12.6)") &
     626         9315 :                   iatom, element_symbol, ikind, sumorbpop(1), zeff - sumorbpop(1)
     627              :             ELSE
     628         4362 :                totsumorbpop(1:2) = totsumorbpop(1:2) + sumorbpop(1:2)
     629         1454 :                totsumorbpop(3) = totsumorbpop(3) + zeff - sumorbpop(1) - sumorbpop(2)
     630              :                WRITE (UNIT=output_unit, &
     631              :                       FMT="(T2,I7,5X,A2,2X,I6,T28,4(1X,F12.6))") &
     632         1454 :                   iatom, element_symbol, ikind, sumorbpop(1:2), &
     633         2908 :                   zeff - sumorbpop(1) - sumorbpop(2), sumorbpop(3)
     634              :             END IF
     635              :          END IF ! atom has an orbital basis
     636              :       END DO ! next atom iatom
     637              : 
     638              :       ! Write total sums
     639         2583 :       IF (print_orbital_contributions) WRITE (UNIT=output_unit, FMT="(A)") ""
     640         2583 :       IF (nspin == 1) THEN
     641              :          WRITE (UNIT=output_unit, &
     642              :                 FMT="(T2,A,T42,F12.6,T68,F12.6,/)") &
     643         2198 :             "# Total charge", totsumorbpop(1), totsumorbpop(3)
     644              :       ELSE
     645              :          WRITE (UNIT=output_unit, &
     646              :                 FMT="(T2,A,T28,4(1X,F12.6),/)") &
     647          385 :             "# Total charge and spin", totsumorbpop(1:2), totsumorbpop(3), &
     648          770 :             totsumorbpop(1) - totsumorbpop(2)
     649              :       END IF
     650              : 
     651         2583 :       IF (output_unit > 0) CALL m_flush(output_unit)
     652              : 
     653         2583 :       CALL timestop(handle)
     654              : 
     655         2583 :    END SUBROUTINE write_orbpop
     656              : 
     657              : END MODULE population_analyses
        

Generated by: LCOV version 2.0-1