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

Generated by: LCOV version 2.0-1