LCOV - code coverage report
Current view: top level - src - iao_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:06f838d) Lines: 99.4 % 159 158
Test Date: 2026-06-05 07:04:50 Functions: 80.0 % 5 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              : ! **************************************************************************************************
       9              : !> \brief Calculate ntrinsic atomic orbitals and analyze wavefunctions
      10              : !> \par History
      11              : !>      03.2023 created [JGH]
      12              : !> \author JGH
      13              : ! **************************************************************************************************
      14              : MODULE iao_types
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      16              :                                               get_atomic_kind_set
      17              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type
      18              :    USE cell_types,                      ONLY: cell_type,&
      19              :                                               pbc
      20              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      21              :    USE cp_dbcsr_api,                    ONLY: dbcsr_get_info,&
      22              :                                               dbcsr_p_type,&
      23              :                                               dbcsr_type
      24              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm
      25              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      26              :                                               cp_fm_struct_release,&
      27              :                                               cp_fm_struct_type
      28              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      29              :                                               cp_fm_release,&
      30              :                                               cp_fm_to_fm_submat,&
      31              :                                               cp_fm_type,&
      32              :                                               cp_fm_write_formatted
      33              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      34              :                                               cp_logger_type
      35              :    USE cp_output_handling,              ONLY: cp_p_file,&
      36              :                                               cp_print_key_finished_output,&
      37              :                                               cp_print_key_should_output,&
      38              :                                               cp_print_key_unit_nr
      39              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      40              :    USE input_constants,                 ONLY: do_iaoloc_enone,&
      41              :                                               do_iaoloc_pm2
      42              :    USE input_section_types,             ONLY: section_vals_get,&
      43              :                                               section_vals_get_subs_vals,&
      44              :                                               section_vals_type,&
      45              :                                               section_vals_val_get
      46              :    USE kinds,                           ONLY: dp
      47              :    USE message_passing,                 ONLY: mp_para_env_type
      48              :    USE particle_types,                  ONLY: particle_type
      49              :    USE qs_environment_types,            ONLY: get_qs_env,&
      50              :                                               qs_environment_type
      51              : #include "./base/base_uses.f90"
      52              : 
      53              :    IMPLICIT NONE
      54              :    PRIVATE
      55              : 
      56              :    PUBLIC ::  iao_env_type, iao_read_input, iao_set_default, &
      57              :              organise_printout_for_rose, print_fragment_association
      58              : 
      59              : ! **************************************************************************************************
      60              :    TYPE iao_env_type
      61              :       LOGICAL                                :: do_iao = .FALSE.
      62              :       !
      63              :       REAL(KIND=dp)                          :: eps_svd = 0.0_dp
      64              :       REAL(KIND=dp)                          :: eps_occ = 0.0_dp
      65              :       ! chages
      66              :       LOGICAL                                :: do_charges = .FALSE.
      67              :       ! one-center expansion
      68              :       LOGICAL                                :: do_oce = .FALSE.
      69              :       INTEGER                                :: lmax_oce = 0
      70              :       INTEGER                                :: nbas_oce = 0
      71              :       LOGICAL                                :: append_oce = .FALSE.
      72              :       ! Bond orbitals
      73              :       LOGICAL                                :: do_bondorbitals = .FALSE.
      74              :       ! Wannier centers
      75              :       LOGICAL                                :: do_center = .FALSE.
      76              :       LOGICAL                                :: pos_periodic = .FALSE.
      77              :       INTEGER                                :: loc_operator = 0
      78              :       INTEGER                                :: eloc_function = 0
      79              :       REAL(KIND=dp)                          :: eloc_weight = 0.0_dp
      80              :       ! Molden
      81              :       LOGICAL                                :: molden_iao = .FALSE.
      82              :       LOGICAL                                :: molden_ibo = .FALSE.
      83              :       ! CUBE files
      84              :       LOGICAL                                :: cubes_iao = .FALSE.
      85              :       LOGICAL                                :: cubes_ibo = .FALSE.
      86              :       ! Input sections
      87              :       TYPE(section_vals_type), POINTER       :: iao_cubes_section => NULL(), &
      88              :                                                 iao_molden_section => NULL(), &
      89              :                                                 ibo_cubes_section => NULL(), &
      90              :                                                 ibo_molden_section => NULL(), &
      91              :                                                 ibo_cc_section => NULL()
      92              :       ! Fragments
      93              :       LOGICAL                                 :: do_fragments = .FALSE.
      94              :       INTEGER                                 :: nfrags = 0
      95              :    END TYPE iao_env_type
      96              : 
      97              : ! **************************************************************************************************
      98              : 
      99              : CONTAINS
     100              : 
     101              : ! **************************************************************************************************
     102              : !> \brief ...
     103              : !> \param iao_env ...
     104              : ! **************************************************************************************************
     105           64 :    SUBROUTINE iao_set_default(iao_env)
     106              :       TYPE(iao_env_type), INTENT(INOUT)                  :: iao_env
     107              : 
     108              :       !iao
     109           64 :       iao_env%do_iao = .FALSE.
     110           64 :       iao_env%eps_svd = 0.0_dp
     111           64 :       iao_env%eps_occ = 0.0_dp
     112              :       ! charges
     113           64 :       iao_env%do_charges = .FALSE.
     114              :       ! one-center expansion
     115           64 :       iao_env%do_oce = .FALSE.
     116           64 :       iao_env%lmax_oce = 3
     117           64 :       iao_env%nbas_oce = 10
     118           64 :       iao_env%append_oce = .FALSE.
     119              :       ! Bond orbitals
     120           64 :       iao_env%do_bondorbitals = .FALSE.
     121              :       ! Wannier centers
     122           64 :       iao_env%do_center = .FALSE.
     123           64 :       iao_env%pos_periodic = .FALSE.
     124           64 :       iao_env%loc_operator = do_iaoloc_pm2
     125           64 :       iao_env%eloc_function = do_iaoloc_enone
     126           64 :       iao_env%eloc_weight = 0.0_dp
     127              :       ! i/o
     128           64 :       iao_env%molden_iao = .FALSE.
     129           64 :       iao_env%molden_ibo = .FALSE.
     130           64 :       iao_env%cubes_iao = .FALSE.
     131           64 :       iao_env%cubes_ibo = .FALSE.
     132              :       ! Input sections
     133           64 :       NULLIFY (iao_env%iao_cubes_section, iao_env%iao_molden_section)
     134           64 :       NULLIFY (iao_env%ibo_cubes_section, iao_env%ibo_molden_section)
     135           64 :       NULLIFY (iao_env%ibo_cc_section)
     136              : 
     137           64 :    END SUBROUTINE iao_set_default
     138              : 
     139              : ! **************************************************************************************************
     140              : 
     141              : ! **************************************************************************************************
     142              : !> \brief ...
     143              : !> \param iao_env ...
     144              : !> \param iao_section ...
     145              : !> \param cell ...
     146              : ! **************************************************************************************************
     147           68 :    SUBROUTINE iao_read_input(iao_env, iao_section, cell)
     148              :       TYPE(iao_env_type), INTENT(INOUT)                  :: iao_env
     149              :       TYPE(section_vals_type), POINTER                   :: iao_section
     150              :       TYPE(cell_type), OPTIONAL                          :: cell
     151              : 
     152              :       LOGICAL                                            :: explicit, iao_explicit
     153              :       TYPE(section_vals_type), POINTER                   :: subsection
     154              : 
     155           34 :       CALL iao_set_default(iao_env)
     156              : 
     157           34 :       CALL section_vals_get(iao_section, explicit=iao_explicit)
     158           34 :       IF (iao_explicit) THEN
     159            6 :          iao_env%do_iao = .TRUE.
     160              :          ! input options
     161            6 :          CALL section_vals_val_get(iao_section, "EPS_SVD", r_val=iao_env%eps_svd)
     162            6 :          CALL section_vals_val_get(iao_section, "EPS_OCC", r_val=iao_env%eps_occ)
     163            6 :          CALL section_vals_val_get(iao_section, "ATOMIC_CHARGES", l_val=iao_env%do_charges)
     164            6 :          iao_env%iao_molden_section => section_vals_get_subs_vals(iao_section, "IAO_MOLDEN")
     165            6 :          CALL section_vals_get(iao_env%iao_molden_section, explicit=iao_env%molden_iao)
     166            6 :          iao_env%iao_cubes_section => section_vals_get_subs_vals(iao_section, "IAO_CUBES")
     167            6 :          CALL section_vals_get(iao_env%iao_cubes_section, explicit=iao_env%cubes_iao)
     168            6 :          subsection => section_vals_get_subs_vals(iao_section, "ONE_CENTER_EXPANSION")
     169            6 :          CALL section_vals_get(subsection, explicit=iao_env%do_oce)
     170            6 :          IF (iao_env%do_oce) THEN
     171            4 :             subsection => section_vals_get_subs_vals(iao_section, "ONE_CENTER_EXPANSION")
     172            4 :             CALL section_vals_val_get(subsection, "LMAX", i_val=iao_env%lmax_oce)
     173            4 :             CALL section_vals_val_get(subsection, "NBAS", i_val=iao_env%nbas_oce)
     174            4 :             CALL section_vals_val_get(subsection, "APPEND", l_val=iao_env%append_oce)
     175              :          END IF
     176            6 :          subsection => section_vals_get_subs_vals(iao_section, "BOND_ORBITALS")
     177            6 :          CALL section_vals_get(subsection, explicit=iao_env%do_bondorbitals)
     178            6 :          IF (iao_env%do_bondorbitals) THEN
     179            6 :             subsection => section_vals_get_subs_vals(iao_section, "BOND_ORBITALS")
     180            6 :             CALL section_vals_val_get(subsection, "LOCALIZATION_OPERATOR", i_val=iao_env%loc_operator)
     181            6 :             CALL section_vals_val_get(subsection, "ENERGY_LOCALIZATION_FUNCTION", i_val=iao_env%eloc_function)
     182            6 :             CALL section_vals_val_get(subsection, "ENERGY_LOCALIZATION_WEIGHT", r_val=iao_env%eloc_weight)
     183            6 :             iao_env%ibo_molden_section => section_vals_get_subs_vals(subsection, "IBO_MOLDEN")
     184            6 :             CALL section_vals_get(iao_env%ibo_molden_section, explicit=iao_env%molden_ibo)
     185            6 :             iao_env%ibo_cubes_section => section_vals_get_subs_vals(subsection, "IBO_CUBES")
     186            6 :             CALL section_vals_get(iao_env%ibo_cubes_section, explicit=iao_env%cubes_ibo)
     187            6 :             iao_env%ibo_cc_section => section_vals_get_subs_vals(subsection, "CHARGE_CENTER")
     188            6 :             CALL section_vals_get(iao_env%ibo_cc_section, explicit=iao_env%do_center)
     189            6 :             IF (iao_env%do_center) THEN
     190              :                CALL section_vals_val_get(iao_env%ibo_cc_section, "POSITION_OPERATOR_BERRY", &
     191            6 :                                          l_val=iao_env%pos_periodic, explicit=explicit)
     192            6 :                IF (.NOT. explicit) THEN
     193              :                   ! set default according to cell periodicity
     194            2 :                   iao_env%pos_periodic = .TRUE.
     195            2 :                   IF (PRESENT(cell)) THEN
     196            8 :                      IF (ALL(cell%perd == 0)) iao_env%pos_periodic = .FALSE.
     197              :                   END IF
     198              :                END IF
     199              :             END IF
     200              :          END IF
     201              :       END IF
     202              : 
     203           34 :    END SUBROUTINE iao_read_input
     204              : ! **************************************************************************************************
     205              : !> \brief Prints fragmented overlap matrices for interface with ROSE
     206              : !> \param qs_env ...
     207              : !> \param orb_basis_set_list ...
     208              : ! **************************************************************************************************
     209            2 :    SUBROUTINE organise_printout_for_rose(qs_env, orb_basis_set_list)
     210              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     211              :       TYPE(gto_basis_set_p_type), DIMENSION(:), &
     212              :          INTENT(IN), POINTER                             :: orb_basis_set_list
     213              : 
     214              :       CHARACTER(len=*), PARAMETER :: routineN = 'organise_printout_for_rose'
     215              : 
     216              :       INTEGER                                            :: after, colskip, handle, iatom, ii, &
     217              :                                                             ikind, iounit, jj, ncol, nfrags, nrow, &
     218              :                                                             rowfrag, rowskip, totalcol, totalrow
     219            2 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of
     220              :       LOGICAL                                            :: lfirstcol, lfirstcoljj
     221            2 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     222              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     223              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
     224              :       TYPE(cp_fm_type)                                   :: fm_sorb, fm_sorb_frags12, fm_sorb_frags22
     225              :       TYPE(cp_logger_type), POINTER                      :: logger
     226            2 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s
     227              :       TYPE(dbcsr_type), POINTER                          :: smat
     228              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     229            2 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     230              : 
     231            2 :       CALL timeset(routineN, handle)
     232              : 
     233              :       !get number of fragments
     234            2 :       NULLIFY (particle_set, atomic_kind_set)
     235              :       CALL get_qs_env(qs_env, particle_set=particle_set, atomic_kind_set=atomic_kind_set, &
     236            2 :                       matrix_s_kp=matrix_s)
     237            2 :       CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
     238            2 :       smat => matrix_s(1, 1)%matrix
     239              : 
     240            2 :       nfrags = 0
     241           16 :       DO ii = 1, SIZE(particle_set)
     242           14 :          IF (nfrags < particle_set(ii)%fragment_index) &
     243            2 :             nfrags = particle_set(ii)%fragment_index
     244              :       END DO
     245              : 
     246            2 :       logger => cp_get_default_logger()
     247            2 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     248              :                                            qs_env%input, "DFT%PRINT%IAO_ANALYSIS%IAO_OVERLAP"), cp_p_file)) THEN
     249              :          iounit = cp_print_key_unit_nr(logger, qs_env%input, "DFT%PRINT%IAO_ANALYSIS%IAO_OVERLAP", &
     250              :                                        extension=".Log", file_form="FORMATTED", file_action="WRITE", &
     251            2 :                                        file_status="REPLACE")
     252            2 :          CALL section_vals_val_get(qs_env%input, "DFT%PRINT%IAO_ANALYSIS%IAO_OVERLAP%NDIGITS", i_val=after)
     253              :          after = MIN(MAX(after, 1), 16)
     254              : 
     255            6 :          DO ii = 1, nfrags
     256           14 :             DO jj = 1, nfrags
     257            8 :                NULLIFY (para_env, blacs_env)
     258            8 :                CALL get_qs_env(qs_env=qs_env, blacs_env=blacs_env, para_env=para_env)
     259            8 :                totalcol = 0
     260            8 :                totalrow = 0
     261            8 :                rowfrag = 0
     262            8 :                colskip = 0
     263            8 :                rowskip = 0
     264            8 :                lfirstcol = .TRUE.
     265            8 :                lfirstcoljj = .TRUE.
     266              : 
     267           64 :                DO iatom = 1, SIZE(particle_set)
     268           56 :                   ikind = kind_of(iatom)
     269           56 :                   IF (particle_set(iatom)%fragment_index == jj) THEN
     270           28 :                      totalcol = totalcol + orb_basis_set_list(ikind)%gto_basis_set%nsgf
     271           28 :                      lfirstcoljj = .FALSE.
     272           28 :                   ELSEIF (lfirstcoljj) THEN
     273           16 :                      colskip = colskip + orb_basis_set_list(ikind)%gto_basis_set%nsgf
     274              :                   END IF
     275           56 :                   IF (particle_set(iatom)%fragment_index == ii) THEN
     276           28 :                      totalrow = totalrow + orb_basis_set_list(ikind)%gto_basis_set%nsgf
     277           28 :                      lfirstcol = .FALSE.
     278           28 :                   ELSEIF (lfirstcol) THEN
     279           16 :                      rowskip = rowskip + orb_basis_set_list(ikind)%gto_basis_set%nsgf
     280              :                   END IF
     281           64 :                   rowfrag = rowfrag + orb_basis_set_list(ikind)%gto_basis_set%nsgf
     282              :                END DO
     283              : 
     284            8 :                CALL dbcsr_get_info(matrix_s(1, 1)%matrix, nfullrows_total=nrow, nfullcols_total=ncol)
     285              :                CALL cp_fm_struct_create(fmstruct=fmstruct, para_env=para_env, context=blacs_env, &
     286            8 :                                         nrow_global=nrow, ncol_global=ncol)
     287            8 :                CALL cp_fm_create(matrix=fm_sorb, matrix_struct=fmstruct, name="Overlap matrix S_B1")
     288            8 :                CALL cp_fm_struct_release(fmstruct=fmstruct)
     289            8 :                CALL copy_dbcsr_to_fm(matrix_s(1, 1)%matrix, fm_sorb)
     290              : 
     291              :                CALL cp_fm_struct_create(fmstruct=fmstruct, para_env=para_env, context=blacs_env, &
     292            8 :                                         nrow_global=totalrow, ncol_global=totalcol)
     293            8 :                CALL cp_fm_create(matrix=fm_sorb_frags22, matrix_struct=fmstruct, name="Overlap matrix S_B1^kk' (S22)")
     294            8 :                CALL cp_fm_struct_release(fmstruct=fmstruct)
     295              :                CALL cp_fm_to_fm_submat(fm_sorb, fm_sorb_frags22, &
     296            8 :                                        totalrow, totalcol, 1 + rowskip, 1 + colskip, 1, 1)
     297              : 
     298              :                CALL cp_fm_struct_create(fmstruct=fmstruct, para_env=para_env, context=blacs_env, &
     299            8 :                                         nrow_global=rowfrag, ncol_global=totalcol)
     300            8 :                CALL cp_fm_create(matrix=fm_sorb_frags12, matrix_struct=fmstruct, name="Overlap matrix S_B1^k' (S12)")
     301            8 :                CALL cp_fm_struct_release(fmstruct=fmstruct)
     302            8 :                CALL cp_fm_to_fm_submat(fm_sorb, fm_sorb_frags12, rowfrag, totalcol, 1, 1 + colskip, 1, 1)
     303              : 
     304            8 :                IF (iounit > 0) WRITE (iounit, *) "FRAGMENTS kk' NR. ", ii, jj
     305            8 :                CALL cp_fm_write_formatted(fm_sorb_frags22, iounit, "Overlap matrix S_B1^kk' (S22)")
     306            8 :                IF (ii /= jj) THEN
     307            4 :                   IF (iounit > 0) WRITE (iounit, *) "FRAGMENTS kk' NR. ", ii, jj
     308            4 :                   CALL cp_fm_write_formatted(fm_sorb_frags12, iounit, "Overlap matrix S_B1^k' (S12)")
     309              :                END IF
     310              : 
     311            8 :                CALL cp_fm_release(fm_sorb)
     312            8 :                CALL cp_fm_release(fm_sorb_frags22)
     313           44 :                CALL cp_fm_release(fm_sorb_frags12)
     314              : 
     315              :             END DO
     316              :          END DO
     317              : 
     318            2 :          CALL cp_print_key_finished_output(iounit, logger, qs_env%input, "DFT%PRINT%IAO_ANALYSIS%IAO_OVERLAP")
     319              :       END IF
     320              : 
     321            2 :       CALL timestop(handle)
     322              : 
     323            4 :    END SUBROUTINE organise_printout_for_rose
     324              : ! **************************************************************************************************
     325              : !> \brief Associates IBO centers to fragments
     326              : !> \param qs_env ...
     327              : !> \param moments ...
     328              : !> \param unit_nr ...
     329              : ! **************************************************************************************************
     330            2 :    SUBROUTINE print_fragment_association(qs_env, moments, unit_nr)
     331              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     332              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: moments
     333              :       INTEGER, INTENT(IN), OPTIONAL                      :: unit_nr
     334              : 
     335              :       CHARACTER(len=*), PARAMETER :: routineN = 'print_fragment_association'
     336              : 
     337              :       INTEGER                                            :: handle, iatom, is, ispin, jcenter, &
     338              :                                                             natom, ncenters, nspin
     339            2 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: atomcenter
     340              :       REAL(KIND=dp)                                      :: conv, dab, mindab
     341              :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     342              :       TYPE(cell_type), POINTER                           :: cell
     343            2 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     344              : 
     345            2 :       CALL timeset(routineN, handle)
     346              : 
     347            2 :       NULLIFY (cell, particle_set)
     348            2 :       CALL get_qs_env(qs_env=qs_env, cell=cell, particle_set=particle_set, natom=natom)
     349            2 :       conv = cp_unit_from_cp2k(1.0_dp, TRIM("angstrom"))
     350            2 :       nspin = SIZE(moments, 3)
     351            2 :       ncenters = SIZE(moments, 2)
     352            8 :       ALLOCATE (atomcenter(ncenters, nspin))
     353            2 :       atomcenter = 0
     354            4 :       DO ispin = 1, nspin
     355           22 :       DO jcenter = 1, SIZE(moments, 2)
     356           20 :          mindab = 10.0_dp
     357          162 :          DO iatom = 1, natom
     358          140 :             rab(:) = pbc(particle_set(iatom)%r(:), moments(:, jcenter, ispin), cell)
     359          140 :             dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
     360          160 :             IF (dab <= mindab) THEN
     361           40 :                mindab = dab
     362           40 :                atomcenter(jcenter, ispin) = iatom
     363              :             END IF
     364              :          END DO
     365              :       END DO
     366              : 
     367            4 :       IF (unit_nr > 0) THEN
     368            1 :          WRITE (unit_nr, "(/,T2,A,i1)") "Intrinsic Bond Orbitals: Centers associated to fragments for Spin ", &
     369            2 :             ispin
     370            1 :          WRITE (unit_nr, "(T2,A6,T30,A6,T60,A4,T70,A8)") "Center", "Moment", "Atom", "Fragment"
     371           11 :          DO is = 1, ncenters
     372           10 :             WRITE (unit_nr, "(i7,3F15.8,4X,I7,4X,I7)") is, moments(1:3, is, ispin), atomcenter(is, ispin), &
     373           21 :                particle_set(atomcenter(is, ispin))%fragment_index
     374              :          END DO
     375            1 :          WRITE (unit_nr, "(/)")
     376              :       END IF
     377              :       END DO
     378              : 
     379            2 :       CALL timestop(handle)
     380              : 
     381            4 :    END SUBROUTINE print_fragment_association
     382              : 
     383            0 : END MODULE iao_types
        

Generated by: LCOV version 2.0-1