LCOV - code coverage report
Current view: top level - src - et_coupling_proj.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:1f285aa) Lines: 473 617 76.7 %
Date: 2024-04-23 06:49:27 Functions: 15 20 75.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 calculates the electron transfer coupling elements by projection-operator approach
      10             : !>        Kondov et al. J.Phys.Chem.C 2007, 111, 11970-11981
      11             : !> \author Z. Futera (02.2017)
      12             : ! **************************************************************************************************
      13             : MODULE et_coupling_proj
      14             : 
      15             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      16             :                                               get_atomic_kind
      17             :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      18             :                                               gto_basis_set_type
      19             :    USE bibliography,                    ONLY: Futera2017,&
      20             :                                               cite_reference
      21             :    USE cell_types,                      ONLY: cell_type
      22             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      23             :    USE cp_control_types,                ONLY: dft_control_type
      24             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      25             :                                               cp_dbcsr_sm_fm_multiply
      26             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      27             :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      28             :                                               cp_fm_power
      29             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      30             :                                               cp_fm_struct_equivalent,&
      31             :                                               cp_fm_struct_release,&
      32             :                                               cp_fm_struct_type
      33             :    USE cp_fm_types,                     ONLY: &
      34             :         cp_fm_create, cp_fm_get_element, cp_fm_get_submatrix, cp_fm_release, cp_fm_set_all, &
      35             :         cp_fm_set_element, cp_fm_to_fm, cp_fm_to_fm_submat, cp_fm_type, cp_fm_vectorssum
      36             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      37             :                                               cp_logger_type,&
      38             :                                               cp_to_string
      39             :    USE cp_output_handling,              ONLY: cp_p_file,&
      40             :                                               cp_print_key_finished_output,&
      41             :                                               cp_print_key_should_output,&
      42             :                                               cp_print_key_unit_nr
      43             :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      44             :    USE dbcsr_api,                       ONLY: dbcsr_p_type
      45             :    USE input_section_types,             ONLY: section_get_ivals,&
      46             :                                               section_get_lval,&
      47             :                                               section_vals_get,&
      48             :                                               section_vals_get_subs_vals,&
      49             :                                               section_vals_type,&
      50             :                                               section_vals_val_get
      51             :    USE kinds,                           ONLY: default_path_length,&
      52             :                                               default_string_length,&
      53             :                                               dp
      54             :    USE kpoint_types,                    ONLY: kpoint_type
      55             :    USE message_passing,                 ONLY: mp_para_env_type
      56             :    USE orbital_pointers,                ONLY: nso
      57             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      58             :    USE particle_list_types,             ONLY: particle_list_type
      59             :    USE particle_types,                  ONLY: particle_type
      60             :    USE physcon,                         ONLY: evolt
      61             :    USE pw_env_types,                    ONLY: pw_env_get,&
      62             :                                               pw_env_type
      63             :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      64             :                                               pw_pool_type
      65             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      66             :                                               pw_r3d_rs_type
      67             :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      68             :    USE qs_environment_types,            ONLY: get_qs_env,&
      69             :                                               qs_environment_type
      70             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      71             :                                               get_qs_kind_set,&
      72             :                                               qs_kind_type
      73             :    USE qs_mo_methods,                   ONLY: make_mo_eig
      74             :    USE qs_mo_occupation,                ONLY: set_mo_occupation
      75             :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      76             :                                               deallocate_mo_set,&
      77             :                                               mo_set_type
      78             :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
      79             :                                               qs_subsys_type
      80             :    USE scf_control_types,               ONLY: scf_control_type
      81             : #include "./base/base_uses.f90"
      82             : 
      83             :    IMPLICIT NONE
      84             : 
      85             :    PRIVATE
      86             : 
      87             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'et_coupling_proj'
      88             : 
      89             :    ! Electronic-coupling calculation data structure
      90             :    !
      91             :    ! n_atoms      - number of atoms in the blocks
      92             :    ! n_blocks     - number of atomic blocks (donor,acceptor,bridge,...)
      93             :    ! fermi        - system Fermi level (alpha/beta spin component)
      94             :    ! m_transf     - transformation matrix for basis-set orthogonalization (S^{-1/2})
      95             :    ! m_transf_inv - inversion transformation matrix
      96             :    ! block        - atomic data blocks
      97             :    TYPE et_cpl
      98             :       INTEGER                                            :: n_atoms = 0
      99             :       INTEGER                                            :: n_blocks = 0
     100             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: fermi => NULL()
     101             :       TYPE(cp_fm_type), POINTER                          :: m_transf => NULL()
     102             :       TYPE(cp_fm_type), POINTER                          :: m_transf_inv => NULL()
     103             :       TYPE(et_cpl_block), DIMENSION(:), POINTER          :: block => NULL()
     104             :    END TYPE et_cpl
     105             : 
     106             :    ! Electronic-coupling data block
     107             :    !
     108             :    ! n_atoms     - number of atoms
     109             :    ! n_electrons - number of electrons
     110             :    ! n_ao        - number of AO basis functions
     111             :    ! atom        - list of atoms
     112             :    ! mo          - electronic states
     113             :    ! hab         - electronic-coupling elements
     114             :    TYPE et_cpl_block
     115             :       INTEGER                                            :: n_atoms = 0
     116             :       INTEGER                                            :: n_electrons = 0
     117             :       INTEGER                                            :: n_ao = 0
     118             :       TYPE(et_cpl_atom), DIMENSION(:), POINTER           :: atom => NULL()
     119             :       TYPE(mo_set_type), DIMENSION(:), POINTER         :: mo => NULL()
     120             :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER        :: hab => NULL()
     121             :    END TYPE et_cpl_block
     122             : 
     123             :    ! Electronic-coupling block-atom data
     124             :    ! id     - atom ID
     125             :    ! n_ao   - number of AO basis functions
     126             :    ! ao_pos - position of atom in array of AO functions
     127             :    TYPE et_cpl_atom
     128             :       INTEGER                                            :: id = 0
     129             :       INTEGER                                            :: n_ao = 0
     130             :       INTEGER                                            :: ao_pos = 0
     131             :    END TYPE et_cpl_atom
     132             : 
     133             :    PUBLIC :: calc_et_coupling_proj
     134             : 
     135             : CONTAINS
     136             : 
     137             : ! **************************************************************************************************
     138             : !> \brief Release memory allocate for electronic coupling data structures
     139             : !> \param ec electronic coupling data structure
     140             : !> \author Z. Futera (02.2017)
     141             : ! **************************************************************************************************
     142          10 :    SUBROUTINE release_ec_data(ec)
     143             : 
     144             :       ! Routine arguments
     145             :       TYPE(et_cpl), POINTER                              :: ec
     146             : 
     147             :       INTEGER                                            :: i, j
     148             : 
     149             : ! Routine name for debug purposes
     150             : 
     151          10 :       IF (ASSOCIATED(ec)) THEN
     152             : 
     153          10 :          IF (ASSOCIATED(ec%fermi)) &
     154          10 :             DEALLOCATE (ec%fermi)
     155          10 :          IF (ASSOCIATED(ec%m_transf)) THEN
     156          10 :             CALL cp_fm_release(matrix=ec%m_transf)
     157          10 :             DEALLOCATE (ec%m_transf)
     158          10 :             NULLIFY (ec%m_transf)
     159             :          END IF
     160          10 :          IF (ASSOCIATED(ec%m_transf_inv)) THEN
     161          10 :             CALL cp_fm_release(matrix=ec%m_transf_inv)
     162          10 :             DEALLOCATE (ec%m_transf_inv)
     163          10 :             NULLIFY (ec%m_transf_inv)
     164             :          END IF
     165             : 
     166          10 :          IF (ASSOCIATED(ec%block)) THEN
     167             : 
     168          30 :             DO i = 1, SIZE(ec%block)
     169          20 :                IF (ASSOCIATED(ec%block(i)%atom)) &
     170          20 :                   DEALLOCATE (ec%block(i)%atom)
     171          20 :                IF (ASSOCIATED(ec%block(i)%mo)) THEN
     172          60 :                   DO j = 1, SIZE(ec%block(i)%mo)
     173          60 :                      CALL deallocate_mo_set(ec%block(i)%mo(j))
     174             :                   END DO
     175          20 :                   DEALLOCATE (ec%block(i)%mo)
     176             :                END IF
     177          30 :                CALL cp_fm_release(ec%block(i)%hab)
     178             :             END DO
     179             : 
     180          10 :             DEALLOCATE (ec%block)
     181             : 
     182             :          END IF
     183             : 
     184          10 :          DEALLOCATE (ec)
     185             : 
     186             :       END IF
     187             : 
     188          10 :    END SUBROUTINE release_ec_data
     189             : 
     190             : ! **************************************************************************************************
     191             : !> \brief check the electronic-coupling input section and set the atomic block data
     192             : !> \param qs_env QuickStep environment containing all system data
     193             : !> \param et_proj_sec the electronic-coupling input section
     194             : !> \param ec electronic coupling data structure
     195             : !> \author Z. Futera (02.2017)
     196             : ! **************************************************************************************************
     197          10 :    SUBROUTINE set_block_data(qs_env, et_proj_sec, ec)
     198             : 
     199             :       ! Routine arguments
     200             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     201             :       TYPE(section_vals_type), POINTER                   :: et_proj_sec
     202             :       TYPE(et_cpl), POINTER                              :: ec
     203             : 
     204             :       INTEGER                                            :: i, j, k, l, n, n_ao, n_atoms, n_set
     205          10 :       INTEGER, DIMENSION(:), POINTER                     :: atom_id, atom_nf, atom_ps, n_shell, t
     206          10 :       INTEGER, DIMENSION(:, :), POINTER                  :: ang_mom_id
     207             :       LOGICAL                                            :: found
     208             :       TYPE(gto_basis_set_type), POINTER                  :: ao_basis_set
     209          10 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     210          10 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     211             :       TYPE(section_vals_type), POINTER                   :: block_sec
     212             : 
     213             : ! Routine name for debug purposes
     214             : 
     215          10 :       NULLIFY (ao_basis_set)
     216          10 :       NULLIFY (particle_set)
     217          10 :       NULLIFY (qs_kind_set)
     218          10 :       NULLIFY (n_shell)
     219          10 :       NULLIFY (ang_mom_id)
     220          10 :       NULLIFY (atom_nf)
     221          10 :       NULLIFY (atom_id)
     222          10 :       NULLIFY (block_sec)
     223             : 
     224             :       ! Initialization
     225          10 :       ec%n_atoms = 0
     226          10 :       ec%n_blocks = 0
     227          10 :       NULLIFY (ec%fermi)
     228          10 :       NULLIFY (ec%m_transf)
     229          10 :       NULLIFY (ec%m_transf_inv)
     230          10 :       NULLIFY (ec%block)
     231             : 
     232             :       ! Number of atoms / atom types
     233          10 :       CALL get_qs_env(qs_env, particle_set=particle_set, qs_kind_set=qs_kind_set, natom=n_atoms)
     234             :       ! Number of AO basis functions
     235          10 :       CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
     236             : 
     237             :       ! Number of AO functions per atom
     238          30 :       ALLOCATE (atom_nf(n_atoms))
     239          10 :       CPASSERT(ASSOCIATED(atom_nf))
     240             : 
     241          82 :       atom_nf = 0
     242          82 :       DO i = 1, n_atoms
     243          72 :          CALL get_atomic_kind(particle_set(i)%atomic_kind, kind_number=j)
     244          72 :          CALL get_qs_kind(qs_kind_set(j), basis_set=ao_basis_set)
     245          72 :          IF (.NOT. ASSOCIATED(ao_basis_set)) &
     246           0 :             CPABORT('Unsupported basis set type. ')
     247             :          CALL get_gto_basis_set(gto_basis_set=ao_basis_set, &
     248          72 :                                 nset=n_set, nshell=n_shell, l=ang_mom_id)
     249         238 :          DO j = 1, n_set
     250         280 :             DO k = 1, n_shell(j)
     251         208 :                atom_nf(i) = atom_nf(i) + nso(ang_mom_id(k, j))
     252             :             END DO
     253             :          END DO
     254             :       END DO
     255             : 
     256             :       ! Sanity check
     257          10 :       n = 0
     258          82 :       DO i = 1, n_atoms
     259          82 :          n = n + atom_nf(i)
     260             :       END DO
     261          10 :       CPASSERT(n == n_ao)
     262             : 
     263             :       ! Atom position in AO array
     264          30 :       ALLOCATE (atom_ps(n_atoms))
     265          10 :       CPASSERT(ASSOCIATED(atom_ps))
     266          82 :       atom_ps = 1
     267          72 :       DO i = 1, n_atoms - 1
     268          72 :          atom_ps(i + 1) = atom_ps(i) + atom_nf(i)
     269             :       END DO
     270             : 
     271             :       ! Number of blocks
     272          10 :       block_sec => section_vals_get_subs_vals(et_proj_sec, 'BLOCK')
     273          10 :       CALL section_vals_get(block_sec, n_repetition=ec%n_blocks)
     274          50 :       ALLOCATE (ec%block(ec%n_blocks))
     275          10 :       CPASSERT(ASSOCIATED(ec%block))
     276             : 
     277             :       ! Block data
     278          30 :       ALLOCATE (t(n_atoms))
     279          10 :       CPASSERT(ASSOCIATED(t))
     280             : 
     281          10 :       ec%n_atoms = 0
     282          30 :       DO i = 1, ec%n_blocks
     283             : 
     284             :          ! Initialization
     285          20 :          ec%block(i)%n_atoms = 0
     286          20 :          ec%block(i)%n_electrons = 0
     287          20 :          ec%block(i)%n_ao = 0
     288          20 :          NULLIFY (ec%block(i)%atom)
     289          20 :          NULLIFY (ec%block(i)%mo)
     290          20 :          NULLIFY (ec%block(i)%hab)
     291             : 
     292             :          ! Number of electrons
     293             :          CALL section_vals_val_get(block_sec, i_rep_section=i, &
     294          20 :                                    keyword_name='NELECTRON', i_val=ec%block(i)%n_electrons)
     295             : 
     296             :          ! User-defined atom array
     297             :          CALL section_vals_val_get(block_sec, i_rep_section=i, &
     298          20 :                                    keyword_name='ATOMS', i_vals=atom_id)
     299             : 
     300             :          ! Count unique atoms
     301          92 :          DO j = 1, SIZE(atom_id)
     302             :             ! Check atom ID validity
     303          72 :             IF (atom_id(j) < 1 .OR. atom_id(j) > n_atoms) &
     304           0 :                CPABORT('invalid fragment atom ID ('//TRIM(ADJUSTL(cp_to_string(atom_id(j))))//')')
     305             :             ! Check if the atom is not in previously-defined blocks
     306             :             found = .FALSE.
     307         108 :             DO k = 1, i - 1
     308         348 :                DO l = 1, ec%block(k)%n_atoms
     309         276 :                   IF (ec%block(k)%atom(l)%id == atom_id(j)) THEN
     310           0 :                      CPWARN('multiple definition of atom'//TRIM(ADJUSTL(cp_to_string(atom_id(j)))))
     311           0 :                      found = .TRUE.
     312           0 :                      EXIT
     313             :                   END IF
     314             :                END DO
     315             :             END DO
     316             :             ! Check if the atom is not in already defined in the present block
     317          72 :             IF (.NOT. found) THEN
     318         276 :                DO k = 1, ec%block(i)%n_atoms
     319         276 :                   IF (t(k) == atom_id(j)) THEN
     320           0 :                      CPWARN('multiple definition of atom'//TRIM(ADJUSTL(cp_to_string(atom_id(j)))))
     321             :                      found = .TRUE.
     322             :                      EXIT
     323             :                   END IF
     324             :                END DO
     325             :             END IF
     326             :             ! Save the atom
     327          92 :             IF (.NOT. found) THEN
     328          72 :                ec%block(i)%n_atoms = ec%block(i)%n_atoms + 1
     329          72 :                t(ec%block(i)%n_atoms) = atom_id(j)
     330             :             END IF
     331             :          END DO
     332             : 
     333             :          ! Memory allocation
     334         132 :          ALLOCATE (ec%block(i)%atom(ec%block(i)%n_atoms))
     335          20 :          CPASSERT(ASSOCIATED(ec%block(i)%atom))
     336             : 
     337             :          ! Save atom IDs and number of AOs
     338          92 :          DO j = 1, ec%block(i)%n_atoms
     339          72 :             ec%block(i)%atom(j)%id = t(j)
     340          72 :             ec%block(i)%atom(j)%n_ao = atom_nf(ec%block(i)%atom(j)%id)
     341          72 :             ec%block(i)%atom(j)%ao_pos = atom_ps(ec%block(i)%atom(j)%id)
     342          92 :             ec%block(i)%n_ao = ec%block(i)%n_ao + ec%block(i)%atom(j)%n_ao
     343             :          END DO
     344             : 
     345          30 :          ec%n_atoms = ec%n_atoms + ec%block(i)%n_atoms
     346             :       END DO
     347             : 
     348             :       ! Clean memory
     349          10 :       IF (ASSOCIATED(atom_nf)) &
     350          10 :          DEALLOCATE (atom_nf)
     351          10 :       IF (ASSOCIATED(atom_ps)) &
     352          10 :          DEALLOCATE (atom_ps)
     353          10 :       IF (ASSOCIATED(t)) &
     354          10 :          DEALLOCATE (t)
     355             : 
     356          10 :    END SUBROUTINE set_block_data
     357             : 
     358             : ! **************************************************************************************************
     359             : !> \brief check the electronic-coupling input section and set the atomic block data
     360             : !> \param ec electronic coupling data structure
     361             : !> \param fa system Fermi level (alpha spin)
     362             : !> \param fb system Fermi level (beta spin)
     363             : !> \author Z. Futera (02.2017)
     364             : ! **************************************************************************************************
     365          10 :    SUBROUTINE set_fermi(ec, fa, fb)
     366             : 
     367             :       ! Routine arguments
     368             :       TYPE(et_cpl), POINTER                              :: ec
     369             :       REAL(KIND=dp)                                      :: fa
     370             :       REAL(KIND=dp), OPTIONAL                            :: fb
     371             : 
     372             : ! Routine name for debug purposes
     373             : 
     374          10 :       NULLIFY (ec%fermi)
     375             : 
     376          10 :       IF (PRESENT(fb)) THEN
     377             : 
     378          10 :          ALLOCATE (ec%fermi(2))
     379          10 :          CPASSERT(ASSOCIATED(ec%fermi))
     380          10 :          ec%fermi(1) = fa
     381          10 :          ec%fermi(2) = fb
     382             : 
     383             :       ELSE
     384             : 
     385           0 :          ALLOCATE (ec%fermi(1))
     386           0 :          CPASSERT(ASSOCIATED(ec%fermi))
     387           0 :          ec%fermi(1) = fa
     388             : 
     389             :       END IF
     390             : 
     391          10 :    END SUBROUTINE set_fermi
     392             : 
     393             : ! **************************************************************************************************
     394             : !> \brief reorder Hamiltonian matrix according to defined atomic blocks
     395             : !> \param ec electronic coupling data structure
     396             : !> \param mat_h the Hamiltonian matrix
     397             : !> \param mat_w working matrix of the same dimension
     398             : !> \author Z. Futera (02.2017)
     399             : ! **************************************************************************************************
     400          20 :    SUBROUTINE reorder_hamiltonian_matrix(ec, mat_h, mat_w)
     401             : 
     402             :       ! Routine arguments
     403             :       TYPE(et_cpl), POINTER                              :: ec
     404             :       TYPE(cp_fm_type), INTENT(IN)                       :: mat_h, mat_w
     405             : 
     406             :       INTEGER                                            :: ic, ir, jc, jr, kc, kr, mc, mr, nc, nr
     407             :       REAL(KIND=dp)                                      :: xh
     408             : 
     409             : ! Routine name for debug purposes
     410             : ! Local variables
     411             : 
     412          20 :       IF (.NOT. cp_fm_struct_equivalent(mat_h%matrix_struct, mat_w%matrix_struct)) &
     413           0 :          CPABORT('cannot reorder Hamiltonian, working-matrix structure is not equivalent')
     414             : 
     415             :       ! Matrix-element reordering
     416          20 :       nr = 1
     417             :       ! Rows
     418          60 :       DO ir = 1, ec%n_blocks
     419         204 :          DO jr = 1, ec%block(ir)%n_atoms
     420         592 :             DO kr = 1, ec%block(ir)%atom(jr)%n_ao
     421             :                ! Columns
     422         408 :                nc = 1
     423        1224 :                DO ic = 1, ec%n_blocks
     424        6072 :                   DO jc = 1, ec%block(ic)%n_atoms
     425       18384 :                      DO kc = 1, ec%block(ic)%atom(jc)%n_ao
     426       12720 :                         mr = ec%block(ir)%atom(jr)%ao_pos + kr - 1
     427       12720 :                         mc = ec%block(ic)%atom(jc)%ao_pos + kc - 1
     428       12720 :                         CALL cp_fm_get_element(mat_h, nr, nc, xh)
     429       12720 :                         CALL cp_fm_set_element(mat_w, nr, nc, xh)
     430       30288 :                         nc = nc + 1
     431             :                      END DO
     432             :                   END DO
     433             :                END DO
     434         552 :                nr = nr + 1
     435             :             END DO
     436             :          END DO
     437             :       END DO
     438             : 
     439             :       ! Copy the reordered matrix to original data array
     440          20 :       CALL cp_fm_to_fm(mat_w, mat_h)
     441             : 
     442          20 :    END SUBROUTINE reorder_hamiltonian_matrix
     443             : 
     444             : ! **************************************************************************************************
     445             : !> \brief calculated transformation matrix for basis-set orthogonalization (S^{-1/2})
     446             : !> \param qs_env QuickStep environment containing all system data
     447             : !> \param mat_t storage for the transformation matrix
     448             : !> \param mat_i storage for the inversion transformation matrix
     449             : !> \param mat_w working matrix of the same dimension
     450             : !> \author Z. Futera (02.2017)
     451             : ! **************************************************************************************************
     452          10 :    SUBROUTINE get_s_half_inv_matrix(qs_env, mat_t, mat_i, mat_w)
     453             : 
     454             :       ! Routine arguments
     455             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     456             :       TYPE(cp_fm_type), INTENT(IN)                       :: mat_t, mat_i, mat_w
     457             : 
     458             :       INTEGER                                            :: n_deps
     459          10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_s
     460             :       TYPE(scf_control_type), POINTER                    :: scf_cntrl
     461             : 
     462             : ! Routine name for debug purposes
     463             : 
     464          10 :       NULLIFY (mat_s)
     465          10 :       NULLIFY (scf_cntrl)
     466             : 
     467          10 :       CALL get_qs_env(qs_env, matrix_s=mat_s)
     468          10 :       CALL copy_dbcsr_to_fm(mat_s(1)%matrix, mat_t)
     469          10 :       CALL copy_dbcsr_to_fm(mat_s(1)%matrix, mat_i)
     470             : 
     471             :       ! Transformation S -> S^{-1/2}
     472          10 :       CALL get_qs_env(qs_env, scf_control=scf_cntrl)
     473          10 :       CALL cp_fm_power(mat_t, mat_w, -0.5_dp, scf_cntrl%eps_eigval, n_deps)
     474          10 :       CALL cp_fm_power(mat_i, mat_w, +0.5_dp, scf_cntrl%eps_eigval, n_deps)
     475             :       ! Sanity check
     476          10 :       IF (n_deps /= 0) THEN
     477             :          CALL cp_warn(__LOCATION__, &
     478             :                       "Overlap matrix exhibits linear dependencies. At least some "// &
     479           0 :                       "eigenvalues have been quenched.")
     480             :       END IF
     481             : 
     482          10 :    END SUBROUTINE get_s_half_inv_matrix
     483             : 
     484             : ! **************************************************************************************************
     485             : !> \brief transform KS hamiltonian to orthogonalized block-separated basis set
     486             : !> \param qs_env QuickStep environment containing all system data
     487             : !> \param ec electronic coupling data structure
     488             : !> \param fm_s full-matrix structure used for allocation of KS matrices
     489             : !> \param mat_t storage for pointers to the transformed KS matrices
     490             : !> \param mat_w working matrix of the same dimension
     491             : !> \param n_ao total number of AO basis functions
     492             : !> \param n_spins number of spin components
     493             : !> \author Z. Futera (02.2017)
     494             : ! **************************************************************************************************
     495          10 :    SUBROUTINE get_block_hamiltonian(qs_env, ec, fm_s, mat_t, mat_w, n_ao, n_spins)
     496             : 
     497             :       ! Routine arguments
     498             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     499             :       TYPE(et_cpl), POINTER                              :: ec
     500             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_s
     501             :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     502             :          INTENT(OUT)                                     :: mat_t
     503             :       TYPE(cp_fm_type), INTENT(IN)                       :: mat_w
     504             :       INTEGER                                            :: n_ao, n_spins
     505             : 
     506             :       INTEGER                                            :: i
     507          10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_h
     508             : 
     509             : ! Routine name for debug purposes
     510             : 
     511          10 :       NULLIFY (mat_h)
     512             : 
     513             :       ! Memory allocation
     514          50 :       ALLOCATE (mat_t(n_spins))
     515             : 
     516             :       ! KS Hamiltonian
     517          10 :       CALL get_qs_env(qs_env, matrix_ks=mat_h)
     518             :       ! Transformation matrix
     519          10 :       ALLOCATE (ec%m_transf, ec%m_transf_inv)
     520             :       CALL cp_fm_create(matrix=ec%m_transf, matrix_struct=fm_s, &
     521          10 :                         name='S^(-1/2) TRANSFORMATION MATRIX')
     522             :       CALL cp_fm_create(matrix=ec%m_transf_inv, matrix_struct=fm_s, &
     523          10 :                         name='S^(+1/2) TRANSFORMATION MATRIX')
     524          10 :       CALL get_s_half_inv_matrix(qs_env, ec%m_transf, ec%m_transf_inv, mat_w)
     525             : 
     526          30 :       DO i = 1, n_spins
     527             : 
     528             :          ! Full-matrix format
     529             :          CALL cp_fm_create(matrix=mat_t(i), matrix_struct=fm_s, &
     530          20 :                            name='KS HAMILTONIAN IN SEPARATED ORTHOGONALIZED BASIS SET')
     531          20 :          CALL copy_dbcsr_to_fm(mat_h(i)%matrix, mat_t(i))
     532             : 
     533             :          ! Transform KS Hamiltonian to the orthogonalized AO basis set
     534          20 :          CALL parallel_gemm("N", "N", n_ao, n_ao, n_ao, 1.0_dp, ec%m_transf, mat_t(i), 0.0_dp, mat_w)
     535          20 :          CALL parallel_gemm("N", "N", n_ao, n_ao, n_ao, 1.0_dp, mat_w, ec%m_transf, 0.0_dp, mat_t(i))
     536             : 
     537             :          ! Reorder KS Hamiltonain elements to defined block structure
     538          30 :          CALL reorder_hamiltonian_matrix(ec, mat_t(i), mat_w)
     539             : 
     540             :       END DO
     541             : 
     542          10 :    END SUBROUTINE get_block_hamiltonian
     543             : 
     544             : ! **************************************************************************************************
     545             : !> \brief Diagonalize diagonal blocks of the KS hamiltonian in separated orthogonalized basis set
     546             : !> \param qs_env QuickStep environment containing all system data
     547             : !> \param ec electronic coupling data structure
     548             : !> \param mat_h Hamiltonian in separated orthogonalized basis set
     549             : !> \author Z. Futera (02.2017)
     550             : ! **************************************************************************************************
     551          10 :    SUBROUTINE hamiltonian_block_diag(qs_env, ec, mat_h)
     552             : 
     553             :       ! Routine arguments
     554             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     555             :       TYPE(et_cpl), POINTER                              :: ec
     556             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mat_h
     557             : 
     558             :       INTEGER                                            :: i, j, k, l, n_spins, spin
     559          10 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vec_e
     560             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     561             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_s
     562             :       TYPE(cp_fm_type)                                   :: mat_u
     563          10 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: dat
     564             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     565             : 
     566             : ! Routine name for debug purposes
     567             : 
     568          10 :       NULLIFY (vec_e)
     569          10 :       NULLIFY (blacs_env)
     570          10 :       NULLIFY (para_env)
     571          10 :       NULLIFY (fm_s)
     572             : 
     573             :       ! Parallel environment
     574          10 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
     575             : 
     576             :       ! Storage for block sub-matrices
     577          50 :       ALLOCATE (dat(ec%n_blocks))
     578          10 :       CPASSERT(ALLOCATED(dat))
     579             : 
     580             :       ! Storage for electronic states and couplings
     581          10 :       n_spins = SIZE(mat_h)
     582          30 :       DO i = 1, ec%n_blocks
     583         100 :          ALLOCATE (ec%block(i)%mo(n_spins))
     584          20 :          CPASSERT(ASSOCIATED(ec%block(i)%mo))
     585         200 :          ALLOCATE (ec%block(i)%hab(n_spins, ec%n_blocks))
     586          30 :          CPASSERT(ASSOCIATED(ec%block(i)%hab))
     587             :       END DO
     588             : 
     589             :       ! Spin components
     590          30 :       DO spin = 1, n_spins
     591             : 
     592             :          ! Diagonal blocks
     593          20 :          j = 1
     594          60 :          DO i = 1, ec%n_blocks
     595             : 
     596             :             ! Memory allocation
     597             :             CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
     598          40 :                                      nrow_global=ec%block(i)%n_ao, ncol_global=ec%block(i)%n_ao)
     599             :             CALL cp_fm_create(matrix=dat(i), matrix_struct=fm_s, &
     600          40 :                               name='H_KS DIAGONAL BLOCK')
     601             : 
     602         120 :             ALLOCATE (vec_e(ec%block(i)%n_ao))
     603          40 :             CPASSERT(ASSOCIATED(vec_e))
     604             : 
     605             :             ! Copy block data
     606             :             CALL cp_fm_to_fm_submat(mat_h(spin), &
     607             :                                     dat(i), ec%block(i)%n_ao, &
     608          40 :                                     ec%block(i)%n_ao, j, j, 1, 1)
     609             : 
     610             :             ! Diagonalization
     611          40 :             CALL cp_fm_create(matrix=mat_u, matrix_struct=fm_s, name='UNITARY MATRIX')
     612          40 :             CALL choose_eigv_solver(dat(i), mat_u, vec_e)
     613          40 :             CALL cp_fm_to_fm(mat_u, dat(i))
     614             : 
     615             :             ! Save state energies / vectors
     616          40 :             CALL create_block_mo_set(qs_env, ec, i, spin, mat_u, vec_e)
     617             : 
     618             :             ! Clean memory
     619          40 :             CALL cp_fm_struct_release(fmstruct=fm_s)
     620          40 :             CALL cp_fm_release(matrix=mat_u)
     621          40 :             DEALLOCATE (vec_e)
     622             : 
     623             :             ! Off-set for next block
     624          60 :             j = j + ec%block(i)%n_ao
     625             : 
     626             :          END DO
     627             : 
     628             :          ! Off-diagonal blocks
     629          20 :          k = 1
     630          60 :          DO i = 1, ec%n_blocks
     631          40 :             l = 1
     632         120 :             DO j = 1, ec%n_blocks
     633          80 :                IF (i /= j) THEN
     634             : 
     635             :                   ! Memory allocation
     636             :                   CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
     637          40 :                                            nrow_global=ec%block(i)%n_ao, ncol_global=ec%block(j)%n_ao)
     638             :                   CALL cp_fm_create(matrix=ec%block(i)%hab(spin, j), matrix_struct=fm_s, &
     639          40 :                                     name='H_KS OFF-DIAGONAL BLOCK')
     640             : 
     641             :                   ! Copy block data
     642             :                   CALL cp_fm_to_fm_submat(mat_h(spin), &
     643             :                                           ec%block(i)%hab(spin, j), ec%block(i)%n_ao, &
     644          40 :                                           ec%block(j)%n_ao, k, l, 1, 1)
     645             : 
     646             :                   ! Transformation
     647          40 :                   CALL cp_fm_create(matrix=mat_u, matrix_struct=fm_s, name='FULL WORK MATRIX')
     648             :                   CALL parallel_gemm("T", "N", ec%block(i)%n_ao, ec%block(j)%n_ao, ec%block(i)%n_ao, &
     649          40 :                                      1.0_dp, dat(i), ec%block(i)%hab(spin, j), 0.0_dp, mat_u)
     650             :                   CALL parallel_gemm("N", "N", ec%block(i)%n_ao, ec%block(j)%n_ao, ec%block(j)%n_ao, &
     651          40 :                                      1.0_dp, mat_u, dat(j), 0.0_dp, ec%block(i)%hab(spin, j))
     652             : 
     653             :                   ! Clean memory
     654          40 :                   CALL cp_fm_struct_release(fmstruct=fm_s)
     655          40 :                   CALL cp_fm_release(matrix=mat_u)
     656             : 
     657             :                END IF
     658             :                ! Off-set for next block
     659         120 :                l = l + ec%block(j)%n_ao
     660             :             END DO
     661             :             ! Off-set for next block
     662          60 :             k = k + ec%block(i)%n_ao
     663             :          END DO
     664             : 
     665             :          ! Clean memory
     666          30 :          IF (ALLOCATED(dat)) THEN
     667          60 :             DO i = 1, SIZE(dat)
     668          60 :                CALL cp_fm_release(dat(i))
     669             :             END DO
     670             :          END IF
     671             :       END DO
     672             : 
     673             :       ! Clean memory
     674          10 :       IF (ALLOCATED(dat)) &
     675          10 :          DEALLOCATE (dat)
     676             : 
     677          20 :    END SUBROUTINE hamiltonian_block_diag
     678             : 
     679             : ! **************************************************************************************************
     680             : !> \brief Return sum of selected squared MO coefficients
     681             : !> \param blk_at list of atoms in the block
     682             : !> \param mo array of MO sets
     683             : !> \param id state index
     684             : !> \param atom list of atoms for MO coefficient summing
     685             : !> \return ...
     686             : !> \author Z. Futera (02.2017)
     687             : ! **************************************************************************************************
     688           0 :    FUNCTION get_mo_c2_sum(blk_at, mo, id, atom) RESULT(c2)
     689             : 
     690             :       ! Routine arguments
     691             :       TYPE(et_cpl_atom), DIMENSION(:), POINTER           :: blk_at
     692             :       TYPE(cp_fm_type), INTENT(IN)                       :: mo
     693             :       INTEGER, INTENT(IN)                                :: id
     694             :       INTEGER, DIMENSION(:), POINTER                     :: atom
     695             :       REAL(KIND=dp)                                      :: c2
     696             : 
     697             :       INTEGER                                            :: i, ir, j, k
     698             :       LOGICAL                                            :: found
     699             :       REAL(KIND=dp)                                      :: c
     700             : 
     701             : ! Returning value
     702             : ! Routine name for debug purposes
     703             : ! Local variables
     704             : 
     705             :       ! initialization
     706           0 :       c2 = 0.0d0
     707             : 
     708             :       ! selected atoms
     709           0 :       DO i = 1, SIZE(atom)
     710             : 
     711             :          ! find atomic function offset
     712           0 :          found = .FALSE.
     713           0 :          DO j = 1, SIZE(blk_at)
     714           0 :             IF (blk_at(j)%id == atom(i)) THEN
     715             :                found = .TRUE.
     716             :                EXIT
     717             :             END IF
     718             :          END DO
     719             : 
     720           0 :          IF (.NOT. found) &
     721           0 :             CPABORT('MO-fraction atom ID not defined in the block')
     722             : 
     723             :          ! sum MO coefficients from the atom
     724           0 :          DO k = 1, blk_at(j)%n_ao
     725           0 :             ir = blk_at(j)%ao_pos + k - 1
     726           0 :             CALL cp_fm_get_element(mo, ir, id, c)
     727           0 :             c2 = c2 + c*c
     728             :          END DO
     729             : 
     730             :       END DO
     731             : 
     732           0 :    END FUNCTION get_mo_c2_sum
     733             : 
     734             : ! **************************************************************************************************
     735             : !> \brief Print out specific MO coefficients
     736             : !> \param output_unit unit number of the open output stream
     737             : !> \param qs_env QuickStep environment containing all system data
     738             : !> \param ec electronic coupling data structure
     739             : !> \param blk atomic-block ID
     740             : !> \param n_spins number of spin components
     741             : !> \author Z. Futera (02.2017)
     742             : ! **************************************************************************************************
     743          20 :    SUBROUTINE print_mo_coeff(output_unit, qs_env, ec, blk, n_spins)
     744             : 
     745             :       ! Routine arguments
     746             :       INTEGER, INTENT(IN)                                :: output_unit
     747             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     748             :       TYPE(et_cpl), POINTER                              :: ec
     749             :       INTEGER, INTENT(IN)                                :: blk, n_spins
     750             : 
     751             :       INTEGER                                            :: j, k, l, m, n, n_ao, n_mo
     752          20 :       INTEGER, DIMENSION(:), POINTER                     :: list_at, list_mo
     753             :       REAL(KIND=dp)                                      :: c1, c2
     754          20 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mat_w
     755          20 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     756             :       TYPE(section_vals_type), POINTER                   :: block_sec, print_sec
     757             : 
     758             : ! Routine name for debug purposes
     759             : 
     760          20 :       NULLIFY (block_sec)
     761          20 :       NULLIFY (print_sec)
     762          20 :       NULLIFY (qs_kind_set)
     763             : 
     764             :       ! Atomic block data
     765             :       block_sec => section_vals_get_subs_vals(qs_env%input, &
     766          40 :                                               'PROPERTIES%ET_COUPLING%PROJECTION%BLOCK')
     767             : 
     768          20 :       print_sec => section_vals_get_subs_vals(block_sec, 'PRINT', i_rep_section=blk)
     769             : 
     770             :       ! List of atoms
     771          20 :       CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM', n_rep_val=n)
     772             : 
     773          20 :       IF (n > 0) THEN
     774             : 
     775           0 :          IF (output_unit > 0) &
     776           0 :             WRITE (output_unit, '(/,T3,A/)') 'Block state fractions:'
     777             : 
     778             :          ! Number of AO functions
     779           0 :          CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
     780           0 :          CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
     781             : 
     782             :          ! MOs in orthonormal basis set
     783           0 :          ALLOCATE (mat_w(n_spins))
     784           0 :          DO j = 1, n_spins
     785           0 :             n_mo = ec%block(blk)%n_ao
     786             :             CALL cp_fm_create(matrix=mat_w(j), &
     787             :                               matrix_struct=ec%block(blk)%mo(j)%mo_coeff%matrix_struct, &
     788           0 :                               name='BLOCK MOs IN ORTHONORMAL BASIS SET')
     789             :             CALL parallel_gemm("N", "N", n_ao, n_mo, n_ao, 1.0_dp, ec%m_transf_inv, &
     790           0 :                                ec%block(blk)%mo(j)%mo_coeff, 0.0_dp, mat_w(j))
     791             :          END DO
     792             : 
     793           0 :          DO j = 1, n
     794           0 :             NULLIFY (list_at)
     795             :             CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM', &
     796           0 :                                       i_rep_val=j, i_vals=list_at)
     797           0 :             IF (ASSOCIATED(list_at)) THEN
     798             : 
     799             :                ! List of states
     800           0 :                CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM_STATE', n_rep_val=m)
     801             : 
     802           0 :                IF (m > 0) THEN
     803             : 
     804           0 :                   DO k = 1, m
     805           0 :                      NULLIFY (list_mo)
     806             :                      CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM_STATE', &
     807           0 :                                                i_rep_val=k, i_vals=list_mo)
     808           0 :                      IF (ASSOCIATED(list_mo)) THEN
     809             : 
     810           0 :                         IF (j > 1) THEN
     811           0 :                            IF (output_unit > 0) &
     812           0 :                               WRITE (output_unit, *)
     813             :                         END IF
     814             : 
     815           0 :                         DO l = 1, SIZE(list_mo)
     816             : 
     817           0 :                            IF (n_spins > 1) THEN
     818             :                               c1 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(1), &
     819           0 :                                                  list_mo(l), list_at)
     820             :                               c2 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(2), &
     821           0 :                                                  list_mo(l), list_at)
     822           0 :                               IF (output_unit > 0) &
     823           0 :                                  WRITE (output_unit, '(I5,A,I5,2F20.10)') j, ' /', list_mo(l), c1, c2
     824             :                            ELSE
     825             :                               c1 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(1), &
     826           0 :                                                  list_mo(l), list_at)
     827           0 :                               IF (output_unit > 0) &
     828           0 :                                  WRITE (output_unit, '(I5,A,I5,F20.10)') j, ' /', list_mo(l), c1
     829             :                            END IF
     830             : 
     831             :                         END DO
     832             : 
     833             :                      END IF
     834             :                   END DO
     835             : 
     836             :                END IF
     837             : 
     838             :             END IF
     839             :          END DO
     840             : 
     841             :          ! Clean memory
     842           0 :          CALL cp_fm_release(mat_w)
     843             : 
     844             :       END IF
     845             : 
     846          40 :    END SUBROUTINE print_mo_coeff
     847             : 
     848             : ! **************************************************************************************************
     849             : !> \brief Print out electronic states (MOs)
     850             : !> \param output_unit unit number of the open output stream
     851             : !> \param mo array of MO sets
     852             : !> \param n_spins number of spin components
     853             : !> \param label output label
     854             : !> \param mx_mo_a maximum number of alpha states to print out
     855             : !> \param mx_mo_b maximum number of beta states to print out
     856             : !> \param fermi print out Fermi level and number of electrons
     857             : !> \author Z. Futera (02.2017)
     858             : ! **************************************************************************************************
     859          40 :    SUBROUTINE print_states(output_unit, mo, n_spins, label, mx_mo_a, mx_mo_b, fermi)
     860             : 
     861             :       ! Routine arguments
     862             :       INTEGER, INTENT(IN)                                :: output_unit
     863             :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo
     864             :       INTEGER, INTENT(IN)                                :: n_spins
     865             :       CHARACTER(LEN=*), INTENT(IN)                       :: label
     866             :       INTEGER, INTENT(IN), OPTIONAL                      :: mx_mo_a, mx_mo_b
     867             :       LOGICAL, INTENT(IN), OPTIONAL                      :: fermi
     868             : 
     869             :       INTEGER                                            :: i, mx_a, mx_b, n
     870             :       LOGICAL                                            :: prnt_fm
     871             : 
     872             : ! Routine name for debug purposes
     873             : 
     874          20 :       prnt_fm = .FALSE.
     875          20 :       IF (PRESENT(fermi)) &
     876          20 :          prnt_fm = fermi
     877             : 
     878          20 :       IF (output_unit > 0) THEN
     879             : 
     880          15 :          WRITE (output_unit, '(/,T3,A/)') 'State energies ('//TRIM(ADJUSTL(label))//'):'
     881             : 
     882             :          ! Spin-polarized calculation
     883          15 :          IF (n_spins > 1) THEN
     884             : 
     885          15 :             mx_a = mo(1)%nmo
     886          15 :             IF (PRESENT(mx_mo_a)) &
     887          10 :                mx_a = MIN(mo(1)%nmo, mx_mo_a)
     888          15 :             mx_b = mo(2)%nmo
     889          15 :             IF (PRESENT(mx_mo_b)) &
     890          10 :                mx_b = MIN(mo(2)%nmo, mx_mo_b)
     891          15 :             n = MAX(mx_a, mx_b)
     892             : 
     893         181 :             DO i = 1, n
     894         166 :                WRITE (output_unit, '(T3,I10)', ADVANCE='no') i
     895         166 :                IF (i <= mx_a) THEN
     896             :                   WRITE (output_unit, '(2F12.4)', ADVANCE='no') &
     897         166 :                      mo(1)%occupation_numbers(i), mo(1)%eigenvalues(i)
     898             :                ELSE
     899           0 :                   WRITE (output_unit, '(A)', ADVANCE='no') '                        '
     900             :                END IF
     901         166 :                WRITE (output_unit, '(A)', ADVANCE='no') '     '
     902         181 :                IF (i <= mx_b) THEN
     903             :                   WRITE (output_unit, '(2F12.4)') &
     904         161 :                      mo(2)%occupation_numbers(i), mo(2)%eigenvalues(i)
     905             :                ELSE
     906           5 :                   WRITE (output_unit, *)
     907             :                END IF
     908             :             END DO
     909             : 
     910          15 :             IF (prnt_fm) THEN
     911             :                WRITE (output_unit, '(/,T3,I10,F24.4,I10,F19.4)') &
     912          15 :                   mo(1)%nelectron, mo(1)%mu, &
     913          30 :                   mo(2)%nelectron, mo(2)%mu
     914             :             END IF
     915             : 
     916             :             ! Spin-restricted calculation
     917             :          ELSE
     918             : 
     919           0 :             mx_a = mo(1)%nmo
     920           0 :             IF (PRESENT(mx_mo_a)) &
     921           0 :                mx_a = MIN(mo(1)%nmo, mx_mo_a)
     922             : 
     923           0 :             DO i = 1, mx_a
     924             :                WRITE (output_unit, '(T3,I10,2F12.4)') &
     925           0 :                   i, mo(1)%occupation_numbers(i), mo(1)%eigenvalues(i)
     926             :             END DO
     927             : 
     928           0 :             IF (prnt_fm) THEN
     929             :                WRITE (output_unit, '(/,T3,I10,F24.4)') &
     930           0 :                   mo(1)%nelectron, mo(1)%mu
     931             :             END IF
     932             : 
     933             :          END IF
     934             : 
     935             :       END IF
     936             : 
     937          20 :    END SUBROUTINE print_states
     938             : 
     939             : ! **************************************************************************************************
     940             : !> \brief Print out donor-acceptor state couplings
     941             : !> \param ec_sec ...
     942             : !> \param output_unit unit number of the open output stream
     943             : !> \param logger ...
     944             : !> \param ec electronic coupling data structure
     945             : !> \param mo ...
     946             : !> \author Z. Futera (02.2017)
     947             : ! **************************************************************************************************
     948          10 :    SUBROUTINE print_couplings(ec_sec, output_unit, logger, ec, mo)
     949             : 
     950             :       ! Routine arguments
     951             :       TYPE(section_vals_type), POINTER                   :: ec_sec
     952             :       INTEGER, INTENT(IN)                                :: output_unit
     953             :       TYPE(cp_logger_type), POINTER                      :: logger
     954             :       TYPE(et_cpl), POINTER                              :: ec
     955             :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo
     956             : 
     957             :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos, title
     958             :       INTEGER                                            :: i, j, k, l, n_states(2), nc, nr, nspins, &
     959             :                                                             unit_nr
     960             :       LOGICAL                                            :: append
     961          10 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: w1, w2
     962             :       TYPE(section_vals_type), POINTER                   :: print_key
     963             : 
     964             : ! Routine name for debug purposes
     965             : ! Local variables
     966             : 
     967          10 :       n_states = 0
     968          30 :       DO i = 1, SIZE(mo)
     969          30 :          n_states(i) = mo(i)%nmo
     970             :       END DO
     971          10 :       nspins = 1
     972          10 :       IF (n_states(2) > 0) nspins = 2
     973             : 
     974             :       print_key => section_vals_get_subs_vals(section_vals=ec_sec, &
     975          10 :                                               subsection_name="PRINT%COUPLINGS")
     976             : 
     977          10 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
     978             :                 cp_p_file)) THEN
     979             : 
     980          10 :          my_pos = "REWIND"
     981          10 :          append = section_get_lval(print_key, "APPEND")
     982          10 :          IF (append) THEN
     983           0 :             my_pos = "APPEND"
     984             :          END IF
     985             : 
     986          10 :          IF (output_unit > 0) &
     987           5 :             WRITE (output_unit, '(/,T3,A/)') 'Printing coupling elements to output files'
     988             : 
     989          30 :          DO i = 1, ec%n_blocks
     990          40 :             DO j = i + 1, ec%n_blocks
     991             : 
     992          10 :                nr = ec%block(i)%hab(1, j)%matrix_struct%nrow_global
     993          10 :                nc = ec%block(i)%hab(1, j)%matrix_struct%ncol_global
     994             : 
     995          40 :                ALLOCATE (w1(nr, nc))
     996          10 :                CPASSERT(ASSOCIATED(w1))
     997          10 :                CALL cp_fm_get_submatrix(ec%block(i)%hab(1, j), w1)
     998          10 :                IF (nspins > 1) THEN
     999          40 :                   ALLOCATE (w2(nr, nc))
    1000          10 :                   CPASSERT(ASSOCIATED(w2))
    1001          10 :                   CALL cp_fm_get_submatrix(ec%block(i)%hab(2, j), w2)
    1002             :                END IF
    1003             : 
    1004          10 :                IF (output_unit > 0) THEN
    1005             : 
    1006           5 :                   WRITE (filename, '(a5,I1.1,a1,I1.1)') "ET_BL_", i, "-", j
    1007             :                   unit_nr = cp_print_key_unit_nr(logger, ec_sec, "PRINT%COUPLINGS", extension=".elcoup", &
    1008           5 :                                                  middle_name=TRIM(filename), file_position=my_pos, log_filename=.FALSE.)
    1009             : 
    1010           5 :                   WRITE (title, *) 'Coupling elements [meV] between blocks:', i, j
    1011             : 
    1012           5 :                   WRITE (unit_nr, *) TRIM(title)
    1013           5 :                   IF (nspins > 1) THEN
    1014           5 :                      WRITE (unit_nr, '(T3,A8,T13,A8,T28,A,A)') 'State A', 'State B', 'Coupling spin 1', '  Coupling spin 2'
    1015             :                   ELSE
    1016           0 :                      WRITE (unit_nr, '(T3,A8,T13,A8,T28,A)') 'State A', 'State B', 'Coupling'
    1017             :                   END IF
    1018             : 
    1019          55 :                   DO k = 1, MIN(ec%block(i)%n_ao, n_states(1))
    1020         836 :                      DO l = 1, MIN(ec%block(j)%n_ao, n_states(1))
    1021             : 
    1022         836 :                         IF (nspins > 1) THEN
    1023             : 
    1024             :                            WRITE (unit_nr, '(T3,I5,T13,I5,T22,E20.6)', ADVANCE='no') &
    1025         786 :                               k, l, w1(k, l)*evolt*1000.0_dp
    1026         786 :                            IF ((k <= n_states(2)) .AND. (l <= n_states(2))) THEN
    1027             :                               WRITE (unit_nr, '(E20.6)') &
    1028         779 :                                  w2(k, l)*evolt*1000.0_dp
    1029             :                            ELSE
    1030           7 :                               WRITE (unit_nr, *)
    1031             :                            END IF
    1032             : 
    1033             :                         ELSE
    1034             : 
    1035             :                            WRITE (unit_nr, '(T3,I5,T13,I5,T22,E20.6)') &
    1036           0 :                               k, l, w1(k, l)*evolt*1000.0_dp
    1037             :                         END IF
    1038             : 
    1039             :                      END DO
    1040          55 :                      WRITE (unit_nr, *)
    1041             :                   END DO
    1042           5 :                   CALL cp_print_key_finished_output(unit_nr, logger, ec_sec, "PRINT%COUPLINGS")
    1043             : 
    1044             :                END IF
    1045             : 
    1046          10 :                IF (ASSOCIATED(w1)) DEALLOCATE (w1)
    1047          30 :                IF (ASSOCIATED(w2)) DEALLOCATE (w2)
    1048             : 
    1049             :             END DO
    1050             :          END DO
    1051             : 
    1052             :       END IF
    1053          10 :    END SUBROUTINE print_couplings
    1054             : 
    1055             : ! **************************************************************************************************
    1056             : !> \brief Normalize set of MO vectors
    1057             : !> \param qs_env QuickStep environment containing all system data
    1058             : !> \param mo storage for the MO data set
    1059             : !> \param n_ao number of AO basis functions
    1060             : !> \param n_mo number of block states
    1061             : !> \author Z. Futera (02.2017)
    1062             : ! **************************************************************************************************
    1063          40 :    SUBROUTINE normalize_mo_vectors(qs_env, mo, n_ao, n_mo)
    1064             : 
    1065             :       ! Routine arguments
    1066             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1067             :       TYPE(mo_set_type), POINTER                         :: mo
    1068             :       INTEGER, INTENT(IN)                                :: n_ao, n_mo
    1069             : 
    1070             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vec_t
    1071             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1072             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_s
    1073             :       TYPE(cp_fm_type)                                   :: mat_sc, mat_t
    1074          40 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_s
    1075             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1076             : 
    1077             : ! Routine name for debug purposes
    1078             : 
    1079             :       ! Initialization
    1080          40 :       NULLIFY (blacs_env)
    1081          40 :       NULLIFY (para_env)
    1082          40 :       NULLIFY (fm_s)
    1083          40 :       NULLIFY (mat_s)
    1084             :       NULLIFY (vec_t)
    1085             : 
    1086             :       ! Overlap matrix
    1087          40 :       CALL get_qs_env(qs_env, matrix_s=mat_s)
    1088             : 
    1089             :       ! Calculate S*C product
    1090             :       CALL cp_fm_create(matrix=mat_sc, matrix_struct=mo%mo_coeff%matrix_struct, &
    1091          40 :                         name='S*C PRODUCT MATRIX')
    1092          40 :       CALL cp_dbcsr_sm_fm_multiply(mat_s(1)%matrix, mo%mo_coeff, mat_sc, n_mo)
    1093             : 
    1094             :       ! Calculate C^T*S*C
    1095          40 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
    1096             :       CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
    1097          40 :                                nrow_global=n_mo, ncol_global=n_mo)
    1098             :       CALL cp_fm_create(matrix=mat_t, matrix_struct=fm_s, &
    1099          40 :                         name='C^T*S*C OVERLAP PRODUCT MATRIX')
    1100          40 :       CALL parallel_gemm('T', 'N', n_mo, n_mo, n_ao, 1.0_dp, mo%mo_coeff, mat_sc, 0.0_dp, mat_t)
    1101             : 
    1102             :       ! Normalization
    1103         120 :       ALLOCATE (vec_t(n_mo))
    1104          40 :       CPASSERT(ASSOCIATED(vec_t))
    1105          40 :       CALL cp_fm_vectorssum(mat_t, vec_t)
    1106         448 :       vec_t = 1.0_dp/DSQRT(vec_t)
    1107          40 :       CALL cp_fm_column_scale(mo%mo_coeff, vec_t)
    1108             : 
    1109             :       ! Clean memory
    1110          40 :       CALL cp_fm_struct_release(fmstruct=fm_s)
    1111          40 :       CALL cp_fm_release(matrix=mat_sc)
    1112          40 :       CALL cp_fm_release(matrix=mat_t)
    1113          40 :       IF (ASSOCIATED(vec_t)) &
    1114          40 :          DEALLOCATE (vec_t)
    1115             : 
    1116          40 :    END SUBROUTINE normalize_mo_vectors
    1117             : 
    1118             : ! **************************************************************************************************
    1119             : !> \brief Transform block MO coefficients to original non-orthogonal basis set and save them
    1120             : !> \param qs_env QuickStep environment containing all system data
    1121             : !> \param ec electronic coupling data structure
    1122             : !> \param id block ID
    1123             : !> \param mo storage for the MO data set
    1124             : !> \param mat_u matrix of the block states
    1125             : !> \param n_ao number of AO basis functions
    1126             : !> \param n_mo number of block states
    1127             : !> \author Z. Futera (02.2017)
    1128             : ! **************************************************************************************************
    1129          40 :    SUBROUTINE set_mo_coefficients(qs_env, ec, id, mo, mat_u, n_ao, n_mo)
    1130             : 
    1131             :       ! Routine arguments
    1132             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1133             :       TYPE(et_cpl), POINTER                              :: ec
    1134             :       INTEGER, INTENT(IN)                                :: id
    1135             :       TYPE(mo_set_type), POINTER                         :: mo
    1136             :       TYPE(cp_fm_type), INTENT(IN)                       :: mat_u
    1137             :       INTEGER, INTENT(IN)                                :: n_ao, n_mo
    1138             : 
    1139             :       INTEGER                                            :: ic, ir, jc, jr, mr, nc, nr
    1140             :       REAL(KIND=dp)                                      :: xu
    1141             :       TYPE(cp_fm_type)                                   :: mat_w
    1142             : 
    1143             : ! Routine name for debug purposes
    1144             : ! Local variables
    1145             : 
    1146             :       ! Working matrix
    1147             :       CALL cp_fm_create(matrix=mat_w, matrix_struct=mo%mo_coeff%matrix_struct, &
    1148          40 :                         name='BLOCK MO-TRANSFORMATION WORKING MATRIX')
    1149          40 :       CALL cp_fm_set_all(mat_w, 0.0_dp)
    1150             : 
    1151             :       ! Matrix-element reordering
    1152          40 :       nr = 1
    1153             :       ! Rows
    1154         184 :       DO ir = 1, ec%block(id)%n_atoms
    1155         592 :          DO jr = 1, ec%block(id)%atom(ir)%n_ao
    1156             :             ! Columns
    1157         408 :             nc = 1
    1158        2832 :             DO ic = 1, ec%block(id)%n_atoms
    1159        9192 :                DO jc = 1, ec%block(id)%atom(ic)%n_ao
    1160        6360 :                   mr = ec%block(id)%atom(ir)%ao_pos + jr - 1
    1161        6360 :                   CALL cp_fm_get_element(mat_u, nr, nc, xu)
    1162        6360 :                   CALL cp_fm_set_element(mat_w, mr, nc, xu)
    1163       15144 :                   nc = nc + 1
    1164             :                END DO
    1165             :             END DO
    1166         552 :             nr = nr + 1
    1167             :          END DO
    1168             :       END DO
    1169             : 
    1170             :       ! Transformation to original non-orthogonal basis set
    1171          40 :       CALL parallel_gemm("N", "N", n_ao, n_mo, n_ao, 1.0_dp, ec%m_transf, mat_w, 0.0_dp, mo%mo_coeff)
    1172          40 :       CALL normalize_mo_vectors(qs_env, mo, n_ao, n_mo)
    1173             : 
    1174             :       ! Clean memory
    1175          40 :       CALL cp_fm_release(matrix=mat_w)
    1176             : 
    1177          40 :    END SUBROUTINE set_mo_coefficients
    1178             : 
    1179             : ! **************************************************************************************************
    1180             : !> \brief Creates MO set corresponding to one atomic data block
    1181             : !> \param qs_env QuickStep environment containing all system data
    1182             : !> \param ec electronic coupling data structure
    1183             : !> \param id block ID
    1184             : !> \param spin spin component
    1185             : !> \param mat_u matrix of the block states
    1186             : !> \param vec_e array of the block eigenvalues
    1187             : !> \author Z. Futera (02.2017)
    1188             : ! **************************************************************************************************
    1189          40 :    SUBROUTINE create_block_mo_set(qs_env, ec, id, spin, mat_u, vec_e)
    1190             : 
    1191             :       ! Routine arguments
    1192             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1193             :       TYPE(et_cpl), POINTER                              :: ec
    1194             :       INTEGER, INTENT(IN)                                :: id, spin
    1195             :       TYPE(cp_fm_type), INTENT(IN)                       :: mat_u
    1196             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vec_e
    1197             : 
    1198             :       INTEGER                                            :: n_ao, n_el, n_mo
    1199             :       REAL(KIND=dp)                                      :: mx_occ
    1200             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1201             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_s
    1202             :       TYPE(dft_control_type), POINTER                    :: dft_cntrl
    1203             :       TYPE(mo_set_type), POINTER                         :: mo
    1204             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1205          40 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1206             :       TYPE(scf_control_type), POINTER                    :: scf_cntrl
    1207             : 
    1208             : ! Routine name for debug purposes
    1209             : 
    1210          40 :       NULLIFY (blacs_env)
    1211          40 :       NULLIFY (dft_cntrl)
    1212          40 :       NULLIFY (para_env)
    1213          40 :       NULLIFY (qs_kind_set)
    1214          40 :       NULLIFY (fm_s)
    1215          40 :       NULLIFY (scf_cntrl)
    1216          40 :       NULLIFY (mo)
    1217             : 
    1218             :       ! Number of basis functions
    1219          40 :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
    1220          40 :       CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
    1221             : 
    1222             :       ! Number of states
    1223          40 :       n_mo = mat_u%matrix_struct%nrow_global
    1224          40 :       IF (n_mo /= mat_u%matrix_struct%ncol_global) &
    1225           0 :          CPABORT('block state matrix is not square')
    1226          40 :       IF (n_mo /= SIZE(vec_e)) &
    1227           0 :          CPABORT('inconsistent number of states / energies')
    1228             : 
    1229             :       ! Maximal occupancy
    1230          40 :       CALL get_qs_env(qs_env, dft_control=dft_cntrl)
    1231          40 :       mx_occ = 2.0_dp
    1232          40 :       IF (dft_cntrl%nspins > 1) &
    1233          40 :          mx_occ = 1.0_dp
    1234             : 
    1235             :       ! Number of electrons
    1236          40 :       n_el = ec%block(id)%n_electrons
    1237          40 :       IF (dft_cntrl%nspins > 1) THEN
    1238          40 :          n_el = n_el/2
    1239          40 :          IF (MOD(ec%block(id)%n_electrons, 2) == 1) THEN
    1240          28 :             IF (spin == 1) &
    1241          14 :                n_el = n_el + 1
    1242             :          END IF
    1243             :       END IF
    1244             : 
    1245             :       ! Memory allocation (Use deallocate_mo_set to prevent accidental memory leaks)
    1246          40 :       CALL deallocate_mo_set(ec%block(id)%mo(spin))
    1247          40 :       CALL allocate_mo_set(ec%block(id)%mo(spin), n_ao, n_mo, n_el, REAL(n_el, dp), mx_occ, 0.0_dp)
    1248          40 :       mo => ec%block(id)%mo(spin)
    1249             : 
    1250             :       ! State energies
    1251         120 :       ALLOCATE (mo%eigenvalues(n_mo))
    1252          40 :       CPASSERT(ASSOCIATED(mo%eigenvalues))
    1253         896 :       mo%eigenvalues = vec_e
    1254             : 
    1255             :       ! States coefficients
    1256          40 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
    1257             :       CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
    1258          40 :                                nrow_global=n_ao, ncol_global=n_mo)
    1259          40 :       ALLOCATE (mo%mo_coeff)
    1260          40 :       CALL cp_fm_create(matrix=mo%mo_coeff, matrix_struct=fm_s, name='BLOCK STATES')
    1261             : 
    1262             :       ! Transform MO coefficients to original non-orthogonal basis set
    1263          40 :       CALL set_mo_coefficients(qs_env, ec, id, mo, mat_u, n_ao, n_mo)
    1264             : 
    1265             :       ! Occupancies
    1266         120 :       ALLOCATE (mo%occupation_numbers(n_mo))
    1267          40 :       CPASSERT(ASSOCIATED(mo%occupation_numbers))
    1268         448 :       mo%occupation_numbers = 0.0_dp
    1269             : 
    1270          40 :       IF (n_el > 0) THEN
    1271          28 :          CALL get_qs_env(qs_env, scf_control=scf_cntrl)
    1272          28 :          CALL set_mo_occupation(mo_set=mo, smear=scf_cntrl%smear)
    1273             :       END IF
    1274             : 
    1275             :       ! Clean memory
    1276          40 :       CALL cp_fm_struct_release(fmstruct=fm_s)
    1277             : 
    1278          40 :    END SUBROUTINE create_block_mo_set
    1279             : 
    1280             : ! **************************************************************************************************
    1281             : !> \brief save given electronic state to cube files
    1282             : !> \param qs_env QuickStep environment containing all system data
    1283             : !> \param logger output logger
    1284             : !> \param input input-file block print setting section
    1285             : !> \param mo electronic states data
    1286             : !> \param ib block ID
    1287             : !> \param im state ID
    1288             : !> \param is spin ID
    1289             : !> \author Z. Futera (02.2017)
    1290             : ! **************************************************************************************************
    1291           0 :    SUBROUTINE save_mo_cube(qs_env, logger, input, mo, ib, im, is)
    1292             : 
    1293             :       ! Routine arguments
    1294             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1295             :       TYPE(cp_logger_type), POINTER                      :: logger
    1296             :       TYPE(section_vals_type), POINTER                   :: input
    1297             :       TYPE(mo_set_type), POINTER                         :: mo
    1298             :       INTEGER, INTENT(IN)                                :: ib, im, is
    1299             : 
    1300             :       CHARACTER(LEN=default_path_length)                 :: filename
    1301             :       CHARACTER(LEN=default_string_length)               :: title
    1302             :       INTEGER                                            :: unit_nr
    1303           0 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1304             :       TYPE(cell_type), POINTER                           :: cell
    1305             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1306             :       TYPE(particle_list_type), POINTER                  :: particles
    1307           0 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1308             :       TYPE(pw_c1d_gs_type)                               :: wf_g
    1309             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1310           0 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1311             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1312             :       TYPE(pw_r3d_rs_type)                               :: wf_r
    1313           0 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1314             :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1315             : 
    1316             : ! Routine name for debug purposes
    1317             : 
    1318             :       ! Initialization
    1319           0 :       NULLIFY (particles)
    1320           0 :       NULLIFY (subsys)
    1321             : 
    1322           0 :       NULLIFY (pw_env)
    1323           0 :       NULLIFY (pw_pools)
    1324           0 :       NULLIFY (auxbas_pw_pool)
    1325             : 
    1326           0 :       NULLIFY (atomic_kind_set)
    1327           0 :       NULLIFY (cell)
    1328           0 :       NULLIFY (dft_control)
    1329           0 :       NULLIFY (particle_set)
    1330           0 :       NULLIFY (qs_kind_set)
    1331             : 
    1332             :       ! Name of the cube file
    1333           0 :       WRITE (filename, '(A4,I1.1,A1,I5.5,A1,I1.1)') 'BWF_', ib, '_', im, '_', is
    1334             :       ! Open the file
    1335             :       unit_nr = cp_print_key_unit_nr(logger, input, 'MO_CUBES', extension='.cube', &
    1336           0 :                                      middle_name=TRIM(filename), file_position='REWIND', log_filename=.FALSE.)
    1337             :       ! Title of the file
    1338           0 :       WRITE (title, *) 'WAVEFUNCTION ', im, ' block ', ib, ' spin ', is
    1339             : 
    1340             :       ! List of all atoms
    1341           0 :       CALL get_qs_env(qs_env, subsys=subsys)
    1342           0 :       CALL qs_subsys_get(subsys, particles=particles)
    1343             : 
    1344             :       ! Grids for wavefunction
    1345           0 :       CALL get_qs_env(qs_env, pw_env=pw_env)
    1346           0 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
    1347           0 :       CALL auxbas_pw_pool%create_pw(wf_r)
    1348           0 :       CALL auxbas_pw_pool%create_pw(wf_g)
    1349             : 
    1350             :       ! Calculate the grid values
    1351             :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
    1352           0 :                       cell=cell, dft_control=dft_control, particle_set=particle_set)
    1353             :       CALL calculate_wavefunction(mo%mo_coeff, im, wf_r, wf_g, atomic_kind_set, &
    1354           0 :                                   qs_kind_set, cell, dft_control, particle_set, pw_env)
    1355             :       CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, &
    1356           0 :                          stride=section_get_ivals(input, 'MO_CUBES%STRIDE'))
    1357             : 
    1358             :       ! Close file
    1359           0 :       CALL cp_print_key_finished_output(unit_nr, logger, input, 'MO_CUBES')
    1360             : 
    1361             :       ! Clean memory
    1362           0 :       CALL auxbas_pw_pool%give_back_pw(wf_r)
    1363           0 :       CALL auxbas_pw_pool%give_back_pw(wf_g)
    1364             : 
    1365           0 :    END SUBROUTINE save_mo_cube
    1366             : 
    1367             : ! **************************************************************************************************
    1368             : !> \brief save specified electronic states to cube files
    1369             : !> \param qs_env QuickStep environment containing all system data
    1370             : !> \param ec electronic coupling data structure
    1371             : !> \param n_spins number of spin states
    1372             : !> \author Z. Futera (02.2017)
    1373             : ! **************************************************************************************************
    1374          10 :    SUBROUTINE save_el_states(qs_env, ec, n_spins)
    1375             : 
    1376             :       ! Routine arguments
    1377             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1378             :       TYPE(et_cpl), POINTER                              :: ec
    1379             :       INTEGER, INTENT(IN)                                :: n_spins
    1380             : 
    1381             :       INTEGER                                            :: i, j, k, l, n
    1382          10 :       INTEGER, DIMENSION(:), POINTER                     :: list
    1383             :       TYPE(cp_logger_type), POINTER                      :: logger
    1384             :       TYPE(mo_set_type), POINTER                         :: mo
    1385             :       TYPE(section_vals_type), POINTER                   :: block_sec, mo_sec, print_sec
    1386             : 
    1387             : ! Routine name for debug purposes
    1388             : 
    1389          10 :       NULLIFY (logger)
    1390          10 :       NULLIFY (block_sec)
    1391          10 :       NULLIFY (print_sec)
    1392          10 :       NULLIFY (mo_sec)
    1393             : 
    1394             :       ! Output logger
    1395          20 :       logger => cp_get_default_logger()
    1396             :       block_sec => section_vals_get_subs_vals(qs_env%input, &
    1397          10 :                                               'PROPERTIES%ET_COUPLING%PROJECTION%BLOCK')
    1398             : 
    1399             :       ! Print states of all blocks
    1400          30 :       DO i = 1, ec%n_blocks
    1401             : 
    1402          20 :          print_sec => section_vals_get_subs_vals(block_sec, 'PRINT', i_rep_section=i)
    1403             : 
    1404             :          ! Check if the print input section is active
    1405          20 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    1406          10 :                                               print_sec, 'MO_CUBES'), cp_p_file)) THEN
    1407             : 
    1408           0 :             mo_sec => section_vals_get_subs_vals(print_sec, 'MO_CUBES')
    1409             : 
    1410             :             ! Spin states
    1411           0 :             DO j = 1, n_spins
    1412             : 
    1413           0 :                mo => ec%block(i)%mo(j)
    1414             : 
    1415           0 :                CALL section_vals_val_get(mo_sec, keyword_name='MO_LIST', n_rep_val=n)
    1416             : 
    1417             :                ! List of specific MOs
    1418           0 :                IF (n > 0) THEN
    1419             : 
    1420           0 :                   DO k = 1, n
    1421           0 :                      NULLIFY (list)
    1422             :                      CALL section_vals_val_get(mo_sec, keyword_name='MO_LIST', &
    1423           0 :                                                i_rep_val=k, i_vals=list)
    1424           0 :                      IF (ASSOCIATED(list)) THEN
    1425           0 :                         DO l = 1, SIZE(list)
    1426           0 :                            CALL save_mo_cube(qs_env, logger, print_sec, mo, i, list(l), j)
    1427             :                         END DO
    1428             :                      END IF
    1429             :                   END DO
    1430             : 
    1431             :                   ! Frontier MOs
    1432             :                ELSE
    1433             : 
    1434             :                   ! Occupied states
    1435           0 :                   CALL section_vals_val_get(mo_sec, keyword_name='NHOMO', i_val=n)
    1436             : 
    1437           0 :                   IF (n > 0) THEN
    1438           0 :                      DO k = MAX(1, mo%homo - n + 1), mo%homo
    1439           0 :                         CALL save_mo_cube(qs_env, logger, print_sec, mo, i, k, j)
    1440             :                      END DO
    1441             :                   END IF
    1442             : 
    1443             :                   ! Unoccupied states
    1444           0 :                   CALL section_vals_val_get(mo_sec, keyword_name='NLUMO', i_val=n)
    1445             : 
    1446           0 :                   IF (n > 0) THEN
    1447           0 :                      DO k = mo%lfomo, MIN(mo%lfomo + n - 1, mo%nmo)
    1448           0 :                         CALL save_mo_cube(qs_env, logger, print_sec, mo, i, k, j)
    1449             :                      END DO
    1450             :                   END IF
    1451             : 
    1452             :                END IF
    1453             : 
    1454             :             END DO
    1455             : 
    1456             :          END IF
    1457             : 
    1458             :       END DO
    1459             : 
    1460          10 :    END SUBROUTINE save_el_states
    1461             : 
    1462             : ! **************************************************************************************************
    1463             : !> \brief calculates the electron transfer coupling elements by projection-operator approach
    1464             : !>        Kondov et al. J.Phys.Chem.C 2007, 111, 11970-11981
    1465             : !> \param qs_env QuickStep environment containing all system data
    1466             : !> \author Z. Futera (02.2017)
    1467             : ! **************************************************************************************************
    1468          10 :    SUBROUTINE calc_et_coupling_proj(qs_env)
    1469             : 
    1470             :       ! Routine arguments
    1471             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1472             : 
    1473             :       INTEGER                                            :: i, j, k, n_ao, n_atoms, output_unit
    1474             :       LOGICAL                                            :: do_kp, master
    1475             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1476             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_s
    1477             :       TYPE(cp_fm_type)                                   :: mat_w
    1478          10 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mat_h
    1479             :       TYPE(cp_logger_type), POINTER                      :: logger
    1480          10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks, mo_der
    1481             :       TYPE(dft_control_type), POINTER                    :: dft_cntrl
    1482             :       TYPE(et_cpl), POINTER                              :: ec
    1483             :       TYPE(kpoint_type), POINTER                         :: kpoints
    1484          10 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo
    1485             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1486          10 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1487             :       TYPE(scf_control_type), POINTER                    :: scf_control
    1488             :       TYPE(section_vals_type), POINTER                   :: et_proj_sec
    1489             : 
    1490             : ! Routine name for debug purposes
    1491             : 
    1492             :       ! Pointer initialization
    1493          10 :       NULLIFY (logger)
    1494             : 
    1495          10 :       NULLIFY (blacs_env)
    1496          10 :       NULLIFY (para_env)
    1497          10 :       NULLIFY (dft_cntrl)
    1498          10 :       NULLIFY (kpoints)
    1499          10 :       NULLIFY (qs_kind_set)
    1500             :       NULLIFY (et_proj_sec)
    1501             : 
    1502          10 :       NULLIFY (fm_s)
    1503          10 :       NULLIFY (ks, mo_der)
    1504             : 
    1505          10 :       NULLIFY (ec)
    1506             : 
    1507             :       ! Reference
    1508          10 :       CALL cite_reference(Futera2017)
    1509             : 
    1510             :       ! Stream for output to LOG file
    1511          10 :       logger => cp_get_default_logger()
    1512             : 
    1513          10 :       et_proj_sec => section_vals_get_subs_vals(qs_env%input, 'PROPERTIES%ET_COUPLING%PROJECTION')
    1514             : 
    1515             :       output_unit = cp_print_key_unit_nr(logger, et_proj_sec, &
    1516          10 :                                          'PROGRAM_RUN_INFO', extension='.log')
    1517             : 
    1518             :       ! Parallel calculation - master thread
    1519          10 :       master = .FALSE.
    1520          10 :       IF (output_unit > 0) &
    1521             :          master = .TRUE.
    1522             : 
    1523             :       ! Header
    1524             :       IF (master) THEN
    1525             :          WRITE (output_unit, '(/,T2,A)') &
    1526           5 :             '!-----------------------------------------------------------------------------!'
    1527             :          WRITE (output_unit, '(T17,A)') &
    1528           5 :             'Electronic coupling - Projection-operator method'
    1529             :       END IF
    1530             : 
    1531             :       ! Main data structure
    1532          10 :       ALLOCATE (ec)
    1533          10 :       CPASSERT(ASSOCIATED(ec))
    1534          10 :       CALL set_block_data(qs_env, et_proj_sec, ec)
    1535             : 
    1536             :       ! Number of atoms and AO functions
    1537          10 :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, natom=n_atoms)
    1538          10 :       CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
    1539             : 
    1540             :       ! Print out info about system partitioning
    1541          10 :       IF (master) THEN
    1542             : 
    1543             :          WRITE (output_unit, '(/,T3,A,I10)') &
    1544           5 :             'Number of atoms                    = ', n_atoms
    1545             :          WRITE (output_unit, '(T3,A,I10)') &
    1546           5 :             'Number of fragments                = ', ec%n_blocks
    1547             :          WRITE (output_unit, '(T3,A,I10)') &
    1548           5 :             'Number of fragment atoms           = ', ec%n_atoms
    1549             :          WRITE (output_unit, '(T3,A,I10)') &
    1550           5 :             'Number of unassigned atoms         = ', n_atoms - ec%n_atoms
    1551             :          WRITE (output_unit, '(T3,A,I10)') &
    1552           5 :             'Number of AO basis functions       = ', n_ao
    1553             : 
    1554          15 :          DO i = 1, ec%n_blocks
    1555             : 
    1556             :             WRITE (output_unit, '(/,T3,A,I0,A)') &
    1557          10 :                'Block ', i, ':'
    1558             :             WRITE (output_unit, '(T3,A,I10)') &
    1559          10 :                'Number of block atoms              = ', ec%block(i)%n_atoms
    1560             :             WRITE (output_unit, '(T3,A,I10)') &
    1561          10 :                'Number of block electrons          = ', ec%block(i)%n_electrons
    1562             :             WRITE (output_unit, '(T3,A,I10)') &
    1563          10 :                'Number of block AO functions       = ', ec%block(i)%n_ao
    1564             : 
    1565          15 :             IF (ec%block(i)%n_atoms < 10) THEN
    1566             : 
    1567             :                WRITE (output_unit, '(T3,A,10I6)') &
    1568          10 :                   'Block atom IDs                     =     ', &
    1569          56 :                   (ec%block(i)%atom(j)%id, j=1, ec%block(i)%n_atoms)
    1570             : 
    1571             :             ELSE
    1572             : 
    1573           0 :                WRITE (output_unit, '(T3,A)') 'Block atom IDs                     ='
    1574           0 :                DO j = 1, ec%block(i)%n_atoms/10
    1575           0 :                   WRITE (output_unit, '(T3,A,10I6)') '      ', &
    1576           0 :                      (ec%block(i)%atom((j - 1)*10 + k)%id, k=1, 10)
    1577             :                END DO
    1578           0 :                IF (MOD(ec%block(i)%n_atoms, 10) /= 0) THEN
    1579           0 :                   WRITE (output_unit, '(T3,A,10I6)') '      ', &
    1580           0 :                      (ec%block(i)%atom(k + 10*(ec%block(i)%n_atoms/10))%id, &
    1581           0 :                       k=1, MOD(ec%block(i)%n_atoms, 10))
    1582             :                END IF
    1583             : 
    1584             :             END IF
    1585             : 
    1586             :          END DO
    1587             : 
    1588             :       END IF
    1589             : 
    1590             :       ! Full matrix data structure
    1591          10 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
    1592             :       CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
    1593          10 :                                nrow_global=n_ao, ncol_global=n_ao)
    1594          10 :       CALL cp_fm_create(matrix=mat_w, matrix_struct=fm_s, name='FULL WORK MATRIX')
    1595             : 
    1596             :       ! Spin polarization / K-point sampling
    1597          10 :       CALL get_qs_env(qs_env, dft_control=dft_cntrl, do_kpoints=do_kp)
    1598          10 :       CALL get_qs_env(qs_env, mos=mo, matrix_ks=ks, mo_derivs=mo_der, scf_control=scf_control)
    1599          10 :       CALL make_mo_eig(mo, dft_cntrl%nspins, ks, scf_control, mo_der)
    1600             : 
    1601          10 :       IF (do_kp) THEN
    1602           0 :          CPABORT('ET_COUPLING not implemented with kpoints')
    1603             :       ELSE
    1604             :          !  no K-points
    1605          10 :          IF (master) &
    1606           5 :             WRITE (output_unit, '(T3,A)') 'No K-point sampling (Gamma point only)'
    1607             :       END IF
    1608             : 
    1609          10 :       IF (dft_cntrl%nspins == 2) THEN
    1610             : 
    1611          10 :          IF (master) &
    1612           5 :             WRITE (output_unit, '(/,T3,A)') 'Spin-polarized calculation'
    1613             : 
    1614             :          !<--- Open shell / No K-points ------------------------------------------------>!
    1615             : 
    1616             :          ! State eneries of the whole system
    1617          10 :          IF (mo(1)%nao /= mo(2)%nao) &
    1618           0 :             CPABORT('different number of alpha/beta AO basis functions')
    1619          10 :          IF (master) THEN
    1620             :             WRITE (output_unit, '(/,T3,A,I10)') &
    1621           5 :                'Number of AO basis functions       = ', mo(1)%nao
    1622             :             WRITE (output_unit, '(T3,A,I10)') &
    1623           5 :                'Number of alpha states             = ', mo(1)%nmo
    1624             :             WRITE (output_unit, '(T3,A,I10)') &
    1625           5 :                'Number of beta states              = ', mo(2)%nmo
    1626             :          END IF
    1627          10 :          CALL print_states(output_unit, mo, dft_cntrl%nspins, 'the whole system', fermi=.TRUE.)
    1628          10 :          CALL set_fermi(ec, mo(1)%mu, mo(2)%mu)
    1629             : 
    1630             :          ! KS Hamiltonian
    1631          10 :          CALL get_block_hamiltonian(qs_env, ec, fm_s, mat_h, mat_w, n_ao, dft_cntrl%nspins)
    1632             : 
    1633             :          ! Block diagonization
    1634          10 :          CALL hamiltonian_block_diag(qs_env, ec, mat_h)
    1635             : 
    1636             :          ! Print out energies and couplings
    1637          30 :          DO i = 1, ec%n_blocks
    1638          20 :             IF (output_unit > 0) THEN
    1639             :                CALL print_states(output_unit, ec%block(i)%mo, dft_cntrl%nspins, &
    1640             :                                  'block '//TRIM(ADJUSTL(cp_to_string(i)))//' states', &
    1641          10 :                                  mx_mo_a=mo(1)%nmo, mx_mo_b=mo(2)%nmo, fermi=.TRUE.)
    1642             :             END IF
    1643          30 :             CALL print_mo_coeff(output_unit, qs_env, ec, i, dft_cntrl%nspins)
    1644             :          END DO
    1645             : 
    1646          10 :          CALL print_couplings(et_proj_sec, output_unit, logger, ec, mo)
    1647             : 
    1648             :       ELSE
    1649             : 
    1650           0 :          IF (master) &
    1651           0 :             WRITE (output_unit, '(/,T3,A)') 'Spin-restricted calculation'
    1652             : 
    1653             :          !<--- Close shell / No K-points ----------------------------------------------->!
    1654             : 
    1655             :          ! State eneries of the whole system
    1656           0 :          IF (master) THEN
    1657             :             WRITE (output_unit, '(/,T3,A,I10)') &
    1658           0 :                'Number of AO basis functions       = ', mo(1)%nao
    1659             :             WRITE (output_unit, '(T3,A,I10)') &
    1660           0 :                'Number of states                   = ', mo(1)%nmo
    1661             :          END IF
    1662           0 :          CALL print_states(output_unit, mo, dft_cntrl%nspins, 'the whole system', fermi=.TRUE.)
    1663           0 :          CALL set_fermi(ec, mo(1)%mu)
    1664             : 
    1665             :          ! KS Hamiltonian
    1666           0 :          CALL get_block_hamiltonian(qs_env, ec, fm_s, mat_h, mat_w, n_ao, dft_cntrl%nspins)
    1667             : 
    1668             :          ! Block diagonization
    1669           0 :          CALL hamiltonian_block_diag(qs_env, ec, mat_h)
    1670             : 
    1671             :          ! Print out energies and couplings
    1672           0 :          DO i = 1, ec%n_blocks
    1673           0 :             IF (output_unit > 0) THEN
    1674             :                CALL print_states(output_unit, ec%block(i)%mo, dft_cntrl%nspins, &
    1675             :                                  'block '//TRIM(ADJUSTL(cp_to_string(i)))//' states', &
    1676           0 :                                  mx_mo_a=mo(1)%nmo, fermi=.TRUE.)
    1677             :             END IF
    1678           0 :             CALL print_mo_coeff(output_unit, qs_env, ec, i, dft_cntrl%nspins)
    1679             :          END DO
    1680             : 
    1681           0 :          CALL print_couplings(et_proj_sec, output_unit, logger, ec, mo)
    1682             : 
    1683             :       END IF
    1684             : 
    1685             :       ! Save electronic states
    1686          10 :       CALL save_el_states(qs_env, ec, dft_cntrl%nspins)
    1687             : 
    1688             :       ! Footer
    1689          10 :       IF (master) WRITE (output_unit, '(/,T2,A)') &
    1690           5 :          '!-----------------------------------------------------------------------------!'
    1691             : 
    1692             :       ! Clean memory
    1693          10 :       CALL cp_fm_struct_release(fmstruct=fm_s)
    1694          10 :       CALL cp_fm_release(matrix=mat_w)
    1695          10 :       IF (ALLOCATED(mat_h)) THEN
    1696          30 :          DO i = 1, SIZE(mat_h)
    1697          30 :             CALL cp_fm_release(matrix=mat_h(i))
    1698             :          END DO
    1699          10 :          DEALLOCATE (mat_h)
    1700             :       END IF
    1701          10 :       CALL release_ec_data(ec)
    1702             : 
    1703             :       ! Close output stream
    1704          10 :       CALL cp_print_key_finished_output(output_unit, logger, et_proj_sec, 'PROGRAM_RUN_INFO')
    1705             : 
    1706          20 :    END SUBROUTINE calc_et_coupling_proj
    1707             : 
    1708           0 : END MODULE et_coupling_proj

Generated by: LCOV version 1.15