LCOV - code coverage report
Current view: top level - src - qs_loc_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:06f838d) Lines: 91.8 % 785 721
Test Date: 2026-06-05 07:04:50 Functions: 100.0 % 12 12

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Some utilities for the construction of
      10              : !>      the localization environment
      11              : !> \author MI (05-2005)
      12              : ! **************************************************************************************************
      13              : MODULE qs_loc_utils
      14              : 
      15              :    USE ai_moments,                      ONLY: contract_cossin,&
      16              :                                               cossin
      17              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      18              :                                               gto_basis_set_type
      19              :    USE block_p_types,                   ONLY: block_p_type
      20              :    USE cell_types,                      ONLY: cell_type,&
      21              :                                               pbc
      22              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      25              :                                               dbcsr_get_block_p,&
      26              :                                               dbcsr_p_type,&
      27              :                                               dbcsr_set,&
      28              :                                               dbcsr_type
      29              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply
      30              :    USE cp_files,                        ONLY: close_file,&
      31              :                                               open_file
      32              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      33              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      34              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      35              :                                               cp_fm_struct_release,&
      36              :                                               cp_fm_struct_type
      37              :    USE cp_fm_types,                     ONLY: &
      38              :         cp_fm_create, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, cp_fm_set_all, &
      39              :         cp_fm_set_submatrix, cp_fm_to_fm, cp_fm_type, cp_fm_write_unformatted
      40              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      41              :                                               cp_logger_get_default_io_unit,&
      42              :                                               cp_logger_type,&
      43              :                                               cp_to_string
      44              :    USE cp_output_handling,              ONLY: cp_p_file,&
      45              :                                               cp_print_key_finished_output,&
      46              :                                               cp_print_key_generate_filename,&
      47              :                                               cp_print_key_should_output,&
      48              :                                               cp_print_key_unit_nr
      49              :    USE distribution_1d_types,           ONLY: distribution_1d_type
      50              :    USE input_constants,                 ONLY: &
      51              :         do_loc_crazy, do_loc_direct, do_loc_gapo, do_loc_jacobi, do_loc_l1_norm_sd, do_loc_none, &
      52              :         do_loc_scdm, energy_loc_range, op_loc_berry, op_loc_boys, op_loc_pipek, state_loc_all, &
      53              :         state_loc_list, state_loc_mixed, state_loc_none, state_loc_range
      54              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      55              :                                               section_vals_type,&
      56              :                                               section_vals_val_get
      57              :    USE kinds,                           ONLY: default_path_length,&
      58              :                                               default_string_length,&
      59              :                                               dp
      60              :    USE mathconstants,                   ONLY: twopi
      61              :    USE memory_utilities,                ONLY: reallocate
      62              :    USE message_passing,                 ONLY: mp_para_env_type
      63              :    USE orbital_pointers,                ONLY: ncoset
      64              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      65              :    USE particle_types,                  ONLY: particle_type
      66              :    USE qs_environment_types,            ONLY: get_qs_env,&
      67              :                                               qs_environment_type
      68              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      69              :                                               get_qs_kind_set,&
      70              :                                               qs_kind_type
      71              :    USE qs_loc_types,                    ONLY: get_qs_loc_env,&
      72              :                                               localized_wfn_control_create,&
      73              :                                               localized_wfn_control_release,&
      74              :                                               localized_wfn_control_type,&
      75              :                                               qs_loc_env_type,&
      76              :                                               set_qs_loc_env
      77              :    USE qs_localization_methods,         ONLY: initialize_weights
      78              :    USE qs_mo_methods,                   ONLY: make_mo_eig
      79              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      80              :                                               mo_set_type
      81              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      82              :                                               neighbor_list_iterate,&
      83              :                                               neighbor_list_iterator_create,&
      84              :                                               neighbor_list_iterator_p_type,&
      85              :                                               neighbor_list_iterator_release,&
      86              :                                               neighbor_list_set_p_type
      87              :    USE qs_scf_types,                    ONLY: ot_method_nr
      88              :    USE scf_control_types,               ONLY: scf_control_type
      89              : #include "./base/base_uses.f90"
      90              : 
      91              :    IMPLICIT NONE
      92              : 
      93              :    PRIVATE
      94              : 
      95              : ! *** Global parameters ***
      96              : 
      97              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_loc_utils'
      98              : 
      99              : ! *** Public ***
     100              :    PUBLIC :: qs_loc_env_init, loc_write_restart, &
     101              :              retain_history, qs_loc_init, compute_berry_operator, &
     102              :              set_loc_centers, set_loc_wfn_lists, qs_loc_control_init
     103              : 
     104              : CONTAINS
     105              : 
     106              : ! **************************************************************************************************
     107              : !> \brief copy old mos to new ones, allocating as necessary
     108              : !> \param mo_loc_history ...
     109              : !> \param mo_loc ...
     110              : ! **************************************************************************************************
     111           10 :    SUBROUTINE retain_history(mo_loc_history, mo_loc)
     112              : 
     113              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mo_loc_history
     114              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_loc
     115              : 
     116              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'retain_history'
     117              : 
     118              :       INTEGER                                            :: handle, i, ncol_hist, ncol_loc
     119              : 
     120           10 :       CALL timeset(routineN, handle)
     121              : 
     122           10 :       IF (.NOT. ASSOCIATED(mo_loc_history)) THEN
     123            8 :          ALLOCATE (mo_loc_history(SIZE(mo_loc)))
     124            4 :          DO i = 1, SIZE(mo_loc_history)
     125            4 :             CALL cp_fm_create(mo_loc_history(i), mo_loc(i)%matrix_struct)
     126              :          END DO
     127              :       END IF
     128              : 
     129           20 :       DO i = 1, SIZE(mo_loc_history)
     130           10 :          CALL cp_fm_get_info(mo_loc_history(i), ncol_global=ncol_hist)
     131           10 :          CALL cp_fm_get_info(mo_loc(i), ncol_global=ncol_loc)
     132           10 :          CPASSERT(ncol_hist == ncol_loc)
     133           30 :          CALL cp_fm_to_fm(mo_loc(i), mo_loc_history(i))
     134              :       END DO
     135              : 
     136           10 :       CALL timestop(handle)
     137              : 
     138           10 :    END SUBROUTINE retain_history
     139              : 
     140              : ! **************************************************************************************************
     141              : !> \brief rotate the mo_new, so that the orbitals are as similar
     142              : !>        as possible to ones in mo_ref.
     143              : !> \param mo_new ...
     144              : !> \param mo_ref ...
     145              : !> \param matrix_S ...
     146              : ! **************************************************************************************************
     147            8 :    SUBROUTINE rotate_state_to_ref(mo_new, mo_ref, matrix_S)
     148              : 
     149              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_new, mo_ref
     150              :       TYPE(dbcsr_type), POINTER                          :: matrix_S
     151              : 
     152              :       CHARACTER(len=*), PARAMETER :: routineN = 'rotate_state_to_ref'
     153              : 
     154              :       INTEGER                                            :: handle, ncol, ncol_ref, nrow
     155              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
     156              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     157              :       TYPE(cp_fm_type)                                   :: o1, o2, o3, o4, smo
     158              : 
     159            8 :       CALL timeset(routineN, handle)
     160              : 
     161            8 :       CALL cp_fm_get_info(mo_new, nrow_global=nrow, ncol_global=ncol)
     162            8 :       CALL cp_fm_get_info(mo_ref, ncol_global=ncol_ref)
     163            8 :       CPASSERT(ncol == ncol_ref)
     164              : 
     165            8 :       NULLIFY (fm_struct_tmp)
     166            8 :       CALL cp_fm_create(smo, mo_ref%matrix_struct)
     167              : 
     168              :       CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, &
     169              :                                ncol_global=ncol, para_env=mo_new%matrix_struct%para_env, &
     170            8 :                                context=mo_new%matrix_struct%context)
     171            8 :       CALL cp_fm_create(o1, fm_struct_tmp)
     172            8 :       CALL cp_fm_create(o2, fm_struct_tmp)
     173            8 :       CALL cp_fm_create(o3, fm_struct_tmp)
     174            8 :       CALL cp_fm_create(o4, fm_struct_tmp)
     175            8 :       CALL cp_fm_struct_release(fm_struct_tmp)
     176              : 
     177              :       ! o1 = (mo_new)^T matrix_S mo_ref
     178            8 :       CALL cp_dbcsr_sm_fm_multiply(matrix_S, mo_ref, smo, ncol)
     179            8 :       CALL parallel_gemm('T', 'N', ncol, ncol, nrow, 1.0_dp, mo_new, smo, 0.0_dp, o1)
     180              : 
     181              :       ! o2 = (o1^T o1)
     182            8 :       CALL parallel_gemm('T', 'N', ncol, ncol, ncol, 1.0_dp, o1, o1, 0.0_dp, o2)
     183              : 
     184              :       ! o2 = (o1^T o1)^-1/2
     185           24 :       ALLOCATE (eigenvalues(ncol))
     186            8 :       CALL choose_eigv_solver(o2, o3, eigenvalues)
     187            8 :       CALL cp_fm_to_fm(o3, o4)
     188           72 :       eigenvalues(:) = 1.0_dp/SQRT(eigenvalues(:))
     189            8 :       CALL cp_fm_column_scale(o4, eigenvalues)
     190            8 :       CALL parallel_gemm('N', 'T', ncol, ncol, ncol, 1.0_dp, o3, o4, 0.0_dp, o2)
     191              : 
     192              :       ! o3 = o1 (o1^T o1)^-1/2
     193            8 :       CALL parallel_gemm('N', 'N', ncol, ncol, ncol, 1.0_dp, o1, o2, 0.0_dp, o3)
     194              : 
     195              :       ! mo_new o1 (o1^T o1)^-1/2
     196            8 :       CALL parallel_gemm('N', 'N', nrow, ncol, ncol, 1.0_dp, mo_new, o3, 0.0_dp, smo)
     197            8 :       CALL cp_fm_to_fm(smo, mo_new)
     198              : 
     199              :       ! XXXXXXX testing
     200              :       ! CALL parallel_gemm('N','T',ncol,ncol,ncol,1.0_dp,o3,o3,0.0_dp,o1)
     201              :       ! WRITE(*,*) o1%local_data
     202              :       ! CALL parallel_gemm('T','N',ncol,ncol,ncol,1.0_dp,o3,o3,0.0_dp,o1)
     203              :       ! WRITE(*,*) o1%local_data
     204              : 
     205            8 :       CALL cp_fm_release(o1)
     206            8 :       CALL cp_fm_release(o2)
     207            8 :       CALL cp_fm_release(o3)
     208            8 :       CALL cp_fm_release(o4)
     209            8 :       CALL cp_fm_release(smo)
     210              : 
     211            8 :       CALL timestop(handle)
     212              : 
     213           32 :    END SUBROUTINE rotate_state_to_ref
     214              : 
     215              : ! **************************************************************************************************
     216              : !> \brief allocates the data, and initializes the operators
     217              : !> \param qs_loc_env new environment for the localization calculations
     218              : !> \param localized_wfn_control variables and directives for the localization
     219              : !> \param qs_env the qs_env in which the qs_env lives
     220              : !> \param myspin ...
     221              : !> \param do_localize ...
     222              : !> \param loc_coeff ...
     223              : !> \param mo_loc_history ...
     224              : !> \par History
     225              : !>      04.2005 created [MI]
     226              : !> \author MI
     227              : !> \note
     228              : !>      similar to the old one, but not quite
     229              : ! **************************************************************************************************
     230          968 :    SUBROUTINE qs_loc_env_init(qs_loc_env, localized_wfn_control, qs_env, myspin, do_localize, &
     231          484 :                               loc_coeff, mo_loc_history)
     232              : 
     233              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     234              :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
     235              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     236              :       INTEGER, INTENT(IN), OPTIONAL                      :: myspin
     237              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_localize
     238              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN), &
     239              :          OPTIONAL                                        :: loc_coeff
     240              :       TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER  :: mo_loc_history
     241              : 
     242              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_loc_env_init'
     243              : 
     244              :       INTEGER                                            :: dim_op, handle, i, iatom, imo, imoloc, &
     245              :                                                             ispin, j, l_spin, lb, nao, naosub, &
     246              :                                                             natoms, nmo, nmosub, nspins, s_spin, ub
     247              :       REAL(KIND=dp)                                      :: my_occ, occ_imo
     248          484 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupations
     249          484 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: vecbuffer
     250              :       TYPE(cell_type), POINTER                           :: cell
     251              :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
     252          484 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: moloc_coeff
     253              :       TYPE(cp_fm_type), POINTER                          :: mat_ptr, mo_coeff
     254          484 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     255              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     256          484 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     257              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     258          484 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     259              : 
     260          484 :       CALL timeset(routineN, handle)
     261              : 
     262          484 :       NULLIFY (mos, matrix_s, moloc_coeff, particle_set, para_env, cell, &
     263          484 :                local_molecules, occupations, mat_ptr)
     264          484 :       IF (PRESENT(do_localize)) qs_loc_env%do_localize = do_localize
     265          484 :       IF (qs_loc_env%do_localize) THEN
     266              :          CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, cell=cell, &
     267              :                          local_molecules=local_molecules, particle_set=particle_set, &
     268          484 :                          para_env=para_env, mos=mos)
     269          484 :          nspins = SIZE(mos, 1)
     270          484 :          s_spin = 1
     271          484 :          l_spin = nspins
     272          484 :          IF (PRESENT(myspin)) THEN
     273          162 :             s_spin = myspin
     274          162 :             l_spin = myspin
     275              :          END IF
     276          484 :          IF (PRESENT(loc_coeff) .AND. nspins*2 == SIZE(loc_coeff)) THEN
     277          166 :             ALLOCATE (moloc_coeff(s_spin:s_spin + 2*(l_spin - s_spin) + 1))
     278              :          ELSE
     279         1948 :             ALLOCATE (moloc_coeff(s_spin:l_spin))
     280              :          END IF
     281         1102 :          DO ispin = s_spin, l_spin
     282          618 :             NULLIFY (tmp_fm_struct, mo_coeff)
     283          618 :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
     284          618 :             nmosub = localized_wfn_control%nloc_states(ispin)
     285              :             CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nao, &
     286          618 :                                      ncol_global=nmosub, para_env=para_env, context=mo_coeff%matrix_struct%context)
     287          618 :             IF (PRESENT(loc_coeff) .AND. nspins*2 == SIZE(loc_coeff)) THEN
     288           44 :                CALL cp_fm_create(moloc_coeff(2*ispin - 1), tmp_fm_struct)
     289           44 :                CALL cp_fm_create(moloc_coeff(2*ispin), tmp_fm_struct)
     290              :             ELSE
     291          574 :                CALL cp_fm_create(moloc_coeff(ispin), tmp_fm_struct)
     292              :             END IF
     293              : 
     294              :             CALL cp_fm_get_info(moloc_coeff(ispin), nrow_global=naosub, &
     295          618 :                                 ncol_global=nmosub)
     296          618 :             CPASSERT(nao == naosub)
     297          618 :             IF ((localized_wfn_control%do_homo) .OR. &
     298              :                 (localized_wfn_control%set_of_states == state_loc_mixed)) THEN
     299          606 :                CPASSERT(nmo >= nmosub)
     300              :             ELSE
     301           12 :                CPASSERT(nao - nmo >= nmosub)
     302              :             END IF
     303          618 :             CALL cp_fm_set_all(moloc_coeff(ispin), 0.0_dp)
     304         2338 :             CALL cp_fm_struct_release(tmp_fm_struct)
     305              :          END DO ! ispin
     306              :          ! Copy the submatrix
     307              : 
     308          484 :          IF (PRESENT(loc_coeff)) ALLOCATE (mat_ptr)
     309              : 
     310         1102 :          DO ispin = s_spin, l_spin
     311              :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, &
     312          618 :                             occupation_numbers=occupations, nao=nao, nmo=nmo)
     313          618 :             lb = localized_wfn_control%lu_bound_states(1, ispin)
     314          618 :             ub = localized_wfn_control%lu_bound_states(2, ispin)
     315              : 
     316          618 :             IF (PRESENT(loc_coeff)) THEN
     317          428 :                mat_ptr = loc_coeff(ispin)
     318              :             ELSE
     319          190 :                mat_ptr => mo_coeff
     320              :             END IF
     321          618 :             IF ((localized_wfn_control%set_of_states == state_loc_list) .OR. &
     322              :                 (localized_wfn_control%set_of_states == state_loc_mixed)) THEN
     323          444 :                ALLOCATE (vecbuffer(1, nao))
     324          148 :                IF (localized_wfn_control%do_homo) THEN
     325          134 :                   my_occ = occupations(localized_wfn_control%loc_states(1, ispin))
     326              :                END IF
     327          148 :                nmosub = SIZE(localized_wfn_control%loc_states, 1)
     328          148 :                CPASSERT(nmosub > 0)
     329          148 :                imoloc = 0
     330          934 :                DO i = lb, ub
     331              :                   ! Get the index in the subset
     332          786 :                   imoloc = imoloc + 1
     333              :                   ! Get the index in the full set
     334          786 :                   imo = localized_wfn_control%loc_states(i, ispin)
     335          786 :                   IF (localized_wfn_control%do_homo) THEN
     336          652 :                      occ_imo = occupations(imo)
     337          652 :                      IF (ABS(occ_imo - my_occ) > localized_wfn_control%eps_occ) THEN
     338            0 :                         IF (localized_wfn_control%localization_method /= do_loc_none) &
     339              :                            CALL cp_abort(__LOCATION__, &
     340              :                                          "States with different occupations "// &
     341            0 :                                          "cannot be rotated together")
     342              :                      END IF
     343              :                   END IF
     344              :                   ! Take the imo vector from the full set and copy in the imoloc vector of the subset
     345              :                   CALL cp_fm_get_submatrix(mat_ptr, vecbuffer, 1, imo, &
     346          786 :                                            nao, 1, transpose=.TRUE.)
     347              :                   CALL cp_fm_set_submatrix(moloc_coeff(ispin), vecbuffer, 1, imoloc, &
     348          934 :                                            nao, 1, transpose=.TRUE.)
     349              :                END DO
     350          148 :                DEALLOCATE (vecbuffer)
     351              :             ELSE
     352          470 :                my_occ = occupations(lb)
     353          470 :                occ_imo = occupations(ub)
     354          470 :                IF (ABS(occ_imo - my_occ) > localized_wfn_control%eps_occ) THEN
     355            0 :                   IF (localized_wfn_control%localization_method /= do_loc_none) &
     356              :                      CALL cp_abort(__LOCATION__, &
     357              :                                    "States with different occupations "// &
     358            0 :                                    "cannot be rotated together")
     359              :                END IF
     360          470 :                nmosub = localized_wfn_control%nloc_states(ispin)
     361              : 
     362          470 :                IF (PRESENT(loc_coeff) .AND. nspins*2 == SIZE(loc_coeff)) THEN
     363           44 :                   CALL cp_fm_to_fm(loc_coeff(2*ispin - 1), moloc_coeff(2*ispin - 1))
     364           44 :                   CALL cp_fm_to_fm(loc_coeff(2*ispin), moloc_coeff(2*ispin))
     365              :                ELSE
     366          426 :                   CALL cp_fm_to_fm(mat_ptr, moloc_coeff(ispin), nmosub, lb, 1)
     367              :                END IF
     368              :             END IF
     369              : 
     370              :             ! we have the mo's to be localized now, see if we can rotate them according to the history
     371              :             ! only do that if we have a history of course. The history is filled
     372         1720 :             IF (PRESENT(mo_loc_history)) THEN
     373          104 :                IF (localized_wfn_control%use_history .AND. ASSOCIATED(mo_loc_history)) THEN
     374              :                   CALL rotate_state_to_ref(moloc_coeff(ispin), &
     375            8 :                                            mo_loc_history(ispin), matrix_s(1)%matrix)
     376              :                END IF
     377              :             END IF
     378              : 
     379              :          END DO
     380              : 
     381          484 :          IF (PRESENT(loc_coeff)) DEALLOCATE (mat_ptr)
     382              : 
     383              :          CALL set_qs_loc_env(qs_loc_env=qs_loc_env, cell=cell, local_molecules=local_molecules, &
     384              :                              moloc_coeff=moloc_coeff, particle_set=particle_set, para_env=para_env, &
     385          484 :                              localized_wfn_control=localized_wfn_control)
     386              : 
     387              :          ! Prepare the operators
     388          484 :          NULLIFY (tmp_fm_struct, mo_coeff)
     389         1452 :          nmosub = MAXVAL(localized_wfn_control%nloc_states)
     390          484 :          CALL get_mo_set(mos(1), mo_coeff=mo_coeff)
     391              :          CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmosub, &
     392          484 :                                   ncol_global=nmosub, para_env=para_env, context=mo_coeff%matrix_struct%context)
     393              : 
     394          484 :          IF (localized_wfn_control%operator_type == op_loc_berry) THEN
     395          478 :             IF (qs_loc_env%cell%orthorhombic) THEN
     396          466 :                dim_op = 3
     397              :             ELSE
     398           12 :                dim_op = 6
     399              :             END IF
     400          478 :             CALL set_qs_loc_env(qs_loc_env=qs_loc_env, dim_op=dim_op)
     401         5844 :             ALLOCATE (qs_loc_env%op_sm_set(2, dim_op))
     402         1948 :             DO i = 1, dim_op
     403         4888 :                DO j = 1, SIZE(qs_loc_env%op_sm_set, 1)
     404         2940 :                   NULLIFY (qs_loc_env%op_sm_set(j, i)%matrix)
     405         2940 :                   ALLOCATE (qs_loc_env%op_sm_set(j, i)%matrix)
     406              :                   CALL dbcsr_copy(qs_loc_env%op_sm_set(j, i)%matrix, matrix_s(1)%matrix, &
     407         2940 :                                   name="qs_loc_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(j)))//"-"//TRIM(ADJUSTL(cp_to_string(i))))
     408         4410 :                   CALL dbcsr_set(qs_loc_env%op_sm_set(j, i)%matrix, 0.0_dp)
     409              :                END DO
     410              :             END DO
     411              : 
     412            6 :          ELSEIF (localized_wfn_control%operator_type == op_loc_pipek) THEN
     413            6 :             natoms = SIZE(qs_loc_env%particle_set, 1)
     414           96 :             ALLOCATE (qs_loc_env%op_fm_set(natoms, 1))
     415            6 :             CALL set_qs_loc_env(qs_loc_env=qs_loc_env, dim_op=natoms)
     416           12 :             DO ispin = 1, SIZE(qs_loc_env%op_fm_set, 2)
     417            6 :                CALL get_mo_set(mos(ispin), nmo=nmo)
     418           84 :                DO iatom = 1, natoms
     419           72 :                   CALL cp_fm_create(qs_loc_env%op_fm_set(iatom, ispin), tmp_fm_struct)
     420              : 
     421           72 :                   CALL cp_fm_get_info(qs_loc_env%op_fm_set(iatom, ispin), nrow_global=nmosub)
     422           72 :                   CPASSERT(nmo >= nmosub)
     423          150 :                   CALL cp_fm_set_all(qs_loc_env%op_fm_set(iatom, ispin), 0.0_dp)
     424              :                END DO ! iatom
     425              :             END DO ! ispin
     426              :          ELSE
     427            0 :             CPABORT("Type of operator not implemented")
     428              :          END IF
     429          484 :          CALL cp_fm_struct_release(tmp_fm_struct)
     430              : 
     431          484 :          IF (localized_wfn_control%operator_type == op_loc_berry) THEN
     432              : 
     433          478 :             CALL initialize_weights(qs_loc_env%cell, qs_loc_env%weights)
     434              : 
     435          478 :             CALL get_berry_operator(qs_loc_env, qs_env)
     436              : 
     437              :          ELSEIF (localized_wfn_control%operator_type == op_loc_pipek) THEN
     438              : 
     439              :             !!    here we don't have to do anything
     440              :             !!    CALL get_pipek_mezey_operator ( qs_loc_env, qs_env )
     441              : 
     442              :          END IF
     443              : 
     444          484 :          qs_loc_env%molecular_states = .FALSE.
     445          484 :          qs_loc_env%wannier_states = .FALSE.
     446              :       END IF
     447          484 :       CALL timestop(handle)
     448              : 
     449          484 :    END SUBROUTINE qs_loc_env_init
     450              : 
     451              : ! **************************************************************************************************
     452              : !> \brief A wrapper to compute the Berry operator for periodic systems
     453              : !> \param qs_loc_env new environment for the localization calculations
     454              : !> \param qs_env the qs_env in which the qs_env lives
     455              : !> \par History
     456              : !>      04.2005 created [MI]
     457              : !>      04.2018 modified [RZK, ZL]
     458              : !> \author MI
     459              : ! **************************************************************************************************
     460          478 :    SUBROUTINE get_berry_operator(qs_loc_env, qs_env)
     461              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     462              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     463              : 
     464              :       CHARACTER(len=*), PARAMETER :: routineN = 'get_berry_operator'
     465              : 
     466              :       INTEGER                                            :: dim_op, handle
     467              :       TYPE(cell_type), POINTER                           :: cell
     468          478 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_sm_set
     469              : 
     470          478 :       CALL timeset(routineN, handle)
     471              : 
     472          478 :       NULLIFY (cell, op_sm_set)
     473              :       CALL get_qs_loc_env(qs_loc_env=qs_loc_env, op_sm_set=op_sm_set, &
     474          478 :                           cell=cell, dim_op=dim_op)
     475          478 :       CALL compute_berry_operator(qs_env, cell, op_sm_set, dim_op)
     476              : 
     477          478 :       CALL timestop(handle)
     478          478 :    END SUBROUTINE get_berry_operator
     479              : 
     480              : ! **************************************************************************************************
     481              : !> \brief Computes the Berry operator for periodic systems
     482              : !>       used to define the spread of the MOS
     483              : !>       Here the matrix elements of the type <mu|cos(kr)|nu> and  <mu|sin(kr)|nu>
     484              : !>       are computed, where mu and nu are the contracted basis functions.
     485              : !>       Namely the Berry operator is exp(ikr)
     486              : !>       k is defined somewhere
     487              : !>       the pair lists are exploited and sparse matrixes are constructed
     488              : !> \param qs_env the qs_env in which the qs_env lives
     489              : !> \param cell ...
     490              : !> \param op_sm_set ...
     491              : !> \param dim_op ...
     492              : !> \par History
     493              : !>      04.2005 created [MI]
     494              : !>      04.2018 wrapped old code [RZK, ZL]
     495              : !> \author MI
     496              : !> \note
     497              : !>      The intgrals are computed analytically  using the primitives GTO
     498              : !>      The contraction is performed block-wise
     499              : ! **************************************************************************************************
     500          504 :    SUBROUTINE compute_berry_operator(qs_env, cell, op_sm_set, dim_op)
     501              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     502              :       TYPE(cell_type), POINTER                           :: cell
     503              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_sm_set
     504              :       INTEGER                                            :: dim_op
     505              : 
     506              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_berry_operator'
     507              : 
     508              :       INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
     509              :          ldab, ldsa, ldsb, ldwork, maxl, ncoa, ncob, nkind, nrow, nseta, nsetb, sgfa, sgfb
     510              :       INTEGER, DIMENSION(3)                              :: perd0
     511          504 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     512          504 :                                                             npgfb, nsgfa, nsgfb
     513          504 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     514              :       LOGICAL                                            :: found, new_atom_b
     515              :       REAL(KIND=dp)                                      :: dab, kvec(3), rab2, vector_k(3, 6)
     516              :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rab, rb
     517          504 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     518          504 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cosab, rpgfa, rpgfb, sinab, sphi_a, &
     519          504 :                                                             sphi_b, work, zeta, zetb
     520          504 :       TYPE(block_p_type), DIMENSION(:), POINTER          :: op_cos, op_sin
     521          504 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     522              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     523              :       TYPE(neighbor_list_iterator_p_type), &
     524          504 :          DIMENSION(:), POINTER                           :: nl_iterator
     525              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     526          504 :          POINTER                                         :: sab_orb
     527          504 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     528          504 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     529              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     530              : 
     531          504 :       CALL timeset(routineN, handle)
     532          504 :       NULLIFY (qs_kind, qs_kind_set)
     533          504 :       NULLIFY (particle_set)
     534          504 :       NULLIFY (sab_orb)
     535              :       NULLIFY (cosab, sinab, work)
     536          504 :       NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
     537          504 :       NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
     538              : 
     539              :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
     540          504 :                       particle_set=particle_set, sab_orb=sab_orb)
     541              : 
     542          504 :       nkind = SIZE(qs_kind_set)
     543              : 
     544              :       CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
     545          504 :                            maxco=ldwork, maxlgto=maxl)
     546          504 :       ldab = ldwork
     547         2016 :       ALLOCATE (cosab(ldab, ldab))
     548       136612 :       cosab = 0.0_dp
     549         1512 :       ALLOCATE (sinab(ldab, ldab))
     550       136612 :       sinab = 0.0_dp
     551         1512 :       ALLOCATE (work(ldwork, ldwork))
     552       136612 :       work = 0.0_dp
     553              : 
     554         3060 :       ALLOCATE (op_cos(dim_op))
     555         2556 :       ALLOCATE (op_sin(dim_op))
     556         2052 :       DO i = 1, dim_op
     557         1548 :          NULLIFY (op_cos(i)%block)
     558         2052 :          NULLIFY (op_sin(i)%block)
     559              :       END DO
     560              : 
     561          504 :       kvec = 0.0_dp
     562          504 :       vector_k = 0.0_dp
     563         2016 :       vector_k(:, 1) = twopi*cell%h_inv(1, :)
     564         2016 :       vector_k(:, 2) = twopi*cell%h_inv(2, :)
     565         2016 :       vector_k(:, 3) = twopi*cell%h_inv(3, :)
     566         2016 :       vector_k(:, 4) = twopi*(cell%h_inv(1, :) + cell%h_inv(2, :))
     567         2016 :       vector_k(:, 5) = twopi*(cell%h_inv(1, :) + cell%h_inv(3, :))
     568         2016 :       vector_k(:, 6) = twopi*(cell%h_inv(2, :) + cell%h_inv(3, :))
     569              : 
     570              :       ! This operator can be used only for periodic systems
     571              :       ! If an isolated system is used the periodicity is overimposed
     572         2016 :       perd0(1:3) = cell%perd(1:3)
     573         2016 :       cell%perd(1:3) = 1
     574              : 
     575         2424 :       ALLOCATE (basis_set_list(nkind))
     576         1416 :       DO ikind = 1, nkind
     577          912 :          qs_kind => qs_kind_set(ikind)
     578          912 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
     579         1416 :          IF (ASSOCIATED(basis_set_a)) THEN
     580          912 :             basis_set_list(ikind)%gto_basis_set => basis_set_a
     581              :          ELSE
     582            0 :             NULLIFY (basis_set_list(ikind)%gto_basis_set)
     583              :          END IF
     584              :       END DO
     585          504 :       CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
     586        76448 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     587              :          CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
     588        75944 :                                 iatom=iatom, jatom=jatom, r=rab)
     589        75944 :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     590        75944 :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     591        75944 :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     592        75944 :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     593        75944 :          ra = pbc(particle_set(iatom)%r, cell)
     594              :          ! basis ikind
     595        75944 :          first_sgfa => basis_set_a%first_sgf
     596        75944 :          la_max => basis_set_a%lmax
     597        75944 :          la_min => basis_set_a%lmin
     598        75944 :          npgfa => basis_set_a%npgf
     599        75944 :          nseta = basis_set_a%nset
     600        75944 :          nsgfa => basis_set_a%nsgf_set
     601        75944 :          rpgfa => basis_set_a%pgf_radius
     602        75944 :          set_radius_a => basis_set_a%set_radius
     603        75944 :          sphi_a => basis_set_a%sphi
     604        75944 :          zeta => basis_set_a%zet
     605              :          ! basis jkind
     606        75944 :          first_sgfb => basis_set_b%first_sgf
     607        75944 :          lb_max => basis_set_b%lmax
     608        75944 :          lb_min => basis_set_b%lmin
     609        75944 :          npgfb => basis_set_b%npgf
     610        75944 :          nsetb = basis_set_b%nset
     611        75944 :          nsgfb => basis_set_b%nsgf_set
     612        75944 :          rpgfb => basis_set_b%pgf_radius
     613        75944 :          set_radius_b => basis_set_b%set_radius
     614        75944 :          sphi_b => basis_set_b%sphi
     615        75944 :          zetb => basis_set_b%zet
     616              : 
     617        75944 :          ldsa = SIZE(sphi_a, 1)
     618        75944 :          ldsb = SIZE(sphi_b, 1)
     619        75944 :          IF (inode == 1) last_jatom = 0
     620              : 
     621       303776 :          rb = rab + ra
     622              : 
     623        75944 :          IF (jatom /= last_jatom) THEN
     624              :             new_atom_b = .TRUE.
     625              :             last_jatom = jatom
     626              :          ELSE
     627              :             new_atom_b = .FALSE.
     628              :          END IF
     629              : 
     630              :          IF (new_atom_b) THEN
     631        18941 :             IF (iatom <= jatom) THEN
     632         9900 :                irow = iatom
     633         9900 :                icol = jatom
     634              :             ELSE
     635         9041 :                irow = jatom
     636         9041 :                icol = iatom
     637              :             END IF
     638              : 
     639        76232 :             DO i = 1, dim_op
     640        57291 :                NULLIFY (op_cos(i)%block)
     641              :                CALL dbcsr_get_block_p(matrix=op_sm_set(1, i)%matrix, &
     642        57291 :                                       row=irow, col=icol, block=op_cos(i)%block, found=found)
     643        57291 :                NULLIFY (op_sin(i)%block)
     644              :                CALL dbcsr_get_block_p(matrix=op_sm_set(2, i)%matrix, &
     645        76232 :                                       row=irow, col=icol, block=op_sin(i)%block, found=found)
     646              :             END DO
     647              :          END IF ! new_atom_b
     648              : 
     649        75944 :          rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
     650        75944 :          dab = SQRT(rab2)
     651              : 
     652        75944 :          nrow = 0
     653       236712 :          DO iset = 1, nseta
     654              : 
     655       160264 :             ncoa = npgfa(iset)*ncoset(la_max(iset))
     656       160264 :             sgfa = first_sgfa(1, iset)
     657              : 
     658       520586 :             DO jset = 1, nsetb
     659              : 
     660       360322 :                ncob = npgfb(jset)*ncoset(lb_max(jset))
     661       360322 :                sgfb = first_sgfb(1, jset)
     662              : 
     663       520586 :                IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
     664              : 
     665              : !           *** Calculate the primitive overlap integrals ***
     666       734618 :                   DO i = 1, dim_op
     667      2275572 :                      kvec(1:3) = vector_k(1:3, i)
     668    192166821 :                      cosab = 0.0_dp
     669    192166821 :                      sinab = 0.0_dp
     670              :                      CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), &
     671              :                                  la_min(iset), lb_max(jset), npgfb(jset), zetb(:, jset), &
     672              :                                  rpgfb(:, jset), lb_min(jset), &
     673       568893 :                                  ra, rb, kvec, cosab, sinab)
     674              :                      CALL contract_cossin(op_cos(i)%block, op_sin(i)%block, &
     675              :                                           iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
     676              :                                           jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
     677       734618 :                                           cosab, sinab, ldab, work, ldwork)
     678              :                   END DO
     679              : 
     680              :                END IF !  >= dab
     681              : 
     682              :             END DO ! jset
     683              : 
     684       236208 :             nrow = nrow + ncoa
     685              : 
     686              :          END DO ! iset
     687              : 
     688              :       END DO
     689          504 :       CALL neighbor_list_iterator_release(nl_iterator)
     690              : 
     691              :       ! Set back the correct periodicity
     692         2016 :       cell%perd(1:3) = perd0(1:3)
     693              : 
     694         2052 :       DO i = 1, dim_op
     695         1548 :          NULLIFY (op_cos(i)%block)
     696         2052 :          NULLIFY (op_sin(i)%block)
     697              :       END DO
     698          504 :       DEALLOCATE (op_cos, op_sin)
     699              : 
     700          504 :       DEALLOCATE (cosab, sinab, work, basis_set_list)
     701              : 
     702          504 :       CALL timestop(handle)
     703         1008 :    END SUBROUTINE compute_berry_operator
     704              : 
     705              : ! **************************************************************************************************
     706              : !> \brief ...
     707              : !> \param qs_loc_env ...
     708              : !> \param section ...
     709              : !> \param mo_array ...
     710              : !> \param coeff_localized ...
     711              : !> \param do_homo ...
     712              : !> \param evals ...
     713              : !> \param do_mixed ...
     714              : ! **************************************************************************************************
     715          298 :    SUBROUTINE loc_write_restart(qs_loc_env, section, mo_array, coeff_localized, &
     716              :                                 do_homo, evals, do_mixed)
     717              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     718              :       TYPE(section_vals_type), POINTER                   :: section
     719              :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo_array
     720              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: coeff_localized
     721              :       LOGICAL, INTENT(IN)                                :: do_homo
     722              :       TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
     723              :          POINTER                                         :: evals
     724              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_mixed
     725              : 
     726              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'loc_write_restart'
     727              : 
     728              :       CHARACTER(LEN=default_path_length)                 :: filename
     729              :       CHARACTER(LEN=default_string_length)               :: my_middle
     730              :       INTEGER                                            :: handle, ispin, max_block, nao, nloc, &
     731              :                                                             nmo, output_unit, rst_unit
     732              :       LOGICAL                                            :: my_do_mixed
     733              :       TYPE(cp_logger_type), POINTER                      :: logger
     734              :       TYPE(section_vals_type), POINTER                   :: print_key
     735              : 
     736          298 :       CALL timeset(routineN, handle)
     737          298 :       NULLIFY (logger)
     738          298 :       logger => cp_get_default_logger()
     739          298 :       output_unit = cp_logger_get_default_io_unit(logger)
     740              : 
     741          298 :       IF (qs_loc_env%do_localize) THEN
     742              : 
     743          282 :          print_key => section_vals_get_subs_vals(section, "LOC_RESTART")
     744          282 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     745              :                                               section, "LOC_RESTART"), &
     746              :                    cp_p_file)) THEN
     747              : 
     748              :             ! Open file
     749              :             rst_unit = -1
     750              : 
     751           30 :             my_do_mixed = .FALSE.
     752           30 :             IF (PRESENT(do_mixed)) my_do_mixed = do_mixed
     753           30 :             IF (do_homo) THEN
     754           30 :                my_middle = "LOC_HOMO"
     755            0 :             ELSEIF (my_do_mixed) THEN
     756            0 :                my_middle = "LOC_MIXED"
     757              :             ELSE
     758            0 :                my_middle = "LOC_LUMO"
     759              :             END IF
     760              : 
     761              :             rst_unit = cp_print_key_unit_nr(logger, section, "LOC_RESTART", &
     762              :                                             extension=".wfn", file_status="REPLACE", file_action="WRITE", &
     763           30 :                                             file_form="UNFORMATTED", middle_name=TRIM(my_middle))
     764              : 
     765           30 :             IF (rst_unit > 0) filename = cp_print_key_generate_filename(logger, print_key, &
     766              :                                                                         middle_name=TRIM(my_middle), extension=".wfn", &
     767           15 :                                                                         my_local=.FALSE.)
     768              : 
     769           30 :             IF (output_unit > 0) THEN
     770              :                WRITE (UNIT=output_unit, FMT="(/,T2,A, A/)") &
     771           15 :                   "LOCALIZATION| Write restart file for the localized MOS : ", &
     772           30 :                   TRIM(filename)
     773              :             END IF
     774              : 
     775           30 :             IF (rst_unit > 0) THEN
     776           15 :                WRITE (rst_unit) qs_loc_env%localized_wfn_control%set_of_states
     777          105 :                WRITE (rst_unit) qs_loc_env%localized_wfn_control%lu_bound_states
     778           45 :                WRITE (rst_unit) qs_loc_env%localized_wfn_control%nloc_states
     779              :             END IF
     780              : 
     781           70 :             DO ispin = 1, SIZE(coeff_localized)
     782           30 :                ASSOCIATE (mo_coeff => coeff_localized(ispin))
     783           40 :                   CALL cp_fm_get_info(mo_coeff, nrow_global=nao, ncol_global=nmo, ncol_block=max_block)
     784           40 :                   nloc = qs_loc_env%localized_wfn_control%nloc_states(ispin)
     785           40 :                   IF (rst_unit > 0) THEN
     786          198 :                      WRITE (rst_unit) qs_loc_env%localized_wfn_control%loc_states(1:nloc, ispin)
     787           20 :                      IF (do_homo .OR. my_do_mixed) THEN
     788           20 :                         WRITE (rst_unit) nmo, &
     789           20 :                            mo_array(ispin)%homo, &
     790           20 :                            mo_array(ispin)%lfomo, &
     791           40 :                            mo_array(ispin)%nelectron
     792          456 :                         WRITE (rst_unit) mo_array(ispin)%eigenvalues(1:nmo), &
     793          476 :                            mo_array(ispin)%occupation_numbers(1:nmo)
     794              :                      ELSE
     795            0 :                         WRITE (rst_unit) nmo
     796            0 :                         WRITE (rst_unit) evals(ispin)%array(1:nmo)
     797              :                      END IF
     798              :                   END IF
     799              : 
     800           80 :                   CALL cp_fm_write_unformatted(mo_coeff, rst_unit)
     801              :                END ASSOCIATE
     802              : 
     803              :             END DO
     804              : 
     805              :             CALL cp_print_key_finished_output(rst_unit, logger, section, &
     806           30 :                                               "LOC_RESTART")
     807              :          END IF
     808              : 
     809              :       END IF
     810              : 
     811          298 :       CALL timestop(handle)
     812              : 
     813          298 :    END SUBROUTINE loc_write_restart
     814              : 
     815              : ! **************************************************************************************************
     816              : !> \brief ...
     817              : !> \param qs_loc_env ...
     818              : !> \param mos ...
     819              : !> \param mos_localized ...
     820              : !> \param section ...
     821              : !> \param section2 ...
     822              : !> \param para_env ...
     823              : !> \param do_homo ...
     824              : !> \param restart_found ...
     825              : !> \param evals ...
     826              : !> \param do_mixed ...
     827              : ! **************************************************************************************************
     828            6 :    SUBROUTINE loc_read_restart(qs_loc_env, mos, mos_localized, section, section2, para_env, &
     829              :                                do_homo, restart_found, evals, do_mixed)
     830              : 
     831              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     832              :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     833              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: mos_localized
     834              :       TYPE(section_vals_type), POINTER                   :: section, section2
     835              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     836              :       LOGICAL, INTENT(IN)                                :: do_homo
     837              :       LOGICAL, INTENT(INOUT)                             :: restart_found
     838              :       TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
     839              :          POINTER                                         :: evals
     840              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_mixed
     841              : 
     842              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'loc_read_restart'
     843              : 
     844              :       CHARACTER(LEN=25)                                  :: fname_key
     845              :       CHARACTER(LEN=default_path_length)                 :: filename
     846              :       CHARACTER(LEN=default_string_length)               :: my_middle
     847              :       INTEGER :: handle, homo_read, i, ispin, lfomo_read, max_nloc, n_rep_val, nao, &
     848              :          nelectron_read, nloc, nmo, nmo_read, nspin, output_unit, rst_unit
     849              :       LOGICAL                                            :: file_exists, my_do_mixed
     850            6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eig_read, occ_read
     851            6 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: vecbuffer
     852              :       TYPE(cp_logger_type), POINTER                      :: logger
     853              :       TYPE(section_vals_type), POINTER                   :: print_key
     854              : 
     855            6 :       CALL timeset(routineN, handle)
     856              : 
     857            6 :       logger => cp_get_default_logger()
     858              : 
     859            6 :       nspin = SIZE(mos_localized)
     860            6 :       nao = mos(1)%nao
     861            6 :       rst_unit = -1
     862              : 
     863              :       output_unit = cp_print_key_unit_nr(logger, section2, &
     864            6 :                                          "PROGRAM_RUN_INFO", extension=".Log")
     865              : 
     866            6 :       my_do_mixed = .FALSE.
     867            6 :       IF (PRESENT(do_mixed)) my_do_mixed = do_mixed
     868            6 :       IF (do_homo) THEN
     869            6 :          fname_key = "LOCHOMO_RESTART_FILE_NAME"
     870            0 :       ELSEIF (my_do_mixed) THEN
     871            0 :          fname_key = "LOCMIXD_RESTART_FILE_NAME"
     872              :       ELSE
     873            0 :          fname_key = "LOCLUMO_RESTART_FILE_NAME"
     874            0 :          IF (.NOT. PRESENT(evals)) &
     875            0 :             CPABORT("Missing argument to localize unoccupied states.")
     876              :       END IF
     877              : 
     878            6 :       file_exists = .FALSE.
     879            6 :       CALL section_vals_val_get(section, fname_key, n_rep_val=n_rep_val)
     880            6 :       IF (n_rep_val > 0) THEN
     881            0 :          CALL section_vals_val_get(section, fname_key, c_val=filename)
     882              :       ELSE
     883              : 
     884            6 :          print_key => section_vals_get_subs_vals(section2, "LOC_RESTART")
     885            6 :          IF (do_homo) THEN
     886            6 :             my_middle = "LOC_HOMO"
     887            0 :          ELSEIF (my_do_mixed) THEN
     888            0 :             my_middle = "LOC_MIXED"
     889              :          ELSE
     890            0 :             my_middle = "LOC_LUMO"
     891              :          END IF
     892              :          filename = cp_print_key_generate_filename(logger, print_key, &
     893              :                                                    middle_name=TRIM(my_middle), extension=".wfn", &
     894            6 :                                                    my_local=.FALSE.)
     895              :       END IF
     896              : 
     897            6 :       IF (para_env%is_source()) INQUIRE (FILE=filename, exist=file_exists)
     898              : 
     899            6 :       IF (file_exists) THEN
     900            2 :          IF (para_env%is_source()) THEN
     901              :             CALL open_file(file_name=filename, &
     902              :                            file_action="READ", &
     903              :                            file_form="UNFORMATTED", &
     904              :                            file_status="OLD", &
     905            2 :                            unit_number=rst_unit)
     906              : 
     907            2 :             READ (rst_unit) qs_loc_env%localized_wfn_control%set_of_states
     908           14 :             READ (rst_unit) qs_loc_env%localized_wfn_control%lu_bound_states
     909            6 :             READ (rst_unit) qs_loc_env%localized_wfn_control%nloc_states
     910              :          END IF
     911              :       ELSE
     912            4 :          IF (output_unit > 0) WRITE (output_unit, "(/,T10,A)") &
     913            1 :             "Restart file not available filename=<"//TRIM(filename)//'>'
     914              :       END IF
     915            6 :       CALL para_env%bcast(file_exists)
     916              : 
     917            6 :       IF (file_exists) THEN
     918            4 :          restart_found = .TRUE.
     919              : 
     920            4 :          CALL para_env%bcast(qs_loc_env%localized_wfn_control%set_of_states)
     921            4 :          CALL para_env%bcast(qs_loc_env%localized_wfn_control%lu_bound_states)
     922            4 :          CALL para_env%bcast(qs_loc_env%localized_wfn_control%nloc_states)
     923              : 
     924           12 :          max_nloc = MAXVAL(qs_loc_env%localized_wfn_control%nloc_states(:))
     925              : 
     926           12 :          ALLOCATE (vecbuffer(1, nao))
     927            4 :          IF (ASSOCIATED(qs_loc_env%localized_wfn_control%loc_states)) THEN
     928            2 :             DEALLOCATE (qs_loc_env%localized_wfn_control%loc_states)
     929              :          END IF
     930           12 :          ALLOCATE (qs_loc_env%localized_wfn_control%loc_states(max_nloc, 2))
     931           56 :          qs_loc_env%localized_wfn_control%loc_states = 0
     932              : 
     933           10 :          DO ispin = 1, nspin
     934            6 :             IF (do_homo .OR. do_mixed) THEN
     935            6 :                nmo = mos(ispin)%nmo
     936              :             ELSE
     937            0 :                nmo = SIZE(evals(ispin)%array, 1)
     938              :             END IF
     939            6 :             IF (para_env%is_source() .AND. (nmo > 0)) THEN
     940            3 :                nloc = qs_loc_env%localized_wfn_control%nloc_states(ispin)
     941           21 :                READ (rst_unit) qs_loc_env%localized_wfn_control%loc_states(1:nloc, ispin)
     942            3 :                IF (do_homo .OR. do_mixed) THEN
     943            3 :                   READ (rst_unit) nmo_read, homo_read, lfomo_read, nelectron_read
     944           12 :                   ALLOCATE (eig_read(nmo_read), occ_read(nmo_read))
     945            3 :                   eig_read = 0.0_dp
     946            3 :                   occ_read = 0.0_dp
     947            3 :                   READ (rst_unit) eig_read(1:nmo_read), occ_read(1:nmo_read)
     948              :                ELSE
     949            0 :                   READ (rst_unit) nmo_read
     950            0 :                   ALLOCATE (eig_read(nmo_read))
     951            0 :                   eig_read = 0.0_dp
     952            0 :                   READ (rst_unit) eig_read(1:nmo_read)
     953              :                END IF
     954            3 :                IF (nmo_read < nmo) &
     955              :                   CALL cp_warn(__LOCATION__, &
     956              :                                "The number of MOs on the restart unit is smaller than the number of "// &
     957            0 :                                "the allocated MOs. ")
     958            3 :                IF (nmo_read > nmo) &
     959              :                   CALL cp_warn(__LOCATION__, &
     960              :                                "The number of MOs on the restart unit is greater than the number of "// &
     961            0 :                                "the allocated MOs. The read MO set will be truncated!")
     962              : 
     963            3 :                nmo = MIN(nmo, nmo_read)
     964            3 :                IF (do_homo .OR. do_mixed) THEN
     965           79 :                   mos(ispin)%eigenvalues(1:nmo) = eig_read(1:nmo)
     966           79 :                   mos(ispin)%occupation_numbers(1:nmo) = occ_read(1:nmo)
     967            3 :                   DEALLOCATE (eig_read, occ_read)
     968              :                ELSE
     969            0 :                   evals(ispin)%array(1:nmo) = eig_read(1:nmo)
     970            0 :                   DEALLOCATE (eig_read)
     971              :                END IF
     972              : 
     973              :             END IF
     974            6 :             IF (do_homo .OR. do_mixed) THEN
     975          310 :                CALL para_env%bcast(mos(ispin)%eigenvalues)
     976          310 :                CALL para_env%bcast(mos(ispin)%occupation_numbers)
     977              :             ELSE
     978            0 :                CALL para_env%bcast(evals(ispin)%array)
     979              :             END IF
     980              : 
     981          162 :             DO i = 1, nmo
     982          152 :                IF (para_env%is_source()) THEN
     983        15236 :                   READ (rst_unit) vecbuffer
     984              :                ELSE
     985         7656 :                   vecbuffer(1, :) = 0.0_dp
     986              :                END IF
     987        60792 :                CALL para_env%bcast(vecbuffer)
     988              :                CALL cp_fm_set_submatrix(mos_localized(ispin), &
     989          158 :                                         vecbuffer, 1, i, nao, 1, transpose=.TRUE.)
     990              :             END DO
     991              :          END DO
     992              : 
     993          108 :          CALL para_env%bcast(qs_loc_env%localized_wfn_control%loc_states)
     994              : 
     995            4 :          DEALLOCATE (vecbuffer)
     996              : 
     997              :       END IF
     998              : 
     999              :       ! Close restart file
    1000            6 :       IF (para_env%is_source()) THEN
    1001            3 :          IF (file_exists) CALL close_file(unit_number=rst_unit)
    1002              :       END IF
    1003              : 
    1004            6 :       CALL timestop(handle)
    1005              : 
    1006            6 :    END SUBROUTINE loc_read_restart
    1007              : 
    1008              : ! **************************************************************************************************
    1009              : !> \brief initializes everything needed for localization of the HOMOs
    1010              : !> \param qs_loc_env ...
    1011              : !> \param loc_section ...
    1012              : !> \param do_homo ...
    1013              : !> \param do_mixed ...
    1014              : !> \param do_xas ...
    1015              : !> \param nloc_xas ...
    1016              : !> \param spin_xas ...
    1017              : !> \par History
    1018              : !>      2009 created
    1019              : ! **************************************************************************************************
    1020          432 :    SUBROUTINE qs_loc_control_init(qs_loc_env, loc_section, do_homo, do_mixed, &
    1021              :                                   do_xas, nloc_xas, spin_xas)
    1022              : 
    1023              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
    1024              :       TYPE(section_vals_type), POINTER                   :: loc_section
    1025              :       LOGICAL, INTENT(IN)                                :: do_homo
    1026              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_mixed, do_xas
    1027              :       INTEGER, INTENT(IN), OPTIONAL                      :: nloc_xas, spin_xas
    1028              : 
    1029              :       LOGICAL                                            :: my_do_mixed
    1030              :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
    1031              : 
    1032          432 :       NULLIFY (localized_wfn_control)
    1033              : 
    1034          432 :       IF (PRESENT(do_mixed)) THEN
    1035            2 :          my_do_mixed = do_mixed
    1036              :       ELSE
    1037          430 :          my_do_mixed = .FALSE.
    1038              :       END IF
    1039          432 :       CALL localized_wfn_control_create(localized_wfn_control)
    1040          432 :       CALL set_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
    1041          432 :       CALL localized_wfn_control_release(localized_wfn_control)
    1042          432 :       CALL get_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
    1043          432 :       localized_wfn_control%do_homo = do_homo
    1044          432 :       localized_wfn_control%do_mixed = my_do_mixed
    1045              :       CALL read_loc_section(localized_wfn_control, loc_section, qs_loc_env%do_localize, &
    1046          432 :                             my_do_mixed, do_xas, nloc_xas, spin_xas)
    1047              : 
    1048          432 :    END SUBROUTINE qs_loc_control_init
    1049              : 
    1050              : ! **************************************************************************************************
    1051              : !> \brief initializes everything needed for localization of the molecular orbitals
    1052              : !> \param qs_env ...
    1053              : !> \param qs_loc_env ...
    1054              : !> \param localize_section ...
    1055              : !> \param mos_localized ...
    1056              : !> \param do_homo ...
    1057              : !> \param do_mo_cubes ...
    1058              : !> \param mo_loc_history ...
    1059              : !> \param evals ...
    1060              : !> \param tot_zeff_corr ...
    1061              : !> \param do_mixed ...
    1062              : ! **************************************************************************************************
    1063          324 :    SUBROUTINE qs_loc_init(qs_env, qs_loc_env, localize_section, mos_localized, &
    1064              :                           do_homo, do_mo_cubes, mo_loc_history, evals, &
    1065              :                           tot_zeff_corr, do_mixed)
    1066              : 
    1067              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1068              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
    1069              :       TYPE(section_vals_type), POINTER                   :: localize_section
    1070              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: mos_localized
    1071              :       LOGICAL, OPTIONAL                                  :: do_homo, do_mo_cubes
    1072              :       TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER  :: mo_loc_history
    1073              :       TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
    1074              :          POINTER                                         :: evals
    1075              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: tot_zeff_corr
    1076              :       LOGICAL, OPTIONAL                                  :: do_mixed
    1077              : 
    1078              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_loc_init'
    1079              : 
    1080              :       INTEGER :: handle, homo, i, ilast_intocc, ilow, ispin, iup, n_mo(2), n_mos(2), nao, &
    1081              :          nelectron, nextra, nmoloc(2), nocc, npocc, nspin, output_unit
    1082              :       LOGICAL                                            :: my_do_homo, my_do_mixed, my_do_mo_cubes, &
    1083              :                                                             restart_found
    1084              :       REAL(KIND=dp)                                      :: maxocc, my_tot_zeff_corr
    1085          324 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, occupation
    1086              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1087              :       TYPE(cp_logger_type), POINTER                      :: logger
    1088          324 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, mo_derivs
    1089              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1090              :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
    1091          324 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1092              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1093              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1094              :       TYPE(section_vals_type), POINTER                   :: loc_print_section
    1095              : 
    1096          324 :       CALL timeset(routineN, handle)
    1097              : 
    1098          324 :       NULLIFY (mos, mo_coeff, mo_eigenvalues, occupation, ks_rmpv, mo_derivs, scf_control, para_env)
    1099              :       CALL get_qs_env(qs_env, &
    1100              :                       mos=mos, &
    1101              :                       matrix_ks=ks_rmpv, &
    1102              :                       mo_derivs=mo_derivs, &
    1103              :                       scf_control=scf_control, &
    1104              :                       dft_control=dft_control, &
    1105          324 :                       para_env=para_env)
    1106              : 
    1107          324 :       loc_print_section => section_vals_get_subs_vals(localize_section, "PRINT")
    1108              : 
    1109          324 :       logger => cp_get_default_logger()
    1110          324 :       output_unit = cp_logger_get_default_io_unit(logger)
    1111              : 
    1112          324 :       nspin = SIZE(mos)
    1113          324 :       IF (PRESENT(do_homo)) THEN
    1114          324 :          my_do_homo = do_homo
    1115              :       ELSE
    1116            0 :          my_do_homo = .TRUE.
    1117              :       END IF
    1118          324 :       IF (PRESENT(do_mo_cubes)) THEN
    1119          134 :          my_do_mo_cubes = do_mo_cubes
    1120              :       ELSE
    1121              :          my_do_mo_cubes = .FALSE.
    1122              :       END IF
    1123          324 :       IF (PRESENT(do_mixed)) THEN
    1124            2 :          my_do_mixed = do_mixed
    1125              :       ELSE
    1126          322 :          my_do_mixed = .FALSE.
    1127              :       END IF
    1128          324 :       IF (PRESENT(tot_zeff_corr)) THEN
    1129            2 :          my_tot_zeff_corr = tot_zeff_corr
    1130              :       ELSE
    1131          322 :          my_tot_zeff_corr = 0.0_dp
    1132              :       END IF
    1133          324 :       restart_found = .FALSE.
    1134              : 
    1135          324 :       IF (qs_loc_env%do_localize) THEN
    1136              :          ! Some setup for MOs to be localized
    1137          308 :          CALL get_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
    1138          308 :          IF (localized_wfn_control%loc_restart) THEN
    1139            6 :             IF (localized_wfn_control%nextra > 0) THEN
    1140              :                ! currently only the occupied guess is read
    1141            0 :                my_do_homo = .FALSE.
    1142              :             END IF
    1143              :             CALL loc_read_restart(qs_loc_env, mos, mos_localized, localize_section, &
    1144              :                                   loc_print_section, para_env, my_do_homo, restart_found, evals=evals, &
    1145            6 :                                   do_mixed=my_do_mixed)
    1146            9 :             IF (output_unit > 0) WRITE (output_unit, "(/,T2,A,A)") "LOCALIZATION| ", &
    1147            6 :                "   The orbitals to be localized are read from localization restart file."
    1148           18 :             nmoloc = localized_wfn_control%nloc_states
    1149           18 :             localized_wfn_control%nguess = nmoloc
    1150            6 :             IF (localized_wfn_control%nextra > 0) THEN
    1151              :                ! reset different variables in localized_wfn_control:
    1152              :                ! lu_bound_states, nloc_states, loc_states
    1153            0 :                localized_wfn_control%loc_restart = restart_found
    1154            0 :                localized_wfn_control%set_of_states = state_loc_mixed
    1155            0 :                DO ispin = 1, nspin
    1156              :                   CALL get_mo_set(mos(ispin), homo=homo, occupation_numbers=occupation, &
    1157            0 :                                   maxocc=maxocc)
    1158            0 :                   nextra = localized_wfn_control%nextra
    1159            0 :                   nocc = homo
    1160            0 :                   DO i = nocc, 1, -1
    1161            0 :                      IF (maxocc - occupation(i) < localized_wfn_control%eps_occ) THEN
    1162            0 :                         ilast_intocc = i
    1163            0 :                         EXIT
    1164              :                      END IF
    1165              :                   END DO
    1166            0 :                   nocc = ilast_intocc
    1167            0 :                   npocc = homo - nocc
    1168            0 :                   nmoloc(ispin) = nocc + nextra
    1169            0 :                   localized_wfn_control%lu_bound_states(1, ispin) = 1
    1170            0 :                   localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
    1171            0 :                   localized_wfn_control%nloc_states(ispin) = nmoloc(ispin)
    1172              :                END DO
    1173            0 :                my_do_homo = .FALSE.
    1174              :             END IF
    1175              :          END IF
    1176          308 :          IF (.NOT. restart_found) THEN
    1177          304 :             nmoloc = 0
    1178          726 :             DO ispin = 1, nspin
    1179              :                CALL get_mo_set(mos(ispin), nmo=n_mo(ispin), nelectron=nelectron, homo=homo, nao=nao, &
    1180              :                                mo_coeff=mo_coeff, eigenvalues=mo_eigenvalues, occupation_numbers=occupation, &
    1181          422 :                                maxocc=maxocc)
    1182              :                ! Get eigenstates (only needed if not already calculated before)
    1183              :                IF ((.NOT. my_do_mo_cubes) &
    1184              :                    !                  .OR. section_get_ival(dft_section,"PRINT%MO_CUBES%NHOMO")==0)&
    1185              :                    .AND. my_do_homo .AND. ASSOCIATED(qs_env%scf_env) &
    1186          422 :                    .AND. qs_env%scf_env%method == ot_method_nr .AND. (.NOT. dft_control%restricted)) THEN
    1187           30 :                   CALL make_mo_eig(mos, nspin, ks_rmpv, scf_control, mo_derivs)
    1188              :                END IF
    1189         1148 :                IF (localized_wfn_control%set_of_states == state_loc_all .AND. my_do_homo) THEN
    1190          382 :                   nmoloc(ispin) = NINT(nelectron/occupation(1))
    1191          382 :                   IF (n_mo(ispin) > homo) THEN
    1192           30 :                      DO i = nmoloc(ispin), 1, -1
    1193           30 :                         IF (occupation(1) - occupation(i) < localized_wfn_control%eps_occ) THEN
    1194           14 :                            ilast_intocc = i
    1195           14 :                            EXIT
    1196              :                         END IF
    1197              :                      END DO
    1198              :                   ELSE
    1199          368 :                      ilast_intocc = nmoloc(ispin)
    1200              :                   END IF
    1201          382 :                   nmoloc(ispin) = ilast_intocc
    1202          382 :                   localized_wfn_control%lu_bound_states(1, ispin) = 1
    1203          382 :                   localized_wfn_control%lu_bound_states(2, ispin) = ilast_intocc
    1204          382 :                   IF (nmoloc(ispin) /= n_mo(ispin)) THEN
    1205           14 :                      IF (output_unit > 0) &
    1206              :                         WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,F12.6,A,F12.6,A)") &
    1207            7 :                         "LOCALIZATION| Spin ", ispin, " The first ", &
    1208            7 :                         ilast_intocc, " occupied orbitals are localized,", " with energies from ", &
    1209           14 :                         mo_eigenvalues(1), " to ", mo_eigenvalues(ilast_intocc), " [a.u.]."
    1210              :                   END IF
    1211           40 :                ELSE IF (localized_wfn_control%set_of_states == energy_loc_range .AND. my_do_homo) THEN
    1212           12 :                   ilow = 0
    1213           12 :                   iup = 0
    1214           20 :                   DO i = 1, n_mo(ispin)
    1215           20 :                      IF (mo_eigenvalues(i) >= localized_wfn_control%lu_ene_bound(1)) THEN
    1216              :                         ilow = i
    1217              :                         EXIT
    1218              :                      END IF
    1219              :                   END DO
    1220          324 :                   DO i = n_mo(ispin), 1, -1
    1221          324 :                      IF (mo_eigenvalues(i) <= localized_wfn_control%lu_ene_bound(2)) THEN
    1222              :                         iup = i
    1223              :                         EXIT
    1224              :                      END IF
    1225              :                   END DO
    1226           12 :                   localized_wfn_control%lu_bound_states(1, ispin) = ilow
    1227           12 :                   localized_wfn_control%lu_bound_states(2, ispin) = iup
    1228           12 :                   localized_wfn_control%nloc_states(ispin) = iup - ilow + 1
    1229           12 :                   nmoloc(ispin) = localized_wfn_control%nloc_states(ispin)
    1230           12 :                   IF (occupation(ilow) - occupation(iup) > localized_wfn_control%eps_occ) THEN
    1231              :                      CALL cp_abort(__LOCATION__, &
    1232              :                                    "The selected energy range includes orbitals with different occupation number. "// &
    1233            0 :                                    "The localization procedure cannot be applied.")
    1234              :                   END IF
    1235           18 :                   IF (output_unit > 0) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", ispin, " : ", &
    1236           12 :                      nmoloc(ispin), " orbitals in the selected energy range are localized."
    1237           28 :                ELSE IF (localized_wfn_control%set_of_states == state_loc_all .AND. (.NOT. my_do_homo)) THEN
    1238            0 :                   nmoloc(ispin) = n_mo(ispin) - homo
    1239            0 :                   localized_wfn_control%lu_bound_states(1, ispin) = homo + 1
    1240            0 :                   localized_wfn_control%lu_bound_states(2, ispin) = n_mo(ispin)
    1241            0 :                   IF (output_unit > 0) &
    1242              :                      WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,F12.6,A,F12.6,A)") &
    1243            0 :                      "LOCALIZATION| Spin ", ispin, " The first ", &
    1244            0 :                      nmoloc(ispin), " virtual orbitals are localized,", " with energies from ", &
    1245            0 :                      mo_eigenvalues(homo + 1), " to ", mo_eigenvalues(n_mo(ispin)), " [a.u.]."
    1246           28 :                ELSE IF (localized_wfn_control%set_of_states == state_loc_mixed) THEN
    1247            2 :                   nextra = localized_wfn_control%nextra
    1248            2 :                   nocc = homo
    1249            6 :                   DO i = nocc, 1, -1
    1250            6 :                      IF (maxocc - occupation(i) < localized_wfn_control%eps_occ) THEN
    1251            2 :                         ilast_intocc = i
    1252            2 :                         EXIT
    1253              :                      END IF
    1254              :                   END DO
    1255            2 :                   nocc = ilast_intocc
    1256            2 :                   npocc = homo - nocc
    1257            2 :                   nmoloc(ispin) = nocc + nextra
    1258            2 :                   localized_wfn_control%lu_bound_states(1, ispin) = 1
    1259            2 :                   localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
    1260            2 :                   IF (output_unit > 0) &
    1261              :                      WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,I6,/,T15,A,I6,/,T15,A,I6,/,T15,A,F12.6,A)") &
    1262            1 :                      "LOCALIZATION| Spin ", ispin, " The first ", &
    1263            1 :                      nmoloc(ispin), " orbitals are localized.", &
    1264            1 :                      "Number of fully occupied MOs: ", nocc, &
    1265            1 :                      "Number of partially occupied MOs: ", npocc, &
    1266            1 :                      "Number of extra degrees of freedom: ", nextra, &
    1267            2 :                      "Excess charge: ", my_tot_zeff_corr, " electrons"
    1268              :                ELSE
    1269           26 :                   nmoloc(ispin) = MIN(localized_wfn_control%nloc_states(1), n_mo(ispin))
    1270           33 :                   IF (output_unit > 0 .AND. my_do_homo) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", ispin, &
    1271           14 :                      " : ", nmoloc(ispin), " occupied orbitals are localized, as given in the input list."
    1272           19 :                   IF (output_unit > 0 .AND. (.NOT. my_do_homo)) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", &
    1273           12 :                      ispin, " : ", nmoloc(ispin), " unoccupied orbitals are localized, as given in the input list."
    1274           26 :                   IF (n_mo(ispin) > homo .AND. my_do_homo) THEN
    1275            8 :                      ilow = localized_wfn_control%loc_states(1, ispin)
    1276           56 :                      DO i = 2, nmoloc(ispin)
    1277           48 :                         iup = localized_wfn_control%loc_states(i, ispin)
    1278           56 :                         IF (ABS(occupation(ilow) - occupation(iup)) > localized_wfn_control%eps_occ) THEN
    1279              :                            ! write warning
    1280              :                            CALL cp_warn(__LOCATION__, &
    1281              :                                         "User requested the calculation of localized wavefunction from a subset of MOs, "// &
    1282              :                                         "including MOs with different occupations. Check the selected subset, "// &
    1283              :                                         "the electronic density is not invariant with "// &
    1284            0 :                                         "respect to rotations among orbitals with different occupation numbers!")
    1285              :                         END IF
    1286              :                      END DO
    1287              :                   END IF
    1288              :                END IF
    1289              :             END DO ! ispin
    1290          912 :             n_mos(:) = nao - n_mo(:)
    1291          304 :             IF (my_do_homo .OR. my_do_mixed) n_mos = n_mo
    1292          304 :             CALL set_loc_wfn_lists(localized_wfn_control, nmoloc, n_mos, nspin)
    1293              :          END IF
    1294          308 :          CALL set_loc_centers(localized_wfn_control, nmoloc, nspin)
    1295          308 :          IF (my_do_homo .OR. my_do_mixed) THEN
    1296              :             CALL qs_loc_env_init(qs_loc_env, localized_wfn_control, qs_env, &
    1297          302 :                                  loc_coeff=mos_localized, mo_loc_history=mo_loc_history)
    1298              :          END IF
    1299              :       ELSE
    1300              :          ! Let's inform in case the section is not present in the input
    1301              :          CALL cp_warn(__LOCATION__, &
    1302              :                       "User requested the calculation of the localized wavefunction but the section "// &
    1303           16 :                       "LOCALIZE was not specified. Localization will not be performed!")
    1304              :       END IF
    1305              : 
    1306          324 :       CALL timestop(handle)
    1307              : 
    1308          324 :    END SUBROUTINE qs_loc_init
    1309              : 
    1310              : ! **************************************************************************************************
    1311              : !> \brief read the controlparameter from input, using the new input scheme
    1312              : !> \param localized_wfn_control ...
    1313              : !> \param loc_section ...
    1314              : !> \param localize ...
    1315              : !> \param do_mixed ...
    1316              : !> \param do_xas ...
    1317              : !> \param nloc_xas ...
    1318              : !> \param spin_channel_xas ...
    1319              : !> \par History
    1320              : !>      05.2005 created [MI]
    1321              : ! **************************************************************************************************
    1322          864 :    SUBROUTINE read_loc_section(localized_wfn_control, loc_section, &
    1323              :                                localize, do_mixed, do_xas, nloc_xas, spin_channel_xas)
    1324              : 
    1325              :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
    1326              :       TYPE(section_vals_type), POINTER                   :: loc_section
    1327              :       LOGICAL, INTENT(OUT)                               :: localize
    1328              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_mixed, do_xas
    1329              :       INTEGER, INTENT(IN), OPTIONAL                      :: nloc_xas, spin_channel_xas
    1330              : 
    1331              :       INTEGER                                            :: i, ind, ir, n_list, n_rep, n_state, &
    1332              :                                                             nextra, nline, other_spin, &
    1333              :                                                             output_unit, spin_xas
    1334          432 :       INTEGER, DIMENSION(:), POINTER                     :: list, loc_list
    1335              :       LOGICAL                                            :: my_do_mixed, my_do_xas
    1336          432 :       REAL(dp), POINTER                                  :: ene(:)
    1337              :       TYPE(cp_logger_type), POINTER                      :: logger
    1338              :       TYPE(section_vals_type), POINTER                   :: loc_print_section
    1339              : 
    1340          432 :       my_do_xas = .FALSE.
    1341          432 :       spin_xas = 1
    1342          432 :       IF (PRESENT(do_xas)) THEN
    1343          108 :          my_do_xas = do_xas
    1344          108 :          CPASSERT(PRESENT(nloc_xas))
    1345              :       END IF
    1346          432 :       IF (PRESENT(spin_channel_xas)) spin_xas = spin_channel_xas
    1347          432 :       my_do_mixed = .FALSE.
    1348          432 :       IF (PRESENT(do_mixed)) THEN
    1349          432 :          my_do_mixed = do_mixed
    1350              :       END IF
    1351          432 :       CPASSERT(ASSOCIATED(loc_section))
    1352          432 :       NULLIFY (logger)
    1353          432 :       logger => cp_get_default_logger()
    1354              : 
    1355          432 :       CALL section_vals_val_get(loc_section, "_SECTION_PARAMETERS_", l_val=localize)
    1356          432 :       IF (localize) THEN
    1357          384 :          loc_print_section => section_vals_get_subs_vals(loc_section, "PRINT")
    1358          384 :          NULLIFY (list)
    1359          384 :          NULLIFY (loc_list)
    1360         2688 :          localized_wfn_control%lu_bound_states = 0
    1361         1152 :          localized_wfn_control%lu_ene_bound = 0.0_dp
    1362         1152 :          localized_wfn_control%nloc_states = 0
    1363          384 :          localized_wfn_control%set_of_states = 0
    1364          384 :          localized_wfn_control%nextra = 0
    1365          384 :          n_state = 0
    1366              : 
    1367              :          CALL section_vals_val_get(loc_section, "MAX_ITER", &
    1368          384 :                                    i_val=localized_wfn_control%max_iter)
    1369              :          CALL section_vals_val_get(loc_section, "MAX_CRAZY_ANGLE", &
    1370          384 :                                    r_val=localized_wfn_control%max_crazy_angle)
    1371              :          CALL section_vals_val_get(loc_section, "CRAZY_SCALE", &
    1372          384 :                                    r_val=localized_wfn_control%crazy_scale)
    1373              :          CALL section_vals_val_get(loc_section, "EPS_OCCUPATION", &
    1374          384 :                                    r_val=localized_wfn_control%eps_occ)
    1375              :          CALL section_vals_val_get(loc_section, "CRAZY_USE_DIAG", &
    1376          384 :                                    l_val=localized_wfn_control%crazy_use_diag)
    1377              :          CALL section_vals_val_get(loc_section, "OUT_ITER_EACH", &
    1378          384 :                                    i_val=localized_wfn_control%out_each)
    1379              :          CALL section_vals_val_get(loc_section, "EPS_LOCALIZATION", &
    1380          384 :                                    r_val=localized_wfn_control%eps_localization)
    1381              :          CALL section_vals_val_get(loc_section, "MIN_OR_MAX", &
    1382          384 :                                    i_val=localized_wfn_control%min_or_max)
    1383              :          CALL section_vals_val_get(loc_section, "JACOBI_FALLBACK", &
    1384          384 :                                    l_val=localized_wfn_control%jacobi_fallback)
    1385              :          CALL section_vals_val_get(loc_section, "JACOBI_REFINEMENT", &
    1386          384 :                                    l_val=localized_wfn_control%jacobi_refinement)
    1387              :          CALL section_vals_val_get(loc_section, "METHOD", &
    1388          384 :                                    i_val=localized_wfn_control%localization_method)
    1389              :          CALL section_vals_val_get(loc_section, "OPERATOR", &
    1390          384 :                                    i_val=localized_wfn_control%operator_type)
    1391              :          CALL section_vals_val_get(loc_section, "RESTART", &
    1392          384 :                                    l_val=localized_wfn_control%loc_restart)
    1393              :          CALL section_vals_val_get(loc_section, "USE_HISTORY", &
    1394          384 :                                    l_val=localized_wfn_control%use_history)
    1395              :          CALL section_vals_val_get(loc_section, "NEXTRA", &
    1396          384 :                                    i_val=localized_wfn_control%nextra)
    1397              :          CALL section_vals_val_get(loc_section, "CPO_GUESS", &
    1398          384 :                                    i_val=localized_wfn_control%coeff_po_guess)
    1399              :          CALL section_vals_val_get(loc_section, "CPO_GUESS_SPACE", &
    1400          384 :                                    i_val=localized_wfn_control%coeff_po_guess_mo_space)
    1401              :          CALL section_vals_val_get(loc_section, "CG_PO", &
    1402          384 :                                    l_val=localized_wfn_control%do_cg_po)
    1403              : 
    1404          384 :          IF (localized_wfn_control%do_homo) THEN
    1405              :             ! List of States HOMO
    1406          376 :             CALL section_vals_val_get(loc_section, "LIST", n_rep_val=n_rep)
    1407          376 :             IF (n_rep > 0) THEN
    1408           14 :                n_list = 0
    1409           28 :                DO ir = 1, n_rep
    1410           14 :                   NULLIFY (list)
    1411           14 :                   CALL section_vals_val_get(loc_section, "LIST", i_rep_val=ir, i_vals=list)
    1412           28 :                   IF (ASSOCIATED(list)) THEN
    1413           14 :                      CALL reallocate(loc_list, 1, n_list + SIZE(list))
    1414           90 :                      DO i = 1, SIZE(list)
    1415           90 :                         loc_list(n_list + i) = list(i)
    1416              :                      END DO ! i
    1417           14 :                      n_list = n_list + SIZE(list)
    1418              :                   END IF
    1419              :                END DO ! ir
    1420           14 :                IF (n_list /= 0) THEN
    1421           14 :                   localized_wfn_control%set_of_states = state_loc_list
    1422           42 :                   ALLOCATE (localized_wfn_control%loc_states(n_list, 2))
    1423          194 :                   localized_wfn_control%loc_states = 0
    1424          180 :                   localized_wfn_control%loc_states(:, 1) = loc_list(:)
    1425          180 :                   localized_wfn_control%loc_states(:, 2) = loc_list(:)
    1426           14 :                   localized_wfn_control%nloc_states(1) = n_list
    1427           14 :                   localized_wfn_control%nloc_states(2) = n_list
    1428           14 :                   IF (my_do_xas) THEN
    1429            4 :                      other_spin = 2
    1430            4 :                      IF (spin_xas == 2) other_spin = 1
    1431            4 :                      localized_wfn_control%nloc_states(other_spin) = 0
    1432           22 :                      localized_wfn_control%loc_states(:, other_spin) = 0
    1433              :                   END IF
    1434           14 :                   DEALLOCATE (loc_list)
    1435              :                END IF
    1436              :             END IF
    1437              : 
    1438              :          ELSE
    1439              :             ! List of States LUMO
    1440            8 :             CALL section_vals_val_get(loc_section, "LIST_UNOCCUPIED", n_rep_val=n_rep)
    1441            8 :             IF (n_rep > 0) THEN
    1442            6 :                n_list = 0
    1443           12 :                DO ir = 1, n_rep
    1444            6 :                   NULLIFY (list)
    1445            6 :                   CALL section_vals_val_get(loc_section, "LIST_UNOCCUPIED", i_rep_val=ir, i_vals=list)
    1446           12 :                   IF (ASSOCIATED(list)) THEN
    1447            6 :                      CALL reallocate(loc_list, 1, n_list + SIZE(list))
    1448           46 :                      DO i = 1, SIZE(list)
    1449           46 :                         loc_list(n_list + i) = list(i)
    1450              :                      END DO ! i
    1451            6 :                      n_list = n_list + SIZE(list)
    1452              :                   END IF
    1453              :                END DO ! ir
    1454            6 :                IF (n_list /= 0) THEN
    1455            6 :                   localized_wfn_control%set_of_states = state_loc_list
    1456           18 :                   ALLOCATE (localized_wfn_control%loc_states(n_list, 2))
    1457           98 :                   localized_wfn_control%loc_states = 0
    1458           92 :                   localized_wfn_control%loc_states(:, 1) = loc_list(:)
    1459           92 :                   localized_wfn_control%loc_states(:, 2) = loc_list(:)
    1460            6 :                   localized_wfn_control%nloc_states(1) = n_list
    1461            6 :                   DEALLOCATE (loc_list)
    1462              :                END IF
    1463              :             END IF
    1464              :          END IF
    1465              : 
    1466          384 :          IF (localized_wfn_control%set_of_states == 0) THEN
    1467          364 :             CALL section_vals_val_get(loc_section, "ENERGY_RANGE", r_vals=ene)
    1468          364 :             IF (ene(1) /= ene(2)) THEN
    1469           10 :                localized_wfn_control%set_of_states = energy_loc_range
    1470           10 :                localized_wfn_control%lu_ene_bound(1) = ene(1)
    1471           10 :                localized_wfn_control%lu_ene_bound(2) = ene(2)
    1472              :             END IF
    1473              :          END IF
    1474              : 
    1475              :          ! All States or XAS specific states
    1476          384 :          IF (localized_wfn_control%set_of_states == 0) THEN
    1477          354 :             IF (my_do_xas) THEN
    1478           72 :                localized_wfn_control%set_of_states = state_loc_range
    1479          216 :                localized_wfn_control%nloc_states(:) = 0
    1480          216 :                localized_wfn_control%lu_bound_states(1, :) = 0
    1481          216 :                localized_wfn_control%lu_bound_states(2, :) = 0
    1482           72 :                localized_wfn_control%nloc_states(spin_xas) = nloc_xas
    1483           72 :                localized_wfn_control%lu_bound_states(1, spin_xas) = 1
    1484           72 :                localized_wfn_control%lu_bound_states(2, spin_xas) = nloc_xas
    1485          282 :             ELSE IF (my_do_mixed) THEN
    1486            2 :                localized_wfn_control%set_of_states = state_loc_mixed
    1487            2 :                nextra = localized_wfn_control%nextra
    1488              :             ELSE
    1489          280 :                localized_wfn_control%set_of_states = state_loc_all
    1490              :             END IF
    1491              :          END IF
    1492              : 
    1493              :          localized_wfn_control%print_centers = &
    1494              :             BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
    1495          384 :                                              "WANNIER_CENTERS"), cp_p_file)
    1496              :          localized_wfn_control%print_spreads = &
    1497              :             BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
    1498          384 :                                              "WANNIER_SPREADS"), cp_p_file)
    1499              :          localized_wfn_control%print_cubes = &
    1500              :             BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
    1501          384 :                                              "WANNIER_CUBES"), cp_p_file)
    1502              : 
    1503              :          output_unit = cp_print_key_unit_nr(logger, loc_print_section, "PROGRAM_RUN_INFO", &
    1504          384 :                                             extension=".Log")
    1505              : 
    1506          384 :          IF (output_unit > 0) THEN
    1507              :             WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
    1508          192 :                "LOCALIZE| The spread relative to a set of orbitals is computed"
    1509              : 
    1510          332 :             SELECT CASE (localized_wfn_control%set_of_states)
    1511              :             CASE (state_loc_all)
    1512              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1513          140 :                   "LOCALIZE| Orbitals to be localized: All orbitals"
    1514              :                WRITE (UNIT=output_unit, FMT="(T2,A,/,T12,A,F16.8)") &
    1515          140 :                   "LOCALIZE| If fractional occupation, fully occupied MOs are those ", &
    1516          280 :                   "within occupation tolerance of ", localized_wfn_control%eps_occ
    1517              :             CASE (state_loc_range)
    1518              :                WRITE (UNIT=output_unit, FMT="(T2,A,T65,I8,A,I8)") &
    1519           36 :                   "LOCALIZE| Orbitals to be localized: Those with index between ", &
    1520           36 :                   localized_wfn_control%lu_bound_states(1, spin_xas), " and ", &
    1521           72 :                   localized_wfn_control%lu_bound_states(2, spin_xas)
    1522              :             CASE (state_loc_list)
    1523              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1524           10 :                   "LOCALIZE| Orbitals to be localized: Those with index in the following list"
    1525           10 :                nline = localized_wfn_control%nloc_states(1)/10 + 1
    1526           10 :                ind = 0
    1527           21 :                DO i = 1, nline
    1528           21 :                   IF (ind + 10 < localized_wfn_control%nloc_states(1)) THEN
    1529           11 :                      WRITE (UNIT=output_unit, FMT="(T8,10I7)") localized_wfn_control%loc_states(ind + 1:ind + 10, 1)
    1530            1 :                      ind = ind + 10
    1531              :                   ELSE
    1532              :                      WRITE (UNIT=output_unit, FMT="(T8,10I7)") &
    1533           58 :                         localized_wfn_control%loc_states(ind + 1:localized_wfn_control%nloc_states(1), 1)
    1534           10 :                      ind = localized_wfn_control%nloc_states(1)
    1535              :                   END IF
    1536              :                END DO
    1537              :             CASE (energy_loc_range)
    1538              :                WRITE (UNIT=output_unit, FMT="(T2,A,T65,/,f16.6,A,f16.6,A)") &
    1539            5 :                   "LOCALIZE| Orbitals to be localized: Those with energy in the range between ", &
    1540           10 :                   localized_wfn_control%lu_ene_bound(1), " and ", localized_wfn_control%lu_ene_bound(2), " a.u."
    1541              :             CASE (state_loc_mixed)
    1542              :                WRITE (UNIT=output_unit, FMT="(T2,A,I4,A)") &
    1543            1 :                   "LOCALIZE| Orbitals to be localized: Occupied orbitals + ", nextra, " orbitals"
    1544              :             CASE DEFAULT
    1545              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1546          192 :                   "LOCALIZE| Orbitals to be localized: None "
    1547              :             END SELECT
    1548              : 
    1549          381 :             SELECT CASE (localized_wfn_control%operator_type)
    1550              :             CASE (op_loc_berry)
    1551              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1552          189 :                   "LOCALIZE| Spread defined by the Berry phase operator "
    1553              :             CASE (op_loc_boys)
    1554              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1555            0 :                   "LOCALIZE| Spread defined by the Boys phase operator "
    1556              :             CASE DEFAULT
    1557              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1558          192 :                   "LOCALIZE| Spread defined by the Pipek phase operator "
    1559              :             END SELECT
    1560              : 
    1561          328 :             SELECT CASE (localized_wfn_control%localization_method)
    1562              :             CASE (do_loc_jacobi)
    1563              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1564          136 :                   "LOCALIZE| Optimal unitary transformation generated by Jacobi algorithm"
    1565              :             CASE (do_loc_crazy)
    1566              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1567           38 :                   "LOCALIZE| Optimal unitary transformation generated by Crazy angle algorithm"
    1568              :                WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
    1569           38 :                   "LOCALIZE| maximum angle: ", localized_wfn_control%max_crazy_angle
    1570              :                WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
    1571           38 :                   "LOCALIZE| scaling: ", localized_wfn_control%crazy_scale
    1572              :                WRITE (UNIT=output_unit, FMT="(T2,A,L1)") &
    1573           38 :                   "LOCALIZE| use diag:", localized_wfn_control%crazy_use_diag
    1574              :             CASE (do_loc_gapo)
    1575              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1576            1 :                   "LOCALIZE| Optimal unitary transformation generated by gradient ascent algorithm "
    1577              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1578            1 :                   "LOCALIZE| for partially occupied wannier functions"
    1579              :             CASE (do_loc_direct)
    1580              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1581            1 :                   "LOCALIZE| Optimal unitary transformation generated by direct algorithm"
    1582              :             CASE (do_loc_l1_norm_sd)
    1583              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1584            9 :                   "LOCALIZE| Optimal unitary transformation generated by "
    1585              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1586            9 :                   "LOCALIZE| steepest descent algorithm applied on an approximate l1 norm"
    1587              :             CASE (do_loc_none)
    1588              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1589            0 :                   "LOCALIZE| No unitary transformation is applied"
    1590              :             CASE (do_loc_scdm)
    1591              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
    1592          192 :                   "LOCALIZE| Pivoted QR decomposition is used to transform coefficients"
    1593              :             END SELECT
    1594              : 
    1595              :          END IF ! process has output_unit
    1596              : 
    1597          384 :          CALL cp_print_key_finished_output(output_unit, logger, loc_print_section, "PROGRAM_RUN_INFO")
    1598              : 
    1599              :       ELSE
    1600           48 :          localized_wfn_control%localization_method = do_loc_none
    1601           48 :          localized_wfn_control%localization_method = state_loc_none
    1602           48 :          localized_wfn_control%print_centers = .FALSE.
    1603           48 :          localized_wfn_control%print_spreads = .FALSE.
    1604           48 :          localized_wfn_control%print_cubes = .FALSE.
    1605              :       END IF
    1606              : 
    1607          432 :    END SUBROUTINE read_loc_section
    1608              : 
    1609              : ! **************************************************************************************************
    1610              : !> \brief create the center and spread array and the file names for the output
    1611              : !> \param localized_wfn_control ...
    1612              : !> \param nmoloc ...
    1613              : !> \param nspins ...
    1614              : !> \par History
    1615              : !>      04.2005 created [MI]
    1616              : ! **************************************************************************************************
    1617          484 :    SUBROUTINE set_loc_centers(localized_wfn_control, nmoloc, nspins)
    1618              : 
    1619              :       TYPE(localized_wfn_control_type)                   :: localized_wfn_control
    1620              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: nmoloc
    1621              :       INTEGER, INTENT(IN)                                :: nspins
    1622              : 
    1623              :       INTEGER                                            :: ispin
    1624              : 
    1625         1144 :       DO ispin = 1, nspins
    1626         1938 :          ALLOCATE (localized_wfn_control%centers_set(ispin)%array(6, nmoloc(ispin)))
    1627        32210 :          localized_wfn_control%centers_set(ispin)%array = 0.0_dp
    1628              :       END DO
    1629              : 
    1630          484 :    END SUBROUTINE set_loc_centers
    1631              : 
    1632              : ! **************************************************************************************************
    1633              : !> \brief create the lists of mos that are taken into account
    1634              : !> \param localized_wfn_control ...
    1635              : !> \param nmoloc ...
    1636              : !> \param nmo ...
    1637              : !> \param nspins ...
    1638              : !> \param my_spin ...
    1639              : !> \par History
    1640              : !>      04.2005 created [MI]
    1641              : ! **************************************************************************************************
    1642          346 :    SUBROUTINE set_loc_wfn_lists(localized_wfn_control, nmoloc, nmo, nspins, my_spin)
    1643              : 
    1644              :       TYPE(localized_wfn_control_type)                   :: localized_wfn_control
    1645              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: nmoloc, nmo
    1646              :       INTEGER, INTENT(IN)                                :: nspins
    1647              :       INTEGER, INTENT(IN), OPTIONAL                      :: my_spin
    1648              : 
    1649              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'set_loc_wfn_lists'
    1650              : 
    1651              :       INTEGER                                            :: i, ispin, max_iloc, max_nmoloc, state
    1652              : 
    1653          346 :       CALL timeset(routineN, state)
    1654              : 
    1655         1038 :       localized_wfn_control%nloc_states(1:2) = nmoloc(1:2)
    1656          346 :       max_nmoloc = MAX(nmoloc(1), nmoloc(2))
    1657              : 
    1658          364 :       SELECT CASE (localized_wfn_control%set_of_states)
    1659              :       CASE (state_loc_list)
    1660              :          ! List
    1661           18 :          CPASSERT(ASSOCIATED(localized_wfn_control%loc_states))
    1662           52 :          DO ispin = 1, nspins
    1663           34 :             localized_wfn_control%lu_bound_states(1, ispin) = 1
    1664           34 :             localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
    1665           52 :             IF (nmoloc(ispin) < 1) THEN
    1666            4 :                localized_wfn_control%lu_bound_states(1, ispin) = 0
    1667           22 :                localized_wfn_control%loc_states(:, ispin) = 0
    1668              :             END IF
    1669              :          END DO
    1670              :       CASE (state_loc_range)
    1671              :          ! Range
    1672          114 :          ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
    1673          446 :          localized_wfn_control%loc_states = 0
    1674          114 :          DO ispin = 1, nspins
    1675              :             localized_wfn_control%lu_bound_states(1, ispin) = &
    1676           76 :                localized_wfn_control%lu_bound_states(1, my_spin)
    1677              :             localized_wfn_control%lu_bound_states(2, ispin) = &
    1678           76 :                localized_wfn_control%lu_bound_states(1, my_spin) + nmoloc(ispin) - 1
    1679           76 :             max_iloc = localized_wfn_control%lu_bound_states(2, ispin)
    1680          242 :             DO i = 1, nmoloc(ispin)
    1681          242 :                localized_wfn_control%loc_states(i, ispin) = localized_wfn_control%lu_bound_states(1, ispin) + i - 1
    1682              :             END DO
    1683           76 :             CPASSERT(max_iloc <= nmo(ispin))
    1684           38 :             MARK_USED(nmo)
    1685              :          END DO
    1686              :       CASE (energy_loc_range)
    1687              :          ! Energy
    1688           30 :          ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
    1689          214 :          localized_wfn_control%loc_states = 0
    1690           22 :          DO ispin = 1, nspins
    1691          134 :             DO i = 1, nmoloc(ispin)
    1692          124 :                localized_wfn_control%loc_states(i, ispin) = localized_wfn_control%lu_bound_states(1, ispin) + i - 1
    1693              :             END DO
    1694              :          END DO
    1695              :       CASE (state_loc_all)
    1696              :          ! All
    1697          834 :          ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
    1698         5674 :          localized_wfn_control%loc_states = 0
    1699              : 
    1700          278 :          IF (localized_wfn_control%lu_bound_states(1, 1) == 1) THEN
    1701          660 :             DO ispin = 1, nspins
    1702          382 :                localized_wfn_control%lu_bound_states(1, ispin) = 1
    1703          382 :                localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
    1704          382 :                IF (nmoloc(ispin) < 1) localized_wfn_control%lu_bound_states(1, ispin) = 0
    1705         3806 :                DO i = 1, nmoloc(ispin)
    1706         3528 :                   localized_wfn_control%loc_states(i, ispin) = i
    1707              :                END DO
    1708              :             END DO
    1709              :          ELSE
    1710            0 :             DO ispin = 1, nspins
    1711            0 :                IF (nmoloc(ispin) < 1) localized_wfn_control%lu_bound_states(1, ispin) = 0
    1712            0 :                DO i = 1, nmoloc(ispin)
    1713              :                   localized_wfn_control%loc_states(i, ispin) = &
    1714            0 :                      localized_wfn_control%lu_bound_states(1, ispin) + i - 1
    1715              :                END DO
    1716              :             END DO
    1717              :          END IF
    1718              :       CASE (state_loc_mixed)
    1719              :          ! Mixed
    1720            6 :          ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
    1721          178 :          localized_wfn_control%loc_states = 0
    1722          350 :          DO ispin = 1, nspins
    1723           90 :             DO i = 1, nmoloc(ispin)
    1724           88 :                localized_wfn_control%loc_states(i, ispin) = i
    1725              :             END DO
    1726              :          END DO
    1727              :       END SELECT
    1728              : 
    1729          346 :       CALL timestop(state)
    1730              : 
    1731          346 :    END SUBROUTINE set_loc_wfn_lists
    1732              : 
    1733              : END MODULE qs_loc_utils
    1734              : 
        

Generated by: LCOV version 2.0-1