LCOV - code coverage report
Current view: top level - src - wannier_states.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 113 174 64.9 %
Date: 2024-12-21 06:28:57 Functions: 1 1 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Routines for the calculation of wannier states
      10             : !> \author Alin M Elena
      11             : ! **************************************************************************************************
      12             : MODULE wannier_states
      13             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      14             :                                               get_atomic_kind,&
      15             :                                               get_atomic_kind_set
      16             :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      17             :                                               gto_basis_set_type
      18             :    USE cp_dbcsr_api,                    ONLY: dbcsr_type
      19             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply
      20             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      21             :                                               cp_fm_struct_release,&
      22             :                                               cp_fm_struct_type
      23             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      24             :                                               cp_fm_get_element,&
      25             :                                               cp_fm_get_info,&
      26             :                                               cp_fm_get_submatrix,&
      27             :                                               cp_fm_release,&
      28             :                                               cp_fm_to_fm,&
      29             :                                               cp_fm_type
      30             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      31             :                                               cp_logger_get_default_io_unit,&
      32             :                                               cp_logger_type
      33             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      34             :                                               cp_print_key_unit_nr
      35             :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      36             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      37             :                                               section_vals_type,&
      38             :                                               section_vals_val_get
      39             :    USE kinds,                           ONLY: default_string_length,&
      40             :                                               dp
      41             :    USE message_passing,                 ONLY: mp_para_env_type
      42             :    USE orbital_pointers,                ONLY: indco,&
      43             :                                               nco,&
      44             :                                               nso
      45             :    USE orbital_symbols,                 ONLY: cgf_symbol,&
      46             :                                               sgf_symbol
      47             :    USE orbital_transformation_matrices, ONLY: orbtramat
      48             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      49             :    USE particle_types,                  ONLY: particle_type
      50             :    USE qs_dftb_types,                   ONLY: qs_dftb_atom_type
      51             :    USE qs_dftb_utils,                   ONLY: get_dftb_atom_param
      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 wannier_states_types,            ONLY: wannier_centres_type
      58             : !!!! this ones are needed to mapping
      59             : #include "./base/base_uses.f90"
      60             : 
      61             :    IMPLICIT NONE
      62             : 
      63             :    PRIVATE
      64             : 
      65             : ! *** Global parameters ***
      66             : 
      67             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'wannier_states'
      68             : 
      69             :    LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .TRUE.
      70             : 
      71             : ! *** Public subroutines ***
      72             : 
      73             :    PUBLIC :: construct_wannier_states
      74             : 
      75             : CONTAINS
      76             : 
      77             : ! **************************************************************************************************
      78             : !> \brief constructs wannier states. mo_localized should not be overwritten!
      79             : !> \param mo_localized ...
      80             : !> \param Hks ...
      81             : !> \param qs_env ...
      82             : !> \param loc_print_section ...
      83             : !> \param WannierCentres ...
      84             : !> \param ns ...
      85             : !> \param states ...
      86             : !> \par History
      87             : !>      - Printout Wannier states in AO basis (11.09.2025, H. Elgabarty)
      88             : ! **************************************************************************************************
      89          16 :    SUBROUTINE construct_wannier_states(mo_localized, &
      90             :                                        Hks, qs_env, loc_print_section, WannierCentres, ns, states)
      91             : 
      92             :       TYPE(cp_fm_type), INTENT(in)                       :: mo_localized
      93             :       TYPE(dbcsr_type), POINTER                          :: Hks
      94             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      95             :       TYPE(section_vals_type), POINTER                   :: loc_print_section
      96             :       TYPE(wannier_centres_type), INTENT(INOUT)          :: WannierCentres
      97             :       INTEGER, INTENT(IN)                                :: ns
      98             :       INTEGER, INTENT(IN), POINTER                       :: states(:)
      99             : 
     100             :       CHARACTER(len=*), PARAMETER :: routineN = 'construct_wannier_states'
     101             : 
     102             :       CHARACTER(default_string_length)                   :: unit_str
     103             :       CHARACTER(LEN=12)                                  :: symbol
     104          16 :       CHARACTER(LEN=12), DIMENSION(:), POINTER           :: bcgf_symbol
     105             :       CHARACTER(LEN=2)                                   :: element_symbol
     106             :       CHARACTER(LEN=40)                                  :: fmtstr1, fmtstr2, fmtstr3
     107          16 :       CHARACTER(LEN=6), DIMENSION(:), POINTER            :: bsgf_symbol
     108             :       INTEGER :: after, before, from, handle, i, iatom, icgf, ico, icol, ikind, iproc, irow, iset, &
     109             :          isgf, ishell, iso, jcol, left, lmax, lshell, natom, ncgf, ncol, ncol_global, nrow_global, &
     110             :          nset, nsgf, nstates(2), output_unit, right, to, unit_mat
     111          16 :       INTEGER, DIMENSION(:), POINTER                     :: nshell
     112          16 :       INTEGER, DIMENSION(:, :), POINTER                  :: l
     113             :       LOGICAL                                            :: print_cartesian
     114             :       REAL(KIND=dp)                                      :: unit_conv
     115          16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cmatrix, smatrix
     116          16 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     117             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     118             :       TYPE(cp_fm_type)                                   :: b, c, d
     119             :       TYPE(cp_logger_type), POINTER                      :: logger
     120             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     121             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     122          16 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     123             :       TYPE(qs_dftb_atom_type), POINTER                   :: dftb_parameter
     124          16 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     125             :       TYPE(section_vals_type), POINTER                   :: print_key
     126             : 
     127             : !-----------------------------------------------------------------------
     128             : !-----------------------------------------------------------------------
     129             : 
     130          16 :       CALL timeset(routineN, handle)
     131          16 :       NULLIFY (logger, para_env)
     132             : 
     133             :       CALL get_qs_env(qs_env, para_env=para_env, &
     134             :                       atomic_kind_set=atomic_kind_set, &
     135             :                       qs_kind_set=qs_kind_set, &
     136          16 :                       particle_set=particle_set)
     137             : 
     138          16 :       logger => cp_get_default_logger()
     139             : 
     140          16 :       output_unit = cp_logger_get_default_io_unit(logger)
     141             : 
     142             :       CALL cp_fm_get_info(mo_localized, &
     143             :                           ncol_global=ncol_global, &
     144          16 :                           nrow_global=nrow_global)
     145             : 
     146          16 :       nstates(1) = ns
     147          16 :       nstates(2) = para_env%mepos
     148          16 :       iproc = nstates(2)
     149          16 :       NULLIFY (fm_struct_tmp, print_key)
     150             : 
     151          16 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CENTERS")
     152          16 :       CALL section_vals_val_get(print_key, "UNIT", c_val=unit_str)
     153          16 :       unit_conv = cp_unit_from_cp2k(1.0_dp, TRIM(unit_str))
     154             : 
     155          16 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_STATES")
     156             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nrow_global, &
     157             :                                ncol_global=1, &
     158             :                                para_env=mo_localized%matrix_struct%para_env, &
     159          16 :                                context=mo_localized%matrix_struct%context)
     160             : 
     161          16 :       CALL cp_fm_create(b, fm_struct_tmp, name="b")
     162          16 :       CALL cp_fm_create(c, fm_struct_tmp, name="c")
     163             : 
     164          16 :       CALL cp_fm_struct_release(fm_struct_tmp)
     165             : 
     166             :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=1, ncol_global=1, &
     167             :                                para_env=mo_localized%matrix_struct%para_env, &
     168          16 :                                context=mo_localized%matrix_struct%context)
     169             : 
     170          16 :       CALL cp_fm_create(d, fm_struct_tmp, name="d")
     171          16 :       CALL cp_fm_struct_release(fm_struct_tmp)
     172             : 
     173         132 :       WannierCentres%WannierHamDiag = 0.0_dp
     174             : 
     175             :       unit_mat = cp_print_key_unit_nr(logger, loc_print_section, &
     176             :                                       "WANNIER_STATES", extension=".whks", &
     177          16 :                                       ignore_should_output=.FALSE.)
     178          16 :       IF (unit_mat > 0) THEN
     179           8 :          WRITE (unit_mat, '(a16,1(i0,1x))') "Wannier states: ", ns
     180           8 :          WRITE (unit_mat, '(a16)') "#No x y z energy "
     181             :       END IF
     182         132 :       DO i = 1, ns
     183         116 :          CALL cp_fm_to_fm(mo_localized, b, 1, states(i), 1)
     184         116 :          CALL cp_dbcsr_sm_fm_multiply(Hks, b, c, 1)
     185             :          CALL parallel_gemm('T', 'N', 1, 1, nrow_global, 1.0_dp, &
     186         116 :                             b, c, 0.0_dp, d)
     187         116 :          CALL cp_fm_get_element(d, 1, 1, WannierCentres%WannierHamDiag(i))
     188             :          !               if (iproc==para_env%mepos) WRITE(unit_mat,'(f16.8,2x)', advance='no')WannierCentres%WannierHamDiag(i)
     189         174 :          IF (unit_mat > 0) WRITE (unit_mat, '(i0,1x,4(f16.8,2x))') states(i), &
     190         306 :             WannierCentres%centres(1:3, states(i))*unit_conv, WannierCentres%WannierHamDiag(states(i))
     191             :       END DO
     192             : 
     193          16 :       IF (unit_mat > 0) WRITE (unit_mat, *)
     194             : 
     195          16 :       IF (output_unit > 0) THEN
     196           8 :          WRITE (output_unit, *) ""
     197           8 :          WRITE (output_unit, *) "NUMBER OF Wannier STATES  ", ns
     198           8 :          WRITE (output_unit, *) "ENERGY      original MO-index"
     199          66 :          DO i = 1, ns
     200          66 :             WRITE (output_unit, '(f16.8,2x,i0)') WannierCentres%WannierHamDiag(i), states(i)
     201             :          END DO
     202             :       END IF
     203             : 
     204          16 :       CALL cp_fm_release(b)
     205          16 :       CALL cp_fm_release(c)
     206          16 :       CALL cp_fm_release(d)
     207             : 
     208             :       ! Print the states in AO basis
     209          16 :       CALL section_vals_val_get(print_key, "CARTESIAN", l_val=print_cartesian)
     210             : 
     211          64 :       ALLOCATE (smatrix(nrow_global, ncol_global))
     212          16 :       CALL cp_fm_get_submatrix(mo_localized, smatrix(1:nrow_global, 1:ncol_global))
     213             : 
     214          16 :       IF (unit_mat > 0) THEN
     215             : 
     216           8 :          NULLIFY (nshell)
     217           8 :          NULLIFY (bsgf_symbol)
     218           8 :          NULLIFY (l)
     219             :          NULLIFY (bsgf_symbol)
     220             : 
     221           8 :          CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
     222           8 :          CALL get_qs_kind_set(qs_kind_set, ncgf=ncgf, nsgf=nsgf)
     223             : 
     224             :          ! Print header, define column widths and string templates
     225           8 :          after = 6
     226           8 :          before = 4
     227           8 :          ncol = INT(56/(before + after + 3))
     228             : 
     229           8 :          fmtstr1 = "(T2,A,21X,  (  X,I5,  X))"
     230           8 :          fmtstr2 = "(T2,A,9X,  (1X,F  .  ))"
     231           8 :          fmtstr3 = "(T2,A,I5,1X,I5,1X,A,1X,A6,  (1X,F  .  ))"
     232             : 
     233           8 :          right = MAX((after - 2), 1)
     234           8 :          left = (before + after + 3) - right - 5
     235             : 
     236           8 :          IF (print_cartesian) THEN
     237           0 :             WRITE (UNIT=unit_mat, FMT="(T2,A,16X,A)") "WS|", "Wannier states in the cartesian AO basis"
     238             :          ELSE
     239           8 :             WRITE (UNIT=unit_mat, FMT="(T2,A,16X,A)") "WS|", "Wannier states in the spherical AO basis"
     240             :          END IF
     241           8 :          WRITE (UNIT=fmtstr1(11:12), FMT="(I2)") ncol
     242           8 :          WRITE (UNIT=fmtstr1(14:15), FMT="(I2)") left
     243           8 :          WRITE (UNIT=fmtstr1(21:22), FMT="(I2)") right
     244             : 
     245           8 :          WRITE (UNIT=fmtstr2(10:11), FMT="(I2)") ncol
     246           8 :          WRITE (UNIT=fmtstr2(17:18), FMT="(I2)") before + after + 2
     247           8 :          WRITE (UNIT=fmtstr2(20:21), FMT="(I2)") after
     248             : 
     249           8 :          WRITE (UNIT=fmtstr3(27:28), FMT="(I2)") ncol
     250           8 :          WRITE (UNIT=fmtstr3(34:35), FMT="(I2)") before + after + 2
     251           8 :          WRITE (UNIT=fmtstr3(37:38), FMT="(I2)") after
     252             : 
     253             :          ! get MO coefficients in terms of contracted cartesian functions
     254           8 :          IF (print_cartesian) THEN
     255             : 
     256           0 :             ALLOCATE (cmatrix(ncgf, ncgf))
     257           0 :             cmatrix = 0.0_dp
     258             : 
     259             :             ! Transform spherical to Cartesian AO basis
     260           0 :             icgf = 1
     261           0 :             isgf = 1
     262           0 :             DO iatom = 1, natom
     263           0 :                NULLIFY (orb_basis_set, dftb_parameter)
     264           0 :                CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
     265             :                CALL get_qs_kind(qs_kind_set(ikind), &
     266             :                                 basis_set=orb_basis_set, &
     267           0 :                                 dftb_parameter=dftb_parameter)
     268           0 :                IF (ASSOCIATED(orb_basis_set)) THEN
     269             :                   CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     270             :                                          nset=nset, &
     271             :                                          nshell=nshell, &
     272           0 :                                          l=l)
     273           0 :                   DO iset = 1, nset
     274           0 :                      DO ishell = 1, nshell(iset)
     275           0 :                         lshell = l(ishell, iset)
     276             :                         CALL dgemm("T", "N", nco(lshell), ncol_global, nso(lshell), 1.0_dp, &
     277             :                                    orbtramat(lshell)%c2s, nso(lshell), &
     278             :                                    smatrix(isgf, 1), nsgf, 0.0_dp, &
     279           0 :                                    cmatrix(icgf, 1), ncgf)
     280           0 :                         icgf = icgf + nco(lshell)
     281           0 :                         isgf = isgf + nso(lshell)
     282             :                      END DO
     283             :                   END DO
     284           0 :                ELSE IF (ASSOCIATED(dftb_parameter)) THEN
     285           0 :                   CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     286           0 :                   DO ishell = 1, lmax + 1
     287           0 :                      lshell = ishell - 1
     288             :                      CALL dgemm("T", "N", nco(lshell), nsgf, nso(lshell), 1.0_dp, &
     289             :                                 orbtramat(lshell)%c2s, nso(lshell), &
     290             :                                 smatrix(isgf, 1), nsgf, 0.0_dp, &
     291           0 :                                 cmatrix(icgf, 1), ncgf)
     292           0 :                      icgf = icgf + nco(lshell)
     293           0 :                      isgf = isgf + nso(lshell)
     294             :                   END DO
     295             :                ELSE
     296             :                   ! assume atom without basis set
     297             :                END IF
     298             :             END DO ! iatom
     299             : 
     300             :          END IF
     301             : 
     302             :          ! Print to file
     303          23 :          DO icol = 1, ncol_global, ncol
     304             : 
     305          15 :             from = icol
     306          15 :             to = MIN((from + ncol - 1), ncol_global)
     307             : 
     308          15 :             WRITE (UNIT=unit_mat, FMT="(T2,A)") "WS|"
     309          73 :             WRITE (UNIT=unit_mat, FMT=fmtstr1) "WS|", (jcol, jcol=from, to)
     310          15 :             WRITE (UNIT=unit_mat, FMT=fmtstr2) "WS|    Energies", &
     311          88 :                (WannierCentres%WannierHamDiag(states(jcol)), jcol=from, to)
     312          15 :             WRITE (UNIT=unit_mat, FMT="(T2,A)") "WS|"
     313             : 
     314          15 :             irow = 1
     315             : 
     316         110 :             DO iatom = 1, natom
     317             : 
     318          87 :                IF (iatom /= 1) WRITE (UNIT=unit_mat, FMT="(T2,A)") "WS|"
     319             : 
     320          87 :                NULLIFY (orb_basis_set, dftb_parameter)
     321             :                CALL get_atomic_kind(particle_set(iatom)%atomic_kind, &
     322          87 :                                     element_symbol=element_symbol, kind_number=ikind)
     323             :                CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set, &
     324          87 :                                 dftb_parameter=dftb_parameter)
     325             : 
     326         189 :                IF (print_cartesian) THEN
     327             : 
     328           0 :                   NULLIFY (bcgf_symbol)
     329           0 :                   IF (ASSOCIATED(orb_basis_set)) THEN
     330             :                      CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     331             :                                             nset=nset, &
     332             :                                             nshell=nshell, &
     333             :                                             l=l, &
     334           0 :                                             cgf_symbol=bcgf_symbol)
     335             : 
     336           0 :                      icgf = 1
     337           0 :                      DO iset = 1, nset
     338           0 :                         DO ishell = 1, nshell(iset)
     339           0 :                            lshell = l(ishell, iset)
     340           0 :                            DO ico = 1, nco(lshell)
     341             :                               WRITE (UNIT=unit_mat, FMT=fmtstr3) &
     342           0 :                                  "WS|", irow, iatom, ADJUSTR(element_symbol), bcgf_symbol(icgf), &
     343           0 :                                  (cmatrix(irow, jcol), jcol=from, to)
     344           0 :                               icgf = icgf + 1
     345           0 :                               irow = irow + 1
     346             :                            END DO
     347             :                         END DO
     348             :                      END DO
     349           0 :                   ELSE IF (ASSOCIATED(dftb_parameter)) THEN
     350           0 :                      CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     351           0 :                      icgf = 1
     352           0 :                      DO ishell = 1, lmax + 1
     353           0 :                         lshell = ishell - 1
     354           0 :                         DO ico = 1, nco(lshell)
     355           0 :                            symbol = cgf_symbol(1, indco(1:3, icgf))
     356           0 :                            symbol(1:2) = "  "
     357             :                            WRITE (UNIT=unit_mat, FMT=fmtstr3) &
     358           0 :                               "WS|", irow, iatom, ADJUSTR(element_symbol), symbol, &
     359           0 :                               (cmatrix(irow, jcol), jcol=from, to)
     360           0 :                            icgf = icgf + 1
     361           0 :                            irow = irow + 1
     362             :                         END DO
     363             :                      END DO
     364             :                   ELSE
     365             :                      ! assume atom without basis set
     366             :                   END IF
     367             : 
     368             :                ELSE !print in spherical AO basis
     369             : 
     370          87 :                   IF (ASSOCIATED(orb_basis_set)) THEN
     371             :                      CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     372             :                                             nset=nset, &
     373             :                                             nshell=nshell, &
     374             :                                             l=l, &
     375          87 :                                             sgf_symbol=bsgf_symbol)
     376          87 :                      isgf = 1
     377         255 :                      DO iset = 1, nset
     378         525 :                         DO ishell = 1, nshell(iset)
     379         270 :                            lshell = l(ishell, iset)
     380         970 :                            DO iso = 1, nso(lshell)
     381             :                               WRITE (UNIT=unit_mat, FMT=fmtstr3) &
     382         532 :                                  "WS|", irow, iatom, ADJUSTR(element_symbol), bsgf_symbol(isgf), &
     383        1064 :                                  (smatrix(irow, jcol), jcol=from, to)
     384         532 :                               isgf = isgf + 1
     385         802 :                               irow = irow + 1
     386             :                            END DO
     387             :                         END DO
     388             :                      END DO
     389           0 :                   ELSE IF (ASSOCIATED(dftb_parameter)) THEN
     390           0 :                      CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     391           0 :                      isgf = 1
     392           0 :                      DO ishell = 1, lmax + 1
     393           0 :                         lshell = ishell - 1
     394           0 :                         DO iso = 1, nso(lshell)
     395           0 :                            symbol = sgf_symbol(1, lshell, -lshell + iso - 1)
     396           0 :                            symbol(1:2) = "  "
     397             :                            WRITE (UNIT=unit_mat, FMT=fmtstr3) &
     398           0 :                               "WS|", irow, iatom, ADJUSTR(element_symbol), symbol, &
     399           0 :                               (smatrix(irow, jcol), jcol=from, to)
     400           0 :                            isgf = isgf + 1
     401           0 :                            irow = irow + 1
     402             :                         END DO
     403             :                      END DO
     404             :                   ELSE
     405             :                      ! assume atom without basis set
     406             :                   END IF
     407             : 
     408             :                END IF ! print cartesian
     409             : 
     410             :             END DO ! iatom
     411             : 
     412             :          END DO ! icol
     413             : 
     414           8 :          WRITE (UNIT=unit_mat, FMT="(T2,A)") "WS|"
     415             : 
     416           8 :          IF (print_cartesian) THEN
     417           0 :             DEALLOCATE (cmatrix)
     418             :          END IF
     419             : 
     420             :       END IF ! output Wannier states in AO
     421          16 :       DEALLOCATE (smatrix)
     422             : 
     423             :       CALL cp_print_key_finished_output(unit_mat, logger, loc_print_section, &
     424          16 :                                         "WANNIER_STATES")
     425             : 
     426          16 :       CALL timestop(handle)
     427          96 :    END SUBROUTINE construct_wannier_states
     428             : 
     429             : END MODULE wannier_states
     430             : 

Generated by: LCOV version 1.15