LCOV - code coverage report
Current view: top level - src - molecular_states.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 119 121 98.3 %
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 molecular states
      10             : !> \author CJM
      11             : ! **************************************************************************************************
      12             : MODULE molecular_states
      13             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      14             :    USE bibliography,                    ONLY: Hunt2003,&
      15             :                                               cite_reference
      16             :    USE cell_types,                      ONLY: cell_type
      17             :    USE cp_control_types,                ONLY: dft_control_type
      18             :    USE cp_dbcsr_api,                    ONLY: dbcsr_type
      19             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply
      20             :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      21             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      22             :                                               cp_fm_struct_release,&
      23             :                                               cp_fm_struct_type
      24             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      25             :                                               cp_fm_get_element,&
      26             :                                               cp_fm_get_info,&
      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_p_file,&
      34             :                                               cp_print_key_finished_output,&
      35             :                                               cp_print_key_should_output,&
      36             :                                               cp_print_key_unit_nr
      37             :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      38             :    USE input_section_types,             ONLY: section_get_ivals,&
      39             :                                               section_vals_type,&
      40             :                                               section_vals_val_get
      41             :    USE kinds,                           ONLY: default_path_length,&
      42             :                                               default_string_length,&
      43             :                                               dp
      44             :    USE message_passing,                 ONLY: mp_para_env_type
      45             :    USE molecule_types,                  ONLY: molecule_type
      46             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      47             :    USE particle_list_types,             ONLY: particle_list_type
      48             :    USE particle_types,                  ONLY: particle_type
      49             :    USE pw_env_types,                    ONLY: pw_env_type
      50             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      51             :                                               pw_r3d_rs_type
      52             :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      53             :    USE qs_environment_types,            ONLY: get_qs_env,&
      54             :                                               qs_environment_type
      55             :    USE qs_kind_types,                   ONLY: qs_kind_type
      56             : #include "./base/base_uses.f90"
      57             : 
      58             :    IMPLICIT NONE
      59             : 
      60             :    PRIVATE
      61             : 
      62             : ! *** Global parameters ***
      63             : 
      64             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'molecular_states'
      65             : 
      66             :    LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
      67             : 
      68             : ! *** Public subroutines ***
      69             : 
      70             :    PUBLIC :: construct_molecular_states
      71             : 
      72             : CONTAINS
      73             : 
      74             : ! **************************************************************************************************
      75             : !> \brief constructs molecular states. mo_localized gets overwritten!
      76             : !> \param molecule_set ...
      77             : !> \param mo_localized ...
      78             : !> \param mo_coeff ...
      79             : !> \param mo_eigenvalues ...
      80             : !> \param Hks ...
      81             : !> \param matrix_S ...
      82             : !> \param qs_env ...
      83             : !> \param wf_r ...
      84             : !> \param wf_g ...
      85             : !> \param loc_print_section ...
      86             : !> \param particles ...
      87             : !> \param tag ...
      88             : !> \param marked_states ...
      89             : !> \param ispin ...
      90             : ! **************************************************************************************************
      91          28 :    SUBROUTINE construct_molecular_states(molecule_set, mo_localized, &
      92             :                                          mo_coeff, mo_eigenvalues, Hks, matrix_S, qs_env, wf_r, wf_g, &
      93             :                                          loc_print_section, particles, tag, marked_states, ispin)
      94             : 
      95             :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
      96             :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_localized, mo_coeff
      97             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
      98             :       TYPE(dbcsr_type), POINTER                          :: Hks, matrix_S
      99             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     100             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: wf_r
     101             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: wf_g
     102             :       TYPE(section_vals_type), POINTER                   :: loc_print_section
     103             :       TYPE(particle_list_type), POINTER                  :: particles
     104             :       CHARACTER(LEN=*), INTENT(IN)                       :: tag
     105             :       INTEGER, DIMENSION(:), POINTER                     :: marked_states
     106             :       INTEGER, INTENT(IN)                                :: ispin
     107             : 
     108             :       CHARACTER(len=*), PARAMETER :: routineN = 'construct_molecular_states'
     109             : 
     110             :       CHARACTER(LEN=default_path_length)                 :: filename
     111             :       CHARACTER(LEN=default_string_length)               :: title
     112             :       INTEGER                                            :: handle, i, imol, iproc, k, n_rep, &
     113             :                                                             ncol_global, nproc, nrow_global, ns, &
     114             :                                                             output_unit, unit_nr, unit_report
     115          28 :       INTEGER, DIMENSION(:), POINTER                     :: ind, mark_list
     116          28 :       INTEGER, DIMENSION(:, :), POINTER                  :: mark_states
     117          28 :       INTEGER, POINTER                                   :: nstates(:), states(:)
     118             :       LOGICAL                                            :: explicit, mpi_io
     119             :       REAL(KIND=dp)                                      :: tmp
     120          28 :       REAL(KIND=dp), ALLOCATABLE                         :: evals(:)
     121          28 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eval_range
     122          28 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     123             :       TYPE(cell_type), POINTER                           :: cell
     124             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     125             :       TYPE(cp_fm_type)                                   :: b, c, d, D_igk, e_vectors, &
     126             :                                                             rot_e_vectors, smo, storage
     127             :       TYPE(cp_logger_type), POINTER                      :: logger
     128             :       TYPE(dft_control_type), POINTER                    :: dft_control
     129             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     130          28 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     131             :       TYPE(pw_env_type), POINTER                         :: pw_env
     132          28 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     133             : 
     134          28 :       CALL cite_reference(Hunt2003)
     135             : 
     136          28 :       CALL timeset(routineN, handle)
     137             : 
     138          28 :       NULLIFY (logger, mark_states, mark_list, para_env)
     139          28 :       logger => cp_get_default_logger()
     140             :       !-----------------------------------------------------------------------------
     141             :       ! 1.
     142             :       !-----------------------------------------------------------------------------
     143          28 :       CALL get_qs_env(qs_env, para_env=para_env)
     144          28 :       nproc = para_env%num_pe
     145          28 :       output_unit = cp_logger_get_default_io_unit(logger)
     146             :       CALL section_vals_val_get(loc_print_section, "MOLECULAR_STATES%CUBE_EVAL_RANGE", &
     147          28 :                                 explicit=explicit)
     148          28 :       IF (explicit) THEN
     149             :          CALL section_vals_val_get(loc_print_section, "MOLECULAR_STATES%CUBE_EVAL_RANGE", &
     150           0 :                                    r_vals=eval_range)
     151             :       ELSE
     152          28 :          ALLOCATE (eval_range(2))
     153          28 :          eval_range(1) = -HUGE(0.0_dp)
     154          28 :          eval_range(2) = +HUGE(0.0_dp)
     155             :       END IF
     156             :       CALL section_vals_val_get(loc_print_section, "MOLECULAR_STATES%MARK_STATES", &
     157          28 :                                 n_rep_val=n_rep)
     158          28 :       IF (n_rep .GT. 0) THEN
     159          84 :          ALLOCATE (mark_states(2, n_rep))
     160          28 :          IF (.NOT. ASSOCIATED(marked_states)) THEN
     161          84 :             ALLOCATE (marked_states(n_rep))
     162             :          END IF
     163          64 :          DO i = 1, n_rep
     164             :             CALL section_vals_val_get(loc_print_section, "MOLECULAR_STATES%MARK_STATES", &
     165          36 :                                       i_rep_val=i, i_vals=mark_list)
     166         208 :             mark_states(:, i) = mark_list(:)
     167             :          END DO
     168             :       ELSE
     169           0 :          NULLIFY (marked_states)
     170             :       END IF
     171             : 
     172             :       !-----------------------------------------------------------------------------
     173             :       !-----------------------------------------------------------------------------
     174             :       ! 2.
     175             :       !-----------------------------------------------------------------------------
     176             :       unit_report = cp_print_key_unit_nr(logger, loc_print_section, "MOLECULAR_STATES", &
     177          28 :                                          extension=".data", middle_name="Molecular_DOS", log_filename=.FALSE.)
     178          28 :       IF (unit_report > 0) THEN
     179          14 :          WRITE (unit_report, *) SIZE(mo_eigenvalues), " number of states "
     180         104 :          DO i = 1, SIZE(mo_eigenvalues)
     181         104 :             WRITE (unit_report, *) mo_eigenvalues(i)
     182             :          END DO
     183             :       END IF
     184             : 
     185             :       !-----------------------------------------------------------------------------
     186             :       !-----------------------------------------------------------------------------
     187             :       ! 3.
     188             :       !-----------------------------------------------------------------------------
     189             :       CALL cp_fm_get_info(mo_localized, &
     190             :                           ncol_global=ncol_global, &
     191          28 :                           nrow_global=nrow_global)
     192          28 :       CALL cp_fm_create(smo, mo_coeff%matrix_struct)
     193          28 :       CALL cp_dbcsr_sm_fm_multiply(matrix_S, mo_coeff, smo, ncol_global)
     194             : 
     195             :       !-----------------------------------------------------------------------------
     196             :       !-----------------------------------------------------------------------------
     197             :       ! 4.
     198             :       !-----------------------------------------------------------------------------
     199          28 :       ALLOCATE (nstates(2))
     200             : 
     201          28 :       CALL cp_fm_create(storage, mo_localized%matrix_struct, name='storage')
     202             : 
     203          72 :       DO imol = 1, SIZE(molecule_set)
     204          44 :          IF (ASSOCIATED(molecule_set(imol)%lmi)) THEN
     205          22 :             nstates(1) = molecule_set(imol)%lmi(ispin)%nstates
     206             :          ELSE
     207          22 :             nstates(1) = 0
     208             :          END IF
     209          44 :          nstates(2) = para_env%mepos
     210             : 
     211         220 :          CALL para_env%maxloc(nstates)
     212             : 
     213          44 :          IF (nstates(1) == 0) CYCLE
     214          44 :          NULLIFY (states)
     215         132 :          ALLOCATE (states(nstates(1)))
     216         192 :          states(:) = 0
     217             : 
     218          44 :          iproc = nstates(2)
     219          44 :          IF (iproc == para_env%mepos) THEN
     220          96 :             states(:) = molecule_set(imol)%lmi(ispin)%states(:)
     221             :          END IF
     222             :          !!BCAST from here root = iproc
     223         340 :          CALL para_env%bcast(states, iproc)
     224             : 
     225          44 :          ns = nstates(1)
     226          44 :          ind => states(:)
     227         132 :          ALLOCATE (evals(ns))
     228             : 
     229          44 :          NULLIFY (fm_struct_tmp)
     230             : 
     231             :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nrow_global, &
     232             :                                   ncol_global=ns, &
     233             :                                   para_env=mo_localized%matrix_struct%para_env, &
     234          44 :                                   context=mo_localized%matrix_struct%context)
     235             : 
     236          44 :          CALL cp_fm_create(b, fm_struct_tmp, name="b")
     237          44 :          CALL cp_fm_create(c, fm_struct_tmp, name="c")
     238          44 :          CALL cp_fm_create(rot_e_vectors, fm_struct_tmp, name="rot_e_vectors")
     239             : 
     240          44 :          CALL cp_fm_struct_release(fm_struct_tmp)
     241             : 
     242             :          CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ns, ncol_global=ns, &
     243             :                                   para_env=mo_localized%matrix_struct%para_env, &
     244          44 :                                   context=mo_localized%matrix_struct%context)
     245             : 
     246          44 :          CALL cp_fm_create(d, fm_struct_tmp, name="d")
     247          44 :          CALL cp_fm_create(e_vectors, fm_struct_tmp, name="e_vectors")
     248          44 :          CALL cp_fm_struct_release(fm_struct_tmp)
     249             : 
     250         192 :          DO i = 1, ns
     251         192 :             CALL cp_fm_to_fm(mo_localized, b, 1, ind(i), i)
     252             :          END DO
     253             : 
     254          44 :          CALL cp_dbcsr_sm_fm_multiply(Hks, b, c, ns)
     255             : 
     256             :          CALL parallel_gemm('T', 'N', ns, ns, nrow_global, 1.0_dp, &
     257          44 :                             b, c, 0.0_dp, d)
     258             : 
     259          44 :          CALL choose_eigv_solver(d, e_vectors, evals)
     260             : 
     261          44 :          IF (output_unit > 0) WRITE (output_unit, *) ""
     262          22 :          IF (output_unit > 0) WRITE (output_unit, *) "MOLECULE ", imol
     263          44 :          IF (output_unit > 0) WRITE (output_unit, *) "NUMBER OF STATES  ", ns
     264          22 :          IF (output_unit > 0) WRITE (output_unit, *) "EIGENVALUES"
     265          22 :          IF (output_unit > 0) WRITE (output_unit, *) ""
     266          22 :          IF (output_unit > 0) WRITE (output_unit, *) "ENERGY      original MO-index"
     267             : 
     268         192 :          DO k = 1, ns
     269         148 :             IF (ASSOCIATED(mark_states)) THEN
     270         328 :                DO i = 1, n_rep
     271         328 :                   IF (imol == mark_states(1, i) .AND. k == mark_states(2, i)) marked_states(i) = ind(k)
     272             :                END DO
     273             :             END IF
     274         192 :             IF (output_unit > 0) WRITE (output_unit, *) evals(k), ind(k)
     275             :          END DO
     276          44 :          IF (unit_report > 0) THEN
     277          22 :             WRITE (unit_report, *) imol, ns, " imol, number of states"
     278          96 :             DO k = 1, ns
     279          96 :                WRITE (unit_report, *) evals(k)
     280             :             END DO
     281             :          END IF
     282             : 
     283             :          CALL parallel_gemm('N', 'N', nrow_global, ns, ns, 1.0_dp, &
     284          44 :                             b, e_vectors, 0.0_dp, rot_e_vectors)
     285             : 
     286         192 :          DO i = 1, ns
     287         192 :             CALL cp_fm_to_fm(rot_e_vectors, storage, 1, i, ind(i))
     288             :          END DO
     289             : 
     290             :          IF (.FALSE.) THEN ! this is too much data for large systems
     291             :             ! compute Eq. 6 from P. Hunt et al. (CPL 376, p. 68-74)
     292             :             CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ns, &
     293             :                                      ncol_global=ncol_global, &
     294             :                                      para_env=mo_localized%matrix_struct%para_env, &
     295             :                                      context=mo_localized%matrix_struct%context)
     296             :             CALL cp_fm_create(D_igk, fm_struct_tmp)
     297             :             CALL cp_fm_struct_release(fm_struct_tmp)
     298             :             CALL parallel_gemm('T', 'N', ns, ncol_global, nrow_global, 1.0_dp, &
     299             :                                rot_e_vectors, smo, 0.0_dp, D_igk)
     300             :             DO i = 1, ns
     301             :                DO k = 1, ncol_global
     302             :                   CALL cp_fm_get_element(D_igk, i, k, tmp)
     303             :                   IF (unit_report > 0) THEN
     304             :                      WRITE (unit_report, *) tmp**2
     305             :                   END IF
     306             :                END DO
     307             :             END DO
     308             :             CALL cp_fm_release(D_igk)
     309             :          END IF
     310             : 
     311          44 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
     312             :                                               "MOLECULAR_STATES%CUBES"), cp_p_file)) THEN
     313             : 
     314             :             CALL get_qs_env(qs_env=qs_env, &
     315             :                             atomic_kind_set=atomic_kind_set, &
     316             :                             qs_kind_set=qs_kind_set, &
     317             :                             cell=cell, &
     318             :                             dft_control=dft_control, &
     319             :                             particle_set=particle_set, &
     320          16 :                             pw_env=pw_env)
     321             : 
     322          48 :             DO i = 1, ns
     323          32 :                IF (evals(i) < eval_range(1) .OR. evals(i) > eval_range(2)) CYCLE
     324             : 
     325             :                CALL calculate_wavefunction(rot_e_vectors, i, wf_r, &
     326             :                                            wf_g, atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, &
     327          32 :                                            pw_env)
     328             : 
     329          32 :                WRITE (filename, '(a9,I4.4,a1,I5.5,a4)') "MOLECULE_", imol, "_", i, tag
     330          32 :                WRITE (title, '(A,I0,A,I0,A,F14.6,A,I0)') "Mol. Eigenstate ", i, " of ", ns, " E [a.u.] = ", &
     331          64 :                   evals(i), " Orig. index ", ind(i)
     332          32 :                mpi_io = .TRUE.
     333             :                unit_nr = cp_print_key_unit_nr(logger, loc_print_section, "MOLECULAR_STATES%CUBES", &
     334             :                                               extension=".cube", middle_name=TRIM(filename), log_filename=.FALSE., &
     335          32 :                                               mpi_io=mpi_io)
     336             :                CALL cp_pw_to_cube(wf_r, unit_nr, particles=particles, title=title, &
     337             :                                   stride=section_get_ivals(loc_print_section, &
     338          32 :                                                            "MOLECULAR_STATES%CUBES%STRIDE"), mpi_io=mpi_io)
     339             :                CALL cp_print_key_finished_output(unit_nr, logger, loc_print_section, &
     340          48 :                                                  "MOLECULAR_STATES%CUBES", mpi_io=mpi_io)
     341             :             END DO
     342             :          END IF
     343             : 
     344          44 :          DEALLOCATE (evals)
     345          44 :          CALL cp_fm_release(b)
     346          44 :          CALL cp_fm_release(c)
     347          44 :          CALL cp_fm_release(d)
     348          44 :          CALL cp_fm_release(e_vectors)
     349          44 :          CALL cp_fm_release(rot_e_vectors)
     350             : 
     351         160 :          DEALLOCATE (states)
     352             : 
     353             :       END DO
     354          28 :       CALL cp_fm_release(smo)
     355          28 :       CALL cp_fm_to_fm(storage, mo_localized)
     356          28 :       CALL cp_fm_release(storage)
     357          28 :       IF (ASSOCIATED(mark_states)) THEN
     358          28 :          DEALLOCATE (mark_states)
     359             :       END IF
     360          28 :       DEALLOCATE (nstates)
     361             :       CALL cp_print_key_finished_output(unit_report, logger, loc_print_section, &
     362          28 :                                         "MOLECULAR_STATES")
     363             :       !------------------------------------------------------------------------------
     364             : 
     365          28 :       IF (.NOT. explicit) THEN
     366          28 :          DEALLOCATE (eval_range)
     367             :       END IF
     368             : 
     369          28 :       CALL timestop(handle)
     370             : 
     371         168 :    END SUBROUTINE construct_molecular_states
     372             : 
     373             : END MODULE molecular_states

Generated by: LCOV version 1.15